Index: head/sys/amd64/conf/NOTES =================================================================== --- head/sys/amd64/conf/NOTES (revision 152908) +++ head/sys/amd64/conf/NOTES (revision 152909) @@ -1,555 +1,556 @@ # # NOTES -- Lines that can be cut/pasted into kernel and hints configs. # # This file contains machine dependent kernel configuration notes. For # machine independent notes, look in /sys/conf/NOTES. # # $FreeBSD$ # # # We want LINT to cover profiling as well. profile 2 ##################################################################### # SMP OPTIONS: # # Notes: # # IPI_PREEMPTION instructs the kernel to preempt threads running on other # CPUS if needed. Relies on the PREEMPTION option # Optional: options IPI_PREEMPTION device atpic # Optional legacy pic support device mptable # Optional MPSPEC mptable support # # Watchdog routines. # options MP_WATCHDOG # # Debugging options. # options STOP_NMI # Stop CPUS using NMI instead of IPI ##################################################################### # CPU OPTIONS # # You must specify at least one CPU (the one you intend to run on); # deleting the specification for CPUs you don't need to use may make # parts of the system run faster. # cpu HAMMER # aka K8, aka Opteron & Athlon64 # # Options for CPU features. # # # PERFMON causes the driver for Pentium/Pentium Pro performance counters # to be compiled. See perfmon(4) for more information. # #XXX#options PERFMON ##################################################################### # NETWORKING OPTIONS # # DEVICE_POLLING adds support for mixed interrupt-polling handling # of network device drivers, which has significant benefits in terms # of robustness to overloads and responsivity, as well as permitting # accurate scheduling of the CPU time between kernel network processing # and other activities. The drawback is a moderate (up to 1/HZ seconds) # potential increase in response times. # It is strongly recommended to use HZ=1000 or 2000 with DEVICE_POLLING # to achieve smoother behaviour. # Additionally, you can enable/disable polling at runtime with help of # the ifconfig(8) utility, and select the CPU fraction reserved to # userland with the sysctl variable kern.polling.user_frac # (default 50, range 0..100). # # Not all device drivers support this mode of operation at the time of # this writing. See polling(4) for more details. options DEVICE_POLLING ##################################################################### # CLOCK OPTIONS # The following options are used for debugging clock behavior only, and # should not be used for production systems. # CLK_CALIBRATION_LOOP causes clock calibration to be run in a loop at # startup until the user presses a key. (The i8254 clock is always # calibrated relative to the RTC (mc146818a) and this option causes the # calibration to be repeated.) options CLK_CALIBRATION_LOOP # CLK_USE_I8254_CALIBRATION causes the calibrated frequency of the i8254 # clock to actually be used. options CLK_USE_I8254_CALIBRATION ##################################################################### # MISCELLANEOUS DEVICES AND OPTIONS device speaker #Play IBM BASIC-style noises out your speaker hint.speaker.0.at="isa" hint.speaker.0.port="0x61" device gzip #Exec gzipped a.out's. REQUIRES COMPAT_AOUT! ##################################################################### # HARDWARE BUS CONFIGURATION # # ISA bus # device isa # # Options for `isa': # # AUTO_EOI_1 enables the `automatic EOI' feature for the master 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # This option breaks suspend/resume on some portables. # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # Automatic EOI is documented not to work for for the slave with the # original i8259A, but it works for some clones and some integrated # versions. # # MAXMEM specifies the amount of RAM on the machine; if this is not # specified, FreeBSD will first read the amount of memory from the CMOS # RAM, so the amount of memory will initially be limited to 64MB or 16MB # depending on the BIOS. If the BIOS reports 64MB, a memory probe will # then attempt to detect the installed amount of RAM. If this probe # fails to detect >64MB RAM you will have to use the MAXMEM option. # The amount is in kilobytes, so for a machine with 128MB of RAM, it would # be 131072 (128 * 1024). # # BROKEN_KEYBOARD_RESET disables the use of the keyboard controller to # reset the CPU for reboot. This is needed on some systems with broken # keyboard controllers. options AUTO_EOI_1 #options AUTO_EOI_2 options MAXMEM=(128*1024) #options BROKEN_KEYBOARD_RESET # # PCI bus & PCI options: # device pci # # AGP GART support device agp ##################################################################### # HARDWARE DEVICE CONFIGURATION # # Optional devices: # # 3Dfx Voodoo Graphics, Voodoo II /dev/3dfx CDEV support. This will create # the /dev/3dfx0 device to work with glide implementations. This should get # linked to /dev/3dfx and /dev/voodoo. Note that this is not the same as # the tdfx DRI module from XFree86 and is completely unrelated. # # To enable Linuxulator support, one must also include COMPAT_LINUX in the # config as well, or you will not have the dependencies. The other option # is to load both as modules. device tdfx # Enable 3Dfx Voodoo support #XXX#options TDFX_LINUX # Enable Linuxulator support # # ACPI support using the Intel ACPI Component Architecture reference # implementation. # # ACPI_DEBUG enables the use of the debug.acpi.level and debug.acpi.layer # kernel environment variables to select initial debugging levels for the # Intel ACPICA code. (Note that the Intel code must also have USE_DEBUGGER # defined when it is built). # # ACPI_NO_SEMAPHORES makes the AcpiOs*Semaphore routines a no-op. # # ACPICA_PEDANTIC enables strict checking of AML. Our default is to # relax these checks to allow code generated by the Microsoft compiler # to still execute. # # Note that building ACPI into the kernel is deprecated; the module is # normally loaded automatically by the loader. device acpi options ACPI_DEBUG #!options ACPI_NO_SEMAPHORES #!options ACPICA_PEDANTIC # The cpufreq(4) driver provides support for non-ACPI CPU frequency control device cpufreq # Direct Rendering modules for 3D acceleration. device drm # DRM core module required by DRM drivers device mach64drm # ATI Rage Pro, Rage Mobility P/M, Rage XL device mgadrm # AGP Matrox G200, G400, G450, G550 device r128drm # ATI Rage 128 device radeondrm # ATI Radeon +device savagedrm # S3 Savage3D, Savage4 device sisdrm # SiS 300/305, 540, 630 device tdfxdrm # 3dfx Voodoo 3/4/5 and Banshee options DRM_DEBUG # Include debug printfs (slow) # # Network interfaces: # # ath: Atheros a/b/g WiFi adapters (requires ath_hal and wlan) # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # HP PC Lan+, various PC Card devices (refer to etc/defaults/pccard.conf) # (requires miibus) # lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL, AMD Am7990 and # Am79C960) # nve: nVidia nForce MCP on-board Ethernet Networking device ed options ED_3C503 options ED_HPP options ED_SIC #XXX# still calls MD i386 kvtop function instead of vtophys etc #XXX#device lnc device nve # nVidia nForce MCP on-board Ethernet Networking device ath device ath_hal # Atheros HAL (includes binary component) #device ath_rate_amrr # AMRR rate control for ath driver #device ath_rate_onoe # Onoe rate control for ath driver device ath_rate_sample # SampleRate rate control for the ath driver #device wlan # 802.11 layer # #XXX this stores pointers in a 32bit field that is defined by the hardware #device pst # # Areca 11xx and 12xx series of SATA II RAID controllers. # CAM is required. # device arcmsr # Areca SATA II RAID # # 3ware 9000 series PATA/SATA RAID controller driver and options. # The driver is implemented as a SIM, and so, needs the CAM infrastructure. # options TWA_DEBUG # 0-10; 10 prints the most messages. options TWA_FLASH_FIRMWARE # firmware image bundled when defined. device twa # 3ware 9000 series PATA/SATA RAID # # SCSI host adapters: # # ncv: NCR 53C500 based SCSI host adapters. # nsp: Workbit Ninja SCSI-3 based PC Card SCSI host adapters. # stg: TMC 18C30, 18C50 based SCSI host adapters. device ncv device nsp device stg # # Adaptec FSA RAID controllers, including integrated DELL controllers, # the Dell PERC 2/QC and the HP NetRAID-4M device aac device aacp # SCSI Passthrough interface (optional, CAM required) # # Highpoint RocketRAID 182x. This is really just software RAID on a # Marvell SATA chip. device hptmv # # IBM (now Adaptec) ServeRAID controllers device ips # # SafeNet crypto driver: can be moved to the MI NOTES as soon as # it's tested on a big-endian machine # device safe # SafeNet 1141 options SAFE_DEBUG # enable debugging support: hw.safe.debug options SAFE_RNDTEST # enable rndtest support ##################################################################### # # Miscellaneous hardware: # # smbios: DMI/SMBIOS entry point # vpd: Vital Product Data kernel interface # cy: Cyclades serial driver # digi: Digiboard driver # Notes on the Specialix SI/XIO driver: # The host card is memory, not IO mapped. # The Rev 1 host cards use a 64K chunk, on a 32K boundary. # The Rev 2 host cards use a 32K chunk, on a 32K boundary. # The cards can use an IRQ of 11, 12 or 15. device cy options CY_PCI_FASTINTR # Use with cy_pci unless irq is shared device digi # BIOS & FEP/OS components of device digi. device digi_CX device digi_CX_PCI device digi_EPCX device digi_EPCX_PCI device digi_Xe device digi_Xem device digi_Xr # Parallel (8255 PPI) basic I/O (mode 0) port (e.g. Advantech PCL-724) device pbio hint.pbio.0.at="isa" hint.pbio.0.port="0x360" device smbios device vpd # HOT1 Xilinx 6200 card (http://www.vcc.com/) device xrpu # # Laptop/Notebook options: # # # I2C Bus # # # Hardware watchdog timers: # # ichwd: Intel ICH watchdog timer # device ichwd #--------------------------------------------------------------------------- # ISDN4BSD # # See /usr/share/examples/isdn/ROADMAP for an introduction to isdn4bsd. # # i4b passive ISDN cards support contains the following hardware drivers: # # isic - Siemens/Infineon ISDN ISAC/HSCX/IPAC chipset driver # iwic - Winbond W6692 PCI bus ISDN S/T interface controller # ifpi - AVM Fritz!Card PCI driver # ifpi2 - AVM Fritz!Card PCI version 2 driver # itjc - Siemens ISAC / TJNet Tiger300/320 chipset # # i4b active ISDN cards support contains the following hardware drivers: # # iavc - AVM B1 PCI, AVM B1 ISA, AVM T1 # # Note that the ``options'' (if given) and ``device'' lines must BOTH # be uncommented to enable support for a given card ! # # In addition to a hardware driver (and probably an option) the mandatory # ISDN protocol stack devices and the mandatory support device must be # enabled as well as one or more devices from the optional devices section. # #--------------------------------------------------------------------------- # isic driver (Siemens/Infineon chipsets) # #XXX#device isic # # PCI bus Cards: # -------------- # # ELSA MicroLink ISDN/PCI (same as ELSA QuickStep 1000pro PCI) options ELSA_QS1PCI # #--------------------------------------------------------------------------- # ifpi2 driver for AVM Fritz!Card PCI version 2 # # AVM Fritz!Card PCI version 2 #XXX#device ifpi2 # #--------------------------------------------------------------------------- # iwic driver for Winbond W6692 chipset # # ASUSCOM P-IN100-ST-D (and other Winbond W6692 based cards) #XXX#device iwic # #--------------------------------------------------------------------------- # itjc driver for Siemens ISAC / TJNet Tiger300/320 chipset # # Traverse Technologies NETjet-S # Teles PCI-TJ #XXX#device itjc # #--------------------------------------------------------------------------- # iavc driver (AVM active cards, needs i4bcapi driver!) # #XXX#device iavc # #--------------------------------------------------------------------------- # ISDN Protocol Stack - mandatory for all hardware drivers # # Q.921 / layer 2 - i4b passive cards D channel handling #XXX#device i4bq921 # # Q.931 / layer 3 - i4b passive cards D channel handling #XXX#device i4bq931 # # layer 4 - i4b common passive and active card handling #XXX#device i4b # #--------------------------------------------------------------------------- # ISDN devices - mandatory for all hardware drivers # # userland driver to do ISDN tracing (for passive cards only) #XXX#device i4btrc #XXX#options NI4BTRC=4 # # userland driver to control the whole thing #XXX#device i4bctl # #--------------------------------------------------------------------------- # ISDN devices - optional # # userland driver for access to raw B channel #XXX#device i4brbch #XXX#options NI4BRBCH=4 # # userland driver for telephony #XXX#device i4btel #XXX#options NI4BTEL=2 # # network driver for IP over raw HDLC ISDN #XXX#device i4bipr #XXX#options NI4BIPR=4 # enable VJ header compression detection for ipr i/f options IPR_VJ # enable logging of the first n IP packets to isdnd (n=32 here) options IPR_LOG=32 # # network driver for sync PPP over ISDN; requires an equivalent # number of sppp device to be configured #XXX#device i4bisppp #XXX#options NI4BISPPP=4 # # B-channel interface to the netgraph subsystem #XXX#device i4bing #XXX#options NI4BING=2 # # CAPI driver needed for active ISDN cards (see iavc driver above) #XXX#device i4bcapi # #--------------------------------------------------------------------------- # # System Management Bus (SMB) # options ENABLE_ALART # Control alarm on Intel intpm driver # # Set the number of PV entries per process. Increasing this can # stop panics related to heavy use of shared memory. However, that can # (combined with large amounts of physical memory) cause panics at # boot time due the kernel running out of VM space. # # If you're tweaking this, you might also want to increase the sysctls # "vm.v_free_min", "vm.v_free_reserved", and "vm.v_free_target". # # The value below is the one more than the default. # options PMAP_SHPGPERPROC=201 ##################################################################### # ABI Emulation #XXX keep these here for now and reactivate when support for emulating #XXX these 32 bit binaries is added. # Enable 32-bit runtime support for FreeBSD/i386 binaries. options COMPAT_IA32 # Enable iBCS2 runtime support for SCO and ISC binaries #XXX#options IBCS2 # Emulate spx device for client side of SVR3 local X interface #XXX#options SPX_HACK # Enable Linux ABI emulation #XXX#options COMPAT_LINUX # Enable 32-bit Linux ABI emulation (requires COMPAT_43 and COMPAT_IA32) options COMPAT_LINUX32 # Enable the linux-like proc filesystem support (requires COMPAT_LINUX32 # and PSEUDOFS) options LINPROCFS # # SysVR4 ABI emulation # # The svr4 ABI emulator can be statically compiled into the kernel or loaded as # a KLD module. # The STREAMS network emulation code can also be compiled statically or as a # module. If loaded as a module, it must be loaded before the svr4 module # (the /usr/sbin/svr4 script does this for you). If compiling statically, # the `streams' device must be configured into any kernel which also # specifies COMPAT_SVR4. It is possible to have a statically-configured # STREAMS device and a dynamically loadable svr4 emulator; the /usr/sbin/svr4 # script understands that it doesn't need to load the `streams' module under # those circumstances. # Caveat: At this time, `options KTRACE' is required for the svr4 emulator # (whether static or dynamic). # #XXX#options COMPAT_SVR4 # build emulator statically #XXX#options DEBUG_SVR4 # enable verbose debugging #XXX#device streams # STREAMS network driver (required for svr4). ##################################################################### # VM OPTIONS # KSTACK_PAGES is the number of memory pages to assign to the kernel # stack of each thread. options KSTACK_PAGES=3 ##################################################################### # More undocumented options for linting. # Note that documenting these are not considered an affront. options FB_INSTALL_CDEV # install a CDEV entry in /dev options KBDIO_DEBUG=2 options KBD_MAXRETRY=4 options KBD_MAXWAIT=6 options KBD_RESETDELAY=201 options PSM_DEBUG=1 options TIMER_FREQ=((14318182+6)/12) options VM_KMEM_SIZE options VM_KMEM_SIZE_MAX options VM_KMEM_SIZE_SCALE # The I/O device device io Index: head/sys/conf/files =================================================================== --- head/sys/conf/files (revision 152908) +++ head/sys/conf/files (revision 152909) @@ -1,1871 +1,1874 @@ # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # acpi_quirks.h optional acpi \ dependency "$S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ compile-with "${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ no-obj no-implicit-rule before-depend \ clean "acpi_quirks.h" aicasm optional ahc | ahd \ dependency "$S/dev/aic7xxx/aicasm/*.[chyl]" \ compile-with "CC=${CC} ${MAKE} -f $S/dev/aic7xxx/aicasm/Makefile MAKESRCPATH=$S/dev/aic7xxx/aicasm" \ no-obj no-implicit-rule \ clean "aicasm* y.tab.h" aic7xxx_seq.h optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic7xxx_seq.h" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg.h optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic7xxx_reg.h" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg_print.c optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule local \ clean "aic7xxx_reg_print.c" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg_print.o optional ahc ahc_reg_pretty_print \ compile-with "${NORMAL_C}" \ no-implicit-rule local aic79xx_seq.h optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic79xx_seq.h" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg.h optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic79xx_reg.h" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg_print.c optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule local \ clean "aic79xx_reg_print.c" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg_print.o optional ahd pci ahd_reg_pretty_print \ compile-with "${NORMAL_C}" \ no-implicit-rule local emu10k1-alsa%diked.h optional snd_emu10k1 pci \ dependency "$S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/emu10k1-alsa.h" \ compile-with "CC=${CC} AWK=${AWK} sh $S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/emu10k1-alsa.h emu10k1-alsa%diked.h" \ no-obj no-implicit-rule before-depend \ clean "emu10k1-alsa%diked.h" miidevs.h optional miibus \ dependency "$S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ compile-with "${AWK} -f $S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ no-obj no-implicit-rule before-depend \ clean "miidevs.h" pccarddevs.h standard \ dependency "$S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ compile-with "${AWK} -f $S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ no-obj no-implicit-rule before-depend \ clean "pccarddevs.h" usbdevs.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -h" \ no-obj no-implicit-rule before-depend \ clean "usbdevs.h" usbdevs_data.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -d" \ no-obj no-implicit-rule before-depend \ clean "usbdevs_data.h" cam/cam.c optional scbus cam/cam_periph.c optional scbus cam/cam_queue.c optional scbus cam/cam_sim.c optional scbus cam/cam_xpt.c optional scbus cam/scsi/scsi_all.c optional scbus cam/scsi/scsi_cd.c optional cd cam/scsi/scsi_ch.c optional ch cam/scsi/scsi_da.c optional da cam/scsi/scsi_low.c optional ct | ncv | nsp | stg cam/scsi/scsi_low_pisa.c optional ct | ncv | nsp | stg cam/scsi/scsi_pass.c optional pass cam/scsi/scsi_pt.c optional pt cam/scsi/scsi_sa.c optional sa cam/scsi/scsi_ses.c optional ses cam/scsi/scsi_targ_bh.c optional targbh cam/scsi/scsi_target.c optional targ coda/coda_fbsd.c optional vcoda coda/coda_namecache.c optional vcoda coda/coda_psdev.c optional vcoda coda/coda_subr.c optional vcoda coda/coda_venus.c optional vcoda coda/coda_vfsops.c optional vcoda coda/coda_vnops.c optional vcoda compat/linprocfs/linprocfs.c optional linprocfs contrib/altq/altq/altq_cbq.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_cdnr.c optional altq contrib/altq/altq/altq_hfsc.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_priq.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_red.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_rio.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_rmclass.c optional altq contrib/altq/altq/altq_subr.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/dev/acpica/dbcmds.c optional acpi acpi_debug contrib/dev/acpica/dbdisply.c optional acpi acpi_debug contrib/dev/acpica/dbexec.c optional acpi acpi_debug contrib/dev/acpica/dbfileio.c optional acpi acpi_debug contrib/dev/acpica/dbhistry.c optional acpi acpi_debug contrib/dev/acpica/dbinput.c optional acpi acpi_debug contrib/dev/acpica/dbstats.c optional acpi acpi_debug contrib/dev/acpica/dbutils.c optional acpi acpi_debug contrib/dev/acpica/dbxface.c optional acpi acpi_debug contrib/dev/acpica/dmbuffer.c optional acpi acpi_debug contrib/dev/acpica/dmnames.c optional acpi acpi_debug contrib/dev/acpica/dmopcode.c optional acpi acpi_debug contrib/dev/acpica/dmobject.c optional acpi acpi_debug contrib/dev/acpica/dmresrc.c optional acpi acpi_debug contrib/dev/acpica/dmresrcl.c optional acpi acpi_debug contrib/dev/acpica/dmresrcs.c optional acpi acpi_debug contrib/dev/acpica/dmutils.c optional acpi acpi_debug contrib/dev/acpica/dmwalk.c optional acpi acpi_debug contrib/dev/acpica/dsfield.c optional acpi contrib/dev/acpica/dsinit.c optional acpi contrib/dev/acpica/dsmethod.c optional acpi contrib/dev/acpica/dsmthdat.c optional acpi contrib/dev/acpica/dsobject.c optional acpi contrib/dev/acpica/dsopcode.c optional acpi contrib/dev/acpica/dsutils.c optional acpi contrib/dev/acpica/dswexec.c optional acpi contrib/dev/acpica/dswload.c optional acpi contrib/dev/acpica/dswscope.c optional acpi contrib/dev/acpica/dswstate.c optional acpi contrib/dev/acpica/evevent.c optional acpi contrib/dev/acpica/evgpe.c optional acpi contrib/dev/acpica/evgpeblk.c optional acpi contrib/dev/acpica/evmisc.c optional acpi contrib/dev/acpica/evregion.c optional acpi contrib/dev/acpica/evrgnini.c optional acpi contrib/dev/acpica/evsci.c optional acpi contrib/dev/acpica/evxface.c optional acpi contrib/dev/acpica/evxfevnt.c optional acpi contrib/dev/acpica/evxfregn.c optional acpi contrib/dev/acpica/exconfig.c optional acpi contrib/dev/acpica/exconvrt.c optional acpi contrib/dev/acpica/excreate.c optional acpi contrib/dev/acpica/exdump.c optional acpi contrib/dev/acpica/exfield.c optional acpi contrib/dev/acpica/exfldio.c optional acpi contrib/dev/acpica/exmisc.c optional acpi contrib/dev/acpica/exmutex.c optional acpi contrib/dev/acpica/exnames.c optional acpi contrib/dev/acpica/exoparg1.c optional acpi contrib/dev/acpica/exoparg2.c optional acpi contrib/dev/acpica/exoparg3.c optional acpi contrib/dev/acpica/exoparg6.c optional acpi contrib/dev/acpica/exprep.c optional acpi contrib/dev/acpica/exregion.c optional acpi contrib/dev/acpica/exresnte.c optional acpi contrib/dev/acpica/exresolv.c optional acpi contrib/dev/acpica/exresop.c optional acpi contrib/dev/acpica/exstore.c optional acpi contrib/dev/acpica/exstoren.c optional acpi contrib/dev/acpica/exstorob.c optional acpi contrib/dev/acpica/exsystem.c optional acpi contrib/dev/acpica/exutils.c optional acpi contrib/dev/acpica/hwacpi.c optional acpi contrib/dev/acpica/hwgpe.c optional acpi contrib/dev/acpica/hwregs.c optional acpi contrib/dev/acpica/hwsleep.c optional acpi contrib/dev/acpica/hwtimer.c optional acpi contrib/dev/acpica/nsaccess.c optional acpi contrib/dev/acpica/nsalloc.c optional acpi contrib/dev/acpica/nsdump.c optional acpi contrib/dev/acpica/nseval.c optional acpi contrib/dev/acpica/nsinit.c optional acpi contrib/dev/acpica/nsload.c optional acpi contrib/dev/acpica/nsnames.c optional acpi contrib/dev/acpica/nsobject.c optional acpi contrib/dev/acpica/nsparse.c optional acpi contrib/dev/acpica/nssearch.c optional acpi contrib/dev/acpica/nsutils.c optional acpi contrib/dev/acpica/nswalk.c optional acpi contrib/dev/acpica/nsxfeval.c optional acpi contrib/dev/acpica/nsxfname.c optional acpi contrib/dev/acpica/nsxfobj.c optional acpi contrib/dev/acpica/psargs.c optional acpi contrib/dev/acpica/psloop.c optional acpi contrib/dev/acpica/psopcode.c optional acpi contrib/dev/acpica/psparse.c optional acpi contrib/dev/acpica/psscope.c optional acpi contrib/dev/acpica/pstree.c optional acpi contrib/dev/acpica/psutils.c optional acpi contrib/dev/acpica/pswalk.c optional acpi contrib/dev/acpica/psxface.c optional acpi contrib/dev/acpica/rsaddr.c optional acpi contrib/dev/acpica/rscalc.c optional acpi contrib/dev/acpica/rscreate.c optional acpi contrib/dev/acpica/rsdump.c optional acpi contrib/dev/acpica/rsinfo.c optional acpi contrib/dev/acpica/rsio.c optional acpi contrib/dev/acpica/rsirq.c optional acpi contrib/dev/acpica/rslist.c optional acpi contrib/dev/acpica/rsmemory.c optional acpi contrib/dev/acpica/rsmisc.c optional acpi contrib/dev/acpica/rsutils.c optional acpi contrib/dev/acpica/rsxface.c optional acpi contrib/dev/acpica/tbconvrt.c optional acpi contrib/dev/acpica/tbget.c optional acpi contrib/dev/acpica/tbgetall.c optional acpi contrib/dev/acpica/tbinstal.c optional acpi contrib/dev/acpica/tbrsdt.c optional acpi contrib/dev/acpica/tbutils.c optional acpi contrib/dev/acpica/tbxface.c optional acpi contrib/dev/acpica/tbxfroot.c optional acpi contrib/dev/acpica/utalloc.c optional acpi contrib/dev/acpica/utcache.c optional acpi \ compile-with "${NORMAL_C} -DACPI_USE_LOCAL_CACHE" contrib/dev/acpica/utclib.c optional acpi contrib/dev/acpica/utcopy.c optional acpi contrib/dev/acpica/utdebug.c optional acpi contrib/dev/acpica/utdelete.c optional acpi contrib/dev/acpica/uteval.c optional acpi contrib/dev/acpica/utglobal.c optional acpi contrib/dev/acpica/utinit.c optional acpi contrib/dev/acpica/utmath.c optional acpi contrib/dev/acpica/utmisc.c optional acpi contrib/dev/acpica/utmutex.c optional acpi contrib/dev/acpica/utobject.c optional acpi contrib/dev/acpica/utstate.c optional acpi contrib/dev/acpica/utxface.c optional acpi contrib/dev/ath/freebsd/ah_osdep.c optional ath_hal \ compile-with "${NORMAL_C} -I$S/contrib/dev/ath/freebsd" contrib/ipfilter/netinet/fil.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_auth.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_fil_freebsd.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_frag.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_log.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_nat.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_proxy.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_state.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_lookup.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_pool.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_htable.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_sync.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/mlfk_ipl.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ngatm/netnatm/api/cc_conn.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_data.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_dump.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_port.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_sig.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_user.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/unisap.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/misc/straddr.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/misc/unimsg_common.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/traffic.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/uni_ie.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/uni_msg.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/saal/saal_sscfu.c optional ngatm_sscfu \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/saal/saal_sscop.c optional ngatm_sscop \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_call.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_coord.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_party.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_print.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_reset.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_uni.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_unimsgcpy.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_verify.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/pf/net/if_pflog.c optional pflog \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/if_pfsync.c optional pfsync \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_if.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_subr.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_ioctl.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_norm.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_table.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_osfp.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/netinet/in4_cksum.c optional pf inet crypto/blowfish/bf_ecb.c optional ipsec ipsec_esp crypto/blowfish/bf_skey.c optional crypto | ipsec ipsec_esp crypto/des/des_ecb.c optional crypto | ipsec ipsec_esp | netsmbcrypto crypto/des/des_setkey.c optional crypto | ipsec ipsec_esp | netsmbcrypto crypto/rc4/rc4.c optional netgraph_mppc_encryption crypto/rijndael/rijndael-alg-fst.c optional crypto | geom_bde | \ ipsec | random | wlan_ccmp crypto/rijndael/rijndael-api-fst.c optional geom_bde | random crypto/rijndael/rijndael-api.c optional crypto | ipsec | wlan_ccmp crypto/sha1.c optional carp | crypto | ipsec | \ netgraph_mppc_encryption crypto/sha2/sha2.c optional crypto | geom_bde | ipsec | random ddb/db_access.c optional ddb ddb/db_break.c optional ddb ddb/db_command.c optional ddb ddb/db_examine.c optional ddb ddb/db_expr.c optional ddb ddb/db_input.c optional ddb ddb/db_lex.c optional ddb ddb/db_main.c optional ddb ddb/db_output.c optional ddb ddb/db_print.c optional ddb ddb/db_ps.c optional ddb ddb/db_run.c optional ddb ddb/db_sym.c optional ddb ddb/db_thread.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb #dev/dpt/dpt_control.c optional dpt dev/aac/aac.c optional aac dev/aac/aac_cam.c optional aacp aac dev/aac/aac_debug.c optional aac dev/aac/aac_disk.c optional aac dev/aac/aac_linux.c optional aac compat_linux dev/aac/aac_pci.c optional aac pci dev/acpi_support/acpi_asus.c optional acpi_asus acpi dev/acpi_support/acpi_fujitsu.c optional acpi_fujitsu acpi dev/acpi_support/acpi_ibm.c optional acpi_ibm acpi dev/acpi_support/acpi_panasonic.c optional acpi_panasonic acpi dev/acpi_support/acpi_sony.c optional acpi_sony acpi dev/acpi_support/acpi_toshiba.c optional acpi_toshiba acpi dev/acpica/Osd/OsdDebug.c optional acpi dev/acpica/Osd/OsdHardware.c optional acpi dev/acpica/Osd/OsdInterrupt.c optional acpi dev/acpica/Osd/OsdMemory.c optional acpi dev/acpica/Osd/OsdSchedule.c optional acpi dev/acpica/Osd/OsdStream.c optional acpi dev/acpica/Osd/OsdSynch.c optional acpi dev/acpica/Osd/OsdTable.c optional acpi dev/acpica/acpi.c optional acpi dev/acpica/acpi_acad.c optional acpi dev/acpica/acpi_battery.c optional acpi dev/acpica/acpi_button.c optional acpi dev/acpica/acpi_cmbat.c optional acpi dev/acpica/acpi_cpu.c optional acpi dev/acpica/acpi_ec.c optional acpi dev/acpica/acpi_hpet.c optional acpi dev/acpica/acpi_isab.c optional acpi isa dev/acpica/acpi_lid.c optional acpi dev/acpica/acpi_package.c optional acpi dev/acpica/acpi_pci.c optional acpi pci dev/acpica/acpi_pci_link.c optional acpi pci dev/acpica/acpi_pcib.c optional acpi pci dev/acpica/acpi_pcib_acpi.c optional acpi pci dev/acpica/acpi_pcib_pci.c optional acpi pci dev/acpica/acpi_perf.c optional acpi dev/acpica/acpi_powerres.c optional acpi dev/acpica/acpi_quirk.c optional acpi dev/acpica/acpi_resource.c optional acpi dev/acpica/acpi_smbat.c optional acpi dev/acpica/acpi_thermal.c optional acpi dev/acpica/acpi_throttle.c optional acpi dev/acpica/acpi_timer.c optional acpi dev/acpica/acpi_video.c optional acpi_video acpi dev/adlink/adlink.c optional adlink dev/advansys/adv_eisa.c optional adv eisa dev/advansys/adv_pci.c optional adv pci dev/advansys/advansys.c optional adv dev/advansys/advlib.c optional adv dev/advansys/advmcode.c optional adv dev/advansys/adw_pci.c optional adw pci dev/advansys/adwcam.c optional adw dev/advansys/adwlib.c optional adw dev/advansys/adwmcode.c optional adw dev/aha/aha.c optional aha dev/aha/aha_isa.c optional aha isa dev/aha/aha_mca.c optional aha mca dev/ahb/ahb.c optional ahb eisa dev/aic/aic.c optional aic dev/aic/aic_pccard.c optional aic pccard dev/aic7xxx/ahc_eisa.c optional ahc eisa dev/aic7xxx/ahc_isa.c optional ahc isa dev/aic7xxx/ahc_pci.c optional ahc pci dev/aic7xxx/ahd_pci.c optional ahd pci dev/aic7xxx/aic7770.c optional ahc dev/aic7xxx/aic79xx.c optional ahd pci dev/aic7xxx/aic79xx_osm.c optional ahd pci dev/aic7xxx/aic79xx_pci.c optional ahd pci dev/aic7xxx/aic7xxx.c optional ahc dev/aic7xxx/aic7xxx_93cx6.c optional ahc dev/aic7xxx/aic7xxx_osm.c optional ahc dev/aic7xxx/aic7xxx_pci.c optional ahc pci dev/amd/amd.c optional amd dev/amr/amr.c optional amr dev/amr/amr_cam.c optional amr dev/amr/amr_disk.c optional amr dev/amr/amr_pci.c optional amr pci dev/an/if_an.c optional an dev/an/if_an_isa.c optional an isa dev/an/if_an_pccard.c optional an pccard dev/an/if_an_pci.c optional an pci dev/asr/asr.c optional asr pci dev/ata/ata_if.m optional ata dev/ata/ata-all.c optional ata dev/ata/ata-card.c optional ata pccard dev/ata/ata-cbus.c optional ata pc98 dev/ata/ata-chipset.c optional ata pci dev/ata/ata-disk.c optional atadisk dev/ata/ata-dma.c optional ata pci dev/ata/ata-isa.c optional ata isa dev/ata/ata-lowlevel.c optional ata dev/ata/ata-pci.c optional ata pci dev/ata/ata-queue.c optional ata dev/ata/ata-raid.c optional ataraid dev/ata/atapi-cam.c optional atapicam dev/ata/atapi-cd.c optional atapicd dev/ata/atapi-fd.c optional atapifd dev/ata/atapi-tape.c optional atapist dev/ath/ath_rate/amrr/amrr.c optional ath_rate_amrr dev/ath/ath_rate/onoe/onoe.c optional ath_rate_onoe \ compile-with "${NORMAL_C} -I$S/contrib/dev/ath/freebsd" dev/ath/ath_rate/sample/sample.c optional ath_rate_sample \ compile-with "${NORMAL_C} -I$S/contrib/dev/ath/freebsd" dev/ath/if_ath.c optional ath \ compile-with "${NORMAL_C} -I$S/contrib/dev/ath/freebsd" dev/ath/if_ath_pci.c optional ath pci \ compile-with "${NORMAL_C} -I$S/contrib/dev/ath/freebsd" dev/awi/am79c930.c optional awi dev/awi/awi.c optional awi dev/awi/if_awi_pccard.c optional awi pccard dev/bfe/if_bfe.c optional bfe dev/bge/if_bge.c optional bge dev/bktr/bktr_audio.c optional bktr pci dev/bktr/bktr_card.c optional bktr pci dev/bktr/bktr_core.c optional bktr pci dev/bktr/bktr_i2c.c optional bktr pci smbus dev/bktr/bktr_os.c optional bktr pci dev/bktr/bktr_tuner.c optional bktr pci dev/bktr/msp34xx.c optional bktr pci dev/buslogic/bt.c optional bt dev/buslogic/bt_eisa.c optional bt eisa dev/buslogic/bt_isa.c optional bt isa dev/buslogic/bt_mca.c optional bt mca dev/buslogic/bt_pci.c optional bt pci dev/cardbus/cardbus.c optional cardbus dev/cardbus/cardbus_cis.c optional cardbus dev/ciss/ciss.c optional ciss dev/cm/smc90cx6.c optional cm dev/cnw/if_cnw.c optional cnw pccard dev/cpufreq/ichss.c optional cpufreq dev/cs/if_cs.c optional cs dev/cs/if_cs_isa.c optional cs isa dev/cs/if_cs_pccard.c optional cs pccard dev/cy/cy.c optional cy dev/cy/cy_isa.c optional cy isa dev/cy/cy_pci.c optional cy pci dev/dc/if_dc.c optional dc pci dev/dc/dcphy.c optional dc pci dev/dc/pnphy.c optional dc pci dev/dcons/dcons.c optional dcons dev/dcons/dcons_crom.c optional dcons_crom dev/dcons/dcons_os.c optional dcons dev/digi/CX.c optional digi_CX dev/digi/CX_PCI.c optional digi_CX_PCI dev/digi/EPCX.c optional digi_EPCX dev/digi/EPCX_PCI.c optional digi_EPCX_PCI dev/digi/Xe.c optional digi_Xe dev/digi/Xem.c optional digi_Xem dev/digi/Xr.c optional digi_Xr dev/digi/digi.c optional digi dev/digi/digi_isa.c optional digi isa dev/digi/digi_pci.c optional digi pci dev/dpt/dpt_eisa.c optional dpt eisa dev/dpt/dpt_pci.c optional dpt pci dev/dpt/dpt_scsi.c optional dpt dev/drm/ati_pcigart.c optional drm dev/drm/drm_agpsupport.c optional drm dev/drm/drm_auth.c optional drm dev/drm/drm_bufs.c optional drm dev/drm/drm_context.c optional drm dev/drm/drm_dma.c optional drm dev/drm/drm_drawable.c optional drm dev/drm/drm_drv.c optional drm dev/drm/drm_fops.c optional drm dev/drm/drm_ioctl.c optional drm dev/drm/drm_irq.c optional drm dev/drm/drm_lock.c optional drm dev/drm/drm_memory.c optional drm dev/drm/drm_pci.c optional drm dev/drm/drm_scatter.c optional drm dev/drm/drm_sysctl.c optional drm dev/drm/drm_vm.c optional drm dev/drm/mach64_dma.c optional mach64drm dev/drm/mach64_drv.c optional mach64drm dev/drm/mach64_irq.c optional mach64drm dev/drm/mach64_state.c optional mach64drm dev/drm/mga_dma.c optional mgadrm dev/drm/mga_drv.c optional mgadrm dev/drm/mga_irq.c optional mgadrm dev/drm/mga_state.c optional mgadrm \ compile-with "${NORMAL_C} -finline-limit=13500" dev/drm/mga_warp.c optional mgadrm dev/drm/r128_cce.c optional r128drm dev/drm/r128_drv.c optional r128drm dev/drm/r128_irq.c optional r128drm dev/drm/r128_state.c optional r128drm \ compile-with "${NORMAL_C} -finline-limit=13500" dev/drm/r300_cmdbuf.c optional radeondrm dev/drm/radeon_cp.c optional radeondrm dev/drm/radeon_drv.c optional radeondrm dev/drm/radeon_irq.c optional radeondrm dev/drm/radeon_mem.c optional radeondrm dev/drm/radeon_state.c optional radeondrm +dev/drm/savage_bci.c optional savagedrm +dev/drm/savage_drv.c optional savagedrm +dev/drm/savage_state.c optional savagedrm dev/drm/sis_drv.c optional sisdrm dev/drm/sis_ds.c optional sisdrm dev/drm/sis_mm.c optional sisdrm dev/drm/tdfx_drv.c optional tdfxdrm dev/ed/if_ed.c optional ed dev/ed/if_ed_novell.c optional ed dev/ed/if_ed_rtl80x9.c optional ed dev/ed/if_ed_pccard.c optional ed pccard dev/ed/if_ed_pci.c optional ed pci dev/eisa/eisa_if.m standard dev/eisa/eisaconf.c optional eisa dev/em/if_em.c optional em dev/em/if_em_hw.c optional em dev/en/if_en_pci.c optional en pci dev/en/midway.c optional en dev/ep/if_ep.c optional ep dev/ep/if_ep_eisa.c optional ep eisa dev/ep/if_ep_isa.c optional ep isa dev/ep/if_ep_mca.c optional ep mca dev/ep/if_ep_pccard.c optional ep pccard dev/esp/ncr53c9x.c optional esp dev/ex/if_ex.c optional ex dev/ex/if_ex_isa.c optional ex isa dev/ex/if_ex_pccard.c optional ex pccard dev/exca/exca.c optional cbb dev/fatm/if_fatm.c optional fatm pci dev/fe/if_fe.c optional fe dev/fe/if_fe_pccard.c optional fe pccard dev/firewire/firewire.c optional firewire dev/firewire/fwcrom.c optional firewire dev/firewire/fwdev.c optional firewire dev/firewire/fwdma.c optional firewire dev/firewire/fwmem.c optional firewire dev/firewire/fwohci.c optional firewire dev/firewire/fwohci_pci.c optional firewire pci dev/firewire/if_fwe.c optional fwe dev/firewire/if_fwip.c optional fwip dev/firewire/sbp.c optional sbp dev/firewire/sbp_targ.c optional sbp_targ dev/fxp/if_fxp.c optional fxp dev/gem/if_gem.c optional gem dev/gem/if_gem_pci.c optional gem pci dev/harp/if_harp.c optional harp pci dev/hatm/if_hatm.c optional hatm pci dev/hatm/if_hatm_intr.c optional hatm pci dev/hatm/if_hatm_ioctl.c optional hatm pci dev/hatm/if_hatm_rx.c optional hatm pci dev/hatm/if_hatm_tx.c optional hatm pci dev/hfa/fore_buffer.c optional hfa dev/hfa/fore_command.c optional hfa dev/hfa/fore_globals.c optional hfa dev/hfa/fore_if.c optional hfa dev/hfa/fore_init.c optional hfa dev/hfa/fore_intr.c optional hfa dev/hfa/fore_output.c optional hfa dev/hfa/fore_receive.c optional hfa dev/hfa/fore_stats.c optional hfa dev/hfa/fore_timer.c optional hfa dev/hfa/fore_transmit.c optional hfa dev/hfa/fore_vcm.c optional hfa #dev/hfa/hfa_eisa.c optional hfa eisa dev/hfa/hfa_freebsd.c optional hfa dev/hfa/hfa_pci.c optional hfa pci #dev/hfa/hfa_sbus.c optional hfa sbus dev/hifn/hifn7751.c optional hifn dev/hme/if_hme.c optional hme dev/hme/if_hme_pci.c optional hme pci dev/hme/if_hme_sbus.c optional hme sbus dev/hwpmc/hwpmc_logging.c optional hwpmc dev/hwpmc/hwpmc_mod.c optional hwpmc dev/ichsmb/ichsmb.c optional ichsmb dev/ichsmb/ichsmb_pci.c optional ichsmb pci dev/ida/ida.c optional ida dev/ida/ida_disk.c optional ida dev/ida/ida_eisa.c optional ida eisa dev/ida/ida_pci.c optional ida pci dev/ie/if_ie.c optional ie isa nowerror dev/ie/if_ie_isa.c optional ie isa dev/ieee488/ibfoo.c optional pcii | tnt4882 dev/ieee488/pcii.c optional pcii dev/ieee488/tnt4882.c optional tnt4882 dev/ieee488/upd7210.c optional pcii | tnt4882 dev/iicbus/if_ic.c optional ic dev/iicbus/iic.c optional iic dev/iicbus/iicbb.c optional iicbb dev/iicbus/iicbb_if.m optional iicbb dev/iicbus/iicbus.c optional iicbus dev/iicbus/iicbus_if.m optional iicbus dev/iicbus/iiconf.c optional iicbus dev/iicbus/iicsmb.c optional iicsmb \ dependency "iicbus_if.h" dev/iir/iir.c optional iir dev/iir/iir_ctrl.c optional iir dev/iir/iir_pci.c optional iir pci dev/ips/ips.c optional ips dev/ips/ips_commands.c optional ips dev/ips/ips_disk.c optional ips dev/ips/ips_ioctl.c optional ips dev/ips/ips_pci.c optional ips pci dev/ipw/if_ipw.c optional ipw dev/isp/isp.c optional isp dev/isp/isp_freebsd.c optional isp dev/isp/isp_pci.c optional isp pci dev/isp/isp_sbus.c optional isp sbus dev/isp/isp_target.c optional isp dev/ispfw/ispfw.c optional ispfw dev/iwi/if_iwi.c optional iwi dev/ixgb/if_ixgb.c optional ixgb dev/ixgb/ixgb_ee.c optional ixgb dev/ixgb/ixgb_hw.c optional ixgb dev/joy/joy.c optional joy dev/joy/joy_isa.c optional joy isa dev/joy/joy_pccard.c optional joy pccard dev/kbdmux/kbdmux.c optional kbdmux dev/led/led.c standard dev/lge/if_lge.c optional lge dev/lmc/if_lmc.c optional lmc dev/lnc/if_lnc.c optional lnc dev/lnc/if_lnc_pci.c optional lnc pci dev/mc146818/mc146818.c optional mc146818 dev/mca/mca_bus.c optional mca dev/mcd/mcd.c optional mcd isa nowerror dev/mcd/mcd_isa.c optional mcd isa nowerror dev/md/md.c optional md dev/mem/memdev.c optional mem dev/mii/acphy.c optional miibus dev/mii/amphy.c optional miibus dev/mii/bmtphy.c optional miibus dev/mii/brgphy.c optional miibus dev/mii/ciphy.c optional miibus dev/mii/e1000phy.c optional miibus dev/mii/exphy.c optional miibus dev/mii/inphy.c optional miibus dev/mii/lxtphy.c optional miibus dev/mii/mii.c optional miibus dev/mii/mii_physubr.c optional miibus dev/mii/miibus_if.m optional miibus dev/mii/mlphy.c optional miibus dev/mii/nsgphy.c optional miibus dev/mii/nsphy.c optional miibus dev/mii/pnaphy.c optional miibus dev/mii/qsphy.c optional miibus dev/mii/rgephy.c optional miibus dev/mii/rlphy.c optional miibus dev/mii/ruephy.c optional miibus dev/mii/tdkphy.c optional miibus dev/mii/tlphy.c optional miibus dev/mii/ukphy.c optional miibus dev/mii/ukphy_subr.c optional miibus dev/mii/xmphy.c optional miibus dev/mk48txx/mk48txx.c optional mk48txx dev/mlx/mlx.c optional mlx dev/mlx/mlx_disk.c optional mlx dev/mlx/mlx_pci.c optional mlx pci dev/mly/mly.c optional mly dev/mpt/mpt.c optional mpt dev/mpt/mpt_cam.c optional mpt dev/mpt/mpt_debug.c optional mpt dev/mpt/mpt_pci.c optional mpt pci dev/mpt/mpt_raid.c optional mpt dev/my/if_my.c optional my dev/ncv/ncr53c500.c optional ncv dev/ncv/ncr53c500_pccard.c optional ncv pccard dev/nge/if_nge.c optional nge dev/nmdm/nmdm.c optional nmdm dev/nsp/nsp.c optional nsp dev/nsp/nsp_pccard.c optional nsp pccard dev/null/null.c standard dev/patm/if_patm.c optional patm pci dev/patm/if_patm_attach.c optional patm pci dev/patm/if_patm_intr.c optional patm pci dev/patm/if_patm_ioctl.c optional patm pci dev/patm/if_patm_rtables.c optional patm pci dev/patm/if_patm_rx.c optional patm pci dev/patm/if_patm_tx.c optional patm pci dev/pbio/pbio.c optional pbio isa dev/pccard/card_if.m standard dev/pccard/pccard.c optional pccard dev/pccard/pccard_cis.c optional pccard dev/pccard/pccard_cis_quirks.c optional pccard dev/pccard/pccard_device.c optional pccard dev/pccard/power_if.m standard dev/pccbb/pccbb.c optional cbb dev/pccbb/pccbb_isa.c optional cbb isa dev/pccbb/pccbb_pci.c optional cbb pci dev/pcf/pcf.c optional pcf dev/pci/eisa_pci.c optional pci eisa dev/pci/fixup_pci.c optional pci dev/pci/ignore_pci.c optional pci dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_pci.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard dev/pdq/if_fea.c optional fea eisa dev/pdq/if_fpa.c optional fpa pci dev/pdq/pdq.c optional nowerror fea eisa | fpa pci dev/pdq/pdq_ifsubr.c optional nowerror fea eisa | fpa pci dev/ppbus/if_plip.c optional plip dev/ppbus/immio.c optional vpo dev/ppbus/lpbb.c optional lpbb dev/ppbus/lpt.c optional lpt dev/ppbus/pcfclock.c optional pcfclock dev/ppbus/ppb_1284.c optional ppbus dev/ppbus/ppb_base.c optional ppbus dev/ppbus/ppb_msq.c optional ppbus dev/ppbus/ppbconf.c optional ppbus dev/ppbus/ppbus_if.m optional ppbus dev/ppbus/ppi.c optional ppi dev/ppbus/pps.c optional pps dev/ppbus/vpo.c optional vpo dev/ppbus/vpoio.c optional vpo dev/pst/pst-iop.c optional pst dev/pst/pst-pci.c optional pst pci dev/pst/pst-raid.c optional pst dev/puc/puc.c optional puc dev/puc/puc_ebus.c optional puc ebus dev/puc/puc_pccard.c optional puc pccard dev/puc/puc_pci.c optional puc pci dev/puc/puc_sbus.c optional puc fhc | puc sbus dev/puc/pucdata.c optional puc pci dev/ral/if_ral.c optional ral dev/ral/if_ralrate.c optional ral dev/ral/if_ral_pccard.c optional ral pccard dev/ral/if_ral_pci.c optional ral pci dev/random/harvest.c standard dev/random/hash.c optional random dev/random/probe.c optional random dev/random/randomdev.c optional random dev/random/randomdev_soft.c optional random dev/random/yarrow.c optional random dev/ray/if_ray.c optional ray pccard dev/rc/rc.c optional rc dev/re/if_re.c optional re dev/rndtest/rndtest.c optional rndtest dev/rp/rp.c optional rp dev/rp/rp_isa.c optional rp isa dev/rp/rp_pci.c optional rp pci dev/sab/sab.c optional sab ebus dev/safe/safe.c optional safe dev/sbsh/if_sbsh.c optional sbsh dev/scd/scd.c optional scd isa dev/scd/scd_isa.c optional scd isa dev/si/si.c optional si dev/si/si2_z280.c optional si dev/si/si3_t225.c optional si dev/si/si_eisa.c optional si eisa dev/si/si_isa.c optional si isa dev/si/si_pci.c optional si pci dev/sio/sio_pccard.c optional sio pccard dev/sio/sio_pci.c optional sio pci dev/sio/sio_puc.c optional sio puc pci dev/smbus/smb.c optional smb dev/smbus/smbconf.c optional smbus dev/smbus/smbus.c optional smbus dev/smbus/smbus_if.m optional smbus dev/sn/if_sn.c optional sn dev/sn/if_sn_isa.c optional sn isa dev/sn/if_sn_pccard.c optional sn pccard dev/snp/snp.c optional snp dev/sound/isa/ad1816.c optional snd_ad1816 isa dev/sound/isa/es1888.c optional snd_ess isa dev/sound/isa/ess.c optional snd_ess isa dev/sound/isa/gusc.c optional snd_gusc isa dev/sound/isa/mss.c optional snd_mss isa dev/sound/isa/sb16.c optional snd_sb16 isa dev/sound/isa/sb8.c optional snd_sb8 isa dev/sound/isa/sbc.c optional snd_sbc isa dev/sound/isa/sndbuf_dma.c optional sound isa dev/sound/pci/als4000.c optional snd_als4000 pci dev/sound/pci/atiixp.c optional snd_atiixp pci #dev/sound/pci/au88x0.c optional snd_au88x0 pci dev/sound/pci/cmi.c optional snd_cmi pci dev/sound/pci/cs4281.c optional snd_cs4281 pci dev/sound/pci/csa.c optional snd_csa pci \ warning "kernel contains GPL contaminated csaimg.h header" dev/sound/pci/csapcm.c optional snd_csa pci dev/sound/pci/ds1.c optional snd_ds1 pci dev/sound/pci/emu10k1.c optional snd_emu10k1 pci \ dependency "emu10k1-alsa%diked.h" \ warning "kernel contains GPL contaminated emu10k1 headers" dev/sound/pci/es137x.c optional snd_es137x pci dev/sound/pci/fm801.c optional snd_fm801 pci dev/sound/pci/ich.c optional snd_ich pci dev/sound/pci/maestro.c optional snd_maestro pci dev/sound/pci/maestro3.c optional snd_maestro3 pci \ warning "kernel contains GPL contaminated maestro3 headers" dev/sound/pci/neomagic.c optional snd_neomagic pci dev/sound/pci/solo.c optional snd_solo pci dev/sound/pci/t4dwave.c optional snd_t4dwave pci dev/sound/pci/via8233.c optional snd_via8233 pci dev/sound/pci/via82c686.c optional snd_via82c686 pci dev/sound/pci/vibes.c optional snd_vibes pci #dev/sound/pci/vortex1.c optional snd_vortex1 pci dev/sound/pcm/ac97.c optional sound dev/sound/pcm/ac97_if.m optional sound dev/sound/pcm/ac97_patch.c optional sound dev/sound/pcm/buffer.c optional sound dev/sound/pcm/channel.c optional sound dev/sound/pcm/channel_if.m optional sound dev/sound/pcm/dsp.c optional sound dev/sound/pcm/fake.c optional sound dev/sound/pcm/feeder.c optional sound dev/sound/pcm/feeder_fmt.c optional sound dev/sound/pcm/feeder_if.m optional sound dev/sound/pcm/feeder_rate.c optional sound dev/sound/pcm/feeder_volume.c optional sound dev/sound/pcm/mixer.c optional sound dev/sound/pcm/mixer_if.m optional sound dev/sound/pcm/sndstat.c optional sound dev/sound/pcm/sound.c optional sound dev/sound/pcm/vchan.c optional sound #dev/sound/usb/upcm.c optional snd_upcm usb dev/sound/usb/uaudio.c optional snd_uaudio usb dev/sound/usb/uaudio_pcm.c optional snd_uaudio usb dev/sr/if_sr.c optional sr dev/sr/if_sr_pci.c optional sr pci dev/stg/tmc18c30.c optional stg dev/stg/tmc18c30_isa.c optional stg isa dev/stg/tmc18c30_pccard.c optional stg pccard dev/stg/tmc18c30_pci.c optional stg pci dev/stg/tmc18c30_subr.c optional stg dev/streams/streams.c optional streams dev/sym/sym_hipd.c optional sym \ dependency "$S/dev/sym/sym_{conf,defs}.h" dev/syscons/blank/blank_saver.c optional blank_saver dev/syscons/daemon/daemon_saver.c optional daemon_saver dev/syscons/dragon/dragon_saver.c optional dragon_saver dev/syscons/fade/fade_saver.c optional fade_saver dev/syscons/fire/fire_saver.c optional fire_saver dev/syscons/green/green_saver.c optional green_saver dev/syscons/logo/logo.c optional logo_saver dev/syscons/logo/logo_saver.c optional logo_saver dev/syscons/rain/rain_saver.c optional rain_saver dev/syscons/snake/snake_saver.c optional snake_saver dev/syscons/star/star_saver.c optional star_saver dev/syscons/warp/warp_saver.c optional warp_saver dev/tdfx/tdfx_pci.c optional tdfx pci dev/trm/trm.c optional trm dev/twa/tw_cl_fwimg.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_init.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_intr.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_io.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_misc.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_osl_cam.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_osl_freebsd.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twe/twe.c optional twe dev/twe/twe_freebsd.c optional twe dev/tx/if_tx.c optional tx dev/txp/if_txp.c optional txp dev/uart/uart_bus_acpi.c optional uart acpi #dev/uart/uart_bus_cbus.c optional uart cbus dev/uart/uart_bus_ebus.c optional uart ebus dev/uart/uart_bus_isa.c optional uart isa dev/uart/uart_bus_pccard.c optional uart pccard dev/uart/uart_bus_pci.c optional uart pci dev/uart/uart_bus_puc.c optional uart puc dev/uart/uart_core.c optional uart dev/uart/uart_dbg.c optional uart gdb dev/uart/uart_dev_ns8250.c optional uart dev/uart/uart_dev_sab82532.c optional uart dev/uart/uart_dev_z8530.c optional uart dev/uart/uart_if.m optional uart dev/uart/uart_subr.c optional uart dev/uart/uart_tty.c optional uart dev/ubsec/ubsec.c optional ubsec # # USB support dev/usb/ehci.c optional ehci dev/usb/ehci_pci.c optional ehci pci dev/usb/hid.c optional usb dev/usb/if_aue.c optional aue dev/usb/if_axe.c optional axe dev/usb/if_cdce.c optional cdce dev/usb/if_cue.c optional cue dev/usb/if_kue.c optional kue dev/usb/if_ural.c optional ural dev/usb/if_rue.c optional rue dev/usb/if_udav.c optional udav dev/usb/ohci.c optional ohci dev/usb/ohci_pci.c optional ohci pci dev/usb/sl811hs.c optional slhci dev/usb/slhci_pccard.c optional slhci pccard dev/usb/ubsa.c optional ubsa ucom dev/usb/ubser.c optional ubser dev/usb/ucom.c optional ucom dev/usb/ucycom.c optional ucycom ucom dev/usb/udbp.c optional udbp dev/usb/ufm.c optional ufm dev/usb/uftdi.c optional uftdi ucom dev/usb/ugen.c optional ugen dev/usb/uhci.c optional uhci dev/usb/uhci_pci.c optional uhci pci dev/usb/uhid.c optional uhid dev/usb/uhub.c optional usb dev/usb/ukbd.c optional ukbd dev/usb/ulpt.c optional ulpt dev/usb/umass.c optional umass dev/usb/umct.c optional umct dev/usb/umodem.c optional umodem dev/usb/ums.c optional ums dev/usb/uplcom.c optional uplcom ucom dev/usb/urio.c optional urio dev/usb/usb.c optional usb dev/usb/usb_ethersubr.c optional usb dev/usb/usb_if.m optional usb dev/usb/usb_mem.c optional usb dev/usb/usb_quirks.c optional usb dev/usb/usb_subr.c optional usb dev/usb/usbdi.c optional usb dev/usb/usbdi_util.c optional usb dev/usb/uscanner.c optional uscanner dev/usb/uvisor.c optional uvisor ucom dev/usb/uvscom.c optional uvscom ucom dev/utopia/idtphy.c optional utopia dev/utopia/suni.c optional utopia dev/utopia/utopia.c optional utopia dev/vge/if_vge.c optional vge dev/vkbd/vkbd.c optional vkbd dev/vx/if_vx.c optional vx dev/vx/if_vx_eisa.c optional vx eisa dev/vx/if_vx_pci.c optional vx pci dev/watchdog/watchdog.c standard dev/wds/wd7000.c optional wds isa dev/wi/if_wi.c optional wi dev/wi/if_wi_pccard.c optional wi pccard dev/wi/if_wi_pci.c optional wi pci dev/wl/if_wl.c optional wl isa dev/xe/if_xe.c optional xe dev/xe/if_xe_pccard.c optional xe pccard fs/deadfs/dead_vnops.c standard fs/devfs/devfs_devs.c standard fs/devfs/devfs_rule.c standard fs/devfs/devfs_vfsops.c standard fs/devfs/devfs_vnops.c standard fs/fdescfs/fdesc_vfsops.c optional fdescfs fs/fdescfs/fdesc_vnops.c optional fdescfs fs/fifofs/fifo_vnops.c standard fs/hpfs/hpfs_alsubr.c optional hpfs fs/hpfs/hpfs_lookup.c optional hpfs fs/hpfs/hpfs_subr.c optional hpfs fs/hpfs/hpfs_vfsops.c optional hpfs fs/hpfs/hpfs_vnops.c optional hpfs fs/msdosfs/msdosfs_conv.c optional msdosfs fs/msdosfs/msdosfs_denode.c optional msdosfs fs/msdosfs/msdosfs_fat.c optional msdosfs fs/msdosfs/msdosfs_fileno.c optional msdosfs_large fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv fs/msdosfs/msdosfs_lookup.c optional msdosfs fs/msdosfs/msdosfs_vfsops.c optional msdosfs fs/msdosfs/msdosfs_vnops.c optional msdosfs fs/ntfs/ntfs_compr.c optional ntfs fs/ntfs/ntfs_iconv.c optional ntfs_iconv fs/ntfs/ntfs_ihash.c optional ntfs fs/ntfs/ntfs_subr.c optional ntfs fs/ntfs/ntfs_vfsops.c optional ntfs fs/ntfs/ntfs_vnops.c optional ntfs fs/nullfs/null_subr.c optional nullfs fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs fs/nwfs/nwfs_io.c optional nwfs fs/nwfs/nwfs_ioctl.c optional nwfs fs/nwfs/nwfs_node.c optional nwfs fs/nwfs/nwfs_subr.c optional nwfs fs/nwfs/nwfs_vfsops.c optional nwfs fs/nwfs/nwfs_vnops.c optional nwfs fs/portalfs/portal_vfsops.c optional portalfs fs/portalfs/portal_vnops.c optional portalfs fs/procfs/procfs.c optional procfs fs/procfs/procfs_ctl.c optional procfs fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_ioctl.c optional procfs fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_note.c optional procfs fs/procfs/procfs_regs.c optional procfs fs/procfs/procfs_rlimit.c optional procfs fs/procfs/procfs_status.c optional procfs fs/procfs/procfs_type.c optional procfs fs/pseudofs/pseudofs.c optional pseudofs fs/pseudofs/pseudofs_fileno.c optional pseudofs fs/pseudofs/pseudofs_vncache.c optional pseudofs fs/pseudofs/pseudofs_vnops.c optional pseudofs fs/smbfs/smbfs_io.c optional smbfs fs/smbfs/smbfs_node.c optional smbfs fs/smbfs/smbfs_smb.c optional smbfs fs/smbfs/smbfs_subr.c optional smbfs fs/smbfs/smbfs_vfsops.c optional smbfs fs/smbfs/smbfs_vnops.c optional smbfs fs/udf/osta.c optional udf fs/udf/udf_iconv.c optional udf_iconv fs/udf/udf_vfsops.c optional udf fs/udf/udf_vnops.c optional udf fs/umapfs/umap_subr.c optional umapfs fs/umapfs/umap_vfsops.c optional umapfs fs/umapfs/umap_vnops.c optional umapfs fs/unionfs/union_subr.c optional unionfs fs/unionfs/union_vfsops.c optional unionfs fs/unionfs/union_vnops.c optional unionfs gdb/gdb_main.c optional gdb gdb/gdb_packet.c optional gdb geom/bde/g_bde.c optional geom_bde geom/bde/g_bde_crypt.c optional geom_bde geom/bde/g_bde_lock.c optional geom_bde geom/bde/g_bde_work.c optional geom_bde geom/concat/g_concat.c optional geom_concat geom/eli/g_eli.c optional geom_eli geom/eli/g_eli_crypto.c optional geom_eli geom/eli/g_eli_ctl.c optional geom_eli geom/eli/g_eli_key.c optional geom_eli geom/eli/pkcs5v2.c optional geom_eli geom/gate/g_gate.c optional geom_gate geom/geom_aes.c optional geom_aes geom/geom_apple.c optional geom_apple geom/geom_bsd.c optional geom_bsd geom/geom_bsd_enc.c optional geom_bsd geom/geom_ccd.c optional ccd | geom_ccd geom/geom_ctl.c standard geom/geom_dev.c standard geom/geom_disk.c standard geom/geom_dump.c standard geom/geom_event.c standard geom/geom_fox.c optional geom_fox geom/geom_gpt.c optional geom_gpt geom/geom_io.c standard geom/geom_kern.c standard geom/geom_mbr.c optional geom_mbr geom/geom_mbr_enc.c optional geom_mbr geom/geom_pc98.c optional geom_pc98 geom/geom_pc98_enc.c optional geom_pc98 geom/geom_slice.c standard geom/geom_subr.c standard geom/geom_sunlabel.c optional geom_sunlabel geom/geom_sunlabel_enc.c optional geom_sunlabel geom/geom_vfs.c standard geom/geom_vol_ffs.c optional geom_vol geom/label/g_label.c optional geom_label geom/label/g_label_ext2fs.c optional geom_label geom/label/g_label_iso9660.c optional geom_label geom/label/g_label_msdosfs.c optional geom_label geom/label/g_label_ntfs.c optional geom_label geom/label/g_label_reiserfs.c optional geom_label geom/label/g_label_ufs.c optional geom_label geom/mirror/g_mirror.c optional geom_mirror geom/mirror/g_mirror_ctl.c optional geom_mirror geom/nop/g_nop.c optional geom_nop geom/raid3/g_raid3.c optional geom_raid3 geom/raid3/g_raid3_ctl.c optional geom_raid3 geom/shsec/g_shsec.c optional geom_shsec geom/stripe/g_stripe.c optional geom_stripe geom/uzip/g_uzip.c optional geom_uzip geom/zero/g_zero.c optional geom_zero gnu/fs/ext2fs/ext2_alloc.c optional ext2fs \ warning "kernel contains GPL contaminated ext2fs filesystem" gnu/fs/ext2fs/ext2_balloc.c optional ext2fs gnu/fs/ext2fs/ext2_bmap.c optional ext2fs gnu/fs/ext2fs/ext2_inode.c optional ext2fs gnu/fs/ext2fs/ext2_inode_cnv.c optional ext2fs gnu/fs/ext2fs/ext2_linux_balloc.c optional ext2fs gnu/fs/ext2fs/ext2_linux_ialloc.c optional ext2fs gnu/fs/ext2fs/ext2_lookup.c optional ext2fs gnu/fs/ext2fs/ext2_subr.c optional ext2fs gnu/fs/ext2fs/ext2_vfsops.c optional ext2fs gnu/fs/ext2fs/ext2_vnops.c optional ext2fs gnu/fs/reiserfs/reiserfs_hashes.c optional reiserfs \ warning "kernel contains GPL contaminated ReiserFS filesystem" gnu/fs/reiserfs/reiserfs_inode.c optional reiserfs gnu/fs/reiserfs/reiserfs_item_ops.c optional reiserfs gnu/fs/reiserfs/reiserfs_namei.c optional reiserfs gnu/fs/reiserfs/reiserfs_prints.c optional reiserfs gnu/fs/reiserfs/reiserfs_stree.c optional reiserfs gnu/fs/reiserfs/reiserfs_vfsops.c optional reiserfs gnu/fs/reiserfs/reiserfs_vnops.c optional reiserfs # # isdn4bsd device drivers # i4b/driver/i4b_trace.c optional i4btrc i4b/driver/i4b_rbch.c optional i4brbch i4b/driver/i4b_tel.c optional i4btel i4b/driver/i4b_ipr.c optional i4bipr net/slcompress.c optional i4bipr | i4bisppp i4b/driver/i4b_ctl.c optional i4bctl i4b/driver/i4b_ing.c optional i4bing i4b/driver/i4b_isppp.c optional i4bisppp # # isdn4bsd CAPI driver # i4b/capi/capi_l4if.c optional i4bcapi i4b/capi/capi_llif.c optional i4bcapi i4b/capi/capi_msgs.c optional i4bcapi # # isdn4bsd AVM B1/T1 CAPI driver # i4b/capi/iavc/iavc_pci.c optional iavc i4bcapi pci i4b/capi/iavc/iavc_isa.c optional iavc i4bcapi isa i4b/capi/iavc/iavc_lli.c optional iavc i4bcapi i4b/capi/iavc/iavc_card.c optional iavc i4bcapi # # isdn4bsd support # i4b/layer2/i4b_mbuf.c optional i4btrc # # isdn4bsd Q.921 handler # i4b/layer2/i4b_l2.c optional i4bq921 i4b/layer2/i4b_l2fsm.c optional i4bq921 i4b/layer2/i4b_uframe.c optional i4bq921 i4b/layer2/i4b_tei.c optional i4bq921 i4b/layer2/i4b_sframe.c optional i4bq921 i4b/layer2/i4b_iframe.c optional i4bq921 i4b/layer2/i4b_l2timer.c optional i4bq921 i4b/layer2/i4b_util.c optional i4bq921 i4b/layer2/i4b_lme.c optional i4bq921 # # isdn4bsd Q.931 handler # i4b/layer3/i4b_q931.c optional i4bq931 i4b/layer3/i4b_l3fsm.c optional i4bq931 i4b/layer3/i4b_l3timer.c optional i4bq931 i4b/layer3/i4b_l2if.c optional i4bq931 i4b/layer3/i4b_l4if.c optional i4bq931 i4b/layer3/i4b_q932fac.c optional i4bq931 # # isdn4bsd control device driver, interface to isdnd # i4b/layer4/i4b_i4bdrv.c optional i4b i4b/layer4/i4b_l4.c optional i4b i4b/layer4/i4b_l4mgmt.c optional i4b i4b/layer4/i4b_l4timer.c optional i4b # isa/isa_if.m standard isa/isa_common.c optional isa isa/isahint.c optional isa isa/orm.c optional isa isa/pnp.c optional isa isa/pnpparse.c optional isa isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 isofs/cd9660/cd9660_rrip.c optional cd9660 isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 isofs/cd9660/cd9660_iconv.c optional cd9660_iconv kern/bus_if.m standard kern/clock_if.m optional genclock kern/cpufreq_if.m standard kern/device_if.m standard kern/imgact_elf.c standard kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard kern/kern_acct.c standard kern/kern_acl.c standard kern/kern_alq.c optional alq kern/kern_clock.c standard kern/kern_condvar.c standard kern/kern_conf.c standard kern/kern_cpu.c standard kern/kern_context.c standard kern/kern_descrip.c standard kern/kern_environment.c standard kern/kern_event.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard kern/kern_idle.c standard kern/kern_intr.c standard kern/kern_jail.c standard kern/kern_kse.c standard kern/kern_kthread.c standard kern/kern_ktr.c optional ktr kern/kern_ktrace.c standard kern/kern_linker.c standard kern/kern_lock.c standard kern/kern_lockf.c standard kern/kern_mac.c standard kern/kern_malloc.c standard kern/kern_mbuf.c standard kern/kern_mib.c standard kern/kern_module.c standard kern/kern_mtxpool.c standard kern/kern_mutex.c standard kern/kern_ntptime.c standard kern/kern_physio.c standard kern/kern_pmc.c standard kern/kern_poll.c optional device_polling kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_sema.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_subr.c standard kern/kern_sx.c standard kern/kern_synch.c standard kern/kern_syscalls.c standard kern/kern_sysctl.c standard kern/kern_tc.c standard kern/kern_thr.c standard kern/kern_thread.c standard kern/kern_time.c standard kern/kern_timeout.c standard kern/kern_umtx.c standard kern/kern_uuid.c standard kern/kern_xxx.c standard kern/link_elf.c standard kern/linker_if.m standard kern/md4c.c optional netsmb kern/md5c.c standard kern/sched_4bsd.c optional sched_4bsd kern/sched_ule.c optional sched_ule kern/subr_autoconf.c standard kern/subr_blist.c standard kern/subr_bus.c standard kern/subr_clock.c optional genclock kern/subr_devstat.c standard kern/subr_disk.c standard kern/subr_eventhandler.c standard kern/subr_hints.c standard kern/subr_kdb.c standard kern/subr_kobj.c standard kern/subr_log.c standard kern/subr_mbpool.c optional libmbpool kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_msgbuf.c standard kern/subr_param.c standard kern/subr_pcpu.c standard kern/subr_power.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rman.c standard kern/subr_sbuf.c standard kern/subr_scanf.c standard kern/subr_sleepqueue.c standard kern/subr_smp.c standard kern/subr_stack.c optional ddb kern/subr_taskqueue.c standard kern/subr_trap.c standard kern/subr_turnstile.c standard kern/subr_unit.c standard kern/subr_witness.c optional witness kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/syscalls.c optional witness kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c standard kern/tty_conf.c standard kern/tty_cons.c standard kern/tty_pty.c optional pty kern/tty_subr.c standard kern/tty_tty.c standard kern/uipc_accf.c optional inet kern/uipc_cow.c optional zero_copy_sockets kern/uipc_domain.c standard kern/uipc_mbuf.c standard kern/uipc_mbuf2.c standard kern/uipc_mqueue.c optional p1003_1b_mqueue kern/uipc_proto.c standard kern/uipc_sem.c optional p1003_1b_semaphores kern/uipc_socket.c standard kern/uipc_socket2.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_aio.c optional vfs_aio kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_default.c standard kern/vfs_export.c standard kern/vfs_hash.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_mount.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard # # These files in libkern/ are those needed by all architectures. Some # of the files in libkern/ are only needed on some architectures, e.g., # libkern/divdi3.c is needed by i386 but not alpha. Also, some of these # routines may be optimized for a particular platform. In either case, # the file should be moved to conf/files. from here. # libkern/arc4random.c standard libkern/bcd.c standard libkern/bsearch.c standard libkern/crc32.c standard libkern/fnmatch.c standard libkern/gets.c standard libkern/iconv.c optional libiconv libkern/iconv_converter_if.m optional libiconv libkern/iconv_xlat.c optional libiconv libkern/iconv_xlat16.c optional libiconv libkern/index.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine libkern/qsort.c standard libkern/qsort_r.c standard libkern/random.c standard libkern/rindex.c standard libkern/scanc.c standard libkern/skpc.c standard libkern/strcasecmp.c standard libkern/strcat.c standard libkern/strcmp.c standard libkern/strcpy.c standard libkern/strdup.c standard libkern/strlcat.c standard libkern/strlcpy.c standard libkern/strlen.c standard libkern/strncmp.c standard libkern/strncpy.c standard libkern/strsep.c standard libkern/strspn.c standard libkern/strtol.c standard libkern/strtoq.c standard libkern/strtoul.c standard libkern/strtouq.c standard libkern/strvalid.c standard net/bpf.c standard net/bpf_filter.c optional bpf | netgraph_bpf net/bridgestp.c optional if_bridge net/bsd_comp.c optional ppp_bsdcomp net/if.c standard net/if_arcsubr.c optional arcnet net/if_atmsubr.c optional atm net/if_bridge.c optional if_bridge net/if_clone.c standard net/if_disc.c optional disc net/if_ef.c optional ef net/if_ethersubr.c optional ether net/if_faith.c optional faith net/if_fddisubr.c optional fddi net/if_fwsubr.c optional fwip net/if_gif.c optional gif net/if_gre.c optional gre net/if_iso88025subr.c optional token net/if_loop.c optional loop net/if_media.c standard net/if_mib.c standard net/if_ppp.c optional ppp net/if_sl.c optional sl net/if_spppfr.c optional i4bisppp | sppp net/if_spppsubr.c optional i4bisppp | sppp net/if_stf.c optional stf net/if_tun.c optional tun net/if_tap.c optional tap net/if_vlan.c optional vlan net/netisr.c standard net/ppp_deflate.c optional ppp_deflate net/ppp_tty.c optional ppp net/pfil.c optional ether | inet net/radix.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard net/slcompress.c optional netgraph_vjc | ppp | sl | sppp net/zlib.c optional crypto | geom_uzip | ipsec | \ ppp_deflate net80211/ieee80211.c optional wlan net80211/ieee80211_acl.c optional wlan_acl net80211/ieee80211_crypto.c optional wlan net80211/ieee80211_crypto_ccmp.c optional wlan_ccmp net80211/ieee80211_crypto_none.c optional wlan net80211/ieee80211_crypto_tkip.c optional wlan_tkip net80211/ieee80211_crypto_wep.c optional wlan_wep net80211/ieee80211_freebsd.c optional wlan net80211/ieee80211_input.c optional wlan net80211/ieee80211_ioctl.c optional wlan net80211/ieee80211_node.c optional wlan net80211/ieee80211_output.c optional wlan net80211/ieee80211_proto.c optional wlan net80211/ieee80211_xauth.c optional wlan_xauth netatalk/aarp.c optional netatalk netatalk/at_control.c optional netatalk netatalk/at_proto.c optional netatalk netatalk/at_rmx.c optional netatalkdebug netatalk/ddp_input.c optional netatalk netatalk/ddp_output.c optional netatalk netatalk/ddp_pcb.c optional netatalk netatalk/ddp_usrreq.c optional netatalk netatm/atm_aal5.c optional atm_core netatm/atm_cm.c optional atm_core netatm/atm_device.c optional atm_core netatm/atm_if.c optional atm_core netatm/atm_proto.c optional atm_core netatm/atm_signal.c optional atm_core netatm/atm_socket.c optional atm_core netatm/atm_subr.c optional atm_core netatm/atm_usrreq.c optional atm_core netatm/ipatm/ipatm_event.c optional atm_ip atm_core netatm/ipatm/ipatm_if.c optional atm_ip atm_core netatm/ipatm/ipatm_input.c optional atm_ip atm_core netatm/ipatm/ipatm_load.c optional atm_ip atm_core netatm/ipatm/ipatm_output.c optional atm_ip atm_core netatm/ipatm/ipatm_usrreq.c optional atm_ip atm_core netatm/ipatm/ipatm_vcm.c optional atm_ip atm_core netatm/sigpvc/sigpvc_if.c optional atm_sigpvc atm_core netatm/sigpvc/sigpvc_subr.c optional atm_sigpvc atm_core netatm/spans/spans_arp.c optional atm_spans atm_core \ dependency "spans_xdr.h" netatm/spans/spans_cls.c optional atm_spans atm_core netatm/spans/spans_if.c optional atm_spans atm_core netatm/spans/spans_kxdr.c optional atm_spans atm_core netatm/spans/spans_msg.c optional atm_spans atm_core netatm/spans/spans_print.c optional atm_spans atm_core netatm/spans/spans_proto.c optional atm_spans atm_core netatm/spans/spans_subr.c optional atm_spans atm_core netatm/spans/spans_util.c optional atm_spans atm_core spans_xdr.h optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -h -C $S/netatm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.h" \ clean "spans_xdr.h" \ no-obj no-implicit-rule spans_xdr.c optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -c -C $S/netatm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.c" \ clean "spans_xdr.c" \ no-obj no-implicit-rule local spans_xdr.o optional atm_spans atm_core \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "${NORMAL_C}" \ no-implicit-rule local netatm/uni/q2110_sigaa.c optional atm_uni atm_core netatm/uni/q2110_sigcpcs.c optional atm_uni atm_core netatm/uni/q2110_subr.c optional atm_uni atm_core netatm/uni/qsaal1_sigaa.c optional atm_uni atm_core netatm/uni/qsaal1_sigcpcs.c optional atm_uni atm_core netatm/uni/qsaal1_subr.c optional atm_uni atm_core netatm/uni/sscf_uni.c optional atm_uni atm_core netatm/uni/sscf_uni_lower.c optional atm_uni atm_core netatm/uni/sscf_uni_upper.c optional atm_uni atm_core netatm/uni/sscop.c optional atm_uni atm_core netatm/uni/sscop_lower.c optional atm_uni atm_core netatm/uni/sscop_pdu.c optional atm_uni atm_core netatm/uni/sscop_sigaa.c optional atm_uni atm_core netatm/uni/sscop_sigcpcs.c optional atm_uni atm_core netatm/uni/sscop_subr.c optional atm_uni atm_core netatm/uni/sscop_timer.c optional atm_uni atm_core netatm/uni/sscop_upper.c optional atm_uni atm_core netatm/uni/uni_load.c optional atm_uni atm_core netatm/uni/uniarp.c optional atm_uni atm_core netatm/uni/uniarp_cache.c optional atm_uni atm_core netatm/uni/uniarp_input.c optional atm_uni atm_core netatm/uni/uniarp_output.c optional atm_uni atm_core netatm/uni/uniarp_timer.c optional atm_uni atm_core netatm/uni/uniarp_vcm.c optional atm_uni atm_core netatm/uni/uniip.c optional atm_uni atm_core netatm/uni/unisig_decode.c optional atm_uni atm_core netatm/uni/unisig_encode.c optional atm_uni atm_core netatm/uni/unisig_if.c optional atm_uni atm_core netatm/uni/unisig_mbuf.c optional atm_uni atm_core netatm/uni/unisig_msg.c optional atm_uni atm_core netatm/uni/unisig_print.c optional atm_uni atm_core netatm/uni/unisig_proto.c optional atm_uni atm_core netatm/uni/unisig_sigmgr_state.c optional atm_uni atm_core netatm/uni/unisig_subr.c optional atm_uni atm_core netatm/uni/unisig_util.c optional atm_uni atm_core netatm/uni/unisig_vc_state.c optional atm_uni atm_core netgraph/atm/atmpif/ng_atmpif.c optional netgraph_atm_atmpif netgraph/atm/atmpif/ng_atmpif_harp.c optional netgraph_atm_atmpif netgraph/atm/ccatm/ng_ccatm.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/ng_atm.c optional ngatm_atm netgraph/atm/ngatmbase.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/sscfu/ng_sscfu.c optional ngatm_sscfu \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/sscop/ng_sscop.c optional ngatm_sscop \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/uni/ng_uni.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/bluetooth/common/ng_bluetooth.c optional netgraph_bluetooth netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c optional netgraph_bluetooth_bt3c netgraph/bluetooth/drivers/h4/ng_h4.c optional netgraph_bluetooth_h4 netgraph/bluetooth/drivers/ubt/ng_ubt.c optional netgraph_bluetooth_ubt netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c optional netgraph_bluetooth_ubtbcmfw netgraph/bluetooth/hci/ng_hci_cmds.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_evnt.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_main.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_misc.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_ulpi.c optional netgraph_bluetooth_hci netgraph/bluetooth/l2cap/ng_l2cap_cmds.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_evnt.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_llpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_main.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_misc.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_ulpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/socket/ng_btsocket.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_hci_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_rfcomm.c optional netgraph_bluetooth_socket netgraph/netflow/netflow.c optional netgraph_netflow netgraph/netflow/ng_netflow.c optional netgraph_netflow netgraph/ng_UI.c optional netgraph_UI netgraph/ng_async.c optional netgraph_async netgraph/ng_atmllc.c optional netgraph_atmllc netgraph/ng_base.c optional netgraph netgraph/ng_bpf.c optional netgraph_bpf netgraph/ng_bridge.c optional netgraph_bridge netgraph/ng_cisco.c optional netgraph_cisco netgraph/ng_device.c optional netgraph_device netgraph/ng_echo.c optional netgraph_echo netgraph/ng_eiface.c optional netgraph_eiface netgraph/ng_ether.c optional netgraph_ether netgraph/ng_fec.c optional netgraph_fec netgraph/ng_frame_relay.c optional netgraph_frame_relay netgraph/ng_gif.c optional netgraph_gif netgraph/ng_gif_demux.c optional netgraph_gif_demux netgraph/ng_hole.c optional netgraph_hole netgraph/ng_iface.c optional netgraph_iface netgraph/ng_ip_input.c optional netgraph_ip_input netgraph/ng_ipfw.c optional netgraph_ipfw netgraph/ng_ksocket.c optional netgraph_ksocket netgraph/ng_l2tp.c optional netgraph_l2tp netgraph/ng_lmi.c optional netgraph_lmi netgraph/ng_mppc.c optional netgraph_mppc_compression | \ netgraph_mppc_encryption netgraph/ng_nat.c optional netgraph_nat netgraph/ng_one2many.c optional netgraph_one2many netgraph/ng_parse.c optional netgraph netgraph/ng_ppp.c optional netgraph_ppp netgraph/ng_pppoe.c optional netgraph_pppoe netgraph/ng_pptpgre.c optional netgraph_pptpgre netgraph/ng_rfc1490.c optional netgraph_rfc1490 netgraph/ng_socket.c optional netgraph_socket netgraph/ng_split.c optional netgraph_split netgraph/ng_sppp.c optional netgraph_sppp netgraph/ng_tcpmss.c optional netgraph_tcpmss netgraph/ng_tee.c optional netgraph_tee netgraph/ng_tty.c optional netgraph_tty netgraph/ng_vjc.c optional netgraph_vjc netinet/accf_data.c optional accept_filter_data netinet/accf_http.c optional accept_filter_http netinet/if_atm.c optional atm netinet/if_ether.c optional ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/ip_carp.c optional carp netinet/in_gif.c optional gif inet netinet/ip_gre.c optional gre inet netinet/ip_id.c optional inet netinet/in_pcb.c optional inet netinet/in_proto.c optional inet \ compile-with "${NORMAL_C} -I$S/contrib/pf" netinet/in_rmx.c optional inet netinet/ip_divert.c optional ipdivert netinet/ip_dummynet.c optional dummynet netinet/ip_ecn.c optional inet | inet6 netinet/ip_encap.c optional inet | inet6 netinet/ip_fastfwd.c optional inet netinet/ip_fw2.c optional ipfirewall netinet/ip_fw_pfil.c optional ipfirewall netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_mroute.c optional mrouting netinet/ip_options.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/tcp_debug.c optional tcpdebug netinet/tcp_hostcache.c optional inet netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet netinet/tcp_sack.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_syncache.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet netinet/libalias/alias.c optional libalias netinet/libalias/alias_cuseeme.c optional libalias netinet/libalias/alias_db.c optional libalias netinet/libalias/alias_ftp.c optional libalias netinet/libalias/alias_irc.c optional libalias netinet/libalias/alias_nbt.c optional libalias netinet/libalias/alias_pptp.c optional libalias netinet/libalias/alias_proxy.c optional libalias netinet/libalias/alias_skinny.c optional libalias netinet/libalias/alias_smedia.c optional libalias netinet/libalias/alias_util.c optional libalias netinet6/ah_aesxcbcmac.c optional ipsec netinet6/ah_core.c optional ipsec netinet6/ah_input.c optional ipsec netinet6/ah_output.c optional ipsec netinet6/dest6.c optional inet6 netinet6/esp_aesctr.c optional ipsec ipsec_esp netinet6/esp_core.c optional ipsec ipsec_esp netinet6/esp_input.c optional ipsec ipsec_esp netinet6/esp_output.c optional ipsec ipsec_esp netinet6/esp_rijndael.c optional ipsec ipsec_esp netinet6/frag6.c optional inet6 netinet6/icmp6.c optional inet6 netinet6/in6.c optional inet6 netinet6/in6_cksum.c optional inet6 netinet6/in6_gif.c optional gif inet6 netinet6/in6_ifattach.c optional inet6 netinet6/in6_pcb.c optional inet6 netinet6/in6_proto.c optional inet6 netinet6/in6_rmx.c optional inet6 netinet6/in6_src.c optional inet6 netinet6/ip6_forward.c optional inet6 netinet6/ip6_fw.c optional inet6 ipv6firewall netinet6/ip6_id.c optional inet6 netinet6/ip6_input.c optional inet6 netinet6/ip6_mroute.c optional inet6 netinet6/ip6_output.c optional inet6 netinet6/ipcomp_core.c optional ipsec netinet6/ipcomp_input.c optional ipsec netinet6/ipcomp_output.c optional ipsec netinet6/ipsec.c optional ipsec netinet6/mld6.c optional inet6 netinet6/nd6.c optional inet6 netinet6/nd6_nbr.c optional inet6 netinet6/nd6_rtr.c optional inet6 netinet6/raw_ip6.c optional inet6 netinet6/route6.c optional inet6 netinet6/scope6.c optional inet6 netinet6/udp6_output.c optional inet6 netinet6/udp6_usrreq.c optional inet6 netipsec/ipsec.c optional fast_ipsec netipsec/ipsec_input.c optional fast_ipsec netipsec/ipsec_mbuf.c optional fast_ipsec netipsec/ipsec_output.c optional fast_ipsec netipsec/key.c optional fast_ipsec netipsec/key_debug.c optional fast_ipsec netipsec/keysock.c optional fast_ipsec netipsec/xform_ah.c optional fast_ipsec netipsec/xform_esp.c optional fast_ipsec netipsec/xform_ipcomp.c optional fast_ipsec netipsec/xform_ipip.c optional fast_ipsec netipsec/xform_tcp.c optional fast_ipsec tcp_signature netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_input.c optional ipx netipx/ipx_ip.c optional ipx netipx/ipx_outputfl.c optional ipx netipx/ipx_pcb.c optional ipx netipx/ipx_proto.c optional ipx netipx/ipx_usrreq.c optional ipx netipx/spx_debug.c optional ipx netipx/spx_usrreq.c optional ipx netkey/key.c optional ipsec netkey/key_debug.c optional ipsec netkey/keydb.c optional ipsec netkey/keysock.c optional ipsec netnatm/natm.c optional natm netnatm/natm_pcb.c optional natm netnatm/natm_proto.c optional natm netncp/ncp_conn.c optional ncp netncp/ncp_crypt.c optional ncp netncp/ncp_login.c optional ncp netncp/ncp_mod.c optional ncp netncp/ncp_ncp.c optional ncp netncp/ncp_nls.c optional ncp netncp/ncp_rq.c optional ncp netncp/ncp_sock.c optional ncp netncp/ncp_subr.c optional ncp netsmb/smb_conn.c optional netsmb netsmb/smb_crypt.c optional netsmb netsmb/smb_dev.c optional netsmb netsmb/smb_iod.c optional netsmb netsmb/smb_rq.c optional netsmb netsmb/smb_smb.c optional netsmb netsmb/smb_subr.c optional netsmb netsmb/smb_trantcp.c optional netsmb netsmb/smb_usr.c optional netsmb nfs/nfs_common.c optional nfsclient | nfsserver nfs4client/nfs4_dev.c optional nfsclient nfs4client/nfs4_idmap.c optional nfsclient nfs4client/nfs4_socket.c optional nfsclient nfs4client/nfs4_subs.c optional nfsclient nfs4client/nfs4_vfs_subs.c optional nfsclient nfs4client/nfs4_vfsops.c optional nfsclient nfs4client/nfs4_vn_subs.c optional nfsclient nfs4client/nfs4_vnops.c optional nfsclient nfsclient/bootp_subr.c optional bootp nfsclient nfsclient/krpc_subr.c optional bootp nfsclient nfsclient/nfs_bio.c optional nfsclient nfsclient/nfs_diskless.c optional nfsclient nfs_root nfsclient/nfs_node.c optional nfsclient nfsclient/nfs_socket.c optional nfsclient nfsclient/nfs_subs.c optional nfsclient nfsclient/nfs_nfsiod.c optional nfsclient nfsclient/nfs_vfsops.c optional nfsclient nfsclient/nfs_vnops.c optional nfsclient nfsclient/nfs_lock.c optional nfsclient nfsserver/nfs_serv.c optional nfsserver nfsserver/nfs_srvsock.c optional nfsserver nfsserver/nfs_srvcache.c optional nfsserver nfsserver/nfs_srvsubs.c optional nfsserver nfsserver/nfs_syscalls.c optional nfsserver # crypto support opencrypto/cast.c optional crypto | ipsec ipsec_esp opencrypto/criov.c optional crypto opencrypto/crypto.c optional crypto opencrypto/cryptodev.c optional cryptodev opencrypto/cryptosoft.c optional crypto opencrypto/deflate.c optional crypto opencrypto/rmd160.c optional crypto | ipsec opencrypto/skipjack.c optional crypto opencrypto/xform.c optional crypto pci/agp.c optional agp pci pci/agp_if.m optional agp pci pci/alpm.c optional alpm pci pci/amdpm.c optional amdpm pci | nfpm pci pci/if_de.c optional de pci pci/if_mn.c optional mn pci pci/if_pcn.c optional pcn pci pci/if_rl.c optional rl pci pci/if_sf.c optional sf pci pci/if_sis.c optional sis pci pci/if_sk.c optional sk pci pci/if_ste.c optional ste pci pci/if_ti.c optional ti pci pci/if_tl.c optional tl pci pci/if_vr.c optional vr pci pci/if_wb.c optional wb pci pci/if_xl.c optional xl pci pci/intpm.c optional intpm pci pci/ncr.c optional ncr pci pci/viapm.c optional viapm pci pci/xrpu.c optional xrpu pci posix4/ksched.c optional _kposix_priority_scheduling posix4/p1003_1b.c standard posix4/posix4_mib.c standard rpc/rpcclnt.c optional nfsclient security/mac/mac_inet.c optional mac inet security/mac/mac_label.c optional mac security/mac/mac_net.c optional mac security/mac/mac_pipe.c optional mac security/mac/mac_posix_sem.c optional mac security/mac/mac_process.c optional mac security/mac/mac_socket.c optional mac security/mac/mac_system.c optional mac security/mac/mac_sysv_msg.c optional mac security/mac/mac_sysv_sem.c optional mac security/mac/mac_sysv_shm.c optional mac security/mac/mac_vfs.c optional mac security/mac_biba/mac_biba.c optional mac_biba security/mac_bsdextended/mac_bsdextended.c optional mac_bsdextended security/mac_ifoff/mac_ifoff.c optional mac_ifoff security/mac_lomac/mac_lomac.c optional mac_lomac security/mac_mls/mac_mls.c optional mac_mls security/mac_none/mac_none.c optional mac_none security/mac_partition/mac_partition.c optional mac_partition security/mac_portacl/mac_portacl.c optional mac_portacl security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids security/mac_stub/mac_stub.c optional mac_stub security/mac_test/mac_test.c optional mac_test ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_snapshot.c optional ffs ufs/ffs/ffs_softdep.c optional ffs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vnops.c optional ffs ufs/ffs/ffs_rawread.c optional directio ufs/ufs/ufs_acl.c optional ffs ufs/ufs/ufs_bmap.c optional ffs ufs/ufs/ufs_dirhash.c optional ffs ufs/ufs/ufs_extattr.c optional ffs ufs/ufs/ufs_inode.c optional ffs ufs/ufs/ufs_lookup.c optional ffs ufs/ufs/ufs_quota.c optional ffs ufs/ufs/ufs_vfsops.c optional ffs ufs/ufs/ufs_vnops.c optional ffs vm/default_pager.c standard vm/device_pager.c standard vm/phys_pager.c standard vm/swap_pager.c standard vm/uma_core.c standard vm/uma_dbg.c standard vm/vm_contig.c standard vm/memguard.c optional DEBUG_MEMGUARD vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageout.c standard vm/vm_pageq.c standard vm/vm_pager.c standard vm/vm_unix.c standard vm/vm_zeroidle.c standard vm/vnode_pager.c standard Index: head/sys/dev/drm/ati_pcigart.c =================================================================== --- head/sys/dev/drm/ati_pcigart.c (revision 152908) +++ head/sys/dev/drm/ati_pcigart.c (revision 152909) @@ -1,123 +1,103 @@ /* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*- * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com */ /*- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" -#if PAGE_SIZE == 8192 -# define ATI_PCIGART_TABLE_ORDER 2 -# define ATI_PCIGART_TABLE_PAGES (1 << 2) -#elif PAGE_SIZE == 4096 -# define ATI_PCIGART_TABLE_ORDER 3 -# define ATI_PCIGART_TABLE_PAGES (1 << 3) -#elif -# error - PAGE_SIZE not 8K or 4K -#endif +#define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */ +#define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */ +#define ATI_PCIGART_TABLE_SIZE 32768 -# define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */ -# define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */ - -int drm_ati_pcigart_init(drm_device_t *dev, unsigned long *addr, - dma_addr_t *bus_addr, int is_pcie) +int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) { - drm_sg_mem_t *entry = dev->sg; - unsigned long address = 0; unsigned long pages; - u32 *pci_gart=0, page_base, bus_address = 0; - int i, j, ret = 0; + u32 *pci_gart = NULL, page_base; + int i, j; - if ( !entry ) { + if (dev->sg == NULL) { DRM_ERROR( "no scatter/gather memory!\n" ); - goto done; + return 0; } - address = (long)contigmalloc((1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE, - M_DRM, M_NOWAIT, 0ul, 0xfffffffful, PAGE_SIZE, 0); - if ( !address ) { - DRM_ERROR( "cannot allocate PCI GART page!\n" ); - goto done; + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { + /* GART table in system memory */ + dev->sg->dmah = drm_pci_alloc(dev, ATI_PCIGART_TABLE_SIZE, 0, + 0xfffffffful); + if (dev->sg->dmah == NULL) { + DRM_ERROR("cannot allocate PCI GART table!\n"); + return 0; + } + + gart_info->addr = (void *)dev->sg->dmah->vaddr; + gart_info->bus_addr = dev->sg->dmah->busaddr; + pci_gart = (u32 *)dev->sg->dmah->vaddr; + } else { + /* GART table in framebuffer memory */ + pci_gart = gart_info->addr; } + + pages = DRM_MIN(dev->sg->pages, ATI_MAX_PCIGART_PAGES); - /* XXX: we need to busdma this */ - bus_address = vtophys( address ); + bzero(pci_gart, ATI_PCIGART_TABLE_SIZE); - pci_gart = (u32 *)address; + KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE, ("page size too small")); - pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) - ? entry->pages : ATI_MAX_PCIGART_PAGES; - - bzero( pci_gart, ATI_MAX_PCIGART_PAGES * sizeof(u32) ); - for ( i = 0 ; i < pages ; i++ ) { - entry->busaddr[i] = vtophys( entry->handle + (i*PAGE_SIZE) ); - page_base = (u32) entry->busaddr[i]; + page_base = (u32) dev->sg->busaddr[i]; for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { - if (is_pcie) { - *pci_gart = (cpu_to_le32(page_base)>>8) | 0xc; - DRM_DEBUG("PCIE: %d %08X %08X to %p\n", i, - page_base, (cpu_to_le32(page_base)>>8)|0xc, - pci_gart); - } else + if (gart_info->is_pcie) + *pci_gart = (cpu_to_le32(page_base) >> 8) | 0xc; + else *pci_gart = cpu_to_le32(page_base); pci_gart++; page_base += ATI_PCIGART_PAGE_SIZE; } } DRM_MEMORYBARRIER(); - ret = 1; - -done: - *addr = address; - *bus_addr = bus_address; - return ret; + return 1; } -int drm_ati_pcigart_cleanup(drm_device_t *dev, unsigned long addr, - dma_addr_t bus_addr) +int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) { - drm_sg_mem_t *entry = dev->sg; - - /* we need to support large memory configurations */ - if ( !entry ) { + if (dev->sg == NULL) { DRM_ERROR( "no scatter/gather memory!\n" ); return 0; } -#if __FreeBSD_version > 500000 - /* Not available on 4.x */ - contigfree((void *)addr, (1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE, - M_DRM); -#endif + drm_pci_free(dev, dev->sg->dmah); + return 1; } Index: head/sys/dev/drm/drm-preprocess.sh =================================================================== --- head/sys/dev/drm/drm-preprocess.sh (nonexistent) +++ head/sys/dev/drm/drm-preprocess.sh (revision 152909) @@ -0,0 +1,20 @@ +#!/bin/sh + +# $FreeBSD$ + +cp /usr/src/drm/bsd-core/*.[ch] . +rm i810*.[ch] +rm via*.[ch] + +# Replace drm_pciids.h with one with a $FreeBSD$ +rm -f drm_pciids.h +echo "/*" >> drm_pciids.h +echo " * \$FreeBSD\$" >> drm_pciids.h +echo " */" >> drm_pciids.h +cat /usr/src/drm/bsd-core/drm_pciids.h >> drm_pciids.h + +for i in `ls *.[ch]`; do + mv $i $i.orig + perl drm-subprocess.pl < $i.orig > $i +done + Property changes on: head/sys/dev/drm/drm-preprocess.sh ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/dev/drm/drm-subprocess.pl =================================================================== --- head/sys/dev/drm/drm-subprocess.pl (nonexistent) +++ head/sys/dev/drm/drm-subprocess.pl (revision 152909) @@ -0,0 +1,50 @@ +# $FreeBSD$ +# +# Props to Daniel Stone for starting this script for me. I hate perl. + +my $lastline = ""; +my $foundopening = 0; +my $foundclosing = 0; + +while (<>) { + $curline = $_; + if (!$foundopening) { + if (/Copyright/) { + $foundopening = 1; + # print the previous line we buffered, but with /*- + if ($lastline !~ /\/\*-/) { + $lastline =~ s/\/\*/\/\*-/; + } + print $lastline; + # now, print the current line. + print $curline; + } else { + # print the previous line and continue on + print $lastline; + } + } elsif ($foundopening && !$foundclosing && /\*\//) { + # print the $FreeBSD$ bits after the end of the license block + $foundclosing = 1; + print; + print "\n"; + print "#include \n"; + print "__FBSDID(\"\$FreeBSD\$\");\n"; + } elsif ($foundopening) { + # Replace headers with the system's paths. the headers we're + # concerned with are drm*.h, *_drm.h and *_drv.h + # + s/#include "(.*)_drv.h/#include "dev\/drm\/\1_drv.h/; + s/#include "(.*)_drm.h/#include "dev\/drm\/\1_drm.h/; + s/#include "mga_ucode.h/#include "dev\/drm\/mga_ucode.h/; + s/#include "r300_reg.h/#include "dev\/drm\/r300_reg.h/; + s/#include "sis_ds.h/#include "dev\/drm\/sis_ds.h/; + s/#include "drm/#include "dev\/drm\/drm/; + print; + } + $lastline = $curline; +} + +# if we never found the copyright header, then we're still a line behind. +if (!$foundopening) { + print $lastline; +} \ No newline at end of file Property changes on: head/sys/dev/drm/drm-subprocess.pl ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/dev/drm/drm.h =================================================================== --- head/sys/dev/drm/drm.h (revision 152908) +++ head/sys/dev/drm/drm.h (revision 152909) @@ -1,694 +1,711 @@ /** * \file drm.h * Header for the Direct Rendering Manager * * \author Rickard E. (Rik) Faith * * \par Acknowledgments: * Dec 1999, Richard Henderson , move to generic \c cmpxchg. */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + /** * \mainpage * * The Direct Rendering Manager (DRM) is a device-independent kernel-level * device driver that provides support for the XFree86 Direct Rendering * Infrastructure (DRI). * * The DRM supports the Direct Rendering Infrastructure (DRI) in four major * ways: * -# The DRM provides synchronized access to the graphics hardware via * the use of an optimized two-tiered lock. * -# The DRM enforces the DRI security policy for access to the graphics * hardware by only allowing authenticated X11 clients access to * restricted regions of memory. * -# The DRM provides a generic DMA engine, complete with multiple * queues and the ability to detect the need for an OpenGL context * switch. * -# The DRM is extensible via the use of small device-specific modules * that rely extensively on the API exported by the DRM module. * */ #ifndef _DRM_H_ #define _DRM_H_ #ifndef __user #define __user #endif +#ifdef __GNUC__ +# define DEPRECATED __attribute__ ((deprecated)) +#else +# define DEPRECATED +#endif + #if defined(__linux__) +#if defined(__KERNEL__) #include +#endif #include /* For _IO* macros */ #define DRM_IOCTL_NR(n) _IOC_NR(n) #define DRM_IOC_VOID _IOC_NONE #define DRM_IOC_READ _IOC_READ #define DRM_IOC_WRITE _IOC_WRITE #define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) #if defined(__FreeBSD__) && defined(IN_MODULE) /* Prevent name collision when including sys/ioccom.h */ #undef ioctl #include #define ioctl(a,b,c) xf86ioctl(a,b,c) #else #include #endif /* __FreeBSD__ && xf86ioctl */ #define DRM_IOCTL_NR(n) ((n) & 0xff) #define DRM_IOC_VOID IOC_VOID #define DRM_IOC_READ IOC_OUT #define DRM_IOC_WRITE IOC_IN #define DRM_IOC_READWRITE IOC_INOUT #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) #endif #define XFREE86_VERSION(major,minor,patch,snap) \ ((major << 16) | (minor << 8) | patch) #ifndef CONFIG_XFREE86_VERSION #define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0) #endif #if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) #define DRM_PROC_DEVICES "/proc/devices" #define DRM_PROC_MISC "/proc/misc" #define DRM_PROC_DRM "/proc/drm" #define DRM_DEV_DRM "/dev/drm" #define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) #define DRM_DEV_UID 0 #define DRM_DEV_GID 0 #endif #if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0) #ifdef __OpenBSD__ #define DRM_MAJOR 81 #endif #if defined(__linux__) || defined(__NetBSD__) #define DRM_MAJOR 226 #endif #define DRM_MAX_MINOR 255 #endif #define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ #define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ #define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ #define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ #define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ #define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ #define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) #define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) +#if defined(__linux__) +typedef unsigned int drm_handle_t; +#else typedef unsigned long drm_handle_t; /**< To mapped regions */ +#endif typedef unsigned int drm_context_t; /**< GLXContext handle */ typedef unsigned int drm_drawable_t; typedef unsigned int drm_magic_t; /**< Magic for authentication */ /** * Cliprect. * * \warning If you change this structure, make sure you change * XF86DRIClipRectRec in the server as well * * \note KW: Actually it's illegal to change either for * backwards-compatibility reasons. */ typedef struct drm_clip_rect { unsigned short x1; unsigned short y1; unsigned short x2; unsigned short y2; } drm_clip_rect_t; /** * Texture region, */ typedef struct drm_tex_region { unsigned char next; unsigned char prev; unsigned char in_use; unsigned char padding; unsigned int age; } drm_tex_region_t; /** * Hardware lock. * * The lock structure is a simple cache-line aligned integer. To avoid * processor bus contention on a multiprocessor system, there should not be any * other data stored in the same cache line. */ typedef struct drm_hw_lock { __volatile__ unsigned int lock; /**< lock variable */ char padding[60]; /**< Pad to cache line */ } drm_hw_lock_t; /* This is beyond ugly, and only works on GCC. However, it allows me to use * drm.h in places (i.e., in the X-server) where I can't use size_t. The real * fix is to use uint32_t instead of size_t, but that fix will break existing * LP64 (i.e., PowerPC64, SPARC64, IA-64, Alpha, etc.) systems. That *will* * eventually happen, though. I chose 'unsigned long' to be the fallback type * because that works on all the platforms I know about. Hopefully, the * real fix will happen before that bites us. */ #ifdef __SIZE_TYPE__ # define DRM_SIZE_T __SIZE_TYPE__ #else # warning "__SIZE_TYPE__ not defined. Assuming sizeof(size_t) == sizeof(unsigned long)!" # define DRM_SIZE_T unsigned long #endif /** * DRM_IOCTL_VERSION ioctl argument type. * * \sa drmGetVersion(). */ typedef struct drm_version { int version_major; /**< Major version */ int version_minor; /**< Minor version */ int version_patchlevel; /**< Patch level */ DRM_SIZE_T name_len; /**< Length of name buffer */ char __user *name; /**< Name of driver */ DRM_SIZE_T date_len; /**< Length of date buffer */ char __user *date; /**< User-space buffer to hold date */ DRM_SIZE_T desc_len; /**< Length of desc buffer */ char __user *desc; /**< User-space buffer to hold desc */ } drm_version_t; /** * DRM_IOCTL_GET_UNIQUE ioctl argument type. * * \sa drmGetBusid() and drmSetBusId(). */ typedef struct drm_unique { DRM_SIZE_T unique_len; /**< Length of unique */ char __user *unique; /**< Unique name for driver instantiation */ } drm_unique_t; #undef DRM_SIZE_T typedef struct drm_list { int count; /**< Length of user-space structures */ drm_version_t __user *version; } drm_list_t; typedef struct drm_block { int unused; } drm_block_t; /** * DRM_IOCTL_CONTROL ioctl argument type. * * \sa drmCtlInstHandler() and drmCtlUninstHandler(). */ typedef struct drm_control { enum { DRM_ADD_COMMAND, DRM_RM_COMMAND, DRM_INST_HANDLER, DRM_UNINST_HANDLER } func; int irq; } drm_control_t; /** * Type of memory to map. */ typedef enum drm_map_type { _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */ _DRM_REGISTERS = 1, /**< no caching, no core dump */ _DRM_SHM = 2, /**< shared, cached */ _DRM_AGP = 3, /**< AGP/GART */ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */ } drm_map_type_t; /** * Memory mapping flags. */ typedef enum drm_map_flags { _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */ _DRM_READ_ONLY = 0x02, _DRM_LOCKED = 0x04, /**< shared, cached, locked */ _DRM_KERNEL = 0x08, /**< kernel requires access */ _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ _DRM_REMOVABLE = 0x40 /**< Removable mapping */ } drm_map_flags_t; typedef struct drm_ctx_priv_map { unsigned int ctx_id; /**< Context requesting private mapping */ void *handle; /**< Handle of map */ } drm_ctx_priv_map_t; /** * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls * argument type. * * \sa drmAddMap(). */ typedef struct drm_map { unsigned long offset; /**< Requested physical address (0 for SAREA)*/ unsigned long size; /**< Requested physical size (bytes) */ drm_map_type_t type; /**< Type of memory to map */ drm_map_flags_t flags; /**< Flags */ void *handle; /**< User-space: "Handle" to pass to mmap() */ /**< Kernel-space: kernel-virtual address */ int mtrr; /**< MTRR slot used */ /* Private data */ } drm_map_t; /** * DRM_IOCTL_GET_CLIENT ioctl argument type. */ typedef struct drm_client { int idx; /**< Which client desired? */ int auth; /**< Is client authenticated? */ unsigned long pid; /**< Process ID */ unsigned long uid; /**< User ID */ unsigned long magic; /**< Magic */ unsigned long iocs; /**< Ioctl count */ } drm_client_t; typedef enum { _DRM_STAT_LOCK, _DRM_STAT_OPENS, _DRM_STAT_CLOSES, _DRM_STAT_IOCTLS, _DRM_STAT_LOCKS, _DRM_STAT_UNLOCKS, _DRM_STAT_VALUE, /**< Generic value */ _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */ _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */ _DRM_STAT_IRQ, /**< IRQ */ _DRM_STAT_PRIMARY, /**< Primary DMA bytes */ _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */ _DRM_STAT_DMA, /**< DMA */ _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */ _DRM_STAT_MISSED /**< Missed DMA opportunity */ /* Add to the *END* of the list */ } drm_stat_type_t; /** * DRM_IOCTL_GET_STATS ioctl argument type. */ typedef struct drm_stats { unsigned long count; struct { unsigned long value; drm_stat_type_t type; } data[15]; } drm_stats_t; /** * Hardware locking flags. */ typedef enum drm_lock_flags { _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ /* These *HALT* flags aren't supported yet -- they will be used to support the full-screen DGA-like mode. */ _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ } drm_lock_flags_t; /** * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type. * * \sa drmGetLock() and drmUnlock(). */ typedef struct drm_lock { int context; drm_lock_flags_t flags; } drm_lock_t; /** * DMA flags * * \warning * These values \e must match xf86drm.h. * * \sa drm_dma. */ typedef enum drm_dma_flags { /* Flags for DMA buffer dispatch */ _DRM_DMA_BLOCK = 0x01, /**< * Block until buffer dispatched. * * \note The buffer may not yet have * been processed by the hardware -- * getting a hardware lock with the * hardware quiescent will ensure * that the buffer has been * processed. */ _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ /* Flags for DMA buffer request */ _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ } drm_dma_flags_t; /** * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type. * * \sa drmAddBufs(). */ typedef struct drm_buf_desc { int count; /**< Number of buffers of this size */ int size; /**< Size in bytes */ int low_mark; /**< Low water mark */ int high_mark; /**< High water mark */ enum { _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */ } flags; unsigned long agp_start; /**< * Start address of where the AGP buffers are * in the AGP aperture */ } drm_buf_desc_t; /** * DRM_IOCTL_INFO_BUFS ioctl argument type. */ typedef struct drm_buf_info { int count; /**< Number of buffers described in list */ drm_buf_desc_t __user *list; /**< List of buffer descriptions */ } drm_buf_info_t; /** * DRM_IOCTL_FREE_BUFS ioctl argument type. */ typedef struct drm_buf_free { int count; int __user *list; } drm_buf_free_t; /** * Buffer information * * \sa drm_buf_map. */ typedef struct drm_buf_pub { int idx; /**< Index into the master buffer list */ int total; /**< Buffer size */ int used; /**< Amount of buffer in use (for DMA) */ void __user *address; /**< Address of buffer */ } drm_buf_pub_t; /** * DRM_IOCTL_MAP_BUFS ioctl argument type. */ typedef struct drm_buf_map { int count; /**< Length of the buffer list */ +#if defined(__cplusplus) + void __user *c_virtual; +#else void __user *virtual; /**< Mmap'd area in user-virtual */ +#endif drm_buf_pub_t __user *list; /**< Buffer information */ } drm_buf_map_t; /** * DRM_IOCTL_DMA ioctl argument type. * * Indices here refer to the offset into the buffer list in drm_buf_get. * * \sa drmDMA(). */ typedef struct drm_dma { int context; /**< Context handle */ int send_count; /**< Number of buffers to send */ int __user *send_indices; /**< List of handles to buffers */ int __user *send_sizes; /**< Lengths of data to send */ drm_dma_flags_t flags; /**< Flags */ int request_count; /**< Number of buffers requested */ int request_size; /**< Desired size for buffers */ int __user *request_indices; /**< Buffer information */ int __user *request_sizes; int granted_count; /**< Number of buffers granted */ } drm_dma_t; typedef enum { _DRM_CONTEXT_PRESERVED = 0x01, _DRM_CONTEXT_2DONLY = 0x02 } drm_ctx_flags_t; /** * DRM_IOCTL_ADD_CTX ioctl argument type. * * \sa drmCreateContext() and drmDestroyContext(). */ typedef struct drm_ctx { drm_context_t handle; drm_ctx_flags_t flags; } drm_ctx_t; /** * DRM_IOCTL_RES_CTX ioctl argument type. */ typedef struct drm_ctx_res { int count; drm_ctx_t __user *contexts; } drm_ctx_res_t; /** * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type. */ typedef struct drm_draw { drm_drawable_t handle; } drm_draw_t; /** * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. */ typedef struct drm_auth { drm_magic_t magic; } drm_auth_t; /** * DRM_IOCTL_IRQ_BUSID ioctl argument type. * * \sa drmGetInterruptFromBusID(). */ typedef struct drm_irq_busid { int irq; /**< IRQ number */ int busnum; /**< bus number */ int devnum; /**< device number */ int funcnum; /**< function number */ } drm_irq_busid_t; typedef enum { _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ } drm_vblank_seq_type_t; #define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL struct drm_wait_vblank_request { drm_vblank_seq_type_t type; unsigned int sequence; unsigned long signal; }; struct drm_wait_vblank_reply { drm_vblank_seq_type_t type; unsigned int sequence; long tval_sec; long tval_usec; }; /** * DRM_IOCTL_WAIT_VBLANK ioctl argument type. * * \sa drmWaitVBlank(). */ typedef union drm_wait_vblank { struct drm_wait_vblank_request request; struct drm_wait_vblank_reply reply; } drm_wait_vblank_t; /** * DRM_IOCTL_AGP_ENABLE ioctl argument type. * * \sa drmAgpEnable(). */ typedef struct drm_agp_mode { unsigned long mode; /**< AGP mode */ } drm_agp_mode_t; /** * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type. * * \sa drmAgpAlloc() and drmAgpFree(). */ typedef struct drm_agp_buffer { unsigned long size; /**< In bytes -- will round to page boundary */ unsigned long handle; /**< Used for binding / unbinding */ unsigned long type; /**< Type of memory to allocate */ unsigned long physical; /**< Physical used by i810 */ } drm_agp_buffer_t; /** * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type. * * \sa drmAgpBind() and drmAgpUnbind(). */ typedef struct drm_agp_binding { unsigned long handle; /**< From drm_agp_buffer */ unsigned long offset; /**< In bytes -- will round to page boundary */ } drm_agp_binding_t; /** * DRM_IOCTL_AGP_INFO ioctl argument type. * * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(), * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(), * drmAgpVendorId() and drmAgpDeviceId(). */ typedef struct drm_agp_info { int agp_version_major; int agp_version_minor; unsigned long mode; unsigned long aperture_base; /**< physical address */ unsigned long aperture_size; /**< bytes */ unsigned long memory_allowed; /**< bytes */ unsigned long memory_used; /** \name PCI information */ /*@{ */ unsigned short id_vendor; unsigned short id_device; /*@} */ } drm_agp_info_t; /** * DRM_IOCTL_SG_ALLOC ioctl argument type. */ typedef struct drm_scatter_gather { unsigned long size; /**< In bytes -- will round to page boundary */ unsigned long handle; /**< Used for mapping / unmapping */ } drm_scatter_gather_t; /** * DRM_IOCTL_SET_VERSION ioctl argument type. */ typedef struct drm_set_version { int drm_di_major; int drm_di_minor; int drm_dd_major; int drm_dd_minor; } drm_set_version_t; /** * \name Ioctls Definitions */ /*@{*/ #define DRM_IOCTL_BASE 'd' #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) #define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) #define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) #define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) #define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t) #define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t) #define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t) #define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t) #define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t) #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, drm_set_version_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t) #define DRM_IOCTL_BLOCK DRM_IOWR(0x12, drm_block_t) #define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, drm_block_t) #define DRM_IOCTL_CONTROL DRM_IOW( 0x14, drm_control_t) #define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, drm_map_t) #define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, drm_buf_desc_t) #define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, drm_buf_desc_t) #define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm_buf_info_t) #define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm_buf_map_t) #define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm_buf_free_t) #define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, drm_map_t) #define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, drm_ctx_priv_map_t) #define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, drm_ctx_priv_map_t) #define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, drm_ctx_t) #define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, drm_ctx_t) #define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, drm_ctx_t) #define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, drm_ctx_t) #define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t) #define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, drm_ctx_t) #define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t) #define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, drm_draw_t) #define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, drm_draw_t) #define DRM_IOCTL_DMA DRM_IOWR(0x29, drm_dma_t) #define DRM_IOCTL_LOCK DRM_IOW( 0x2a, drm_lock_t) #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t) #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t) #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) #define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) #define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t) #define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t) #define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t) #define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t) #define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t) #define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t) #define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t) #define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t) #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) /*@}*/ /** * Device specific ioctls should only be in their respective headers * The device specific ioctl range is from 0x40 to 0x79. * * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and * drmCommandReadWrite(). */ #define DRM_COMMAND_BASE 0x40 #endif Index: head/sys/dev/drm/drmP.h =================================================================== --- head/sys/dev/drm/drmP.h (revision 152908) +++ head/sys/dev/drm/drmP.h (revision 152909) @@ -1,957 +1,1027 @@ /* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef _DRM_P_H_ #define _DRM_P_H_ #if defined(_KERNEL) || defined(__KERNEL__) typedef struct drm_device drm_device_t; typedef struct drm_file drm_file_t; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__FreeBSD__) #include #include #include #include #if __FreeBSD_version >= 500000 #include #include #include #else /* __FreeBSD_version >= 500000 */ #include #include #endif /* __FreeBSD_version < 500000 */ #elif defined(__NetBSD__) #include #include #include #include #include #include #include #include #include #include #include #include #elif defined(__OpenBSD__) #include #include #endif #include #include "dev/drm/drm.h" #include "dev/drm/drm_linux_list.h" #include "dev/drm/drm_atomic.h" #ifdef __FreeBSD__ #include #ifdef DRM_DEBUG #undef DRM_DEBUG #define DRM_DEBUG_DEFAULT_ON 1 #endif /* DRM_DEBUG */ #endif #if defined(DRM_LINUX) && DRM_LINUX && !defined(__amd64__) #include #include #include #include #else /* Either it was defined when it shouldn't be (FreeBSD amd64) or it isn't * supported on this OS yet. */ #undef DRM_LINUX #define DRM_LINUX 0 #endif #define DRM_HASH_SIZE 16 /* Size of key hash table */ #define DRM_KERNEL_CONTEXT 0 /* Change drm_resctx if changed */ #define DRM_RESERVED_CONTEXTS 1 /* Change drm_resctx if changed */ #define DRM_MEM_DMA 0 #define DRM_MEM_SAREA 1 #define DRM_MEM_DRIVER 2 #define DRM_MEM_MAGIC 3 #define DRM_MEM_IOCTLS 4 #define DRM_MEM_MAPS 5 #define DRM_MEM_BUFS 6 #define DRM_MEM_SEGS 7 #define DRM_MEM_PAGES 8 #define DRM_MEM_FILES 9 #define DRM_MEM_QUEUES 10 #define DRM_MEM_CMDS 11 #define DRM_MEM_MAPPINGS 12 #define DRM_MEM_BUFLISTS 13 #define DRM_MEM_AGPLISTS 14 #define DRM_MEM_TOTALAGP 15 #define DRM_MEM_BOUNDAGP 16 #define DRM_MEM_CTXBITMAP 17 #define DRM_MEM_STUB 18 #define DRM_MEM_SGLISTS 19 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) /* Internal types and structures */ #define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define DRM_MIN(a,b) ((a)<(b)?(a):(b)) #define DRM_MAX(a,b) ((a)>(b)?(a):(b)) #define DRM_IF_VERSION(maj, min) (maj << 16 | min) MALLOC_DECLARE(M_DRM); #define __OS_HAS_AGP 1 #define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) #define DRM_DEV_UID 0 #define DRM_DEV_GID 0 #define wait_queue_head_t atomic_t #define DRM_WAKEUP(w) wakeup((void *)w) #define DRM_WAKEUP_INT(w) wakeup(w) #define DRM_INIT_WAITQUEUE(queue) do {} while (0) #if defined(__FreeBSD__) && __FreeBSD_version < 502109 #define bus_alloc_resource_any(dev, type, rid, flags) \ bus_alloc_resource(dev, type, rid, 0ul, ~0ul, 1, flags) #endif #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 #define DRM_CURPROC curthread #define DRM_STRUCTPROC struct thread #define DRM_SPINTYPE struct mtx #define DRM_SPININIT(l,name) mtx_init(&l, name, NULL, MTX_DEF) #define DRM_SPINUNINIT(l) mtx_destroy(&l) #define DRM_SPINLOCK(l) mtx_lock(l) #define DRM_SPINUNLOCK(u) mtx_unlock(u); #define DRM_SPINLOCK_ASSERT(l) mtx_assert(l, MA_OWNED) #define DRM_CURRENTPID curthread->td_proc->p_pid #define DRM_LOCK() mtx_lock(&dev->dev_lock) #define DRM_UNLOCK() mtx_unlock(&dev->dev_lock) #define DRM_SYSCTL_HANDLER_ARGS (SYSCTL_HANDLER_ARGS) #else /* __FreeBSD__ && __FreeBSD_version >= 500000 */ #define DRM_CURPROC curproc #define DRM_STRUCTPROC struct proc #define DRM_SPINTYPE struct simplelock #define DRM_SPININIT(l,name) #define DRM_SPINUNINIT(l) #define DRM_SPINLOCK(l) #define DRM_SPINUNLOCK(u) #define DRM_SPINLOCK_ASSERT(l) #define DRM_CURRENTPID curproc->p_pid #define DRM_LOCK() #define DRM_UNLOCK() #define DRM_SYSCTL_HANDLER_ARGS SYSCTL_HANDLER_ARGS #define spldrm() spltty() #endif /* __NetBSD__ || __OpenBSD__ */ /* Currently our DRMFILE (filp) is a void * which is actually the pid * of the current process. It should be a per-open unique pointer, but * code for that is not yet written */ #define DRMFILE void * #define DRM_IRQ_ARGS void *arg typedef void irqreturn_t; #define IRQ_HANDLED /* nothing */ #define IRQ_NONE /* nothing */ +enum { + DRM_IS_NOT_AGP, + DRM_MIGHT_BE_AGP, + DRM_IS_AGP +}; +#define DRM_AGP_MEM struct agp_memory_info + #if defined(__FreeBSD__) #define DRM_DEVICE \ drm_device_t *dev = kdev->si_drv1 #define DRM_IOCTL_ARGS struct cdev *kdev, u_long cmd, caddr_t data, \ int flags, DRM_STRUCTPROC *p, DRMFILE filp #define PAGE_ALIGN(addr) round_page(addr) -#define DRM_SUSER(p) suser(p) +/* DRM_SUSER returns true if the user is superuser */ +#define DRM_SUSER(p) (suser(p) == 0) #define DRM_AGP_FIND_DEVICE() agp_find_device() #define DRM_MTRR_WC MDF_WRITECOMBINE #define jiffies ticks #else /* __FreeBSD__ */ #if defined(__NetBSD__) #define DRM_DEVICE \ drm_device_t *dev = device_lookup(&drm_cd, minor(kdev)) #elif defined(__OpenBSD__) #define DRM_DEVICE \ drm_device_t *dev = (device_lookup(&drm_cd, \ minor(kdev)))->dv_cfdata->cf_driver->cd_devs[minor(kdev)] #endif /* __OpenBSD__ */ #define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, \ int flags, DRM_STRUCTPROC *p, DRMFILE filp #define CDEV_MAJOR 34 #define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) -#define DRM_SUSER(p) suser(p->p_ucred, &p->p_acflag) +/* DRM_SUSER returns true if the user is superuser */ +#define DRM_SUSER(p) (suser(p->p_ucred, &p->p_acflag) == 0) #define DRM_AGP_FIND_DEVICE() agp_find_device(0) #define DRM_MTRR_WC MTRR_TYPE_WC #define jiffies hardclock_ticks typedef drm_device_t *device_t; extern struct cfdriver drm_cd; #endif /* !__FreeBSD__ */ /* Capabilities taken from src/sys/dev/pci/pcireg.h. */ #ifndef PCIY_AGP #define PCIY_AGP 0x02 #endif #ifndef PCIY_EXPRESS #define PCIY_EXPRESS 0x10 #endif typedef unsigned long dma_addr_t; typedef u_int32_t u32; typedef u_int16_t u16; typedef u_int8_t u8; /* DRM_READMEMORYBARRIER() prevents reordering of reads. * DRM_WRITEMEMORYBARRIER() prevents reordering of writes. * DRM_MEMORYBARRIER() prevents reordering of reads and writes. */ #if defined(__i386__) #define DRM_READMEMORYBARRIER() __asm __volatile( \ "lock; addl $0,0(%%esp)" : : : "memory"); #define DRM_WRITEMEMORYBARRIER() __asm __volatile("" : : : "memory"); #define DRM_MEMORYBARRIER() __asm __volatile( \ "lock; addl $0,0(%%esp)" : : : "memory"); #elif defined(__alpha__) #define DRM_READMEMORYBARRIER() alpha_mb(); #define DRM_WRITEMEMORYBARRIER() alpha_wmb(); #define DRM_MEMORYBARRIER() alpha_mb(); #elif defined(__amd64__) #define DRM_READMEMORYBARRIER() __asm __volatile( \ "lock; addl $0,0(%%rsp)" : : : "memory"); #define DRM_WRITEMEMORYBARRIER() __asm __volatile("" : : : "memory"); #define DRM_MEMORYBARRIER() __asm __volatile( \ "lock; addl $0,0(%%rsp)" : : : "memory"); #endif #ifdef __FreeBSD__ #define DRM_READ8(map, offset) \ *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset)) #define DRM_READ16(map, offset) \ *(volatile u_int16_t *) (((unsigned long)(map)->handle) + (offset)) #define DRM_READ32(map, offset) \ *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) #define DRM_WRITE8(map, offset, val) \ *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset)) = val #define DRM_WRITE16(map, offset, val) \ *(volatile u_int16_t *) (((unsigned long)(map)->handle) + (offset)) = val #define DRM_WRITE32(map, offset, val) \ *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) = val #define DRM_VERIFYAREA_READ( uaddr, size ) \ (!useracc(__DECONST(caddr_t, uaddr), size, VM_PROT_READ)) #else /* __FreeBSD__ */ typedef vaddr_t vm_offset_t; #define DRM_READ8(map, offset) \ bus_space_read_1( (map)->bst, (map)->bsh, (offset)) #define DRM_READ16(map, offset) \ bus_space_read_2( (map)->bst, (map)->bsh, (offset)) #define DRM_READ32(map, offset) \ bus_space_read_4( (map)->bst, (map)->bsh, (offset)) #define DRM_WRITE8(map, offset, val) \ bus_space_write_1((map)->bst, (map)->bsh, (offset), (val)) #define DRM_WRITE16(map, offset, val) \ bus_space_write_2((map)->bst, (map)->bsh, (offset), (val)) #define DRM_WRITE32(map, offset, val) \ bus_space_write_4((map)->bst, (map)->bsh, (offset), (val)) #define DRM_VERIFYAREA_READ( uaddr, size ) \ (!uvm_useracc((caddr_t)uaddr, size, VM_PROT_READ)) #endif /* !__FreeBSD__ */ #define DRM_COPY_TO_USER_IOCTL(user, kern, size) \ if ( IOCPARM_LEN(cmd) != size) \ return EINVAL; \ *user = kern; #define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \ if ( IOCPARM_LEN(cmd) != size) \ return EINVAL; \ kern = *user; #define DRM_COPY_TO_USER(user, kern, size) \ copyout(kern, user, size) #define DRM_COPY_FROM_USER(kern, user, size) \ copyin(user, kern, size) #define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \ copyin(arg2, arg1, arg3) #define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \ copyout(arg2, arg1, arg3) #if __FreeBSD_version > 500000 #define DRM_GET_USER_UNCHECKED(val, uaddr) \ ((val) = fuword32(uaddr), 0) #else #define DRM_GET_USER_UNCHECKED(val, uaddr) \ ((val) = fuword(uaddr), 0) #endif #define cpu_to_le32(x) htole32(x) #define le32_to_cpu(x) le32toh(x) #define DRM_ERR(v) v #define DRM_HZ hz #define DRM_UDELAY(udelay) DELAY(udelay) #define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */ #define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \ (_map) = (_dev)->context_sareas[_ctx]; \ } while(0) #define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) \ do { \ if (_filp != (DRMFILE)(intptr_t)DRM_CURRENTPID) { \ DRM_ERROR("filp doesn't match curproc\n"); \ return EINVAL; \ } \ _priv = drm_find_file_by_proc(dev, DRM_CURPROC); \ if (_priv == NULL) { \ DRM_ERROR("can't find authenticator\n"); \ return EINVAL; \ } \ } while (0) #define LOCK_TEST_WITH_RETURN(dev, filp) \ do { \ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || \ dev->lock.filp != filp) { \ DRM_ERROR("%s called without lock held\n", \ __FUNCTION__); \ return EINVAL; \ } \ } while (0) #define DRM_GETSAREA() \ do { \ drm_local_map_t *map; \ DRM_SPINLOCK_ASSERT(&dev->dev_lock); \ TAILQ_FOREACH(map, &dev->maplist, link) { \ if (map->type == _DRM_SHM && \ map->flags & _DRM_CONTAINS_LOCK) { \ dev_priv->sarea = map; \ break; \ } \ } \ } while (0) #if defined(__FreeBSD__) && __FreeBSD_version > 500000 #define DRM_WAIT_ON( ret, queue, timeout, condition ) \ for ( ret = 0 ; !ret && !(condition) ; ) { \ DRM_UNLOCK(); \ mtx_lock(&dev->irq_lock); \ if (!(condition)) \ ret = msleep(&(queue), &dev->irq_lock, \ PZERO | PCATCH, "drmwtq", (timeout)); \ mtx_unlock(&dev->irq_lock); \ DRM_LOCK(); \ } #else #define DRM_WAIT_ON( ret, queue, timeout, condition ) \ for ( ret = 0 ; !ret && !(condition) ; ) { \ int s = spldrm(); \ if (!(condition)) \ ret = tsleep( &(queue), PZERO | PCATCH, \ "drmwtq", (timeout) ); \ splx(s); \ } #endif #define DRM_ERROR(fmt, arg...) \ printf("error: [" DRM_NAME ":pid%d:%s] *ERROR* " fmt, \ DRM_CURRENTPID, __func__ , ## arg) #define DRM_INFO(fmt, arg...) printf("info: [" DRM_NAME "] " fmt , ## arg) #define DRM_DEBUG(fmt, arg...) do { \ if (drm_debug_flag) \ printf("[" DRM_NAME ":pid%d:%s] " fmt, DRM_CURRENTPID, \ __func__ , ## arg); \ } while (0) typedef struct drm_pci_id_list { int vendor; int device; long driver_private; char *name; } drm_pci_id_list_t; +#define DRM_AUTH 0x1 +#define DRM_MASTER 0x2 +#define DRM_ROOT_ONLY 0x4 typedef struct drm_ioctl_desc { int (*func)(DRM_IOCTL_ARGS); - int auth_needed; - int root_only; + int flags; } drm_ioctl_desc_t; typedef struct drm_magic_entry { drm_magic_t magic; struct drm_file *priv; struct drm_magic_entry *next; } drm_magic_entry_t; typedef struct drm_magic_head { struct drm_magic_entry *head; struct drm_magic_entry *tail; } drm_magic_head_t; typedef struct drm_buf { int idx; /* Index into master buflist */ int total; /* Buffer size */ int order; /* log-base-2(total) */ int used; /* Amount of buffer in use (for DMA) */ unsigned long offset; /* Byte offset (used internally) */ void *address; /* Address of buffer */ unsigned long bus_address; /* Bus address of buffer */ struct drm_buf *next; /* Kernel-only: used for free list */ __volatile__ int pending; /* On hardware DMA queue */ DRMFILE filp; /* Unique identifier of holding process */ int context; /* Kernel queue for this buffer */ enum { DRM_LIST_NONE = 0, DRM_LIST_FREE = 1, DRM_LIST_WAIT = 2, DRM_LIST_PEND = 3, DRM_LIST_PRIO = 4, DRM_LIST_RECLAIM = 5 } list; /* Which list we're on */ int dev_priv_size; /* Size of buffer private stoarge */ void *dev_private; /* Per-buffer private storage */ } drm_buf_t; typedef struct drm_freelist { int initialized; /* Freelist in use */ atomic_t count; /* Number of free buffers */ drm_buf_t *next; /* End pointer */ int low_mark; /* Low water mark */ int high_mark; /* High water mark */ } drm_freelist_t; +typedef struct drm_dma_handle { + void *vaddr; + bus_addr_t busaddr; +#if defined(__FreeBSD__) + bus_dma_tag_t tag; + bus_dmamap_t map; +#elif defined(__NetBSD__) + bus_dma_segment_t seg; +#endif +} drm_dma_handle_t; + typedef struct drm_buf_entry { int buf_size; int buf_count; drm_buf_t *buflist; int seg_count; + drm_dma_handle_t **seglist; int page_order; - vm_offset_t *seglist; - dma_addr_t *seglist_bus; drm_freelist_t freelist; } drm_buf_entry_t; typedef TAILQ_HEAD(drm_file_list, drm_file) drm_file_list_t; struct drm_file { TAILQ_ENTRY(drm_file) link; int authenticated; + int master; int minor; pid_t pid; uid_t uid; int refs; drm_magic_t magic; unsigned long ioctl_count; void *driver_priv; }; typedef struct drm_lock_data { drm_hw_lock_t *hw_lock; /* Hardware lock */ DRMFILE filp; /* Unique identifier of holding process (NULL is kernel)*/ int lock_queue; /* Queue of blocked processes */ unsigned long lock_time; /* Time of last lock in jiffies */ } drm_lock_data_t; /* This structure, in the drm_device_t, is always initialized while the device * is open. dev->dma_lock protects the incrementing of dev->buf_use, which * when set marks that no further bufs may be allocated until device teardown * occurs (when the last open of the device has closed). The high/low * watermarks of bufs are only touched by the X Server, and thus not * concurrently accessed, so no locking is needed. */ typedef struct drm_device_dma { drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; int buf_count; drm_buf_t **buflist; /* Vector of pointers info bufs */ int seg_count; int page_count; unsigned long *pagelist; unsigned long byte_count; enum { _DRM_DMA_USE_AGP = 0x01, _DRM_DMA_USE_SG = 0x02 } flags; } drm_device_dma_t; typedef struct drm_agp_mem { void *handle; unsigned long bound; /* address */ int pages; struct drm_agp_mem *prev; struct drm_agp_mem *next; } drm_agp_mem_t; typedef struct drm_agp_head { device_t agpdev; struct agp_info info; const char *chipset; drm_agp_mem_t *memory; unsigned long mode; int enabled; int acquired; unsigned long base; int mtrr; int cant_use_aperture; unsigned long page_mask; } drm_agp_head_t; typedef struct drm_sg_mem { unsigned long handle; void *virtual; int pages; dma_addr_t *busaddr; + drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */ } drm_sg_mem_t; typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t; typedef struct drm_local_map { unsigned long offset; /* Physical address (0 for SAREA)*/ unsigned long size; /* Physical size (bytes) */ drm_map_type_t type; /* Type of memory mapped */ drm_map_flags_t flags; /* Flags */ void *handle; /* User-space: "Handle" to pass to mmap */ /* Kernel-space: kernel-virtual address */ int mtrr; /* Boolean: MTRR used */ /* Private data */ int rid; /* PCI resource ID for bus_space */ - int kernel_owned; /* Boolean: 1 = initmapped, 0 = addmapped */ struct resource *bsr; bus_space_tag_t bst; bus_space_handle_t bsh; + drm_dma_handle_t *dmah; TAILQ_ENTRY(drm_local_map) link; } drm_local_map_t; TAILQ_HEAD(drm_vbl_sig_list, drm_vbl_sig); typedef struct drm_vbl_sig { TAILQ_ENTRY(drm_vbl_sig) link; unsigned int sequence; int signo; int pid; } drm_vbl_sig_t; -/** - * DRM device functions structure - */ -struct drm_device { -#if defined(__NetBSD__) || defined(__OpenBSD__) - struct device device; /* softc is an extension of struct device */ -#endif +/* location of GART table */ +#define DRM_ATI_GART_MAIN 1 +#define DRM_ATI_GART_FB 2 - /* Beginning of driver-config section */ - int (*preinit)(struct drm_device *, unsigned long flags); - int (*postinit)(struct drm_device *, unsigned long flags); - void (*prerelease)(struct drm_device *, void *filp); - void (*pretakedown)(struct drm_device *); - int (*postcleanup)(struct drm_device *); - int (*presetup)(struct drm_device *); - int (*postsetup)(struct drm_device *); - int (*open_helper)(struct drm_device *, drm_file_t *); - void (*free_filp_priv)(struct drm_device *, drm_file_t *); - void (*release)(struct drm_device *, void *filp); +typedef struct ati_pcigart_info { + int gart_table_location; + int is_pcie; + void *addr; + dma_addr_t bus_addr; + drm_local_map_t mapping; +} drm_ati_pcigart_info; + +struct drm_driver_info { + int (*load)(struct drm_device *, unsigned long flags); + int (*firstopen)(struct drm_device *); + int (*open)(struct drm_device *, drm_file_t *); + void (*preclose)(struct drm_device *, void *filp); + void (*postclose)(struct drm_device *, drm_file_t *); + void (*lastclose)(struct drm_device *); + int (*unload)(struct drm_device *); + void (*reclaim_buffers_locked)(struct drm_device *, void *filp); int (*dma_ioctl)(DRM_IOCTL_ARGS); void (*dma_ready)(struct drm_device *); int (*dma_quiescent)(struct drm_device *); int (*dma_flush_block_and_flush)(struct drm_device *, int context, drm_lock_flags_t flags); int (*dma_flush_unblock)(struct drm_device *, int context, drm_lock_flags_t flags); int (*context_ctor)(struct drm_device *dev, int context); int (*context_dtor)(struct drm_device *dev, int context); int (*kernel_context_switch)(struct drm_device *dev, int old, int new); int (*kernel_context_switch_unlock)(struct drm_device *dev); void (*irq_preinstall)(drm_device_t *dev); void (*irq_postinstall)(drm_device_t *dev); void (*irq_uninstall)(drm_device_t *dev); void (*irq_handler)(DRM_IRQ_ARGS); int (*vblank_wait)(drm_device_t *dev, unsigned int *sequence); - drm_ioctl_desc_t *driver_ioctls; - int max_driver_ioctl; + drm_pci_id_list_t *id_entry; /* PCI ID, name, and chipset private */ - int dev_priv_size; + /** + * Called by \c drm_device_is_agp. Typically used to determine if a + * card is really attached to AGP or not. + * + * \param dev DRM device handle + * + * \returns + * One of three values is returned depending on whether or not the + * card is absolutely \b not AGP (return of 0), absolutely \b is AGP + * (return of 1), or may or may not be AGP (return of 2). + */ + int (*device_is_agp) (struct drm_device * dev); - int driver_major; - int driver_minor; - int driver_patchlevel; - const char *driver_name; /* Simple driver name */ - const char *driver_desc; /* Longer driver name */ - const char *driver_date; /* Date of last major changes. */ + drm_ioctl_desc_t *ioctls; + int max_ioctl; + int buf_priv_size; + + int major; + int minor; + int patchlevel; + const char *name; /* Simple driver name */ + const char *desc; /* Longer driver name */ + const char *date; /* Date of last major changes. */ + unsigned use_agp :1; unsigned require_agp :1; unsigned use_sg :1; unsigned use_dma :1; unsigned use_pci_dma :1; unsigned use_dma_queue :1; unsigned use_irq :1; unsigned use_vbl_irq :1; unsigned use_mtrr :1; - /* End of driver-config section */ +}; +/* Length for the array of resource pointers for drm_get_resource_*. */ +#define DRM_MAX_PCI_RESOURCE 3 + +/** + * DRM device functions structure + */ +struct drm_device { +#if defined(__NetBSD__) || defined(__OpenBSD__) + struct device device; /* softc is an extension of struct device */ +#endif + + struct drm_driver_info driver; + drm_pci_id_list_t *id_entry; /* PCI ID, name, and chipset private */ + char *unique; /* Unique identifier: e.g., busid */ int unique_len; /* Length of unique field */ #ifdef __FreeBSD__ device_t device; /* Device instance from newbus */ #endif struct cdev *devnode; /* Device number for mknod */ int if_version; /* Highest interface version set */ int flags; /* Flags to open(2) */ /* Locks */ #if defined(__FreeBSD__) && __FreeBSD_version > 500000 struct mtx dma_lock; /* protects dev->dma */ struct mtx irq_lock; /* protects irq condition checks */ struct mtx dev_lock; /* protects everything else */ #endif /* Usage Counters */ int open_count; /* Outstanding files open */ int buf_use; /* Buffers in use -- cannot alloc */ /* Performance counters */ unsigned long counters; drm_stat_type_t types[15]; atomic_t counts[15]; /* Authentication */ drm_file_list_t files; drm_magic_head_t magiclist[DRM_HASH_SIZE]; /* Linked list of mappable regions. Protected by dev_lock */ drm_map_list_t maplist; drm_local_map_t **context_sareas; int max_context; drm_lock_data_t lock; /* Information on hardware lock */ /* DMA queues (contexts) */ drm_device_dma_t *dma; /* Optional pointer for DMA support */ /* Context support */ int irq; /* Interrupt used by board */ int irq_enabled; /* True if the irq handler is enabled */ #ifdef __FreeBSD__ int irqrid; /* Interrupt used by board */ struct resource *irqr; /* Resource for interrupt used by board */ #elif defined(__NetBSD__) || defined(__OpenBSD__) struct pci_attach_args pa; - pci_intr_handle_t ih; #endif void *irqh; /* Handle from bus_setup_intr */ + /* Storage of resource pointers for drm_get_resource_* */ + struct resource *pcir[DRM_MAX_PCI_RESOURCE]; + int pcirid[DRM_MAX_PCI_RESOURCE]; + int pci_domain; int pci_bus; int pci_slot; int pci_func; atomic_t context_flag; /* Context swapping flag */ int last_context; /* Last current context */ int vbl_queue; /* vbl wait channel */ atomic_t vbl_received; #ifdef __FreeBSD__ struct sigio *buf_sigio; /* Processes waiting for SIGIO */ #elif defined(__NetBSD__) pid_t buf_pgid; #endif /* Sysctl support */ struct drm_sysctl_info *sysctl; drm_agp_head_t *agp; drm_sg_mem_t *sg; /* Scatter gather memory */ atomic_t *ctx_bitmap; void *dev_private; + unsigned int agp_buffer_token; drm_local_map_t *agp_buffer_map; }; extern int drm_debug_flag; /* Device setup support (drm_drv.c) */ #ifdef __FreeBSD__ int drm_probe(device_t nbdev, drm_pci_id_list_t *idlist); int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist); int drm_detach(device_t nbdev); d_ioctl_t drm_ioctl; d_open_t drm_open; d_close_t drm_close; d_read_t drm_read; d_poll_t drm_poll; d_mmap_t drm_mmap; #elif defined(__NetBSD__) || defined(__OpenBSD__) int drm_probe(struct pci_attach_args *pa, drm_pci_id_list_t *idlist); int drm_attach(struct pci_attach_args *pa, dev_t kdev, drm_pci_id_list_t *idlist); dev_type_ioctl(drm_ioctl); dev_type_open(drm_open); dev_type_close(drm_close); dev_type_read(drm_read); dev_type_poll(drm_poll); dev_type_mmap(drm_mmap); #endif /* File operations helpers (drm_fops.c) */ #ifdef __FreeBSD__ extern int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p, drm_device_t *dev); extern drm_file_t *drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p); #elif defined(__NetBSD__) || defined(__OpenBSD__) extern int drm_open_helper(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p, drm_device_t *dev); extern drm_file_t *drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p); #endif /* __NetBSD__ || __OpenBSD__ */ /* Memory management support (drm_memory.c) */ void drm_mem_init(void); void drm_mem_uninit(void); void *drm_alloc(size_t size, int area); void *drm_calloc(size_t nmemb, size_t size, int area); void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); void drm_free(void *pt, size_t size, int area); void *drm_ioremap(drm_device_t *dev, drm_local_map_t *map); void drm_ioremapfree(drm_local_map_t *map); int drm_mtrr_add(unsigned long offset, size_t size, int flags); -int drm_mtrr_del(unsigned long offset, size_t size, int flags); +int drm_mtrr_del(int handle, unsigned long offset, size_t size, int flags); int drm_context_switch(drm_device_t *dev, int old, int new); int drm_context_switch_complete(drm_device_t *dev, int new); int drm_ctxbitmap_init(drm_device_t *dev); void drm_ctxbitmap_cleanup(drm_device_t *dev); void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle); int drm_ctxbitmap_next(drm_device_t *dev); /* Locking IOCTL support (drm_lock.c) */ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context); int drm_lock_transfer(drm_device_t *dev, __volatile__ unsigned int *lock, unsigned int context); int drm_lock_free(drm_device_t *dev, __volatile__ unsigned int *lock, unsigned int context); /* Buffer management support (drm_bufs.c) */ unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource); unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource); -int drm_initmap(drm_device_t *dev, unsigned long start, unsigned long len, - unsigned int resource, int type, int flags); -void drm_remove_map(drm_device_t *dev, drm_local_map_t *map); +void drm_rmmap(drm_device_t *dev, drm_local_map_t *map); int drm_order(unsigned long size); +int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, + drm_map_type_t type, drm_map_flags_t flags, + drm_local_map_t **map_ptr); +int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request); +int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request); +int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request); /* DMA support (drm_dma.c) */ int drm_dma_setup(drm_device_t *dev); void drm_dma_takedown(drm_device_t *dev); void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf); void drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp); +#define drm_core_reclaim_buffers drm_reclaim_buffers /* IRQ support (drm_irq.c) */ int drm_irq_install(drm_device_t *dev); int drm_irq_uninstall(drm_device_t *dev); irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); void drm_driver_irq_preinstall(drm_device_t *dev); void drm_driver_irq_postinstall(drm_device_t *dev); void drm_driver_irq_uninstall(drm_device_t *dev); int drm_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq); void drm_vbl_send_signals(drm_device_t *dev); /* AGP/PCI Express/GART support (drm_agpsupport.c) */ int drm_device_is_agp(drm_device_t *dev); int drm_device_is_pcie(drm_device_t *dev); drm_agp_head_t *drm_agp_init(void); -void drm_agp_uninit(void); -void drm_agp_do_release(void); +int drm_agp_acquire(drm_device_t *dev); +int drm_agp_release(drm_device_t *dev); +int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info); +int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode); void *drm_agp_allocate_memory(size_t pages, u32 type); int drm_agp_free_memory(void *handle); int drm_agp_bind_memory(void *handle, off_t start); int drm_agp_unbind_memory(void *handle); +int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request); +int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request); +int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request); +int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request); /* Scatter Gather Support (drm_scatter.c) */ void drm_sg_cleanup(drm_sg_mem_t *entry); #ifdef __FreeBSD__ /* sysctl support (drm_sysctl.h) */ extern int drm_sysctl_init(drm_device_t *dev); extern int drm_sysctl_cleanup(drm_device_t *dev); #endif /* __FreeBSD__ */ /* ATI PCIGART support (ati_pcigart.c) */ -int drm_ati_pcigart_init(drm_device_t *dev, unsigned long *addr, - dma_addr_t *bus_addr, int is_pcie); -int drm_ati_pcigart_cleanup(drm_device_t *dev, unsigned long addr, - dma_addr_t bus_addr); +int drm_ati_pcigart_init(drm_device_t *dev, + drm_ati_pcigart_info *gart_info); +int drm_ati_pcigart_cleanup(drm_device_t *dev, + drm_ati_pcigart_info *gart_info); /* Locking IOCTL support (drm_drv.c) */ int drm_lock(DRM_IOCTL_ARGS); int drm_unlock(DRM_IOCTL_ARGS); int drm_version(DRM_IOCTL_ARGS); int drm_setversion(DRM_IOCTL_ARGS); /* Misc. IOCTL support (drm_ioctl.c) */ int drm_irq_by_busid(DRM_IOCTL_ARGS); int drm_getunique(DRM_IOCTL_ARGS); int drm_setunique(DRM_IOCTL_ARGS); int drm_getmap(DRM_IOCTL_ARGS); int drm_getclient(DRM_IOCTL_ARGS); int drm_getstats(DRM_IOCTL_ARGS); int drm_noop(DRM_IOCTL_ARGS); /* Context IOCTL support (drm_context.c) */ int drm_resctx(DRM_IOCTL_ARGS); int drm_addctx(DRM_IOCTL_ARGS); int drm_modctx(DRM_IOCTL_ARGS); int drm_getctx(DRM_IOCTL_ARGS); int drm_switchctx(DRM_IOCTL_ARGS); int drm_newctx(DRM_IOCTL_ARGS); int drm_rmctx(DRM_IOCTL_ARGS); int drm_setsareactx(DRM_IOCTL_ARGS); int drm_getsareactx(DRM_IOCTL_ARGS); /* Drawable IOCTL support (drm_drawable.c) */ int drm_adddraw(DRM_IOCTL_ARGS); int drm_rmdraw(DRM_IOCTL_ARGS); /* Authentication IOCTL support (drm_auth.c) */ int drm_getmagic(DRM_IOCTL_ARGS); int drm_authmagic(DRM_IOCTL_ARGS); /* Buffer management support (drm_bufs.c) */ -int drm_addmap(DRM_IOCTL_ARGS); -int drm_rmmap(DRM_IOCTL_ARGS); -int drm_addbufs(DRM_IOCTL_ARGS); +int drm_addmap_ioctl(DRM_IOCTL_ARGS); +int drm_rmmap_ioctl(DRM_IOCTL_ARGS); +int drm_addbufs_ioctl(DRM_IOCTL_ARGS); int drm_infobufs(DRM_IOCTL_ARGS); int drm_markbufs(DRM_IOCTL_ARGS); int drm_freebufs(DRM_IOCTL_ARGS); int drm_mapbufs(DRM_IOCTL_ARGS); /* DMA support (drm_dma.c) */ int drm_dma(DRM_IOCTL_ARGS); /* IRQ support (drm_irq.c) */ int drm_control(DRM_IOCTL_ARGS); int drm_wait_vblank(DRM_IOCTL_ARGS); /* AGP/GART support (drm_agpsupport.c) */ -int drm_agp_acquire(DRM_IOCTL_ARGS); -int drm_agp_release(DRM_IOCTL_ARGS); -int drm_agp_enable(DRM_IOCTL_ARGS); -int drm_agp_info(DRM_IOCTL_ARGS); -int drm_agp_alloc(DRM_IOCTL_ARGS); -int drm_agp_free(DRM_IOCTL_ARGS); -int drm_agp_unbind(DRM_IOCTL_ARGS); -int drm_agp_bind(DRM_IOCTL_ARGS); +int drm_agp_acquire_ioctl(DRM_IOCTL_ARGS); +int drm_agp_release_ioctl(DRM_IOCTL_ARGS); +int drm_agp_enable_ioctl(DRM_IOCTL_ARGS); +int drm_agp_info_ioctl(DRM_IOCTL_ARGS); +int drm_agp_alloc_ioctl(DRM_IOCTL_ARGS); +int drm_agp_free_ioctl(DRM_IOCTL_ARGS); +int drm_agp_unbind_ioctl(DRM_IOCTL_ARGS); +int drm_agp_bind_ioctl(DRM_IOCTL_ARGS); /* Scatter Gather Support (drm_scatter.c) */ int drm_sg_alloc(DRM_IOCTL_ARGS); int drm_sg_free(DRM_IOCTL_ARGS); /* consistent PCI memory functions (drm_pci.c) */ -void *drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, - dma_addr_t maxaddr, dma_addr_t *busaddr); -void drm_pci_free(drm_device_t *dev, size_t size, void *vaddr, - dma_addr_t busaddr); +drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, + dma_addr_t maxaddr); +void drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah); /* Inline replacements for DRM_IOREMAP macros */ static __inline__ void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev) { map->handle = drm_ioremap(dev, map); } static __inline__ void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev) { if ( map->handle && map->size ) drm_ioremapfree(map); } static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev, unsigned long offset) { drm_local_map_t *map; DRM_SPINLOCK_ASSERT(&dev->dev_lock); TAILQ_FOREACH(map, &dev->maplist, link) { if (map->offset == offset) return map; } return NULL; } static __inline__ void drm_core_dropmap(struct drm_map *map) { } #endif /* __KERNEL__ */ #endif /* _DRM_P_H_ */ Index: head/sys/dev/drm/drm_agpsupport.c =================================================================== --- head/sys/dev/drm/drm_agpsupport.c (revision 152908) +++ head/sys/dev/drm/drm_agpsupport.c (revision 152909) @@ -1,370 +1,473 @@ /* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*- * Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Author: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #ifdef __FreeBSD__ #include #include #endif +/* Returns 1 if AGP or 0 if not. */ static int drm_device_find_capability(drm_device_t *dev, int cap) { + int ret; + + if (dev->driver.device_is_agp != NULL) { + ret = (*dev->driver.device_is_agp)(dev); + + if (ret != DRM_MIGHT_BE_AGP) { + return ret == 2; + } + } + #ifdef __FreeBSD__ /* Code taken from agp.c. IWBNI that was a public interface. */ u_int32_t status; u_int8_t ptr, next; /* * Check the CAP_LIST bit of the PCI status register first. */ status = pci_read_config(dev->device, PCIR_STATUS, 2); if (!(status & 0x10)) return 0; /* * Traverse the capabilities list. */ for (ptr = pci_read_config(dev->device, AGP_CAPPTR, 1); ptr != 0; ptr = next) { u_int32_t capid = pci_read_config(dev->device, ptr, 4); next = AGP_CAPID_GET_NEXT_PTR(capid); /* * If this capability entry ID is cap, then we are done. */ if (AGP_CAPID_GET_CAP_ID(capid) == cap) return 1; } return 0; #else /* XXX: fill me in for non-FreeBSD */ return 1; #endif } -int -drm_device_is_agp(drm_device_t *dev) +int drm_device_is_agp(drm_device_t *dev) { + if (dev->driver.device_is_agp != NULL) { + int ret; + + /* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely + * AGP, 2 = fall back to PCI capability + */ + ret = (*dev->driver.device_is_agp)(dev); + if (ret != 2) + return ret; + } + return (drm_device_find_capability(dev, PCIY_AGP)); } -int -drm_device_is_pcie(drm_device_t *dev) +int drm_device_is_pcie(drm_device_t *dev) { return (drm_device_find_capability(dev, PCIY_EXPRESS)); } -int drm_agp_info(DRM_IOCTL_ARGS) +int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info) { - DRM_DEVICE; struct agp_info *kern; - drm_agp_info_t info; if (!dev->agp || !dev->agp->acquired) return EINVAL; kern = &dev->agp->info; agp_get_info(dev->agp->agpdev, kern); - info.agp_version_major = 1; - info.agp_version_minor = 0; - info.mode = kern->ai_mode; - info.aperture_base = kern->ai_aperture_base; - info.aperture_size = kern->ai_aperture_size; - info.memory_allowed = kern->ai_memory_allowed; - info.memory_used = kern->ai_memory_used; - info.id_vendor = kern->ai_devid & 0xffff; - info.id_device = kern->ai_devid >> 16; + info->agp_version_major = 1; + info->agp_version_minor = 0; + info->mode = kern->ai_mode; + info->aperture_base = kern->ai_aperture_base; + info->aperture_size = kern->ai_aperture_size; + info->memory_allowed = kern->ai_memory_allowed; + info->memory_used = kern->ai_memory_used; + info->id_vendor = kern->ai_devid & 0xffff; + info->id_device = kern->ai_devid >> 16; + return 0; +} + +int drm_agp_info_ioctl(DRM_IOCTL_ARGS) +{ + int err; + drm_agp_info_t info; + DRM_DEVICE; + + err = drm_agp_info(dev, &info); + if (err != 0) + return err; + *(drm_agp_info_t *) data = info; return 0; } -int drm_agp_acquire(DRM_IOCTL_ARGS) +int drm_agp_acquire_ioctl(DRM_IOCTL_ARGS) { DRM_DEVICE; - int retcode; + return drm_agp_acquire(dev); +} + +int drm_agp_acquire(drm_device_t *dev) +{ + int retcode; + if (!dev->agp || dev->agp->acquired) return EINVAL; + retcode = agp_acquire(dev->agp->agpdev); if (retcode) return retcode; + dev->agp->acquired = 1; return 0; } -int drm_agp_release(DRM_IOCTL_ARGS) +int drm_agp_release_ioctl(DRM_IOCTL_ARGS) { DRM_DEVICE; + return drm_agp_release(dev); +} + +int drm_agp_release(drm_device_t * dev) +{ if (!dev->agp || !dev->agp->acquired) return EINVAL; agp_release(dev->agp->agpdev); dev->agp->acquired = 0; return 0; - } -void drm_agp_do_release(void) +int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode) { - device_t agpdev; - agpdev = DRM_AGP_FIND_DEVICE(); - if (agpdev) - agp_release(agpdev); -} - -int drm_agp_enable(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - drm_agp_mode_t mode; - if (!dev->agp || !dev->agp->acquired) return EINVAL; - - mode = *(drm_agp_mode_t *) data; dev->agp->mode = mode.mode; agp_enable(dev->agp->agpdev, mode.mode); dev->agp->base = dev->agp->info.ai_aperture_base; dev->agp->enabled = 1; return 0; } -int drm_agp_alloc(DRM_IOCTL_ARGS) +int drm_agp_enable_ioctl(DRM_IOCTL_ARGS) { + drm_agp_mode_t mode; DRM_DEVICE; - drm_agp_buffer_t request; + + mode = *(drm_agp_mode_t *) data; + + return drm_agp_enable(dev, mode); +} + +int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request) +{ drm_agp_mem_t *entry; void *handle; unsigned long pages; u_int32_t type; struct agp_memory_info info; if (!dev->agp || !dev->agp->acquired) return EINVAL; - request = *(drm_agp_buffer_t *) data; - entry = malloc(sizeof(*entry), M_DRM, M_NOWAIT | M_ZERO); if (entry == NULL) return ENOMEM; - pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; - type = (u_int32_t) request.type; + pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; + type = (u_int32_t) request->type; - if (!(handle = drm_agp_allocate_memory(pages, type))) { + DRM_UNLOCK(); + handle = drm_agp_allocate_memory(pages, type); + DRM_LOCK(); + if (handle == NULL) { free(entry, M_DRM); return ENOMEM; } entry->handle = handle; entry->bound = 0; entry->pages = pages; entry->prev = NULL; entry->next = dev->agp->memory; if (dev->agp->memory) dev->agp->memory->prev = entry; dev->agp->memory = entry; agp_memory_info(dev->agp->agpdev, entry->handle, &info); - request.handle = (unsigned long) entry->handle; - request.physical = info.ami_physical; + request->handle = (unsigned long) entry->handle; + request->physical = info.ami_physical; + return 0; +} + +int drm_agp_alloc_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_agp_buffer_t request; + int retcode; + + request = *(drm_agp_buffer_t *) data; + + DRM_LOCK(); + retcode = drm_agp_alloc(dev, &request); + DRM_UNLOCK(); + *(drm_agp_buffer_t *) data = request; - return 0; + return retcode; } static drm_agp_mem_t * drm_agp_lookup_entry(drm_device_t *dev, void *handle) { drm_agp_mem_t *entry; for (entry = dev->agp->memory; entry; entry = entry->next) { if (entry->handle == handle) return entry; } return NULL; } -int drm_agp_unbind(DRM_IOCTL_ARGS) +int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request) { - DRM_DEVICE; - drm_agp_binding_t request; drm_agp_mem_t *entry; int retcode; if (!dev->agp || !dev->agp->acquired) return EINVAL; - request = *(drm_agp_binding_t *) data; - if (!(entry = drm_agp_lookup_entry(dev, (void *)request.handle))) + + entry = drm_agp_lookup_entry(dev, (void *)request->handle); + if (entry == NULL || !entry->bound) return EINVAL; - if (!entry->bound) return EINVAL; + + DRM_UNLOCK(); retcode = drm_agp_unbind_memory(entry->handle); - if (!retcode) - { - entry->bound=0; - return 0; - } - else - return retcode; + DRM_LOCK(); + + if (retcode == 0) + entry->bound = 0; + + return retcode; } -int drm_agp_bind(DRM_IOCTL_ARGS) +int drm_agp_unbind_ioctl(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_agp_binding_t request; + int retcode; + + request = *(drm_agp_binding_t *) data; + + DRM_LOCK(); + retcode = drm_agp_unbind(dev, &request); + DRM_UNLOCK(); + + return retcode; +} + +int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request) +{ drm_agp_mem_t *entry; int retcode; int page; - DRM_DEBUG("agp_bind, page_size=%x\n", PAGE_SIZE); if (!dev->agp || !dev->agp->acquired) return EINVAL; - request = *(drm_agp_binding_t *) data; - if (!(entry = drm_agp_lookup_entry(dev, (void *)request.handle))) + + DRM_DEBUG("agp_bind, page_size=%x\n", PAGE_SIZE); + + entry = drm_agp_lookup_entry(dev, (void *)request->handle); + if (entry == NULL || entry->bound) return EINVAL; - if (entry->bound) return EINVAL; - page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; - if ((retcode = drm_agp_bind_memory(entry->handle, page))) - return retcode; - entry->bound = dev->agp->base + (page << PAGE_SHIFT); - return 0; + + page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE; + + DRM_UNLOCK(); + retcode = drm_agp_bind_memory(entry->handle, page); + DRM_LOCK(); + if (retcode == 0) + entry->bound = dev->agp->base + (page << PAGE_SHIFT); + + return retcode; } -int drm_agp_free(DRM_IOCTL_ARGS) +int drm_agp_bind_ioctl(DRM_IOCTL_ARGS) { DRM_DEVICE; - drm_agp_buffer_t request; + drm_agp_binding_t request; + int retcode; + + request = *(drm_agp_binding_t *) data; + + DRM_LOCK(); + retcode = drm_agp_bind(dev, &request); + DRM_UNLOCK(); + + return retcode; +} + +int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request) +{ drm_agp_mem_t *entry; if (!dev->agp || !dev->agp->acquired) return EINVAL; - request = *(drm_agp_buffer_t *) data; - if (!(entry = drm_agp_lookup_entry(dev, (void*)request.handle))) + + entry = drm_agp_lookup_entry(dev, (void*)request->handle); + if (entry == NULL) return EINVAL; - if (entry->bound) - drm_agp_unbind_memory(entry->handle); if (entry->prev) entry->prev->next = entry->next; else dev->agp->memory = entry->next; if (entry->next) entry->next->prev = entry->prev; + + DRM_UNLOCK(); + if (entry->bound) + drm_agp_unbind_memory(entry->handle); drm_agp_free_memory(entry->handle); + DRM_LOCK(); + free(entry, M_DRM); + return 0; + } +int drm_agp_free_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_agp_buffer_t request; + int retcode; + + request = *(drm_agp_buffer_t *) data; + + DRM_LOCK(); + retcode = drm_agp_free(dev, &request); + DRM_UNLOCK(); + + return retcode; +} + drm_agp_head_t *drm_agp_init(void) { device_t agpdev; drm_agp_head_t *head = NULL; int agp_available = 1; agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev) agp_available = 0; DRM_DEBUG("agp_available = %d\n", agp_available); if (agp_available) { head = malloc(sizeof(*head), M_DRM, M_NOWAIT | M_ZERO); if (head == NULL) return NULL; head->agpdev = agpdev; agp_get_info(agpdev, &head->info); head->memory = NULL; DRM_INFO("AGP at 0x%08lx %dMB\n", (long)head->info.ai_aperture_base, (int)(head->info.ai_aperture_size >> 20)); } return head; } - -void drm_agp_uninit(void) -{ -/* FIXME: What goes here */ -} - void *drm_agp_allocate_memory(size_t pages, u32 type) { device_t agpdev; agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev) return NULL; return agp_alloc_memory(agpdev, type, pages << AGP_PAGE_SHIFT); } int drm_agp_free_memory(void *handle) { device_t agpdev; agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev || !handle) return 0; agp_free_memory(agpdev, handle); return 1; } int drm_agp_bind_memory(void *handle, off_t start) { device_t agpdev; agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev || !handle) return EINVAL; return agp_bind_memory(agpdev, handle, start * PAGE_SIZE); } int drm_agp_unbind_memory(void *handle) { device_t agpdev; agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev || !handle) return EINVAL; return agp_unbind_memory(agpdev, handle); } Index: head/sys/dev/drm/drm_atomic.h =================================================================== --- head/sys/dev/drm/drm_atomic.h (revision 152908) +++ head/sys/dev/drm/drm_atomic.h (revision 152909) @@ -1,143 +1,144 @@ /** * \file drm_atomic.h * Atomic operations used in the DRM which may or may not be provided by the OS. * * \author Eric Anholt */ /*- * Copyright 2004 Eric Anholt * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); /* Many of these implementations are rather fake, but good enough. */ typedef u_int32_t atomic_t; #ifdef __FreeBSD__ #define atomic_set(p, v) (*(p) = (v)) #define atomic_read(p) (*(p)) #define atomic_inc(p) atomic_add_int(p, 1) #define atomic_dec(p) atomic_subtract_int(p, 1) #define atomic_add(n, p) atomic_add_int(p, n) #define atomic_sub(n, p) atomic_subtract_int(p, n) #else /* __FreeBSD__ */ /* FIXME */ #define atomic_set(p, v) (*(p) = (v)) #define atomic_read(p) (*(p)) #define atomic_inc(p) (*(p) += 1) #define atomic_dec(p) (*(p) -= 1) #define atomic_add(n, p) (*(p) += (n)) #define atomic_sub(n, p) (*(p) -= (n)) /* FIXME */ #define atomic_add_int(p, v) *(p) += v #define atomic_subtract_int(p, v) *(p) -= v #define atomic_set_int(p, bits) *(p) |= (bits) #define atomic_clear_int(p, bits) *(p) &= ~(bits) #endif /* !__FreeBSD__ */ #if !defined(__FreeBSD_version) || (__FreeBSD_version < 500000) #if defined(__i386__) /* The extra atomic functions from 5.0 haven't been merged to 4.x */ static __inline int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) { int res = exp; __asm __volatile ( " lock ; " " cmpxchgl %1,%2 ; " " setz %%al ; " " movzbl %%al,%0 ; " "1: " "# atomic_cmpset_int" : "+a" (res) /* 0 (result) */ : "r" (src), /* 1 */ "m" (*(dst)) /* 2 */ : "memory"); return (res); } #else /* __i386__ */ static __inline int atomic_cmpset_int(__volatile__ int *dst, int old, int new) { int s = splhigh(); if (*dst==old) { *dst = new; splx(s); return 1; } splx(s); return 0; } #endif /* !__i386__ */ #endif /* !__FreeBSD_version || __FreeBSD_version < 500000 */ static __inline atomic_t test_and_set_bit(int b, volatile void *p) { int s = splhigh(); unsigned int m = 1<> 5), 1 << (b & 0x1f)); } static __inline void set_bit(int b, volatile void *p) { atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); } static __inline int test_bit(int b, volatile void *p) { return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f)); } static __inline int find_first_zero_bit(volatile void *p, int max) { int b; volatile int *ptr = (volatile int *)p; for (b = 0; b < max; b += 32) { if (ptr[b >> 5] != ~0) { for (;;) { if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0) return b; b++; } } } return max; } Index: head/sys/dev/drm/drm_auth.c =================================================================== --- head/sys/dev/drm/drm_auth.c (revision 152908) +++ head/sys/dev/drm/drm_auth.c (revision 152909) @@ -1,173 +1,175 @@ /* drm_auth.h -- IOCTLs for authentication -*- linux-c -*- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include "dev/drm/drmP.h" static int drm_hash_magic(drm_magic_t magic) { return magic & (DRM_HASH_SIZE-1); } static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic) { drm_file_t *retval = NULL; drm_magic_entry_t *pt; int hash; hash = drm_hash_magic(magic); DRM_LOCK(); for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { if (pt->magic == magic) { retval = pt->priv; break; } } DRM_UNLOCK(); return retval; } static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) { int hash; drm_magic_entry_t *entry; DRM_DEBUG("%d\n", magic); hash = drm_hash_magic(magic); entry = malloc(sizeof(*entry), M_DRM, M_ZERO | M_NOWAIT); if (!entry) return DRM_ERR(ENOMEM); entry->magic = magic; entry->priv = priv; entry->next = NULL; DRM_LOCK(); if (dev->magiclist[hash].tail) { dev->magiclist[hash].tail->next = entry; dev->magiclist[hash].tail = entry; } else { dev->magiclist[hash].head = entry; dev->magiclist[hash].tail = entry; } DRM_UNLOCK(); return 0; } static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic) { drm_magic_entry_t *prev = NULL; drm_magic_entry_t *pt; int hash; DRM_DEBUG("%d\n", magic); hash = drm_hash_magic(magic); DRM_LOCK(); for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { if (pt->magic == magic) { if (dev->magiclist[hash].head == pt) { dev->magiclist[hash].head = pt->next; } if (dev->magiclist[hash].tail == pt) { dev->magiclist[hash].tail = prev; } if (prev) { prev->next = pt->next; } DRM_UNLOCK(); return 0; } } DRM_UNLOCK(); free(pt, M_DRM); return DRM_ERR(EINVAL); } int drm_getmagic(DRM_IOCTL_ARGS) { DRM_DEVICE; static drm_magic_t sequence = 0; drm_auth_t auth; drm_file_t *priv; DRM_LOCK(); priv = drm_find_file_by_proc(dev, p); DRM_UNLOCK(); if (priv == NULL) { DRM_ERROR("can't find authenticator\n"); return EINVAL; } /* Find unique magic */ if (priv->magic) { auth.magic = priv->magic; } else { do { int old = sequence; auth.magic = old+1; if (!atomic_cmpset_int(&sequence, old, auth.magic)) continue; } while (drm_find_file(dev, auth.magic)); priv->magic = auth.magic; drm_add_magic(dev, priv, auth.magic); } DRM_DEBUG("%u\n", auth.magic); DRM_COPY_TO_USER_IOCTL((drm_auth_t *)data, auth, sizeof(auth)); return 0; } int drm_authmagic(DRM_IOCTL_ARGS) { drm_auth_t auth; drm_file_t *file; DRM_DEVICE; DRM_COPY_FROM_USER_IOCTL(auth, (drm_auth_t *)data, sizeof(auth)); DRM_DEBUG("%u\n", auth.magic); if ((file = drm_find_file(dev, auth.magic))) { file->authenticated = 1; drm_remove_magic(dev, auth.magic); return 0; } return DRM_ERR(EINVAL); } Index: head/sys/dev/drm/drm_bufs.c =================================================================== --- head/sys/dev/drm/drm_bufs.c (revision 152908) +++ head/sys/dev/drm/drm_bufs.c (revision 152909) @@ -1,1034 +1,1133 @@ /* drm_bufs.h -- Generic buffer template -*- linux-c -*- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com */ /*- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + +#include "dev/pci/pcireg.h" + #include "dev/drm/drmP.h" /* * Compute order. Can be made faster. */ int drm_order(unsigned long size) { int order; unsigned long tmp; for ( order = 0, tmp = size ; tmp >>= 1 ; ++order ); if ( size & ~(1 << order) ) ++order; return order; } -unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource) +/* Allocation of PCI memory resources (framebuffer, registers, etc.) for + * drm_get_resource_*. Note that they are not RF_ACTIVE, so there's no virtual + * address for accessing them. Cleaned up at unload. + */ +static int drm_alloc_resource(drm_device_t *dev, int resource) { - struct resource *bsr; - unsigned long offset; + if (resource >= DRM_MAX_PCI_RESOURCE) { + DRM_ERROR("Resource %d too large\n", resource); + return 1; + } - resource = resource * 4 + 0x10; - - bsr = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &resource, - RF_ACTIVE | RF_SHAREABLE); - if (bsr == NULL) { - DRM_ERROR("Couldn't find resource 0x%x\n", resource); + DRM_UNLOCK(); + if (dev->pcir[resource] != NULL) { + DRM_LOCK(); return 0; } - offset = rman_get_start(bsr); + dev->pcirid[resource] = PCIR_BAR(resource); + dev->pcir[resource] = bus_alloc_resource_any(dev->device, + SYS_RES_MEMORY, &dev->pcirid[resource], RF_SHAREABLE); + DRM_LOCK(); - bus_release_resource(dev->device, SYS_RES_MEMORY, resource, bsr); + if (dev->pcir[resource] == NULL) { + DRM_ERROR("Couldn't find resource 0x%x\n", resource); + return 1; + } - return offset; + return 0; } -unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource) +unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource) { - struct resource *bsr; - unsigned long len; + if (drm_alloc_resource(dev, resource) != 0) + return 0; - resource = resource * 4 + 0x10; - - bsr = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &resource, - RF_ACTIVE | RF_SHAREABLE); - if (bsr == NULL) { - DRM_ERROR("Couldn't find resource 0x%x\n", resource); - return ENOMEM; - } - - len = rman_get_size(bsr); - - bus_release_resource(dev->device, SYS_RES_MEMORY, resource, bsr); - - return len; + return rman_get_start(dev->pcir[resource]); } -int drm_initmap(drm_device_t *dev, unsigned long start, unsigned long len, - unsigned int resource, int type, int flags) +unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource) { - drm_local_map_t *map; - struct resource *bsr; + if (drm_alloc_resource(dev, resource) != 0) + return 0; - if (type != _DRM_REGISTERS && type != _DRM_FRAME_BUFFER) - return EINVAL; - if (len == 0) - return EINVAL; - - map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT); - if (map == NULL) - return ENOMEM; - - map->rid = resource * 4 + 0x10; - bsr = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &map->rid, - RF_ACTIVE | RF_SHAREABLE); - if (bsr == NULL) { - DRM_ERROR("Couldn't allocate %s resource\n", - ((type == _DRM_REGISTERS) ? "mmio" : "framebuffer")); - free(map, M_DRM); - return ENOMEM; - } - - map->kernel_owned = 1; - map->type = type; - map->flags = flags; - map->bsr = bsr; - map->bst = rman_get_bustag(bsr); - map->bsh = rman_get_bushandle(bsr); - map->offset = start; - map->size = len; - - if (type == _DRM_REGISTERS) - map->handle = rman_get_virtual(bsr); - - DRM_DEBUG("initmap %d,0x%x@0x%lx/0x%lx\n", map->type, map->flags, - map->offset, map->size); - - if (map->flags & _DRM_WRITE_COMBINING) { - int err; - - err = drm_mtrr_add(map->offset, map->size, DRM_MTRR_WC); - if (err == 0) - map->mtrr = 1; - } - - DRM_LOCK(); - TAILQ_INSERT_TAIL(&dev->maplist, map, link); - DRM_UNLOCK(); - - return 0; + return rman_get_size(dev->pcir[resource]); } -int drm_addmap(DRM_IOCTL_ARGS) +int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, + drm_map_type_t type, drm_map_flags_t flags, drm_local_map_t **map_ptr) { - DRM_DEVICE; - drm_map_t request; drm_local_map_t *map; - dma_addr_t bus_addr; - - if (!(dev->flags & (FREAD|FWRITE))) - return DRM_ERR(EACCES); /* Require read/write */ + int align; + /*drm_agp_mem_t *entry; + int valid;*/ - DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(drm_map_t) ); - /* Only allow shared memory to be removable since we only keep enough * book keeping information about shared memory to allow for removal * when processes fork. */ - if ((request.flags & _DRM_REMOVABLE) && request.type != _DRM_SHM) + if ((flags & _DRM_REMOVABLE) && type != _DRM_SHM) { + DRM_ERROR("Requested removable map for non-DRM_SHM\n"); return EINVAL; - if ((request.offset & PAGE_MASK) || (request.size & PAGE_MASK)) + } + if ((offset & PAGE_MASK) || (size & PAGE_MASK)) { + DRM_ERROR("offset/size not page aligned: 0x%lx/0x%lx\n", + offset, size); return EINVAL; - if (request.offset + request.size < request.offset) + } + if (offset + size < offset) { + DRM_ERROR("offset and size wrap around: 0x%lx/0x%lx\n", + offset, size); return EINVAL; + } - DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n", - request.offset, request.size, request.type); + DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n", offset, + size, type); /* Check if this is just another version of a kernel-allocated map, and * just hand that back if so. */ - if (request.type == _DRM_REGISTERS || request.type == _DRM_FRAME_BUFFER) - { - DRM_LOCK(); + if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER || + type == _DRM_SHM) { TAILQ_FOREACH(map, &dev->maplist, link) { - if (map->kernel_owned && map->type == request.type && - map->offset == request.offset) { - /* XXX: this size setting is questionable. */ - map->size = request.size; - DRM_DEBUG("Found kernel map %d\n", request.type); + if (map->type == type && (map->offset == offset || + (map->type == _DRM_SHM && + map->flags == _DRM_CONTAINS_LOCK))) { + map->size = size; + DRM_DEBUG("Found kernel map %d\n", type); goto done; } } - DRM_UNLOCK(); } + DRM_UNLOCK(); /* Allocate a new map structure, fill it in, and do any type-specific * initialization necessary. */ map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT); if ( !map ) return DRM_ERR(ENOMEM); - map->offset = request.offset; - map->size = request.size; - map->type = request.type; - map->flags = request.flags; + map->offset = offset; + map->size = size; + map->type = type; + map->flags = flags; switch ( map->type ) { case _DRM_REGISTERS: map->handle = drm_ioremap(dev, map); if (!(map->flags & _DRM_WRITE_COMBINING)) break; /* FALLTHROUGH */ case _DRM_FRAME_BUFFER: if (drm_mtrr_add(map->offset, map->size, DRM_MTRR_WC) == 0) map->mtrr = 1; break; case _DRM_SHM: map->handle = malloc(map->size, M_DRM, M_NOWAIT); DRM_DEBUG( "%lu %d %p\n", map->size, drm_order(map->size), map->handle ); if ( !map->handle ) { free(map, M_DRM); return DRM_ERR(ENOMEM); } map->offset = (unsigned long)map->handle; if ( map->flags & _DRM_CONTAINS_LOCK ) { /* Prevent a 2nd X Server from creating a 2nd lock */ DRM_LOCK(); if (dev->lock.hw_lock != NULL) { DRM_UNLOCK(); free(map->handle, M_DRM); free(map, M_DRM); return DRM_ERR(EBUSY); } dev->lock.hw_lock = map->handle; /* Pointer to lock */ DRM_UNLOCK(); } break; case _DRM_AGP: + /*valid = 0;*/ map->offset += dev->agp->base; map->mtrr = dev->agp->mtrr; /* for getmap */ + /*for (entry = dev->agp->memory; entry; entry = entry->next) { + if ((map->offset >= entry->bound) && + (map->offset + map->size <= + entry->bound + entry->pages * PAGE_SIZE)) { + valid = 1; + break; + } + } + if (!valid) { + free(map, M_DRM); + return DRM_ERR(EACCES); + }*/ break; case _DRM_SCATTER_GATHER: if (!dev->sg) { free(map, M_DRM); return DRM_ERR(EINVAL); } map->offset = map->offset + dev->sg->handle; break; case _DRM_CONSISTENT: - map->handle = drm_pci_alloc(dev, map->size, map->size, - 0xfffffffful, &bus_addr); - if (map->handle == NULL) { + /* Unfortunately, we don't get any alignment specification from + * the caller, so we have to guess. drm_pci_alloc requires + * a power-of-two alignment, so try to align the bus address of + * the map to it size if possible, otherwise just assume + * PAGE_SIZE alignment. + */ + align = map->size; + if ((align & (align - 1)) != 0) + align = PAGE_SIZE; + map->dmah = drm_pci_alloc(dev, map->size, align, 0xfffffffful); + if (map->dmah == NULL) { free(map, M_DRM); - return ENOMEM; + return DRM_ERR(ENOMEM); } - map->offset = (unsigned long)bus_addr; + map->handle = map->dmah->vaddr; + map->offset = map->dmah->busaddr; break; default: + DRM_ERROR("Bad map type %d\n", map->type); free(map, M_DRM); return DRM_ERR(EINVAL); } DRM_LOCK(); TAILQ_INSERT_TAIL(&dev->maplist, map, link); done: /* Jumped to, with lock held, when a kernel map is found. */ + + DRM_DEBUG("Added map %d 0x%lx/0x%lx\n", map->type, map->offset, + map->size); + + *map_ptr = map; + + return 0; +} + +int drm_addmap_ioctl(DRM_IOCTL_ARGS) +{ + drm_map_t request; + drm_local_map_t *map; + int err; + DRM_DEVICE; + + if (!(dev->flags & (FREAD|FWRITE))) + return DRM_ERR(EACCES); /* Require read/write */ + + DRM_COPY_FROM_USER_IOCTL(request, (drm_map_t *)data, sizeof(drm_map_t)); + + if (!DRM_SUSER(p) && request.type != _DRM_AGP) + return DRM_ERR(EACCES); + + DRM_LOCK(); + err = drm_addmap(dev, request.offset, request.size, request.type, + request.flags, &map); + DRM_UNLOCK(); + if (err != 0) + return err; + request.offset = map->offset; request.size = map->size; request.type = map->type; request.flags = map->flags; request.mtrr = map->mtrr; request.handle = map->handle; - DRM_UNLOCK(); - DRM_DEBUG("Added map %d 0x%lx/0x%lx\n", request.type, request.offset, request.size); - - if ( request.type != _DRM_SHM ) { + if (request.type != _DRM_SHM) { request.handle = (void *)request.offset; } + DRM_COPY_TO_USER_IOCTL((drm_map_t *)data, request, sizeof(drm_map_t)); - DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, request, sizeof(drm_map_t) ); - return 0; } -void drm_remove_map(drm_device_t *dev, drm_local_map_t *map) +void drm_rmmap(drm_device_t *dev, drm_local_map_t *map) { DRM_SPINLOCK_ASSERT(&dev->dev_lock); TAILQ_REMOVE(&dev->maplist, map, link); switch (map->type) { case _DRM_REGISTERS: if (map->bsr == NULL) drm_ioremapfree(map); /* FALLTHROUGH */ case _DRM_FRAME_BUFFER: if (map->mtrr) { int __unused retcode; - retcode = drm_mtrr_del(map->offset, map->size, + retcode = drm_mtrr_del(0, map->offset, map->size, DRM_MTRR_WC); DRM_DEBUG("mtrr_del = %d\n", retcode); } break; case _DRM_SHM: free(map->handle, M_DRM); break; case _DRM_AGP: case _DRM_SCATTER_GATHER: break; case _DRM_CONSISTENT: - drm_pci_free(dev, map->size, map->handle, map->offset); + drm_pci_free(dev, map->dmah); break; } if (map->bsr != NULL) { bus_release_resource(dev->device, SYS_RES_MEMORY, map->rid, map->bsr); } free(map, M_DRM); } /* Remove a map private from list and deallocate resources if the mapping * isn't in use. */ -int drm_rmmap(DRM_IOCTL_ARGS) +int drm_rmmap_ioctl(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_local_map_t *map; drm_map_t request; DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(request) ); DRM_LOCK(); TAILQ_FOREACH(map, &dev->maplist, link) { if (map->handle == request.handle && map->flags & _DRM_REMOVABLE) break; } /* No match found. */ if (map == NULL) { DRM_UNLOCK(); return DRM_ERR(EINVAL); } - drm_remove_map(dev, map); + drm_rmmap(dev, map); DRM_UNLOCK(); return 0; } static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry) { int i; if (entry->seg_count) { for (i = 0; i < entry->seg_count; i++) { - drm_pci_free(dev, entry->buf_size, - (void *)entry->seglist[i], - entry->seglist_bus[i]); + drm_pci_free(dev, entry->seglist[i]); } free(entry->seglist, M_DRM); - free(entry->seglist_bus, M_DRM); entry->seg_count = 0; } if (entry->buf_count) { for (i = 0; i < entry->buf_count; i++) { free(entry->buflist[i].dev_private, M_DRM); } free(entry->buflist, M_DRM); entry->buf_count = 0; } } -static int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) +static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) { drm_device_dma_t *dma = dev->dma; drm_buf_entry_t *entry; + /*drm_agp_mem_t *agp_entry; + int valid*/ drm_buf_t *buf; unsigned long offset; unsigned long agp_offset; int count; int order; int size; int alignment; int page_order; int total; int byte_count; int i; drm_buf_t **temp_buflist; count = request->count; order = drm_order(request->size); size = 1 << order; alignment = (request->flags & _DRM_PAGE_ALIGN) ? round_page(size) : size; page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; total = PAGE_SIZE << page_order; byte_count = 0; agp_offset = dev->agp->base + request->agp_start; DRM_DEBUG( "count: %d\n", count ); DRM_DEBUG( "order: %d\n", order ); DRM_DEBUG( "size: %d\n", size ); DRM_DEBUG( "agp_offset: 0x%lx\n", agp_offset ); DRM_DEBUG( "alignment: %d\n", alignment ); DRM_DEBUG( "page_order: %d\n", page_order ); DRM_DEBUG( "total: %d\n", total ); + /* Make sure buffers are located in AGP memory that we own */ + /* Breaks MGA due to drm_alloc_agp not setting up entries for the + * memory. Safe to ignore for now because these ioctls are still + * root-only. + */ + /*valid = 0; + for (agp_entry = dev->agp->memory; agp_entry; + agp_entry = agp_entry->next) { + if ((agp_offset >= agp_entry->bound) && + (agp_offset + total * count <= + agp_entry->bound + agp_entry->pages * PAGE_SIZE)) { + valid = 1; + break; + } + } + if (!valid) { + DRM_DEBUG("zone invalid\n"); + return DRM_ERR(EINVAL); + }*/ + entry = &dma->bufs[order]; entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM, M_NOWAIT | M_ZERO); if ( !entry->buflist ) { return DRM_ERR(ENOMEM); } entry->buf_size = size; entry->page_order = page_order; offset = 0; while ( entry->buf_count < count ) { buf = &entry->buflist[entry->buf_count]; buf->idx = dma->buf_count + entry->buf_count; buf->total = alignment; buf->order = order; buf->used = 0; buf->offset = (dma->byte_count + offset); buf->bus_address = agp_offset + offset; buf->address = (void *)(agp_offset + offset); buf->next = NULL; buf->pending = 0; buf->filp = NULL; - buf->dev_priv_size = dev->dev_priv_size; + buf->dev_priv_size = dev->driver.buf_priv_size; buf->dev_private = malloc(buf->dev_priv_size, M_DRM, M_NOWAIT | M_ZERO); if (buf->dev_private == NULL) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; drm_cleanup_buf_error(dev, entry); return DRM_ERR(ENOMEM); } offset += alignment; entry->buf_count++; byte_count += PAGE_SIZE << page_order; } DRM_DEBUG( "byte_count: %d\n", byte_count ); temp_buflist = realloc(dma->buflist, (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist), M_DRM, M_NOWAIT); if (temp_buflist == NULL) { /* Free the entry because it isn't valid */ drm_cleanup_buf_error(dev, entry); return DRM_ERR(ENOMEM); } dma->buflist = temp_buflist; for ( i = 0 ; i < entry->buf_count ; i++ ) { dma->buflist[i + dma->buf_count] = &entry->buflist[i]; } dma->buf_count += entry->buf_count; dma->byte_count += byte_count; DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count ); DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count ); request->count = entry->buf_count; request->size = size; dma->flags = _DRM_DMA_USE_AGP; return 0; } -static int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request) +static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request) { drm_device_dma_t *dma = dev->dma; int count; int order; int size; int total; int page_order; drm_buf_entry_t *entry; - vm_offset_t vaddr; drm_buf_t *buf; int alignment; unsigned long offset; int i; int byte_count; int page_count; unsigned long *temp_pagelist; drm_buf_t **temp_buflist; - dma_addr_t bus_addr; count = request->count; order = drm_order(request->size); size = 1 << order; DRM_DEBUG( "count=%d, size=%d (%d), order=%d\n", request->count, request->size, size, order ); alignment = (request->flags & _DRM_PAGE_ALIGN) ? round_page(size) : size; page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; total = PAGE_SIZE << page_order; entry = &dma->bufs[order]; entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM, M_NOWAIT | M_ZERO); entry->seglist = malloc(count * sizeof(*entry->seglist), M_DRM, M_NOWAIT | M_ZERO); - entry->seglist_bus = malloc(count * sizeof(*entry->seglist_bus), M_DRM, - M_NOWAIT | M_ZERO); /* Keep the original pagelist until we know all the allocations * have succeeded */ temp_pagelist = malloc((dma->page_count + (count << page_order)) * sizeof(*dma->pagelist), M_DRM, M_NOWAIT); if (entry->buflist == NULL || entry->seglist == NULL || - entry->seglist_bus == NULL || temp_pagelist == NULL) { + temp_pagelist == NULL) { free(entry->buflist, M_DRM); free(entry->seglist, M_DRM); - free(entry->seglist_bus, M_DRM); return DRM_ERR(ENOMEM); } memcpy(temp_pagelist, dma->pagelist, dma->page_count * sizeof(*dma->pagelist)); DRM_DEBUG( "pagelist: %d entries\n", dma->page_count + (count << page_order) ); entry->buf_size = size; entry->page_order = page_order; byte_count = 0; page_count = 0; while ( entry->buf_count < count ) { - vaddr = (vm_offset_t)drm_pci_alloc(dev, size, alignment, - 0xfffffffful, &bus_addr); - if (vaddr == 0) { + drm_dma_handle_t *dmah = drm_pci_alloc(dev, size, alignment, + 0xfffffffful); + if (dmah == NULL) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; entry->seg_count = count; drm_cleanup_buf_error(dev, entry); free(temp_pagelist, M_DRM); return DRM_ERR(ENOMEM); } - - entry->seglist_bus[entry->seg_count] = bus_addr; - entry->seglist[entry->seg_count++] = vaddr; + + entry->seglist[entry->seg_count++] = dmah; for ( i = 0 ; i < (1 << page_order) ; i++ ) { - DRM_DEBUG( "page %d @ 0x%08lx\n", + DRM_DEBUG( "page %d @ %p\n", dma->page_count + page_count, - (long)vaddr + PAGE_SIZE * i ); + (char *)dmah->vaddr + PAGE_SIZE * i ); temp_pagelist[dma->page_count + page_count++] = - vaddr + PAGE_SIZE * i; + (long)dmah->vaddr + PAGE_SIZE * i; } for ( offset = 0 ; offset + size <= total && entry->buf_count < count ; offset += alignment, ++entry->buf_count ) { buf = &entry->buflist[entry->buf_count]; buf->idx = dma->buf_count + entry->buf_count; buf->total = alignment; buf->order = order; buf->used = 0; buf->offset = (dma->byte_count + byte_count + offset); - buf->address = (void *)(vaddr + offset); - buf->bus_address = bus_addr + offset; + buf->address = ((char *)dmah->vaddr + offset); + buf->bus_address = dmah->busaddr + offset; buf->next = NULL; buf->pending = 0; buf->filp = NULL; - buf->dev_priv_size = dev->dev_priv_size; + buf->dev_priv_size = dev->driver.buf_priv_size; buf->dev_private = malloc(buf->dev_priv_size, M_DRM, M_NOWAIT | M_ZERO); if (buf->dev_private == NULL) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; entry->seg_count = count; drm_cleanup_buf_error(dev, entry); free(temp_pagelist, M_DRM); return DRM_ERR(ENOMEM); } DRM_DEBUG( "buffer %d @ %p\n", entry->buf_count, buf->address ); } byte_count += PAGE_SIZE << page_order; } temp_buflist = realloc(dma->buflist, (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist), M_DRM, M_NOWAIT); if (temp_buflist == NULL) { /* Free the entry because it isn't valid */ drm_cleanup_buf_error(dev, entry); free(temp_pagelist, M_DRM); return DRM_ERR(ENOMEM); } dma->buflist = temp_buflist; for ( i = 0 ; i < entry->buf_count ; i++ ) { dma->buflist[i + dma->buf_count] = &entry->buflist[i]; } /* No allocations failed, so now we can replace the orginal pagelist * with the new one. */ free(dma->pagelist, M_DRM); dma->pagelist = temp_pagelist; dma->buf_count += entry->buf_count; dma->seg_count += entry->seg_count; dma->page_count += entry->seg_count << page_order; dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); request->count = entry->buf_count; request->size = size; return 0; } -static int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) +static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) { drm_device_dma_t *dma = dev->dma; drm_buf_entry_t *entry; drm_buf_t *buf; unsigned long offset; unsigned long agp_offset; int count; int order; int size; int alignment; int page_order; int total; int byte_count; int i; drm_buf_t **temp_buflist; count = request->count; order = drm_order(request->size); size = 1 << order; alignment = (request->flags & _DRM_PAGE_ALIGN) ? round_page(size) : size; page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; total = PAGE_SIZE << page_order; byte_count = 0; agp_offset = request->agp_start; DRM_DEBUG( "count: %d\n", count ); DRM_DEBUG( "order: %d\n", order ); DRM_DEBUG( "size: %d\n", size ); DRM_DEBUG( "agp_offset: %ld\n", agp_offset ); DRM_DEBUG( "alignment: %d\n", alignment ); DRM_DEBUG( "page_order: %d\n", page_order ); DRM_DEBUG( "total: %d\n", total ); entry = &dma->bufs[order]; entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM, M_NOWAIT | M_ZERO); if (entry->buflist == NULL) return DRM_ERR(ENOMEM); entry->buf_size = size; entry->page_order = page_order; offset = 0; while ( entry->buf_count < count ) { buf = &entry->buflist[entry->buf_count]; buf->idx = dma->buf_count + entry->buf_count; buf->total = alignment; buf->order = order; buf->used = 0; buf->offset = (dma->byte_count + offset); buf->bus_address = agp_offset + offset; buf->address = (void *)(agp_offset + offset + dev->sg->handle); buf->next = NULL; buf->pending = 0; buf->filp = NULL; - buf->dev_priv_size = dev->dev_priv_size; + buf->dev_priv_size = dev->driver.buf_priv_size; buf->dev_private = malloc(buf->dev_priv_size, M_DRM, M_NOWAIT | M_ZERO); if (buf->dev_private == NULL) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; drm_cleanup_buf_error(dev, entry); return DRM_ERR(ENOMEM); } DRM_DEBUG( "buffer %d @ %p\n", entry->buf_count, buf->address ); offset += alignment; entry->buf_count++; byte_count += PAGE_SIZE << page_order; } DRM_DEBUG( "byte_count: %d\n", byte_count ); temp_buflist = realloc(dma->buflist, (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist), M_DRM, M_NOWAIT); if (temp_buflist == NULL) { /* Free the entry because it isn't valid */ drm_cleanup_buf_error(dev, entry); return DRM_ERR(ENOMEM); } dma->buflist = temp_buflist; for ( i = 0 ; i < entry->buf_count ; i++ ) { dma->buflist[i + dma->buf_count] = &entry->buflist[i]; } dma->buf_count += entry->buf_count; dma->byte_count += byte_count; DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count ); DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count ); request->count = entry->buf_count; request->size = size; dma->flags = _DRM_DMA_USE_SG; return 0; } -int drm_addbufs(DRM_IOCTL_ARGS) +int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) { - DRM_DEVICE; - drm_buf_desc_t request; - int err; - int order; + int order, ret; - DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) ); + DRM_SPINLOCK(&dev->dma_lock); - if (request.count < 0 || request.count > 4096) + if (request->count < 0 || request->count > 4096) return DRM_ERR(EINVAL); + + order = drm_order(request->size); + if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) + return DRM_ERR(EINVAL); - order = drm_order(request.size); + /* No more allocations after first buffer-using ioctl. */ + if (dev->buf_use != 0) { + DRM_SPINUNLOCK(&dev->dma_lock); + return DRM_ERR(EBUSY); + } + /* No more than one allocation per order */ + if (dev->dma->bufs[order].buf_count != 0) { + DRM_SPINUNLOCK(&dev->dma_lock); + return DRM_ERR(ENOMEM); + } + + ret = drm_do_addbufs_agp(dev, request); + + DRM_SPINUNLOCK(&dev->dma_lock); + + return ret; +} + +int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) +{ + int order, ret; + + DRM_SPINLOCK(&dev->dma_lock); + + if (!DRM_SUSER(DRM_CURPROC)) + return DRM_ERR(EACCES); + + if (request->count < 0 || request->count > 4096) + return DRM_ERR(EINVAL); + + order = drm_order(request->size); if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return DRM_ERR(EINVAL); + /* No more allocations after first buffer-using ioctl. */ + if (dev->buf_use != 0) { + DRM_SPINUNLOCK(&dev->dma_lock); + return DRM_ERR(EBUSY); + } + /* No more than one allocation per order */ + if (dev->dma->bufs[order].buf_count != 0) { + DRM_SPINUNLOCK(&dev->dma_lock); + return DRM_ERR(ENOMEM); + } + + ret = drm_do_addbufs_sg(dev, request); + + DRM_SPINUNLOCK(&dev->dma_lock); + + return ret; +} + +int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request) +{ + int order, ret; + DRM_SPINLOCK(&dev->dma_lock); + + if (!DRM_SUSER(DRM_CURPROC)) + return DRM_ERR(EACCES); + + if (request->count < 0 || request->count > 4096) + return DRM_ERR(EINVAL); + + order = drm_order(request->size); + if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) + return DRM_ERR(EINVAL); + /* No more allocations after first buffer-using ioctl. */ if (dev->buf_use != 0) { DRM_SPINUNLOCK(&dev->dma_lock); return DRM_ERR(EBUSY); } /* No more than one allocation per order */ if (dev->dma->bufs[order].buf_count != 0) { DRM_SPINUNLOCK(&dev->dma_lock); return DRM_ERR(ENOMEM); } - if ( request.flags & _DRM_AGP_BUFFER ) + ret = drm_do_addbufs_pci(dev, request); + + DRM_SPINUNLOCK(&dev->dma_lock); + + return ret; +} + +int drm_addbufs_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_buf_desc_t request; + int err; + + DRM_COPY_FROM_USER_IOCTL(request, (drm_buf_desc_t *)data, + sizeof(request)); + + if (request.flags & _DRM_AGP_BUFFER) err = drm_addbufs_agp(dev, &request); - else - if ( request.flags & _DRM_SG_BUFFER ) + else if (request.flags & _DRM_SG_BUFFER) err = drm_addbufs_sg(dev, &request); else err = drm_addbufs_pci(dev, &request); - DRM_SPINUNLOCK(&dev->dma_lock); - DRM_COPY_TO_USER_IOCTL((drm_buf_desc_t *)data, request, sizeof(request)); + DRM_COPY_TO_USER_IOCTL((drm_buf_desc_t *)data, request, + sizeof(request)); return err; } int drm_infobufs(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_info_t request; int i; int count; int retcode = 0; DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) ); DRM_SPINLOCK(&dev->dma_lock); ++dev->buf_use; /* Can't allocate more after this call */ DRM_SPINUNLOCK(&dev->dma_lock); for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) { if ( dma->bufs[i].buf_count ) ++count; } DRM_DEBUG( "count = %d\n", count ); if ( request.count >= count ) { for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) { if ( dma->bufs[i].buf_count ) { drm_buf_desc_t from; from.count = dma->bufs[i].buf_count; from.size = dma->bufs[i].buf_size; from.low_mark = dma->bufs[i].freelist.low_mark; from.high_mark = dma->bufs[i].freelist.high_mark; if (DRM_COPY_TO_USER(&request.list[count], &from, sizeof(drm_buf_desc_t)) != 0) { retcode = DRM_ERR(EFAULT); break; } DRM_DEBUG( "%d %d %d %d %d\n", i, dma->bufs[i].buf_count, dma->bufs[i].buf_size, dma->bufs[i].freelist.low_mark, dma->bufs[i].freelist.high_mark ); ++count; } } } request.count = count; DRM_COPY_TO_USER_IOCTL( (drm_buf_info_t *)data, request, sizeof(request) ); return retcode; } int drm_markbufs(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_desc_t request; int order; DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) ); DRM_DEBUG( "%d, %d, %d\n", request.size, request.low_mark, request.high_mark ); order = drm_order(request.size); if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER || request.low_mark < 0 || request.high_mark < 0) { return DRM_ERR(EINVAL); } DRM_SPINLOCK(&dev->dma_lock); if (request.low_mark > dma->bufs[order].buf_count || request.high_mark > dma->bufs[order].buf_count) { return DRM_ERR(EINVAL); } dma->bufs[order].freelist.low_mark = request.low_mark; dma->bufs[order].freelist.high_mark = request.high_mark; DRM_SPINUNLOCK(&dev->dma_lock); return 0; } int drm_freebufs(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_free_t request; int i; int idx; drm_buf_t *buf; int retcode = 0; DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_free_t *)data, sizeof(request) ); DRM_DEBUG( "%d\n", request.count ); DRM_SPINLOCK(&dev->dma_lock); for ( i = 0 ; i < request.count ; i++ ) { if (DRM_COPY_FROM_USER(&idx, &request.list[i], sizeof(idx))) { retcode = DRM_ERR(EFAULT); break; } if ( idx < 0 || idx >= dma->buf_count ) { DRM_ERROR( "Index %d (of %d max)\n", idx, dma->buf_count - 1 ); retcode = DRM_ERR(EINVAL); break; } buf = dma->buflist[idx]; if ( buf->filp != filp ) { DRM_ERROR("Process %d freeing buffer not owned\n", DRM_CURRENTPID); retcode = DRM_ERR(EINVAL); break; } drm_free_buffer(dev, buf); } DRM_SPINUNLOCK(&dev->dma_lock); return retcode; } int drm_mapbufs(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; int retcode = 0; const int zero = 0; vm_offset_t address; struct vmspace *vms; #ifdef __FreeBSD__ vm_ooffset_t foff; vm_size_t size; vm_offset_t vaddr; #elif defined(__NetBSD__) || defined(__OpenBSD__) struct vnode *vn; - vm_size_t size; + voff_t foff; + vsize_t size; vaddr_t vaddr; #endif /* __NetBSD__ || __OpenBSD__ */ drm_buf_map_t request; int i; DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_map_t *)data, sizeof(request) ); #if defined(__NetBSD__) || defined(__OpenBSD__) if (!vfinddev(kdev, VCHR, &vn)) return 0; /* FIXME: Shouldn't this be EINVAL or something? */ #endif /* __NetBSD__ || __OpenBSD */ #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 vms = p->td_proc->p_vmspace; #else vms = p->p_vmspace; #endif DRM_SPINLOCK(&dev->dma_lock); dev->buf_use++; /* Can't allocate more after this call */ DRM_SPINUNLOCK(&dev->dma_lock); if (request.count < dma->buf_count) goto done; - if ((dev->use_agp && (dma->flags & _DRM_DMA_USE_AGP)) || - (dev->use_sg && (dma->flags & _DRM_DMA_USE_SG))) { + if ((dev->driver.use_agp && (dma->flags & _DRM_DMA_USE_AGP)) || + (dev->driver.use_sg && (dma->flags & _DRM_DMA_USE_SG))) { drm_local_map_t *map = dev->agp_buffer_map; if (map == NULL) { retcode = EINVAL; goto done; } size = round_page(map->size); foff = map->offset; } else { size = round_page(dma->byte_count), foff = 0; } #ifdef __FreeBSD__ vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ); #if __FreeBSD_version >= 600023 retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE, VM_PROT_ALL, MAP_SHARED, OBJT_DEVICE, kdev, foff ); #else retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE, VM_PROT_ALL, MAP_SHARED, SLIST_FIRST(&kdev->si_hlist), foff ); #endif #elif defined(__NetBSD__) || defined(__OpenBSD__) vaddr = round_page((vaddr_t)vms->vm_daddr + MAXDSIZ); retcode = uvm_mmap(&vms->vm_map, &vaddr, size, UVM_PROT_READ | UVM_PROT_WRITE, UVM_PROT_ALL, MAP_SHARED, &vn->v_uobj, foff, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); #endif /* __NetBSD__ || __OpenBSD */ if (retcode) goto done; request.virtual = (void *)vaddr; for ( i = 0 ; i < dma->buf_count ; i++ ) { if (DRM_COPY_TO_USER(&request.list[i].idx, &dma->buflist[i]->idx, sizeof(request.list[0].idx))) { retcode = EFAULT; goto done; } if (DRM_COPY_TO_USER(&request.list[i].total, &dma->buflist[i]->total, sizeof(request.list[0].total))) { retcode = EFAULT; goto done; } if (DRM_COPY_TO_USER(&request.list[i].used, &zero, sizeof(zero))) { retcode = EFAULT; goto done; } address = vaddr + dma->buflist[i]->offset; /* *** */ if (DRM_COPY_TO_USER(&request.list[i].address, &address, sizeof(address))) { retcode = EFAULT; goto done; } } done: request.count = dma->buf_count; DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode ); DRM_COPY_TO_USER_IOCTL((drm_buf_map_t *)data, request, sizeof(request)); return DRM_ERR(retcode); } Index: head/sys/dev/drm/drm_context.c =================================================================== --- head/sys/dev/drm/drm_context.c (revision 152908) +++ head/sys/dev/drm/drm_context.c (revision 152909) @@ -1,343 +1,348 @@ /* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*- * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com */ /*- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" /* ================================================================ * Context bitmap support */ void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle) { if (ctx_handle < 0 || ctx_handle >= DRM_MAX_CTXBITMAP || dev->ctx_bitmap == NULL) { DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle); return; } DRM_LOCK(); clear_bit(ctx_handle, dev->ctx_bitmap); dev->context_sareas[ctx_handle] = NULL; DRM_UNLOCK(); return; } int drm_ctxbitmap_next(drm_device_t *dev) { int bit; if (dev->ctx_bitmap == NULL) return -1; DRM_LOCK(); bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP ); if (bit >= DRM_MAX_CTXBITMAP) { DRM_UNLOCK(); return -1; } set_bit(bit, dev->ctx_bitmap); DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit); if ((bit+1) > dev->max_context) { dev->max_context = (bit+1); if (dev->context_sareas != NULL) { drm_local_map_t **ctx_sareas; ctx_sareas = realloc(dev->context_sareas, dev->max_context * sizeof(*dev->context_sareas), M_DRM, M_NOWAIT); if (ctx_sareas == NULL) { clear_bit(bit, dev->ctx_bitmap); DRM_UNLOCK(); return -1; } dev->context_sareas = ctx_sareas; dev->context_sareas[bit] = NULL; } else { /* max_context == 1 at this point */ dev->context_sareas = malloc(dev->max_context * sizeof(*dev->context_sareas), M_DRM, M_NOWAIT); if (dev->context_sareas == NULL) { clear_bit(bit, dev->ctx_bitmap); DRM_UNLOCK(); return -1; } dev->context_sareas[bit] = NULL; } } DRM_UNLOCK(); return bit; } int drm_ctxbitmap_init(drm_device_t *dev) { int i; int temp; DRM_LOCK(); dev->ctx_bitmap = malloc(PAGE_SIZE, M_DRM, M_NOWAIT | M_ZERO); if ( dev->ctx_bitmap == NULL ) { DRM_UNLOCK(); return DRM_ERR(ENOMEM); } dev->context_sareas = NULL; dev->max_context = -1; DRM_UNLOCK(); for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) { temp = drm_ctxbitmap_next(dev); DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp ); } return 0; } void drm_ctxbitmap_cleanup(drm_device_t *dev) { DRM_LOCK(); if (dev->context_sareas != NULL) free(dev->context_sareas, M_DRM); free(dev->ctx_bitmap, M_DRM); DRM_UNLOCK(); } /* ================================================================ * Per Context SAREA Support */ int drm_getsareactx( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_ctx_priv_map_t request; drm_local_map_t *map; DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data, sizeof(request) ); DRM_LOCK(); if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) { DRM_UNLOCK(); return DRM_ERR(EINVAL); } map = dev->context_sareas[request.ctx_id]; DRM_UNLOCK(); request.handle = map->handle; DRM_COPY_TO_USER_IOCTL( (drm_ctx_priv_map_t *)data, request, sizeof(request) ); return 0; } int drm_setsareactx( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_ctx_priv_map_t request; drm_local_map_t *map = NULL; DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data, sizeof(request) ); DRM_LOCK(); TAILQ_FOREACH(map, &dev->maplist, link) { if (map->handle == request.handle) { if (dev->max_context < 0) goto bad; if (request.ctx_id >= (unsigned) dev->max_context) goto bad; dev->context_sareas[request.ctx_id] = map; DRM_UNLOCK(); return 0; } } bad: DRM_UNLOCK(); return DRM_ERR(EINVAL); } /* ================================================================ * The actual DRM context handling routines */ int drm_context_switch(drm_device_t *dev, int old, int new) { if ( test_and_set_bit( 0, &dev->context_flag ) ) { DRM_ERROR( "Reentering -- FIXME\n" ); return DRM_ERR(EBUSY); } DRM_DEBUG( "Context switch from %d to %d\n", old, new ); if ( new == dev->last_context ) { clear_bit( 0, &dev->context_flag ); return 0; } return 0; } int drm_context_switch_complete(drm_device_t *dev, int new) { dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) { DRM_ERROR( "Lock isn't held after context switch\n" ); } /* If a context switch is ever initiated when the kernel holds the lock, release that lock here. */ clear_bit( 0, &dev->context_flag ); return 0; } int drm_resctx(DRM_IOCTL_ARGS) { drm_ctx_res_t res; + drm_ctx_t ctx; int i; DRM_COPY_FROM_USER_IOCTL( res, (drm_ctx_res_t *)data, sizeof(res) ); if ( res.count >= DRM_RESERVED_CONTEXTS ) { + bzero(&ctx, sizeof(ctx)); for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) { + ctx.handle = i; if ( DRM_COPY_TO_USER( &res.contexts[i], - &i, sizeof(i) ) ) + &ctx, sizeof(ctx) ) ) return DRM_ERR(EFAULT); } } res.count = DRM_RESERVED_CONTEXTS; DRM_COPY_TO_USER_IOCTL( (drm_ctx_res_t *)data, res, sizeof(res) ); return 0; } int drm_addctx(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_ctx_t ctx; DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); ctx.handle = drm_ctxbitmap_next(dev); if ( ctx.handle == DRM_KERNEL_CONTEXT ) { /* Skip kernel's context and get a new one. */ ctx.handle = drm_ctxbitmap_next(dev); } DRM_DEBUG( "%d\n", ctx.handle ); if ( ctx.handle == -1 ) { DRM_DEBUG( "Not enough free contexts.\n" ); /* Should this return -EBUSY instead? */ return DRM_ERR(ENOMEM); } - if (dev->context_ctor && ctx.handle != DRM_KERNEL_CONTEXT) { + if (dev->driver.context_ctor && ctx.handle != DRM_KERNEL_CONTEXT) { DRM_LOCK(); - dev->context_ctor(dev, ctx.handle); + dev->driver.context_ctor(dev, ctx.handle); DRM_UNLOCK(); } DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) ); return 0; } int drm_modctx(DRM_IOCTL_ARGS) { /* This does nothing */ return 0; } int drm_getctx(DRM_IOCTL_ARGS) { drm_ctx_t ctx; DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); /* This is 0, because we don't handle any context flags */ ctx.flags = 0; DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) ); return 0; } int drm_switchctx(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_ctx_t ctx; DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG( "%d\n", ctx.handle ); return drm_context_switch(dev, dev->last_context, ctx.handle); } int drm_newctx(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_ctx_t ctx; DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG( "%d\n", ctx.handle ); drm_context_switch_complete(dev, ctx.handle); return 0; } int drm_rmctx(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_ctx_t ctx; DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG( "%d\n", ctx.handle ); if ( ctx.handle != DRM_KERNEL_CONTEXT ) { - if (dev->context_dtor) { + if (dev->driver.context_dtor) { DRM_LOCK(); - dev->context_dtor(dev, ctx.handle); + dev->driver.context_dtor(dev, ctx.handle); DRM_UNLOCK(); } drm_ctxbitmap_free(dev, ctx.handle); } return 0; } Index: head/sys/dev/drm/drm_dma.c =================================================================== --- head/sys/dev/drm/drm_dma.c (revision 152908) +++ head/sys/dev/drm/drm_dma.c (revision 152909) @@ -1,134 +1,133 @@ /* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*- * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com */ /*- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" int drm_dma_setup(drm_device_t *dev) { dev->dma = malloc(sizeof(*dev->dma), M_DRM, M_NOWAIT | M_ZERO); if (dev->dma == NULL) return DRM_ERR(ENOMEM); DRM_SPININIT(dev->dma_lock, "drmdma"); return 0; } void drm_dma_takedown(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; int i, j; if (dma == NULL) return; /* Clear dma buffers */ for (i = 0; i <= DRM_MAX_ORDER; i++) { if (dma->bufs[i].seg_count) { DRM_DEBUG("order %d: buf_count = %d," " seg_count = %d\n", i, dma->bufs[i].buf_count, dma->bufs[i].seg_count); for (j = 0; j < dma->bufs[i].seg_count; j++) { - drm_pci_free(dev, dma->bufs[i].buf_size, - (void *)dma->bufs[i].seglist[j], - dma->bufs[i].seglist_bus[j]); + drm_pci_free(dev, dma->bufs[i].seglist[j]); } free(dma->bufs[i].seglist, M_DRM); - free(dma->bufs[i].seglist_bus, M_DRM); } if (dma->bufs[i].buf_count) { for (j = 0; j < dma->bufs[i].buf_count; j++) { free(dma->bufs[i].buflist[j].dev_private, M_DRM); } free(dma->bufs[i].buflist, M_DRM); } } free(dma->buflist, M_DRM); free(dma->pagelist, M_DRM); free(dev->dma, M_DRM); dev->dma = NULL; DRM_SPINUNINIT(dev->dma_lock); } void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf) { if (!buf) return; buf->pending = 0; buf->filp = NULL; buf->used = 0; } void drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp) { drm_device_dma_t *dma = dev->dma; int i; if (!dma) return; for (i = 0; i < dma->buf_count; i++) { if (dma->buflist[i]->filp == filp) { switch (dma->buflist[i]->list) { case DRM_LIST_NONE: drm_free_buffer(dev, dma->buflist[i]); break; case DRM_LIST_WAIT: dma->buflist[i]->list = DRM_LIST_RECLAIM; break; default: /* Buffer already on hardware. */ break; } } } } /* Call into the driver-specific DMA handler */ int drm_dma(DRM_IOCTL_ARGS) { DRM_DEVICE; - if (dev->dma_ioctl) { - return dev->dma_ioctl(kdev, cmd, data, flags, p, filp); + if (dev->driver.dma_ioctl) { + return dev->driver.dma_ioctl(kdev, cmd, data, flags, p, filp); } else { DRM_DEBUG("DMA ioctl on driver with no dma handler\n"); return EINVAL; } } Index: head/sys/dev/drm/drm_drawable.c =================================================================== --- head/sys/dev/drm/drm_drawable.c (revision 152908) +++ head/sys/dev/drm/drm_drawable.c (revision 152909) @@ -1,52 +1,54 @@ /* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include "dev/drm/drmP.h" int drm_adddraw(DRM_IOCTL_ARGS) { drm_draw_t draw; draw.handle = 0; /* NOOP */ DRM_DEBUG("%d\n", draw.handle); DRM_COPY_TO_USER_IOCTL( (drm_draw_t *)data, draw, sizeof(draw) ); return 0; } int drm_rmdraw(DRM_IOCTL_ARGS) { return 0; /* NOOP */ } Index: head/sys/dev/drm/drm_drv.c =================================================================== --- head/sys/dev/drm/drm_drv.c (revision 152908) +++ head/sys/dev/drm/drm_drv.c (revision 152909) @@ -1,916 +1,937 @@ /* drm_drv.h -- Generic driver template -*- linux-c -*- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com */ /*- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" +#include "dev/drm/drm_sarea.h" int drm_debug_flag = 0; -static int drm_init(device_t nbdev); -static void drm_cleanup(drm_device_t *dev); +static int drm_load(drm_device_t *dev); +static void drm_unload(drm_device_t *dev); +static drm_pci_id_list_t *drm_find_description(int vendor, int device, + drm_pci_id_list_t *idlist); #ifdef __FreeBSD__ #define DRIVER_SOFTC(unit) \ ((drm_device_t *)devclass_get_softc(drm_devclass, unit)) MODULE_VERSION(drm, 1); MODULE_DEPEND(drm, agp, 1, 1, 1); MODULE_DEPEND(drm, pci, 1, 1, 1); #if __FreeBSD_version > 502127 MODULE_DEPEND(drm, mem, 1, 1, 1); #endif #endif /* __FreeBSD__ */ #if defined(__NetBSD__) || defined(__OpenBSD__) #define DRIVER_SOFTC(unit) \ ((drm_device_t *)device_lookup(&drm_cd, unit)) #endif /* __NetBSD__ || __OpenBSD__ */ static drm_ioctl_desc_t drm_ioctls[256] = { - [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_by_busid, 0, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { drm_getmap, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { drm_getclient, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { drm_getstats, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { drm_setversion, 0, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { drm_getmap, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { drm_getclient, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { drm_getstats, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { drm_setversion, DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_noop, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap_ioctl, DRM_AUTH }, - [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, DRM_AUTH }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, DRM_AUTH }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { drm_lock, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { drm_unlock, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_noop, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { drm_lock, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { drm_unlock, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_noop, DRM_AUTH }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { drm_dma, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, DRM_AUTH|DRM_MASTER }, + [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { drm_dma, DRM_AUTH }, - [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info_ioctl, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0 }, }; -const char *drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist); - #ifdef __FreeBSD__ static struct cdevsw drm_cdevsw = { #if __FreeBSD_version >= 502103 .d_version = D_VERSION, #endif .d_open = drm_open, .d_close = drm_close, .d_read = drm_read, .d_ioctl = drm_ioctl, .d_poll = drm_poll, .d_mmap = drm_mmap, .d_name = "drm", #if __FreeBSD_version >= 502103 .d_flags = D_TRACKCLOSE | D_NEEDGIANT, #else .d_maj = 145, .d_flags = D_TRACKCLOSE, #endif #if __FreeBSD_version < 500000 .d_bmaj = -1 #endif }; int drm_probe(device_t dev, drm_pci_id_list_t *idlist) { - const char *s = NULL; + drm_pci_id_list_t *id_entry; int vendor, device; vendor = pci_get_vendor(dev); device = pci_get_device(dev); - s = drm_find_description(vendor, device, idlist); - if (s != NULL) { - device_set_desc(dev, s); + id_entry = drm_find_description(vendor, device, idlist); + if (id_entry != NULL) { + device_set_desc(dev, id_entry->name); return 0; } return ENXIO; } -int drm_attach(device_t dev, drm_pci_id_list_t *idlist) +int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist) { - return drm_init(dev); + drm_device_t *dev; + drm_pci_id_list_t *id_entry; + int unit; + + unit = device_get_unit(nbdev); + dev = device_get_softc(nbdev); + + if (!strcmp(device_get_name(nbdev), "drmsub")) + dev->device = device_get_parent(nbdev); + else + dev->device = nbdev; + + dev->devnode = make_dev(&drm_cdevsw, + unit, + DRM_DEV_UID, + DRM_DEV_GID, + DRM_DEV_MODE, + "dri/card%d", unit); +#if __FreeBSD_version >= 500000 + mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF); +#endif + + id_entry = drm_find_description(pci_get_vendor(nbdev), + pci_get_device(nbdev), idlist); + dev->id_entry = id_entry; + + return drm_load(dev); } int drm_detach(device_t dev) { - drm_cleanup(device_get_softc(dev)); + drm_unload(device_get_softc(dev)); return 0; } #ifndef DRM_DEV_NAME #define DRM_DEV_NAME "drm" #endif devclass_t drm_devclass; #elif defined(__NetBSD__) || defined(__OpenBSD__) static struct cdevsw drm_cdevsw = { drm_open, drm_close, drm_read, nowrite, drm_ioctl, nostop, notty, drm_poll, drm_mmap, nokqfilter, D_TTY }; int drm_refcnt = 0; #if defined(__NetBSD__) && __NetBSD_Version__ >= 106080000 MOD_DEV("drm", DRIVER_NAME, NULL, -1, &drm_cdevsw, CDEV_MAJOR); #else MOD_DEV("drm", LM_DT_CHAR, CDEV_MAJOR, &drm_cdevsw); #endif int drm_lkmentry(struct lkm_table *lkmtp, int cmd, int ver); static int drm_lkmhandle(struct lkm_table *lkmtp, int cmd); -int drm_modprobe(); +int drm_modprobe(void); int drm_probe(struct pci_attach_args *pa); void drm_attach(struct pci_attach_args *pa, dev_t kdev); int drm_lkmentry(struct lkm_table *lkmtp, int cmd, int ver) { DISPATCH(lkmtp, cmd, ver, drm_lkmhandle, drm_lkmhandle, drm_lkmhandle); } static int drm_lkmhandle(struct lkm_table *lkmtp, int cmd) { - int j, error = 0; -#if defined(__NetBSD__) && (__NetBSD_Version__ > 106080000) - struct lkm_dev *args = lkmtp->private.lkm_dev; -#endif + int error = 0; switch(cmd) { case LKM_E_LOAD: if (lkmexists(lkmtp)) return EEXIST; if(drm_modprobe()) return 0; return 1; case LKM_E_UNLOAD: if (drm_refcnt > 0) return (EBUSY); break; case LKM_E_STAT: break; default: error = EIO; break; } return error; } -int drm_modprobe() { +int drm_modprobe(void) +{ struct pci_attach_args pa; int error; error = pci_find_device(&pa, drm_probe, idlist); if (error != 0) drm_attach(&pa, 0); return error; } int drm_probe(struct pci_attach_args *pa, drm_pci_id_list_t idlist) { const char *desc; + drm_pci_id_list_t *id_entry; - desc = drm_find_description(PCI_VENDOR(pa->pa_id), + id_entry = drm_find_description(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), idlist); - if (desc != NULL) { + if (id_entry != NULL) { return 1; } return 0; } void drm_attach(struct pci_attach_args *pa, dev_t kdev, drm_pci_id_list_t *idlist) { int i; drm_device_t *dev; + drm_pci_id_list_t *id_entry; config_makeroom(kdev, &drm_cd); drm_cd.cd_devs[(kdev)] = malloc(sizeof(drm_device_t), M_DRM, M_WAITOK); dev = DRIVER_SOFTC(kdev); memset(dev, 0, sizeof(drm_device_t)); memcpy(&dev->pa, pa, sizeof(dev->pa)); - DRM_INFO("%s", drm_find_description(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), idlist)); - drm_init(dev); + dev->irq = pa->pa_intrline; + dev->pci_domain = 0; + dev->pci_bus = pa->pa_bus; + dev->pci_slot = pa->pa_device; + dev->pci_func = pa->pa_function; + dev->dma_tag = pa->pa_dmat; + + id_entry = drm_find_description(PCI_VENDOR(pa->pa_id), + PCI_PRODUCT(pa->pa_id), idlist); + dev->driver.pci_id_entry = id_entry; + + DRM_INFO("%s", id_entry->name); + drm_load(dev); } int drm_detach(struct device *self, int flags) { - drm_cleanup((drm_device_t *)self); + drm_unload((drm_device_t *)self); return 0; } int drm_activate(struct device *self, enum devact act) { switch (act) { case DVACT_ACTIVATE: return (EOPNOTSUPP); break; case DVACT_DEACTIVATE: /* FIXME */ break; } return (0); } #endif /* __NetBSD__ || __OpenBSD__ */ -const char *drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist) { +drm_pci_id_list_t *drm_find_description(int vendor, int device, + drm_pci_id_list_t *idlist) +{ int i = 0; for (i = 0; idlist[i].vendor != 0; i++) { if ((idlist[i].vendor == vendor) && (idlist[i].device == device)) { - return idlist[i].name; + return &idlist[i]; } } return NULL; } -/* Initialize the DRM on first open. */ -static int drm_setup(drm_device_t *dev) +static int drm_firstopen(drm_device_t *dev) { + drm_local_map_t *map; int i; DRM_SPINLOCK_ASSERT(&dev->dev_lock); - if (dev->presetup) - dev->presetup(dev); + /* prebuild the SAREA */ + i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, + _DRM_CONTAINS_LOCK, &map); + if (i != 0) + return i; + if (dev->driver.firstopen) + dev->driver.firstopen(dev); + dev->buf_use = 0; - if (dev->use_dma) { + if (dev->driver.use_dma) { i = drm_dma_setup(dev); if (i != 0) return i; } dev->counters = 6; dev->types[0] = _DRM_STAT_LOCK; dev->types[1] = _DRM_STAT_OPENS; dev->types[2] = _DRM_STAT_CLOSES; dev->types[3] = _DRM_STAT_IOCTLS; dev->types[4] = _DRM_STAT_LOCKS; dev->types[5] = _DRM_STAT_UNLOCKS; for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ ) atomic_set( &dev->counts[i], 0 ); for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) { dev->magiclist[i].head = NULL; dev->magiclist[i].tail = NULL; } - dev->lock.hw_lock = NULL; dev->lock.lock_queue = 0; dev->irq_enabled = 0; dev->context_flag = 0; dev->last_context = 0; dev->if_version = 0; #ifdef __FreeBSD__ dev->buf_sigio = NULL; #elif defined(__NetBSD__) || defined(__OpenBSD__) dev->buf_pgid = 0; #endif DRM_DEBUG( "\n" ); - if (dev->postsetup) - dev->postsetup(dev); - return 0; } -/* Free resources associated with the DRM on the last close. */ -static int drm_takedown(drm_device_t *dev) +static int drm_lastclose(drm_device_t *dev) { drm_magic_entry_t *pt, *next; drm_local_map_t *map, *mapsave; int i; DRM_SPINLOCK_ASSERT(&dev->dev_lock); DRM_DEBUG( "\n" ); - if (dev->pretakedown != NULL) - dev->pretakedown(dev); + if (dev->driver.lastclose != NULL) + dev->driver.lastclose(dev); if (dev->irq_enabled) drm_irq_uninstall(dev); if ( dev->unique ) { free(dev->unique, M_DRM); dev->unique = NULL; dev->unique_len = 0; } /* Clear pid list */ for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) { for ( pt = dev->magiclist[i].head ; pt ; pt = next ) { next = pt->next; free(pt, M_DRM); } dev->magiclist[i].head = dev->magiclist[i].tail = NULL; } /* Clear AGP information */ if ( dev->agp ) { drm_agp_mem_t *entry; drm_agp_mem_t *nexte; - /* Remove AGP resources, but leave dev->agp - intact until drm_cleanup is called. */ + /* Remove AGP resources, but leave dev->agp intact until + * drm_unload is called. + */ for ( entry = dev->agp->memory ; entry ; entry = nexte ) { nexte = entry->next; if ( entry->bound ) drm_agp_unbind_memory(entry->handle); drm_agp_free_memory(entry->handle); free(entry, M_DRM); } dev->agp->memory = NULL; if (dev->agp->acquired) - drm_agp_do_release(); + drm_agp_release(dev); dev->agp->acquired = 0; dev->agp->enabled = 0; } if (dev->sg != NULL) { drm_sg_cleanup(dev->sg); dev->sg = NULL; } - /* Clean up maps that weren't set up by the driver. */ TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) { - if (!map->kernel_owned) - drm_remove_map(dev, map); + drm_rmmap(dev, map); } + drm_dma_takedown(dev); if ( dev->lock.hw_lock ) { dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.filp = NULL; DRM_WAKEUP_INT((void *)&dev->lock.lock_queue); } return 0; } -/* linux: drm_init is called via init_module at module load time, or via - * linux/init/main.c (this is not currently supported). - * bsd: drm_init is called via the attach function per device. - */ -static int drm_init(device_t nbdev) +static int drm_load(drm_device_t *dev) { - int unit; - drm_device_t *dev; int retcode; + DRM_DEBUG( "\n" ); -#ifdef __FreeBSD__ - unit = device_get_unit(nbdev); - dev = device_get_softc(nbdev); - - if (!strcmp(device_get_name(nbdev), "drmsub")) - dev->device = device_get_parent(nbdev); - else - dev->device = nbdev; - - dev->devnode = make_dev(&drm_cdevsw, - unit, - DRM_DEV_UID, - DRM_DEV_GID, - DRM_DEV_MODE, - "dri/card%d", unit); -#if __FreeBSD_version >= 500000 - mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF); -#endif -#elif defined(__NetBSD__) || defined(__OpenBSD__) - dev = nbdev; - unit = minor(dev->device.dv_unit); -#endif - dev->irq = pci_get_irq(dev->device); /* XXX Fix domain number (alpha hoses) */ dev->pci_domain = 0; dev->pci_bus = pci_get_bus(dev->device); dev->pci_slot = pci_get_slot(dev->device); dev->pci_func = pci_get_function(dev->device); TAILQ_INIT(&dev->maplist); drm_mem_init(); #ifdef __FreeBSD__ drm_sysctl_init(dev); #endif TAILQ_INIT(&dev->files); - if (dev->preinit != NULL) { - retcode = dev->preinit(dev, 0); + if (dev->driver.load != NULL) { + DRM_LOCK(); + retcode = dev->driver.load(dev, dev->id_entry->driver_private); + DRM_UNLOCK(); if (retcode != 0) goto error; } - if (dev->use_agp) { + if (dev->driver.use_agp) { if (drm_device_is_agp(dev)) dev->agp = drm_agp_init(); - if (dev->require_agp && dev->agp == NULL) { + if (dev->driver.require_agp && dev->agp == NULL) { DRM_ERROR("Card isn't AGP, or couldn't initialize " "AGP.\n"); retcode = DRM_ERR(ENOMEM); goto error; } if (dev->agp != NULL) { if (drm_mtrr_add(dev->agp->info.ai_aperture_base, dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0) dev->agp->mtrr = 1; } } retcode = drm_ctxbitmap_init(dev); if (retcode != 0) { DRM_ERROR("Cannot allocate memory for context bitmap.\n"); goto error; } - DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n", - dev->driver_name, - dev->driver_major, - dev->driver_minor, - dev->driver_patchlevel, - dev->driver_date, - unit ); + DRM_INFO("Initialized %s %d.%d.%d %s\n", + dev->driver.name, + dev->driver.major, + dev->driver.minor, + dev->driver.patchlevel, + dev->driver.date); - if (dev->postinit != NULL) - dev->postinit(dev, 0); - return 0; error: #ifdef __FreeBSD__ drm_sysctl_cleanup(dev); #endif DRM_LOCK(); - drm_takedown(dev); + drm_lastclose(dev); DRM_UNLOCK(); #ifdef __FreeBSD__ destroy_dev(dev->devnode); #if __FreeBSD_version >= 500000 mtx_destroy(&dev->dev_lock); #endif #endif return retcode; } -/* linux: drm_cleanup is called via cleanup_module at module unload time. - * bsd: drm_cleanup is called per device at module unload time. - * FIXME: NetBSD - */ -static void drm_cleanup(drm_device_t *dev) +static void drm_unload(drm_device_t *dev) { - drm_local_map_t *map; + int i; DRM_DEBUG( "\n" ); #ifdef __FreeBSD__ drm_sysctl_cleanup(dev); destroy_dev(dev->devnode); #endif drm_ctxbitmap_cleanup(dev); if (dev->agp && dev->agp->mtrr) { int __unused retcode; - retcode = drm_mtrr_del(dev->agp->info.ai_aperture_base, + retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base, dev->agp->info.ai_aperture_size, DRM_MTRR_WC); DRM_DEBUG("mtrr_del = %d", retcode); } DRM_LOCK(); - drm_takedown(dev); + drm_lastclose(dev); DRM_UNLOCK(); - /* Clean up any maps left over that had been allocated by the driver. */ - while ((map = TAILQ_FIRST(&dev->maplist)) != NULL) { - drm_remove_map(dev, map); + /* Clean up PCI resources allocated by drm_bufs.c. We're not really + * worried about resource consumption while the DRM is inactive (between + * lastclose and firstopen or unload) because these aren't actually + * taking up KVA, just keeping the PCI resource allocated. + */ + for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) { + if (dev->pcir[i] == NULL) + continue; + bus_release_resource(dev->device, SYS_RES_MEMORY, + dev->pcirid[i], dev->pcir[i]); + dev->pcir[i] = NULL; } if ( dev->agp ) { - drm_agp_uninit(); free(dev->agp, M_DRM); dev->agp = NULL; } - if (dev->postcleanup != NULL) - dev->postcleanup(dev); + if (dev->driver.unload != NULL) + dev->driver.unload(dev); drm_mem_uninit(); #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 mtx_destroy(&dev->dev_lock); #endif } int drm_version(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_version_t version; int len; DRM_COPY_FROM_USER_IOCTL( version, (drm_version_t *)data, sizeof(version) ); #define DRM_COPY( name, value ) \ len = strlen( value ); \ if ( len > name##_len ) len = name##_len; \ name##_len = strlen( value ); \ if ( len && name ) { \ if ( DRM_COPY_TO_USER( name, value, len ) ) \ return DRM_ERR(EFAULT); \ } - version.version_major = dev->driver_major; - version.version_minor = dev->driver_minor; - version.version_patchlevel = dev->driver_patchlevel; + version.version_major = dev->driver.major; + version.version_minor = dev->driver.minor; + version.version_patchlevel = dev->driver.patchlevel; - DRM_COPY(version.name, dev->driver_name); - DRM_COPY(version.date, dev->driver_date); - DRM_COPY(version.desc, dev->driver_desc); + DRM_COPY(version.name, dev->driver.name); + DRM_COPY(version.date, dev->driver.date); + DRM_COPY(version.desc, dev->driver.desc); DRM_COPY_TO_USER_IOCTL( (drm_version_t *)data, version, sizeof(version) ); return 0; } int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p) { drm_device_t *dev = NULL; int retcode = 0; dev = DRIVER_SOFTC(minor(kdev)); DRM_DEBUG( "open_count = %d\n", dev->open_count ); retcode = drm_open_helper(kdev, flags, fmt, p, dev); if ( !retcode ) { atomic_inc( &dev->counts[_DRM_STAT_OPENS] ); DRM_LOCK(); #ifdef __FreeBSD__ device_busy(dev->device); #endif if ( !dev->open_count++ ) - retcode = drm_setup(dev); + retcode = drm_firstopen(dev); DRM_UNLOCK(); } return retcode; } int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p) { drm_file_t *priv; DRM_DEVICE; int retcode = 0; DRMFILE filp = (void *)(uintptr_t)(DRM_CURRENTPID); DRM_DEBUG( "open_count = %d\n", dev->open_count ); DRM_LOCK(); priv = drm_find_file_by_proc(dev, p); if (!priv) { DRM_UNLOCK(); DRM_ERROR("can't find authenticator\n"); return EINVAL; } - if (dev->prerelease != NULL) - dev->prerelease(dev, filp); + if (dev->driver.preclose != NULL) + dev->driver.preclose(dev, filp); /* ======================================================== * Begin inline drm_release */ #ifdef __FreeBSD__ DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n", DRM_CURRENTPID, (long)dev->device, dev->open_count ); #elif defined(__NetBSD__) || defined(__OpenBSD__) DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n", DRM_CURRENTPID, (long)&dev->device, dev->open_count); #endif if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && dev->lock.filp == filp) { DRM_DEBUG("Process %d dead, freeing lock for context %d\n", DRM_CURRENTPID, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); - if (dev->release != NULL) - dev->release(dev, filp); + if (dev->driver.reclaim_buffers_locked != NULL) + dev->driver.reclaim_buffers_locked(dev, filp); drm_lock_free(dev, &dev->lock.hw_lock->lock, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); /* FIXME: may require heavy-handed reset of hardware at this point, possibly processed via a callback to the X server. */ - } else if (dev->release != NULL && dev->lock.hw_lock != NULL) { + } else if (dev->driver.reclaim_buffers_locked != NULL && + dev->lock.hw_lock != NULL) { /* The lock is required to reclaim buffers */ for (;;) { if ( !dev->lock.hw_lock ) { /* Device has been unregistered */ retcode = DRM_ERR(EINTR); break; } if (drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { dev->lock.filp = filp; dev->lock.lock_time = jiffies; atomic_inc( &dev->counts[_DRM_STAT_LOCKS] ); break; /* Got lock */ } /* Contention */ #if defined(__FreeBSD__) && __FreeBSD_version > 500000 retcode = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0); #else retcode = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH, "drmlk2", 0); #endif if (retcode) break; } if (retcode == 0) { - dev->release(dev, filp); + dev->driver.reclaim_buffers_locked(dev, filp); drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); } } - if (dev->use_dma) - drm_reclaim_buffers(dev, (void *)(uintptr_t)priv->pid); + if (dev->driver.use_dma && !dev->driver.reclaim_buffers_locked) + drm_reclaim_buffers(dev, filp); #if defined (__FreeBSD__) && (__FreeBSD_version >= 500000) funsetown(&dev->buf_sigio); #elif defined(__FreeBSD__) funsetown(dev->buf_sigio); #elif defined(__NetBSD__) || defined(__OpenBSD__) dev->buf_pgid = 0; #endif /* __NetBSD__ || __OpenBSD__ */ if (--priv->refs == 0) { - if (dev->free_filp_priv != NULL) - dev->free_filp_priv(dev, priv); + if (dev->driver.postclose != NULL) + dev->driver.postclose(dev, priv); TAILQ_REMOVE(&dev->files, priv, link); free(priv, M_DRM); } /* ======================================================== * End inline drm_release */ atomic_inc( &dev->counts[_DRM_STAT_CLOSES] ); #ifdef __FreeBSD__ device_unbusy(dev->device); #endif if (--dev->open_count == 0) { - retcode = drm_takedown(dev); + retcode = drm_lastclose(dev); } DRM_UNLOCK(); return retcode; } /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p) { DRM_DEVICE; int retcode = 0; drm_ioctl_desc_t *ioctl; int (*func)(DRM_IOCTL_ARGS); int nr = DRM_IOCTL_NR(cmd); int is_driver_ioctl = 0; drm_file_t *priv; DRMFILE filp = (DRMFILE)(uintptr_t)DRM_CURRENTPID; DRM_LOCK(); priv = drm_find_file_by_proc(dev, p); DRM_UNLOCK(); if (priv == NULL) { DRM_ERROR("can't find authenticator\n"); return EINVAL; } atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] ); ++priv->ioctl_count; #ifdef __FreeBSD__ DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n", DRM_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated ); #elif defined(__NetBSD__) || defined(__OpenBSD__) DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n", DRM_CURRENTPID, cmd, nr, (long)&dev->device, priv->authenticated ); #endif switch (cmd) { case FIONBIO: case FIOASYNC: return 0; #ifdef __FreeBSD__ case FIOSETOWN: return fsetown(*(int *)data, &dev->buf_sigio); case FIOGETOWN: #if (__FreeBSD_version >= 500000) *(int *) data = fgetown(&dev->buf_sigio); #else *(int *) data = fgetown(dev->buf_sigio); #endif return 0; #endif /* __FreeBSD__ */ #if defined(__NetBSD__) || defined(__OpenBSD__) case TIOCSPGRP: dev->buf_pgid = *(int *)data; return 0; case TIOCGPGRP: *(int *)data = dev->buf_pgid; return 0; #endif /* __NetBSD__ */ } if (IOCGROUP(cmd) != DRM_IOCTL_BASE) { DRM_DEBUG("Bad ioctl group 0x%x\n", (int)IOCGROUP(cmd)); return EINVAL; } ioctl = &drm_ioctls[nr]; /* It's not a core DRM ioctl, try driver-specific. */ if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) { /* The array entries begin at DRM_COMMAND_BASE ioctl nr */ nr -= DRM_COMMAND_BASE; - if (nr > dev->max_driver_ioctl) { + if (nr > dev->driver.max_ioctl) { DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n", - nr, dev->max_driver_ioctl); + nr, dev->driver.max_ioctl); return EINVAL; } - ioctl = &dev->driver_ioctls[nr]; + ioctl = &dev->driver.ioctls[nr]; is_driver_ioctl = 1; } func = ioctl->func; if (func == NULL) { DRM_DEBUG( "no function\n" ); return EINVAL; } - if ((ioctl->root_only && DRM_SUSER(p)) || (ioctl->auth_needed && - !priv->authenticated)) + /* ioctl->master check should be against something in the filp set up + * for the first opener, but it doesn't matter yet. + */ + if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) || + ((ioctl->flags & DRM_AUTH) && !priv->authenticated) || + ((ioctl->flags & DRM_MASTER) && !priv->master)) return EACCES; if (is_driver_ioctl) DRM_LOCK(); retcode = func(kdev, cmd, data, flags, p, filp); if (is_driver_ioctl) DRM_UNLOCK(); if (retcode != 0) DRM_DEBUG(" returning %d\n", retcode); return DRM_ERR(retcode); } #if DRM_LINUX #include MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1); #define LINUX_IOCTL_DRM_MIN 0x6400 #define LINUX_IOCTL_DRM_MAX 0x64ff static linux_ioctl_function_t drm_linux_ioctl; static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX}; SYSINIT(drm_register, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &drm_handler); SYSUNINIT(drm_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &drm_handler); /* The bits for in/out are switched on Linux */ #define LINUX_IOC_IN IOC_OUT #define LINUX_IOC_OUT IOC_IN static int drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args) { int error; int cmd = args->cmd; args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT); if (cmd & LINUX_IOC_IN) args->cmd |= IOC_IN; if (cmd & LINUX_IOC_OUT) args->cmd |= IOC_OUT; error = ioctl(p, (struct ioctl_args *)args); return error; } #endif /* DRM_LINUX */ Index: head/sys/dev/drm/drm_fops.c =================================================================== --- head/sys/dev/drm/drm_fops.c (revision 152908) +++ head/sys/dev/drm/drm_fops.c (revision 152909) @@ -1,124 +1,131 @@ /* drm_fops.h -- File operations for DRM -*- linux-c -*- * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Daryll Strauss * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" drm_file_t *drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p) { #if __FreeBSD_version >= 500021 uid_t uid = p->td_ucred->cr_svuid; pid_t pid = p->td_proc->p_pid; #else uid_t uid = p->p_cred->p_svuid; pid_t pid = p->p_pid; #endif drm_file_t *priv; DRM_SPINLOCK_ASSERT(&dev->dev_lock); TAILQ_FOREACH(priv, &dev->files, link) if (priv->pid == pid && priv->uid == uid) return priv; return NULL; } /* drm_open_helper is called whenever a process opens /dev/drm. */ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p, drm_device_t *dev) { int m = minor(kdev); drm_file_t *priv; int retcode; if (flags & O_EXCL) return EBUSY; /* No exclusive opens */ dev->flags = flags; DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m); DRM_LOCK(); priv = drm_find_file_by_proc(dev, p); if (priv) { priv->refs++; } else { priv = malloc(sizeof(*priv), M_DRM, M_NOWAIT | M_ZERO); if (priv == NULL) { DRM_UNLOCK(); return DRM_ERR(ENOMEM); } #if __FreeBSD_version >= 500000 priv->uid = p->td_ucred->cr_svuid; priv->pid = p->td_proc->p_pid; #else priv->uid = p->p_cred->p_svuid; priv->pid = p->p_pid; #endif priv->refs = 1; priv->minor = m; priv->ioctl_count = 0; - priv->authenticated = !DRM_SUSER(p); - if (dev->open_helper) { - retcode = dev->open_helper(dev, priv); + /* for compatibility root is always authenticated */ + priv->authenticated = DRM_SUSER(p); + + if (dev->driver.open) { + retcode = dev->driver.open(dev, priv); if (retcode != 0) { free(priv, M_DRM); DRM_UNLOCK(); return retcode; } } + + /* first opener automatically becomes master */ + priv->master = TAILQ_EMPTY(&dev->files); TAILQ_INSERT_TAIL(&dev->files, priv, link); } DRM_UNLOCK(); #ifdef __FreeBSD__ kdev->si_drv1 = dev; #endif return 0; } /* The drm_read and drm_poll are stubs to prevent spurious errors * on older X Servers (4.3.0 and earlier) */ int drm_read(struct cdev *kdev, struct uio *uio, int ioflag) { return 0; } int drm_poll(struct cdev *kdev, int events, DRM_STRUCTPROC *p) { return 0; } Index: head/sys/dev/drm/drm_ioctl.c =================================================================== --- head/sys/dev/drm/drm_ioctl.c (revision 152908) +++ head/sys/dev/drm/drm_ioctl.c (revision 152909) @@ -1,297 +1,299 @@ /* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*- * Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" /* * Beginning in revision 1.1 of the DRM interface, getunique will return * a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function) * before setunique has been called. The format for the bus-specific part of * the unique is not defined for any other bus. */ int drm_getunique(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_unique_t u; DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) ); if (u.unique_len >= dev->unique_len) { if (DRM_COPY_TO_USER(u.unique, dev->unique, dev->unique_len)) return DRM_ERR(EFAULT); } u.unique_len = dev->unique_len; DRM_COPY_TO_USER_IOCTL( (drm_unique_t *)data, u, sizeof(u) ); return 0; } /* Deprecated in DRM version 1.1, and will return EBUSY when setversion has * requested version 1.1 or greater. */ int drm_setunique(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_unique_t u; int domain, bus, slot, func, ret; char *busid; DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) ); /* Check and copy in the submitted Bus ID */ if (!u.unique_len || u.unique_len > 1024) return DRM_ERR(EINVAL); busid = malloc(u.unique_len + 1, M_DRM, M_WAITOK); if (busid == NULL) return DRM_ERR(ENOMEM); if (DRM_COPY_FROM_USER(busid, u.unique, u.unique_len)) { free(busid, M_DRM); return DRM_ERR(EFAULT); } busid[u.unique_len] = '\0'; /* Return error if the busid submitted doesn't match the device's actual * busid. */ ret = sscanf(busid, "PCI:%d:%d:%d", &bus, &slot, &func); if (ret != 3) { free(busid, M_DRM); return DRM_ERR(EINVAL); } domain = bus >> 8; bus &= 0xff; if ((domain != dev->pci_domain) || (bus != dev->pci_bus) || (slot != dev->pci_slot) || (func != dev->pci_func)) { free(busid, M_DRM); return DRM_ERR(EINVAL); } /* Actually set the device's busid now. */ DRM_LOCK(); if (dev->unique_len || dev->unique) { DRM_UNLOCK(); return DRM_ERR(EBUSY); } dev->unique_len = u.unique_len; dev->unique = busid; DRM_UNLOCK(); return 0; } static int drm_set_busid(drm_device_t *dev) { DRM_LOCK(); if (dev->unique != NULL) { DRM_UNLOCK(); return EBUSY; } dev->unique_len = 20; dev->unique = malloc(dev->unique_len + 1, M_DRM, M_NOWAIT); if (dev->unique == NULL) { DRM_UNLOCK(); return ENOMEM; } snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x", dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func); DRM_UNLOCK(); return 0; } int drm_getmap(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_map_t map; drm_local_map_t *mapinlist; int idx; int i = 0; DRM_COPY_FROM_USER_IOCTL( map, (drm_map_t *)data, sizeof(map) ); idx = map.offset; DRM_LOCK(); if (idx < 0) { DRM_UNLOCK(); return DRM_ERR(EINVAL); } TAILQ_FOREACH(mapinlist, &dev->maplist, link) { if (i==idx) { map.offset = mapinlist->offset; map.size = mapinlist->size; map.type = mapinlist->type; map.flags = mapinlist->flags; map.handle = mapinlist->handle; map.mtrr = mapinlist->mtrr; break; } i++; } DRM_UNLOCK(); if (mapinlist == NULL) return EINVAL; DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) ); return 0; } int drm_getclient(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_client_t client; drm_file_t *pt; int idx; int i = 0; DRM_COPY_FROM_USER_IOCTL( client, (drm_client_t *)data, sizeof(client) ); idx = client.idx; DRM_LOCK(); TAILQ_FOREACH(pt, &dev->files, link) { if (i==idx) { client.auth = pt->authenticated; client.pid = pt->pid; client.uid = pt->uid; client.magic = pt->magic; client.iocs = pt->ioctl_count; DRM_UNLOCK(); *(drm_client_t *)data = client; return 0; } i++; } DRM_UNLOCK(); DRM_COPY_TO_USER_IOCTL( (drm_client_t *)data, client, sizeof(client) ); return 0; } int drm_getstats(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_stats_t stats; int i; memset(&stats, 0, sizeof(stats)); DRM_LOCK(); for (i = 0; i < dev->counters; i++) { if (dev->types[i] == _DRM_STAT_LOCK) stats.data[i].value = (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0); else stats.data[i].value = atomic_read(&dev->counts[i]); stats.data[i].type = dev->types[i]; } stats.count = dev->counters; DRM_UNLOCK(); DRM_COPY_TO_USER_IOCTL( (drm_stats_t *)data, stats, sizeof(stats) ); return 0; } #define DRM_IF_MAJOR 1 #define DRM_IF_MINOR 2 int drm_setversion(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_set_version_t sv; drm_set_version_t retv; int if_version; DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv)); retv.drm_di_major = DRM_IF_MAJOR; retv.drm_di_minor = DRM_IF_MINOR; - retv.drm_dd_major = dev->driver_major; - retv.drm_dd_minor = dev->driver_minor; + retv.drm_dd_major = dev->driver.major; + retv.drm_dd_minor = dev->driver.minor; DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv)); if (sv.drm_di_major != -1) { if (sv.drm_di_major != DRM_IF_MAJOR || sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR) return EINVAL; if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor); dev->if_version = DRM_MAX(if_version, dev->if_version); if (sv.drm_di_minor >= 1) { /* * Version 1.1 includes tying of DRM to specific device */ drm_set_busid(dev); } } if (sv.drm_dd_major != -1) { - if (sv.drm_dd_major != dev->driver_major || - sv.drm_dd_minor < 0 || sv.drm_dd_minor > dev->driver_minor) + if (sv.drm_dd_major != dev->driver.major || + sv.drm_dd_minor < 0 || sv.drm_dd_minor > dev->driver.minor) return EINVAL; } return 0; } int drm_noop(DRM_IOCTL_ARGS) { DRM_DEBUG("\n"); return 0; } Index: head/sys/dev/drm/drm_irq.c =================================================================== --- head/sys/dev/drm/drm_irq.c (revision 152908) +++ head/sys/dev/drm/drm_irq.c (revision 152909) @@ -1,285 +1,294 @@ -/* drm_dma.c -- DMA IOCTL and function support +/* drm_irq.c -- IRQ IOCTL and function support * Created: Fri Oct 18 2003 by anholt@FreeBSD.org */ /*- * Copyright 2003 Eric Anholt * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Eric Anholt * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" int drm_irq_by_busid(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_irq_busid_t irq; DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq)); if ((irq.busnum >> 8) != dev->pci_domain || (irq.busnum & 0xff) != dev->pci_bus || irq.devnum != dev->pci_slot || irq.funcnum != dev->pci_func) return EINVAL; irq.irq = dev->irq; DRM_DEBUG("%d:%d:%d => IRQ %d\n", irq.busnum, irq.devnum, irq.funcnum, irq.irq); DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) ); return 0; } #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 static irqreturn_t drm_irq_handler_wrap(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *)arg; DRM_SPINLOCK(&dev->irq_lock); - dev->irq_handler(arg); + dev->driver.irq_handler(arg); DRM_SPINUNLOCK(&dev->irq_lock); } #endif int drm_irq_install(drm_device_t *dev) { int retcode; +#ifdef __NetBSD__ + pci_intr_handle_t ih; +#endif if (dev->irq == 0 || dev->dev_private == NULL) return DRM_ERR(EINVAL); DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); DRM_LOCK(); if (dev->irq_enabled) { DRM_UNLOCK(); return DRM_ERR(EBUSY); } dev->irq_enabled = 1; dev->context_flag = 0; DRM_SPININIT(dev->irq_lock, "DRM IRQ lock"); /* Before installing handler */ - dev->irq_preinstall(dev); + dev->driver.irq_preinstall(dev); DRM_UNLOCK(); /* Install handler */ #ifdef __FreeBSD__ dev->irqrid = 0; dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, &dev->irqrid, RF_SHAREABLE); if (!dev->irqr) { retcode = ENOENT; goto err; } #if __FreeBSD_version < 500000 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY, dev->irq_handler, dev, &dev->irqh); #else retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE, drm_irq_handler_wrap, dev, &dev->irqh); #endif if (retcode != 0) goto err; #elif defined(__NetBSD__) || defined(__OpenBSD__) - if (pci_intr_map(&dev->pa, &dev->ih) != 0) { + if (pci_intr_map(&dev->pa, &ih) != 0) { retcode = ENOENT; goto err; } - dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY, - (irqreturn_t (*)(DRM_IRQ_ARGS))dev->irq_handler, dev); + dev->irqh = pci_intr_establish(&dev->pa.pa_pc, ih, IPL_TTY, + (irqreturn_t (*)(void *))dev->irq_handler, dev); if (!dev->irqh) { retcode = ENOENT; goto err; } #endif /* After installing handler */ DRM_LOCK(); - dev->irq_postinstall(dev); + dev->driver.irq_postinstall(dev); DRM_UNLOCK(); return 0; err: DRM_LOCK(); dev->irq_enabled = 0; #ifdef ___FreeBSD__ if (dev->irqrid != 0) { bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr); dev->irqrid = 0; } #endif DRM_SPINUNINIT(dev->irq_lock); DRM_UNLOCK(); return retcode; } int drm_irq_uninstall(drm_device_t *dev) { +#ifdef __FreeBSD__ int irqrid; +#endif if (!dev->irq_enabled) return DRM_ERR(EINVAL); dev->irq_enabled = 0; +#ifdef __FreeBSD__ irqrid = dev->irqrid; dev->irqrid = 0; +#endif DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); - dev->irq_uninstall(dev); + dev->driver.irq_uninstall(dev); #ifdef __FreeBSD__ DRM_UNLOCK(); bus_teardown_intr(dev->device, dev->irqr, dev->irqh); bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr); DRM_LOCK(); #elif defined(__NetBSD__) || defined(__OpenBSD__) pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh); #endif DRM_SPINUNINIT(dev->irq_lock); return 0; } int drm_control(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_control_t ctl; int err; DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) ); switch ( ctl.func ) { case DRM_INST_HANDLER: /* Handle drivers whose DRM used to require IRQ setup but the * no longer does. */ - if (!dev->use_irq) + if (!dev->driver.use_irq) return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && ctl.irq != dev->irq) return DRM_ERR(EINVAL); return drm_irq_install(dev); case DRM_UNINST_HANDLER: - if (!dev->use_irq) + if (!dev->driver.use_irq) return 0; DRM_LOCK(); err = drm_irq_uninstall(dev); DRM_UNLOCK(); return err; default: return DRM_ERR(EINVAL); } } int drm_wait_vblank(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_wait_vblank_t vblwait; struct timeval now; int ret; if (!dev->irq_enabled) return DRM_ERR(EINVAL); DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data, sizeof(vblwait) ); if (vblwait.request.type & _DRM_VBLANK_RELATIVE) { vblwait.request.sequence += atomic_read(&dev->vbl_received); vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; } flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; if (flags & _DRM_VBLANK_SIGNAL) { #if 0 /* disabled */ drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM, M_NOWAIT | M_ZERO); if (vbl_sig == NULL) return ENOMEM; vbl_sig->sequence = vblwait.request.sequence; vbl_sig->signo = vblwait.request.signal; vbl_sig->pid = DRM_CURRENTPID; vblwait.reply.sequence = atomic_read(&dev->vbl_received); DRM_SPINLOCK(&dev->irq_lock); TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); DRM_SPINUNLOCK(&dev->irq_lock); ret = 0; #endif ret = EINVAL; } else { DRM_LOCK(); - ret = dev->vblank_wait(dev, &vblwait.request.sequence); + ret = dev->driver.vblank_wait(dev, &vblwait.request.sequence); DRM_UNLOCK(); microtime(&now); vblwait.reply.tval_sec = now.tv_sec; vblwait.reply.tval_usec = now.tv_usec; } DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, sizeof(vblwait) ); return ret; } void drm_vbl_send_signals(drm_device_t *dev) { } #if 0 /* disabled */ void drm_vbl_send_signals( drm_device_t *dev ) { drm_vbl_sig_t *vbl_sig; unsigned int vbl_seq = atomic_read( &dev->vbl_received ); struct proc *p; vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); while (vbl_sig != NULL) { drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { p = pfind(vbl_sig->pid); if (p != NULL) psignal(p, vbl_sig->signo); TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); DRM_FREE(vbl_sig,sizeof(*vbl_sig)); } vbl_sig = next; } } #endif Index: head/sys/dev/drm/drm_linux_list.h =================================================================== --- head/sys/dev/drm/drm_linux_list.h (revision 152908) +++ head/sys/dev/drm/drm_linux_list.h (revision 152909) @@ -1,72 +1,74 @@ /* drm_linux_list.h -- linux list functions for the BSDs. * Created: Mon Apr 7 14:30:16 1999 by anholt@FreeBSD.org */ /*- * Copyright 2003 Eric Anholt * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Eric Anholt * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); struct list_head { struct list_head *next, *prev; }; /* Cheat, assume the list_head is at the start of the struct */ #define list_entry(entry, type, member) (type *)(entry) static __inline__ void INIT_LIST_HEAD(struct list_head *head) { (head)->next = head; (head)->prev = head; } static __inline__ int list_empty(struct list_head *head) { return (head)->next == head; } static __inline__ void list_add_tail(struct list_head *entry, struct list_head *head) { (entry)->prev = (head)->prev; (entry)->next = head; (head)->prev->next = entry; (head)->prev = entry; } static __inline__ void list_del(struct list_head *entry) { (entry)->next->prev = (entry)->prev; (entry)->prev->next = (entry)->next; } #define list_for_each(entry, head) \ for (entry = (head)->next; entry != head; entry = (entry)->next) #define list_for_each_safe(entry, temp, head) \ for (entry = (head)->next, temp = (entry)->next; \ temp != head; \ entry = temp, temp = temp->next) Index: head/sys/dev/drm/drm_lock.c =================================================================== --- head/sys/dev/drm/drm_lock.c (revision 152908) +++ head/sys/dev/drm/drm_lock.c (revision 152909) @@ -1,177 +1,180 @@ /* lock.c -- IOCTLs for locking -*- linux-c -*- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context) { unsigned int old, new; do { old = *lock; if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT; else new = context | _DRM_LOCK_HELD; } while (!atomic_cmpset_int(lock, old, new)); if (_DRM_LOCKING_CONTEXT(old) == context) { if (old & _DRM_LOCK_HELD) { if (context != DRM_KERNEL_CONTEXT) { DRM_ERROR("%d holds heavyweight lock\n", context); } return 0; } } if (new == (context | _DRM_LOCK_HELD)) { /* Have lock */ return 1; } return 0; } /* This takes a lock forcibly and hands it to context. Should ONLY be used inside *_unlock to give lock to kernel before calling *_dma_schedule. */ int drm_lock_transfer(drm_device_t *dev, __volatile__ unsigned int *lock, unsigned int context) { unsigned int old, new; dev->lock.filp = NULL; do { old = *lock; new = context | _DRM_LOCK_HELD; } while (!atomic_cmpset_int(lock, old, new)); return 1; } int drm_lock_free(drm_device_t *dev, __volatile__ unsigned int *lock, unsigned int context) { unsigned int old, new; dev->lock.filp = NULL; do { old = *lock; new = 0; } while (!atomic_cmpset_int(lock, old, new)); if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) { DRM_ERROR("%d freed heavyweight lock held by %d\n", context, _DRM_LOCKING_CONTEXT(old)); return 1; } DRM_WAKEUP_INT((void *)&dev->lock.lock_queue); return 0; } int drm_lock(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_lock_t lock; int ret = 0; DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock)); if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", DRM_CURRENTPID, lock.context); return EINVAL; } DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock, lock.flags); - if (dev->use_dma_queue && lock.context < 0) + if (dev->driver.use_dma_queue && lock.context < 0) return EINVAL; DRM_LOCK(); for (;;) { if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) { dev->lock.filp = (void *)(uintptr_t)DRM_CURRENTPID; dev->lock.lock_time = jiffies; atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); break; /* Got lock */ } /* Contention */ #if defined(__FreeBSD__) && __FreeBSD_version > 500000 ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0); #else ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH, "drmlk2", 0); #endif if (ret != 0) break; } DRM_UNLOCK(); DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); if (ret != 0) return ret; /* XXX: Add signal blocking here */ - if (dev->dma_quiescent != NULL && (lock.flags & _DRM_LOCK_QUIESCENT)) - dev->dma_quiescent(dev); + if (dev->driver.dma_quiescent != NULL && + (lock.flags & _DRM_LOCK_QUIESCENT)) + dev->driver.dma_quiescent(dev); return 0; } int drm_unlock(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_lock_t lock; DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock)); if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", DRM_CURRENTPID, lock.context); return EINVAL; } atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); DRM_LOCK(); drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { DRM_ERROR("\n"); } DRM_UNLOCK(); return 0; } Index: head/sys/dev/drm/drm_memory.c =================================================================== --- head/sys/dev/drm/drm_memory.c (revision 152908) +++ head/sys/dev/drm/drm_memory.c (revision 152909) @@ -1,155 +1,157 @@ /* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*- * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com */ /*- *Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" MALLOC_DEFINE(M_DRM, "drm", "DRM Data Structures"); void drm_mem_init(void) { #if defined(__NetBSD__) || defined(__OpenBSD__) malloc_type_attach(M_DRM); #endif } void drm_mem_uninit(void) { } void *drm_alloc(size_t size, int area) { return malloc(size, M_DRM, M_NOWAIT); } void *drm_calloc(size_t nmemb, size_t size, int area) { return malloc(size * nmemb, M_DRM, M_NOWAIT | M_ZERO); } void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) { void *pt; pt = malloc(size, M_DRM, M_NOWAIT); if (pt == NULL) return NULL; if (oldpt && oldsize) { memcpy(pt, oldpt, oldsize); free(oldpt, M_DRM); } return pt; } void drm_free(void *pt, size_t size, int area) { free(pt, M_DRM); } void *drm_ioremap(drm_device_t *dev, drm_local_map_t *map) { #ifdef __FreeBSD__ return pmap_mapdev(map->offset, map->size); #elif defined(__NetBSD__) || defined(__OpenBSD__) map->bst = dev->pa.pa_memt; if (bus_space_map(map->bst, map->offset, map->size, BUS_SPACE_MAP_LINEAR, &map->bsh)) return NULL; return bus_space_vaddr(map->bst, map->bsh); #endif } void drm_ioremapfree(drm_local_map_t *map) { #ifdef __FreeBSD__ pmap_unmapdev((vm_offset_t) map->handle, map->size); #elif defined(__NetBSD__) || defined(__OpenBSD__) bus_space_unmap(map->bst, map->bsh, map->size); #endif } #ifdef __FreeBSD__ int drm_mtrr_add(unsigned long offset, size_t size, int flags) { int act; struct mem_range_desc mrdesc; mrdesc.mr_base = offset; mrdesc.mr_len = size; mrdesc.mr_flags = flags; act = MEMRANGE_SET_UPDATE; strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner)); return mem_range_attr_set(&mrdesc, &act); } int -drm_mtrr_del(unsigned long offset, size_t size, int flags) +drm_mtrr_del(int __unused handle, unsigned long offset, size_t size, int flags) { int act; struct mem_range_desc mrdesc; mrdesc.mr_base = offset; mrdesc.mr_len = size; mrdesc.mr_flags = flags; act = MEMRANGE_SET_REMOVE; strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner)); return mem_range_attr_set(&mrdesc, &act); } #elif defined(__NetBSD__) || defined(__OpenBSD__) int drm_mtrr_add(unsigned long offset, size_t size, int flags) { struct mtrr mtrrmap; int one = 1; mtrrmap.base = offset; mtrrmap.len = size; mtrrmap.type = flags; mtrrmap.flags = MTRR_VALID; return mtrr_set(&mtrrmap, &one, NULL, MTRR_GETSET_KERNEL); } int drm_mtrr_del(unsigned long offset, size_t size, int flags) { struct mtrr mtrrmap; int one = 1; mtrrmap.base = offset; mtrrmap.len = size; mtrrmap.type = flags; mtrrmap.flags = 0; return mtrr_set(&mtrrmap, &one, NULL, MTRR_GETSET_KERNEL); } #endif Index: head/sys/dev/drm/drm_pci.c =================================================================== --- head/sys/dev/drm/drm_pci.c (revision 152908) +++ head/sys/dev/drm/drm_pci.c (revision 152909) @@ -1,69 +1,144 @@ /** * \file drm_pci.h * \brief PCI consistent, DMA-accessible memory functions. * * \author Eric Anholt */ /*- * Copyright 2003 Eric Anholt. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" /**********************************************************************/ /** \name PCI memory */ /*@{*/ +#if defined(__FreeBSD__) +static void +drm_pci_busdma_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + drm_dma_handle_t *dmah = arg; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("drm_pci_busdma_callback: bad dma segment count")); + dmah->busaddr = segs[0].ds_addr; +} +#endif + /** * \brief Allocate a physically contiguous DMA-accessible consistent * memory block. */ -void * -drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr, - dma_addr_t *busaddr) +drm_dma_handle_t * +drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr) { - void *vaddr; + drm_dma_handle_t *dmah; + int ret; - vaddr = contigmalloc(size, M_DRM, M_NOWAIT, 0ul, maxaddr, align, - 0); - *busaddr = vtophys(vaddr); - - return vaddr; + /* Need power-of-two alignment, so fail the allocation if it isn't. */ + if ((align & (align - 1)) != 0) { + DRM_ERROR("drm_pci_alloc with non-power-of-two alignment %d\n", + (int)align); + return NULL; + } + + dmah = malloc(sizeof(drm_dma_handle_t), M_DRM, M_ZERO | M_NOWAIT); + if (dmah == NULL) + return NULL; + +#ifdef __FreeBSD__ + ret = bus_dma_tag_create(NULL, align, 0, /* tag, align, boundary */ + maxaddr, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */ + NULL, NULL, /* filtfunc, filtfuncargs */ + size, 1, size, /* maxsize, nsegs, maxsegsize */ + BUS_DMA_ALLOCNOW, NULL, NULL, /* flags, lockfunc, lockfuncargs */ + &dmah->tag); + if (ret != 0) { + free(dmah, M_DRM); + return NULL; + } + + ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr, BUS_DMA_NOWAIT, + &dmah->map); + if (ret != 0) { + bus_dma_tag_destroy(dmah->tag); + free(dmah, M_DRM); + return NULL; + } + + ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr, size, + drm_pci_busdma_callback, dmah, 0); + if (ret != 0) { + bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map); + bus_dma_tag_destroy(dmah->tag); + free(dmah, M_DRM); + return NULL; + } +#elif defined(__NetBSD__) + ret = bus_dmamem_alloc(dev->dma_tag, size, align, PAGE_SIZE, + &dmah->seg, 1, &nsegs, BUS_DMA_NOWAIT); + if ((ret != 0) || (nsegs != 1)) { + free(dmah, M_DRM); + return NULL; + } + + ret = bus_dmamem_map(dev->dma_tag, &dmah->seg, 1, size, &dmah->addr, + BUS_DMA_NOWAIT); + if (ret != 0) { + bus_dmamem_free(dev->dma_tag, &dmah->seg, 1); + free(dmah, M_DRM); + return NULL; + } + + dmah->dmaaddr = h->seg.ds_addr; +#endif + + return dmah; } /** * \brief Free a DMA-accessible consistent memory block. */ void -drm_pci_free(drm_device_t *dev, size_t size, void *vaddr, dma_addr_t busaddr) +drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah) { -#if __FreeBSD_version > 500000 - if (vaddr == NULL) + if (dmah == NULL) return; - contigfree(vaddr, size, M_DRM); /* Not available on 4.x */ + +#if defined(__FreeBSD__) + bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map); + bus_dma_tag_destroy(dmah->tag); +#elif defined(__NetBSD__) + bus_dmamem_free(dev->dma_tag, &dmah->seg, 1); #endif + + free(dmah, M_DRM); } /*@}*/ Index: head/sys/dev/drm/drm_pciids.h =================================================================== --- head/sys/dev/drm/drm_pciids.h (revision 152908) +++ head/sys/dev/drm/drm_pciids.h (revision 152909) @@ -1,242 +1,435 @@ /* * $FreeBSD$ */ - /* This file is auto-generated from the drm_pciids.txt in the DRM CVS Please contact dri-devel@lists.sf.net to add new cards to this list */ #define radeon_PCI_IDS \ {0x1002, 0x4136, CHIP_RS100|CHIP_IS_IGP, "ATI Radeon RS100 IGP 320M"}, \ {0x1002, 0x4137, CHIP_RS200|CHIP_IS_IGP, "ATI Radeon RS200 IGP"}, \ {0x1002, 0x4144, CHIP_R300, "ATI Radeon AD 9500 Pro"}, \ {0x1002, 0x4145, CHIP_R300, "ATI Radeon AE 9700 Pro"}, \ {0x1002, 0x4146, CHIP_R300, "ATI Radeon AF 9700 Pro"}, \ {0x1002, 0x4147, CHIP_R300, "ATI FireGL AG Z1/X1"}, \ {0x1002, 0x4150, CHIP_RV350, "ATI Radeon AP 9600"}, \ {0x1002, 0x4151, CHIP_RV350, "ATI Radeon AQ 9600"}, \ {0x1002, 0x4152, CHIP_RV350, "ATI Radeon AR 9600"}, \ {0x1002, 0x4153, CHIP_RV350, "ATI Radeon AS 9600 AS"}, \ {0x1002, 0x4154, CHIP_RV350, "ATI FireGL AT T2"}, \ {0x1002, 0x4156, CHIP_RV350, "ATI FireGL AV T2"}, \ {0x1002, 0x4237, CHIP_RS250|CHIP_IS_IGP, "ATI Radeon RS250 IGP"}, \ {0x1002, 0x4242, CHIP_R200, "ATI Radeon BB R200 AIW 8500DV"}, \ {0x1002, 0x4243, CHIP_R200, "ATI Radeon BC R200"}, \ {0x1002, 0x4336, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY, "ATI Radeon RS100 Mobility U1"}, \ {0x1002, 0x4337, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY, "ATI Radeon RS200 Mobility IGP 340M"}, \ {0x1002, 0x4437, CHIP_RS250|CHIP_IS_IGP|CHIP_IS_MOBILITY, "ATI Radeon RS250 Mobility IGP"}, \ {0x1002, 0x4964, CHIP_R250, "ATI Radeon Id R250 9000"}, \ {0x1002, 0x4965, CHIP_R250, "ATI Radeon Ie R250 9000"}, \ {0x1002, 0x4966, CHIP_R250, "ATI Radeon If R250 9000"}, \ {0x1002, 0x4967, CHIP_R250, "ATI Radeon Ig R250 9000"}, \ {0x1002, 0x4A49, CHIP_R420, "ATI Radeon JI R420 X800PRO"}, \ {0x1002, 0x4A4B, CHIP_R420, "ATI Radeon JK R420 X800 XT"}, \ {0x1002, 0x4C57, CHIP_RV200|CHIP_IS_MOBILITY, "ATI Radeon LW RV200 Mobility 7500 M7"}, \ {0x1002, 0x4C58, CHIP_RV200|CHIP_IS_MOBILITY, "ATI Radeon LX RV200 Mobility FireGL 7800 M7"}, \ {0x1002, 0x4C59, CHIP_RV100|CHIP_IS_MOBILITY, "ATI Radeon LY RV100 Mobility M6"}, \ {0x1002, 0x4C5A, CHIP_RV100|CHIP_IS_MOBILITY, "ATI Radeon LZ RV100 Mobility M6"}, \ {0x1002, 0x4C64, CHIP_R250|CHIP_IS_MOBILITY, "ATI Radeon Ld R250 Mobility 9000 M9"}, \ {0x1002, 0x4C65, CHIP_R250|CHIP_IS_MOBILITY, "ATI Radeon Le R250 Mobility 9000 M9"}, \ {0x1002, 0x4C66, CHIP_R250|CHIP_IS_MOBILITY, "ATI Radeon Lf R250 Mobility 9000 M9"}, \ {0x1002, 0x4C67, CHIP_R250|CHIP_IS_MOBILITY, "ATI Radeon Lg R250 Mobility 9000 M9"}, \ {0x1002, 0x4E44, CHIP_R300, "ATI Radeon ND R300 9700 Pro"}, \ {0x1002, 0x4E45, CHIP_R300, "ATI Radeon NE R300 9500 Pro"}, \ {0x1002, 0x4E46, CHIP_RV350, "ATI Radeon NF RV350 9600"}, \ {0x1002, 0x4E47, CHIP_R300, "ATI Radeon NG R300 FireGL X1"}, \ {0x1002, 0x4E48, CHIP_R350, "ATI Radeon NH R350 9800 Pro"}, \ {0x1002, 0x4E49, CHIP_R350, "ATI Radeon NI R350 9800"}, \ {0x1002, 0x4E4A, CHIP_RV350, "ATI Radeon NJ RV350 9800 XT"}, \ {0x1002, 0x4E4B, CHIP_R350, "ATI Radeon NK R350 FireGL X2"}, \ {0x1002, 0x4E50, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon RV300 Mobility 9600 M10"}, \ {0x1002, 0x4E51, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon RV350 Mobility 9600 M10 NQ"}, \ {0x1002, 0x4E54, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon FireGL T2 128"}, \ + {0x1002, 0x4E56, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon FireGL Mobility T2e"}, \ {0x1002, 0x5144, CHIP_R100|CHIP_SINGLE_CRTC, "ATI Radeon QD R100"}, \ {0x1002, 0x5145, CHIP_R100|CHIP_SINGLE_CRTC, "ATI Radeon QE R100"}, \ {0x1002, 0x5146, CHIP_R100|CHIP_SINGLE_CRTC, "ATI Radeon QF R100"}, \ {0x1002, 0x5147, CHIP_R100|CHIP_SINGLE_CRTC, "ATI Radeon QG R100"}, \ {0x1002, 0x5148, CHIP_R200, "ATI Radeon QH R200 8500"}, \ {0x1002, 0x5149, CHIP_R200, "ATI Radeon QI R200"}, \ {0x1002, 0x514A, CHIP_R200, "ATI Radeon QJ R200"}, \ {0x1002, 0x514B, CHIP_R200, "ATI Radeon QK R200"}, \ {0x1002, 0x514C, CHIP_R200, "ATI Radeon QL R200 8500 LE"}, \ {0x1002, 0x514D, CHIP_R200, "ATI Radeon QM R200 9100"}, \ {0x1002, 0x514E, CHIP_R200, "ATI Radeon QN R200 8500 LE"}, \ {0x1002, 0x514F, CHIP_R200, "ATI Radeon QO R200 8500 LE"}, \ {0x1002, 0x5157, CHIP_RV200, "ATI Radeon QW RV200 7500"}, \ {0x1002, 0x5158, CHIP_RV200, "ATI Radeon QX RV200 7500"}, \ {0x1002, 0x5159, CHIP_RV100, "ATI Radeon QY RV100 7000/VE"}, \ {0x1002, 0x515A, CHIP_RV100, "ATI Radeon QZ RV100 7000/VE"}, \ + {0x1002, 0x515E, CHIP_RV100, "ATI ES1000 RN50"}, \ {0x1002, 0x5168, CHIP_R200, "ATI Radeon Qh R200"}, \ {0x1002, 0x5169, CHIP_R200, "ATI Radeon Qi R200"}, \ {0x1002, 0x516A, CHIP_R200, "ATI Radeon Qj R200"}, \ {0x1002, 0x516B, CHIP_R200, "ATI Radeon Qk R200"}, \ {0x1002, 0x516C, CHIP_R200, "ATI Radeon Ql R200"}, \ {0x1002, 0x5460, CHIP_RV350, "ATI Radeon X300"}, \ + {0x1002, 0x554F, CHIP_R350, "ATI Radeon X800"}, \ {0x1002, 0x5834, CHIP_RS300|CHIP_IS_IGP, "ATI Radeon RS300 IGP"}, \ {0x1002, 0x5835, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY, "ATI Radeon RS300 Mobility IGP"}, \ {0x1002, 0x5836, CHIP_RS300|CHIP_IS_IGP, "ATI Radeon RS300 IGP"}, \ {0x1002, 0x5837, CHIP_RS300|CHIP_IS_IGP, "ATI Radeon RS300 IGP"}, \ {0x1002, 0x5960, CHIP_RV280, "ATI Radeon RV280 9200"}, \ {0x1002, 0x5961, CHIP_RV280, "ATI Radeon RV280 9200 SE"}, \ {0x1002, 0x5962, CHIP_RV280, "ATI Radeon RV280 9200"}, \ {0x1002, 0x5963, CHIP_RV280, "ATI Radeon RV280 9200"}, \ {0x1002, 0x5964, CHIP_RV280, "ATI Radeon RV280 9200 SE"}, \ {0x1002, 0x5968, CHIP_RV280, "ATI Radeon RV280 9200"}, \ {0x1002, 0x5969, CHIP_RV100, "ATI ES1000 RN50"}, \ {0x1002, 0x596A, CHIP_RV280, "ATI Radeon RV280 9200"}, \ {0x1002, 0x596B, CHIP_RV280, "ATI Radeon RV280 9200"}, \ + {0x1002, 0x5b60, CHIP_RV350, "ATI Radeon RV370 X300SE"}, \ {0x1002, 0x5c61, CHIP_RV280|CHIP_IS_MOBILITY, "ATI Radeon RV280 Mobility"}, \ {0x1002, 0x5c62, CHIP_RV280, "ATI Radeon RV280"}, \ {0x1002, 0x5c63, CHIP_RV280|CHIP_IS_MOBILITY, "ATI Radeon RV280 Mobility"}, \ {0x1002, 0x5c64, CHIP_RV280, "ATI Radeon RV280"}, \ + {0x1002, 0x5d4d, CHIP_R350, "ATI Radeon R480"}, \ {0, 0, 0, NULL} #define r128_PCI_IDS \ {0x1002, 0x4c45, 0, "ATI Rage 128 Mobility LE (PCI)"}, \ {0x1002, 0x4c46, 0, "ATI Rage 128 Mobility LF (AGP)"}, \ {0x1002, 0x4d46, 0, "ATI Rage 128 Mobility MF (AGP)"}, \ {0x1002, 0x4d4c, 0, "ATI Rage 128 Mobility ML (AGP)"}, \ {0x1002, 0x5041, 0, "ATI Rage 128 Pro PA (PCI)"}, \ {0x1002, 0x5042, 0, "ATI Rage 128 Pro PB (AGP)"}, \ {0x1002, 0x5043, 0, "ATI Rage 128 Pro PC (AGP)"}, \ {0x1002, 0x5044, 0, "ATI Rage 128 Pro PD (PCI)"}, \ {0x1002, 0x5045, 0, "ATI Rage 128 Pro PE (AGP)"}, \ {0x1002, 0x5046, 0, "ATI Rage 128 Pro PF (AGP)"}, \ {0x1002, 0x5047, 0, "ATI Rage 128 Pro PG (PCI)"}, \ {0x1002, 0x5048, 0, "ATI Rage 128 Pro PH (AGP)"}, \ {0x1002, 0x5049, 0, "ATI Rage 128 Pro PI (AGP)"}, \ {0x1002, 0x504A, 0, "ATI Rage 128 Pro PJ (PCI)"}, \ {0x1002, 0x504B, 0, "ATI Rage 128 Pro PK (AGP)"}, \ {0x1002, 0x504C, 0, "ATI Rage 128 Pro PL (AGP)"}, \ {0x1002, 0x504D, 0, "ATI Rage 128 Pro PM (PCI)"}, \ {0x1002, 0x504E, 0, "ATI Rage 128 Pro PN (AGP)"}, \ {0x1002, 0x504F, 0, "ATI Rage 128 Pro PO (AGP)"}, \ {0x1002, 0x5050, 0, "ATI Rage 128 Pro PP (PCI)"}, \ {0x1002, 0x5051, 0, "ATI Rage 128 Pro PQ (AGP)"}, \ {0x1002, 0x5052, 0, "ATI Rage 128 Pro PR (PCI)"}, \ {0x1002, 0x5053, 0, "ATI Rage 128 Pro PS (PCI)"}, \ {0x1002, 0x5054, 0, "ATI Rage 128 Pro PT (AGP)"}, \ {0x1002, 0x5055, 0, "ATI Rage 128 Pro PU (AGP)"}, \ {0x1002, 0x5056, 0, "ATI Rage 128 Pro PV (PCI)"}, \ {0x1002, 0x5057, 0, "ATI Rage 128 Pro PW (AGP)"}, \ {0x1002, 0x5058, 0, "ATI Rage 128 Pro PX (AGP)"}, \ {0x1002, 0x5245, 0, "ATI Rage 128 RE (PCI)"}, \ {0x1002, 0x5246, 0, "ATI Rage 128 RF (AGP)"}, \ {0x1002, 0x5247, 0, "ATI Rage 128 RG (AGP)"}, \ {0x1002, 0x524b, 0, "ATI Rage 128 RK (PCI)"}, \ {0x1002, 0x524c, 0, "ATI Rage 128 RL (AGP)"}, \ {0x1002, 0x534d, 0, "ATI Rage 128 SM (AGP)"}, \ {0x1002, 0x5446, 0, "ATI Rage 128 Pro Ultra TF (AGP)"}, \ {0x1002, 0x544C, 0, "ATI Rage 128 Pro Ultra TL (AGP)"}, \ {0x1002, 0x5452, 0, "ATI Rage 128 Pro Ultra TR (AGP)"}, \ {0, 0, 0, NULL} #define mga_PCI_IDS \ - {0x102b, 0x0521, 0, "Matrox G200 (AGP)"}, \ - {0x102b, 0x0525, 0, "Matrox G400/G450 (AGP)"}, \ - {0x102b, 0x2527, 0, "Matrox G550 (AGP)"}, \ + {0x102b, 0x0520, MGA_CARD_TYPE_G200, "Matrox G200 (PCI)"}, \ + {0x102b, 0x0521, MGA_CARD_TYPE_G200, "Matrox G200 (AGP)"}, \ + {0x102b, 0x0525, MGA_CARD_TYPE_G400, "Matrox G400/G450 (AGP)"}, \ + {0x102b, 0x2527, MGA_CARD_TYPE_G550, "Matrox G550 (AGP)"}, \ {0, 0, 0, NULL} #define mach64_PCI_IDS \ {0x1002, 0x4749, 0, "3D Rage Pro"}, \ {0x1002, 0x4750, 0, "3D Rage Pro 215GP"}, \ {0x1002, 0x4751, 0, "3D Rage Pro 215GQ"}, \ {0x1002, 0x4742, 0, "3D Rage Pro AGP 1X/2X"}, \ {0x1002, 0x4744, 0, "3D Rage Pro AGP 1X"}, \ {0x1002, 0x4c49, 0, "3D Rage LT Pro"}, \ {0x1002, 0x4c50, 0, "3D Rage LT Pro"}, \ {0x1002, 0x4c51, 0, "3D Rage LT Pro"}, \ {0x1002, 0x4c42, 0, "3D Rage LT Pro AGP-133"}, \ {0x1002, 0x4c44, 0, "3D Rage LT Pro AGP-66"}, \ {0x1002, 0x474c, 0, "Rage XC"}, \ {0x1002, 0x474f, 0, "Rage XL"}, \ {0x1002, 0x4752, 0, "Rage XL"}, \ {0x1002, 0x4753, 0, "Rage XC"}, \ {0x1002, 0x474d, 0, "Rage XL AGP 2X"}, \ {0x1002, 0x474e, 0, "Rage XC AGP"}, \ {0x1002, 0x4c52, 0, "Rage Mobility P/M"}, \ {0x1002, 0x4c53, 0, "Rage Mobility L"}, \ {0x1002, 0x4c4d, 0, "Rage Mobility P/M AGP 2X"}, \ {0x1002, 0x4c4e, 0, "Rage Mobility L AGP 2X"}, \ {0, 0, 0, NULL} #define sis_PCI_IDS \ {0x1039, 0x0300, 0, "SiS 300/305"}, \ {0x1039, 0x5300, 0, "SiS 540"}, \ {0x1039, 0x6300, 0, "SiS 630"}, \ {0x1039, 0x7300, 0, "SiS 730"}, \ {0, 0, 0, NULL} #define tdfx_PCI_IDS \ {0x121a, 0x0003, 0, "3dfx Voodoo Banshee"}, \ {0x121a, 0x0004, 0, "3dfx Voodoo3 2000"}, \ {0x121a, 0x0005, 0, "3dfx Voodoo3 3000"}, \ {0x121a, 0x0007, 0, "3dfx Voodoo4 4500"}, \ {0x121a, 0x0009, 0, "3dfx Voodoo5 5500"}, \ {0x121a, 0x000b, 0, "3dfx Voodoo4 4200"}, \ {0, 0, 0, NULL} #define viadrv_PCI_IDS \ {0x1106, 0x3022, 0, "VIA CLE266 3022"}, \ - {0x1106, 0x3118, 0, "VIA CN400"}, \ + {0x1106, 0x3118, VIA_PRO_GROUP_A, "VIA CN400 / PM8X0"}, \ {0x1106, 0x3122, 0, "VIA CLE266"}, \ {0x1106, 0x7205, 0, "VIA KM400"}, \ - {0x1106, 0x7204, 0, "VIA K8M800"}, \ + {0x1106, 0x3108, 0, "VIA K8M800"}, \ {0, 0, 0, NULL} #define i810_PCI_IDS \ {0x8086, 0x7121, 0, "Intel i810 GMCH"}, \ {0x8086, 0x7123, 0, "Intel i810-DC100 GMCH"}, \ {0x8086, 0x7125, 0, "Intel i810E GMCH"}, \ {0x8086, 0x1132, 0, "Intel i815 GMCH"}, \ {0, 0, 0, NULL} #define i830_PCI_IDS \ {0x8086, 0x3577, 0, "Intel i830M GMCH"}, \ {0x8086, 0x2562, 0, "Intel i845G GMCH"}, \ {0x8086, 0x3582, 0, "Intel i852GM/i855GM GMCH"}, \ {0x8086, 0x2572, 0, "Intel i865G GMCH"}, \ {0, 0, 0, NULL} #define gamma_PCI_IDS \ {0x3d3d, 0x0008, 0, "3DLabs GLINT Gamma G1"}, \ {0, 0, 0, NULL} #define savage_PCI_IDS \ {0x5333, 0x8a20, S3_SAVAGE3D, "Savage 3D"}, \ {0x5333, 0x8a21, S3_SAVAGE3D, "Savage 3D/MV"}, \ {0x5333, 0x8a22, S3_SAVAGE4, "Savage4"}, \ {0x5333, 0x8a23, S3_SAVAGE4, "Savage4"}, \ {0x5333, 0x8c10, S3_SAVAGE_MX, "Savage/MX-MV"}, \ {0x5333, 0x8c11, S3_SAVAGE_MX, "Savage/MX"}, \ {0x5333, 0x8c12, S3_SAVAGE_MX, "Savage/IX-MV"}, \ {0x5333, 0x8c13, S3_SAVAGE_MX, "Savage/IX"}, \ {0x5333, 0x8c22, S3_SUPERSAVAGE, "SuperSavage MX/128"}, \ {0x5333, 0x8c24, S3_SUPERSAVAGE, "SuperSavage MX/64"}, \ {0x5333, 0x8c26, S3_SUPERSAVAGE, "SuperSavage MX/64C"}, \ {0x5333, 0x8c2a, S3_SUPERSAVAGE, "SuperSavage IX/128 SDR"}, \ {0x5333, 0x8c2b, S3_SUPERSAVAGE, "SuperSavage IX/128 DDR"}, \ {0x5333, 0x8c2c, S3_SUPERSAVAGE, "SuperSavage IX/64 SDR"}, \ {0x5333, 0x8c2d, S3_SUPERSAVAGE, "SuperSavage IX/64 DDR"}, \ {0x5333, 0x8c2e, S3_SUPERSAVAGE, "SuperSavage IX/C SDR"}, \ {0x5333, 0x8c2f, S3_SUPERSAVAGE, "SuperSavage IX/C DDR"}, \ {0x5333, 0x8a25, S3_PROSAVAGE, "ProSavage PM133"}, \ {0x5333, 0x8a26, S3_PROSAVAGE, "ProSavage KM133"}, \ {0x5333, 0x8d01, S3_TWISTER, "ProSavage Twister PN133"}, \ {0x5333, 0x8d02, S3_TWISTER, "ProSavage Twister KN133"}, \ {0x5333, 0x8d03, S3_PROSAVAGEDDR, "ProSavage DDR"}, \ {0x5333, 0x8d04, S3_PROSAVAGEDDR, "ProSavage DDR-K"}, \ {0, 0, 0, NULL} #define ffb_PCI_IDS \ {0, 0, 0, NULL} #define i915_PCI_IDS \ {0x8086, 0x3577, 0, "Intel i830M GMCH"}, \ {0x8086, 0x2562, 0, "Intel i845G GMCH"}, \ {0x8086, 0x3582, 0, "Intel i852GM/i855GM GMCH"}, \ {0x8086, 0x2572, 0, "Intel i865G GMCH"}, \ {0x8086, 0x2582, 0, "Intel i915G"}, \ - {0x8086, 0x2982, 0, "Intel i915GM"}, \ + {0x8086, 0x2592, 0, "Intel i915GM"}, \ + {0x8086, 0x2772, 0, "Intel i945G"}, \ {0, 0, 0, NULL} +#define imagine_PCI_IDS \ + {0x105d, 0x2309, IMAGINE_128, "Imagine 128"}, \ + {0x105d, 0x2339, IMAGINE_128_2, "Imagine 128-II"}, \ + {0x105d, 0x493d, IMAGINE_T2R, "Ticket to Ride"}, \ + {0x105d, 0x5348, IMAGINE_REV4, "Revolution IV"}, \ + {0, 0, 0, NULL} + +#define nv_PCI_IDS \ + {0x10DE, 0x0020, NV04, "NVidia RIVA TNT"}, \ + {0x10DE, 0x0028, NV04, "NVidia RIVA TNT2"}, \ + {0x10DE, 0x002A, NV04, "NVidia Unknown TNT2"}, \ + {0x10DE, 0x002C, NV04, "NVidia Vanta"}, \ + {0x10DE, 0x0029, NV04, "NVidia RIVA TNT2 Ultra"}, \ + {0x10DE, 0x002D, NV04, "NVidia RIVA TNT2 Model 64"}, \ + {0x10DE, 0x00A0, NV04, "NVidia Aladdin TNT2"}, \ + {0x10DE, 0x0100, NV10, "NVidia GeForce 256"}, \ + {0x10DE, 0x0101, NV10, "NVidia GeForce DDR"}, \ + {0x10DE, 0x0103, NV10, "NVidia Quadro"}, \ + {0x10DE, 0x0110, NV10, "NVidia GeForce2 MX/MX 400"}, \ + {0x10DE, 0x0111, NV10, "NVidia GeForce2 MX 100/200"}, \ + {0x10DE, 0x0112, NV10, "NVidia GeForce2 Go"}, \ + {0x10DE, 0x0113, NV10, "NVidia Quadro2 MXR/EX/Go"}, \ + {0x10DE, 0x0150, NV10, "NVidia GeForce2 GTS"}, \ + {0x10DE, 0x0151, NV10, "NVidia GeForce2 Ti"}, \ + {0x10DE, 0x0152, NV10, "NVidia GeForce2 Ultra"}, \ + {0x10DE, 0x0153, NV10, "NVidia Quadro2 Pro"}, \ + {0x10DE, 0x0170, NV10, "NVidia GeForce4 MX 460"}, \ + {0x10DE, 0x0171, NV10, "NVidia GeForce4 MX 440"}, \ + {0x10DE, 0x0172, NV10, "NVidia GeForce4 MX 420"}, \ + {0x10DE, 0x0173, NV10, "NVidia GeForce4 MX 440-SE"}, \ + {0x10DE, 0x0174, NV10, "NVidia GeForce4 440 Go"}, \ + {0x10DE, 0x0175, NV10, "NVidia GeForce4 420 Go"}, \ + {0x10DE, 0x0176, NV10, "NVidia GeForce4 420 Go 32M"}, \ + {0x10DE, 0x0177, NV10, "NVidia GeForce4 460 Go"}, \ + {0x10DE, 0x0178, NV10, "NVidia Quadro4 550 XGL"}, \ + {0x10DE, 0x0179, NV10, "NVidia GeForce4"}, \ + {0x10DE, 0x017A, NV10, "NVidia Quadro4 NVS"}, \ + {0x10DE, 0x017C, NV10, "NVidia Quadro4 500 GoGL"}, \ + {0x10DE, 0x017D, NV10, "NVidia GeForce4 410 Go 16M"}, \ + {0x10DE, 0x0181, NV10, "NVidia GeForce4 MX 440 with AGP8X"}, \ + {0x10DE, 0x0182, NV10, "NVidia GeForce4 MX 440SE with AGP8X"}, \ + {0x10DE, 0x0183, NV10, "NVidia GeForce4 MX 420 with AGP8X"}, \ + {0x10DE, 0x0185, NV10, "NVidia GeForce4 MX 4000"}, \ + {0x10DE, 0x0186, NV10, "NVidia GeForce4 448 Go"}, \ + {0x10DE, 0x0187, NV10, "NVidia GeForce4 488 Go"}, \ + {0x10DE, 0x0188, NV10, "NVidia Quadro4 580 XGL"}, \ + {0x10DE, 0x0189, NV10, "NVidia GeForce4 MX with AGP8X (Mac)"}, \ + {0x10DE, 0x018A, NV10, "NVidia Quadro4 280 NVS"}, \ + {0x10DE, 0x018B, NV10, "NVidia Quadro4 380 XGL"}, \ + {0x10DE, 0x018C, NV10, "NVidia Quadro NVS 50 PCI"}, \ + {0x10DE, 0x018D, NV10, "NVidia GeForce4 448 Go"}, \ + {0x10DE, 0x01A0, NV10, "NVidia GeForce2 Integrated GPU"}, \ + {0x10DE, 0x01F0, NV10, "NVidia GeForce4 MX Integrated GPU"}, \ + {0x10DE, 0x0200, NV20, "NVidia GeForce3"}, \ + {0x10DE, 0x0201, NV20, "NVidia GeForce3 Ti 200"}, \ + {0x10DE, 0x0202, NV20, "NVidia GeForce3 Ti 500"}, \ + {0x10DE, 0x0203, NV20, "NVidia Quadro DCC"}, \ + {0x10DE, 0x0250, NV20, "NVidia GeForce4 Ti 4600"}, \ + {0x10DE, 0x0251, NV20, "NVidia GeForce4 Ti 4400"}, \ + {0x10DE, 0x0252, NV20, "NVidia 0x0252"}, \ + {0x10DE, 0x0253, NV20, "NVidia GeForce4 Ti 4200"}, \ + {0x10DE, 0x0258, NV20, "NVidia Quadro4 900 XGL"}, \ + {0x10DE, 0x0259, NV20, "NVidia Quadro4 750 XGL"}, \ + {0x10DE, 0x025B, NV20, "NVidia Quadro4 700 XGL"}, \ + {0x10DE, 0x0280, NV20, "NVidia GeForce4 Ti 4800"}, \ + {0x10DE, 0x0281, NV20, "NVidia GeForce4 Ti 4200 with AGP8X"}, \ + {0x10DE, 0x0282, NV20, "NVidia GeForce4 Ti 4800 SE"}, \ + {0x10DE, 0x0286, NV20, "NVidia GeForce4 4200 Go"}, \ + {0x10DE, 0x028C, NV20, "NVidia Quadro4 700 GoGL"}, \ + {0x10DE, 0x0288, NV20, "NVidia Quadro4 980 XGL"}, \ + {0x10DE, 0x0289, NV20, "NVidia Quadro4 780 XGL"}, \ + {0x10DE, 0x0301, NV30, "NVidia GeForce FX 5800 Ultra"}, \ + {0x10DE, 0x0302, NV30, "NVidia GeForce FX 5800"}, \ + {0x10DE, 0x0308, NV30, "NVidia Quadro FX 2000"}, \ + {0x10DE, 0x0309, NV30, "NVidia Quadro FX 1000"}, \ + {0x10DE, 0x0311, NV30, "NVidia GeForce FX 5600 Ultra"}, \ + {0x10DE, 0x0312, NV30, "NVidia GeForce FX 5600"}, \ + {0x10DE, 0x0313, NV30, "NVidia 0x0313"},}, \ + {0x10DE, 0x0314, NV30, "NVidia GeForce FX 5600SE"}, \ + {0x10DE, 0x0316, NV30, "NVidia 0x0316"}, \ + {0x10DE, 0x0317, NV30, "NVidia 0x0317"}, \ + {0x10DE, 0x031A, NV30, "NVidia GeForce FX Go5600"}, \ + {0x10DE, 0x031B, NV30, "NVidia GeForce FX Go5650"}, \ + {0x10DE, 0x031C, NV30, "NVidia Quadro FX Go700"}, \ + {0x10DE, 0x031D, NV30, "NVidia 0x031D"}, \ + {0x10DE, 0x031E, NV30, "NVidia 0x031E"}, \ + {0x10DE, 0x031F, NV30, "NVidia 0x031F"}, \ + {0x10DE, 0x0320, NV30, "NVidia GeForce FX 5200"}, \ + {0x10DE, 0x0321, NV30, "NVidia GeForce FX 5200 Ultra"}, \ + {0x10DE, 0x0322, NV30, "NVidia GeForce FX 5200"}, \ + {0x10DE, 0x0323, NV30, "NVidia GeForce FX 5200SE"}, \ + {0x10DE, 0x0324, NV30, "NVidia GeForce FX Go5200"}, \ + {0x10DE, 0x0325, NV30, "NVidia GeForce FX Go5250"}, \ + {0x10DE, 0x0326, NV30, "NVidia GeForce FX 5500"}, \ + {0x10DE, 0x0327, NV30, "NVidia GeForce FX 5100"}, \ + {0x10DE, 0x0328, NV30, "NVidia GeForce FX Go5200 32M/64M"}, \ + {0x10DE, 0x0329, NV30, "NVidia GeForce FX 5200 (Mac)"}, \ + {0x10DE, 0x032A, NV30, "NVidia Quadro NVS 280 PCI"}, \ + {0x10DE, 0x032B, NV30, "NVidia Quadro FX 500/600 PCI"}, \ + {0x10DE, 0x032C, NV30, "NVidia GeForce FX Go53xx Series"}, \ + {0x10DE, 0x032D, NV30, "NVidia GeForce FX Go5100"}, \ + {0x10DE, 0x032F, NV30, "NVidia 0x032F"}, \ + {0x10DE, 0x0330, NV30, "NVidia GeForce FX 5900 Ultra"}, \ + {0x10DE, 0x0331, NV30, "NVidia GeForce FX 5900"}, \ + {0x10DE, 0x0332, NV30, "NVidia GeForce FX 5900XT"}, \ + {0x10DE, 0x0333, NV30, "NVidia GeForce FX 5950 Ultra"}, \ + {0x10DE, 0x033F, NV30, "NVidia Quadro FX 700"}, \ + {0x10DE, 0x0334, NV30, "NVidia GeForce FX 5900ZT"}, \ + {0x10DE, 0x0338, NV30, "NVidia Quadro FX 3000"}, \ + {0x10DE, 0x0341, NV30, "NVidia GeForce FX 5700 Ultra"}, \ + {0x10DE, 0x0342, NV30, "NVidia GeForce FX 5700"}, \ + {0x10DE, 0x0343, NV30, "NVidia GeForce FX 5700LE"}, \ + {0x10DE, 0x0344, NV30, "NVidia GeForce FX 5700VE"}, \ + {0x10DE, 0x0345, NV30, "NVidia 0x0345"}, \ + {0x10DE, 0x0347, NV30, "NVidia GeForce FX Go5700"}, \ + {0x10DE, 0x0348, NV30, "NVidia GeForce FX Go5700"}, \ + {0x10DE, 0x0349, NV30, "NVidia 0x0349"}, \ + {0x10DE, 0x034B, NV30, "NVidia 0x034B"}, \ + {0x10DE, 0x034C, NV30, "NVidia Quadro FX Go1000"}, \ + {0x10DE, 0x034E, NV30, "NVidia Quadro FX 1100"}, \ + {0x10DE, 0x034F, NV30, "NVidia 0x034F"}, \ + {0x10DE, 0x0040, NV40, "NVidia GeForce 6800 Ultra"}, \ + {0x10DE, 0x0041, NV40, "NVidia GeForce 6800"}, \ + {0x10DE, 0x0042, NV40, "NVidia GeForce 6800 LE"}, \ + {0x10DE, 0x0043, NV40, "NVidia 0x0043"}, \ + {0x10DE, 0x0045, NV40, "NVidia GeForce 6800 GT"}, \ + {0x10DE, 0x0046, NV40, "NVidia GeForce 6800 GT"}, \ + {0x10DE, 0x0049, NV40, "NVidia 0x0049"}, \ + {0x10DE, 0x004E, NV40, "NVidia Quadro FX 4000"}, \ + {0x10DE, 0x00C0, NV40, "NVidia 0x00C0"}, \ + {0x10DE, 0x00C1, NV40, "NVidia GeForce 6800"}, \ + {0x10DE, 0x00C2, NV40, "NVidia GeForce 6800 LE"}, \ + {0x10DE, 0x00C8, NV40, "NVidia GeForce Go 6800"}, \ + {0x10DE, 0x00C9, NV40, "NVidia GeForce Go 6800 Ultra"}, \ + {0x10DE, 0x00CC, NV40, "NVidia Quadro FX Go1400"}, \ + {0x10DE, 0x00CD, NV40, "NVidia Quadro FX 3450/4000 SDI"}, \ + {0x10DE, 0x00CE, NV40, "NVidia Quadro FX 1400"}, \ + {0x10de, 0x00f0, NV40, "Nvidia GeForce 6600 GT"}, \ + {0x10de, 0x00f1, NV40, "Nvidia GeForce 6600 GT"}, \ + {0x10DE, 0x0140, NV40, "NVidia GeForce 6600 GT"}, \ + {0x10DE, 0x0141, NV40, "NVidia GeForce 6600"}, \ + {0x10DE, 0x0142, NV40, "NVidia GeForce 6600 LE"}, \ + {0x10DE, 0x0143, NV40, "NVidia 0x0143"}, \ + {0x10DE, 0x0144, NV40, "NVidia GeForce Go 6600"}, \ + {0x10DE, 0x0145, NV40, "NVidia GeForce 6610 XL"}, \ + {0x10DE, 0x0146, NV40, "NVidia GeForce Go 6600 TE/6200 TE"}, \ + {0x10DE, 0x0147, NV40, "NVidia GeForce 6700 XL"}, \ + {0x10DE, 0x0148, NV40, "NVidia GeForce Go 6600"}, \ + {0x10DE, 0x0149, NV40, "NVidia GeForce Go 6600 GT"}, \ + {0x10DE, 0x014B, NV40, "NVidia 0x014B"}, \ + {0x10DE, 0x014C, NV40, "NVidia 0x014C"}, \ + {0x10DE, 0x014D, NV40, "NVidia 0x014D"}, \ + {0x10DE, 0x014E, NV40, "NVidia Quadro FX 540"}, \ + {0x10DE, 0x014F, NV40, "NVidia GeForce 6200"}, \ + {0x10DE, 0x0160, NV40, "NVidia 0x0160"}, \ + {0x10DE, 0x0161, NV40, "NVidia GeForce 6200 TurboCache(TM)"}, \ + {0x10DE, 0x0162, NV40, "NVidia GeForce 6200SE TurboCache(TM)"}, \ + {0x10DE, 0x0163, NV40, "NVidia 0x0163"}, \ + {0x10DE, 0x0164, NV40, "NVidia GeForce Go 6200"}, \ + {0x10DE, 0x0165, NV40, "NVidia Quadro NVS 285"}, \ + {0x10DE, 0x0166, NV40, "NVidia GeForce Go 6400"}, \ + {0x10DE, 0x0167, NV40, "NVidia GeForce Go 6200"}, \ + {0x10DE, 0x0168, NV40, "NVidia GeForce Go 6400"}, \ + {0x10DE, 0x0169, NV40, "NVidia 0x0169"}, \ + {0x10DE, 0x016B, NV40, "NVidia 0x016B"}, \ + {0x10DE, 0x016C, NV40, "NVidia 0x016C"}, \ + {0x10DE, 0x016D, NV40, "NVidia 0x016D"}, \ + {0x10DE, 0x016E, NV40, "NVidia 0x016E"}, \ + {0x10DE, 0x0210, NV40, "NVidia 0x0210"}, \ + {0x10DE, 0x0211, NV40, "NVidia GeForce 6800"}, \ + {0x10DE, 0x0212, NV40, "NVidia GeForce 6800 LE"}, \ + {0x10DE, 0x0215, NV40, "NVidia GeForce 6800 GT"}, \ + {0x10DE, 0x0220, NV40, "NVidia 0x0220"}, \ + {0x10DE, 0x0221, NV40, "NVidia GeForce 6200"}, \ + {0x10DE, 0x0222, NV40, "NVidia 0x0222"}, \ + {0x10DE, 0x0228, NV40, "NVidia 0x0228"}, \ + {0x10DE, 0x0090, NV40, "NVidia 0x0090"}, \ + {0x10DE, 0x0091, NV40, "NVidia GeForce 7800 GTX"}, \ + {0x10DE, 0x0092, NV40, "NVidia 0x0092"}, \ + {0x10DE, 0x0093, NV40, "NVidia 0x0093"}, \ + {0x10DE, 0x0094, NV40, "NVidia 0x0094"}, \ + {0x10DE, 0x0098, NV40, "NVidia 0x0098"}, \ + {0x10DE, 0x0099, NV40, "NVidia GeForce Go 7800 GTX"}, \ + {0x10DE, 0x009C, NV40, "NVidia 0x009C"}, \ + {0x10DE, 0x009D, NV40, "NVidia Quadro FX 4500"}, \ + {0x10DE, 0x009E, NV40, "NVidia 0x009E"}, \ + {0, 0, 0, NULL} Index: head/sys/dev/drm/drm_sarea.h =================================================================== --- head/sys/dev/drm/drm_sarea.h (revision 152908) +++ head/sys/dev/drm/drm_sarea.h (revision 152909) @@ -1,80 +1,81 @@ /** * \file drm_sarea.h * \brief SAREA definitions * * \author Michel D�zer */ /*- * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #ifndef _DRM_SAREA_H_ #define _DRM_SAREA_H_ #include "dev/drm/drm.h" /* SAREA area needs to be at least a page */ #if defined(__alpha__) #define SAREA_MAX 0x2000 #elif defined(__ia64__) #define SAREA_MAX 0x10000 /* 64kB */ #else /* Intel 830M driver needs at least 8k SAREA */ #define SAREA_MAX 0x2000 #endif /** Maximum number of drawables in the SAREA */ #define SAREA_MAX_DRAWABLES 256 #define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000 /** SAREA drawable */ typedef struct drm_sarea_drawable { unsigned int stamp; unsigned int flags; } drm_sarea_drawable_t; /** SAREA frame */ typedef struct drm_sarea_frame { unsigned int x; unsigned int y; unsigned int width; unsigned int height; unsigned int fullscreen; } drm_sarea_frame_t; /** SAREA */ typedef struct drm_sarea { /** first thing is always the DRM locking structure */ drm_hw_lock_t lock; /** \todo Use readers/writer lock for drm_sarea::drawable_lock */ drm_hw_lock_t drawable_lock; drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */ drm_sarea_frame_t frame; /**< frame */ drm_context_t dummy_context; } drm_sarea_t; #endif /* _DRM_SAREA_H_ */ Index: head/sys/dev/drm/drm_scatter.c =================================================================== --- head/sys/dev/drm/drm_scatter.c (revision 152908) +++ head/sys/dev/drm/drm_scatter.c (revision 152909) @@ -1,126 +1,131 @@ /* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*- * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com */ /*- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * Eric Anholt * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #define DEBUG_SCATTER 0 void drm_sg_cleanup(drm_sg_mem_t *entry) { - free(entry->virtual, M_DRM); + free((void *)entry->handle, M_DRM); free(entry->busaddr, M_DRM); free(entry, M_DRM); } int drm_sg_alloc(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_scatter_gather_t request; drm_sg_mem_t *entry; unsigned long pages; + int i; DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( dev->sg ) return EINVAL; DRM_COPY_FROM_USER_IOCTL(request, (drm_scatter_gather_t *)data, sizeof(request) ); entry = malloc(sizeof(*entry), M_DRM, M_WAITOK | M_ZERO); if ( !entry ) return ENOMEM; pages = round_page(request.size) / PAGE_SIZE; DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages ); entry->pages = pages; entry->busaddr = malloc(pages * sizeof(*entry->busaddr), M_DRM, M_WAITOK | M_ZERO); if ( !entry->busaddr ) { drm_sg_cleanup(entry); return ENOMEM; } - entry->virtual = malloc(pages << PAGE_SHIFT, M_DRM, M_WAITOK | M_ZERO); - if ( !entry->virtual ) { + entry->handle = (long)malloc(pages << PAGE_SHIFT, M_DRM, + M_WAITOK | M_ZERO); + if (entry->handle == 0) { drm_sg_cleanup(entry); return ENOMEM; } - entry->handle = (unsigned long)entry->virtual; + for (i = 0; i < pages; i++) { + entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE); + } DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle ); - DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual ); request.handle = entry->handle; DRM_COPY_TO_USER_IOCTL( (drm_scatter_gather_t *)data, request, sizeof(request) ); DRM_LOCK(); if (dev->sg) { DRM_UNLOCK(); drm_sg_cleanup(entry); return EINVAL; } dev->sg = entry; DRM_UNLOCK(); return 0; } int drm_sg_free(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_scatter_gather_t request; drm_sg_mem_t *entry; DRM_COPY_FROM_USER_IOCTL( request, (drm_scatter_gather_t *)data, sizeof(request) ); DRM_LOCK(); entry = dev->sg; dev->sg = NULL; DRM_UNLOCK(); if ( !entry || entry->handle != request.handle ) return EINVAL; - DRM_DEBUG( "sg free virtual = %p\n", entry->virtual ); + DRM_DEBUG( "sg free virtual = 0x%lx\n", entry->handle ); drm_sg_cleanup(entry); return 0; } Index: head/sys/dev/drm/drm_sysctl.c =================================================================== --- head/sys/dev/drm/drm_sysctl.c (revision 152908) +++ head/sys/dev/drm/drm_sysctl.c (revision 152909) @@ -1,306 +1,307 @@ /*- * Copyright 2003 Eric Anholt * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include static int drm_name_info DRM_SYSCTL_HANDLER_ARGS; static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS; static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS; static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS; struct drm_sysctl_list { const char *name; int (*f) DRM_SYSCTL_HANDLER_ARGS; } drm_sysctl_list[] = { {"name", drm_name_info}, {"vm", drm_vm_info}, {"clients", drm_clients_info}, {"bufs", drm_bufs_info}, }; #define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0])) struct drm_sysctl_info { struct sysctl_ctx_list ctx; char name[2]; }; int drm_sysctl_init(drm_device_t *dev) { struct drm_sysctl_info *info; struct sysctl_oid *oid; struct sysctl_oid *top, *drioid; int i; info = malloc(sizeof *info, M_DRM, M_WAITOK | M_ZERO); if ( !info ) return 1; dev->sysctl = info; /* Add the sysctl node for DRI if it doesn't already exist */ drioid = SYSCTL_ADD_NODE( &info->ctx, &sysctl__hw_children, OID_AUTO, "dri", CTLFLAG_RW, NULL, "DRI Graphics"); if (!drioid) return 1; /* Find the next free slot under hw.dri */ i = 0; SLIST_FOREACH(oid, SYSCTL_CHILDREN(drioid), oid_link) { if (i <= oid->oid_arg2) i = oid->oid_arg2 + 1; } if (i>9) return 1; /* Add the hw.dri.x for our device */ info->name[0] = '0' + i; info->name[1] = 0; top = SYSCTL_ADD_NODE( &info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL); if (!top) return 1; for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) { oid = SYSCTL_ADD_OID(&info->ctx, SYSCTL_CHILDREN(top), OID_AUTO, drm_sysctl_list[i].name, CTLTYPE_INT | CTLFLAG_RD, dev, 0, drm_sysctl_list[i].f, "A", NULL); if (!oid) return 1; } SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(top), OID_AUTO, "debug", CTLFLAG_RW, &drm_debug_flag, sizeof(drm_debug_flag), "Enable debugging output"); return 0; } int drm_sysctl_cleanup(drm_device_t *dev) { int error; error = sysctl_ctx_free( &dev->sysctl->ctx ); free(dev->sysctl, M_DRM); dev->sysctl = NULL; return error; } #define DRM_SYSCTL_PRINT(fmt, arg...) \ do { \ snprintf(buf, sizeof(buf), fmt, ##arg); \ retcode = SYSCTL_OUT(req, buf, strlen(buf)); \ if (retcode) \ goto done; \ } while (0) static int drm_name_info DRM_SYSCTL_HANDLER_ARGS { drm_device_t *dev = arg1; char buf[128]; int retcode; int hasunique = 0; - DRM_SYSCTL_PRINT("%s 0x%x", dev->driver_name, dev2udev(dev->devnode)); + DRM_SYSCTL_PRINT("%s 0x%x", dev->driver.name, dev2udev(dev->devnode)); DRM_LOCK(); if (dev->unique) { snprintf(buf, sizeof(buf), " %s", dev->unique); hasunique = 1; } DRM_UNLOCK(); if (hasunique) SYSCTL_OUT(req, buf, strlen(buf)); SYSCTL_OUT(req, "", 1); done: return retcode; } static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS { drm_device_t *dev = arg1; drm_local_map_t *map, *tempmaps; const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" }; const char *type, *yesno; int i, mapcount; char buf[128]; int retcode; /* We can't hold the lock while doing SYSCTL_OUTs, so allocate a * temporary copy of all the map entries and then SYSCTL_OUT that. */ DRM_LOCK(); mapcount = 0; TAILQ_FOREACH(map, &dev->maplist, link) mapcount++; tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, M_DRM, M_NOWAIT); if (tempmaps == NULL) { DRM_UNLOCK(); return ENOMEM; } i = 0; TAILQ_FOREACH(map, &dev->maplist, link) tempmaps[i++] = *map; DRM_UNLOCK(); DRM_SYSCTL_PRINT("\nslot offset size type flags " "address mtrr\n"); for (i = 0; i < mapcount; i++) { map = &tempmaps[i]; if (map->type < 0 || map->type > 4) type = "??"; else type = types[map->type]; if (!map->mtrr) yesno = "no"; else yesno = "yes"; DRM_SYSCTL_PRINT( "%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx %s\n", i, map->offset, map->size, type, map->flags, (unsigned long)map->handle, yesno); } SYSCTL_OUT(req, "", 1); done: free(tempmaps, M_DRM); return retcode; } static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS { drm_device_t *dev = arg1; drm_device_dma_t *dma = dev->dma; drm_device_dma_t tempdma; int *templists; int i; char buf[128]; int retcode; /* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary * copy of the whole structure and the relevant data from buflist. */ DRM_LOCK(); if (dma == NULL) { DRM_UNLOCK(); return 0; } DRM_SPINLOCK(&dev->dma_lock); tempdma = *dma; templists = malloc(sizeof(int) * dma->buf_count, M_DRM, M_NOWAIT); for (i = 0; i < dma->buf_count; i++) templists[i] = dma->buflist[i]->list; dma = &tempdma; DRM_SPINUNLOCK(&dev->dma_lock); DRM_UNLOCK(); DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n"); for (i = 0; i <= DRM_MAX_ORDER; i++) { if (dma->bufs[i].buf_count) DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n", i, dma->bufs[i].buf_size, dma->bufs[i].buf_count, atomic_read(&dma->bufs[i] .freelist.count), dma->bufs[i].seg_count, dma->bufs[i].seg_count *(1 << dma->bufs[i].page_order), (dma->bufs[i].seg_count * (1 << dma->bufs[i].page_order)) * PAGE_SIZE / 1024); } DRM_SYSCTL_PRINT("\n"); for (i = 0; i < dma->buf_count; i++) { if (i && !(i%32)) DRM_SYSCTL_PRINT("\n"); DRM_SYSCTL_PRINT(" %d", templists[i]); } DRM_SYSCTL_PRINT("\n"); SYSCTL_OUT(req, "", 1); done: free(templists, M_DRM); return retcode; } static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS { drm_device_t *dev = arg1; drm_file_t *priv, *tempprivs; char buf[128]; int retcode; int privcount, i; DRM_LOCK(); privcount = 0; TAILQ_FOREACH(priv, &dev->files, link) privcount++; tempprivs = malloc(sizeof(drm_file_t) * privcount, M_DRM, M_NOWAIT); if (tempprivs == NULL) { DRM_UNLOCK(); return ENOMEM; } i = 0; TAILQ_FOREACH(priv, &dev->files, link) tempprivs[i++] = *priv; DRM_UNLOCK(); DRM_SYSCTL_PRINT("\na dev pid uid magic ioctls\n"); for (i = 0; i < privcount; i++) { priv = &tempprivs[i]; DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n", priv->authenticated ? 'y' : 'n', priv->minor, priv->pid, priv->uid, priv->magic, priv->ioctl_count); } SYSCTL_OUT(req, "", 1); done: free(tempprivs, M_DRM); return retcode; } Index: head/sys/dev/drm/drm_vm.c =================================================================== --- head/sys/dev/drm/drm_vm.c (revision 152908) +++ head/sys/dev/drm/drm_vm.c (revision 152909) @@ -1,127 +1,134 @@ /*- * Copyright 2003 Eric Anholt * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #if defined(__FreeBSD__) && __FreeBSD_version >= 500102 int drm_mmap(struct cdev *kdev, vm_offset_t offset, vm_paddr_t *paddr, int prot) #elif defined(__FreeBSD__) int drm_mmap(dev_t kdev, vm_offset_t offset, int prot) #elif defined(__NetBSD__) || defined(__OpenBSD__) paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) #endif { DRM_DEVICE; drm_local_map_t *map; drm_file_t *priv; drm_map_type_t type; +#ifdef __FreeBSD__ + vm_paddr_t phys; +#else + paddr_t phys; +#endif DRM_LOCK(); priv = drm_find_file_by_proc(dev, DRM_CURPROC); DRM_UNLOCK(); if (priv == NULL) { DRM_ERROR("can't find authenticator\n"); return EINVAL; } if (!priv->authenticated) return DRM_ERR(EACCES); - DRM_SPINLOCK(&dev->dma_lock); if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) { drm_device_dma_t *dma = dev->dma; + DRM_SPINLOCK(&dev->dma_lock); + if (dma->pagelist != NULL) { unsigned long page = offset >> PAGE_SHIFT; unsigned long phys = dma->pagelist[page]; #if defined(__FreeBSD__) && __FreeBSD_version >= 500102 *paddr = phys; DRM_SPINUNLOCK(&dev->dma_lock); return 0; #else return atop(phys); #endif } else { DRM_SPINUNLOCK(&dev->dma_lock); return -1; } + DRM_SPINUNLOCK(&dev->dma_lock); } - DRM_SPINUNLOCK(&dev->dma_lock); /* A sequential search of a linked list is fine here because: 1) there will only be about 5-10 entries in the list and, 2) a DRI client only has to do this mapping once, so it doesn't have to be optimized for performance, even if the list was a bit longer. */ DRM_LOCK(); TAILQ_FOREACH(map, &dev->maplist, link) { if (offset >= map->offset && offset < map->offset + map->size) break; } if (map == NULL) { DRM_UNLOCK(); DRM_DEBUG("can't find map\n"); return -1; } - if (((map->flags&_DRM_RESTRICTED) && DRM_SUSER(DRM_CURPROC))) { + if (((map->flags&_DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) { DRM_UNLOCK(); DRM_DEBUG("restricted map\n"); return -1; } type = map->type; DRM_UNLOCK(); switch (type) { case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: case _DRM_AGP: -#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 - *paddr = offset; - return 0; -#else - return atop(offset); -#endif + phys = offset; + break; + case _DRM_CONSISTENT: + phys = vtophys((char *)map->handle + (offset - map->offset)); + break; case _DRM_SCATTER_GATHER: case _DRM_SHM: -#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 - *paddr = vtophys(offset); - return 0; -#else - return atop(vtophys(offset)); -#endif + phys = vtophys(offset); + break; default: + DRM_ERROR("bad map type %d\n", type); return -1; /* This should never happen. */ } - DRM_DEBUG("bailing out\n"); - return -1; +#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 + *paddr = phys; + return 0; +#else + return atop(phys); +#endif } Index: head/sys/dev/drm/i915_dma.c =================================================================== --- head/sys/dev/drm/i915_dma.c (revision 152908) +++ head/sys/dev/drm/i915_dma.c (revision 152909) @@ -1,728 +1,778 @@ /* i915_dma.c -- DMA support for the I915 -*- linux-c -*- - * - * $FreeBSD$ */ -/************************************************************************** - * +/*- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * - **************************************************************************/ + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" +#include +__FBSDID("$FreeBSD$"); +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/i915_drm.h" +#include "dev/drm/i915_drv.h" + /* Really want an OS-independent resettable timer. Would like to have * this loop run for (eg) 3 sec, but have the timer reset every time * the head pointer changes, so that EBUSY only happens if the ring * actually stalls for (eg) 3 seconds. */ int i915_wait_ring(drm_device_t * dev, int n, const char *caller) { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_ring_buffer_t *ring = &(dev_priv->ring); u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; int i; for (i = 0; i < 10000; i++) { ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->Size; if (ring->space >= n) return 0; dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; if (ring->head != last_head) i = 0; last_head = ring->head; } return DRM_ERR(EBUSY); } void i915_kernel_lost_context(drm_device_t * dev) { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_ring_buffer_t *ring = &(dev_priv->ring); ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR; ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->Size; if (ring->head == ring->tail) dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; } static int i915_dma_cleanup(drm_device_t * dev) { /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if (dev->irq) drm_irq_uninstall(dev); if (dev->dev_private) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; if (dev_priv->ring.virtual_start) { drm_core_ioremapfree(&dev_priv->ring.map, dev); } - if (dev_priv->hw_status_page) { - drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page, - dev_priv->dma_status_page); + if (dev_priv->status_page_dmah) { + drm_pci_free(dev, dev_priv->status_page_dmah); /* Need to rewrite hardware status page */ I915_WRITE(0x02080, 0x1ffff000); } drm_free(dev->dev_private, sizeof(drm_i915_private_t), DRM_MEM_DRIVER); dev->dev_private = NULL; } return 0; } static int i915_initialize(drm_device_t * dev, drm_i915_private_t * dev_priv, drm_i915_init_t * init) { memset(dev_priv, 0, sizeof(drm_i915_private_t)); DRM_GETSAREA(); if (!dev_priv->sarea) { DRM_ERROR("can not find sarea!\n"); dev->dev_private = (void *)dev_priv; i915_dma_cleanup(dev); return DRM_ERR(EINVAL); } dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio_map) { dev->dev_private = (void *)dev_priv; i915_dma_cleanup(dev); DRM_ERROR("can not find mmio map!\n"); return DRM_ERR(EINVAL); } dev_priv->sarea_priv = (drm_i915_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; dev_priv->ring.map.offset = init->ring_start; dev_priv->ring.map.size = init->ring_size; dev_priv->ring.map.type = 0; dev_priv->ring.map.flags = 0; dev_priv->ring.map.mtrr = 0; drm_core_ioremap(&dev_priv->ring.map, dev); if (dev_priv->ring.map.handle == NULL) { dev->dev_private = (void *)dev_priv; i915_dma_cleanup(dev); DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); return DRM_ERR(ENOMEM); } dev_priv->ring.virtual_start = dev_priv->ring.map.handle; dev_priv->back_offset = init->back_offset; dev_priv->front_offset = init->front_offset; dev_priv->current_page = 0; dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; /* We are using separate values as placeholders for mechanisms for * private backbuffer/depthbuffer usage. */ dev_priv->use_mi_batchbuffer_start = 0; /* Allow hardware batchbuffers unless told otherwise. */ dev_priv->allow_batchbuffer = 1; /* Program Hardware Status Page */ - dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, - 0xffffffff, &dev_priv->dma_status_page); + dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, + 0xffffffff); - if (!dev_priv->hw_status_page) { + if (!dev_priv->status_page_dmah) { dev->dev_private = (void *)dev_priv; i915_dma_cleanup(dev); DRM_ERROR("Can not allocate hardware status page\n"); return DRM_ERR(ENOMEM); } + dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; + dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; + memset(dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); I915_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); dev->dev_private = (void *)dev_priv; return 0; } static int i915_dma_resume(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); if (!dev_priv->sarea) { DRM_ERROR("can not find sarea!\n"); return DRM_ERR(EINVAL); } if (!dev_priv->mmio_map) { DRM_ERROR("can not find mmio map!\n"); return DRM_ERR(EINVAL); } if (dev_priv->ring.map.handle == NULL) { DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); return DRM_ERR(ENOMEM); } /* Program Hardware Status Page */ if (!dev_priv->hw_status_page) { DRM_ERROR("Can not find hardware status page\n"); return DRM_ERR(EINVAL); } DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); I915_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); return 0; } static int i915_dma_init(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv; drm_i915_init_t init; int retcode = 0; DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data, sizeof(init)); switch (init.func) { case I915_INIT_DMA: dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return DRM_ERR(ENOMEM); retcode = i915_initialize(dev, dev_priv, &init); break; case I915_CLEANUP_DMA: retcode = i915_dma_cleanup(dev); break; case I915_RESUME_DMA: retcode = i915_dma_resume(dev); break; default: retcode = -EINVAL; break; } return retcode; } /* Implement basically the same security restrictions as hardware does * for MI_BATCH_NON_SECURE. These can be made stricter at any time. * * Most of the calculations below involve calculating the size of a * particular instruction. It's important to get the size right as * that tells us where the next instruction to check is. Any illegal * instruction detected will be given a size of zero, which is a * signal to abort the rest of the buffer. */ static int do_validate_cmd(int cmd) { switch (((cmd >> 29) & 0x7)) { case 0x0: switch ((cmd >> 23) & 0x3f) { case 0x0: return 1; /* MI_NOOP */ case 0x4: return 1; /* MI_FLUSH */ default: return 0; /* disallow everything else */ } break; case 0x1: return 0; /* reserved */ case 0x2: return (cmd & 0xff) + 2; /* 2d commands */ case 0x3: if (((cmd >> 24) & 0x1f) <= 0x18) return 1; switch ((cmd >> 24) & 0x1f) { case 0x1c: return 1; case 0x1d: switch ((cmd >> 16) & 0xff) { case 0x3: return (cmd & 0x1f) + 2; case 0x4: return (cmd & 0xf) + 2; default: return (cmd & 0xffff) + 2; } case 0x1e: if (cmd & (1 << 23)) return (cmd & 0xffff) + 1; else return 1; case 0x1f: if ((cmd & (1 << 23)) == 0) /* inline vertices */ return (cmd & 0x1ffff) + 2; else if (cmd & (1 << 17)) /* indirect random */ if ((cmd & 0xffff) == 0) return 0; /* unknown length, too hard */ else return (((cmd & 0xffff) + 1) / 2) + 1; else return 2; /* indirect sequential */ default: return 0; } default: return 0; } return 0; } static int validate_cmd(int cmd) { int ret = do_validate_cmd(cmd); /* printk("validate_cmd( %x ): %d\n", cmd, ret); */ return ret; } static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords) { drm_i915_private_t *dev_priv = dev->dev_private; int i; RING_LOCALS; for (i = 0; i < dwords;) { int cmd, sz; if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) return DRM_ERR(EINVAL); /* printk("%d/%d ", i, dwords); */ if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) return DRM_ERR(EINVAL); BEGIN_LP_RING(sz); OUT_RING(cmd); while (++i, --sz) { if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) { return DRM_ERR(EINVAL); } OUT_RING(cmd); } ADVANCE_LP_RING(); } return 0; } static int i915_emit_box(drm_device_t * dev, drm_clip_rect_t __user * boxes, int i, int DR1, int DR4) { drm_i915_private_t *dev_priv = dev->dev_private; drm_clip_rect_t box; RING_LOCALS; if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { return EFAULT; } if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { DRM_ERROR("Bad box %d,%d..%d,%d\n", box.x1, box.y1, box.x2, box.y2); return DRM_ERR(EINVAL); } BEGIN_LP_RING(6); OUT_RING(GFX_OP_DRAWRECT_INFO); OUT_RING(DR1); OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); OUT_RING(DR4); OUT_RING(0); ADVANCE_LP_RING(); return 0; } static int i915_dispatch_cmdbuffer(drm_device_t * dev, drm_i915_cmdbuffer_t * cmd) { int nbox = cmd->num_cliprects; int i = 0, count, ret; if (cmd->sz & 0x3) { DRM_ERROR("alignment"); return DRM_ERR(EINVAL); } i915_kernel_lost_context(dev); count = nbox ? nbox : 1; for (i = 0; i < count; i++) { if (i < nbox) { ret = i915_emit_box(dev, cmd->cliprects, i, cmd->DR1, cmd->DR4); if (ret) return ret; } ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4); if (ret) return ret; } return 0; } static int i915_dispatch_batchbuffer(drm_device_t * dev, drm_i915_batchbuffer_t * batch) { drm_i915_private_t *dev_priv = dev->dev_private; drm_clip_rect_t __user *boxes = batch->cliprects; int nbox = batch->num_cliprects; int i = 0, count; RING_LOCALS; if ((batch->start | batch->used) & 0x7) { DRM_ERROR("alignment"); return DRM_ERR(EINVAL); } i915_kernel_lost_context(dev); count = nbox ? nbox : 1; for (i = 0; i < count; i++) { if (i < nbox) { int ret = i915_emit_box(dev, boxes, i, batch->DR1, batch->DR4); if (ret) return ret; } if (dev_priv->use_mi_batchbuffer_start) { BEGIN_LP_RING(2); OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); OUT_RING(batch->start | MI_BATCH_NON_SECURE); ADVANCE_LP_RING(); } else { BEGIN_LP_RING(4); OUT_RING(MI_BATCH_BUFFER); OUT_RING(batch->start | MI_BATCH_NON_SECURE); OUT_RING(batch->start + batch->used - 4); OUT_RING(0); ADVANCE_LP_RING(); } } dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; BEGIN_LP_RING(4); OUT_RING(CMD_STORE_DWORD_IDX); OUT_RING(20); OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); return 0; } static int i915_dispatch_flip(drm_device_t * dev) { drm_i915_private_t *dev_priv = dev->dev_private; RING_LOCALS; DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, dev_priv->current_page, dev_priv->sarea_priv->pf_current_page); i915_kernel_lost_context(dev); BEGIN_LP_RING(2); OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); OUT_RING(0); ADVANCE_LP_RING(); BEGIN_LP_RING(6); OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); OUT_RING(0); if (dev_priv->current_page == 0) { OUT_RING(dev_priv->back_offset); dev_priv->current_page = 1; } else { OUT_RING(dev_priv->front_offset); dev_priv->current_page = 0; } OUT_RING(0); ADVANCE_LP_RING(); BEGIN_LP_RING(2); OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); OUT_RING(0); ADVANCE_LP_RING(); dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; BEGIN_LP_RING(4); OUT_RING(CMD_STORE_DWORD_IDX); OUT_RING(20); OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; return 0; } static int i915_quiescent(drm_device_t * dev) { drm_i915_private_t *dev_priv = dev->dev_private; i915_kernel_lost_context(dev); return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__); } static int i915_flush_ioctl(DRM_IOCTL_ARGS) { DRM_DEVICE; LOCK_TEST_WITH_RETURN(dev, filp); return i915_quiescent(dev); } static int i915_batchbuffer(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_batchbuffer_t batch; int ret; if (!dev_priv->allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data, sizeof(batch)); DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n", batch.start, batch.used, batch.num_cliprects); LOCK_TEST_WITH_RETURN(dev, filp); if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects, batch.num_cliprects * sizeof(drm_clip_rect_t))) return DRM_ERR(EFAULT); ret = i915_dispatch_batchbuffer(dev, &batch); sarea_priv->last_dispatch = (int)hw_status[5]; return ret; } static int i915_cmdbuffer(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_cmdbuffer_t cmdbuf; int ret; DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data, sizeof(cmdbuf)); DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects); LOCK_TEST_WITH_RETURN(dev, filp); if (cmdbuf.num_cliprects && DRM_VERIFYAREA_READ(cmdbuf.cliprects, cmdbuf.num_cliprects * sizeof(drm_clip_rect_t))) { DRM_ERROR("Fault accessing cliprects\n"); return DRM_ERR(EFAULT); } ret = i915_dispatch_cmdbuffer(dev, &cmdbuf); if (ret) { DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); return ret; } sarea_priv->last_dispatch = (int)hw_status[5]; return 0; } static int i915_do_cleanup_pageflip(drm_device_t * dev) { drm_i915_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); if (dev_priv->current_page != 0) i915_dispatch_flip(dev); return 0; } static int i915_flip_bufs(DRM_IOCTL_ARGS) { DRM_DEVICE; DRM_DEBUG("%s\n", __FUNCTION__); LOCK_TEST_WITH_RETURN(dev, filp); return i915_dispatch_flip(dev); } static int i915_getparam(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_getparam_t param; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data, sizeof(param)); switch (param.param) { case I915_PARAM_IRQ_ACTIVE: value = dev->irq ? 1 : 0; break; case I915_PARAM_ALLOW_BATCHBUFFER: value = dev_priv->allow_batchbuffer ? 1 : 0; break; default: DRM_ERROR("Unkown parameter %d\n", param.param); return DRM_ERR(EINVAL); } if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { DRM_ERROR("DRM_COPY_TO_USER failed\n"); return DRM_ERR(EFAULT); } return 0; } static int i915_setparam(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_setparam_t param; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data, sizeof(param)); switch (param.param) { case I915_SETPARAM_USE_MI_BATCHBUFFER_START: dev_priv->use_mi_batchbuffer_start = param.value; break; case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY: dev_priv->tex_lru_log_granularity = param.value; break; case I915_SETPARAM_ALLOW_BATCHBUFFER: dev_priv->allow_batchbuffer = param.value; break; default: DRM_ERROR("unknown parameter %d\n", param.param); return DRM_ERR(EINVAL); } return 0; } -void i915_driver_pretakedown(drm_device_t * dev) +int i915_driver_load(drm_device_t *dev, unsigned long flags) { + /* i915 has 4 more counters */ + dev->counters += 4; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; + + return 0; +} + +void i915_driver_lastclose(drm_device_t * dev) +{ if (dev->dev_private) { drm_i915_private_t *dev_priv = dev->dev_private; i915_mem_takedown(&(dev_priv->agp_heap)); } i915_dma_cleanup(dev); } -void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp) +void i915_driver_preclose(drm_device_t * dev, DRMFILE filp) { if (dev->dev_private) { drm_i915_private_t *dev_priv = dev->dev_private; if (dev_priv->page_flipping) { i915_do_cleanup_pageflip(dev); } i915_mem_release(dev, filp, dev_priv->agp_heap); } } drm_ioctl_desc_t i915_ioctls[] = { - [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1}, - [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0}, - [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0}, - [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0}, - [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0}, - [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0}, - [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0}, - [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1}, - [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0}, - [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0}, - [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1}, - [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0} + [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH} }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); + +/** + * Determine if the device really is AGP or not. + * + * All Intel graphics chipsets are treated as AGP, even if they are really + * PCI-e. + * + * \param dev The device to be tested. + * + * \returns + * A value of 1 is always retured to indictate every i9x5 is AGP. + */ +int i915_driver_device_is_agp(drm_device_t * dev) +{ + return 1; +} Index: head/sys/dev/drm/i915_drm.h =================================================================== --- head/sys/dev/drm/i915_drm.h (revision 152908) +++ head/sys/dev/drm/i915_drm.h (revision 152909) @@ -1,169 +1,196 @@ -/* $FreeBSD$ */ +/*- + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +__FBSDID("$FreeBSD$"); + #ifndef _I915_DRM_H_ #define _I915_DRM_H_ /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. */ -#include "drm.h" +#include "dev/drm/drm.h" /* Each region is a minimum of 16k, and there are at most 255 of them. */ #define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use * of chars for next/prev indices */ #define I915_LOG_MIN_TEX_REGION_SIZE 14 typedef struct _drm_i915_init { enum { I915_INIT_DMA = 0x01, I915_CLEANUP_DMA = 0x02, I915_RESUME_DMA = 0x03 } func; unsigned int mmio_offset; int sarea_priv_offset; unsigned int ring_start; unsigned int ring_end; unsigned int ring_size; unsigned int front_offset; unsigned int back_offset; unsigned int depth_offset; unsigned int w; unsigned int h; unsigned int pitch; unsigned int pitch_bits; unsigned int back_pitch; unsigned int depth_pitch; unsigned int cpp; unsigned int chipset; } drm_i915_init_t; typedef struct _drm_i915_sarea { drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1]; int last_upload; /* last time texture was uploaded */ int last_enqueue; /* last time a buffer was enqueued */ int last_dispatch; /* age of the most recently dispatched buffer */ int ctxOwner; /* last context to upload state */ int texAge; int pf_enabled; /* is pageflipping allowed? */ int pf_active; int pf_current_page; /* which buffer is being displayed? */ int perf_boxes; /* performance boxes to be displayed */ } drm_i915_sarea_t; /* Flags for perf_boxes */ #define I915_BOX_RING_EMPTY 0x1 #define I915_BOX_FLIP 0x2 #define I915_BOX_WAIT 0x4 #define I915_BOX_TEXTURE_LOAD 0x8 #define I915_BOX_LOST_CONTEXT 0x10 /* I915 specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ #define DRM_I915_INIT 0x00 #define DRM_I915_FLUSH 0x01 #define DRM_I915_FLIP 0x02 #define DRM_I915_BATCHBUFFER 0x03 #define DRM_I915_IRQ_EMIT 0x04 #define DRM_I915_IRQ_WAIT 0x05 #define DRM_I915_GETPARAM 0x06 #define DRM_I915_SETPARAM 0x07 #define DRM_I915_ALLOC 0x08 #define DRM_I915_FREE 0x09 #define DRM_I915_INIT_HEAP 0x0a #define DRM_I915_CMDBUFFER 0x0b #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) #define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP) #define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t) #define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t) #define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t) #define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t) #define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t) #define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t) #define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t) #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. */ typedef struct _drm_i915_batchbuffer { int start; /* agp offset */ int used; /* nr bytes in use */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ int num_cliprects; /* mulitpass with multiple cliprects? */ drm_clip_rect_t __user *cliprects; /* pointer to userspace cliprects */ } drm_i915_batchbuffer_t; /* As above, but pass a pointer to userspace buffer which can be * validated by the kernel prior to sending to hardware. */ typedef struct _drm_i915_cmdbuffer { char __user *buf; /* pointer to userspace command buffer */ int sz; /* nr bytes in buf */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ int num_cliprects; /* mulitpass with multiple cliprects? */ drm_clip_rect_t __user *cliprects; /* pointer to userspace cliprects */ } drm_i915_cmdbuffer_t; /* Userspace can request & wait on irq's: */ typedef struct drm_i915_irq_emit { int __user *irq_seq; } drm_i915_irq_emit_t; typedef struct drm_i915_irq_wait { int irq_seq; } drm_i915_irq_wait_t; /* Ioctl to query kernel params: */ #define I915_PARAM_IRQ_ACTIVE 1 #define I915_PARAM_ALLOW_BATCHBUFFER 2 typedef struct drm_i915_getparam { int param; int __user *value; } drm_i915_getparam_t; /* Ioctl to set kernel params: */ #define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 #define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 #define I915_SETPARAM_ALLOW_BATCHBUFFER 3 typedef struct drm_i915_setparam { int param; int value; } drm_i915_setparam_t; /* A memory manager for regions of shared memory: */ #define I915_MEM_REGION_AGP 1 typedef struct drm_i915_mem_alloc { int region; int alignment; int size; int __user *region_offset; /* offset from start of fb or agp */ } drm_i915_mem_alloc_t; typedef struct drm_i915_mem_free { int region; int region_offset; } drm_i915_mem_free_t; typedef struct drm_i915_mem_init_heap { int region; int size; int start; } drm_i915_mem_init_heap_t; #endif /* _I915_DRM_H_ */ Index: head/sys/dev/drm/i915_drv.c =================================================================== --- head/sys/dev/drm/i915_drv.c (revision 152908) +++ head/sys/dev/drm/i915_drv.c (revision 152909) @@ -1,111 +1,112 @@ /* i915_drv.c -- ATI Radeon driver -*- linux-c -*- * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com */ /*- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * - * $FreeBSD$ */ -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" -#include "drm_pciids.h" +#include +__FBSDID("$FreeBSD$"); +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/i915_drm.h" +#include "dev/drm/i915_drv.h" +#include "dev/drm/drm_pciids.h" + /* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */ static drm_pci_id_list_t i915_pciidlist[] = { i915_PCI_IDS }; -extern drm_ioctl_desc_t i915_ioctls[]; -extern int i915_max_ioctl; - static void i915_configure(drm_device_t *dev) { - dev->dev_priv_size = 1; /* No dev_priv */ - dev->prerelease = i915_driver_prerelease; - dev->pretakedown = i915_driver_pretakedown; - dev->irq_preinstall = i915_driver_irq_preinstall; - dev->irq_postinstall = i915_driver_irq_postinstall; - dev->irq_uninstall = i915_driver_irq_uninstall; - dev->irq_handler = i915_driver_irq_handler; + dev->driver.buf_priv_size = 1; /* No dev_priv */ + dev->driver.load = i915_driver_load; + dev->driver.preclose = i915_driver_preclose; + dev->driver.lastclose = i915_driver_lastclose; + dev->driver.device_is_agp = i915_driver_device_is_agp, + dev->driver.irq_preinstall = i915_driver_irq_preinstall; + dev->driver.irq_postinstall = i915_driver_irq_postinstall; + dev->driver.irq_uninstall = i915_driver_irq_uninstall; + dev->driver.irq_handler = i915_driver_irq_handler; - dev->driver_ioctls = i915_ioctls; - dev->max_driver_ioctl = i915_max_ioctl; + dev->driver.ioctls = i915_ioctls; + dev->driver.max_ioctl = i915_max_ioctl; - dev->driver_name = DRIVER_NAME; - dev->driver_desc = DRIVER_DESC; - dev->driver_date = DRIVER_DATE; - dev->driver_major = DRIVER_MAJOR; - dev->driver_minor = DRIVER_MINOR; - dev->driver_patchlevel = DRIVER_PATCHLEVEL; + dev->driver.name = DRIVER_NAME; + dev->driver.desc = DRIVER_DESC; + dev->driver.date = DRIVER_DATE; + dev->driver.major = DRIVER_MAJOR; + dev->driver.minor = DRIVER_MINOR; + dev->driver.patchlevel = DRIVER_PATCHLEVEL; - dev->use_agp = 1; - dev->require_agp = 1; - dev->use_mtrr = 1; - dev->use_irq = 1; + dev->driver.use_agp = 1; + dev->driver.require_agp = 1; + dev->driver.use_mtrr = 1; + dev->driver.use_irq = 1; } #ifdef __FreeBSD__ static int i915_probe(device_t dev) { return drm_probe(dev, i915_pciidlist); } static int i915_attach(device_t nbdev) { drm_device_t *dev = device_get_softc(nbdev); bzero(dev, sizeof(drm_device_t)); i915_configure(dev); return drm_attach(nbdev, i915_pciidlist); } static device_method_t i915_methods[] = { /* Device interface */ DEVMETHOD(device_probe, i915_probe), DEVMETHOD(device_attach, i915_attach), DEVMETHOD(device_detach, drm_detach), { 0, 0 } }; static driver_t i915_driver = { "drmsub", i915_methods, sizeof(drm_device_t) }; extern devclass_t drm_devclass; DRIVER_MODULE(i915, pci, i915_driver, drm_devclass, 0, 0); MODULE_DEPEND(i915, drm, 1, 1, 1); #elif defined(__NetBSD__) || defined(__OpenBSD__) CFDRIVER_DECL(i915, DV_TTY, NULL); #endif Index: head/sys/dev/drm/i915_drv.h =================================================================== --- head/sys/dev/drm/i915_drv.h (revision 152908) +++ head/sys/dev/drm/i915_drv.h (revision 152909) @@ -1,239 +1,268 @@ /* i915_drv.h -- Private header for the I915 driver -*- linux-c -*- - * - * $FreeBSD$ */ -/************************************************************************** - * +/* + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * - **************************************************************************/ + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +__FBSDID("$FreeBSD$"); + #ifndef _I915_DRV_H_ #define _I915_DRV_H_ /* General customization: */ #define DRIVER_AUTHOR "Tungsten Graphics, Inc." #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" #define DRIVER_DATE "20041217" /* Interface history: * * 1.1: Original. * 1.2: Add Power Management */ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 2 #define DRIVER_PATCHLEVEL 0 typedef struct _drm_i915_ring_buffer { int tail_mask; unsigned long Start; unsigned long End; unsigned long Size; u8 *virtual_start; int head; int tail; int space; drm_local_map_t map; } drm_i915_ring_buffer_t; struct mem_block { struct mem_block *next; struct mem_block *prev; int start; int size; DRMFILE filp; /* 0: free, -1: heap, other: real files */ }; typedef struct drm_i915_private { drm_local_map_t *sarea; drm_local_map_t *mmio_map; drm_i915_sarea_t *sarea_priv; drm_i915_ring_buffer_t ring; + drm_dma_handle_t *status_page_dmah; void *hw_status_page; - unsigned long counter; dma_addr_t dma_status_page; + unsigned long counter; int back_offset; int front_offset; int current_page; int page_flipping; int use_mi_batchbuffer_start; wait_queue_head_t irq_queue; atomic_t irq_received; atomic_t irq_emitted; int tex_lru_log_granularity; int allow_batchbuffer; struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; } drm_i915_private_t; +extern drm_ioctl_desc_t i915_ioctls[]; +extern int i915_max_ioctl; + /* i915_dma.c */ extern void i915_kernel_lost_context(drm_device_t * dev); -extern void i915_driver_pretakedown(drm_device_t * dev); -extern void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp); +extern int i915_driver_load(struct drm_device *, unsigned long flags); +extern void i915_driver_lastclose(drm_device_t * dev); +extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp); +extern int i915_driver_device_is_agp(drm_device_t * dev); +extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); /* i915_irq.c */ extern int i915_irq_emit(DRM_IOCTL_ARGS); extern int i915_irq_wait(DRM_IOCTL_ARGS); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(drm_device_t * dev); extern void i915_driver_irq_postinstall(drm_device_t * dev); extern void i915_driver_irq_uninstall(drm_device_t * dev); /* i915_mem.c */ extern int i915_mem_alloc(DRM_IOCTL_ARGS); extern int i915_mem_free(DRM_IOCTL_ARGS); extern int i915_mem_init_heap(DRM_IOCTL_ARGS); extern void i915_mem_takedown(struct mem_block **heap); extern void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap); #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val)) #define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg)) #define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val)) #define I915_VERBOSE 0 #define RING_LOCALS unsigned int outring, ringmask, outcount; \ volatile char *virt; #define BEGIN_LP_RING(n) do { \ if (I915_VERBOSE) \ DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ n, __FUNCTION__); \ if (dev_priv->ring.space < n*4) \ i915_wait_ring(dev, n*4, __FUNCTION__); \ outcount = 0; \ outring = dev_priv->ring.tail; \ ringmask = dev_priv->ring.tail_mask; \ virt = dev_priv->ring.virtual_start; \ } while (0) #define OUT_RING(n) do { \ if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ *(volatile unsigned int *)(virt + outring) = n; \ outcount++; \ outring += 4; \ outring &= ringmask; \ } while (0) #define ADVANCE_LP_RING() do { \ if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \ dev_priv->ring.tail = outring; \ dev_priv->ring.space -= outcount * 4; \ I915_WRITE(LP_RING + RING_TAIL, outring); \ } while(0) extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) #define CMD_REPORT_HEAD (7<<23) #define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1) #define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1) #define INST_PARSER_CLIENT 0x00000000 #define INST_OP_FLUSH 0x02000000 #define INST_FLUSH_MAP_CACHE 0x00000001 #define BB1_START_ADDR_MASK (~0x7) #define BB1_PROTECTED (1<<0) #define BB1_UNPROTECTED (0<<0) #define BB2_END_ADDR_MASK (~0x7) #define I915REG_HWSTAM 0x02098 #define I915REG_INT_IDENTITY_R 0x020a4 #define I915REG_INT_MASK_R 0x020a8 #define I915REG_INT_ENABLE_R 0x020a0 #define SRX_INDEX 0x3c4 #define SRX_DATA 0x3c5 #define SR01 1 #define SR01_SCREEN_OFF (1<<5) #define PPCR 0x61204 #define PPCR_ON (1<<0) #define DVOB 0x61140 #define DVOB_ON (1<<31) #define DVOC 0x61160 #define DVOC_ON (1<<31) #define LVDS 0x61180 #define LVDS_ON (1<<31) #define ADPA 0x61100 #define ADPA_DPMS_MASK (~(3<<10)) #define ADPA_DPMS_ON (0<<10) #define ADPA_DPMS_SUSPEND (1<<10) #define ADPA_DPMS_STANDBY (2<<10) #define ADPA_DPMS_OFF (3<<10) #define NOPID 0x2094 #define LP_RING 0x2030 #define HP_RING 0x2040 #define RING_TAIL 0x00 #define TAIL_ADDR 0x001FFFF8 #define RING_HEAD 0x04 #define HEAD_WRAP_COUNT 0xFFE00000 #define HEAD_WRAP_ONE 0x00200000 #define HEAD_ADDR 0x001FFFFC #define RING_START 0x08 #define START_ADDR 0x0xFFFFF000 #define RING_LEN 0x0C #define RING_NR_PAGES 0x001FF000 #define RING_REPORT_MASK 0x00000006 #define RING_REPORT_64K 0x00000002 #define RING_REPORT_128K 0x00000004 #define RING_NO_REPORT 0x00000000 #define RING_VALID_MASK 0x00000001 #define RING_VALID 0x00000001 #define RING_INVALID 0x00000000 #define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19)) #define SC_UPDATE_SCISSOR (0x1<<1) #define SC_ENABLE_MASK (0x1<<0) #define SC_ENABLE (0x1<<0) #define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1)) #define SCI_YMIN_MASK (0xffff<<16) #define SCI_XMIN_MASK (0xffff<<0) #define SCI_YMAX_MASK (0xffff<<16) #define SCI_XMAX_MASK (0xffff<<0) #define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19)) #define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1) #define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) #define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) #define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4) #define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) #define MI_BATCH_BUFFER ((0x30<<23)|1) #define MI_BATCH_BUFFER_START (0x31<<23) #define MI_BATCH_BUFFER_END (0xA<<23) #define MI_BATCH_NON_SECURE (1) #define MI_WAIT_FOR_EVENT ((0x3<<23)) #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) #define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) #define MI_LOAD_SCAN_LINES_INCL ((0x12<<23)) #define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) #define ASYNC_FLIP (1<<22) #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) #endif Index: head/sys/dev/drm/i915_irq.c =================================================================== --- head/sys/dev/drm/i915_irq.c (revision 152908) +++ head/sys/dev/drm/i915_irq.c (revision 152909) @@ -1,163 +1,183 @@ -/* i915_dma.c -- DMA support for the I915 -*- linux-c -*- - * - * $FreeBSD$ +/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*- */ -/************************************************************************** - * +/*- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * - **************************************************************************/ + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" +#include +__FBSDID("$FreeBSD$"); + +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/i915_drm.h" +#include "dev/drm/i915_drv.h" #define USER_INT_FLAG 0x2 #define MAX_NOPID ((u32)~0) #define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5]) irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u16 temp; temp = I915_READ16(I915REG_INT_IDENTITY_R); temp &= USER_INT_FLAG; DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); if (temp == 0) return IRQ_NONE; I915_WRITE16(I915REG_INT_IDENTITY_R, temp); DRM_WAKEUP(&dev_priv->irq_queue); return IRQ_HANDLED; } static int i915_emit_irq(drm_device_t * dev) { drm_i915_private_t *dev_priv = dev->dev_private; u32 ret; RING_LOCALS; i915_kernel_lost_context(dev); DRM_DEBUG("%s\n", __FUNCTION__); ret = dev_priv->counter; BEGIN_LP_RING(2); OUT_RING(0); OUT_RING(GFX_OP_USER_INTERRUPT); ADVANCE_LP_RING(); return ret; } static int i915_wait_irq(drm_device_t * dev, int irq_nr) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = 0; DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr, READ_BREADCRUMB(dev_priv)); if (READ_BREADCRUMB(dev_priv) >= irq_nr) return 0; dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, READ_BREADCRUMB(dev_priv) >= irq_nr); if (ret == DRM_ERR(EBUSY)) { DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n", __FUNCTION__, READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); } dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); return ret; } /* Needs the lock as it touches the ring. */ int i915_irq_emit(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_irq_emit_t emit; int result; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data, sizeof(emit)); result = i915_emit_irq(dev); if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; } /* Doesn't need the hardware lock. */ int i915_irq_wait(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_irq_wait_t irqwait; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data, sizeof(irqwait)); return i915_wait_irq(dev, irqwait.irq_seq); } /* drm_dma.h hooks */ void i915_driver_irq_preinstall(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; I915_WRITE16(I915REG_HWSTAM, 0xfffe); I915_WRITE16(I915REG_INT_MASK_R, 0x0); I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); } void i915_driver_irq_postinstall(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); } void i915_driver_irq_uninstall(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; if (!dev_priv) return; I915_WRITE16(I915REG_HWSTAM, 0xffff); I915_WRITE16(I915REG_INT_MASK_R, 0xffff); I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); } Index: head/sys/dev/drm/i915_mem.c =================================================================== --- head/sys/dev/drm/i915_mem.c (revision 152908) +++ head/sys/dev/drm/i915_mem.c (revision 152909) @@ -1,350 +1,370 @@ /* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*- - * - * $FreeBSD$ */ -/************************************************************************** - * +/*- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * - **************************************************************************/ + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" +#include +__FBSDID("$FreeBSD$"); + +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/i915_drm.h" +#include "dev/drm/i915_drv.h" /* This memory manager is integrated into the global/local lru * mechanisms used by the clients. Specifically, it operates by * setting the 'in_use' fields of the global LRU to indicate whether * this region is privately allocated to a client. * * This does require the client to actually respect that field. * * Currently no effort is made to allocate 'private' memory in any * clever way - the LRU information isn't used to determine which * block to allocate, and the ring is drained prior to allocations -- * in other words allocation is expensive. */ static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use) { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_tex_region_t *list; unsigned shift, nr; unsigned start; unsigned end; unsigned i; int age; shift = dev_priv->tex_lru_log_granularity; nr = I915_NR_TEX_REGIONS; start = p->start >> shift; end = (p->start + p->size - 1) >> shift; age = ++sarea_priv->texAge; list = sarea_priv->texList; /* Mark the regions with the new flag and update their age. Move * them to head of list to preserve LRU semantics. */ for (i = start; i <= end; i++) { list[i].in_use = in_use; list[i].age = age; /* remove_from_list(i) */ list[(unsigned)list[i].next].prev = list[i].prev; list[(unsigned)list[i].prev].next = list[i].next; /* insert_at_head(list, i) */ list[i].prev = nr; list[i].next = list[nr].next; list[(unsigned)list[nr].next].prev = i; list[nr].next = i; } } /* Very simple allocator for agp memory, working on a static range * already mapped into each client's address space. */ static struct mem_block *split_block(struct mem_block *p, int start, int size, DRMFILE filp) { /* Maybe cut off the start of an existing block */ if (start > p->start) { struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS); if (!newblock) goto out; newblock->start = start; newblock->size = p->size - (start - p->start); newblock->filp = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; p->next = newblock; p->size -= newblock->size; p = newblock; } /* Maybe cut off the end of an existing block */ if (size < p->size) { struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS); if (!newblock) goto out; newblock->start = start + size; newblock->size = p->size - size; newblock->filp = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; p->next = newblock; p->size = size; } out: /* Our block is in the middle */ p->filp = filp; return p; } static struct mem_block *alloc_block(struct mem_block *heap, int size, int align2, DRMFILE filp) { struct mem_block *p; int mask = (1 << align2) - 1; for (p = heap->next; p != heap; p = p->next) { int start = (p->start + mask) & ~mask; if (p->filp == NULL && start + size <= p->start + p->size) return split_block(p, start, size, filp); } return NULL; } static struct mem_block *find_block(struct mem_block *heap, int start) { struct mem_block *p; for (p = heap->next; p != heap; p = p->next) if (p->start == start) return p; return NULL; } static void free_block(struct mem_block *p) { p->filp = NULL; /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ if (p->next->filp == NULL) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; p->next->prev = p; drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS); } if (p->prev->filp == NULL) { struct mem_block *q = p->prev; q->size += p->size; q->next = p->next; q->next->prev = q; drm_free(p, sizeof(*q), DRM_MEM_BUFLISTS); } } /* Initialize. How to check for an uninitialized heap? */ static int init_heap(struct mem_block **heap, int start, int size) { struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFLISTS); if (!blocks) return -ENOMEM; *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFLISTS); if (!*heap) { drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFLISTS); return -ENOMEM; } blocks->start = start; blocks->size = size; blocks->filp = NULL; blocks->next = blocks->prev = *heap; memset(*heap, 0, sizeof(**heap)); (*heap)->filp = (DRMFILE) - 1; (*heap)->next = (*heap)->prev = blocks; return 0; } /* Free all blocks associated with the releasing file. */ void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap) { struct mem_block *p; if (!heap || !heap->next) return; for (p = heap->next; p != heap; p = p->next) { if (p->filp == filp) { p->filp = NULL; mark_block(dev, p, 0); } } /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ for (p = heap->next; p != heap; p = p->next) { while (p->filp == NULL && p->next->filp == NULL) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; p->next->prev = p; drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS); } } } /* Shutdown. */ void i915_mem_takedown(struct mem_block **heap) { struct mem_block *p; if (!*heap) return; for (p = (*heap)->next; p != *heap;) { struct mem_block *q = p; p = p->next; drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS); } drm_free(*heap, sizeof(**heap), DRM_MEM_BUFLISTS); *heap = NULL; } static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region) { switch (region) { case I915_MEM_REGION_AGP: return &dev_priv->agp_heap; default: return NULL; } } /* IOCTL HANDLERS */ int i915_mem_alloc(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_mem_alloc_t alloc; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data, sizeof(alloc)); heap = get_heap(dev_priv, alloc.region); if (!heap || !*heap) return DRM_ERR(EFAULT); /* Make things easier on ourselves: all allocations at least * 4k aligned. */ if (alloc.alignment < 12) alloc.alignment = 12; block = alloc_block(*heap, alloc.size, alloc.alignment, filp); if (!block) return DRM_ERR(ENOMEM); mark_block(dev, block, 1); if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; } int i915_mem_free(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_mem_free_t memfree; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data, sizeof(memfree)); heap = get_heap(dev_priv, memfree.region); if (!heap || !*heap) return DRM_ERR(EFAULT); block = find_block(*heap, memfree.region_offset); if (!block) return DRM_ERR(EFAULT); if (block->filp != filp) return DRM_ERR(EPERM); mark_block(dev, block, 0); free_block(block); return 0; } int i915_mem_init_heap(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_mem_init_heap_t initheap; struct mem_block **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(initheap, (drm_i915_mem_init_heap_t __user *) data, sizeof(initheap)); heap = get_heap(dev_priv, initheap.region); if (!heap) return DRM_ERR(EFAULT); if (*heap) { DRM_ERROR("heap already initialized?"); return DRM_ERR(EFAULT); } return init_heap(heap, initheap.start, initheap.size); } Index: head/sys/dev/drm/mach64_dma.c =================================================================== --- head/sys/dev/drm/mach64_dma.c (revision 152908) +++ head/sys/dev/drm/mach64_dma.c (revision 152909) @@ -1,1532 +1,1530 @@ /* mach64_dma.c -- DMA support for mach64 (Rage Pro) driver -*- linux-c -*- */ /** * \file mach64_dma.c * DMA support for mach64 (Rage Pro) driver * * \author Gareth Hughes * \author Frank C. Earl * \author Leif Delgass * \author Jose Fonseca */ -/* +/*- * Copyright 2000 Gareth Hughes * Copyright 2002 Frank C. Earl * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/mach64_drm.h" #include "dev/drm/mach64_drv.h" /*******************************************************************/ /** \name Engine, FIFO control */ /*@{*/ /** * Waits for free entries in the FIFO. * * \note Most writes to Mach64 registers are automatically routed through * command FIFO which is 16 entry deep. Prior to writing to any draw engine * register one has to ensure that enough FIFO entries are available by calling * this function. Failure to do so may cause the engine to lock. * * \param dev_priv pointer to device private data structure. * \param entries number of free entries in the FIFO to wait for. * * \returns zero on success, or -EBUSY if the timeout (specificed by * drm_mach64_private::usec_timeout) occurs. */ int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries) { int slots = 0, i; for (i = 0; i < dev_priv->usec_timeout; i++) { slots = (MACH64_READ(MACH64_FIFO_STAT) & MACH64_FIFO_SLOT_MASK); if (slots <= (0x8000 >> entries)) return 0; DRM_UDELAY(1); } DRM_INFO("%s failed! slots=%d entries=%d\n", __FUNCTION__, slots, entries); return DRM_ERR(EBUSY); } /** * Wait for the draw engine to be idle. */ int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv) { int i, ret; ret = mach64_do_wait_for_fifo(dev_priv, 16); if (ret < 0) return ret; for (i = 0; i < dev_priv->usec_timeout; i++) { if (!(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) { return 0; } DRM_UDELAY(1); } DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__, MACH64_READ(MACH64_GUI_STAT)); mach64_dump_ring_info(dev_priv); return DRM_ERR(EBUSY); } /** * Wait for free entries in the ring buffer. * * The Mach64 bus master can be configured to act as a virtual FIFO, using a * circular buffer (commonly referred as "ring buffer" in other drivers) with * pointers to engine commands. This allows the CPU to do other things while * the graphics engine is busy, i.e., DMA mode. * * This function should be called before writing new entries to the ring * buffer. * * \param dev_priv pointer to device private data structure. * \param n number of free entries in the ring buffer to wait for. * * \returns zero on success, or -EBUSY if the timeout (specificed by * drm_mach64_private_t::usec_timeout) occurs. * * \sa mach64_dump_ring_info() */ int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; int i; for (i = 0; i < dev_priv->usec_timeout; i++) { mach64_update_ring_snapshot(dev_priv); if (ring->space >= n) { if (i > 0) { DRM_DEBUG("%s: %d usecs\n", __FUNCTION__, i); } return 0; } DRM_UDELAY(1); } /* FIXME: This is being ignored... */ DRM_ERROR("failed!\n"); mach64_dump_ring_info(dev_priv); return DRM_ERR(EBUSY); } /** * Wait until all DMA requests have been processed... * * \sa mach64_wait_ring() */ static int mach64_ring_idle(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; u32 head; int i; head = ring->head; i = 0; while (i < dev_priv->usec_timeout) { mach64_update_ring_snapshot(dev_priv); if (ring->head == ring->tail && !(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) { if (i > 0) { DRM_DEBUG("%s: %d usecs\n", __FUNCTION__, i); } return 0; } if (ring->head == head) { ++i; } else { head = ring->head; i = 0; } DRM_UDELAY(1); } DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__, MACH64_READ(MACH64_GUI_STAT)); mach64_dump_ring_info(dev_priv); return DRM_ERR(EBUSY); } /** * Reset the the ring buffer descriptors. * * \sa mach64_do_engine_reset() */ static void mach64_ring_reset(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; mach64_do_release_used_buffers(dev_priv); ring->head_addr = ring->start_addr; ring->head = ring->tail = 0; ring->space = ring->size; MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); dev_priv->ring_running = 0; } /** * Ensure the all the queued commands will be processed. */ int mach64_do_dma_flush(drm_mach64_private_t * dev_priv) { /* FIXME: It's not necessary to wait for idle when flushing * we just need to ensure the ring will be completely processed * in finite time without another ioctl */ return mach64_ring_idle(dev_priv); } /** * Stop all DMA activity. */ int mach64_do_dma_idle(drm_mach64_private_t * dev_priv) { int ret; /* wait for completion */ if ((ret = mach64_ring_idle(dev_priv)) < 0) { DRM_ERROR("%s failed BM_GUI_TABLE=0x%08x tail: %u\n", __FUNCTION__, MACH64_READ(MACH64_BM_GUI_TABLE), dev_priv->ring.tail); return ret; } mach64_ring_stop(dev_priv); /* clean up after pass */ mach64_do_release_used_buffers(dev_priv); return 0; } /** * Reset the engine. This will stop the DMA if it is running. */ int mach64_do_engine_reset(drm_mach64_private_t * dev_priv) { u32 tmp; DRM_DEBUG("%s\n", __FUNCTION__); /* Kill off any outstanding DMA transfers. */ tmp = MACH64_READ(MACH64_BUS_CNTL); MACH64_WRITE(MACH64_BUS_CNTL, tmp | MACH64_BUS_MASTER_DIS); /* Reset the GUI engine (high to low transition). */ tmp = MACH64_READ(MACH64_GEN_TEST_CNTL); MACH64_WRITE(MACH64_GEN_TEST_CNTL, tmp & ~MACH64_GUI_ENGINE_ENABLE); /* Enable the GUI engine */ tmp = MACH64_READ(MACH64_GEN_TEST_CNTL); MACH64_WRITE(MACH64_GEN_TEST_CNTL, tmp | MACH64_GUI_ENGINE_ENABLE); /* ensure engine is not locked up by clearing any FIFO or HOST errors */ tmp = MACH64_READ(MACH64_BUS_CNTL); MACH64_WRITE(MACH64_BUS_CNTL, tmp | 0x00a00000); /* Once GUI engine is restored, disable bus mastering */ MACH64_WRITE(MACH64_SRC_CNTL, 0); /* Reset descriptor ring */ mach64_ring_reset(dev_priv); return 0; } /*@}*/ /*******************************************************************/ /** \name Debugging output */ /*@{*/ /** * Dump engine registers values. */ void mach64_dump_engine_info(drm_mach64_private_t * dev_priv) { DRM_INFO("\n"); if (!dev_priv->is_pci) { DRM_INFO(" AGP_BASE = 0x%08x\n", MACH64_READ(MACH64_AGP_BASE)); DRM_INFO(" AGP_CNTL = 0x%08x\n", MACH64_READ(MACH64_AGP_CNTL)); } DRM_INFO(" ALPHA_TST_CNTL = 0x%08x\n", MACH64_READ(MACH64_ALPHA_TST_CNTL)); DRM_INFO("\n"); DRM_INFO(" BM_COMMAND = 0x%08x\n", MACH64_READ(MACH64_BM_COMMAND)); DRM_INFO("BM_FRAME_BUF_OFFSET = 0x%08x\n", MACH64_READ(MACH64_BM_FRAME_BUF_OFFSET)); DRM_INFO(" BM_GUI_TABLE = 0x%08x\n", MACH64_READ(MACH64_BM_GUI_TABLE)); DRM_INFO(" BM_STATUS = 0x%08x\n", MACH64_READ(MACH64_BM_STATUS)); DRM_INFO(" BM_SYSTEM_MEM_ADDR = 0x%08x\n", MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR)); DRM_INFO(" BM_SYSTEM_TABLE = 0x%08x\n", MACH64_READ(MACH64_BM_SYSTEM_TABLE)); DRM_INFO(" BUS_CNTL = 0x%08x\n", MACH64_READ(MACH64_BUS_CNTL)); DRM_INFO("\n"); /* DRM_INFO( " CLOCK_CNTL = 0x%08x\n", MACH64_READ( MACH64_CLOCK_CNTL ) ); */ DRM_INFO(" CLR_CMP_CLR = 0x%08x\n", MACH64_READ(MACH64_CLR_CMP_CLR)); DRM_INFO(" CLR_CMP_CNTL = 0x%08x\n", MACH64_READ(MACH64_CLR_CMP_CNTL)); /* DRM_INFO( " CLR_CMP_MSK = 0x%08x\n", MACH64_READ( MACH64_CLR_CMP_MSK ) ); */ DRM_INFO(" CONFIG_CHIP_ID = 0x%08x\n", MACH64_READ(MACH64_CONFIG_CHIP_ID)); DRM_INFO(" CONFIG_CNTL = 0x%08x\n", MACH64_READ(MACH64_CONFIG_CNTL)); DRM_INFO(" CONFIG_STAT0 = 0x%08x\n", MACH64_READ(MACH64_CONFIG_STAT0)); DRM_INFO(" CONFIG_STAT1 = 0x%08x\n", MACH64_READ(MACH64_CONFIG_STAT1)); DRM_INFO(" CONFIG_STAT2 = 0x%08x\n", MACH64_READ(MACH64_CONFIG_STAT2)); DRM_INFO(" CRC_SIG = 0x%08x\n", MACH64_READ(MACH64_CRC_SIG)); DRM_INFO(" CUSTOM_MACRO_CNTL = 0x%08x\n", MACH64_READ(MACH64_CUSTOM_MACRO_CNTL)); DRM_INFO("\n"); /* DRM_INFO( " DAC_CNTL = 0x%08x\n", MACH64_READ( MACH64_DAC_CNTL ) ); */ /* DRM_INFO( " DAC_REGS = 0x%08x\n", MACH64_READ( MACH64_DAC_REGS ) ); */ DRM_INFO(" DP_BKGD_CLR = 0x%08x\n", MACH64_READ(MACH64_DP_BKGD_CLR)); DRM_INFO(" DP_FRGD_CLR = 0x%08x\n", MACH64_READ(MACH64_DP_FRGD_CLR)); DRM_INFO(" DP_MIX = 0x%08x\n", MACH64_READ(MACH64_DP_MIX)); DRM_INFO(" DP_PIX_WIDTH = 0x%08x\n", MACH64_READ(MACH64_DP_PIX_WIDTH)); DRM_INFO(" DP_SRC = 0x%08x\n", MACH64_READ(MACH64_DP_SRC)); DRM_INFO(" DP_WRITE_MASK = 0x%08x\n", MACH64_READ(MACH64_DP_WRITE_MASK)); DRM_INFO(" DSP_CONFIG = 0x%08x\n", MACH64_READ(MACH64_DSP_CONFIG)); DRM_INFO(" DSP_ON_OFF = 0x%08x\n", MACH64_READ(MACH64_DSP_ON_OFF)); DRM_INFO(" DST_CNTL = 0x%08x\n", MACH64_READ(MACH64_DST_CNTL)); DRM_INFO(" DST_OFF_PITCH = 0x%08x\n", MACH64_READ(MACH64_DST_OFF_PITCH)); DRM_INFO("\n"); /* DRM_INFO( " EXT_DAC_REGS = 0x%08x\n", MACH64_READ( MACH64_EXT_DAC_REGS ) ); */ DRM_INFO(" EXT_MEM_CNTL = 0x%08x\n", MACH64_READ(MACH64_EXT_MEM_CNTL)); DRM_INFO("\n"); DRM_INFO(" FIFO_STAT = 0x%08x\n", MACH64_READ(MACH64_FIFO_STAT)); DRM_INFO("\n"); DRM_INFO(" GEN_TEST_CNTL = 0x%08x\n", MACH64_READ(MACH64_GEN_TEST_CNTL)); /* DRM_INFO( " GP_IO = 0x%08x\n", MACH64_READ( MACH64_GP_IO ) ); */ DRM_INFO(" GUI_CMDFIFO_DATA = 0x%08x\n", MACH64_READ(MACH64_GUI_CMDFIFO_DATA)); DRM_INFO(" GUI_CMDFIFO_DEBUG = 0x%08x\n", MACH64_READ(MACH64_GUI_CMDFIFO_DEBUG)); DRM_INFO(" GUI_CNTL = 0x%08x\n", MACH64_READ(MACH64_GUI_CNTL)); DRM_INFO(" GUI_STAT = 0x%08x\n", MACH64_READ(MACH64_GUI_STAT)); DRM_INFO(" GUI_TRAJ_CNTL = 0x%08x\n", MACH64_READ(MACH64_GUI_TRAJ_CNTL)); DRM_INFO("\n"); DRM_INFO(" HOST_CNTL = 0x%08x\n", MACH64_READ(MACH64_HOST_CNTL)); DRM_INFO(" HW_DEBUG = 0x%08x\n", MACH64_READ(MACH64_HW_DEBUG)); DRM_INFO("\n"); DRM_INFO(" MEM_ADDR_CONFIG = 0x%08x\n", MACH64_READ(MACH64_MEM_ADDR_CONFIG)); DRM_INFO(" MEM_BUF_CNTL = 0x%08x\n", MACH64_READ(MACH64_MEM_BUF_CNTL)); DRM_INFO("\n"); DRM_INFO(" PAT_REG0 = 0x%08x\n", MACH64_READ(MACH64_PAT_REG0)); DRM_INFO(" PAT_REG1 = 0x%08x\n", MACH64_READ(MACH64_PAT_REG1)); DRM_INFO("\n"); DRM_INFO(" SC_LEFT = 0x%08x\n", MACH64_READ(MACH64_SC_LEFT)); DRM_INFO(" SC_RIGHT = 0x%08x\n", MACH64_READ(MACH64_SC_RIGHT)); DRM_INFO(" SC_TOP = 0x%08x\n", MACH64_READ(MACH64_SC_TOP)); DRM_INFO(" SC_BOTTOM = 0x%08x\n", MACH64_READ(MACH64_SC_BOTTOM)); DRM_INFO("\n"); DRM_INFO(" SCALE_3D_CNTL = 0x%08x\n", MACH64_READ(MACH64_SCALE_3D_CNTL)); DRM_INFO(" SCRATCH_REG0 = 0x%08x\n", MACH64_READ(MACH64_SCRATCH_REG0)); DRM_INFO(" SCRATCH_REG1 = 0x%08x\n", MACH64_READ(MACH64_SCRATCH_REG1)); DRM_INFO(" SETUP_CNTL = 0x%08x\n", MACH64_READ(MACH64_SETUP_CNTL)); DRM_INFO(" SRC_CNTL = 0x%08x\n", MACH64_READ(MACH64_SRC_CNTL)); DRM_INFO("\n"); DRM_INFO(" TEX_CNTL = 0x%08x\n", MACH64_READ(MACH64_TEX_CNTL)); DRM_INFO(" TEX_SIZE_PITCH = 0x%08x\n", MACH64_READ(MACH64_TEX_SIZE_PITCH)); DRM_INFO(" TIMER_CONFIG = 0x%08x\n", MACH64_READ(MACH64_TIMER_CONFIG)); DRM_INFO("\n"); DRM_INFO(" Z_CNTL = 0x%08x\n", MACH64_READ(MACH64_Z_CNTL)); DRM_INFO(" Z_OFF_PITCH = 0x%08x\n", MACH64_READ(MACH64_Z_OFF_PITCH)); DRM_INFO("\n"); } #define MACH64_DUMP_CONTEXT 3 /** * Used by mach64_dump_ring_info() to dump the contents of the current buffer * pointed by the ring head. */ static void mach64_dump_buf_info(drm_mach64_private_t * dev_priv, drm_buf_t * buf) { u32 addr = GETBUFADDR(buf); u32 used = buf->used >> 2; u32 sys_addr = MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR); u32 *p = GETBUFPTR(buf); int skipped = 0; DRM_INFO("buffer contents:\n"); while (used) { u32 reg, count; reg = le32_to_cpu(*p++); if (addr <= GETBUFADDR(buf) + MACH64_DUMP_CONTEXT * 4 || (addr >= sys_addr - MACH64_DUMP_CONTEXT * 4 && addr <= sys_addr + MACH64_DUMP_CONTEXT * 4) || addr >= GETBUFADDR(buf) + buf->used - MACH64_DUMP_CONTEXT * 4) { DRM_INFO("%08x: 0x%08x\n", addr, reg); } addr += 4; used--; count = (reg >> 16) + 1; reg = reg & 0xffff; reg = MMSELECT(reg); while (count && used) { if (addr <= GETBUFADDR(buf) + MACH64_DUMP_CONTEXT * 4 || (addr >= sys_addr - MACH64_DUMP_CONTEXT * 4 && addr <= sys_addr + MACH64_DUMP_CONTEXT * 4) || addr >= GETBUFADDR(buf) + buf->used - MACH64_DUMP_CONTEXT * 4) { DRM_INFO("%08x: 0x%04x = 0x%08x\n", addr, reg, le32_to_cpu(*p)); skipped = 0; } else { if (!skipped) { DRM_INFO(" ...\n"); skipped = 1; } } p++; addr += 4; used--; reg += 4; count--; } } DRM_INFO("\n"); } /** * Dump the ring state and contents, including the contents of the buffer being * processed by the graphics engine. */ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; int i, skipped; DRM_INFO("\n"); DRM_INFO("ring contents:\n"); DRM_INFO(" head_addr: 0x%08x head: %u tail: %u\n\n", ring->head_addr, ring->head, ring->tail); skipped = 0; for (i = 0; i < ring->size / sizeof(u32); i += 4) { if (i <= MACH64_DUMP_CONTEXT * 4 || i >= ring->size / sizeof(u32) - MACH64_DUMP_CONTEXT * 4 || (i >= ring->tail - MACH64_DUMP_CONTEXT * 4 && i <= ring->tail + MACH64_DUMP_CONTEXT * 4) || (i >= ring->head - MACH64_DUMP_CONTEXT * 4 && i <= ring->head + MACH64_DUMP_CONTEXT * 4)) { DRM_INFO(" 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x%s%s\n", (u32)(ring->start_addr + i * sizeof(u32)), le32_to_cpu(((u32 *) ring->start)[i + 0]), le32_to_cpu(((u32 *) ring->start)[i + 1]), le32_to_cpu(((u32 *) ring->start)[i + 2]), le32_to_cpu(((u32 *) ring->start)[i + 3]), i == ring->head ? " (head)" : "", i == ring->tail ? " (tail)" : ""); skipped = 0; } else { if (!skipped) { DRM_INFO(" ...\n"); skipped = 1; } } } DRM_INFO("\n"); if (ring->head >= 0 && ring->head < ring->size / sizeof(u32)) { struct list_head *ptr; u32 addr = le32_to_cpu(((u32 *) ring->start)[ring->head + 1]); list_for_each(ptr, &dev_priv->pending) { drm_mach64_freelist_t *entry = list_entry(ptr, drm_mach64_freelist_t, list); drm_buf_t *buf = entry->buf; u32 buf_addr = GETBUFADDR(buf); if (buf_addr <= addr && addr < buf_addr + buf->used) { mach64_dump_buf_info(dev_priv, buf); } } } DRM_INFO("\n"); DRM_INFO(" BM_GUI_TABLE = 0x%08x\n", MACH64_READ(MACH64_BM_GUI_TABLE)); DRM_INFO("\n"); DRM_INFO("BM_FRAME_BUF_OFFSET = 0x%08x\n", MACH64_READ(MACH64_BM_FRAME_BUF_OFFSET)); DRM_INFO(" BM_SYSTEM_MEM_ADDR = 0x%08x\n", MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR)); DRM_INFO(" BM_COMMAND = 0x%08x\n", MACH64_READ(MACH64_BM_COMMAND)); DRM_INFO("\n"); DRM_INFO(" BM_STATUS = 0x%08x\n", MACH64_READ(MACH64_BM_STATUS)); DRM_INFO(" BUS_CNTL = 0x%08x\n", MACH64_READ(MACH64_BUS_CNTL)); DRM_INFO(" FIFO_STAT = 0x%08x\n", MACH64_READ(MACH64_FIFO_STAT)); DRM_INFO(" GUI_STAT = 0x%08x\n", MACH64_READ(MACH64_GUI_STAT)); DRM_INFO(" SRC_CNTL = 0x%08x\n", MACH64_READ(MACH64_SRC_CNTL)); } /*@}*/ /*******************************************************************/ /** \name DMA test and initialization */ /*@{*/ /** * Perform a simple DMA operation using the pattern registers to test whether * DMA works. * * \return zero if successful. * * \note This function was the testbed for many experiences regarding Mach64 * DMA operation. It is left here since it so tricky to get DMA operating * properly in some architectures and hardware. */ static int mach64_bm_dma_test(drm_device_t * dev) { drm_mach64_private_t *dev_priv = dev->dev_private; - dma_addr_t data_handle; - void *cpu_addr_data; + drm_dma_handle_t *cpu_addr_dmah; u32 data_addr; u32 *table, *data; u32 expected[2]; u32 src_cntl, pat_reg0, pat_reg1; int i, count, failed; DRM_DEBUG("%s\n", __FUNCTION__); table = (u32 *) dev_priv->ring.start; /* FIXME: get a dma buffer from the freelist here */ DRM_DEBUG("Allocating data memory ...\n"); - cpu_addr_data = - drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful, &data_handle); - if (!cpu_addr_data || !data_handle) { + cpu_addr_dmah = + drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful); + if (!cpu_addr_dmah) { DRM_INFO("data-memory allocation failed!\n"); return DRM_ERR(ENOMEM); } else { - data = (u32 *) cpu_addr_data; - data_addr = (u32) data_handle; + data = (u32 *) cpu_addr_dmah->vaddr; + data_addr = (u32) cpu_addr_dmah->busaddr; } /* Save the X server's value for SRC_CNTL and restore it * in case our test fails. This prevents the X server * from disabling it's cache for this register */ src_cntl = MACH64_READ(MACH64_SRC_CNTL); pat_reg0 = MACH64_READ(MACH64_PAT_REG0); pat_reg1 = MACH64_READ(MACH64_PAT_REG1); mach64_do_wait_for_fifo(dev_priv, 3); MACH64_WRITE(MACH64_SRC_CNTL, 0); MACH64_WRITE(MACH64_PAT_REG0, 0x11111111); MACH64_WRITE(MACH64_PAT_REG1, 0x11111111); mach64_do_wait_for_idle(dev_priv); for (i = 0; i < 2; i++) { u32 reg; reg = MACH64_READ((MACH64_PAT_REG0 + i * 4)); DRM_DEBUG("(Before DMA Transfer) reg %d = 0x%08x\n", i, reg); if (reg != 0x11111111) { DRM_INFO("Error initializing test registers\n"); DRM_INFO("resetting engine ...\n"); mach64_do_engine_reset(dev_priv); DRM_INFO("freeing data buffer memory.\n"); - drm_pci_free(dev, 0x1000, cpu_addr_data, data_handle); + drm_pci_free(dev, cpu_addr_dmah); return DRM_ERR(EIO); } } /* fill up a buffer with sets of 2 consecutive writes starting with PAT_REG0 */ count = 0; data[count++] = cpu_to_le32(DMAREG(MACH64_PAT_REG0) | (1 << 16)); data[count++] = expected[0] = 0x22222222; data[count++] = expected[1] = 0xaaaaaaaa; while (count < 1020) { data[count++] = cpu_to_le32(DMAREG(MACH64_PAT_REG0) | (1 << 16)); data[count++] = 0x22222222; data[count++] = 0xaaaaaaaa; } data[count++] = cpu_to_le32(DMAREG(MACH64_SRC_CNTL) | (0 << 16)); data[count++] = 0; DRM_DEBUG("Preparing table ...\n"); table[MACH64_DMA_FRAME_BUF_OFFSET] = cpu_to_le32(MACH64_BM_ADDR + MACH64_APERTURE_OFFSET); table[MACH64_DMA_SYS_MEM_ADDR] = cpu_to_le32(data_addr); table[MACH64_DMA_COMMAND] = cpu_to_le32(count * sizeof(u32) | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL); table[MACH64_DMA_RESERVED] = 0; DRM_DEBUG("table[0] = 0x%08x\n", table[0]); DRM_DEBUG("table[1] = 0x%08x\n", table[1]); DRM_DEBUG("table[2] = 0x%08x\n", table[2]); DRM_DEBUG("table[3] = 0x%08x\n", table[3]); for (i = 0; i < 6; i++) { DRM_DEBUG(" data[%d] = 0x%08x\n", i, data[i]); } DRM_DEBUG(" ...\n"); for (i = count - 5; i < count; i++) { DRM_DEBUG(" data[%d] = 0x%08x\n", i, data[i]); } DRM_MEMORYBARRIER(); DRM_DEBUG("waiting for idle...\n"); if ((i = mach64_do_wait_for_idle(dev_priv))) { DRM_INFO("mach64_do_wait_for_idle failed (result=%d)\n", i); DRM_INFO("resetting engine ...\n"); mach64_do_engine_reset(dev_priv); mach64_do_wait_for_fifo(dev_priv, 3); MACH64_WRITE(MACH64_SRC_CNTL, src_cntl); MACH64_WRITE(MACH64_PAT_REG0, pat_reg0); MACH64_WRITE(MACH64_PAT_REG1, pat_reg1); DRM_INFO("freeing data buffer memory.\n"); - drm_pci_free(dev, 0x1000, cpu_addr_data, data_handle); + drm_pci_free(dev, cpu_addr_dmah); return i; } DRM_DEBUG("waiting for idle...done\n"); DRM_DEBUG("BUS_CNTL = 0x%08x\n", MACH64_READ(MACH64_BUS_CNTL)); DRM_DEBUG("SRC_CNTL = 0x%08x\n", MACH64_READ(MACH64_SRC_CNTL)); DRM_DEBUG("\n"); DRM_DEBUG("data bus addr = 0x%08x\n", data_addr); DRM_DEBUG("table bus addr = 0x%08x\n", dev_priv->ring.start_addr); DRM_DEBUG("starting DMA transfer...\n"); MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, dev_priv->ring.start_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); MACH64_WRITE(MACH64_SRC_CNTL, MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC | MACH64_SRC_BM_OP_SYSTEM_TO_REG); /* Kick off the transfer */ DRM_DEBUG("starting DMA transfer... done.\n"); MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0); DRM_DEBUG("waiting for idle...\n"); if ((i = mach64_do_wait_for_idle(dev_priv))) { /* engine locked up, dump register state and reset */ DRM_INFO("mach64_do_wait_for_idle failed (result=%d)\n", i); mach64_dump_engine_info(dev_priv); DRM_INFO("resetting engine ...\n"); mach64_do_engine_reset(dev_priv); mach64_do_wait_for_fifo(dev_priv, 3); MACH64_WRITE(MACH64_SRC_CNTL, src_cntl); MACH64_WRITE(MACH64_PAT_REG0, pat_reg0); MACH64_WRITE(MACH64_PAT_REG1, pat_reg1); DRM_INFO("freeing data buffer memory.\n"); - drm_pci_free(dev, 0x1000, cpu_addr_data, data_handle); + drm_pci_free(dev, cpu_addr_dmah); return i; } DRM_DEBUG("waiting for idle...done\n"); /* restore SRC_CNTL */ mach64_do_wait_for_fifo(dev_priv, 1); MACH64_WRITE(MACH64_SRC_CNTL, src_cntl); failed = 0; /* Check register values to see if the GUI master operation succeeded */ for (i = 0; i < 2; i++) { u32 reg; reg = MACH64_READ((MACH64_PAT_REG0 + i * 4)); DRM_DEBUG("(After DMA Transfer) reg %d = 0x%08x\n", i, reg); if (reg != expected[i]) { failed = -1; } } /* restore pattern registers */ mach64_do_wait_for_fifo(dev_priv, 2); MACH64_WRITE(MACH64_PAT_REG0, pat_reg0); MACH64_WRITE(MACH64_PAT_REG1, pat_reg1); DRM_DEBUG("freeing data buffer memory.\n"); - drm_pci_free(dev, 0x1000, cpu_addr_data, data_handle); + drm_pci_free(dev, cpu_addr_dmah); DRM_DEBUG("returning ...\n"); return failed; } /** * Called during the DMA initialization ioctl to initialize all the necessary * software and hardware state for DMA operation. */ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init) { drm_mach64_private_t *dev_priv; u32 tmp; int i, ret; DRM_DEBUG("%s\n", __FUNCTION__); dev_priv = drm_alloc(sizeof(drm_mach64_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return DRM_ERR(ENOMEM); memset(dev_priv, 0, sizeof(drm_mach64_private_t)); dev_priv->is_pci = init->is_pci; dev_priv->fb_bpp = init->fb_bpp; dev_priv->front_offset = init->front_offset; dev_priv->front_pitch = init->front_pitch; dev_priv->back_offset = init->back_offset; dev_priv->back_pitch = init->back_pitch; dev_priv->depth_bpp = init->depth_bpp; dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; dev_priv->front_offset_pitch = (((dev_priv->front_pitch / 8) << 22) | (dev_priv->front_offset >> 3)); dev_priv->back_offset_pitch = (((dev_priv->back_pitch / 8) << 22) | (dev_priv->back_offset >> 3)); dev_priv->depth_offset_pitch = (((dev_priv->depth_pitch / 8) << 22) | (dev_priv->depth_offset >> 3)); dev_priv->usec_timeout = 1000000; /* Set up the freelist, placeholder list and pending list */ INIT_LIST_HEAD(&dev_priv->free_list); INIT_LIST_HEAD(&dev_priv->placeholders); INIT_LIST_HEAD(&dev_priv->pending); DRM_GETSAREA(); if (!dev_priv->sarea) { DRM_ERROR("can not find sarea!\n"); dev->dev_private = (void *)dev_priv; mach64_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } dev_priv->fb = drm_core_findmap(dev, init->fb_offset); if (!dev_priv->fb) { DRM_ERROR("can not find frame buffer map!\n"); dev->dev_private = (void *)dev_priv; mach64_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio) { DRM_ERROR("can not find mmio map!\n"); dev->dev_private = (void *)dev_priv; mach64_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } dev_priv->sarea_priv = (drm_mach64_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); if (!dev_priv->is_pci) { dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset); if (!dev_priv->ring_map) { DRM_ERROR("can not find ring map!\n"); dev->dev_private = (void *)dev_priv; mach64_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } drm_core_ioremap(dev_priv->ring_map, dev); if (!dev_priv->ring_map->handle) { DRM_ERROR("can not ioremap virtual address for" " descriptor ring\n"); dev->dev_private = (void *)dev_priv; mach64_do_cleanup_dma(dev); return DRM_ERR(ENOMEM); } dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("can not find dma buffer map!\n"); dev->dev_private = (void *)dev_priv; mach64_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } /* there might be a nicer way to do this - dev isn't passed all the way though the mach64 - DA */ dev_priv->dev_buffers = dev->agp_buffer_map; drm_core_ioremap(dev->agp_buffer_map, dev); if (!dev->agp_buffer_map->handle) { DRM_ERROR("can not ioremap virtual address for" " dma buffer\n"); dev->dev_private = (void *)dev_priv; mach64_do_cleanup_dma(dev); return DRM_ERR(ENOMEM); } dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset); if (!dev_priv->agp_textures) { DRM_ERROR("can not find agp texture region!\n"); dev->dev_private = (void *)dev_priv; mach64_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } } dev->dev_private = (void *)dev_priv; dev_priv->driver_mode = init->dma_mode; /* changing the FIFO size from the default causes problems with DMA */ tmp = MACH64_READ(MACH64_GUI_CNTL); if ((tmp & MACH64_CMDFIFO_SIZE_MASK) != MACH64_CMDFIFO_SIZE_128) { DRM_INFO("Setting FIFO size to 128 entries\n"); /* FIFO must be empty to change the FIFO depth */ if ((ret = mach64_do_wait_for_idle(dev_priv))) { DRM_ERROR ("wait for idle failed before changing FIFO depth!\n"); mach64_do_cleanup_dma(dev); return ret; } MACH64_WRITE(MACH64_GUI_CNTL, ((tmp & ~MACH64_CMDFIFO_SIZE_MASK) | MACH64_CMDFIFO_SIZE_128)); /* need to read GUI_STAT for proper sync according to docs */ if ((ret = mach64_do_wait_for_idle(dev_priv))) { DRM_ERROR ("wait for idle failed when changing FIFO depth!\n"); mach64_do_cleanup_dma(dev); return ret; } } /* allocate descriptor memory from pci pool */ DRM_DEBUG("Allocating dma descriptor ring\n"); dev_priv->ring.size = 0x4000; /* 16KB */ if (dev_priv->is_pci) { - dev_priv->ring.start = drm_pci_alloc(dev, dev_priv->ring.size, + dev_priv->ring.dmah = drm_pci_alloc(dev, dev_priv->ring.size, dev_priv->ring.size, - 0xfffffffful, - &dev_priv->ring.handle); + 0xfffffffful); - if (!dev_priv->ring.start || !dev_priv->ring.handle) { + if (!dev_priv->ring.dmah) { DRM_ERROR("Allocating dma descriptor ring failed\n"); return DRM_ERR(ENOMEM); } else { - dev_priv->ring.start_addr = (u32) dev_priv->ring.handle; + dev_priv->ring.start = dev_priv->ring.dmah->vaddr; + dev_priv->ring.start_addr = + (u32) dev_priv->ring.dmah->busaddr; } } else { dev_priv->ring.start = dev_priv->ring_map->handle; dev_priv->ring.start_addr = (u32) dev_priv->ring_map->offset; } memset(dev_priv->ring.start, 0, dev_priv->ring.size); DRM_INFO("descriptor ring: cpu addr %p, bus addr: 0x%08x\n", dev_priv->ring.start, dev_priv->ring.start_addr); ret = 0; if (dev_priv->driver_mode != MACH64_MODE_MMIO) { /* enable block 1 registers and bus mastering */ MACH64_WRITE(MACH64_BUS_CNTL, ((MACH64_READ(MACH64_BUS_CNTL) | MACH64_BUS_EXT_REG_EN) & ~MACH64_BUS_MASTER_DIS)); /* try a DMA GUI-mastering pass and fall back to MMIO if it fails */ DRM_DEBUG("Starting DMA test...\n"); if ((ret = mach64_bm_dma_test(dev))) { dev_priv->driver_mode = MACH64_MODE_MMIO; } } switch (dev_priv->driver_mode) { case MACH64_MODE_MMIO: MACH64_WRITE(MACH64_BUS_CNTL, (MACH64_READ(MACH64_BUS_CNTL) | MACH64_BUS_EXT_REG_EN | MACH64_BUS_MASTER_DIS)); if (init->dma_mode == MACH64_MODE_MMIO) DRM_INFO("Forcing pseudo-DMA mode\n"); else DRM_INFO ("DMA test failed (ret=%d), using pseudo-DMA mode\n", ret); break; case MACH64_MODE_DMA_SYNC: DRM_INFO("DMA test succeeded, using synchronous DMA mode\n"); break; case MACH64_MODE_DMA_ASYNC: default: DRM_INFO("DMA test succeeded, using asynchronous DMA mode\n"); } dev_priv->ring_running = 0; /* setup offsets for physical address of table start and end */ dev_priv->ring.head_addr = dev_priv->ring.start_addr; dev_priv->ring.head = dev_priv->ring.tail = 0; dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.space = dev_priv->ring.size; /* setup physical address and size of descriptor table */ mach64_do_wait_for_fifo(dev_priv, 1); MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, (dev_priv->ring. head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB)); /* init frame counter */ dev_priv->sarea_priv->frames_queued = 0; for (i = 0; i < MACH64_MAX_QUEUED_FRAMES; i++) { dev_priv->frame_ofs[i] = ~0; /* All ones indicates placeholder */ } /* Allocate the DMA buffer freelist */ if ((ret = mach64_init_freelist(dev))) { DRM_ERROR("Freelist allocation failed\n"); mach64_do_cleanup_dma(dev); return ret; } return 0; } /*******************************************************************/ /** MMIO Pseudo-DMA (intended primarily for debugging, not performance) */ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; volatile u32 *ring_read; struct list_head *ptr; drm_mach64_freelist_t *entry; drm_buf_t *buf = NULL; u32 *buf_ptr; u32 used, reg, target; int fifo, count, found, ret, no_idle_wait; fifo = count = reg = no_idle_wait = 0; target = MACH64_BM_ADDR; if ((ret = mach64_do_wait_for_idle(dev_priv)) < 0) { DRM_INFO ("%s: idle failed before pseudo-dma dispatch, resetting engine\n", __FUNCTION__); mach64_dump_engine_info(dev_priv); mach64_do_engine_reset(dev_priv); return ret; } ring_read = (u32 *) ring->start; while (ring->tail != ring->head) { u32 buf_addr, new_target, offset; u32 bytes, remaining, head, eol; head = ring->head; new_target = le32_to_cpu(ring_read[head++]) - MACH64_APERTURE_OFFSET; buf_addr = le32_to_cpu(ring_read[head++]); eol = le32_to_cpu(ring_read[head]) & MACH64_DMA_EOL; bytes = le32_to_cpu(ring_read[head++]) & ~(MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL); head++; head &= ring->tail_mask; /* can't wait for idle between a blit setup descriptor * and a HOSTDATA descriptor or the engine will lock */ if (new_target == MACH64_BM_HOSTDATA && target == MACH64_BM_ADDR) no_idle_wait = 1; target = new_target; found = 0; offset = 0; list_for_each(ptr, &dev_priv->pending) { entry = list_entry(ptr, drm_mach64_freelist_t, list); buf = entry->buf; offset = buf_addr - GETBUFADDR(buf); if (offset >= 0 && offset < MACH64_BUFFER_SIZE) { found = 1; break; } } if (!found || buf == NULL) { DRM_ERROR ("Couldn't find pending buffer: head: %u tail: %u buf_addr: 0x%08x %s\n", head, ring->tail, buf_addr, (eol ? "eol" : "")); mach64_dump_ring_info(dev_priv); mach64_do_engine_reset(dev_priv); return DRM_ERR(EINVAL); } /* Hand feed the buffer to the card via MMIO, waiting for the fifo * every 16 writes */ DRM_DEBUG("target: (0x%08x) %s\n", target, (target == MACH64_BM_HOSTDATA ? "BM_HOSTDATA" : "BM_ADDR")); DRM_DEBUG("offset: %u bytes: %u used: %u\n", offset, bytes, buf->used); remaining = (buf->used - offset) >> 2; /* dwords remaining in buffer */ used = bytes >> 2; /* dwords in buffer for this descriptor */ buf_ptr = (u32 *) ((char *)GETBUFPTR(buf) + offset); while (used) { if (count == 0) { if (target == MACH64_BM_HOSTDATA) { reg = DMAREG(MACH64_HOST_DATA0); count = (remaining > 16) ? 16 : remaining; fifo = 0; } else { reg = le32_to_cpu(*buf_ptr++); used--; count = (reg >> 16) + 1; } reg = reg & 0xffff; reg = MMSELECT(reg); } while (count && used) { if (!fifo) { if (no_idle_wait) { if ((ret = mach64_do_wait_for_fifo (dev_priv, 16)) < 0) { no_idle_wait = 0; return ret; } } else { if ((ret = mach64_do_wait_for_idle (dev_priv)) < 0) { return ret; } } fifo = 16; } --fifo; MACH64_WRITE(reg, le32_to_cpu(*buf_ptr++)); used--; remaining--; reg += 4; count--; } } ring->head = head; ring->head_addr = ring->start_addr + (ring->head * sizeof(u32)); ring->space += (4 * sizeof(u32)); } if ((ret = mach64_do_wait_for_idle(dev_priv)) < 0) { return ret; } MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); DRM_DEBUG("%s completed\n", __FUNCTION__); return 0; } /*@}*/ /*******************************************************************/ /** \name DMA cleanup */ /*@{*/ int mach64_do_cleanup_dma(drm_device_t * dev) { DRM_DEBUG("%s\n", __FUNCTION__); /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if (dev->irq) drm_irq_uninstall(dev); if (dev->dev_private) { drm_mach64_private_t *dev_priv = dev->dev_private; if (dev_priv->is_pci) { - if ((dev_priv->ring.start != NULL) - && dev_priv->ring.handle) { - drm_pci_free(dev, dev_priv->ring.size, - dev_priv->ring.start, - dev_priv->ring.handle); + if (dev_priv->ring.dmah) { + drm_pci_free(dev, dev_priv->ring.dmah); } } else { if (dev_priv->ring_map) drm_core_ioremapfree(dev_priv->ring_map, dev); } if (dev->agp_buffer_map) { drm_core_ioremapfree(dev->agp_buffer_map, dev); dev->agp_buffer_map = NULL; } mach64_destroy_freelist(dev); drm_free(dev_priv, sizeof(drm_mach64_private_t), DRM_MEM_DRIVER); dev->dev_private = NULL; } return 0; } /*@}*/ /*******************************************************************/ /** \name IOCTL handlers */ /*@{*/ int mach64_dma_init(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_init_t init; DRM_DEBUG("%s\n", __FUNCTION__); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(init, (drm_mach64_init_t *) data, sizeof(init)); switch (init.func) { case DRM_MACH64_INIT_DMA: return mach64_do_dma_init(dev, &init); case DRM_MACH64_CLEANUP_DMA: return mach64_do_cleanup_dma(dev); } return DRM_ERR(EINVAL); } int mach64_dma_idle(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); LOCK_TEST_WITH_RETURN(dev, filp); return mach64_do_dma_idle(dev_priv); } int mach64_dma_flush(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); LOCK_TEST_WITH_RETURN(dev, filp); return mach64_do_dma_flush(dev_priv); } int mach64_engine_reset(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); LOCK_TEST_WITH_RETURN(dev, filp); return mach64_do_engine_reset(dev_priv); } /*@}*/ /*******************************************************************/ /** \name Freelist management */ /*@{*/ int mach64_init_freelist(drm_device_t * dev) { drm_device_dma_t *dma = dev->dma; drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_freelist_t *entry; struct list_head *ptr; int i; DRM_DEBUG("%s: adding %d buffers to freelist\n", __FUNCTION__, dma->buf_count); for (i = 0; i < dma->buf_count; i++) { if ((entry = (drm_mach64_freelist_t *) drm_alloc(sizeof(drm_mach64_freelist_t), DRM_MEM_BUFLISTS)) == NULL) return DRM_ERR(ENOMEM); memset(entry, 0, sizeof(drm_mach64_freelist_t)); entry->buf = dma->buflist[i]; ptr = &entry->list; list_add_tail(ptr, &dev_priv->free_list); } return 0; } void mach64_destroy_freelist(drm_device_t * dev) { drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_freelist_t *entry; struct list_head *ptr; struct list_head *tmp; DRM_DEBUG("%s\n", __FUNCTION__); list_for_each_safe(ptr, tmp, &dev_priv->pending) { list_del(ptr); entry = list_entry(ptr, drm_mach64_freelist_t, list); drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS); } list_for_each_safe(ptr, tmp, &dev_priv->placeholders) { list_del(ptr); entry = list_entry(ptr, drm_mach64_freelist_t, list); drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS); } list_for_each_safe(ptr, tmp, &dev_priv->free_list) { list_del(ptr); entry = list_entry(ptr, drm_mach64_freelist_t, list); drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS); } } /* IMPORTANT: This function should only be called when the engine is idle or locked up, * as it assumes all buffers in the pending list have been completed by the hardware. */ int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv) { struct list_head *ptr; struct list_head *tmp; drm_mach64_freelist_t *entry; int i; if (list_empty(&dev_priv->pending)) return 0; /* Iterate the pending list and move all buffers into the freelist... */ i = 0; list_for_each_safe(ptr, tmp, &dev_priv->pending) { entry = list_entry(ptr, drm_mach64_freelist_t, list); if (entry->discard) { entry->buf->pending = 0; list_del(ptr); list_add_tail(ptr, &dev_priv->free_list); i++; } } DRM_DEBUG("%s: released %d buffers from pending list\n", __FUNCTION__, i); return 0; } drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; drm_mach64_freelist_t *entry; struct list_head *ptr; struct list_head *tmp; int t; if (list_empty(&dev_priv->free_list)) { u32 head, tail, ofs; if (list_empty(&dev_priv->pending)) { DRM_ERROR ("Couldn't get buffer - pending and free lists empty\n"); t = 0; list_for_each(ptr, &dev_priv->placeholders) { t++; } DRM_INFO("Placeholders: %d\n", t); return NULL; } tail = ring->tail; for (t = 0; t < dev_priv->usec_timeout; t++) { mach64_ring_tick(dev_priv, ring); head = ring->head; if (head == tail) { #if MACH64_EXTRA_CHECKING if (MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE) { DRM_ERROR ("Empty ring with non-idle engine!\n"); mach64_dump_ring_info(dev_priv); return NULL; } #endif /* last pass is complete, so release everything */ mach64_do_release_used_buffers(dev_priv); DRM_DEBUG ("%s: idle engine, freed all buffers.\n", __FUNCTION__); if (list_empty(&dev_priv->free_list)) { DRM_ERROR ("Freelist empty with idle engine\n"); return NULL; } goto _freelist_entry_found; } /* Look for a completed buffer and bail out of the loop * as soon as we find one -- don't waste time trying * to free extra bufs here, leave that to do_release_used_buffers */ list_for_each_safe(ptr, tmp, &dev_priv->pending) { entry = list_entry(ptr, drm_mach64_freelist_t, list); ofs = entry->ring_ofs; if (entry->discard && ((head < tail && (ofs < head || ofs >= tail)) || (head > tail && (ofs < head && ofs >= tail)))) { #if MACH64_EXTRA_CHECKING int i; for (i = head; i != tail; i = (i + 4) & ring->tail_mask) { u32 o1 = le32_to_cpu(((u32 *) ring-> start)[i + 1]); u32 o2 = GETBUFADDR(entry->buf); if (o1 == o2) { DRM_ERROR ("Attempting to free used buffer: " "i=%d buf=0x%08x\n", i, o1); mach64_dump_ring_info (dev_priv); return NULL; } } #endif /* found a processed buffer */ entry->buf->pending = 0; list_del(ptr); entry->buf->used = 0; list_add_tail(ptr, &dev_priv->placeholders); DRM_DEBUG ("%s: freed processed buffer (head=%d tail=%d " "buf ring ofs=%d).\n", __FUNCTION__, head, tail, ofs); return entry->buf; } } DRM_UDELAY(1); } mach64_dump_ring_info(dev_priv); DRM_ERROR ("timeout waiting for buffers: ring head_addr: 0x%08x head: %d tail: %d\n", ring->head_addr, ring->head, ring->tail); return NULL; } _freelist_entry_found: ptr = dev_priv->free_list.next; list_del(ptr); entry = list_entry(ptr, drm_mach64_freelist_t, list); entry->buf->used = 0; list_add_tail(ptr, &dev_priv->placeholders); return entry->buf; } /*@}*/ /*******************************************************************/ /** \name DMA buffer request and submission IOCTL handler */ /*@{*/ static int mach64_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d) { int i; drm_buf_t *buf; drm_mach64_private_t *dev_priv = dev->dev_private; for (i = d->granted_count; i < d->request_count; i++) { buf = mach64_freelist_get(dev_priv); #if MACH64_EXTRA_CHECKING if (!buf) return DRM_ERR(EFAULT); #else if (!buf) return DRM_ERR(EAGAIN); #endif buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return DRM_ERR(EFAULT); d->granted_count++; } return 0; } int mach64_dma_buffers(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_dma_t d; int ret = 0; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t *) data, sizeof(d)); /* Please don't send us buffers. */ if (d.send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", DRM_CURRENTPID, d.send_count); return DRM_ERR(EINVAL); } /* We'll send you buffers. */ if (d.request_count < 0 || d.request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", DRM_CURRENTPID, d.request_count, dma->buf_count); ret = DRM_ERR(EINVAL); } d.granted_count = 0; if (d.request_count) { ret = mach64_dma_get_buffers(filp, dev, &d); } DRM_COPY_TO_USER_IOCTL((drm_dma_t *) data, d, sizeof(d)); return ret; } -void mach64_driver_pretakedown(drm_device_t * dev) +void mach64_driver_lastclose(drm_device_t * dev) { mach64_do_cleanup_dma(dev); } /*@}*/ Index: head/sys/dev/drm/mach64_drm.h =================================================================== --- head/sys/dev/drm/mach64_drm.h (revision 152908) +++ head/sys/dev/drm/mach64_drm.h (revision 152909) @@ -1,257 +1,259 @@ /* mach64_drm.h -- Public header for the mach64 driver -*- linux-c -*- * Created: Thu Nov 30 20:04:32 2000 by gareth@valinux.com - * + */ +/*- * Copyright 2000 Gareth Hughes * Copyright 2002 Frank C. Earl * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * Frank C. Earl * Leif Delgass - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #ifndef __MACH64_DRM_H__ #define __MACH64_DRM_H__ /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (mach64_sarea.h) */ #ifndef __MACH64_SAREA_DEFINES__ #define __MACH64_SAREA_DEFINES__ /* What needs to be changed for the current vertex buffer? * GH: We're going to be pedantic about this. We want the card to do as * little as possible, so let's avoid having it fetch a whole bunch of * register values that don't change all that often, if at all. */ #define MACH64_UPLOAD_DST_OFF_PITCH 0x0001 #define MACH64_UPLOAD_Z_OFF_PITCH 0x0002 #define MACH64_UPLOAD_Z_ALPHA_CNTL 0x0004 #define MACH64_UPLOAD_SCALE_3D_CNTL 0x0008 #define MACH64_UPLOAD_DP_FOG_CLR 0x0010 #define MACH64_UPLOAD_DP_WRITE_MASK 0x0020 #define MACH64_UPLOAD_DP_PIX_WIDTH 0x0040 #define MACH64_UPLOAD_SETUP_CNTL 0x0080 #define MACH64_UPLOAD_MISC 0x0100 #define MACH64_UPLOAD_TEXTURE 0x0200 #define MACH64_UPLOAD_TEX0IMAGE 0x0400 #define MACH64_UPLOAD_TEX1IMAGE 0x0800 #define MACH64_UPLOAD_CLIPRECTS 0x1000 /* handled client-side */ #define MACH64_UPLOAD_CONTEXT 0x00ff #define MACH64_UPLOAD_ALL 0x1fff /* DMA buffer size */ #define MACH64_BUFFER_SIZE 16384 /* Max number of swaps allowed on the ring * before the client must wait */ #define MACH64_MAX_QUEUED_FRAMES 3 /* Byte offsets for host blit buffer data */ #define MACH64_HOSTDATA_BLIT_OFFSET 104 /* Keep these small for testing. */ #define MACH64_NR_SAREA_CLIPRECTS 8 #define MACH64_CARD_HEAP 0 #define MACH64_AGP_HEAP 1 #define MACH64_NR_TEX_HEAPS 2 #define MACH64_NR_TEX_REGIONS 64 #define MACH64_LOG_TEX_GRANULARITY 16 #define MACH64_TEX_MAXLEVELS 1 #define MACH64_NR_CONTEXT_REGS 15 #define MACH64_NR_TEXTURE_REGS 4 #endif /* __MACH64_SAREA_DEFINES__ */ typedef struct { unsigned int dst_off_pitch; unsigned int z_off_pitch; unsigned int z_cntl; unsigned int alpha_tst_cntl; unsigned int scale_3d_cntl; unsigned int sc_left_right; unsigned int sc_top_bottom; unsigned int dp_fog_clr; unsigned int dp_write_mask; unsigned int dp_pix_width; unsigned int dp_mix; unsigned int dp_src; unsigned int clr_cmp_cntl; unsigned int gui_traj_cntl; unsigned int setup_cntl; unsigned int tex_size_pitch; unsigned int tex_cntl; unsigned int secondary_tex_off; unsigned int tex_offset; } drm_mach64_context_regs_t; typedef struct drm_mach64_sarea { /* The channel for communication of state information to the kernel * on firing a vertex dma buffer. */ drm_mach64_context_regs_t context_state; unsigned int dirty; unsigned int vertsize; /* The current cliprects, or a subset thereof. */ drm_clip_rect_t boxes[MACH64_NR_SAREA_CLIPRECTS]; unsigned int nbox; /* Counters for client-side throttling of rendering clients. */ unsigned int frames_queued; /* Texture memory LRU. */ drm_tex_region_t tex_list[MACH64_NR_TEX_HEAPS][MACH64_NR_TEX_REGIONS + 1]; unsigned int tex_age[MACH64_NR_TEX_HEAPS]; int ctx_owner; } drm_mach64_sarea_t; /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (mach64_common.h) */ /* Mach64 specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ #define DRM_MACH64_INIT 0x00 #define DRM_MACH64_IDLE 0x01 #define DRM_MACH64_RESET 0x02 #define DRM_MACH64_SWAP 0x03 #define DRM_MACH64_CLEAR 0x04 #define DRM_MACH64_VERTEX 0x05 #define DRM_MACH64_BLIT 0x06 #define DRM_MACH64_FLUSH 0x07 #define DRM_MACH64_GETPARAM 0x08 #define DRM_IOCTL_MACH64_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_INIT, drm_mach64_init_t) #define DRM_IOCTL_MACH64_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_IDLE ) #define DRM_IOCTL_MACH64_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_RESET ) #define DRM_IOCTL_MACH64_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_SWAP ) #define DRM_IOCTL_MACH64_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_CLEAR, drm_mach64_clear_t) #define DRM_IOCTL_MACH64_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_VERTEX, drm_mach64_vertex_t) #define DRM_IOCTL_MACH64_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_BLIT, drm_mach64_blit_t) #define DRM_IOCTL_MACH64_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_FLUSH ) #define DRM_IOCTL_MACH64_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_MACH64_GETPARAM, drm_mach64_getparam_t) /* Buffer flags for clears */ #define MACH64_FRONT 0x1 #define MACH64_BACK 0x2 #define MACH64_DEPTH 0x4 /* Primitive types for vertex buffers */ #define MACH64_PRIM_POINTS 0x00000000 #define MACH64_PRIM_LINES 0x00000001 #define MACH64_PRIM_LINE_LOOP 0x00000002 #define MACH64_PRIM_LINE_STRIP 0x00000003 #define MACH64_PRIM_TRIANGLES 0x00000004 #define MACH64_PRIM_TRIANGLE_STRIP 0x00000005 #define MACH64_PRIM_TRIANGLE_FAN 0x00000006 #define MACH64_PRIM_QUADS 0x00000007 #define MACH64_PRIM_QUAD_STRIP 0x00000008 #define MACH64_PRIM_POLYGON 0x00000009 typedef enum _drm_mach64_dma_mode_t { MACH64_MODE_DMA_ASYNC, MACH64_MODE_DMA_SYNC, MACH64_MODE_MMIO } drm_mach64_dma_mode_t; typedef struct drm_mach64_init { enum { DRM_MACH64_INIT_DMA = 0x01, DRM_MACH64_CLEANUP_DMA = 0x02 } func; unsigned long sarea_priv_offset; int is_pci; drm_mach64_dma_mode_t dma_mode; unsigned int fb_bpp; unsigned int front_offset, front_pitch; unsigned int back_offset, back_pitch; unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; unsigned long fb_offset; unsigned long mmio_offset; unsigned long ring_offset; unsigned long buffers_offset; unsigned long agp_textures_offset; } drm_mach64_init_t; typedef struct drm_mach64_clear { unsigned int flags; int x, y, w, h; unsigned int clear_color; unsigned int clear_depth; } drm_mach64_clear_t; typedef struct drm_mach64_vertex { int prim; void *buf; /* Address of vertex buffer */ unsigned long used; /* Number of bytes in buffer */ int discard; /* Client finished with buffer? */ } drm_mach64_vertex_t; typedef struct drm_mach64_blit { int idx; int pitch; int offset; int format; unsigned short x, y; unsigned short width, height; } drm_mach64_blit_t; typedef struct drm_mach64_getparam { enum { MACH64_PARAM_FRAMES_QUEUED = 0x01, MACH64_PARAM_IRQ_NR = 0x02 } param; void *value; } drm_mach64_getparam_t; #endif Index: head/sys/dev/drm/mach64_drv.c =================================================================== --- head/sys/dev/drm/mach64_drv.c (revision 152908) +++ head/sys/dev/drm/mach64_drv.c (revision 152909) @@ -1,119 +1,117 @@ /* mach64_drv.c -- ATI Rage 128 driver -*- linux-c -*- * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/mach64_drm.h" #include "dev/drm/mach64_drv.h" #include "dev/drm/drm_pciids.h" /* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */ static drm_pci_id_list_t mach64_pciidlist[] = { mach64_PCI_IDS }; -extern drm_ioctl_desc_t mach64_ioctls[]; -extern int mach64_max_ioctl; - static void mach64_configure(drm_device_t *dev) { - dev->dev_priv_size = 1; /* No dev_priv */ - dev->pretakedown = mach64_driver_pretakedown; - dev->vblank_wait = mach64_driver_vblank_wait; - dev->irq_preinstall = mach64_driver_irq_preinstall; - dev->irq_postinstall = mach64_driver_irq_postinstall; - dev->irq_uninstall = mach64_driver_irq_uninstall; - dev->irq_handler = mach64_driver_irq_handler; - dev->dma_ioctl = mach64_dma_buffers; + dev->driver.buf_priv_size = 1; /* No dev_priv */ + dev->driver.lastclose = mach64_driver_lastclose; + dev->driver.vblank_wait = mach64_driver_vblank_wait; + dev->driver.irq_preinstall = mach64_driver_irq_preinstall; + dev->driver.irq_postinstall = mach64_driver_irq_postinstall; + dev->driver.irq_uninstall = mach64_driver_irq_uninstall; + dev->driver.irq_handler = mach64_driver_irq_handler; + dev->driver.dma_ioctl = mach64_dma_buffers; - dev->driver_ioctls = mach64_ioctls; - dev->max_driver_ioctl = mach64_max_ioctl; + dev->driver.ioctls = mach64_ioctls; + dev->driver.max_ioctl = mach64_max_ioctl; - dev->driver_name = DRIVER_NAME; - dev->driver_desc = DRIVER_DESC; - dev->driver_date = DRIVER_DATE; - dev->driver_major = DRIVER_MAJOR; - dev->driver_minor = DRIVER_MINOR; - dev->driver_patchlevel = DRIVER_PATCHLEVEL; + dev->driver.name = DRIVER_NAME; + dev->driver.desc = DRIVER_DESC; + dev->driver.date = DRIVER_DATE; + dev->driver.major = DRIVER_MAJOR; + dev->driver.minor = DRIVER_MINOR; + dev->driver.patchlevel = DRIVER_PATCHLEVEL; - dev->use_agp = 1; - dev->use_mtrr = 1; - dev->use_pci_dma = 1; - dev->use_dma = 1; - dev->use_irq = 1; - dev->use_vbl_irq = 1; + dev->driver.use_agp = 1; + dev->driver.use_mtrr = 1; + dev->driver.use_pci_dma = 1; + dev->driver.use_dma = 1; + dev->driver.use_irq = 1; + dev->driver.use_vbl_irq = 1; } #ifdef __FreeBSD__ static int mach64_probe(device_t dev) { return drm_probe(dev, mach64_pciidlist); } static int mach64_attach(device_t nbdev) { drm_device_t *dev = device_get_softc(nbdev); bzero(dev, sizeof(drm_device_t)); mach64_configure(dev); return drm_attach(nbdev, mach64_pciidlist); } static device_method_t mach64_methods[] = { /* Device interface */ DEVMETHOD(device_probe, mach64_probe), DEVMETHOD(device_attach, mach64_attach), DEVMETHOD(device_detach, drm_detach), { 0, 0 } }; static driver_t mach64_driver = { "drm", mach64_methods, sizeof(drm_device_t) }; extern devclass_t drm_devclass; DRIVER_MODULE(mach64, pci, mach64_driver, drm_devclass, 0, 0); MODULE_DEPEND(mach64, drm, 1, 1, 1); #elif defined(__NetBSD__) || defined(__OpenBSD__) CFDRIVER_DECL(mach64, DV_TTY, NULL); #endif Index: head/sys/dev/drm/mach64_drv.h =================================================================== --- head/sys/dev/drm/mach64_drv.h (revision 152908) +++ head/sys/dev/drm/mach64_drv.h (revision 152909) @@ -1,1045 +1,1050 @@ /* mach64_drv.h -- Private header for mach64 driver -*- linux-c -*- * Created: Fri Nov 24 22:07:58 2000 by gareth@valinux.com - * + */ +/*- * Copyright 2000 Gareth Hughes * Copyright 2002 Frank C. Earl * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * Frank C. Earl * Leif Delgass * Jos�Fonseca - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef __MACH64_DRV_H__ #define __MACH64_DRV_H__ /* General customization: */ #define DRIVER_AUTHOR "Gareth Hughes, Leif Delgass, José Fonseca" #define DRIVER_NAME "mach64" #define DRIVER_DESC "DRM module for the ATI Rage Pro" #define DRIVER_DATE "20020904" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 /* FIXME: remove these when not needed */ /* Development driver options */ #define MACH64_EXTRA_CHECKING 0 /* Extra sanity checks for DMA/freelist management */ #define MACH64_VERBOSE 0 /* Verbose debugging output */ typedef struct drm_mach64_freelist { struct list_head list; /* List pointers for free_list, placeholders, or pending list */ drm_buf_t *buf; /* Pointer to the buffer */ int discard; /* This flag is set when we're done (re)using a buffer */ u32 ring_ofs; /* dword offset in ring of last descriptor for this buffer */ } drm_mach64_freelist_t; typedef struct drm_mach64_descriptor_ring { - dma_addr_t handle; /* handle (bus address) of ring returned by pci_alloc_consistent() */ + drm_dma_handle_t *dmah; /* Handle to pci dma memory */ void *start; /* write pointer (cpu address) to start of descriptor ring */ u32 start_addr; /* bus address of beginning of descriptor ring */ int size; /* size of ring in bytes */ u32 head_addr; /* bus address of descriptor ring head */ u32 head; /* dword offset of descriptor ring head */ u32 tail; /* dword offset of descriptor ring tail */ u32 tail_mask; /* mask used to wrap ring */ int space; /* number of free bytes in ring */ } drm_mach64_descriptor_ring_t; typedef struct drm_mach64_private { drm_mach64_sarea_t *sarea_priv; int is_pci; drm_mach64_dma_mode_t driver_mode; /* Async DMA, sync DMA, or MMIO */ int usec_timeout; /* Timeout for the wait functions */ drm_mach64_descriptor_ring_t ring; /* DMA descriptor table (ring buffer) */ int ring_running; /* Is bus mastering is enabled */ struct list_head free_list; /* Free-list head */ struct list_head placeholders; /* Placeholder list for buffers held by clients */ struct list_head pending; /* Buffers pending completion */ u32 frame_ofs[MACH64_MAX_QUEUED_FRAMES]; /* dword ring offsets of most recent frame swaps */ unsigned int fb_bpp; unsigned int front_offset, front_pitch; unsigned int back_offset, back_pitch; unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; u32 front_offset_pitch; u32 back_offset_pitch; u32 depth_offset_pitch; drm_local_map_t *sarea; drm_local_map_t *fb; drm_local_map_t *mmio; drm_local_map_t *ring_map; drm_local_map_t *dev_buffers; /* this is a pointer to a structure in dev */ drm_local_map_t *agp_textures; } drm_mach64_private_t; +extern drm_ioctl_desc_t mach64_ioctls[]; +extern int mach64_max_ioctl; + /* mach64_dma.c */ extern int mach64_dma_init(DRM_IOCTL_ARGS); extern int mach64_dma_idle(DRM_IOCTL_ARGS); extern int mach64_dma_flush(DRM_IOCTL_ARGS); extern int mach64_engine_reset(DRM_IOCTL_ARGS); extern int mach64_dma_buffers(DRM_IOCTL_ARGS); -extern void mach64_driver_pretakedown(drm_device_t * dev); +extern void mach64_driver_lastclose(drm_device_t * dev); extern int mach64_init_freelist(drm_device_t * dev); extern void mach64_destroy_freelist(drm_device_t * dev); extern drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv); extern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries); extern int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv); extern int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n); extern int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv); extern int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv); extern void mach64_dump_engine_info(drm_mach64_private_t * dev_priv); extern void mach64_dump_ring_info(drm_mach64_private_t * dev_priv); extern int mach64_do_engine_reset(drm_mach64_private_t * dev_priv); extern int mach64_do_dma_idle(drm_mach64_private_t * dev_priv); extern int mach64_do_dma_flush(drm_mach64_private_t * dev_priv); extern int mach64_do_cleanup_dma(drm_device_t * dev); /* mach64_state.c */ extern int mach64_dma_clear(DRM_IOCTL_ARGS); extern int mach64_dma_swap(DRM_IOCTL_ARGS); extern int mach64_dma_vertex(DRM_IOCTL_ARGS); extern int mach64_dma_blit(DRM_IOCTL_ARGS); extern int mach64_get_param(DRM_IOCTL_ARGS); extern int mach64_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS); extern void mach64_driver_irq_preinstall(drm_device_t * dev); extern void mach64_driver_irq_postinstall(drm_device_t * dev); extern void mach64_driver_irq_uninstall(drm_device_t * dev); /* ================================================================ * Registers */ #define MACH64_AGP_BASE 0x0148 #define MACH64_AGP_CNTL 0x014c #define MACH64_ALPHA_TST_CNTL 0x0550 #define MACH64_DSP_CONFIG 0x0420 #define MACH64_DSP_ON_OFF 0x0424 #define MACH64_EXT_MEM_CNTL 0x04ac #define MACH64_GEN_TEST_CNTL 0x04d0 #define MACH64_HW_DEBUG 0x047c #define MACH64_MEM_ADDR_CONFIG 0x0434 #define MACH64_MEM_BUF_CNTL 0x042c #define MACH64_MEM_CNTL 0x04b0 #define MACH64_BM_ADDR 0x0648 #define MACH64_BM_COMMAND 0x0188 #define MACH64_BM_DATA 0x0648 #define MACH64_BM_FRAME_BUF_OFFSET 0x0180 #define MACH64_BM_GUI_TABLE 0x01b8 #define MACH64_BM_GUI_TABLE_CMD 0x064c # define MACH64_CIRCULAR_BUF_SIZE_16KB (0 << 0) # define MACH64_CIRCULAR_BUF_SIZE_32KB (1 << 0) # define MACH64_CIRCULAR_BUF_SIZE_64KB (2 << 0) # define MACH64_CIRCULAR_BUF_SIZE_128KB (3 << 0) # define MACH64_LAST_DESCRIPTOR (1 << 31) #define MACH64_BM_HOSTDATA 0x0644 #define MACH64_BM_STATUS 0x018c #define MACH64_BM_SYSTEM_MEM_ADDR 0x0184 #define MACH64_BM_SYSTEM_TABLE 0x01bc #define MACH64_BUS_CNTL 0x04a0 # define MACH64_BUS_MSTR_RESET (1 << 1) # define MACH64_BUS_APER_REG_DIS (1 << 4) # define MACH64_BUS_FLUSH_BUF (1 << 2) # define MACH64_BUS_MASTER_DIS (1 << 6) # define MACH64_BUS_EXT_REG_EN (1 << 27) #define MACH64_CLR_CMP_CLR 0x0700 #define MACH64_CLR_CMP_CNTL 0x0708 #define MACH64_CLR_CMP_MASK 0x0704 #define MACH64_CONFIG_CHIP_ID 0x04e0 #define MACH64_CONFIG_CNTL 0x04dc #define MACH64_CONFIG_STAT0 0x04e4 #define MACH64_CONFIG_STAT1 0x0494 #define MACH64_CONFIG_STAT2 0x0498 #define MACH64_CONTEXT_LOAD_CNTL 0x072c #define MACH64_CONTEXT_MASK 0x0720 #define MACH64_COMPOSITE_SHADOW_ID 0x0798 #define MACH64_CRC_SIG 0x04e8 #define MACH64_CUSTOM_MACRO_CNTL 0x04d4 #define MACH64_DP_BKGD_CLR 0x06c0 #define MACH64_DP_FOG_CLR 0x06c4 #define MACH64_DP_FGRD_BKGD_CLR 0x06e0 #define MACH64_DP_FRGD_CLR 0x06c4 #define MACH64_DP_FGRD_CLR_MIX 0x06dc #define MACH64_DP_MIX 0x06d4 # define BKGD_MIX_NOT_D (0 << 0) # define BKGD_MIX_ZERO (1 << 0) # define BKGD_MIX_ONE (2 << 0) # define MACH64_BKGD_MIX_D (3 << 0) # define BKGD_MIX_NOT_S (4 << 0) # define BKGD_MIX_D_XOR_S (5 << 0) # define BKGD_MIX_NOT_D_XOR_S (6 << 0) # define MACH64_BKGD_MIX_S (7 << 0) # define BKGD_MIX_NOT_D_OR_NOT_S (8 << 0) # define BKGD_MIX_D_OR_NOT_S (9 << 0) # define BKGD_MIX_NOT_D_OR_S (10 << 0) # define BKGD_MIX_D_OR_S (11 << 0) # define BKGD_MIX_D_AND_S (12 << 0) # define BKGD_MIX_NOT_D_AND_S (13 << 0) # define BKGD_MIX_D_AND_NOT_S (14 << 0) # define BKGD_MIX_NOT_D_AND_NOT_S (15 << 0) # define BKGD_MIX_D_PLUS_S_DIV2 (23 << 0) # define FRGD_MIX_NOT_D (0 << 16) # define FRGD_MIX_ZERO (1 << 16) # define FRGD_MIX_ONE (2 << 16) # define FRGD_MIX_D (3 << 16) # define FRGD_MIX_NOT_S (4 << 16) # define FRGD_MIX_D_XOR_S (5 << 16) # define FRGD_MIX_NOT_D_XOR_S (6 << 16) # define MACH64_FRGD_MIX_S (7 << 16) # define FRGD_MIX_NOT_D_OR_NOT_S (8 << 16) # define FRGD_MIX_D_OR_NOT_S (9 << 16) # define FRGD_MIX_NOT_D_OR_S (10 << 16) # define FRGD_MIX_D_OR_S (11 << 16) # define FRGD_MIX_D_AND_S (12 << 16) # define FRGD_MIX_NOT_D_AND_S (13 << 16) # define FRGD_MIX_D_AND_NOT_S (14 << 16) # define FRGD_MIX_NOT_D_AND_NOT_S (15 << 16) # define FRGD_MIX_D_PLUS_S_DIV2 (23 << 16) #define MACH64_DP_PIX_WIDTH 0x06d0 # define MACH64_HOST_TRIPLE_ENABLE (1 << 13) # define MACH64_BYTE_ORDER_MSB_TO_LSB (0 << 24) # define MACH64_BYTE_ORDER_LSB_TO_MSB (1 << 24) #define MACH64_DP_SRC 0x06d8 # define MACH64_BKGD_SRC_BKGD_CLR (0 << 0) # define MACH64_BKGD_SRC_FRGD_CLR (1 << 0) # define MACH64_BKGD_SRC_HOST (2 << 0) # define MACH64_BKGD_SRC_BLIT (3 << 0) # define MACH64_BKGD_SRC_PATTERN (4 << 0) # define MACH64_BKGD_SRC_3D (5 << 0) # define MACH64_FRGD_SRC_BKGD_CLR (0 << 8) # define MACH64_FRGD_SRC_FRGD_CLR (1 << 8) # define MACH64_FRGD_SRC_HOST (2 << 8) # define MACH64_FRGD_SRC_BLIT (3 << 8) # define MACH64_FRGD_SRC_PATTERN (4 << 8) # define MACH64_FRGD_SRC_3D (5 << 8) # define MACH64_MONO_SRC_ONE (0 << 16) # define MACH64_MONO_SRC_PATTERN (1 << 16) # define MACH64_MONO_SRC_HOST (2 << 16) # define MACH64_MONO_SRC_BLIT (3 << 16) #define MACH64_DP_WRITE_MASK 0x06c8 #define MACH64_DST_CNTL 0x0530 # define MACH64_DST_X_RIGHT_TO_LEFT (0 << 0) # define MACH64_DST_X_LEFT_TO_RIGHT (1 << 0) # define MACH64_DST_Y_BOTTOM_TO_TOP (0 << 1) # define MACH64_DST_Y_TOP_TO_BOTTOM (1 << 1) # define MACH64_DST_X_MAJOR (0 << 2) # define MACH64_DST_Y_MAJOR (1 << 2) # define MACH64_DST_X_TILE (1 << 3) # define MACH64_DST_Y_TILE (1 << 4) # define MACH64_DST_LAST_PEL (1 << 5) # define MACH64_DST_POLYGON_ENABLE (1 << 6) # define MACH64_DST_24_ROTATION_ENABLE (1 << 7) #define MACH64_DST_HEIGHT_WIDTH 0x0518 #define MACH64_DST_OFF_PITCH 0x0500 #define MACH64_DST_WIDTH_HEIGHT 0x06ec #define MACH64_DST_X_Y 0x06e8 #define MACH64_DST_Y_X 0x050c #define MACH64_FIFO_STAT 0x0710 # define MACH64_FIFO_SLOT_MASK 0x0000ffff # define MACH64_FIFO_ERR (1 << 31) #define MACH64_GEN_TEST_CNTL 0x04d0 # define MACH64_GUI_ENGINE_ENABLE (1 << 8) #define MACH64_GUI_CMDFIFO_DEBUG 0x0170 #define MACH64_GUI_CMDFIFO_DATA 0x0174 #define MACH64_GUI_CNTL 0x0178 # define MACH64_CMDFIFO_SIZE_MASK 0x00000003ul # define MACH64_CMDFIFO_SIZE_192 0x00000000ul # define MACH64_CMDFIFO_SIZE_128 0x00000001ul # define MACH64_CMDFIFO_SIZE_64 0x00000002ul #define MACH64_GUI_STAT 0x0738 # define MACH64_GUI_ACTIVE (1 << 0) #define MACH64_GUI_TRAJ_CNTL 0x0730 #define MACH64_HOST_CNTL 0x0640 #define MACH64_HOST_DATA0 0x0600 #define MACH64_ONE_OVER_AREA 0x029c #define MACH64_ONE_OVER_AREA_UC 0x0300 #define MACH64_PAT_REG0 0x0680 #define MACH64_PAT_REG1 0x0684 #define MACH64_SC_LEFT 0x06a0 #define MACH64_SC_RIGHT 0x06a4 #define MACH64_SC_LEFT_RIGHT 0x06a8 #define MACH64_SC_TOP 0x06ac #define MACH64_SC_BOTTOM 0x06b0 #define MACH64_SC_TOP_BOTTOM 0x06b4 #define MACH64_SCALE_3D_CNTL 0x05fc #define MACH64_SCRATCH_REG0 0x0480 #define MACH64_SCRATCH_REG1 0x0484 #define MACH64_SECONDARY_TEX_OFF 0x0778 #define MACH64_SETUP_CNTL 0x0304 #define MACH64_SRC_CNTL 0x05b4 # define MACH64_SRC_BM_ENABLE (1 << 8) # define MACH64_SRC_BM_SYNC (1 << 9) # define MACH64_SRC_BM_OP_FRAME_TO_SYSTEM (0 << 10) # define MACH64_SRC_BM_OP_SYSTEM_TO_FRAME (1 << 10) # define MACH64_SRC_BM_OP_REG_TO_SYSTEM (2 << 10) # define MACH64_SRC_BM_OP_SYSTEM_TO_REG (3 << 10) #define MACH64_SRC_HEIGHT1 0x0594 #define MACH64_SRC_HEIGHT2 0x05ac #define MACH64_SRC_HEIGHT1_WIDTH1 0x0598 #define MACH64_SRC_HEIGHT2_WIDTH2 0x05b0 #define MACH64_SRC_OFF_PITCH 0x0580 #define MACH64_SRC_WIDTH1 0x0590 #define MACH64_SRC_Y_X 0x058c #define MACH64_TEX_0_OFF 0x05c0 #define MACH64_TEX_CNTL 0x0774 #define MACH64_TEX_SIZE_PITCH 0x0770 #define MACH64_TIMER_CONFIG 0x0428 #define MACH64_VERTEX_1_ARGB 0x0254 #define MACH64_VERTEX_1_S 0x0240 #define MACH64_VERTEX_1_SECONDARY_S 0x0328 #define MACH64_VERTEX_1_SECONDARY_T 0x032c #define MACH64_VERTEX_1_SECONDARY_W 0x0330 #define MACH64_VERTEX_1_SPEC_ARGB 0x024c #define MACH64_VERTEX_1_T 0x0244 #define MACH64_VERTEX_1_W 0x0248 #define MACH64_VERTEX_1_X_Y 0x0258 #define MACH64_VERTEX_1_Z 0x0250 #define MACH64_VERTEX_2_ARGB 0x0274 #define MACH64_VERTEX_2_S 0x0260 #define MACH64_VERTEX_2_SECONDARY_S 0x0334 #define MACH64_VERTEX_2_SECONDARY_T 0x0338 #define MACH64_VERTEX_2_SECONDARY_W 0x033c #define MACH64_VERTEX_2_SPEC_ARGB 0x026c #define MACH64_VERTEX_2_T 0x0264 #define MACH64_VERTEX_2_W 0x0268 #define MACH64_VERTEX_2_X_Y 0x0278 #define MACH64_VERTEX_2_Z 0x0270 #define MACH64_VERTEX_3_ARGB 0x0294 #define MACH64_VERTEX_3_S 0x0280 #define MACH64_VERTEX_3_SECONDARY_S 0x02a0 #define MACH64_VERTEX_3_SECONDARY_T 0x02a4 #define MACH64_VERTEX_3_SECONDARY_W 0x02a8 #define MACH64_VERTEX_3_SPEC_ARGB 0x028c #define MACH64_VERTEX_3_T 0x0284 #define MACH64_VERTEX_3_W 0x0288 #define MACH64_VERTEX_3_X_Y 0x0298 #define MACH64_VERTEX_3_Z 0x0290 #define MACH64_Z_CNTL 0x054c #define MACH64_Z_OFF_PITCH 0x0548 #define MACH64_CRTC_VLINE_CRNT_VLINE 0x0410 # define MACH64_CRTC_VLINE_MASK 0x000007ff # define MACH64_CRTC_CRNT_VLINE_MASK 0x07ff0000 #define MACH64_CRTC_OFF_PITCH 0x0414 #define MACH64_CRTC_INT_CNTL 0x0418 # define MACH64_CRTC_VBLANK (1 << 0) # define MACH64_CRTC_VBLANK_INT_EN (1 << 1) # define MACH64_CRTC_VBLANK_INT (1 << 2) # define MACH64_CRTC_VLINE_INT_EN (1 << 3) # define MACH64_CRTC_VLINE_INT (1 << 4) # define MACH64_CRTC_VLINE_SYNC (1 << 5) /* 0=even, 1=odd */ # define MACH64_CRTC_FRAME (1 << 6) /* 0=even, 1=odd */ # define MACH64_CRTC_SNAPSHOT_INT_EN (1 << 7) # define MACH64_CRTC_SNAPSHOT_INT (1 << 8) # define MACH64_CRTC_I2C_INT_EN (1 << 9) # define MACH64_CRTC_I2C_INT (1 << 10) # define MACH64_CRTC2_VBLANK (1 << 11) /* LT Pro */ # define MACH64_CRTC2_VBLANK_INT_EN (1 << 12) /* LT Pro */ # define MACH64_CRTC2_VBLANK_INT (1 << 13) /* LT Pro */ # define MACH64_CRTC2_VLINE_INT_EN (1 << 14) /* LT Pro */ # define MACH64_CRTC2_VLINE_INT (1 << 15) /* LT Pro */ # define MACH64_CRTC_CAPBUF0_INT_EN (1 << 16) # define MACH64_CRTC_CAPBUF0_INT (1 << 17) # define MACH64_CRTC_CAPBUF1_INT_EN (1 << 18) # define MACH64_CRTC_CAPBUF1_INT (1 << 19) # define MACH64_CRTC_OVERLAY_EOF_INT_EN (1 << 20) # define MACH64_CRTC_OVERLAY_EOF_INT (1 << 21) # define MACH64_CRTC_ONESHOT_CAP_INT_EN (1 << 22) # define MACH64_CRTC_ONESHOT_CAP_INT (1 << 23) # define MACH64_CRTC_BUSMASTER_EOL_INT_EN (1 << 24) # define MACH64_CRTC_BUSMASTER_EOL_INT (1 << 25) # define MACH64_CRTC_GP_INT_EN (1 << 26) # define MACH64_CRTC_GP_INT (1 << 27) # define MACH64_CRTC2_VLINE_SYNC (1 << 28) /* LT Pro */ /* 0=even, 1=odd */ # define MACH64_CRTC_SNAPSHOT2_INT_EN (1 << 29) /* LT Pro */ # define MACH64_CRTC_SNAPSHOT2_INT (1 << 30) /* LT Pro */ # define MACH64_CRTC_VBLANK2_INT (1 << 31) # define MACH64_CRTC_INT_ENS \ ( \ MACH64_CRTC_VBLANK_INT_EN | \ MACH64_CRTC_VLINE_INT_EN | \ MACH64_CRTC_SNAPSHOT_INT_EN | \ MACH64_CRTC_I2C_INT_EN | \ MACH64_CRTC2_VBLANK_INT_EN | \ MACH64_CRTC2_VLINE_INT_EN | \ MACH64_CRTC_CAPBUF0_INT_EN | \ MACH64_CRTC_CAPBUF1_INT_EN | \ MACH64_CRTC_OVERLAY_EOF_INT_EN | \ MACH64_CRTC_ONESHOT_CAP_INT_EN | \ MACH64_CRTC_BUSMASTER_EOL_INT_EN | \ MACH64_CRTC_GP_INT_EN | \ MACH64_CRTC_SNAPSHOT2_INT_EN | \ 0 \ ) # define MACH64_CRTC_INT_ACKS \ ( \ MACH64_CRTC_VBLANK_INT | \ MACH64_CRTC_VLINE_INT | \ MACH64_CRTC_SNAPSHOT_INT | \ MACH64_CRTC_I2C_INT | \ MACH64_CRTC2_VBLANK_INT | \ MACH64_CRTC2_VLINE_INT | \ MACH64_CRTC_CAPBUF0_INT | \ MACH64_CRTC_CAPBUF1_INT | \ MACH64_CRTC_OVERLAY_EOF_INT | \ MACH64_CRTC_ONESHOT_CAP_INT | \ MACH64_CRTC_BUSMASTER_EOL_INT | \ MACH64_CRTC_GP_INT | \ MACH64_CRTC_SNAPSHOT2_INT | \ MACH64_CRTC_VBLANK2_INT | \ 0 \ ) #define MACH64_DATATYPE_CI8 2 #define MACH64_DATATYPE_ARGB1555 3 #define MACH64_DATATYPE_RGB565 4 #define MACH64_DATATYPE_ARGB8888 6 #define MACH64_DATATYPE_RGB332 7 #define MACH64_DATATYPE_Y8 8 #define MACH64_DATATYPE_RGB8 9 #define MACH64_DATATYPE_VYUY422 11 #define MACH64_DATATYPE_YVYU422 12 #define MACH64_DATATYPE_AYUV444 14 #define MACH64_DATATYPE_ARGB4444 15 #define MACH64_READ(reg) DRM_READ32(dev_priv->mmio, (reg) ) #define MACH64_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio, (reg), (val) ) #define DWMREG0 0x0400 #define DWMREG0_END 0x07ff #define DWMREG1 0x0000 #define DWMREG1_END 0x03ff #define ISREG0(r) (((r) >= DWMREG0) && ((r) <= DWMREG0_END)) #define DMAREG0(r) (((r) - DWMREG0) >> 2) #define DMAREG1(r) ((((r) - DWMREG1) >> 2 ) | 0x0100) #define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r)) #define MMREG0 0x0000 #define MMREG0_END 0x00ff #define ISMMREG0(r) (((r) >= MMREG0) && ((r) <= MMREG0_END)) #define MMSELECT0(r) (((r) << 2) + DWMREG0) #define MMSELECT1(r) (((((r) & 0xff) << 2) + DWMREG1)) #define MMSELECT(r) (ISMMREG0(r) ? MMSELECT0(r) : MMSELECT1(r)) /* ================================================================ * DMA constants */ /* DMA descriptor field indices: * The descriptor fields are loaded into the read-only * BM_* system bus master registers during a bus-master operation */ #define MACH64_DMA_FRAME_BUF_OFFSET 0 /* BM_FRAME_BUF_OFFSET */ #define MACH64_DMA_SYS_MEM_ADDR 1 /* BM_SYSTEM_MEM_ADDR */ #define MACH64_DMA_COMMAND 2 /* BM_COMMAND */ #define MACH64_DMA_RESERVED 3 /* BM_STATUS */ /* BM_COMMAND descriptor field flags */ #define MACH64_DMA_HOLD_OFFSET (1<<30) /* Don't increment DMA_FRAME_BUF_OFFSET */ #define MACH64_DMA_EOL (1<<31) /* End of descriptor list flag */ #define MACH64_DMA_CHUNKSIZE 0x1000 /* 4kB per DMA descriptor */ #define MACH64_APERTURE_OFFSET 0x7ff800 /* frame-buffer offset for gui-masters */ /* ================================================================ * Misc helper macros */ static __inline__ void mach64_set_dma_eol(volatile u32 * addr) { #if defined(__i386__) int nr = 31; /* Taken from include/asm-i386/bitops.h linux header */ __asm__ __volatile__("lock;" "btsl %1,%0":"=m"(*addr) :"Ir"(nr)); #elif defined(__powerpc__) u32 old; u32 mask = cpu_to_le32(MACH64_DMA_EOL); /* Taken from the include/asm-ppc/bitops.h linux header */ __asm__ __volatile__("\n\ 1: lwarx %0,0,%3 \n\ or %0,%0,%2 \n\ stwcx. %0,0,%3 \n\ bne- 1b":"=&r"(old), "=m"(*addr) :"r"(mask), "r"(addr), "m"(*addr) :"cc"); #elif defined(__alpha__) u32 temp; u32 mask = MACH64_DMA_EOL; /* Taken from the include/asm-alpha/bitops.h linux header */ __asm__ __volatile__("1: ldl_l %0,%3\n" " bis %0,%2,%0\n" " stl_c %0,%1\n" " beq %0,2f\n" ".subsection 2\n" "2: br 1b\n" ".previous":"=&r"(temp), "=m"(*addr) :"Ir"(mask), "m"(*addr)); #else u32 mask = cpu_to_le32(MACH64_DMA_EOL); *addr |= mask; #endif } static __inline__ void mach64_clear_dma_eol(volatile u32 * addr) { #if defined(__i386__) int nr = 31; /* Taken from include/asm-i386/bitops.h linux header */ __asm__ __volatile__("lock;" "btrl %1,%0":"=m"(*addr) :"Ir"(nr)); #elif defined(__powerpc__) u32 old; u32 mask = cpu_to_le32(MACH64_DMA_EOL); /* Taken from the include/asm-ppc/bitops.h linux header */ __asm__ __volatile__("\n\ 1: lwarx %0,0,%3 \n\ andc %0,%0,%2 \n\ stwcx. %0,0,%3 \n\ bne- 1b":"=&r"(old), "=m"(*addr) :"r"(mask), "r"(addr), "m"(*addr) :"cc"); #elif defined(__alpha__) u32 temp; u32 mask = ~MACH64_DMA_EOL; /* Taken from the include/asm-alpha/bitops.h linux header */ __asm__ __volatile__("1: ldl_l %0,%3\n" " and %0,%2,%0\n" " stl_c %0,%1\n" " beq %0,2f\n" ".subsection 2\n" "2: br 1b\n" ".previous":"=&r"(temp), "=m"(*addr) :"Ir"(mask), "m"(*addr)); #else u32 mask = cpu_to_le32(~MACH64_DMA_EOL); *addr &= mask; #endif } static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", __FUNCTION__, ring->head_addr, ring->head, ring->tail, ring->space); if (mach64_do_wait_for_idle(dev_priv) < 0) { mach64_do_engine_reset(dev_priv); } if (dev_priv->driver_mode != MACH64_MODE_MMIO) { /* enable bus mastering and block 1 registers */ MACH64_WRITE(MACH64_BUS_CNTL, (MACH64_READ(MACH64_BUS_CNTL) & ~MACH64_BUS_MASTER_DIS) | MACH64_BUS_EXT_REG_EN); mach64_do_wait_for_idle(dev_priv); } /* reset descriptor table ring head */ MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); dev_priv->ring_running = 1; } static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv, drm_mach64_descriptor_ring_t * ring) { DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", __FUNCTION__, ring->head_addr, ring->head, ring->tail, ring->space); /* reset descriptor table ring head */ MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); if (dev_priv->driver_mode == MACH64_MODE_MMIO) { mach64_do_dispatch_pseudo_dma(dev_priv); } else { /* enable GUI bus mastering, and sync the bus master to the GUI */ MACH64_WRITE(MACH64_SRC_CNTL, MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC | MACH64_SRC_BM_OP_SYSTEM_TO_REG); /* kick off the transfer */ MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0); if (dev_priv->driver_mode == MACH64_MODE_DMA_SYNC) { if ((mach64_do_wait_for_idle(dev_priv)) < 0) { DRM_ERROR("%s: idle failed, resetting engine\n", __FUNCTION__); mach64_dump_engine_info(dev_priv); mach64_do_engine_reset(dev_priv); return; } mach64_do_release_used_buffers(dev_priv); } } } static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv, drm_mach64_descriptor_ring_t * ring) { DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", __FUNCTION__, ring->head_addr, ring->head, ring->tail, ring->space); if (!dev_priv->ring_running) { mach64_ring_start(dev_priv); if (ring->head != ring->tail) { mach64_ring_resume(dev_priv, ring); } } else { /* GUI_ACTIVE must be read before BM_GUI_TABLE to * correctly determine the ring head */ int gui_active = MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE; ring->head_addr = MACH64_READ(MACH64_BM_GUI_TABLE) & 0xfffffff0; if (gui_active) { /* If not idle, BM_GUI_TABLE points one descriptor * past the current head */ if (ring->head_addr == ring->start_addr) { ring->head_addr += ring->size; } ring->head_addr -= 4 * sizeof(u32); } if (ring->head_addr < ring->start_addr || ring->head_addr >= ring->start_addr + ring->size) { DRM_ERROR("bad ring head address: 0x%08x\n", ring->head_addr); mach64_dump_ring_info(dev_priv); mach64_do_engine_reset(dev_priv); return; } ring->head = (ring->head_addr - ring->start_addr) / sizeof(u32); if (!gui_active && ring->head != ring->tail) { mach64_ring_resume(dev_priv, ring); } } } static __inline__ void mach64_ring_stop(drm_mach64_private_t * dev_priv) { DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", __FUNCTION__, dev_priv->ring.head_addr, dev_priv->ring.head, dev_priv->ring.tail, dev_priv->ring.space); /* restore previous SRC_CNTL to disable busmastering */ mach64_do_wait_for_fifo(dev_priv, 1); MACH64_WRITE(MACH64_SRC_CNTL, 0); /* disable busmastering but keep the block 1 registers enabled */ mach64_do_wait_for_idle(dev_priv); MACH64_WRITE(MACH64_BUS_CNTL, MACH64_READ(MACH64_BUS_CNTL) | MACH64_BUS_MASTER_DIS | MACH64_BUS_EXT_REG_EN); dev_priv->ring_running = 0; } static __inline__ void mach64_update_ring_snapshot(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; DRM_DEBUG("%s\n", __FUNCTION__); mach64_ring_tick(dev_priv, ring); ring->space = (ring->head - ring->tail) * sizeof(u32); if (ring->space <= 0) { ring->space += ring->size; } } /* ================================================================ * DMA descriptor ring macros */ #define RING_LOCALS \ int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring #define RING_WRITE_OFS _ring_write #define BEGIN_RING( n ) \ do { \ if ( MACH64_VERBOSE ) { \ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ (n), __FUNCTION__ ); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ int ret; \ if ((ret=mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \ DRM_ERROR( "wait_ring failed, resetting engine\n"); \ mach64_dump_engine_info( dev_priv ); \ mach64_do_engine_reset( dev_priv ); \ return ret; \ } \ } \ dev_priv->ring.space -= (n) * sizeof(u32); \ _ring = (u32 *) dev_priv->ring.start; \ _ring_tail = _ring_write = dev_priv->ring.tail; \ _ring_mask = dev_priv->ring.tail_mask; \ } while (0) #define OUT_RING( x ) \ do { \ if ( MACH64_VERBOSE ) { \ DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ (unsigned int)(x), _ring_write ); \ } \ _ring[_ring_write++] = cpu_to_le32( x ); \ _ring_write &= _ring_mask; \ } while (0) #define ADVANCE_RING() \ do { \ if ( MACH64_VERBOSE ) { \ DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ _ring_write, _ring_tail ); \ } \ DRM_MEMORYBARRIER(); \ mach64_clear_dma_eol( &_ring[(_ring_tail - 2) & _ring_mask] ); \ DRM_MEMORYBARRIER(); \ dev_priv->ring.tail = _ring_write; \ mach64_ring_tick( dev_priv, &(dev_priv)->ring ); \ } while (0) /* ================================================================ * DMA macros */ #define DMALOCALS \ drm_mach64_freelist_t *_entry = NULL; \ drm_buf_t *_buf = NULL; \ u32 *_buf_wptr; int _outcount #define GETBUFPTR( __buf ) \ ((dev_priv->is_pci) ? \ ((u32 *)(__buf)->address) : \ ((u32 *)((char *)dev_priv->dev_buffers->handle + (__buf)->offset))) #define GETBUFADDR( __buf ) ((u32)(__buf)->bus_address) #define GETRINGOFFSET() (_entry->ring_ofs) static __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t * dev_priv, drm_mach64_freelist_t ** entry, drm_buf_t * buf) { struct list_head *ptr; #if MACH64_EXTRA_CHECKING if (list_empty(&dev_priv->pending)) { DRM_ERROR("Empty pending list in %s\n", __FUNCTION__); return DRM_ERR(EINVAL); } #endif ptr = dev_priv->pending.prev; *entry = list_entry(ptr, drm_mach64_freelist_t, list); while ((*entry)->buf != buf) { if (ptr == &dev_priv->pending) { return DRM_ERR(EFAULT); } ptr = ptr->prev; *entry = list_entry(ptr, drm_mach64_freelist_t, list); } return 0; } #define DMASETPTR( _p ) \ do { \ _buf = (_p); \ _outcount = 0; \ _buf_wptr = GETBUFPTR( _buf ); \ } while(0) /* FIXME: use a private set of smaller buffers for state emits, clears, and swaps? */ #define DMAGETPTR( filp, dev_priv, n ) \ do { \ if ( MACH64_VERBOSE ) { \ DRM_INFO( "DMAGETPTR( %d ) in %s\n", \ n, __FUNCTION__ ); \ } \ _buf = mach64_freelist_get( dev_priv ); \ if (_buf == NULL) { \ DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", \ __FUNCTION__ ); \ return DRM_ERR(EAGAIN); \ } \ if (_buf->pending) { \ DRM_ERROR("%s: pending buf in DMAGETPTR\n", \ __FUNCTION__ ); \ return DRM_ERR(EFAULT); \ } \ _buf->filp = filp; \ _outcount = 0; \ \ _buf_wptr = GETBUFPTR( _buf ); \ } while (0) #define DMAOUTREG( reg, val ) \ do { \ if ( MACH64_VERBOSE ) { \ DRM_INFO( " DMAOUTREG( 0x%x = 0x%08x )\n", \ reg, val ); \ } \ _buf_wptr[_outcount++] = cpu_to_le32(DMAREG(reg)); \ _buf_wptr[_outcount++] = cpu_to_le32((val)); \ _buf->used += 8; \ } while (0) #define DMAADVANCE( dev_priv, _discard ) \ do { \ struct list_head *ptr; \ RING_LOCALS; \ \ if ( MACH64_VERBOSE ) { \ DRM_INFO( "DMAADVANCE() in %s\n", __FUNCTION__ ); \ } \ \ if (_buf->used <= 0) { \ DRM_ERROR( "DMAADVANCE() in %s: sending empty buf %d\n", \ __FUNCTION__, _buf->idx ); \ return DRM_ERR(EFAULT); \ } \ if (_buf->pending) { \ /* This is a resued buffer, so we need to find it in the pending list */ \ int ret; \ if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \ DRM_ERROR( "DMAADVANCE() in %s: couldn't find pending buf %d\n", \ __FUNCTION__, _buf->idx ); \ return ret; \ } \ if (_entry->discard) { \ DRM_ERROR( "DMAADVANCE() in %s: sending discarded pending buf %d\n", \ __FUNCTION__, _buf->idx ); \ return DRM_ERR(EFAULT); \ } \ } else { \ if (list_empty(&dev_priv->placeholders)) { \ DRM_ERROR( "DMAADVANCE() in %s: empty placeholder list\n", \ __FUNCTION__ ); \ return DRM_ERR(EFAULT); \ } \ ptr = dev_priv->placeholders.next; \ list_del(ptr); \ _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ _buf->pending = 1; \ _entry->buf = _buf; \ list_add_tail(ptr, &dev_priv->pending); \ } \ _entry->discard = (_discard); \ ADD_BUF_TO_RING( dev_priv ); \ } while (0) #define DMADISCARDBUF() \ do { \ if (_entry == NULL) { \ int ret; \ if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \ DRM_ERROR( "%s: couldn't find pending buf %d\n", \ __FUNCTION__, _buf->idx ); \ return ret; \ } \ } \ _entry->discard = 1; \ } while(0) #define ADD_BUF_TO_RING( dev_priv ) \ do { \ int bytes, pages, remainder; \ u32 address, page; \ int i; \ \ bytes = _buf->used; \ address = GETBUFADDR( _buf ); \ \ pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; \ \ BEGIN_RING( pages * 4 ); \ \ for ( i = 0 ; i < pages-1 ; i++ ) { \ page = address + i * MACH64_DMA_CHUNKSIZE; \ OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ OUT_RING( page ); \ OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); \ OUT_RING( 0 ); \ } \ \ /* generate the final descriptor for any remaining commands in this buffer */ \ page = address + i * MACH64_DMA_CHUNKSIZE; \ remainder = bytes - i * MACH64_DMA_CHUNKSIZE; \ \ /* Save dword offset of last descriptor for this buffer. \ * This is needed to check for completion of the buffer in freelist_get \ */ \ _entry->ring_ofs = RING_WRITE_OFS; \ \ OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ OUT_RING( page ); \ OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); \ OUT_RING( 0 ); \ \ ADVANCE_RING(); \ } while(0) #define DMAADVANCEHOSTDATA( dev_priv ) \ do { \ struct list_head *ptr; \ RING_LOCALS; \ \ if ( MACH64_VERBOSE ) { \ DRM_INFO( "DMAADVANCEHOSTDATA() in %s\n", __FUNCTION__ ); \ } \ \ if (_buf->used <= 0) { \ DRM_ERROR( "DMAADVANCEHOSTDATA() in %s: sending empty buf %d\n", \ __FUNCTION__, _buf->idx ); \ return DRM_ERR(EFAULT); \ } \ if (list_empty(&dev_priv->placeholders)) { \ DRM_ERROR( "%s: empty placeholder list in DMAADVANCEHOSTDATA()\n", \ __FUNCTION__ ); \ return DRM_ERR(EFAULT); \ } \ \ ptr = dev_priv->placeholders.next; \ list_del(ptr); \ _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ _entry->buf = _buf; \ _entry->buf->pending = 1; \ list_add_tail(ptr, &dev_priv->pending); \ _entry->discard = 1; \ ADD_HOSTDATA_BUF_TO_RING( dev_priv ); \ } while (0) #define ADD_HOSTDATA_BUF_TO_RING( dev_priv ) \ do { \ int bytes, pages, remainder; \ u32 address, page; \ int i; \ \ bytes = _buf->used - MACH64_HOSTDATA_BLIT_OFFSET; \ pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; \ address = GETBUFADDR( _buf ); \ \ BEGIN_RING( 4 + pages * 4 ); \ \ OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ OUT_RING( address ); \ OUT_RING( MACH64_HOSTDATA_BLIT_OFFSET | MACH64_DMA_HOLD_OFFSET ); \ OUT_RING( 0 ); \ \ address += MACH64_HOSTDATA_BLIT_OFFSET; \ \ for ( i = 0 ; i < pages-1 ; i++ ) { \ page = address + i * MACH64_DMA_CHUNKSIZE; \ OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \ OUT_RING( page ); \ OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); \ OUT_RING( 0 ); \ } \ \ /* generate the final descriptor for any remaining commands in this buffer */ \ page = address + i * MACH64_DMA_CHUNKSIZE; \ remainder = bytes - i * MACH64_DMA_CHUNKSIZE; \ \ /* Save dword offset of last descriptor for this buffer. \ * This is needed to check for completion of the buffer in freelist_get \ */ \ _entry->ring_ofs = RING_WRITE_OFS; \ \ OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \ OUT_RING( page ); \ OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); \ OUT_RING( 0 ); \ \ ADVANCE_RING(); \ } while(0) #endif /* __MACH64_DRV_H__ */ Index: head/sys/dev/drm/mach64_irq.c =================================================================== --- head/sys/dev/drm/mach64_irq.c (revision 152908) +++ head/sys/dev/drm/mach64_irq.c (revision 152909) @@ -1,137 +1,139 @@ /* mach64_irq.c -- IRQ handling for ATI Mach64 -*- linux-c -*- * Created: Tue Feb 25, 2003 by Leif Delgass, based on radeon_irq.c/r128_irq.c - * + */ +/*- * Copyright (C) The Weather Channel, Inc. 2002. * Copyright 2003 Leif Delgass * All Rights Reserved. * * The Weather Channel (TM) funded Tungsten Graphics to develop the * initial release of the Radeon 8500 driver under the XFree86 license. * This notice must be preserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Keith Whitwell * Eric Anholt * Leif Delgass - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/mach64_drm.h" #include "dev/drm/mach64_drv.h" irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; drm_mach64_private_t *dev_priv = (drm_mach64_private_t *) dev->dev_private; int status; status = MACH64_READ(MACH64_CRTC_INT_CNTL); /* VBLANK interrupt */ if (status & MACH64_CRTC_VBLANK_INT) { /* Mask off all interrupt ack bits before setting the ack bit, since * there may be other handlers outside the DRM. * * NOTE: On mach64, you need to keep the enable bits set when doing * the ack, despite what the docs say about not acking and enabling * in a single write. */ MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_INT_ACKS) | MACH64_CRTC_VBLANK_INT); atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); return IRQ_HANDLED; } return IRQ_NONE; } int mach64_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) { unsigned int cur_vblank; int ret = 0; /* Assume that the user has missed the current sequence number * by about a day rather than she wants to wait for years * using vertical blanks... */ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, (((cur_vblank = atomic_read(&dev->vbl_received)) - *sequence) <= (1 << 23))); *sequence = cur_vblank; return ret; } /* drm_dma.h hooks */ void mach64_driver_irq_preinstall(drm_device_t * dev) { drm_mach64_private_t *dev_priv = (drm_mach64_private_t *) dev->dev_private; u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status); /* Disable and clear VBLANK interrupt */ MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN) | MACH64_CRTC_VBLANK_INT); } void mach64_driver_irq_postinstall(drm_device_t * dev) { drm_mach64_private_t *dev_priv = (drm_mach64_private_t *) dev->dev_private; /* Turn on VBLANK interrupt */ MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL) | MACH64_CRTC_VBLANK_INT_EN); DRM_DEBUG("after install CRTC_INT_CTNL: 0x%08x\n", MACH64_READ(MACH64_CRTC_INT_CNTL)); } void mach64_driver_irq_uninstall(drm_device_t * dev) { drm_mach64_private_t *dev_priv = (drm_mach64_private_t *) dev->dev_private; if (!dev_priv) return; /* Disable and clear VBLANK interrupt */ MACH64_WRITE(MACH64_CRTC_INT_CNTL, (MACH64_READ(MACH64_CRTC_INT_CNTL) & ~MACH64_CRTC_VBLANK_INT_EN) | MACH64_CRTC_VBLANK_INT); DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n", MACH64_READ(MACH64_CRTC_INT_CNTL)); } Index: head/sys/dev/drm/mach64_state.c =================================================================== --- head/sys/dev/drm/mach64_state.c (revision 152908) +++ head/sys/dev/drm/mach64_state.c (revision 152909) @@ -1,918 +1,921 @@ /* mach64_state.c -- State support for mach64 (Rage Pro) driver -*- linux-c -*- * Created: Sun Dec 03 19:20:26 2000 by gareth@valinux.com - * + */ +/*- * Copyright 2000 Gareth Hughes * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * Leif Delgass * Jos�Fonseca - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/mach64_drm.h" #include "dev/drm/mach64_drv.h" /* Interface history: * * 1.0 - Initial mach64 DRM * */ drm_ioctl_desc_t mach64_ioctls[] = { - [DRM_IOCTL_NR(DRM_MACH64_INIT)] = {mach64_dma_init, 1, 1}, - [DRM_IOCTL_NR(DRM_MACH64_CLEAR)] = {mach64_dma_clear, 1, 0}, - [DRM_IOCTL_NR(DRM_MACH64_SWAP)] = {mach64_dma_swap, 1, 0}, - [DRM_IOCTL_NR(DRM_MACH64_IDLE)] = {mach64_dma_idle, 1, 0}, - [DRM_IOCTL_NR(DRM_MACH64_RESET)] = {mach64_engine_reset, 1, 0}, - [DRM_IOCTL_NR(DRM_MACH64_VERTEX)] = {mach64_dma_vertex, 1, 0}, - [DRM_IOCTL_NR(DRM_MACH64_BLIT)] = {mach64_dma_blit, 1, 0}, - [DRM_IOCTL_NR(DRM_MACH64_FLUSH)] = {mach64_dma_flush, 1, 0}, - [DRM_IOCTL_NR(DRM_MACH64_GETPARAM)] = {mach64_get_param, 1, 0}, + [DRM_IOCTL_NR(DRM_MACH64_INIT)] = {mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_MACH64_CLEAR)] = {mach64_dma_clear, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MACH64_SWAP)] = {mach64_dma_swap, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MACH64_IDLE)] = {mach64_dma_idle, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MACH64_RESET)] = {mach64_engine_reset, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MACH64_VERTEX)] = {mach64_dma_vertex, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MACH64_BLIT)] = {mach64_dma_blit, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MACH64_FLUSH)] = {mach64_dma_flush, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MACH64_GETPARAM)] = {mach64_get_param, DRM_AUTH}, }; int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls); /* ================================================================ * DMA hardware state programming functions */ static void mach64_print_dirty(const char *msg, unsigned int flags) { DRM_DEBUG("%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s\n", msg, flags, (flags & MACH64_UPLOAD_DST_OFF_PITCH) ? "dst_off_pitch, " : "", (flags & MACH64_UPLOAD_Z_ALPHA_CNTL) ? "z_alpha_cntl, " : "", (flags & MACH64_UPLOAD_SCALE_3D_CNTL) ? "scale_3d_cntl, " : "", (flags & MACH64_UPLOAD_DP_FOG_CLR) ? "dp_fog_clr, " : "", (flags & MACH64_UPLOAD_DP_WRITE_MASK) ? "dp_write_mask, " : "", (flags & MACH64_UPLOAD_DP_PIX_WIDTH) ? "dp_pix_width, " : "", (flags & MACH64_UPLOAD_SETUP_CNTL) ? "setup_cntl, " : "", (flags & MACH64_UPLOAD_MISC) ? "misc, " : "", (flags & MACH64_UPLOAD_TEXTURE) ? "texture, " : "", (flags & MACH64_UPLOAD_TEX0IMAGE) ? "tex0 image, " : "", (flags & MACH64_UPLOAD_TEX1IMAGE) ? "tex1 image, " : "", (flags & MACH64_UPLOAD_CLIPRECTS) ? "cliprects, " : ""); } /* Mach64 doesn't have hardware cliprects, just one hardware scissor, * so the GL scissor is intersected with each cliprect here */ /* This function returns 0 on success, 1 for no intersection, and * negative for an error */ static int mach64_emit_cliprect(DRMFILE filp, drm_mach64_private_t * dev_priv, drm_clip_rect_t * box) { u32 sc_left_right, sc_top_bottom; drm_clip_rect_t scissor; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_context_regs_t *regs = &sarea_priv->context_state; DMALOCALS; DRM_DEBUG("%s: box=%p\n", __FUNCTION__, box); /* Get GL scissor */ /* FIXME: store scissor in SAREA as a cliprect instead of in * hardware format, or do intersection client-side */ scissor.x1 = regs->sc_left_right & 0xffff; scissor.x2 = (regs->sc_left_right & 0xffff0000) >> 16; scissor.y1 = regs->sc_top_bottom & 0xffff; scissor.y2 = (regs->sc_top_bottom & 0xffff0000) >> 16; /* Intersect GL scissor with cliprect */ if (box->x1 > scissor.x1) scissor.x1 = box->x1; if (box->y1 > scissor.y1) scissor.y1 = box->y1; if (box->x2 < scissor.x2) scissor.x2 = box->x2; if (box->y2 < scissor.y2) scissor.y2 = box->y2; /* positive return means skip */ if (scissor.x1 >= scissor.x2) return 1; if (scissor.y1 >= scissor.y2) return 1; DMAGETPTR(filp, dev_priv, 2); /* returns on failure to get buffer */ sc_left_right = ((scissor.x1 << 0) | (scissor.x2 << 16)); sc_top_bottom = ((scissor.y1 << 0) | (scissor.y2 << 16)); DMAOUTREG(MACH64_SC_LEFT_RIGHT, sc_left_right); DMAOUTREG(MACH64_SC_TOP_BOTTOM, sc_top_bottom); DMAADVANCE(dev_priv, 1); return 0; } static __inline__ int mach64_emit_state(DRMFILE filp, drm_mach64_private_t * dev_priv) { drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_context_regs_t *regs = &sarea_priv->context_state; unsigned int dirty = sarea_priv->dirty; u32 offset = ((regs->tex_size_pitch & 0xf0) >> 2); DMALOCALS; if (MACH64_VERBOSE) { mach64_print_dirty(__FUNCTION__, dirty); } else { DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty); } DMAGETPTR(filp, dev_priv, 17); /* returns on failure to get buffer */ if (dirty & MACH64_UPLOAD_MISC) { DMAOUTREG(MACH64_DP_MIX, regs->dp_mix); DMAOUTREG(MACH64_DP_SRC, regs->dp_src); DMAOUTREG(MACH64_CLR_CMP_CNTL, regs->clr_cmp_cntl); DMAOUTREG(MACH64_GUI_TRAJ_CNTL, regs->gui_traj_cntl); sarea_priv->dirty &= ~MACH64_UPLOAD_MISC; } if (dirty & MACH64_UPLOAD_DST_OFF_PITCH) { DMAOUTREG(MACH64_DST_OFF_PITCH, regs->dst_off_pitch); sarea_priv->dirty &= ~MACH64_UPLOAD_DST_OFF_PITCH; } if (dirty & MACH64_UPLOAD_Z_OFF_PITCH) { DMAOUTREG(MACH64_Z_OFF_PITCH, regs->z_off_pitch); sarea_priv->dirty &= ~MACH64_UPLOAD_Z_OFF_PITCH; } if (dirty & MACH64_UPLOAD_Z_ALPHA_CNTL) { DMAOUTREG(MACH64_Z_CNTL, regs->z_cntl); DMAOUTREG(MACH64_ALPHA_TST_CNTL, regs->alpha_tst_cntl); sarea_priv->dirty &= ~MACH64_UPLOAD_Z_ALPHA_CNTL; } if (dirty & MACH64_UPLOAD_SCALE_3D_CNTL) { DMAOUTREG(MACH64_SCALE_3D_CNTL, regs->scale_3d_cntl); sarea_priv->dirty &= ~MACH64_UPLOAD_SCALE_3D_CNTL; } if (dirty & MACH64_UPLOAD_DP_FOG_CLR) { DMAOUTREG(MACH64_DP_FOG_CLR, regs->dp_fog_clr); sarea_priv->dirty &= ~MACH64_UPLOAD_DP_FOG_CLR; } if (dirty & MACH64_UPLOAD_DP_WRITE_MASK) { DMAOUTREG(MACH64_DP_WRITE_MASK, regs->dp_write_mask); sarea_priv->dirty &= ~MACH64_UPLOAD_DP_WRITE_MASK; } if (dirty & MACH64_UPLOAD_DP_PIX_WIDTH) { DMAOUTREG(MACH64_DP_PIX_WIDTH, regs->dp_pix_width); sarea_priv->dirty &= ~MACH64_UPLOAD_DP_PIX_WIDTH; } if (dirty & MACH64_UPLOAD_SETUP_CNTL) { DMAOUTREG(MACH64_SETUP_CNTL, regs->setup_cntl); sarea_priv->dirty &= ~MACH64_UPLOAD_SETUP_CNTL; } if (dirty & MACH64_UPLOAD_TEXTURE) { DMAOUTREG(MACH64_TEX_SIZE_PITCH, regs->tex_size_pitch); DMAOUTREG(MACH64_TEX_CNTL, regs->tex_cntl); DMAOUTREG(MACH64_SECONDARY_TEX_OFF, regs->secondary_tex_off); DMAOUTREG(MACH64_TEX_0_OFF + offset, regs->tex_offset); sarea_priv->dirty &= ~MACH64_UPLOAD_TEXTURE; } DMAADVANCE(dev_priv, 1); sarea_priv->dirty &= MACH64_UPLOAD_CLIPRECTS; return 0; } /* ================================================================ * DMA command dispatch functions */ static int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev, unsigned int flags, int cx, int cy, int cw, int ch, unsigned int clear_color, unsigned int clear_depth) { drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_context_regs_t *ctx = &sarea_priv->context_state; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; u32 fb_bpp, depth_bpp; int i; DMALOCALS; DRM_DEBUG("%s\n", __FUNCTION__); switch (dev_priv->fb_bpp) { case 16: fb_bpp = MACH64_DATATYPE_RGB565; break; case 32: fb_bpp = MACH64_DATATYPE_ARGB8888; break; default: return DRM_ERR(EINVAL); } switch (dev_priv->depth_bpp) { case 16: depth_bpp = MACH64_DATATYPE_RGB565; break; case 24: case 32: depth_bpp = MACH64_DATATYPE_ARGB8888; break; default: return DRM_ERR(EINVAL); } if (!nbox) return 0; DMAGETPTR(filp, dev_priv, nbox * 31); /* returns on failure to get buffer */ for (i = 0; i < nbox; i++) { int x = pbox[i].x1; int y = pbox[i].y1; int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2, flags); if (flags & (MACH64_FRONT | MACH64_BACK)) { /* Setup for color buffer clears */ DMAOUTREG(MACH64_Z_CNTL, 0); DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right); DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom); DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); DMAOUTREG(MACH64_GUI_TRAJ_CNTL, (MACH64_DST_X_LEFT_TO_RIGHT | MACH64_DST_Y_TOP_TO_BOTTOM)); DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) | (fb_bpp << 4) | (fb_bpp << 8) | (fb_bpp << 16) | (fb_bpp << 28))); DMAOUTREG(MACH64_DP_FRGD_CLR, clear_color); DMAOUTREG(MACH64_DP_WRITE_MASK, ctx->dp_write_mask); DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S)); DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR | MACH64_FRGD_SRC_FRGD_CLR | MACH64_MONO_SRC_ONE)); } if (flags & MACH64_FRONT) { DMAOUTREG(MACH64_DST_OFF_PITCH, dev_priv->front_offset_pitch); DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); } if (flags & MACH64_BACK) { DMAOUTREG(MACH64_DST_OFF_PITCH, dev_priv->back_offset_pitch); DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); } if (flags & MACH64_DEPTH) { /* Setup for depth buffer clear */ DMAOUTREG(MACH64_Z_CNTL, 0); DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right); DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom); DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); DMAOUTREG(MACH64_GUI_TRAJ_CNTL, (MACH64_DST_X_LEFT_TO_RIGHT | MACH64_DST_Y_TOP_TO_BOTTOM)); DMAOUTREG(MACH64_DP_PIX_WIDTH, ((depth_bpp << 0) | (depth_bpp << 4) | (depth_bpp << 8) | (depth_bpp << 16) | (depth_bpp << 28))); DMAOUTREG(MACH64_DP_FRGD_CLR, clear_depth); DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S)); DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR | MACH64_FRGD_SRC_FRGD_CLR | MACH64_MONO_SRC_ONE)); DMAOUTREG(MACH64_DST_OFF_PITCH, dev_priv->depth_offset_pitch); DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); } } DMAADVANCE(dev_priv, 1); return 0; } static int mach64_dma_dispatch_swap(DRMFILE filp, drm_device_t * dev) { drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; u32 fb_bpp; int i; DMALOCALS; DRM_DEBUG("%s\n", __FUNCTION__); switch (dev_priv->fb_bpp) { case 16: fb_bpp = MACH64_DATATYPE_RGB565; break; case 32: default: fb_bpp = MACH64_DATATYPE_ARGB8888; break; } if (!nbox) return 0; DMAGETPTR(filp, dev_priv, 13 + nbox * 4); /* returns on failure to get buffer */ DMAOUTREG(MACH64_Z_CNTL, 0); DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */ DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16)); DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); DMAOUTREG(MACH64_GUI_TRAJ_CNTL, (MACH64_DST_X_LEFT_TO_RIGHT | MACH64_DST_Y_TOP_TO_BOTTOM)); DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) | (fb_bpp << 4) | (fb_bpp << 8) | (fb_bpp << 16) | (fb_bpp << 28))); DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S)); DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_BKGD_CLR | MACH64_FRGD_SRC_BLIT | MACH64_MONO_SRC_ONE)); DMAOUTREG(MACH64_SRC_OFF_PITCH, dev_priv->back_offset_pitch); DMAOUTREG(MACH64_DST_OFF_PITCH, dev_priv->front_offset_pitch); for (i = 0; i < nbox; i++) { int x = pbox[i].x1; int y = pbox[i].y1; int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2); DMAOUTREG(MACH64_SRC_WIDTH1, w); DMAOUTREG(MACH64_SRC_Y_X, (x << 16) | y); DMAOUTREG(MACH64_DST_Y_X, (x << 16) | y); DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); } DMAADVANCE(dev_priv, 1); if (dev_priv->driver_mode == MACH64_MODE_DMA_ASYNC) { for (i = 0; i < MACH64_MAX_QUEUED_FRAMES - 1; i++) { dev_priv->frame_ofs[i] = dev_priv->frame_ofs[i + 1]; } dev_priv->frame_ofs[i] = GETRINGOFFSET(); dev_priv->sarea_priv->frames_queued++; } return 0; } static int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; int i, start; u32 head, tail, ofs; DRM_DEBUG("%s\n", __FUNCTION__); if (sarea_priv->frames_queued == 0) return 0; tail = ring->tail; mach64_ring_tick(dev_priv, ring); head = ring->head; start = (MACH64_MAX_QUEUED_FRAMES - DRM_MIN(MACH64_MAX_QUEUED_FRAMES, sarea_priv->frames_queued)); if (head == tail) { sarea_priv->frames_queued = 0; for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) { dev_priv->frame_ofs[i] = ~0; } return 0; } for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) { ofs = dev_priv->frame_ofs[i]; DRM_DEBUG("frame_ofs[%d] ofs: %d\n", i, ofs); if (ofs == ~0 || (head < tail && (ofs < head || ofs >= tail)) || (head > tail && (ofs < head && ofs >= tail))) { sarea_priv->frames_queued = (MACH64_MAX_QUEUED_FRAMES - 1) - i; dev_priv->frame_ofs[i] = ~0; } } return sarea_priv->frames_queued; } /* Copy and verify a client submited buffer. * FIXME: Make an assembly optimized version */ -static __inline__ int copy_and_verify_from_user(u32 * to, const u32 * from, +static __inline__ int copy_and_verify_from_user(u32 *to, + const u32 __user *ufrom, unsigned long bytes) { unsigned long n = bytes; /* dwords remaining in buffer */ + u32 *from, *orig_from; - if (DRM_VERIFYAREA_READ(from, n)) { - DRM_ERROR("%s: verify_area\n", __FUNCTION__); + from = drm_alloc(bytes, DRM_MEM_DRIVER); + if (from == NULL) + return ENOMEM; + + if (DRM_COPY_FROM_USER(from, ufrom, bytes)) { + drm_free(from, bytes, DRM_MEM_DRIVER); return DRM_ERR(EFAULT); } + orig_from = from; /* we'll be modifying the "from" ptr, so save it */ n >>= 2; while (n > 1) { u32 data, reg, count; - if (DRM_GET_USER_UNCHECKED(data, from++)) { - DRM_ERROR("%s: get_user\n", __FUNCTION__); - return DRM_ERR(EFAULT); - } + data = *from++; n--; reg = le32_to_cpu(data); count = (reg >> 16) + 1; if (count <= n) { n -= count; reg &= 0xffff; /* This is an exact match of Mach64's Setup Engine registers, * excluding SETUP_CNTL (1_C1). */ if ((reg >= 0x0190 && reg < 0x01c1) || (reg >= 0x01ca && reg <= 0x01cf)) { *to++ = data; - if (DRM_COPY_FROM_USER_UNCHECKED - (to, from, count << 2)) { - DRM_ERROR("%s: copy_from_user\n", - __FUNCTION__); - return DRM_ERR(EFAULT); - } + memcpy(to, from, count << 2); + from += count; to += count; } else { DRM_ERROR("%s: Got bad command: 0x%04x\n", __FUNCTION__, reg); + drm_free(orig_from, bytes, DRM_MEM_DRIVER); return DRM_ERR(EACCES); } - - from += count; } else { DRM_ERROR ("%s: Got bad command count(=%u) dwords remaining=%lu\n", __FUNCTION__, count, n); + drm_free(orig_from, bytes, DRM_MEM_DRIVER); return DRM_ERR(EINVAL); } } + drm_free(orig_from, bytes, DRM_MEM_DRIVER); if (n == 0) return 0; else { DRM_ERROR("%s: Bad buf->used(=%lu)\n", __FUNCTION__, bytes); return DRM_ERR(EINVAL); } } static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev, int prim, void *buf, unsigned long used, int discard) { drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_buf_t *copy_buf; int done = 0; int verify_ret = 0; DMALOCALS; DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n", __FUNCTION__, buf, used, sarea_priv->nbox); if (used) { int ret = 0; int i = 0; copy_buf = mach64_freelist_get(dev_priv); if (copy_buf == NULL) { DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", __FUNCTION__); return DRM_ERR(EAGAIN); } if ((verify_ret = copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, used)) == 0) { copy_buf->used = used; DMASETPTR(copy_buf); if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { ret = mach64_emit_state(filp, dev_priv); if (ret < 0) return ret; } do { /* Emit the next cliprect */ if (i < sarea_priv->nbox) { ret = mach64_emit_cliprect(filp, dev_priv, &sarea_priv-> boxes[i]); if (ret < 0) { /* failed to get buffer */ return ret; } else if (ret != 0) { /* null intersection with scissor */ continue; } } if ((i >= sarea_priv->nbox - 1)) done = 1; /* Add the buffer to the DMA queue */ DMAADVANCE(dev_priv, done); } while (++i < sarea_priv->nbox); } if (copy_buf->pending && !done) { DMADISCARDBUF(); } else if (!done) { /* This buffer wasn't used (no cliprects or verify failed), so place it back * on the free list */ struct list_head *ptr; drm_mach64_freelist_t *entry; #if MACH64_EXTRA_CHECKING list_for_each(ptr, &dev_priv->pending) { entry = list_entry(ptr, drm_mach64_freelist_t, list); if (copy_buf == entry->buf) { DRM_ERROR ("%s: Trying to release a pending buf\n", __FUNCTION__); return DRM_ERR(EFAULT); } } #endif ptr = dev_priv->placeholders.next; entry = list_entry(ptr, drm_mach64_freelist_t, list); copy_buf->pending = 0; copy_buf->used = 0; entry->buf = copy_buf; entry->discard = 1; list_del(ptr); list_add_tail(ptr, &dev_priv->free_list); } } sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS; sarea_priv->nbox = 0; return verify_ret; } static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev, drm_mach64_blit_t * blit) { drm_mach64_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; int dword_shift, dwords; drm_buf_t *buf; DMALOCALS; /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll * use a shift instead. */ switch (blit->format) { case MACH64_DATATYPE_ARGB8888: dword_shift = 0; break; case MACH64_DATATYPE_ARGB1555: case MACH64_DATATYPE_RGB565: case MACH64_DATATYPE_VYUY422: case MACH64_DATATYPE_YVYU422: case MACH64_DATATYPE_ARGB4444: dword_shift = 1; break; case MACH64_DATATYPE_CI8: case MACH64_DATATYPE_RGB8: dword_shift = 2; break; default: DRM_ERROR("invalid blit format %d\n", blit->format); return DRM_ERR(EINVAL); } /* Dispatch the blit buffer. */ buf = dma->buflist[blit->idx]; if (buf->filp != filp) { DRM_ERROR("process %d (filp %p) using buffer with filp %p\n", DRM_CURRENTPID, filp, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", blit->idx); return DRM_ERR(EINVAL); } /* Set buf->used to the bytes of blit data based on the blit dimensions * and verify the size. When the setup is emitted to the buffer with * the DMA* macros below, buf->used is incremented to include the bytes * used for setup as well as the blit data. */ dwords = (blit->width * blit->height) >> dword_shift; buf->used = dwords << 2; if (buf->used <= 0 || buf->used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) { DRM_ERROR("Invalid blit size: %d bytes\n", buf->used); return DRM_ERR(EINVAL); } /* FIXME: Use a last buffer flag and reduce the state emitted for subsequent, * continuation buffers? */ /* Blit via BM_HOSTDATA (gui-master) - like HOST_DATA[0-15], but doesn't require * a register command every 16 dwords. State setup is added at the start of the * buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET */ DMASETPTR(buf); DMAOUTREG(MACH64_Z_CNTL, 0); DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */ DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16)); DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); /* disable */ DMAOUTREG(MACH64_GUI_TRAJ_CNTL, MACH64_DST_X_LEFT_TO_RIGHT | MACH64_DST_Y_TOP_TO_BOTTOM); DMAOUTREG(MACH64_DP_PIX_WIDTH, (blit->format << 0) /* dst pix width */ |(blit->format << 4) /* composite pix width */ |(blit->format << 8) /* src pix width */ |(blit->format << 16) /* host data pix width */ |(blit->format << 28) /* scaler/3D pix width */ ); DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); /* enable all planes */ DMAOUTREG(MACH64_DP_MIX, MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S); DMAOUTREG(MACH64_DP_SRC, MACH64_BKGD_SRC_BKGD_CLR | MACH64_FRGD_SRC_HOST | MACH64_MONO_SRC_ONE); DMAOUTREG(MACH64_DST_OFF_PITCH, (blit->pitch << 22) | (blit->offset >> 3)); DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x); DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width); DRM_DEBUG("%s: %d bytes\n", __FUNCTION__, buf->used); /* Add the buffer to the queue */ DMAADVANCEHOSTDATA(dev_priv); return 0; } /* ================================================================ * IOCTL functions */ int mach64_dma_clear(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_clear_t clear; int ret; DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(clear, (drm_mach64_clear_t *) data, sizeof(clear)); if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; ret = mach64_dma_dispatch_clear(filp, dev, clear.flags, clear.x, clear.y, clear.w, clear.h, clear.clear_color, clear.clear_depth); /* Make sure we restore the 3D state next time. */ sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC); return ret; } int mach64_dma_swap(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; int ret; DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID); LOCK_TEST_WITH_RETURN(dev, filp); if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; ret = mach64_dma_dispatch_swap(filp, dev); /* Make sure we restore the 3D state next time. */ sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC); return ret; } int mach64_dma_vertex(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_vertex_t vertex; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(vertex, (drm_mach64_vertex_t *) data, sizeof(vertex)); DRM_DEBUG("%s: pid=%d buf=%p used=%lu discard=%d\n", __FUNCTION__, DRM_CURRENTPID, vertex.buf, vertex.used, vertex.discard); if (vertex.prim < 0 || vertex.prim > MACH64_PRIM_POLYGON) { DRM_ERROR("buffer prim %d\n", vertex.prim); return DRM_ERR(EINVAL); } if (vertex.used > MACH64_BUFFER_SIZE || (vertex.used & 3) != 0) { DRM_ERROR("Invalid vertex buffer size: %lu bytes\n", vertex.used); return DRM_ERR(EINVAL); } if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; return mach64_dma_dispatch_vertex(filp, dev, vertex.prim, vertex.buf, vertex.used, vertex.discard); } int mach64_dma_blit(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_blit_t blit; int ret; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(blit, (drm_mach64_blit_t *) data, sizeof(blit)); DRM_DEBUG("%s: pid=%d index=%d\n", __FUNCTION__, DRM_CURRENTPID, blit.idx); if (blit.idx < 0 || blit.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", blit.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } ret = mach64_dma_dispatch_blit(filp, dev, &blit); /* Make sure we restore the 3D state next time. */ sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC | MACH64_UPLOAD_CLIPRECTS); return ret; } int mach64_get_param(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_getparam_t param; int value; DRM_DEBUG("%s\n", __FUNCTION__); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(param, (drm_mach64_getparam_t *) data, sizeof(param)); switch (param.param) { case MACH64_PARAM_FRAMES_QUEUED: /* Needs lock since it calls mach64_ring_tick() */ LOCK_TEST_WITH_RETURN(dev, filp); value = mach64_do_get_frames_queued(dev_priv); break; case MACH64_PARAM_IRQ_NR: value = dev->irq; break; default: return DRM_ERR(EINVAL); } if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; } Index: head/sys/dev/drm/mga_dma.c =================================================================== --- head/sys/dev/drm/mga_dma.c (revision 152908) +++ head/sys/dev/drm/mga_dma.c (revision 152909) @@ -1,747 +1,1185 @@ /* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*- - * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com */ -/*- - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com + */ +/* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Rickard E. (Rik) Faith - * Jeff Hartmann - * Keith Whitwell - * - * Rewritten by: - * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + +/** + * \file mga_dma.c + * DMA support for MGA G200 / G400. + * + * \author Rickard E. (Rik) Faith + * \author Jeff Hartmann + * \author Keith Whitwell + * \author Gareth Hughes + */ + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" +#include "dev/drm/drm_sarea.h" #include "dev/drm/mga_drm.h" #include "dev/drm/mga_drv.h" #define MGA_DEFAULT_USEC_TIMEOUT 10000 #define MGA_FREELIST_DEBUG 0 -static int mga_do_cleanup_dma(drm_device_t * dev); +#define MINIMAL_CLEANUP 0 +#define FULL_CLEANUP 1 +static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup); /* ================================================================ * Engine control */ int mga_do_wait_for_idle(drm_mga_private_t * dev_priv) { u32 status = 0; int i; DRM_DEBUG("\n"); for (i = 0; i < dev_priv->usec_timeout; i++) { status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; if (status == MGA_ENDPRDMASTS) { MGA_WRITE8(MGA_CRTC_INDEX, 0); return 0; } DRM_UDELAY(1); } #if MGA_DMA_DEBUG DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x\n", status); #endif return DRM_ERR(EBUSY); } static int mga_do_dma_reset(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_primary_buffer_t *primary = &dev_priv->prim; DRM_DEBUG("\n"); /* The primary DMA stream should look like new right about now. */ primary->tail = 0; primary->space = primary->size; primary->last_flush = 0; sarea_priv->last_wrap = 0; /* FIXME: Reset counters, buffer ages etc... */ /* FIXME: What else do we need to reinitialize? WARP stuff? */ return 0; } /* ================================================================ * Primary DMA stream */ void mga_do_dma_flush(drm_mga_private_t * dev_priv) { drm_mga_primary_buffer_t *primary = &dev_priv->prim; u32 head, tail; u32 status = 0; int i; DMA_LOCALS; DRM_DEBUG("\n"); /* We need to wait so that we can do an safe flush */ for (i = 0; i < dev_priv->usec_timeout; i++) { status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; if (status == MGA_ENDPRDMASTS) break; DRM_UDELAY(1); } if (primary->tail == primary->last_flush) { DRM_DEBUG(" bailing out...\n"); return; } tail = primary->tail + dev_priv->primary->offset; /* We need to pad the stream between flushes, as the card * actually (partially?) reads the first of these commands. * See page 4-16 in the G400 manual, middle of the page or so. */ BEGIN_DMA(1); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); ADVANCE_DMA(); primary->last_flush = primary->tail; head = MGA_READ(MGA_PRIMADDRESS); if (head <= tail) { primary->space = primary->size - primary->tail; } else { primary->space = head - tail; } DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset); DRM_DEBUG(" tail = 0x%06lx\n", tail - dev_priv->primary->offset); DRM_DEBUG(" space = 0x%06x\n", primary->space); mga_flush_write_combine(); - MGA_WRITE(MGA_PRIMEND, tail | MGA_PAGPXFER); + MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access); DRM_DEBUG("done.\n"); } void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv) { drm_mga_primary_buffer_t *primary = &dev_priv->prim; u32 head, tail; DMA_LOCALS; DRM_DEBUG("\n"); BEGIN_DMA_WRAP(); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); ADVANCE_DMA(); tail = primary->tail + dev_priv->primary->offset; primary->tail = 0; primary->last_flush = 0; primary->last_wrap++; head = MGA_READ(MGA_PRIMADDRESS); if (head == dev_priv->primary->offset) { primary->space = primary->size; } else { primary->space = head - dev_priv->primary->offset; } DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset); DRM_DEBUG(" tail = 0x%06x\n", primary->tail); DRM_DEBUG(" wrap = %d\n", primary->last_wrap); DRM_DEBUG(" space = 0x%06x\n", primary->space); mga_flush_write_combine(); - MGA_WRITE(MGA_PRIMEND, tail | MGA_PAGPXFER); + MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access); set_bit(0, &primary->wrapped); DRM_DEBUG("done.\n"); } void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv) { drm_mga_primary_buffer_t *primary = &dev_priv->prim; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; u32 head = dev_priv->primary->offset; DRM_DEBUG("\n"); sarea_priv->last_wrap++; DRM_DEBUG(" wrap = %d\n", sarea_priv->last_wrap); mga_flush_write_combine(); MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL); clear_bit(0, &primary->wrapped); DRM_DEBUG("done.\n"); } /* ================================================================ * Freelist management */ #define MGA_BUFFER_USED ~0 #define MGA_BUFFER_FREE 0 #if MGA_FREELIST_DEBUG static void mga_freelist_print(drm_device_t * dev) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_freelist_t *entry; DRM_INFO("\n"); DRM_INFO("current dispatch: last=0x%x done=0x%x\n", dev_priv->sarea_priv->last_dispatch, (unsigned int)(MGA_READ(MGA_PRIMADDRESS) - dev_priv->primary->offset)); DRM_INFO("current freelist:\n"); for (entry = dev_priv->head->next; entry; entry = entry->next) { DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n", entry, entry->buf->idx, entry->age.head, entry->age.head - dev_priv->primary->offset); } DRM_INFO("\n"); } #endif static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv) { drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_freelist_t *entry; int i; DRM_DEBUG("count=%d\n", dma->buf_count); dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); if (dev_priv->head == NULL) return DRM_ERR(ENOMEM); memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t)); SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0); for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); if (entry == NULL) return DRM_ERR(ENOMEM); memset(entry, 0, sizeof(drm_mga_freelist_t)); entry->next = dev_priv->head->next; entry->prev = dev_priv->head; SET_AGE(&entry->age, MGA_BUFFER_FREE, 0); entry->buf = buf; if (dev_priv->head->next != NULL) dev_priv->head->next->prev = entry; if (entry->next == NULL) dev_priv->tail = entry; buf_priv->list_entry = entry; buf_priv->discard = 0; buf_priv->dispatched = 0; dev_priv->head->next = entry; } return 0; } static void mga_freelist_cleanup(drm_device_t * dev) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_freelist_t *entry; drm_mga_freelist_t *next; DRM_DEBUG("\n"); entry = dev_priv->head; while (entry) { next = entry->next; drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); entry = next; } dev_priv->head = dev_priv->tail = NULL; } #if 0 /* FIXME: Still needed? */ static void mga_freelist_reset(drm_device_t * dev) { drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; int i; for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0); } } #endif static drm_buf_t *mga_freelist_get(drm_device_t * dev) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_freelist_t *next; drm_mga_freelist_t *prev; drm_mga_freelist_t *tail = dev_priv->tail; u32 head, wrap; DRM_DEBUG("\n"); head = MGA_READ(MGA_PRIMADDRESS); wrap = dev_priv->sarea_priv->last_wrap; DRM_DEBUG(" tail=0x%06lx %d\n", tail->age.head ? tail->age.head - dev_priv->primary->offset : 0, tail->age.wrap); DRM_DEBUG(" head=0x%06lx %d\n", head - dev_priv->primary->offset, wrap); if (TEST_AGE(&tail->age, head, wrap)) { prev = dev_priv->tail->prev; next = dev_priv->tail; prev->next = NULL; next->prev = next->next = NULL; dev_priv->tail = prev; SET_AGE(&next->age, MGA_BUFFER_USED, 0); return next->buf; } DRM_DEBUG("returning NULL!\n"); return NULL; } int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; drm_mga_freelist_t *head, *entry, *prev; DRM_DEBUG("age=0x%06lx wrap=%d\n", buf_priv->list_entry->age.head - dev_priv->primary->offset, buf_priv->list_entry->age.wrap); entry = buf_priv->list_entry; head = dev_priv->head; if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) { SET_AGE(&entry->age, MGA_BUFFER_FREE, 0); prev = dev_priv->tail; prev->next = entry; entry->prev = prev; entry->next = NULL; } else { prev = head->next; head->next = entry; prev->prev = entry; entry->prev = head; entry->next = prev; } return 0; } /* ================================================================ * DMA initialization, cleanup */ -static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) +int mga_driver_load(drm_device_t *dev, unsigned long flags) { - drm_mga_private_t *dev_priv; - int ret; - DRM_DEBUG("\n"); + drm_mga_private_t * dev_priv; dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); if (!dev_priv) return DRM_ERR(ENOMEM); + dev->dev_private = (void *)dev_priv; memset(dev_priv, 0, sizeof(drm_mga_private_t)); - dev_priv->chipset = init->chipset; - dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; + dev_priv->chipset = flags; + dev_priv->mmio_base = drm_get_resource_start(dev, 1); + dev_priv->mmio_size = drm_get_resource_len(dev, 1); + + dev->counters += 3; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + + return 0; +} + +/** + * Bootstrap the driver for AGP DMA. + * + * \todo + * Investigate whether there is any benifit to storing the WARP microcode in + * AGP memory. If not, the microcode may as well always be put in PCI + * memory. + * + * \todo + * This routine needs to set dma_bs->agp_mode to the mode actually configured + * in the hardware. Looking just at the Linux AGP driver code, I don't see + * an easy way to determine this. + * + * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap + */ +static int mga_do_agp_dma_bootstrap(drm_device_t * dev, + drm_mga_dma_bootstrap_t * dma_bs) +{ + drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private; + unsigned int warp_size = mga_warp_microcode_size(dev_priv); + int err; + unsigned offset; + const unsigned secondary_size = dma_bs->secondary_bin_count + * dma_bs->secondary_bin_size; + const unsigned agp_size = (dma_bs->agp_size << 20); + drm_buf_desc_t req; + drm_agp_mode_t mode; + drm_agp_info_t info; + drm_agp_buffer_t agp_req; + drm_agp_binding_t bind_req; + + /* Acquire AGP. */ + err = drm_agp_acquire(dev); + if (err) { + DRM_ERROR("Unable to acquire AGP: %d\n", err); + return err; + } + + err = drm_agp_info(dev, &info); + if (err) { + DRM_ERROR("Unable to get AGP info: %d\n", err); + return err; + } + + mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode; + err = drm_agp_enable(dev, mode); + if (err) { + DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); + return err; + } + + /* In addition to the usual AGP mode configuration, the G200 AGP cards + * need to have the AGP mode "manually" set. + */ + + if (dev_priv->chipset == MGA_CARD_TYPE_G200) { + if (mode.mode & 0x02) { + MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE); + } else { + MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE); + } + } + + + /* Allocate and bind AGP memory. */ + agp_req.size = agp_size; + agp_req.type = 0; + err = drm_agp_alloc( dev, & agp_req ); + if (err) { + dev_priv->agp_size = 0; + DRM_ERROR("Unable to allocate %uMB AGP memory\n", + dma_bs->agp_size); + return err; + } + + dev_priv->agp_size = agp_size; + dev_priv->agp_handle = agp_req.handle; + + bind_req.handle = agp_req.handle; + bind_req.offset = 0; + err = drm_agp_bind( dev, &bind_req ); + if (err) { + DRM_ERROR("Unable to bind AGP memory: %d\n", err); + return err; + } + + /* Make drm_addbufs happy by not trying to create a mapping for less + * than a page. + */ + if (warp_size < PAGE_SIZE) + warp_size = PAGE_SIZE; + + offset = 0; + err = drm_addmap( dev, offset, warp_size, + _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp ); + if (err) { + DRM_ERROR("Unable to map WARP microcode: %d\n", err); + return err; + } + + offset += warp_size; + err = drm_addmap( dev, offset, dma_bs->primary_size, + _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary ); + if (err) { + DRM_ERROR("Unable to map primary DMA region: %d\n", err); + return err; + } + + offset += dma_bs->primary_size; + err = drm_addmap( dev, offset, secondary_size, + _DRM_AGP, 0, & dev->agp_buffer_map ); + if (err) { + DRM_ERROR("Unable to map secondary DMA region: %d\n", err); + return err; + } + + (void) memset( &req, 0, sizeof(req) ); + req.count = dma_bs->secondary_bin_count; + req.size = dma_bs->secondary_bin_size; + req.flags = _DRM_AGP_BUFFER; + req.agp_start = offset; + + err = drm_addbufs_agp( dev, & req ); + if (err) { + DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); + return err; + } + +#ifdef __linux__ + { + drm_map_list_t *_entry; + unsigned long agp_token = 0; + + list_for_each_entry(_entry, &dev->maplist->head, head) { + if (_entry->map == dev->agp_buffer_map) + agp_token = _entry->user_token; + } + if (!agp_token) + return -EFAULT; + + dev->agp_buffer_token = agp_token; + } +#endif + + offset += secondary_size; + err = drm_addmap( dev, offset, agp_size - offset, + _DRM_AGP, 0, & dev_priv->agp_textures ); + if (err) { + DRM_ERROR("Unable to map AGP texture region: %d\n", err); + return err; + } + + drm_core_ioremap(dev_priv->warp, dev); + drm_core_ioremap(dev_priv->primary, dev); + drm_core_ioremap(dev->agp_buffer_map, dev); + + if (!dev_priv->warp->handle || + !dev_priv->primary->handle || !dev->agp_buffer_map->handle) { + DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n", + dev_priv->warp->handle, dev_priv->primary->handle, + dev->agp_buffer_map->handle); + return DRM_ERR(ENOMEM); + } + + dev_priv->dma_access = MGA_PAGPXFER; + dev_priv->wagp_enable = MGA_WAGP_ENABLE; + + DRM_INFO("Initialized card for AGP DMA.\n"); + return 0; +} + +/** + * Bootstrap the driver for PCI DMA. + * + * \todo + * The algorithm for decreasing the size of the primary DMA buffer could be + * better. The size should be rounded up to the nearest page size, then + * decrease the request size by a single page each pass through the loop. + * + * \todo + * Determine whether the maximum address passed to drm_pci_alloc is correct. + * The same goes for drm_addbufs_pci. + * + * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap + */ +static int mga_do_pci_dma_bootstrap(drm_device_t * dev, + drm_mga_dma_bootstrap_t * dma_bs) +{ + drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private; + unsigned int warp_size = mga_warp_microcode_size(dev_priv); + unsigned int primary_size; + unsigned int bin_count; + int err; + drm_buf_desc_t req; + + + if (dev->dma == NULL) { + DRM_ERROR("dev->dma is NULL\n"); + return DRM_ERR(EFAULT); + } + + /* Make drm_addbufs happy by not trying to create a mapping for less + * than a page. + */ + if (warp_size < PAGE_SIZE) + warp_size = PAGE_SIZE; + + /* The proper alignment is 0x100 for this mapping */ + err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT, + _DRM_READ_ONLY, &dev_priv->warp); + if (err != 0) { + DRM_ERROR("Unable to create mapping for WARP microcode: %d\n", + err); + return err; + } + + /* Other than the bottom two bits being used to encode other + * information, there don't appear to be any restrictions on the + * alignment of the primary or secondary DMA buffers. + */ + + for ( primary_size = dma_bs->primary_size + ; primary_size != 0 + ; primary_size >>= 1 ) { + /* The proper alignment for this mapping is 0x04 */ + err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT, + _DRM_READ_ONLY, &dev_priv->primary); + if (!err) + break; + } + + if (err != 0) { + DRM_ERROR("Unable to allocate primary DMA region: %d\n", err); + return DRM_ERR(ENOMEM); + } + + if (dev_priv->primary->size != dma_bs->primary_size) { + DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n", + dma_bs->primary_size, + (unsigned) dev_priv->primary->size); + dma_bs->primary_size = dev_priv->primary->size; + } + + for ( bin_count = dma_bs->secondary_bin_count + ; bin_count > 0 + ; bin_count-- ) { + (void) memset( &req, 0, sizeof(req) ); + req.count = bin_count; + req.size = dma_bs->secondary_bin_size; + + err = drm_addbufs_pci( dev, & req ); + if (!err) { + break; + } + } + + if (bin_count == 0) { + DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); + return err; + } + + if (bin_count != dma_bs->secondary_bin_count) { + DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u " + "to %u.\n", dma_bs->secondary_bin_count, bin_count); + + dma_bs->secondary_bin_count = bin_count; + } + + dev_priv->dma_access = 0; + dev_priv->wagp_enable = 0; + + dma_bs->agp_mode = 0; + + DRM_INFO("Initialized card for PCI DMA.\n"); + return 0; +} + + +static int mga_do_dma_bootstrap(drm_device_t * dev, + drm_mga_dma_bootstrap_t * dma_bs) +{ + const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev); + int err; + drm_mga_private_t * const dev_priv = + (drm_mga_private_t *) dev->dev_private; + + + dev_priv->used_new_dma_init = 1; + + /* The first steps are the same for both PCI and AGP based DMA. Map + * the cards MMIO registers and map a status page. + */ + err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size, + _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio ); + if (err) { + DRM_ERROR("Unable to map MMIO region: %d\n", err); + return err; + } + + + err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM, + _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL, + & dev_priv->status ); + if (err) { + DRM_ERROR("Unable to map status region: %d\n", err); + return err; + } + + + /* The DMA initialization procedure is slightly different for PCI and + * AGP cards. AGP cards just allocate a large block of AGP memory and + * carve off portions of it for internal uses. The remaining memory + * is returned to user-mode to be used for AGP textures. + */ + + if (is_agp) { + err = mga_do_agp_dma_bootstrap(dev, dma_bs); + } + + /* If we attempted to initialize the card for AGP DMA but failed, + * clean-up any mess that may have been created. + */ + + if (err) { + mga_do_cleanup_dma(dev, MINIMAL_CLEANUP); + } + + + /* Not only do we want to try and initialized PCI cards for PCI DMA, + * but we also try to initialized AGP cards that could not be + * initialized for AGP DMA. This covers the case where we have an AGP + * card in a system with an unsupported AGP chipset. In that case the + * card will be detected as AGP, but we won't be able to allocate any + * AGP memory, etc. + */ + + if (!is_agp || err) { + err = mga_do_pci_dma_bootstrap(dev, dma_bs); + } + + + return err; +} + +int mga_dma_bootstrap(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_mga_dma_bootstrap_t bootstrap; + int err; + static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 }; + const drm_mga_private_t * const dev_priv = + (drm_mga_private_t *) dev->dev_private; + + + DRM_COPY_FROM_USER_IOCTL(bootstrap, + (drm_mga_dma_bootstrap_t __user *) data, + sizeof(bootstrap)); + + err = mga_do_dma_bootstrap(dev, & bootstrap); + if (err) { + mga_do_cleanup_dma(dev, FULL_CLEANUP); + return err; + } + + if (dev_priv->agp_textures != NULL) { + bootstrap.texture_handle = dev_priv->agp_textures->offset; + bootstrap.texture_size = dev_priv->agp_textures->size; + } else { + bootstrap.texture_handle = 0; + bootstrap.texture_size = 0; + } + + bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07]; + + DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data, + bootstrap, sizeof(bootstrap)); + + return 0; +} + + +static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) +{ + drm_mga_private_t *dev_priv; + int ret; + DRM_DEBUG("\n"); + + + dev_priv = dev->dev_private; + if (init->sgram) { dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; } else { dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; } dev_priv->maccess = init->maccess; dev_priv->fb_cpp = init->fb_cpp; dev_priv->front_offset = init->front_offset; dev_priv->front_pitch = init->front_pitch; dev_priv->back_offset = init->back_offset; dev_priv->back_pitch = init->back_pitch; dev_priv->depth_cpp = init->depth_cpp; dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; /* FIXME: Need to support AGP textures... */ dev_priv->texture_offset = init->texture_offset[0]; dev_priv->texture_size = init->texture_size[0]; DRM_GETSAREA(); if (!dev_priv->sarea) { DRM_ERROR("failed to find sarea!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } - dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); - if (!dev_priv->mmio) { - DRM_ERROR("failed to find mmio region!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); - return DRM_ERR(EINVAL); + if (! dev_priv->used_new_dma_init) { + + dev_priv->dma_access = MGA_PAGPXFER; + dev_priv->wagp_enable = MGA_WAGP_ENABLE; + + dev_priv->status = drm_core_findmap(dev, init->status_offset); + if (!dev_priv->status) { + DRM_ERROR("failed to find status page!\n"); + return DRM_ERR(EINVAL); + } + dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); + if (!dev_priv->mmio) { + DRM_ERROR("failed to find mmio region!\n"); + return DRM_ERR(EINVAL); + } + dev_priv->warp = drm_core_findmap(dev, init->warp_offset); + if (!dev_priv->warp) { + DRM_ERROR("failed to find warp microcode region!\n"); + return DRM_ERR(EINVAL); + } + dev_priv->primary = drm_core_findmap(dev, init->primary_offset); + if (!dev_priv->primary) { + DRM_ERROR("failed to find primary dma region!\n"); + return DRM_ERR(EINVAL); + } + dev->agp_buffer_token = init->buffers_offset; + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if (!dev->agp_buffer_map) { + DRM_ERROR("failed to find dma buffer region!\n"); + return DRM_ERR(EINVAL); + } + + drm_core_ioremap(dev_priv->warp, dev); + drm_core_ioremap(dev_priv->primary, dev); + drm_core_ioremap(dev->agp_buffer_map, dev); } - dev_priv->status = drm_core_findmap(dev, init->status_offset); - if (!dev_priv->status) { - DRM_ERROR("failed to find status page!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); - return DRM_ERR(EINVAL); - } - dev_priv->warp = drm_core_findmap(dev, init->warp_offset); - if (!dev_priv->warp) { - DRM_ERROR("failed to find warp microcode region!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); - return DRM_ERR(EINVAL); - } - dev_priv->primary = drm_core_findmap(dev, init->primary_offset); - if (!dev_priv->primary) { - DRM_ERROR("failed to find primary dma region!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); - return DRM_ERR(EINVAL); - } - dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); - if (!dev->agp_buffer_map) { - DRM_ERROR("failed to find dma buffer region!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); - return DRM_ERR(EINVAL); - } dev_priv->sarea_priv = (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); - drm_core_ioremap(dev_priv->warp, dev); - drm_core_ioremap(dev_priv->primary, dev); - drm_core_ioremap(dev->agp_buffer_map, dev); - if (!dev_priv->warp->handle || - !dev_priv->primary->handle || !dev->agp_buffer_map->handle) { + !dev_priv->primary->handle || + ((dev_priv->dma_access != 0) && + ((dev->agp_buffer_map == NULL) || + (dev->agp_buffer_map->handle == NULL)))) { DRM_ERROR("failed to ioremap agp regions!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); return DRM_ERR(ENOMEM); } ret = mga_warp_install_microcode(dev_priv); - if (ret < 0) { - DRM_ERROR("failed to install WARP ucode!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); + if (ret != 0) { + DRM_ERROR("failed to install WARP ucode: %d!\n", ret); return ret; } ret = mga_warp_init(dev_priv); - if (ret < 0) { - DRM_ERROR("failed to init WARP engine!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); + if (ret != 0) { + DRM_ERROR("failed to init WARP engine: %d!\n", ret); return ret; } dev_priv->prim.status = (u32 *) dev_priv->status->handle; mga_do_wait_for_idle(dev_priv); /* Init the primary DMA registers. */ MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL); #if 0 MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */ MGA_PRIMPTREN1); /* DWGSYNC */ #endif dev_priv->prim.start = (u8 *) dev_priv->primary->handle; dev_priv->prim.end = ((u8 *) dev_priv->primary->handle + dev_priv->primary->size); dev_priv->prim.size = dev_priv->primary->size; dev_priv->prim.tail = 0; dev_priv->prim.space = dev_priv->prim.size; dev_priv->prim.wrapped = 0; dev_priv->prim.last_flush = 0; dev_priv->prim.last_wrap = 0; dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE; dev_priv->prim.status[0] = dev_priv->primary->offset; dev_priv->prim.status[1] = 0; dev_priv->sarea_priv->last_wrap = 0; dev_priv->sarea_priv->last_frame.head = 0; dev_priv->sarea_priv->last_frame.wrap = 0; if (mga_freelist_init(dev, dev_priv) < 0) { DRM_ERROR("could not initialize freelist\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; - mga_do_cleanup_dma(dev); return DRM_ERR(ENOMEM); } - /* Make dev_private visable to others. */ - dev->dev_private = (void *)dev_priv; return 0; } -static int mga_do_cleanup_dma(drm_device_t * dev) +static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup) { + int err = 0; DRM_DEBUG("\n"); /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if (dev->irq_enabled) drm_irq_uninstall(dev); if (dev->dev_private) { drm_mga_private_t *dev_priv = dev->dev_private; - if (dev_priv->warp != NULL) + if ((dev_priv->warp != NULL) + && (dev_priv->warp->type != _DRM_CONSISTENT)) drm_core_ioremapfree(dev_priv->warp, dev); - if (dev_priv->primary != NULL) + + if ((dev_priv->primary != NULL) + && (dev_priv->primary->type != _DRM_CONSISTENT)) drm_core_ioremapfree(dev_priv->primary, dev); - if (dev->agp_buffer_map != NULL) { + + if (dev->agp_buffer_map != NULL) drm_core_ioremapfree(dev->agp_buffer_map, dev); - dev->agp_buffer_map = NULL; + + if (dev_priv->used_new_dma_init) { + if (dev_priv->agp_handle != 0) { + drm_agp_binding_t unbind_req; + drm_agp_buffer_t free_req; + + unbind_req.handle = dev_priv->agp_handle; + drm_agp_unbind(dev, &unbind_req); + + free_req.handle = dev_priv->agp_handle; + drm_agp_free(dev, &free_req); + + dev_priv->agp_textures = NULL; + dev_priv->agp_size = 0; + dev_priv->agp_handle = 0; + } + + if ((dev->agp != NULL) && dev->agp->acquired) { + err = drm_agp_release(dev); + } } + dev_priv->warp = NULL; + dev_priv->primary = NULL; + dev_priv->sarea = NULL; + dev_priv->sarea_priv = NULL; + dev->agp_buffer_map = NULL; + + if (full_cleanup) { + dev_priv->mmio = NULL; + dev_priv->status = NULL; + dev_priv->used_new_dma_init = 0; + } + + memset(&dev_priv->prim, 0, sizeof(dev_priv->prim)); + dev_priv->warp_pipe = 0; + memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); + if (dev_priv->head != NULL) { mga_freelist_cleanup(dev); } - - drm_free(dev->dev_private, sizeof(drm_mga_private_t), - DRM_MEM_DRIVER); - dev->dev_private = NULL; } return 0; } int mga_dma_init(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_init_t init; + int err; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data, sizeof(init)); switch (init.func) { case MGA_INIT_DMA: - return mga_do_init_dma(dev, &init); + err = mga_do_init_dma(dev, &init); + if (err) { + (void) mga_do_cleanup_dma(dev, FULL_CLEANUP); + } + return err; case MGA_CLEANUP_DMA: - return mga_do_cleanup_dma(dev); + return mga_do_cleanup_dma(dev, FULL_CLEANUP); } return DRM_ERR(EINVAL); } /* ================================================================ * Primary DMA stream management */ int mga_dma_flush(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; drm_lock_t lock; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data, sizeof(lock)); DRM_DEBUG("%s%s%s\n", (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "", (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "", (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : ""); WRAP_WAIT_WITH_RETURN(dev_priv); if (lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) { mga_do_dma_flush(dev_priv); } if (lock.flags & _DRM_LOCK_QUIESCENT) { #if MGA_DMA_DEBUG int ret = mga_do_wait_for_idle(dev_priv); if (ret < 0) DRM_INFO("%s: -EBUSY\n", __FUNCTION__); return ret; #else return mga_do_wait_for_idle(dev_priv); #endif } else { return 0; } } int mga_dma_reset(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; LOCK_TEST_WITH_RETURN(dev, filp); return mga_do_dma_reset(dev_priv); } /* ================================================================ * DMA buffer management */ static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d) { drm_buf_t *buf; int i; for (i = d->granted_count; i < d->request_count; i++) { buf = mga_freelist_get(dev); if (!buf) return DRM_ERR(EAGAIN); buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return DRM_ERR(EFAULT); d->granted_count++; } return 0; } int mga_dma_buffers(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; drm_dma_t __user *argp = (void __user *)data; drm_dma_t d; int ret = 0; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); /* Please don't send us buffers. */ if (d.send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", DRM_CURRENTPID, d.send_count); return DRM_ERR(EINVAL); } /* We'll send you buffers. */ if (d.request_count < 0 || d.request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", DRM_CURRENTPID, d.request_count, dma->buf_count); return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN(dev_priv); d.granted_count = 0; if (d.request_count) { ret = mga_dma_get_buffers(filp, dev, &d); } DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); return ret; } -void mga_driver_pretakedown(drm_device_t * dev) +/** + * Called just before the module is unloaded. + */ +int mga_driver_unload(drm_device_t * dev) { - mga_do_cleanup_dma(dev); + drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER); + dev->dev_private = NULL; + + return 0; +} + +/** + * Called when the last opener of the device is closed. + */ +void mga_driver_lastclose(drm_device_t * dev) +{ + mga_do_cleanup_dma(dev, FULL_CLEANUP); } int mga_driver_dma_quiescent(drm_device_t * dev) { drm_mga_private_t *dev_priv = dev->dev_private; return mga_do_wait_for_idle(dev_priv); } Index: head/sys/dev/drm/mga_drm.h =================================================================== --- head/sys/dev/drm/mga_drm.h (revision 152908) +++ head/sys/dev/drm/mga_drm.h (revision 152909) @@ -1,348 +1,428 @@ /* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*- - * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com */ -/*- + * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com + * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Jeff Hartmann * Keith Whitwell * * Rewritten by: * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef __MGA_DRM_H__ #define __MGA_DRM_H__ /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (mga_sarea.h) */ #ifndef __MGA_SAREA_DEFINES__ #define __MGA_SAREA_DEFINES__ /* WARP pipe flags */ #define MGA_F 0x1 /* fog */ #define MGA_A 0x2 /* alpha */ #define MGA_S 0x4 /* specular */ #define MGA_T2 0x8 /* multitexture */ #define MGA_WARP_TGZ 0 #define MGA_WARP_TGZF (MGA_F) #define MGA_WARP_TGZA (MGA_A) #define MGA_WARP_TGZAF (MGA_F|MGA_A) #define MGA_WARP_TGZS (MGA_S) #define MGA_WARP_TGZSF (MGA_S|MGA_F) #define MGA_WARP_TGZSA (MGA_S|MGA_A) #define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) #define MGA_WARP_T2GZ (MGA_T2) #define MGA_WARP_T2GZF (MGA_T2|MGA_F) #define MGA_WARP_T2GZA (MGA_T2|MGA_A) #define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) #define MGA_WARP_T2GZS (MGA_T2|MGA_S) #define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) #define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) #define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) #define MGA_MAX_G200_PIPES 8 /* no multitex */ #define MGA_MAX_G400_PIPES 16 #define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES #define MGA_WARP_UCODE_SIZE 32768 /* in bytes */ #define MGA_CARD_TYPE_G200 1 #define MGA_CARD_TYPE_G400 2 +#define MGA_CARD_TYPE_G450 3 /* not currently used */ +#define MGA_CARD_TYPE_G550 4 #define MGA_FRONT 0x1 #define MGA_BACK 0x2 #define MGA_DEPTH 0x4 /* What needs to be changed for the current vertex dma buffer? */ #define MGA_UPLOAD_CONTEXT 0x1 #define MGA_UPLOAD_TEX0 0x2 #define MGA_UPLOAD_TEX1 0x4 #define MGA_UPLOAD_PIPE 0x8 #define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ #define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ #define MGA_UPLOAD_2D 0x40 #define MGA_WAIT_AGE 0x80 /* handled client-side */ #define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ #if 0 #define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock quiescent */ #endif /* 32 buffers of 64k each, total 2 meg. */ #define MGA_BUFFER_SIZE (1 << 16) #define MGA_NUM_BUFFERS 128 /* Keep these small for testing. */ #define MGA_NR_SAREA_CLIPRECTS 8 /* 2 heaps (1 for card, 1 for agp), each divided into upto 128 * regions, subject to a minimum region size of (1<<16) == 64k. * * Clients may subdivide regions internally, but when sharing between * clients, the region size is the minimum granularity. */ #define MGA_CARD_HEAP 0 #define MGA_AGP_HEAP 1 #define MGA_NR_TEX_HEAPS 2 #define MGA_NR_TEX_REGIONS 16 #define MGA_LOG_MIN_TEX_REGION_SIZE 16 #define DRM_MGA_IDLE_RETRY 2048 #endif /* __MGA_SAREA_DEFINES__ */ /* Setup registers for 3D context */ typedef struct { unsigned int dstorg; unsigned int maccess; unsigned int plnwt; unsigned int dwgctl; unsigned int alphactrl; unsigned int fogcolor; unsigned int wflag; unsigned int tdualstage0; unsigned int tdualstage1; unsigned int fcol; unsigned int stencil; unsigned int stencilctl; } drm_mga_context_regs_t; /* Setup registers for 2D, X server */ typedef struct { unsigned int pitch; } drm_mga_server_regs_t; /* Setup registers for each texture unit */ typedef struct { unsigned int texctl; unsigned int texctl2; unsigned int texfilter; unsigned int texbordercol; unsigned int texorg; unsigned int texwidth; unsigned int texheight; unsigned int texorg1; unsigned int texorg2; unsigned int texorg3; unsigned int texorg4; } drm_mga_texture_regs_t; /* General aging mechanism */ typedef struct { unsigned int head; /* Position of head pointer */ unsigned int wrap; /* Primary DMA wrap count */ } drm_mga_age_t; typedef struct _drm_mga_sarea { /* The channel for communication of state information to the kernel * on firing a vertex dma buffer. */ drm_mga_context_regs_t context_state; drm_mga_server_regs_t server_state; drm_mga_texture_regs_t tex_state[2]; unsigned int warp_pipe; unsigned int dirty; unsigned int vertsize; /* The current cliprects, or a subset thereof. */ drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS]; unsigned int nbox; /* Information about the most recently used 3d drawable. The * client fills in the req_* fields, the server fills in the * exported_ fields and puts the cliprects into boxes, above. * * The client clears the exported_drawable field before * clobbering the boxes data. */ unsigned int req_drawable; /* the X drawable id */ unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ unsigned int exported_drawable; unsigned int exported_index; unsigned int exported_stamp; unsigned int exported_buffers; unsigned int exported_nfront; unsigned int exported_nback; int exported_back_x, exported_front_x, exported_w; int exported_back_y, exported_front_y, exported_h; drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS]; /* Counters for aging textures and for client-side throttling. */ unsigned int status[4]; unsigned int last_wrap; drm_mga_age_t last_frame; unsigned int last_enqueue; /* last time a buffer was enqueued */ unsigned int last_dispatch; /* age of the most recently dispatched buffer */ unsigned int last_quiescent; /* */ /* LRU lists for texture memory in agp space and on the card. */ drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1]; unsigned int texAge[MGA_NR_TEX_HEAPS]; /* Mechanism to validate card state. */ int ctxOwner; } drm_mga_sarea_t; -/* WARNING: If you change any of these defines, make sure to change the - * defines in the Xserver file (xf86drmMga.h) - */ /* MGA specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ #define DRM_MGA_INIT 0x00 #define DRM_MGA_FLUSH 0x01 #define DRM_MGA_RESET 0x02 #define DRM_MGA_SWAP 0x03 #define DRM_MGA_CLEAR 0x04 #define DRM_MGA_VERTEX 0x05 #define DRM_MGA_INDICES 0x06 #define DRM_MGA_ILOAD 0x07 #define DRM_MGA_BLIT 0x08 #define DRM_MGA_GETPARAM 0x09 +/* 3.2: + * ioctls for operating on fences. + */ +#define DRM_MGA_SET_FENCE 0x0a +#define DRM_MGA_WAIT_FENCE 0x0b +#define DRM_MGA_DMA_BOOTSTRAP 0x0c + + #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) #define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t) #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) #define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) #define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) #define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t) #define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t) #define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) #define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) #define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) +#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t) +#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t) +#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) typedef struct _drm_mga_warp_index { int installed; unsigned long phys_addr; int size; } drm_mga_warp_index_t; typedef struct drm_mga_init { enum { MGA_INIT_DMA = 0x01, MGA_CLEANUP_DMA = 0x02 } func; unsigned long sarea_priv_offset; int chipset; int sgram; unsigned int maccess; unsigned int fb_cpp; unsigned int front_offset, front_pitch; unsigned int back_offset, back_pitch; unsigned int depth_cpp; unsigned int depth_offset, depth_pitch; unsigned int texture_offset[MGA_NR_TEX_HEAPS]; unsigned int texture_size[MGA_NR_TEX_HEAPS]; unsigned long fb_offset; unsigned long mmio_offset; unsigned long status_offset; unsigned long warp_offset; unsigned long primary_offset; unsigned long buffers_offset; } drm_mga_init_t; -typedef struct drm_mga_fullscreen { - enum { - MGA_INIT_FULLSCREEN = 0x01, - MGA_CLEANUP_FULLSCREEN = 0x02 - } func; -} drm_mga_fullscreen_t; +typedef struct drm_mga_dma_bootstrap { + /** + * \name AGP texture region + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will + * be filled in with the actual AGP texture settings. + * + * \warning + * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode + * is zero, it means that PCI memory (most likely through the use of + * an IOMMU) is being used for "AGP" textures. + */ + /*@{*/ + unsigned long texture_handle; /**< Handle used to map AGP textures. */ + uint32_t texture_size; /**< Size of the AGP texture region. */ + /*@}*/ + + + /** + * Requested size of the primary DMA region. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual AGP mode. If AGP was not available + */ + uint32_t primary_size; + + + /** + * Requested number of secondary DMA buffers. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual number of secondary DMA buffers + * allocated. Particularly when PCI DMA is used, this may be + * (subtantially) less than the number requested. + */ + uint32_t secondary_bin_count; + + + /** + * Requested size of each secondary DMA buffer. + * + * While the kernel \b is free to reduce + * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed + * to reduce dma_mga_dma_bootstrap::secondary_bin_size. + */ + uint32_t secondary_bin_size; + + + /** + * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, + * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is + * zero, it means that PCI DMA should be used, even if AGP is + * possible. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual AGP mode. If AGP was not available + * (i.e., PCI DMA was used), this value will be zero. + */ + uint32_t agp_mode; + + + /** + * Desired AGP GART size, measured in megabytes. + */ + uint8_t agp_size; +} drm_mga_dma_bootstrap_t; + typedef struct drm_mga_clear { unsigned int flags; unsigned int clear_color; unsigned int clear_depth; unsigned int color_mask; unsigned int depth_mask; } drm_mga_clear_t; typedef struct drm_mga_vertex { int idx; /* buffer to queue */ int used; /* bytes in use */ int discard; /* client finished with buffer? */ } drm_mga_vertex_t; typedef struct drm_mga_indices { int idx; /* buffer to queue */ unsigned int start; unsigned int end; int discard; /* client finished with buffer? */ } drm_mga_indices_t; typedef struct drm_mga_iload { int idx; unsigned int dstorg; unsigned int length; } drm_mga_iload_t; typedef struct _drm_mga_blit { unsigned int planemask; unsigned int srcorg; unsigned int dstorg; int src_pitch, dst_pitch; int delta_sx, delta_sy; int delta_dx, delta_dy; int height, ydir; /* flip image vertically */ int source_pitch, dest_pitch; } drm_mga_blit_t; /* 3.1: An ioctl to get parameters that aren't available to the 3d * client any other way. */ #define MGA_PARAM_IRQ_NR 1 + +/* 3.2: Query the actual card type. The DDX only distinguishes between + * G200 chips and non-G200 chips, which it calls G400. It turns out that + * there are some very sublte differences between the G4x0 chips and the G550 + * chips. Using this parameter query, a client-side driver can detect the + * difference between a G4x0 and a G550. + */ +#define MGA_PARAM_CARD_TYPE 2 typedef struct drm_mga_getparam { int param; void __user *value; } drm_mga_getparam_t; #endif Index: head/sys/dev/drm/mga_drv.c =================================================================== --- head/sys/dev/drm/mga_drv.c (revision 152908) +++ head/sys/dev/drm/mga_drv.c (revision 152909) @@ -1,118 +1,161 @@ /* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*- * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/mga_drm.h" #include "dev/drm/mga_drv.h" #include "dev/drm/drm_pciids.h" /* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */ static drm_pci_id_list_t mga_pciidlist[] = { mga_PCI_IDS }; -extern drm_ioctl_desc_t mga_ioctls[]; -extern int mga_max_ioctl; +/** + * Determine if the device really is AGP or not. + * + * In addition to the usual tests performed by \c drm_device_is_agp, this + * function detects PCI G450 cards that appear to the system exactly like + * AGP G450 cards. + * + * \param dev The device to be tested. + * + * \returns + * If the device is a PCI G450, zero is returned. Otherwise non-zero is + * returned. + * + * \bug + * This function needs to be filled in! The implementation in + * linux-core/mga_drv.c shows what needs to be done. + */ +static int mga_driver_device_is_agp(drm_device_t * dev) +{ + /* There are PCI versions of the G450. These cards have the + * same PCI ID as the AGP G450, but have an additional PCI-to-PCI + * bridge chip. We detect these cards, which are not currently + * supported by this driver, by looking at the device ID of the + * bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the + * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the + * device. + */ + if (pci_get_device(dev->device) == 0x0525 && + pci_get_vendor(device_get_parent(dev->device)) == 0x3388 && + pci_get_device(device_get_parent(dev->device)) == 0x0021) + return 0; + else + return 2; +} static void mga_configure(drm_device_t *dev) { - dev->dev_priv_size = sizeof(drm_mga_buf_priv_t); - /* XXX dev->prerelease = mga_driver_prerelease; */ - dev->pretakedown = mga_driver_pretakedown; - dev->vblank_wait = mga_driver_vblank_wait; - dev->irq_preinstall = mga_driver_irq_preinstall; - dev->irq_postinstall = mga_driver_irq_postinstall; - dev->irq_uninstall = mga_driver_irq_uninstall; - dev->irq_handler = mga_driver_irq_handler; - dev->dma_ioctl = mga_dma_buffers; - dev->dma_quiescent = mga_driver_dma_quiescent; + dev->driver.buf_priv_size = sizeof(drm_mga_buf_priv_t); + dev->driver.load = mga_driver_load; + dev->driver.unload = mga_driver_unload; + dev->driver.lastclose = mga_driver_lastclose; + dev->driver.vblank_wait = mga_driver_vblank_wait; + dev->driver.irq_preinstall = mga_driver_irq_preinstall; + dev->driver.irq_postinstall = mga_driver_irq_postinstall; + dev->driver.irq_uninstall = mga_driver_irq_uninstall; + dev->driver.irq_handler = mga_driver_irq_handler; + dev->driver.dma_ioctl = mga_dma_buffers; + dev->driver.dma_quiescent = mga_driver_dma_quiescent; + dev->driver.device_is_agp = mga_driver_device_is_agp; - dev->driver_ioctls = mga_ioctls; - dev->max_driver_ioctl = mga_max_ioctl; + dev->driver.ioctls = mga_ioctls; + dev->driver.max_ioctl = mga_max_ioctl; - dev->driver_name = DRIVER_NAME; - dev->driver_desc = DRIVER_DESC; - dev->driver_date = DRIVER_DATE; - dev->driver_major = DRIVER_MAJOR; - dev->driver_minor = DRIVER_MINOR; - dev->driver_patchlevel = DRIVER_PATCHLEVEL; + dev->driver.name = DRIVER_NAME; + dev->driver.desc = DRIVER_DESC; + dev->driver.date = DRIVER_DATE; + dev->driver.major = DRIVER_MAJOR; + dev->driver.minor = DRIVER_MINOR; + dev->driver.patchlevel = DRIVER_PATCHLEVEL; - dev->use_agp = 1; - dev->require_agp = 1; - dev->use_mtrr = 1; - dev->use_dma = 1; - dev->use_irq = 1; - dev->use_vbl_irq = 1; + dev->driver.use_agp = 1; + dev->driver.require_agp = 1; + dev->driver.use_mtrr = 1; + dev->driver.use_dma = 1; + dev->driver.use_irq = 1; + dev->driver.use_vbl_irq = 1; } + + #ifdef __FreeBSD__ static int mga_probe(device_t dev) { return drm_probe(dev, mga_pciidlist); } static int mga_attach(device_t nbdev) { drm_device_t *dev = device_get_softc(nbdev); bzero(dev, sizeof(drm_device_t)); mga_configure(dev); return drm_attach(nbdev, mga_pciidlist); } static device_method_t mga_methods[] = { /* Device interface */ DEVMETHOD(device_probe, mga_probe), DEVMETHOD(device_attach, mga_attach), DEVMETHOD(device_detach, drm_detach), { 0, 0 } }; static driver_t mga_driver = { "drm", mga_methods, sizeof(drm_device_t) }; extern devclass_t drm_devclass; DRIVER_MODULE(mga, pci, mga_driver, drm_devclass, 0, 0); MODULE_DEPEND(mga, drm, 1, 1, 1); #elif defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef _LKM CFDRIVER_DECL(mga, DV_TTY, NULL); +#else +CFATTACH_DECL(mga, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach, + drm_activate); +#endif #endif Index: head/sys/dev/drm/mga_drv.h =================================================================== --- head/sys/dev/drm/mga_drv.h (revision 152908) +++ head/sys/dev/drm/mga_drv.h (revision 152909) @@ -1,632 +1,686 @@ /* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- linux-c -*- - * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com */ -/*- + * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com + * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef __MGA_DRV_H__ #define __MGA_DRV_H__ /* General customization: */ #define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." #define DRIVER_NAME "mga" #define DRIVER_DESC "Matrox G200/G400" -#define DRIVER_DATE "20021029" +#define DRIVER_DATE "20051102" #define DRIVER_MAJOR 3 -#define DRIVER_MINOR 1 -#define DRIVER_PATCHLEVEL 0 +#define DRIVER_MINOR 2 +#define DRIVER_PATCHLEVEL 1 typedef struct drm_mga_primary_buffer { u8 *start; u8 *end; int size; u32 tail; int space; volatile long wrapped; volatile u32 *status; u32 last_flush; u32 last_wrap; u32 high_mark; } drm_mga_primary_buffer_t; typedef struct drm_mga_freelist { struct drm_mga_freelist *next; struct drm_mga_freelist *prev; drm_mga_age_t age; drm_buf_t *buf; } drm_mga_freelist_t; typedef struct { drm_mga_freelist_t *list_entry; int discard; int dispatched; } drm_mga_buf_priv_t; typedef struct drm_mga_private { drm_mga_primary_buffer_t prim; drm_mga_sarea_t *sarea_priv; drm_mga_freelist_t *head; drm_mga_freelist_t *tail; unsigned int warp_pipe; unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES]; int chipset; int usec_timeout; + /** + * If set, the new DMA initialization sequence was used. This is + * primarilly used to select how the driver should uninitialized its + * internal DMA structures. + */ + int used_new_dma_init; + + /** + * If AGP memory is used for DMA buffers, this will be the value + * \c MGA_PAGPXFER. Otherwise, it will be zero (for a PCI transfer). + */ + u32 dma_access; + + /** + * If AGP memory is used for DMA buffers, this will be the value + * \c MGA_WAGP_ENABLE. Otherwise, it will be zero (for a PCI + * transfer). + */ + u32 wagp_enable; + + /** + * \name MMIO region parameters. + * + * \sa drm_mga_private_t::mmio + */ + /*@{*/ + u32 mmio_base; /**< Bus address of base of MMIO. */ + u32 mmio_size; /**< Size of the MMIO region. */ + /*@}*/ + u32 clear_cmd; u32 maccess; + wait_queue_head_t fence_queue; + atomic_t last_fence_retired; + u32 next_fence_to_post; + unsigned int fb_cpp; unsigned int front_offset; unsigned int front_pitch; unsigned int back_offset; unsigned int back_pitch; unsigned int depth_cpp; unsigned int depth_offset; unsigned int depth_pitch; unsigned int texture_offset; unsigned int texture_size; drm_local_map_t *sarea; drm_local_map_t *mmio; drm_local_map_t *status; drm_local_map_t *warp; drm_local_map_t *primary; - drm_local_map_t *buffers; drm_local_map_t *agp_textures; + + unsigned long agp_handle; + unsigned int agp_size; } drm_mga_private_t; +extern drm_ioctl_desc_t mga_ioctls[]; +extern int mga_max_ioctl; + /* mga_dma.c */ +extern int mga_dma_bootstrap(DRM_IOCTL_ARGS); extern int mga_dma_init(DRM_IOCTL_ARGS); extern int mga_dma_flush(DRM_IOCTL_ARGS); extern int mga_dma_reset(DRM_IOCTL_ARGS); extern int mga_dma_buffers(DRM_IOCTL_ARGS); -extern void mga_driver_pretakedown(drm_device_t * dev); +extern int mga_driver_load(drm_device_t *dev, unsigned long flags); +extern int mga_driver_unload(drm_device_t * dev); +extern void mga_driver_lastclose(drm_device_t * dev); extern int mga_driver_dma_quiescent(drm_device_t * dev); extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv); extern void mga_do_dma_flush(drm_mga_private_t * dev_priv); extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv); extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv); extern int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf); /* mga_warp.c */ +extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv); extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv); extern int mga_warp_init(drm_mga_private_t * dev_priv); + /* mga_irq.c */ +extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence); extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS); extern void mga_driver_irq_preinstall(drm_device_t * dev); extern void mga_driver_irq_postinstall(drm_device_t * dev); extern void mga_driver_irq_uninstall(drm_device_t * dev); +extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); #define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER() #if defined(__linux__) && defined(__alpha__) #define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle)) #define MGA_ADDR( reg ) (MGA_BASE(reg) + reg) #define MGA_DEREF( reg ) *(volatile u32 *)MGA_ADDR( reg ) #define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg ) #define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg))) #define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg))) #define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0) #define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0) static inline u32 _MGA_READ(u32 * addr) { DRM_MEMORYBARRIER(); return *(volatile u32 *)addr; } #else #define MGA_READ8( reg ) DRM_READ8(dev_priv->mmio, (reg)) #define MGA_READ( reg ) DRM_READ32(dev_priv->mmio, (reg)) #define MGA_WRITE8( reg, val ) DRM_WRITE8(dev_priv->mmio, (reg), (val)) #define MGA_WRITE( reg, val ) DRM_WRITE32(dev_priv->mmio, (reg), (val)) #endif #define DWGREG0 0x1c00 #define DWGREG0_END 0x1dff #define DWGREG1 0x2c00 #define DWGREG1_END 0x2dff #define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END) #define DMAREG0(r) (u8)((r - DWGREG0) >> 2) #define DMAREG1(r) (u8)(((r - DWGREG1) >> 2) | 0x80) #define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r)) /* ================================================================ * Helper macross... */ #define MGA_EMIT_STATE( dev_priv, dirty ) \ do { \ if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) { \ - if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { \ + if ( dev_priv->chipset >= MGA_CARD_TYPE_G400 ) { \ mga_g400_emit_state( dev_priv ); \ } else { \ mga_g200_emit_state( dev_priv ); \ } \ } \ } while (0) #define WRAP_TEST_WITH_RETURN( dev_priv ) \ do { \ if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \ if ( mga_is_idle( dev_priv ) ) { \ mga_do_dma_wrap_end( dev_priv ); \ } else if ( dev_priv->prim.space < \ dev_priv->prim.high_mark ) { \ if ( MGA_DMA_DEBUG ) \ DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ return DRM_ERR(EBUSY); \ } \ } \ } while (0) #define WRAP_WAIT_WITH_RETURN( dev_priv ) \ do { \ if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \ if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \ if ( MGA_DMA_DEBUG ) \ DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ return DRM_ERR(EBUSY); \ } \ mga_do_dma_wrap_end( dev_priv ); \ } \ } while (0) /* ================================================================ * Primary DMA command stream */ #define MGA_VERBOSE 0 #define DMA_LOCALS unsigned int write; volatile u8 *prim; #define DMA_BLOCK_SIZE (5 * sizeof(u32)) #define BEGIN_DMA( n ) \ do { \ if ( MGA_VERBOSE ) { \ DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \ (n), __FUNCTION__ ); \ DRM_INFO( " space=0x%x req=0x%Zx\n", \ dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \ } \ prim = dev_priv->prim.start; \ write = dev_priv->prim.tail; \ } while (0) #define BEGIN_DMA_WRAP() \ do { \ if ( MGA_VERBOSE ) { \ DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \ DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \ } \ prim = dev_priv->prim.start; \ write = dev_priv->prim.tail; \ } while (0) #define ADVANCE_DMA() \ do { \ dev_priv->prim.tail = write; \ if ( MGA_VERBOSE ) { \ DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n", \ write, dev_priv->prim.space ); \ } \ } while (0) #define FLUSH_DMA() \ do { \ if ( 0 ) { \ DRM_INFO( "%s:\n", __FUNCTION__ ); \ DRM_INFO( " tail=0x%06x head=0x%06lx\n", \ dev_priv->prim.tail, \ MGA_READ( MGA_PRIMADDRESS ) - \ dev_priv->primary->offset ); \ } \ if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) { \ if ( dev_priv->prim.space < \ dev_priv->prim.high_mark ) { \ mga_do_dma_wrap_start( dev_priv ); \ } else { \ mga_do_dma_flush( dev_priv ); \ } \ } \ } while (0) /* Never use this, always use DMA_BLOCK(...) for primary DMA output. */ #define DMA_WRITE( offset, val ) \ do { \ if ( MGA_VERBOSE ) { \ DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \ (u32)(val), write + (offset) * sizeof(u32) ); \ } \ *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \ } while (0) #define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 ) \ do { \ DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) | \ (DMAREG( reg1 ) << 8) | \ (DMAREG( reg2 ) << 16) | \ (DMAREG( reg3 ) << 24)) ); \ DMA_WRITE( 1, val0 ); \ DMA_WRITE( 2, val1 ); \ DMA_WRITE( 3, val2 ); \ DMA_WRITE( 4, val3 ); \ write += DMA_BLOCK_SIZE; \ } while (0) /* Buffer aging via primary DMA stream head pointer. */ #define SET_AGE( age, h, w ) \ do { \ (age)->head = h; \ (age)->wrap = w; \ } while (0) #define TEST_AGE( age, h, w ) ( (age)->wrap < w || \ ( (age)->wrap == w && \ (age)->head < h ) ) #define AGE_BUFFER( buf_priv ) \ do { \ drm_mga_freelist_t *entry = (buf_priv)->list_entry; \ if ( (buf_priv)->dispatched ) { \ entry->age.head = (dev_priv->prim.tail + \ dev_priv->primary->offset); \ entry->age.wrap = dev_priv->sarea_priv->last_wrap; \ } else { \ entry->age.head = 0; \ entry->age.wrap = 0; \ } \ } while (0) #define MGA_ENGINE_IDLE_MASK (MGA_SOFTRAPEN | \ MGA_DWGENGSTS | \ MGA_ENDPRDMASTS) #define MGA_DMA_IDLE_MASK (MGA_SOFTRAPEN | \ MGA_ENDPRDMASTS) #define MGA_DMA_DEBUG 0 /* A reduced set of the mga registers. */ #define MGA_CRTC_INDEX 0x1fd4 #define MGA_CRTC_DATA 0x1fd5 /* CRTC11 */ #define MGA_VINTCLR (1 << 4) #define MGA_VINTEN (1 << 5) #define MGA_ALPHACTRL 0x2c7c #define MGA_AR0 0x1c60 #define MGA_AR1 0x1c64 #define MGA_AR2 0x1c68 #define MGA_AR3 0x1c6c #define MGA_AR4 0x1c70 #define MGA_AR5 0x1c74 #define MGA_AR6 0x1c78 #define MGA_CXBNDRY 0x1c80 #define MGA_CXLEFT 0x1ca0 #define MGA_CXRIGHT 0x1ca4 #define MGA_DMAPAD 0x1c54 #define MGA_DSTORG 0x2cb8 #define MGA_DWGCTL 0x1c00 # define MGA_OPCOD_MASK (15 << 0) # define MGA_OPCOD_TRAP (4 << 0) # define MGA_OPCOD_TEXTURE_TRAP (6 << 0) # define MGA_OPCOD_BITBLT (8 << 0) # define MGA_OPCOD_ILOAD (9 << 0) # define MGA_ATYPE_MASK (7 << 4) # define MGA_ATYPE_RPL (0 << 4) # define MGA_ATYPE_RSTR (1 << 4) # define MGA_ATYPE_ZI (3 << 4) # define MGA_ATYPE_BLK (4 << 4) # define MGA_ATYPE_I (7 << 4) # define MGA_LINEAR (1 << 7) # define MGA_ZMODE_MASK (7 << 8) # define MGA_ZMODE_NOZCMP (0 << 8) # define MGA_ZMODE_ZE (2 << 8) # define MGA_ZMODE_ZNE (3 << 8) # define MGA_ZMODE_ZLT (4 << 8) # define MGA_ZMODE_ZLTE (5 << 8) # define MGA_ZMODE_ZGT (6 << 8) # define MGA_ZMODE_ZGTE (7 << 8) # define MGA_SOLID (1 << 11) # define MGA_ARZERO (1 << 12) # define MGA_SGNZERO (1 << 13) # define MGA_SHIFTZERO (1 << 14) # define MGA_BOP_MASK (15 << 16) # define MGA_BOP_ZERO (0 << 16) # define MGA_BOP_DST (10 << 16) # define MGA_BOP_SRC (12 << 16) # define MGA_BOP_ONE (15 << 16) # define MGA_TRANS_SHIFT 20 # define MGA_TRANS_MASK (15 << 20) # define MGA_BLTMOD_MASK (15 << 25) # define MGA_BLTMOD_BMONOLEF (0 << 25) # define MGA_BLTMOD_BMONOWF (4 << 25) # define MGA_BLTMOD_PLAN (1 << 25) # define MGA_BLTMOD_BFCOL (2 << 25) # define MGA_BLTMOD_BU32BGR (3 << 25) # define MGA_BLTMOD_BU32RGB (7 << 25) # define MGA_BLTMOD_BU24BGR (11 << 25) # define MGA_BLTMOD_BU24RGB (15 << 25) # define MGA_PATTERN (1 << 29) # define MGA_TRANSC (1 << 30) # define MGA_CLIPDIS (1 << 31) #define MGA_DWGSYNC 0x2c4c #define MGA_FCOL 0x1c24 #define MGA_FIFOSTATUS 0x1e10 #define MGA_FOGCOL 0x1cf4 #define MGA_FXBNDRY 0x1c84 #define MGA_FXLEFT 0x1ca8 #define MGA_FXRIGHT 0x1cac #define MGA_ICLEAR 0x1e18 # define MGA_SOFTRAPICLR (1 << 0) # define MGA_VLINEICLR (1 << 5) #define MGA_IEN 0x1e1c # define MGA_SOFTRAPIEN (1 << 0) # define MGA_VLINEIEN (1 << 5) #define MGA_LEN 0x1c5c #define MGA_MACCESS 0x1c04 #define MGA_PITCH 0x1c8c #define MGA_PLNWT 0x1c1c #define MGA_PRIMADDRESS 0x1e58 # define MGA_DMA_GENERAL (0 << 0) # define MGA_DMA_BLIT (1 << 0) # define MGA_DMA_VECTOR (2 << 0) # define MGA_DMA_VERTEX (3 << 0) #define MGA_PRIMEND 0x1e5c # define MGA_PRIMNOSTART (1 << 0) # define MGA_PAGPXFER (1 << 1) #define MGA_PRIMPTR 0x1e50 # define MGA_PRIMPTREN0 (1 << 0) # define MGA_PRIMPTREN1 (1 << 1) #define MGA_RST 0x1e40 # define MGA_SOFTRESET (1 << 0) # define MGA_SOFTEXTRST (1 << 1) #define MGA_SECADDRESS 0x2c40 #define MGA_SECEND 0x2c44 #define MGA_SETUPADDRESS 0x2cd0 #define MGA_SETUPEND 0x2cd4 #define MGA_SGN 0x1c58 #define MGA_SOFTRAP 0x2c48 #define MGA_SRCORG 0x2cb4 # define MGA_SRMMAP_MASK (1 << 0) # define MGA_SRCMAP_FB (0 << 0) # define MGA_SRCMAP_SYSMEM (1 << 0) # define MGA_SRCACC_MASK (1 << 1) # define MGA_SRCACC_PCI (0 << 1) # define MGA_SRCACC_AGP (1 << 1) #define MGA_STATUS 0x1e14 # define MGA_SOFTRAPEN (1 << 0) # define MGA_VSYNCPEN (1 << 4) # define MGA_VLINEPEN (1 << 5) # define MGA_DWGENGSTS (1 << 16) # define MGA_ENDPRDMASTS (1 << 17) #define MGA_STENCIL 0x2cc8 #define MGA_STENCILCTL 0x2ccc #define MGA_TDUALSTAGE0 0x2cf8 #define MGA_TDUALSTAGE1 0x2cfc #define MGA_TEXBORDERCOL 0x2c5c #define MGA_TEXCTL 0x2c30 #define MGA_TEXCTL2 0x2c3c # define MGA_DUALTEX (1 << 7) # define MGA_G400_TC2_MAGIC (1 << 15) # define MGA_MAP1_ENABLE (1 << 31) #define MGA_TEXFILTER 0x2c58 #define MGA_TEXHEIGHT 0x2c2c #define MGA_TEXORG 0x2c24 # define MGA_TEXORGMAP_MASK (1 << 0) # define MGA_TEXORGMAP_FB (0 << 0) # define MGA_TEXORGMAP_SYSMEM (1 << 0) # define MGA_TEXORGACC_MASK (1 << 1) # define MGA_TEXORGACC_PCI (0 << 1) # define MGA_TEXORGACC_AGP (1 << 1) #define MGA_TEXORG1 0x2ca4 #define MGA_TEXORG2 0x2ca8 #define MGA_TEXORG3 0x2cac #define MGA_TEXORG4 0x2cb0 #define MGA_TEXTRANS 0x2c34 #define MGA_TEXTRANSHIGH 0x2c38 #define MGA_TEXWIDTH 0x2c28 #define MGA_WACCEPTSEQ 0x1dd4 #define MGA_WCODEADDR 0x1e6c #define MGA_WFLAG 0x1dc4 #define MGA_WFLAG1 0x1de0 #define MGA_WFLAGNB 0x1e64 #define MGA_WFLAGNB1 0x1e08 #define MGA_WGETMSB 0x1dc8 #define MGA_WIADDR 0x1dc0 #define MGA_WIADDR2 0x1dd8 # define MGA_WMODE_SUSPEND (0 << 0) # define MGA_WMODE_RESUME (1 << 0) # define MGA_WMODE_JUMP (2 << 0) # define MGA_WMODE_START (3 << 0) # define MGA_WAGP_ENABLE (1 << 2) #define MGA_WMISC 0x1e70 # define MGA_WUCODECACHE_ENABLE (1 << 0) # define MGA_WMASTER_ENABLE (1 << 1) # define MGA_WCACHEFLUSH_ENABLE (1 << 3) #define MGA_WVRTXSZ 0x1dcc #define MGA_YBOT 0x1c9c #define MGA_YDST 0x1c90 #define MGA_YDSTLEN 0x1c88 #define MGA_YDSTORG 0x1c94 #define MGA_YTOP 0x1c98 #define MGA_ZORG 0x1c0c /* This finishes the current batch of commands */ #define MGA_EXEC 0x0100 + +/* AGP PLL encoding (for G200 only). + */ +#define MGA_AGP_PLL 0x1e4c +# define MGA_AGP2XPLL_DISABLE (0 << 0) +# define MGA_AGP2XPLL_ENABLE (1 << 0) /* Warp registers */ #define MGA_WR0 0x2d00 #define MGA_WR1 0x2d04 #define MGA_WR2 0x2d08 #define MGA_WR3 0x2d0c #define MGA_WR4 0x2d10 #define MGA_WR5 0x2d14 #define MGA_WR6 0x2d18 #define MGA_WR7 0x2d1c #define MGA_WR8 0x2d20 #define MGA_WR9 0x2d24 #define MGA_WR10 0x2d28 #define MGA_WR11 0x2d2c #define MGA_WR12 0x2d30 #define MGA_WR13 0x2d34 #define MGA_WR14 0x2d38 #define MGA_WR15 0x2d3c #define MGA_WR16 0x2d40 #define MGA_WR17 0x2d44 #define MGA_WR18 0x2d48 #define MGA_WR19 0x2d4c #define MGA_WR20 0x2d50 #define MGA_WR21 0x2d54 #define MGA_WR22 0x2d58 #define MGA_WR23 0x2d5c #define MGA_WR24 0x2d60 #define MGA_WR25 0x2d64 #define MGA_WR26 0x2d68 #define MGA_WR27 0x2d6c #define MGA_WR28 0x2d70 #define MGA_WR29 0x2d74 #define MGA_WR30 0x2d78 #define MGA_WR31 0x2d7c #define MGA_WR32 0x2d80 #define MGA_WR33 0x2d84 #define MGA_WR34 0x2d88 #define MGA_WR35 0x2d8c #define MGA_WR36 0x2d90 #define MGA_WR37 0x2d94 #define MGA_WR38 0x2d98 #define MGA_WR39 0x2d9c #define MGA_WR40 0x2da0 #define MGA_WR41 0x2da4 #define MGA_WR42 0x2da8 #define MGA_WR43 0x2dac #define MGA_WR44 0x2db0 #define MGA_WR45 0x2db4 #define MGA_WR46 0x2db8 #define MGA_WR47 0x2dbc #define MGA_WR48 0x2dc0 #define MGA_WR49 0x2dc4 #define MGA_WR50 0x2dc8 #define MGA_WR51 0x2dcc #define MGA_WR52 0x2dd0 #define MGA_WR53 0x2dd4 #define MGA_WR54 0x2dd8 #define MGA_WR55 0x2ddc #define MGA_WR56 0x2de0 #define MGA_WR57 0x2de4 #define MGA_WR58 0x2de8 #define MGA_WR59 0x2dec #define MGA_WR60 0x2df0 #define MGA_WR61 0x2df4 #define MGA_WR62 0x2df8 #define MGA_WR63 0x2dfc # define MGA_G400_WR_MAGIC (1 << 6) # define MGA_G400_WR56_MAGIC 0x46480000 /* 12800.0f */ #define MGA_ILOAD_ALIGN 64 #define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1) #define MGA_DWGCTL_FLUSH (MGA_OPCOD_TEXTURE_TRAP | \ MGA_ATYPE_I | \ MGA_ZMODE_NOZCMP | \ MGA_ARZERO | \ MGA_SGNZERO | \ MGA_BOP_SRC | \ (15 << MGA_TRANS_SHIFT)) #define MGA_DWGCTL_CLEAR (MGA_OPCOD_TRAP | \ MGA_ZMODE_NOZCMP | \ MGA_SOLID | \ MGA_ARZERO | \ MGA_SGNZERO | \ MGA_SHIFTZERO | \ MGA_BOP_SRC | \ (0 << MGA_TRANS_SHIFT) | \ MGA_BLTMOD_BMONOLEF | \ MGA_TRANSC | \ MGA_CLIPDIS) #define MGA_DWGCTL_COPY (MGA_OPCOD_BITBLT | \ MGA_ATYPE_RPL | \ MGA_SGNZERO | \ MGA_SHIFTZERO | \ MGA_BOP_SRC | \ (0 << MGA_TRANS_SHIFT) | \ MGA_BLTMOD_BFCOL | \ MGA_CLIPDIS) /* Simple idle test. */ static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv) { u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; return (status == MGA_ENDPRDMASTS); } #endif Index: head/sys/dev/drm/mga_irq.c =================================================================== --- head/sys/dev/drm/mga_irq.c (revision 152908) +++ head/sys/dev/drm/mga_irq.c (revision 152909) @@ -1,103 +1,153 @@ -/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- */ +/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- + */ /*- * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. * * The Weather Channel (TM) funded Tungsten Graphics to develop the * initial release of the Radeon 8500 driver under the XFree86 license. * This notice must be preserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Keith Whitwell * Eric Anholt - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/mga_drm.h" #include "dev/drm/mga_drv.h" irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; int status; + int handled = 0; status = MGA_READ(MGA_STATUS); /* VBLANK interrupt */ if (status & MGA_VLINEPEN) { MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); + handled = 1; + } + + /* SOFTRAP interrupt */ + if (status & MGA_SOFTRAPEN) { + const u32 prim_start = MGA_READ(MGA_PRIMADDRESS); + const u32 prim_end = MGA_READ(MGA_PRIMEND); + + + MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR); + + /* In addition to clearing the interrupt-pending bit, we + * have to write to MGA_PRIMEND to re-start the DMA operation. + */ + if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) { + MGA_WRITE(MGA_PRIMEND, prim_end); + } + + atomic_inc(&dev_priv->last_fence_retired); + DRM_WAKEUP(&dev_priv->fence_queue); + handled = 1; + } + + if ( handled ) { return IRQ_HANDLED; } return IRQ_NONE; } int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) { unsigned int cur_vblank; int ret = 0; /* Assume that the user has missed the current sequence number * by about a day rather than she wants to wait for years * using vertical blanks... */ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, (((cur_vblank = atomic_read(&dev->vbl_received)) - *sequence) <= (1 << 23))); *sequence = cur_vblank; return ret; } +int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence) +{ + drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; + unsigned int cur_fence; + int ret = 0; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using fences. + */ + DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ, + (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) + - *sequence) <= (1 << 23))); + + *sequence = cur_fence; + + return ret; +} + void mga_driver_irq_preinstall(drm_device_t * dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; /* Disable *all* interrupts */ MGA_WRITE(MGA_IEN, 0); /* Clear bits if they're already high */ MGA_WRITE(MGA_ICLEAR, ~0); } void mga_driver_irq_postinstall(drm_device_t * dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - /* Turn on VBL interrupt */ - MGA_WRITE(MGA_IEN, MGA_VLINEIEN); + DRM_INIT_WAITQUEUE( &dev_priv->fence_queue ); + + /* Turn on vertical blank interrupt and soft trap interrupt. */ + MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); } void mga_driver_irq_uninstall(drm_device_t * dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; if (!dev_priv) return; /* Disable *all* interrupts */ MGA_WRITE(MGA_IEN, 0); + + dev->irq_enabled = 0; } Index: head/sys/dev/drm/mga_state.c =================================================================== --- head/sys/dev/drm/mga_state.c (revision 152908) +++ head/sys/dev/drm/mga_state.c (revision 152909) @@ -1,1118 +1,1181 @@ /* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*- - * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com */ + * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com + */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Jeff Hartmann * Keith Whitwell * * Rewritten by: * Gareth Hughes - * $FreeBSD$ - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/mga_drm.h" #include "dev/drm/mga_drv.h" /* ================================================================ * DMA hardware state programming functions */ static void mga_emit_clip_rect(drm_mga_private_t * dev_priv, drm_clip_rect_t * box) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_context_regs_t *ctx = &sarea_priv->context_state; unsigned int pitch = dev_priv->front_pitch; DMA_LOCALS; BEGIN_DMA(2); /* Force reset of DWGCTL on G400 (eliminates clip disable bit). */ - if (dev_priv->chipset == MGA_CARD_TYPE_G400) { + if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl, MGA_LEN + MGA_EXEC, 0x80000000, MGA_DWGCTL, ctx->dwgctl, MGA_LEN + MGA_EXEC, 0x80000000); } DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1, MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch); ADVANCE_DMA(); } static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_context_regs_t *ctx = &sarea_priv->context_state; DMA_LOCALS; BEGIN_DMA(3); DMA_BLOCK(MGA_DSTORG, ctx->dstorg, MGA_MACCESS, ctx->maccess, MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, MGA_FOGCOL, ctx->fogcolor, MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); DMA_BLOCK(MGA_FCOL, ctx->fcol, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); ADVANCE_DMA(); } static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_context_regs_t *ctx = &sarea_priv->context_state; DMA_LOCALS; BEGIN_DMA(4); DMA_BLOCK(MGA_DSTORG, ctx->dstorg, MGA_MACCESS, ctx->maccess, MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, MGA_FOGCOL, ctx->fogcolor, MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); DMA_BLOCK(MGA_WFLAG1, ctx->wflag, MGA_TDUALSTAGE0, ctx->tdualstage0, MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol); DMA_BLOCK(MGA_STENCIL, ctx->stencil, MGA_STENCILCTL, ctx->stencilctl, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); ADVANCE_DMA(); } static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; DMA_LOCALS; BEGIN_DMA(4); DMA_BLOCK(MGA_TEXCTL2, tex->texctl2, MGA_TEXCTL, tex->texctl, MGA_TEXFILTER, tex->texfilter, MGA_TEXBORDERCOL, tex->texbordercol); DMA_BLOCK(MGA_TEXORG, tex->texorg, MGA_TEXORG1, tex->texorg1, MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); DMA_BLOCK(MGA_TEXORG4, tex->texorg4, MGA_TEXWIDTH, tex->texwidth, MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth); DMA_BLOCK(MGA_WR34, tex->texheight, MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000); ADVANCE_DMA(); } static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; DMA_LOCALS; /* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */ /* tex->texctl, tex->texctl2); */ BEGIN_DMA(6); DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC, MGA_TEXCTL, tex->texctl, MGA_TEXFILTER, tex->texfilter, MGA_TEXBORDERCOL, tex->texbordercol); DMA_BLOCK(MGA_TEXORG, tex->texorg, MGA_TEXORG1, tex->texorg1, MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); DMA_BLOCK(MGA_TEXORG4, tex->texorg4, MGA_TEXWIDTH, tex->texwidth, MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000); DMA_BLOCK(MGA_WR57, 0x00000000, MGA_WR53, 0x00000000, MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC); DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC, MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC, MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC, MGA_DMAPAD, 0x00000000); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff); ADVANCE_DMA(); } static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1]; DMA_LOCALS; /* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */ /* tex->texctl, tex->texctl2); */ BEGIN_DMA(5); DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 | MGA_MAP1_ENABLE | MGA_G400_TC2_MAGIC), MGA_TEXCTL, tex->texctl, MGA_TEXFILTER, tex->texfilter, MGA_TEXBORDERCOL, tex->texbordercol); DMA_BLOCK(MGA_TEXORG, tex->texorg, MGA_TEXORG1, tex->texorg1, MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); DMA_BLOCK(MGA_TEXORG4, tex->texorg4, MGA_TEXWIDTH, tex->texwidth, MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000); DMA_BLOCK(MGA_WR57, 0x00000000, MGA_WR53, 0x00000000, MGA_WR61, 0x00000000, MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC); DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC, MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff, MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC); ADVANCE_DMA(); } static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int pipe = sarea_priv->warp_pipe; DMA_LOCALS; BEGIN_DMA(3); DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND, MGA_WVRTXSZ, 0x00000007, MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000); DMA_BLOCK(MGA_WR25, 0x00000100, MGA_WR34, 0x00000000, MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff); /* Padding required to to hardware bug. */ DMA_BLOCK(MGA_DMAPAD, 0xffffffff, MGA_DMAPAD, 0xffffffff, MGA_DMAPAD, 0xffffffff, MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | - MGA_WMODE_START | MGA_WAGP_ENABLE)); + MGA_WMODE_START | dev_priv->wagp_enable)); ADVANCE_DMA(); } static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int pipe = sarea_priv->warp_pipe; DMA_LOCALS; /* printk("mga_g400_emit_pipe %x\n", pipe); */ BEGIN_DMA(10); DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); if (pipe & MGA_T2) { DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, MGA_WACCEPTSEQ, 0x00000000, MGA_WACCEPTSEQ, 0x00000000, MGA_WACCEPTSEQ, 0x1e000000); } else { if (dev_priv->warp_pipe & MGA_T2) { /* Flush the WARP pipe */ DMA_BLOCK(MGA_YDST, 0x00000000, MGA_FXLEFT, 0x00000000, MGA_FXRIGHT, 0x00000001, MGA_DWGCTL, MGA_DWGCTL_FLUSH); DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001, MGA_DWGSYNC, 0x00007000, MGA_TEXCTL2, MGA_G400_TC2_MAGIC, MGA_LEN + MGA_EXEC, 0x00000000); DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX | MGA_G400_TC2_MAGIC), MGA_LEN + MGA_EXEC, 0x00000000, MGA_TEXCTL2, MGA_G400_TC2_MAGIC, MGA_DMAPAD, 0x00000000); } DMA_BLOCK(MGA_WVRTXSZ, 0x00001807, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, MGA_WACCEPTSEQ, 0x00000000, MGA_WACCEPTSEQ, 0x00000000, MGA_WACCEPTSEQ, 0x18000000); } DMA_BLOCK(MGA_WFLAG, 0x00000000, MGA_WFLAG1, 0x00000000, MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000); DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0 */ MGA_WR57, 0x00000000, /* tex0 */ MGA_WR53, 0x00000000, /* tex1 */ MGA_WR61, 0x00000000); /* tex1 */ DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */ MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */ MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */ MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height */ /* Padding required to to hardware bug */ DMA_BLOCK(MGA_DMAPAD, 0xffffffff, MGA_DMAPAD, 0xffffffff, MGA_DMAPAD, 0xffffffff, MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | - MGA_WMODE_START | MGA_WAGP_ENABLE)); + MGA_WMODE_START | dev_priv->wagp_enable)); ADVANCE_DMA(); } static void mga_g200_emit_state(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { mga_g200_emit_pipe(dev_priv); dev_priv->warp_pipe = sarea_priv->warp_pipe; } if (dirty & MGA_UPLOAD_CONTEXT) { mga_g200_emit_context(dev_priv); sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; } if (dirty & MGA_UPLOAD_TEX0) { mga_g200_emit_tex0(dev_priv); sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; } } static void mga_g400_emit_state(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; int multitex = sarea_priv->warp_pipe & MGA_T2; if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { mga_g400_emit_pipe(dev_priv); dev_priv->warp_pipe = sarea_priv->warp_pipe; } if (dirty & MGA_UPLOAD_CONTEXT) { mga_g400_emit_context(dev_priv); sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; } if (dirty & MGA_UPLOAD_TEX0) { mga_g400_emit_tex0(dev_priv); sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; } if ((dirty & MGA_UPLOAD_TEX1) && multitex) { mga_g400_emit_tex1(dev_priv); sarea_priv->dirty &= ~MGA_UPLOAD_TEX1; } } /* ================================================================ * SAREA state verification */ /* Disallow all write destinations except the front and backbuffer. */ static int mga_verify_context(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_context_regs_t *ctx = &sarea_priv->context_state; if (ctx->dstorg != dev_priv->front_offset && ctx->dstorg != dev_priv->back_offset) { DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n", ctx->dstorg, dev_priv->front_offset, dev_priv->back_offset); ctx->dstorg = 0; return DRM_ERR(EINVAL); } return 0; } /* Disallow texture reads from PCI space. */ static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit]; unsigned int org; org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK); if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) { DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit); tex->texorg = 0; return DRM_ERR(EINVAL); } return 0; } static int mga_verify_state(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; int ret = 0; if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; if (dirty & MGA_UPLOAD_CONTEXT) ret |= mga_verify_context(dev_priv); if (dirty & MGA_UPLOAD_TEX0) ret |= mga_verify_tex(dev_priv, 0); - if (dev_priv->chipset == MGA_CARD_TYPE_G400) { + if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { if (dirty & MGA_UPLOAD_TEX1) ret |= mga_verify_tex(dev_priv, 1); if (dirty & MGA_UPLOAD_PIPE) ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES); } else { if (dirty & MGA_UPLOAD_PIPE) ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES); } return (ret == 0); } static int mga_verify_iload(drm_mga_private_t * dev_priv, unsigned int dstorg, unsigned int length) { if (dstorg < dev_priv->texture_offset || dstorg + length > (dev_priv->texture_offset + dev_priv->texture_size)) { DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg); return DRM_ERR(EINVAL); } if (length & MGA_ILOAD_MASK) { DRM_ERROR("*** bad iload length: 0x%x\n", length & MGA_ILOAD_MASK); return DRM_ERR(EINVAL); } return 0; } static int mga_verify_blit(drm_mga_private_t * dev_priv, unsigned int srcorg, unsigned int dstorg) { if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) || (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) { DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg); return DRM_ERR(EINVAL); } return 0; } /* ================================================================ * */ static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_context_regs_t *ctx = &sarea_priv->context_state; drm_clip_rect_t *pbox = sarea_priv->boxes; int nbox = sarea_priv->nbox; int i; DMA_LOCALS; DRM_DEBUG("\n"); BEGIN_DMA(1); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); ADVANCE_DMA(); for (i = 0; i < nbox; i++) { drm_clip_rect_t *box = &pbox[i]; u32 height = box->y2 - box->y1; DRM_DEBUG(" from=%d,%d to=%d,%d\n", box->x1, box->y1, box->x2, box->y2); if (clear->flags & MGA_FRONT) { BEGIN_DMA(2); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_PLNWT, clear->color_mask, MGA_YDSTLEN, (box->y1 << 16) | height, MGA_FXBNDRY, (box->x2 << 16) | box->x1); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_FCOL, clear->clear_color, MGA_DSTORG, dev_priv->front_offset, MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); ADVANCE_DMA(); } if (clear->flags & MGA_BACK) { BEGIN_DMA(2); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_PLNWT, clear->color_mask, MGA_YDSTLEN, (box->y1 << 16) | height, MGA_FXBNDRY, (box->x2 << 16) | box->x1); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_FCOL, clear->clear_color, MGA_DSTORG, dev_priv->back_offset, MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); ADVANCE_DMA(); } if (clear->flags & MGA_DEPTH) { BEGIN_DMA(2); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_PLNWT, clear->depth_mask, MGA_YDSTLEN, (box->y1 << 16) | height, MGA_FXBNDRY, (box->x2 << 16) | box->x1); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_FCOL, clear->clear_depth, MGA_DSTORG, dev_priv->depth_offset, MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); ADVANCE_DMA(); } } BEGIN_DMA(1); /* Force reset of DWGCTL */ DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); ADVANCE_DMA(); FLUSH_DMA(); } static void mga_dma_dispatch_swap(drm_device_t * dev) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_context_regs_t *ctx = &sarea_priv->context_state; drm_clip_rect_t *pbox = sarea_priv->boxes; int nbox = sarea_priv->nbox; int i; DMA_LOCALS; DRM_DEBUG("\n"); sarea_priv->last_frame.head = dev_priv->prim.tail; sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; BEGIN_DMA(4 + nbox); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset, MGA_MACCESS, dev_priv->maccess, MGA_SRCORG, dev_priv->back_offset, MGA_AR5, dev_priv->front_pitch); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY); for (i = 0; i < nbox; i++) { drm_clip_rect_t *box = &pbox[i]; u32 height = box->y2 - box->y1; u32 start = box->y1 * dev_priv->front_pitch; DRM_DEBUG(" from=%d,%d to=%d,%d\n", box->x1, box->y1, box->x2, box->y2); DMA_BLOCK(MGA_AR0, start + box->x2 - 1, MGA_AR3, start + box->x1, MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1, MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height); } DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_PLNWT, ctx->plnwt, MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl); ADVANCE_DMA(); FLUSH_DMA(); DRM_DEBUG("%s... done.\n", __FUNCTION__); } static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; u32 address = (u32) buf->bus_address; u32 length = (u32) buf->used; int i = 0; DMA_LOCALS; DRM_DEBUG("vertex: buf=%d used=%d\n", buf->idx, buf->used); if (buf->used) { buf_priv->dispatched = 1; MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); do { if (i < sarea_priv->nbox) { mga_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); } BEGIN_DMA(1); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_SECADDRESS, (address | MGA_DMA_VERTEX), MGA_SECEND, ((address + length) | - MGA_PAGPXFER)); + dev_priv->dma_access)); ADVANCE_DMA(); } while (++i < sarea_priv->nbox); } if (buf_priv->discard) { AGE_BUFFER(buf_priv); buf->pending = 0; buf->used = 0; buf_priv->dispatched = 0; mga_freelist_put(dev, buf); } FLUSH_DMA(); } static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf, unsigned int start, unsigned int end) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; u32 address = (u32) buf->bus_address; int i = 0; DMA_LOCALS; DRM_DEBUG("indices: buf=%d start=%d end=%d\n", buf->idx, start, end); if (start != end) { buf_priv->dispatched = 1; MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); do { if (i < sarea_priv->nbox) { mga_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); } BEGIN_DMA(1); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_SETUPADDRESS, address + start, MGA_SETUPEND, ((address + end) | - MGA_PAGPXFER)); + dev_priv->dma_access)); ADVANCE_DMA(); } while (++i < sarea_priv->nbox); } if (buf_priv->discard) { AGE_BUFFER(buf_priv); buf->pending = 0; buf->used = 0; buf_priv->dispatched = 0; mga_freelist_put(dev, buf); } FLUSH_DMA(); } /* This copies a 64 byte aligned agp region to the frambuffer with a * standard blit, the ioctl needs to do checking. */ static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf, unsigned int dstorg, unsigned int length) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; - u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM; + u32 srcorg = buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM; u32 y2; DMA_LOCALS; DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); y2 = length / 64; BEGIN_DMA(5); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); DMA_BLOCK(MGA_DSTORG, dstorg, MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64); DMA_BLOCK(MGA_PITCH, 64, MGA_PLNWT, 0xffffffff, MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY); DMA_BLOCK(MGA_AR0, 63, MGA_AR3, 0, MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2); DMA_BLOCK(MGA_PLNWT, ctx->plnwt, MGA_SRCORG, dev_priv->front_offset, MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000); ADVANCE_DMA(); AGE_BUFFER(buf_priv); buf->pending = 0; buf->used = 0; buf_priv->dispatched = 0; mga_freelist_put(dev, buf); FLUSH_DMA(); } static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_context_regs_t *ctx = &sarea_priv->context_state; drm_clip_rect_t *pbox = sarea_priv->boxes; int nbox = sarea_priv->nbox; u32 scandir = 0, i; DMA_LOCALS; DRM_DEBUG("\n"); BEGIN_DMA(4 + nbox); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY, MGA_PLNWT, blit->planemask, MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg); DMA_BLOCK(MGA_SGN, scandir, MGA_MACCESS, dev_priv->maccess, MGA_AR5, blit->ydir * blit->src_pitch, MGA_PITCH, blit->dst_pitch); for (i = 0; i < nbox; i++) { int srcx = pbox[i].x1 + blit->delta_sx; int srcy = pbox[i].y1 + blit->delta_sy; int dstx = pbox[i].x1 + blit->delta_dx; int dsty = pbox[i].y1 + blit->delta_dy; int h = pbox[i].y2 - pbox[i].y1; int w = pbox[i].x2 - pbox[i].x1 - 1; int start; if (blit->ydir == -1) { srcy = blit->height - srcy - 1; } start = srcy * blit->src_pitch + srcx; DMA_BLOCK(MGA_AR0, start + w, MGA_AR3, start, MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff), MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h); } /* Do something to flush AGP? */ /* Force reset of DWGCTL */ DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_PLNWT, ctx->plnwt, MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl); ADVANCE_DMA(); } /* ================================================================ * */ static int mga_dma_clear(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_clear_t clear; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(clear, (drm_mga_clear_t __user *) data, sizeof(clear)); if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; WRAP_TEST_WITH_RETURN(dev_priv); mga_dma_dispatch_clear(dev, &clear); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; return 0; } static int mga_dma_swap(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; LOCK_TEST_WITH_RETURN(dev, filp); if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; WRAP_TEST_WITH_RETURN(dev_priv); mga_dma_dispatch_swap(dev); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; return 0; } static int mga_dma_vertex(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_vertex_t vertex; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_mga_vertex_t __user *) data, sizeof(vertex)); if (vertex.idx < 0 || vertex.idx > dma->buf_count) return DRM_ERR(EINVAL); buf = dma->buflist[vertex.idx]; buf_priv = buf->dev_private; buf->used = vertex.used; buf_priv->discard = vertex.discard; if (!mga_verify_state(dev_priv)) { if (vertex.discard) { if (buf_priv->dispatched == 1) AGE_BUFFER(buf_priv); buf_priv->dispatched = 0; mga_freelist_put(dev, buf); } return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN(dev_priv); mga_dma_dispatch_vertex(dev, buf); return 0; } static int mga_dma_indices(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_indices_t indices; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(indices, (drm_mga_indices_t __user *) data, sizeof(indices)); if (indices.idx < 0 || indices.idx > dma->buf_count) return DRM_ERR(EINVAL); buf = dma->buflist[indices.idx]; buf_priv = buf->dev_private; buf_priv->discard = indices.discard; if (!mga_verify_state(dev_priv)) { if (indices.discard) { if (buf_priv->dispatched == 1) AGE_BUFFER(buf_priv); buf_priv->dispatched = 0; mga_freelist_put(dev, buf); } return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN(dev_priv); mga_dma_dispatch_indices(dev, buf, indices.start, indices.end); return 0; } static int mga_dma_iload(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_mga_private_t *dev_priv = dev->dev_private; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_iload_t iload; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(iload, (drm_mga_iload_t __user *) data, sizeof(iload)); #if 0 if (mga_do_wait_for_idle(dev_priv) < 0) { if (MGA_DMA_DEBUG) DRM_INFO("%s: -EBUSY\n", __FUNCTION__); return DRM_ERR(EBUSY); } #endif if (iload.idx < 0 || iload.idx > dma->buf_count) return DRM_ERR(EINVAL); buf = dma->buflist[iload.idx]; buf_priv = buf->dev_private; if (mga_verify_iload(dev_priv, iload.dstorg, iload.length)) { mga_freelist_put(dev, buf); return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN(dev_priv); mga_dma_dispatch_iload(dev, buf, iload.dstorg, iload.length); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; return 0; } static int mga_dma_blit(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_blit_t blit; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(blit, (drm_mga_blit_t __user *) data, sizeof(blit)); if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; if (mga_verify_blit(dev_priv, blit.srcorg, blit.dstorg)) return DRM_ERR(EINVAL); WRAP_TEST_WITH_RETURN(dev_priv); mga_dma_dispatch_blit(dev, &blit); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; return 0; } static int mga_getparam(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_getparam_t param; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(param, (drm_mga_getparam_t __user *) data, sizeof(param)); DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); switch (param.param) { case MGA_PARAM_IRQ_NR: value = dev->irq; break; + case MGA_PARAM_CARD_TYPE: + value = dev_priv->chipset; + break; default: return DRM_ERR(EINVAL); } if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; } +static int mga_set_fence(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_mga_private_t *dev_priv = dev->dev_private; + u32 temp; + DMA_LOCALS; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + return DRM_ERR(EINVAL); + } + + DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); + + /* I would normal do this assignment in the declaration of temp, + * but dev_priv may be NULL. + */ + + temp = dev_priv->next_fence_to_post; + dev_priv->next_fence_to_post++; + + BEGIN_DMA(1); + DMA_BLOCK(MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_SOFTRAP, 0x00000000); + ADVANCE_DMA(); + + DRM_COPY_TO_USER_IOCTL((u32 __user *)data, temp, sizeof(u32)); + + return 0; +} + +static int mga_wait_fence(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_mga_private_t *dev_priv = dev->dev_private; + u32 fence; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32)); + + DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); + + mga_driver_fence_wait(dev, & fence); + + DRM_COPY_TO_USER_IOCTL((u32 __user *)data, fence, sizeof(u32)); + + return 0; +} + drm_ioctl_desc_t mga_ioctls[] = { - [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, 1, 1}, - [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, 1, 0}, - [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, 1, 0}, - [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, 1, 0}, - [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, 1, 0}, - [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, 1, 0}, - [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, 1, 0}, - [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, 1, 0}, - [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, 1, 0}, - [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, 1, 0}, + [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + }; int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); Index: head/sys/dev/drm/mga_ucode.h =================================================================== --- head/sys/dev/drm/mga_ucode.h (revision 152908) +++ head/sys/dev/drm/mga_ucode.h (revision 152909) @@ -1,11647 +1,11648 @@ /* mga_ucode.h -- Matrox G200/G400 WARP engine microcode -*- linux-c -*- - * Created: Thu Jan 11 21:20:43 2001 by gareth@valinux.com */ -/*- + * Created: Thu Jan 11 21:20:43 2001 by gareth@valinux.com + * * Copyright 1999 Matrox Graphics Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * MATROX GRAPHICS INC., OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Kernel-based WARP engine management: * Gareth Hughes - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); /* * WARP pipes are named according to the functions they perform, where: * * - T stands for computation of texture stage 0 * - T2 stands for computation of both texture stage 0 and texture stage 1 * - G stands for computation of triangle intensity (Gouraud interpolation) * - Z stands for computation of Z buffer interpolation * - S stands for computation of specular highlight * - A stands for computation of the alpha channel * - F stands for computation of vertex fog interpolation */ static unsigned char warp_g200_tgz[] = { 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x98, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x81, 0x04, 0x89, 0x04, 0x01, 0x04, 0x09, 0x04, 0xC9, 0x41, 0xC0, 0xEC, 0x11, 0x04, 0x00, 0xE0, 0x41, 0xCC, 0x41, 0xCD, 0x49, 0xCC, 0x49, 0xCD, 0xD1, 0x41, 0xC0, 0xEC, 0x51, 0xCC, 0x51, 0xCD, 0x80, 0x04, 0x10, 0x04, 0x08, 0x04, 0x00, 0xE0, 0x00, 0xCC, 0xC0, 0xCD, 0xD1, 0x49, 0xC0, 0xEC, 0x8A, 0x1F, 0x20, 0xE9, 0x8B, 0x3F, 0x20, 0xE9, 0x41, 0x3C, 0x41, 0xAD, 0x49, 0x3C, 0x49, 0xAD, 0x10, 0xCC, 0x10, 0xCD, 0x08, 0xCC, 0x08, 0xCD, 0xB9, 0x41, 0x49, 0xBB, 0x1F, 0xF0, 0x41, 0xCD, 0x51, 0x3C, 0x51, 0xAD, 0x00, 0x98, 0x80, 0xE9, 0x72, 0x80, 0x07, 0xEA, 0x24, 0x1F, 0x20, 0xE9, 0x15, 0x41, 0x49, 0xBD, 0x1D, 0x41, 0x51, 0xBD, 0x2E, 0x41, 0x2A, 0xB8, 0x34, 0x53, 0xA0, 0xE8, 0x15, 0x30, 0x1D, 0x30, 0x58, 0xE3, 0x00, 0xE0, 0xB5, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x24, 0x43, 0xA0, 0xE8, 0x2C, 0x4B, 0xA0, 0xE8, 0x15, 0x72, 0x09, 0xE3, 0x00, 0xE0, 0x1D, 0x72, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0x97, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x6C, 0x64, 0xC8, 0xEC, 0x98, 0xE1, 0xB5, 0x05, 0xBD, 0x05, 0x2E, 0x30, 0x32, 0xC0, 0xA0, 0xE8, 0x33, 0xC0, 0xA0, 0xE8, 0x74, 0x64, 0xC8, 0xEC, 0x40, 0x3C, 0x40, 0xAD, 0x32, 0x6A, 0x2A, 0x30, 0x20, 0x73, 0x33, 0x6A, 0x00, 0xE0, 0x28, 0x73, 0x1C, 0x72, 0x83, 0xE2, 0x60, 0x80, 0x15, 0xEA, 0xB8, 0x3D, 0x28, 0xDF, 0x30, 0x35, 0x20, 0xDF, 0x40, 0x30, 0x00, 0xE0, 0xCC, 0xE2, 0x64, 0x72, 0x25, 0x42, 0x52, 0xBF, 0x2D, 0x42, 0x4A, 0xBF, 0x30, 0x2E, 0x30, 0xDF, 0x38, 0x2E, 0x38, 0xDF, 0x18, 0x1D, 0x45, 0xE9, 0x1E, 0x15, 0x45, 0xE9, 0x2B, 0x49, 0x51, 0xBD, 0x00, 0xE0, 0x1F, 0x73, 0x38, 0x38, 0x40, 0xAF, 0x30, 0x30, 0x40, 0xAF, 0x24, 0x1F, 0x24, 0xDF, 0x1D, 0x32, 0x20, 0xE9, 0x2C, 0x1F, 0x2C, 0xDF, 0x1A, 0x33, 0x20, 0xE9, 0xB0, 0x10, 0x08, 0xE3, 0x40, 0x10, 0xB8, 0x10, 0x26, 0xF0, 0x30, 0xCD, 0x2F, 0xF0, 0x38, 0xCD, 0x2B, 0x80, 0x20, 0xE9, 0x2A, 0x80, 0x20, 0xE9, 0xA6, 0x20, 0x88, 0xE2, 0x00, 0xE0, 0xAF, 0x20, 0x28, 0x2A, 0x26, 0xAF, 0x20, 0x2A, 0xC0, 0xAF, 0x34, 0x1F, 0x34, 0xDF, 0x46, 0x24, 0x46, 0xDF, 0x28, 0x30, 0x80, 0xBF, 0x20, 0x38, 0x80, 0xBF, 0x47, 0x24, 0x47, 0xDF, 0x4E, 0x2C, 0x4E, 0xDF, 0x4F, 0x2C, 0x4F, 0xDF, 0x56, 0x34, 0x56, 0xDF, 0x28, 0x15, 0x28, 0xDF, 0x20, 0x1D, 0x20, 0xDF, 0x57, 0x34, 0x57, 0xDF, 0x00, 0xE0, 0x1D, 0x05, 0x04, 0x80, 0x10, 0xEA, 0x89, 0xE2, 0x2B, 0x30, 0x3F, 0xC1, 0x1D, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x68, 0xBF, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x20, 0xC0, 0x20, 0xAF, 0x28, 0x05, 0x97, 0x74, 0x00, 0xE0, 0x2A, 0x10, 0x16, 0xC0, 0x20, 0xE9, 0x04, 0x80, 0x10, 0xEA, 0x8C, 0xE2, 0x95, 0x05, 0x28, 0xC1, 0x28, 0xAD, 0x1F, 0xC1, 0x15, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA8, 0x67, 0x9F, 0x6B, 0x00, 0x80, 0x00, 0xE8, 0x28, 0xC0, 0x28, 0xAD, 0x1D, 0x25, 0x20, 0x05, 0x28, 0x32, 0x80, 0xAD, 0x40, 0x2A, 0x40, 0xBD, 0x1C, 0x80, 0x20, 0xE9, 0x20, 0x33, 0x20, 0xAD, 0x20, 0x73, 0x00, 0xE0, 0xB6, 0x49, 0x51, 0xBB, 0x26, 0x2F, 0xB0, 0xE8, 0x19, 0x20, 0x20, 0xE9, 0x35, 0x20, 0x35, 0xDF, 0x3D, 0x20, 0x3D, 0xDF, 0x15, 0x20, 0x15, 0xDF, 0x1D, 0x20, 0x1D, 0xDF, 0x26, 0xD0, 0x26, 0xCD, 0x29, 0x49, 0x2A, 0xB8, 0x26, 0x40, 0x80, 0xBD, 0x3B, 0x48, 0x50, 0xBD, 0x3E, 0x54, 0x57, 0x9F, 0x00, 0xE0, 0x82, 0xE1, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x26, 0x30, 0x29, 0x30, 0x48, 0x3C, 0x48, 0xAD, 0x2B, 0x72, 0xC2, 0xE1, 0x2C, 0xC0, 0x44, 0xC2, 0x05, 0x24, 0x34, 0xBF, 0x0D, 0x24, 0x2C, 0xBF, 0x2D, 0x46, 0x4E, 0xBF, 0x25, 0x46, 0x56, 0xBF, 0x20, 0x1D, 0x6F, 0x8F, 0x32, 0x3E, 0x5F, 0xE9, 0x3E, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x30, 0x1E, 0x8F, 0x51, 0x9F, 0x33, 0x1E, 0x5F, 0xE9, 0x05, 0x44, 0x54, 0xB2, 0x0D, 0x44, 0x4C, 0xB2, 0x19, 0xC0, 0xB0, 0xE8, 0x34, 0xC0, 0x44, 0xC4, 0x33, 0x73, 0x00, 0xE0, 0x3E, 0x62, 0x57, 0x9F, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0xE0, 0x0D, 0x20, 0x84, 0x3E, 0x58, 0xE9, 0x28, 0x1D, 0x6F, 0x8F, 0x05, 0x20, 0x00, 0xE0, 0x85, 0x1E, 0x58, 0xE9, 0x9B, 0x3B, 0x33, 0xDF, 0x20, 0x20, 0x42, 0xAF, 0x30, 0x42, 0x56, 0x9F, 0x80, 0x3E, 0x57, 0xE9, 0x3F, 0x8F, 0x51, 0x9F, 0x30, 0x80, 0x5F, 0xE9, 0x28, 0x28, 0x24, 0xAF, 0x81, 0x1E, 0x57, 0xE9, 0x05, 0x47, 0x57, 0xBF, 0x0D, 0x47, 0x4F, 0xBF, 0x88, 0x80, 0x58, 0xE9, 0x1B, 0x29, 0x1B, 0xDF, 0x30, 0x1D, 0x6F, 0x8F, 0x3A, 0x30, 0x4F, 0xE9, 0x1C, 0x30, 0x26, 0xDF, 0x09, 0xE3, 0x3B, 0x05, 0x3E, 0x50, 0x56, 0x9F, 0x3B, 0x3F, 0x4F, 0xE9, 0x1E, 0x8F, 0x51, 0x9F, 0x00, 0xE0, 0xAC, 0x20, 0x2D, 0x44, 0x4C, 0xB4, 0x2C, 0x1C, 0xC0, 0xAF, 0x25, 0x44, 0x54, 0xB4, 0x00, 0xE0, 0xC8, 0x30, 0x30, 0x46, 0x30, 0xAF, 0x1B, 0x1B, 0x48, 0xAF, 0x00, 0xE0, 0x25, 0x20, 0x38, 0x2C, 0x4F, 0xE9, 0x86, 0x80, 0x57, 0xE9, 0x38, 0x1D, 0x6F, 0x8F, 0x28, 0x74, 0x00, 0xE0, 0x0D, 0x44, 0x4C, 0xB0, 0x05, 0x44, 0x54, 0xB0, 0x2D, 0x20, 0x9B, 0x10, 0x82, 0x3E, 0x57, 0xE9, 0x32, 0xF0, 0x1B, 0xCD, 0x1E, 0xBD, 0x59, 0x9F, 0x83, 0x1E, 0x57, 0xE9, 0x38, 0x47, 0x38, 0xAF, 0x34, 0x20, 0x2A, 0x30, 0x00, 0xE0, 0x0D, 0x20, 0x32, 0x20, 0x05, 0x20, 0x87, 0x80, 0x57, 0xE9, 0x1F, 0x54, 0x57, 0x9F, 0x17, 0x42, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x6A, 0x3F, 0x8F, 0x51, 0x9F, 0x37, 0x1E, 0x4F, 0xE9, 0x37, 0x32, 0x2A, 0xAF, 0x00, 0xE0, 0x32, 0x00, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xC0, 0x44, 0xC0, 0x36, 0x1F, 0x4F, 0xE9, 0x1F, 0x1F, 0x26, 0xDF, 0x37, 0x1B, 0x37, 0xBF, 0x17, 0x26, 0x17, 0xDF, 0x3E, 0x17, 0x4F, 0xE9, 0x3F, 0x3F, 0x4F, 0xE9, 0x34, 0x1F, 0x34, 0xAF, 0x2B, 0x05, 0xA7, 0x20, 0x33, 0x2B, 0x37, 0xDF, 0x27, 0x17, 0xC0, 0xAF, 0x34, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x03, 0x80, 0x0A, 0xEA, 0x17, 0xC1, 0x2B, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xB3, 0x68, 0x97, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x33, 0xC0, 0x33, 0xAF, 0x3C, 0x27, 0x4F, 0xE9, 0x57, 0x39, 0x20, 0xE9, 0x28, 0x19, 0x60, 0xEC, 0x2B, 0x32, 0x20, 0xE9, 0x1D, 0x3B, 0x20, 0xE9, 0xB3, 0x05, 0x00, 0xE0, 0x16, 0x28, 0x20, 0xE9, 0x23, 0x3B, 0x33, 0xAD, 0x1E, 0x2B, 0x20, 0xE9, 0x1C, 0x80, 0x20, 0xE9, 0x57, 0x36, 0x20, 0xE9, 0x00, 0x80, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x90, 0xE2, 0x00, 0xE0, 0x85, 0xFF, 0x20, 0xEA, 0x19, 0xC8, 0xC1, 0xCD, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x9F, 0x41, 0x49, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x41, 0x49, 0xBD, 0x2D, 0x41, 0x51, 0xBD, 0x0D, 0x80, 0x07, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x35, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x30, 0x2D, 0x30, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0xA7, 0x5B, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x84, 0xFF, 0x0A, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0xC9, 0x41, 0xC8, 0xEC, 0x42, 0xE1, 0x00, 0xE0, 0x82, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xC8, 0x40, 0xC0, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x7F, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, }; static unsigned char warp_g200_tgza[] = { 0x00, 0x98, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x81, 0x04, 0x89, 0x04, 0x01, 0x04, 0x09, 0x04, 0xC9, 0x41, 0xC0, 0xEC, 0x11, 0x04, 0x00, 0xE0, 0x41, 0xCC, 0x41, 0xCD, 0x49, 0xCC, 0x49, 0xCD, 0xD1, 0x41, 0xC0, 0xEC, 0x51, 0xCC, 0x51, 0xCD, 0x80, 0x04, 0x10, 0x04, 0x08, 0x04, 0x00, 0xE0, 0x00, 0xCC, 0xC0, 0xCD, 0xD1, 0x49, 0xC0, 0xEC, 0x8A, 0x1F, 0x20, 0xE9, 0x8B, 0x3F, 0x20, 0xE9, 0x41, 0x3C, 0x41, 0xAD, 0x49, 0x3C, 0x49, 0xAD, 0x10, 0xCC, 0x10, 0xCD, 0x08, 0xCC, 0x08, 0xCD, 0xB9, 0x41, 0x49, 0xBB, 0x1F, 0xF0, 0x41, 0xCD, 0x51, 0x3C, 0x51, 0xAD, 0x00, 0x98, 0x80, 0xE9, 0x7D, 0x80, 0x07, 0xEA, 0x24, 0x1F, 0x20, 0xE9, 0x15, 0x41, 0x49, 0xBD, 0x1D, 0x41, 0x51, 0xBD, 0x2E, 0x41, 0x2A, 0xB8, 0x34, 0x53, 0xA0, 0xE8, 0x15, 0x30, 0x1D, 0x30, 0x58, 0xE3, 0x00, 0xE0, 0xB5, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x24, 0x43, 0xA0, 0xE8, 0x2C, 0x4B, 0xA0, 0xE8, 0x15, 0x72, 0x09, 0xE3, 0x00, 0xE0, 0x1D, 0x72, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0x97, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x6C, 0x64, 0xC8, 0xEC, 0x98, 0xE1, 0xB5, 0x05, 0xBD, 0x05, 0x2E, 0x30, 0x32, 0xC0, 0xA0, 0xE8, 0x33, 0xC0, 0xA0, 0xE8, 0x74, 0x64, 0xC8, 0xEC, 0x40, 0x3C, 0x40, 0xAD, 0x32, 0x6A, 0x2A, 0x30, 0x20, 0x73, 0x33, 0x6A, 0x00, 0xE0, 0x28, 0x73, 0x1C, 0x72, 0x83, 0xE2, 0x6B, 0x80, 0x15, 0xEA, 0xB8, 0x3D, 0x28, 0xDF, 0x30, 0x35, 0x20, 0xDF, 0x40, 0x30, 0x00, 0xE0, 0xCC, 0xE2, 0x64, 0x72, 0x25, 0x42, 0x52, 0xBF, 0x2D, 0x42, 0x4A, 0xBF, 0x30, 0x2E, 0x30, 0xDF, 0x38, 0x2E, 0x38, 0xDF, 0x18, 0x1D, 0x45, 0xE9, 0x1E, 0x15, 0x45, 0xE9, 0x2B, 0x49, 0x51, 0xBD, 0x00, 0xE0, 0x1F, 0x73, 0x38, 0x38, 0x40, 0xAF, 0x30, 0x30, 0x40, 0xAF, 0x24, 0x1F, 0x24, 0xDF, 0x1D, 0x32, 0x20, 0xE9, 0x2C, 0x1F, 0x2C, 0xDF, 0x1A, 0x33, 0x20, 0xE9, 0xB0, 0x10, 0x08, 0xE3, 0x40, 0x10, 0xB8, 0x10, 0x26, 0xF0, 0x30, 0xCD, 0x2F, 0xF0, 0x38, 0xCD, 0x2B, 0x80, 0x20, 0xE9, 0x2A, 0x80, 0x20, 0xE9, 0xA6, 0x20, 0x88, 0xE2, 0x00, 0xE0, 0xAF, 0x20, 0x28, 0x2A, 0x26, 0xAF, 0x20, 0x2A, 0xC0, 0xAF, 0x34, 0x1F, 0x34, 0xDF, 0x46, 0x24, 0x46, 0xDF, 0x28, 0x30, 0x80, 0xBF, 0x20, 0x38, 0x80, 0xBF, 0x47, 0x24, 0x47, 0xDF, 0x4E, 0x2C, 0x4E, 0xDF, 0x4F, 0x2C, 0x4F, 0xDF, 0x56, 0x34, 0x56, 0xDF, 0x28, 0x15, 0x28, 0xDF, 0x20, 0x1D, 0x20, 0xDF, 0x57, 0x34, 0x57, 0xDF, 0x00, 0xE0, 0x1D, 0x05, 0x04, 0x80, 0x10, 0xEA, 0x89, 0xE2, 0x2B, 0x30, 0x3F, 0xC1, 0x1D, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x68, 0xBF, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x20, 0xC0, 0x20, 0xAF, 0x28, 0x05, 0x97, 0x74, 0x00, 0xE0, 0x2A, 0x10, 0x16, 0xC0, 0x20, 0xE9, 0x04, 0x80, 0x10, 0xEA, 0x8C, 0xE2, 0x95, 0x05, 0x28, 0xC1, 0x28, 0xAD, 0x1F, 0xC1, 0x15, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA8, 0x67, 0x9F, 0x6B, 0x00, 0x80, 0x00, 0xE8, 0x28, 0xC0, 0x28, 0xAD, 0x1D, 0x25, 0x20, 0x05, 0x28, 0x32, 0x80, 0xAD, 0x40, 0x2A, 0x40, 0xBD, 0x1C, 0x80, 0x20, 0xE9, 0x20, 0x33, 0x20, 0xAD, 0x20, 0x73, 0x00, 0xE0, 0xB6, 0x49, 0x51, 0xBB, 0x26, 0x2F, 0xB0, 0xE8, 0x19, 0x20, 0x20, 0xE9, 0x35, 0x20, 0x35, 0xDF, 0x3D, 0x20, 0x3D, 0xDF, 0x15, 0x20, 0x15, 0xDF, 0x1D, 0x20, 0x1D, 0xDF, 0x26, 0xD0, 0x26, 0xCD, 0x29, 0x49, 0x2A, 0xB8, 0x26, 0x40, 0x80, 0xBD, 0x3B, 0x48, 0x50, 0xBD, 0x3E, 0x54, 0x57, 0x9F, 0x00, 0xE0, 0x82, 0xE1, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x26, 0x30, 0x29, 0x30, 0x48, 0x3C, 0x48, 0xAD, 0x2B, 0x72, 0xC2, 0xE1, 0x2C, 0xC0, 0x44, 0xC2, 0x05, 0x24, 0x34, 0xBF, 0x0D, 0x24, 0x2C, 0xBF, 0x2D, 0x46, 0x4E, 0xBF, 0x25, 0x46, 0x56, 0xBF, 0x20, 0x1D, 0x6F, 0x8F, 0x32, 0x3E, 0x5F, 0xE9, 0x3E, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x30, 0x1E, 0x8F, 0x51, 0x9F, 0x33, 0x1E, 0x5F, 0xE9, 0x05, 0x44, 0x54, 0xB2, 0x0D, 0x44, 0x4C, 0xB2, 0x19, 0xC0, 0xB0, 0xE8, 0x34, 0xC0, 0x44, 0xC4, 0x33, 0x73, 0x00, 0xE0, 0x3E, 0x62, 0x57, 0x9F, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0xE0, 0x0D, 0x20, 0x84, 0x3E, 0x58, 0xE9, 0x28, 0x1D, 0x6F, 0x8F, 0x05, 0x20, 0x00, 0xE0, 0x85, 0x1E, 0x58, 0xE9, 0x9B, 0x3B, 0x33, 0xDF, 0x20, 0x20, 0x42, 0xAF, 0x30, 0x42, 0x56, 0x9F, 0x80, 0x3E, 0x57, 0xE9, 0x3F, 0x8F, 0x51, 0x9F, 0x30, 0x80, 0x5F, 0xE9, 0x28, 0x28, 0x24, 0xAF, 0x81, 0x1E, 0x57, 0xE9, 0x05, 0x47, 0x57, 0xBF, 0x0D, 0x47, 0x4F, 0xBF, 0x88, 0x80, 0x58, 0xE9, 0x1B, 0x29, 0x1B, 0xDF, 0x30, 0x1D, 0x6F, 0x8F, 0x3A, 0x30, 0x4F, 0xE9, 0x1C, 0x30, 0x26, 0xDF, 0x09, 0xE3, 0x3B, 0x05, 0x3E, 0x50, 0x56, 0x9F, 0x3B, 0x3F, 0x4F, 0xE9, 0x1E, 0x8F, 0x51, 0x9F, 0x00, 0xE0, 0xAC, 0x20, 0x2D, 0x44, 0x4C, 0xB4, 0x2C, 0x1C, 0xC0, 0xAF, 0x25, 0x44, 0x54, 0xB4, 0x00, 0xE0, 0xC8, 0x30, 0x30, 0x46, 0x30, 0xAF, 0x1B, 0x1B, 0x48, 0xAF, 0x00, 0xE0, 0x25, 0x20, 0x38, 0x2C, 0x4F, 0xE9, 0x86, 0x80, 0x57, 0xE9, 0x38, 0x1D, 0x6F, 0x8F, 0x28, 0x74, 0x00, 0xE0, 0x0D, 0x44, 0x4C, 0xB0, 0x05, 0x44, 0x54, 0xB0, 0x2D, 0x20, 0x9B, 0x10, 0x82, 0x3E, 0x57, 0xE9, 0x32, 0xF0, 0x1B, 0xCD, 0x1E, 0xBD, 0x59, 0x9F, 0x83, 0x1E, 0x57, 0xE9, 0x38, 0x47, 0x38, 0xAF, 0x34, 0x20, 0x2A, 0x30, 0x00, 0xE0, 0x0D, 0x20, 0x32, 0x20, 0x05, 0x20, 0x87, 0x80, 0x57, 0xE9, 0x1F, 0x54, 0x57, 0x9F, 0x17, 0x42, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x6A, 0x3F, 0x8F, 0x51, 0x9F, 0x37, 0x1E, 0x4F, 0xE9, 0x37, 0x32, 0x2A, 0xAF, 0x00, 0xE0, 0x32, 0x00, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xC0, 0x44, 0xC0, 0x36, 0x1F, 0x4F, 0xE9, 0x1F, 0x1F, 0x26, 0xDF, 0x37, 0x1B, 0x37, 0xBF, 0x17, 0x26, 0x17, 0xDF, 0x3E, 0x17, 0x4F, 0xE9, 0x3F, 0x3F, 0x4F, 0xE9, 0x34, 0x1F, 0x34, 0xAF, 0x2B, 0x05, 0xA7, 0x20, 0x33, 0x2B, 0x37, 0xDF, 0x27, 0x17, 0xC0, 0xAF, 0x34, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2D, 0x44, 0x4C, 0xB6, 0x25, 0x44, 0x54, 0xB6, 0x03, 0x80, 0x2A, 0xEA, 0x17, 0xC1, 0x2B, 0xBD, 0x2D, 0x20, 0x25, 0x20, 0x07, 0xC0, 0x44, 0xC6, 0xB3, 0x68, 0x97, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x33, 0xC0, 0x33, 0xAF, 0x3C, 0x27, 0x4F, 0xE9, 0x1F, 0x62, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x3F, 0x3D, 0x5D, 0x9F, 0x00, 0xE0, 0x07, 0x20, 0x00, 0x80, 0x00, 0xE8, 0x28, 0x19, 0x60, 0xEC, 0xB3, 0x05, 0x00, 0xE0, 0x00, 0x80, 0x00, 0xE8, 0x23, 0x3B, 0x33, 0xAD, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0x26, 0x1F, 0xDF, 0x9D, 0x1F, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x9E, 0x3F, 0x4F, 0xE9, 0x07, 0x07, 0x1F, 0xAF, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x9C, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x57, 0x39, 0x20, 0xE9, 0x16, 0x28, 0x20, 0xE9, 0x1D, 0x3B, 0x20, 0xE9, 0x1E, 0x2B, 0x20, 0xE9, 0x2B, 0x32, 0x20, 0xE9, 0x1C, 0x23, 0x20, 0xE9, 0x57, 0x36, 0x20, 0xE9, 0x00, 0x80, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x90, 0xE2, 0x00, 0xE0, 0x7A, 0xFF, 0x20, 0xEA, 0x19, 0xC8, 0xC1, 0xCD, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x9F, 0x41, 0x49, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x41, 0x49, 0xBD, 0x2D, 0x41, 0x51, 0xBD, 0x0D, 0x80, 0x07, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x35, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x30, 0x2D, 0x30, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0xA7, 0x5B, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x79, 0xFF, 0x0A, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0xC9, 0x41, 0xC8, 0xEC, 0x42, 0xE1, 0x00, 0xE0, 0x77, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xC8, 0x40, 0xC0, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x74, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, }; static unsigned char warp_g200_tgzaf[] = { 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x98, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x81, 0x04, 0x89, 0x04, 0x01, 0x04, 0x09, 0x04, 0xC9, 0x41, 0xC0, 0xEC, 0x11, 0x04, 0x00, 0xE0, 0x41, 0xCC, 0x41, 0xCD, 0x49, 0xCC, 0x49, 0xCD, 0xD1, 0x41, 0xC0, 0xEC, 0x51, 0xCC, 0x51, 0xCD, 0x80, 0x04, 0x10, 0x04, 0x08, 0x04, 0x00, 0xE0, 0x00, 0xCC, 0xC0, 0xCD, 0xD1, 0x49, 0xC0, 0xEC, 0x8A, 0x1F, 0x20, 0xE9, 0x8B, 0x3F, 0x20, 0xE9, 0x41, 0x3C, 0x41, 0xAD, 0x49, 0x3C, 0x49, 0xAD, 0x10, 0xCC, 0x10, 0xCD, 0x08, 0xCC, 0x08, 0xCD, 0xB9, 0x41, 0x49, 0xBB, 0x1F, 0xF0, 0x41, 0xCD, 0x51, 0x3C, 0x51, 0xAD, 0x00, 0x98, 0x80, 0xE9, 0x83, 0x80, 0x07, 0xEA, 0x24, 0x1F, 0x20, 0xE9, 0x21, 0x45, 0x80, 0xE8, 0x1A, 0x4D, 0x80, 0xE8, 0x31, 0x55, 0x80, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0x41, 0x49, 0xBD, 0x1D, 0x41, 0x51, 0xBD, 0x2E, 0x41, 0x2A, 0xB8, 0x34, 0x53, 0xA0, 0xE8, 0x15, 0x30, 0x1D, 0x30, 0x58, 0xE3, 0x00, 0xE0, 0xB5, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x24, 0x43, 0xA0, 0xE8, 0x2C, 0x4B, 0xA0, 0xE8, 0x15, 0x72, 0x09, 0xE3, 0x00, 0xE0, 0x1D, 0x72, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0x97, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x6C, 0x64, 0xC8, 0xEC, 0x98, 0xE1, 0xB5, 0x05, 0xBD, 0x05, 0x2E, 0x30, 0x32, 0xC0, 0xA0, 0xE8, 0x33, 0xC0, 0xA0, 0xE8, 0x74, 0x64, 0xC8, 0xEC, 0x40, 0x3C, 0x40, 0xAD, 0x32, 0x6A, 0x2A, 0x30, 0x20, 0x73, 0x33, 0x6A, 0x00, 0xE0, 0x28, 0x73, 0x1C, 0x72, 0x83, 0xE2, 0x6F, 0x80, 0x15, 0xEA, 0xB8, 0x3D, 0x28, 0xDF, 0x30, 0x35, 0x20, 0xDF, 0x40, 0x30, 0x00, 0xE0, 0xCC, 0xE2, 0x64, 0x72, 0x25, 0x42, 0x52, 0xBF, 0x2D, 0x42, 0x4A, 0xBF, 0x30, 0x2E, 0x30, 0xDF, 0x38, 0x2E, 0x38, 0xDF, 0x18, 0x1D, 0x45, 0xE9, 0x1E, 0x15, 0x45, 0xE9, 0x2B, 0x49, 0x51, 0xBD, 0x00, 0xE0, 0x1F, 0x73, 0x38, 0x38, 0x40, 0xAF, 0x30, 0x30, 0x40, 0xAF, 0x24, 0x1F, 0x24, 0xDF, 0x1D, 0x32, 0x20, 0xE9, 0x2C, 0x1F, 0x2C, 0xDF, 0x1A, 0x33, 0x20, 0xE9, 0xB0, 0x10, 0x08, 0xE3, 0x40, 0x10, 0xB8, 0x10, 0x26, 0xF0, 0x30, 0xCD, 0x2F, 0xF0, 0x38, 0xCD, 0x2B, 0x80, 0x20, 0xE9, 0x2A, 0x80, 0x20, 0xE9, 0xA6, 0x20, 0x88, 0xE2, 0x00, 0xE0, 0xAF, 0x20, 0x28, 0x2A, 0x26, 0xAF, 0x20, 0x2A, 0xC0, 0xAF, 0x34, 0x1F, 0x34, 0xDF, 0x46, 0x24, 0x46, 0xDF, 0x28, 0x30, 0x80, 0xBF, 0x20, 0x38, 0x80, 0xBF, 0x47, 0x24, 0x47, 0xDF, 0x4E, 0x2C, 0x4E, 0xDF, 0x4F, 0x2C, 0x4F, 0xDF, 0x56, 0x34, 0x56, 0xDF, 0x28, 0x15, 0x28, 0xDF, 0x20, 0x1D, 0x20, 0xDF, 0x57, 0x34, 0x57, 0xDF, 0x00, 0xE0, 0x1D, 0x05, 0x04, 0x80, 0x10, 0xEA, 0x89, 0xE2, 0x2B, 0x30, 0x3F, 0xC1, 0x1D, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x68, 0xBF, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x20, 0xC0, 0x20, 0xAF, 0x28, 0x05, 0x97, 0x74, 0x00, 0xE0, 0x2A, 0x10, 0x16, 0xC0, 0x20, 0xE9, 0x04, 0x80, 0x10, 0xEA, 0x8C, 0xE2, 0x95, 0x05, 0x28, 0xC1, 0x28, 0xAD, 0x1F, 0xC1, 0x15, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA8, 0x67, 0x9F, 0x6B, 0x00, 0x80, 0x00, 0xE8, 0x28, 0xC0, 0x28, 0xAD, 0x1D, 0x25, 0x20, 0x05, 0x28, 0x32, 0x80, 0xAD, 0x40, 0x2A, 0x40, 0xBD, 0x1C, 0x80, 0x20, 0xE9, 0x20, 0x33, 0x20, 0xAD, 0x20, 0x73, 0x00, 0xE0, 0xB6, 0x49, 0x51, 0xBB, 0x26, 0x2F, 0xB0, 0xE8, 0x19, 0x20, 0x20, 0xE9, 0x35, 0x20, 0x35, 0xDF, 0x3D, 0x20, 0x3D, 0xDF, 0x15, 0x20, 0x15, 0xDF, 0x1D, 0x20, 0x1D, 0xDF, 0x26, 0xD0, 0x26, 0xCD, 0x29, 0x49, 0x2A, 0xB8, 0x26, 0x40, 0x80, 0xBD, 0x3B, 0x48, 0x50, 0xBD, 0x3E, 0x54, 0x57, 0x9F, 0x00, 0xE0, 0x82, 0xE1, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x26, 0x30, 0x29, 0x30, 0x48, 0x3C, 0x48, 0xAD, 0x2B, 0x72, 0xC2, 0xE1, 0x2C, 0xC0, 0x44, 0xC2, 0x05, 0x24, 0x34, 0xBF, 0x0D, 0x24, 0x2C, 0xBF, 0x2D, 0x46, 0x4E, 0xBF, 0x25, 0x46, 0x56, 0xBF, 0x20, 0x1D, 0x6F, 0x8F, 0x32, 0x3E, 0x5F, 0xE9, 0x3E, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x30, 0x1E, 0x8F, 0x51, 0x9F, 0x33, 0x1E, 0x5F, 0xE9, 0x05, 0x44, 0x54, 0xB2, 0x0D, 0x44, 0x4C, 0xB2, 0x19, 0xC0, 0xB0, 0xE8, 0x34, 0xC0, 0x44, 0xC4, 0x33, 0x73, 0x00, 0xE0, 0x3E, 0x62, 0x57, 0x9F, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0xE0, 0x0D, 0x20, 0x84, 0x3E, 0x58, 0xE9, 0x28, 0x1D, 0x6F, 0x8F, 0x05, 0x20, 0x00, 0xE0, 0x85, 0x1E, 0x58, 0xE9, 0x9B, 0x3B, 0x33, 0xDF, 0x20, 0x20, 0x42, 0xAF, 0x30, 0x42, 0x56, 0x9F, 0x80, 0x3E, 0x57, 0xE9, 0x3F, 0x8F, 0x51, 0x9F, 0x30, 0x80, 0x5F, 0xE9, 0x28, 0x28, 0x24, 0xAF, 0x81, 0x1E, 0x57, 0xE9, 0x05, 0x47, 0x57, 0xBF, 0x0D, 0x47, 0x4F, 0xBF, 0x88, 0x80, 0x58, 0xE9, 0x1B, 0x29, 0x1B, 0xDF, 0x30, 0x1D, 0x6F, 0x8F, 0x3A, 0x30, 0x4F, 0xE9, 0x1C, 0x30, 0x26, 0xDF, 0x09, 0xE3, 0x3B, 0x05, 0x3E, 0x50, 0x56, 0x9F, 0x3B, 0x3F, 0x4F, 0xE9, 0x1E, 0x8F, 0x51, 0x9F, 0x00, 0xE0, 0xAC, 0x20, 0x2D, 0x44, 0x4C, 0xB4, 0x2C, 0x1C, 0xC0, 0xAF, 0x25, 0x44, 0x54, 0xB4, 0x00, 0xE0, 0xC8, 0x30, 0x30, 0x46, 0x30, 0xAF, 0x1B, 0x1B, 0x48, 0xAF, 0x00, 0xE0, 0x25, 0x20, 0x38, 0x2C, 0x4F, 0xE9, 0x86, 0x80, 0x57, 0xE9, 0x38, 0x1D, 0x6F, 0x8F, 0x28, 0x74, 0x00, 0xE0, 0x0D, 0x44, 0x4C, 0xB0, 0x05, 0x44, 0x54, 0xB0, 0x2D, 0x20, 0x9B, 0x10, 0x82, 0x3E, 0x57, 0xE9, 0x32, 0xF0, 0x1B, 0xCD, 0x1E, 0xBD, 0x59, 0x9F, 0x83, 0x1E, 0x57, 0xE9, 0x38, 0x47, 0x38, 0xAF, 0x34, 0x20, 0x2A, 0x30, 0x00, 0xE0, 0x0D, 0x20, 0x32, 0x20, 0x05, 0x20, 0x87, 0x80, 0x57, 0xE9, 0x1F, 0x54, 0x57, 0x9F, 0x17, 0x42, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x6A, 0x3F, 0x8F, 0x51, 0x9F, 0x37, 0x1E, 0x4F, 0xE9, 0x37, 0x32, 0x2A, 0xAF, 0x00, 0xE0, 0x32, 0x00, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xC0, 0x44, 0xC0, 0x36, 0x1F, 0x4F, 0xE9, 0x1F, 0x1F, 0x26, 0xDF, 0x37, 0x1B, 0x37, 0xBF, 0x17, 0x26, 0x17, 0xDF, 0x3E, 0x17, 0x4F, 0xE9, 0x3F, 0x3F, 0x4F, 0xE9, 0x34, 0x1F, 0x34, 0xAF, 0x2B, 0x05, 0xA7, 0x20, 0x33, 0x2B, 0x37, 0xDF, 0x27, 0x17, 0xC0, 0xAF, 0x34, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0D, 0x21, 0x1A, 0xB6, 0x05, 0x21, 0x31, 0xB6, 0x2D, 0x44, 0x4C, 0xB6, 0x25, 0x44, 0x54, 0xB6, 0x03, 0x80, 0x2A, 0xEA, 0x17, 0xC1, 0x2B, 0xBD, 0x0D, 0x20, 0x05, 0x20, 0x2F, 0xC0, 0x21, 0xC6, 0xB3, 0x68, 0x97, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x33, 0xC0, 0x33, 0xAF, 0x3C, 0x27, 0x4F, 0xE9, 0x00, 0xE0, 0x25, 0x20, 0x07, 0xC0, 0x44, 0xC6, 0x17, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x2D, 0x20, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0xE0, 0x2F, 0x20, 0x1F, 0x62, 0x57, 0x9F, 0x00, 0xE0, 0x07, 0x20, 0x3F, 0x3D, 0x5D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x28, 0x19, 0x60, 0xEC, 0xB3, 0x05, 0x00, 0xE0, 0x17, 0x26, 0x17, 0xDF, 0x23, 0x3B, 0x33, 0xAD, 0x35, 0x17, 0x4F, 0xE9, 0x1F, 0x26, 0x1F, 0xDF, 0x9D, 0x1F, 0x4F, 0xE9, 0x9E, 0x3F, 0x4F, 0xE9, 0x39, 0x37, 0x4F, 0xE9, 0x2F, 0x2F, 0x17, 0xAF, 0x00, 0x80, 0x00, 0xE8, 0x07, 0x07, 0x1F, 0xAF, 0x00, 0x80, 0x00, 0xE8, 0x31, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x9C, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x57, 0x39, 0x20, 0xE9, 0x16, 0x28, 0x20, 0xE9, 0x1D, 0x3B, 0x20, 0xE9, 0x1E, 0x2B, 0x20, 0xE9, 0x2B, 0x32, 0x20, 0xE9, 0x1C, 0x23, 0x20, 0xE9, 0x57, 0x36, 0x20, 0xE9, 0x00, 0x80, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x90, 0xE2, 0x00, 0xE0, 0x74, 0xFF, 0x20, 0xEA, 0x19, 0xC8, 0xC1, 0xCD, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x9F, 0x41, 0x49, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x41, 0x49, 0xBD, 0x2D, 0x41, 0x51, 0xBD, 0x0D, 0x80, 0x07, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x35, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x30, 0x2D, 0x30, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0xA7, 0x5B, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x73, 0xFF, 0x0A, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0xC9, 0x41, 0xC8, 0xEC, 0x42, 0xE1, 0x00, 0xE0, 0x71, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xC8, 0x40, 0xC0, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x6E, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, }; static unsigned char warp_g200_tgzf[] = { 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x98, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x81, 0x04, 0x89, 0x04, 0x01, 0x04, 0x09, 0x04, 0xC9, 0x41, 0xC0, 0xEC, 0x11, 0x04, 0x00, 0xE0, 0x41, 0xCC, 0x41, 0xCD, 0x49, 0xCC, 0x49, 0xCD, 0xD1, 0x41, 0xC0, 0xEC, 0x51, 0xCC, 0x51, 0xCD, 0x80, 0x04, 0x10, 0x04, 0x08, 0x04, 0x00, 0xE0, 0x00, 0xCC, 0xC0, 0xCD, 0xD1, 0x49, 0xC0, 0xEC, 0x8A, 0x1F, 0x20, 0xE9, 0x8B, 0x3F, 0x20, 0xE9, 0x41, 0x3C, 0x41, 0xAD, 0x49, 0x3C, 0x49, 0xAD, 0x10, 0xCC, 0x10, 0xCD, 0x08, 0xCC, 0x08, 0xCD, 0xB9, 0x41, 0x49, 0xBB, 0x1F, 0xF0, 0x41, 0xCD, 0x51, 0x3C, 0x51, 0xAD, 0x00, 0x98, 0x80, 0xE9, 0x7F, 0x80, 0x07, 0xEA, 0x24, 0x1F, 0x20, 0xE9, 0x21, 0x45, 0x80, 0xE8, 0x1A, 0x4D, 0x80, 0xE8, 0x31, 0x55, 0x80, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0x41, 0x49, 0xBD, 0x1D, 0x41, 0x51, 0xBD, 0x2E, 0x41, 0x2A, 0xB8, 0x34, 0x53, 0xA0, 0xE8, 0x15, 0x30, 0x1D, 0x30, 0x58, 0xE3, 0x00, 0xE0, 0xB5, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x24, 0x43, 0xA0, 0xE8, 0x2C, 0x4B, 0xA0, 0xE8, 0x15, 0x72, 0x09, 0xE3, 0x00, 0xE0, 0x1D, 0x72, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0x97, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x6C, 0x64, 0xC8, 0xEC, 0x98, 0xE1, 0xB5, 0x05, 0xBD, 0x05, 0x2E, 0x30, 0x32, 0xC0, 0xA0, 0xE8, 0x33, 0xC0, 0xA0, 0xE8, 0x74, 0x64, 0xC8, 0xEC, 0x40, 0x3C, 0x40, 0xAD, 0x32, 0x6A, 0x2A, 0x30, 0x20, 0x73, 0x33, 0x6A, 0x00, 0xE0, 0x28, 0x73, 0x1C, 0x72, 0x83, 0xE2, 0x6B, 0x80, 0x15, 0xEA, 0xB8, 0x3D, 0x28, 0xDF, 0x30, 0x35, 0x20, 0xDF, 0x40, 0x30, 0x00, 0xE0, 0xCC, 0xE2, 0x64, 0x72, 0x25, 0x42, 0x52, 0xBF, 0x2D, 0x42, 0x4A, 0xBF, 0x30, 0x2E, 0x30, 0xDF, 0x38, 0x2E, 0x38, 0xDF, 0x18, 0x1D, 0x45, 0xE9, 0x1E, 0x15, 0x45, 0xE9, 0x2B, 0x49, 0x51, 0xBD, 0x00, 0xE0, 0x1F, 0x73, 0x38, 0x38, 0x40, 0xAF, 0x30, 0x30, 0x40, 0xAF, 0x24, 0x1F, 0x24, 0xDF, 0x1D, 0x32, 0x20, 0xE9, 0x2C, 0x1F, 0x2C, 0xDF, 0x1A, 0x33, 0x20, 0xE9, 0xB0, 0x10, 0x08, 0xE3, 0x40, 0x10, 0xB8, 0x10, 0x26, 0xF0, 0x30, 0xCD, 0x2F, 0xF0, 0x38, 0xCD, 0x2B, 0x80, 0x20, 0xE9, 0x2A, 0x80, 0x20, 0xE9, 0xA6, 0x20, 0x88, 0xE2, 0x00, 0xE0, 0xAF, 0x20, 0x28, 0x2A, 0x26, 0xAF, 0x20, 0x2A, 0xC0, 0xAF, 0x34, 0x1F, 0x34, 0xDF, 0x46, 0x24, 0x46, 0xDF, 0x28, 0x30, 0x80, 0xBF, 0x20, 0x38, 0x80, 0xBF, 0x47, 0x24, 0x47, 0xDF, 0x4E, 0x2C, 0x4E, 0xDF, 0x4F, 0x2C, 0x4F, 0xDF, 0x56, 0x34, 0x56, 0xDF, 0x28, 0x15, 0x28, 0xDF, 0x20, 0x1D, 0x20, 0xDF, 0x57, 0x34, 0x57, 0xDF, 0x00, 0xE0, 0x1D, 0x05, 0x04, 0x80, 0x10, 0xEA, 0x89, 0xE2, 0x2B, 0x30, 0x3F, 0xC1, 0x1D, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x68, 0xBF, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x20, 0xC0, 0x20, 0xAF, 0x28, 0x05, 0x97, 0x74, 0x00, 0xE0, 0x2A, 0x10, 0x16, 0xC0, 0x20, 0xE9, 0x04, 0x80, 0x10, 0xEA, 0x8C, 0xE2, 0x95, 0x05, 0x28, 0xC1, 0x28, 0xAD, 0x1F, 0xC1, 0x15, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA8, 0x67, 0x9F, 0x6B, 0x00, 0x80, 0x00, 0xE8, 0x28, 0xC0, 0x28, 0xAD, 0x1D, 0x25, 0x20, 0x05, 0x28, 0x32, 0x80, 0xAD, 0x40, 0x2A, 0x40, 0xBD, 0x1C, 0x80, 0x20, 0xE9, 0x20, 0x33, 0x20, 0xAD, 0x20, 0x73, 0x00, 0xE0, 0xB6, 0x49, 0x51, 0xBB, 0x26, 0x2F, 0xB0, 0xE8, 0x19, 0x20, 0x20, 0xE9, 0x35, 0x20, 0x35, 0xDF, 0x3D, 0x20, 0x3D, 0xDF, 0x15, 0x20, 0x15, 0xDF, 0x1D, 0x20, 0x1D, 0xDF, 0x26, 0xD0, 0x26, 0xCD, 0x29, 0x49, 0x2A, 0xB8, 0x26, 0x40, 0x80, 0xBD, 0x3B, 0x48, 0x50, 0xBD, 0x3E, 0x54, 0x57, 0x9F, 0x00, 0xE0, 0x82, 0xE1, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x26, 0x30, 0x29, 0x30, 0x48, 0x3C, 0x48, 0xAD, 0x2B, 0x72, 0xC2, 0xE1, 0x2C, 0xC0, 0x44, 0xC2, 0x05, 0x24, 0x34, 0xBF, 0x0D, 0x24, 0x2C, 0xBF, 0x2D, 0x46, 0x4E, 0xBF, 0x25, 0x46, 0x56, 0xBF, 0x20, 0x1D, 0x6F, 0x8F, 0x32, 0x3E, 0x5F, 0xE9, 0x3E, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x30, 0x1E, 0x8F, 0x51, 0x9F, 0x33, 0x1E, 0x5F, 0xE9, 0x05, 0x44, 0x54, 0xB2, 0x0D, 0x44, 0x4C, 0xB2, 0x19, 0xC0, 0xB0, 0xE8, 0x34, 0xC0, 0x44, 0xC4, 0x33, 0x73, 0x00, 0xE0, 0x3E, 0x62, 0x57, 0x9F, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0xE0, 0x0D, 0x20, 0x84, 0x3E, 0x58, 0xE9, 0x28, 0x1D, 0x6F, 0x8F, 0x05, 0x20, 0x00, 0xE0, 0x85, 0x1E, 0x58, 0xE9, 0x9B, 0x3B, 0x33, 0xDF, 0x20, 0x20, 0x42, 0xAF, 0x30, 0x42, 0x56, 0x9F, 0x80, 0x3E, 0x57, 0xE9, 0x3F, 0x8F, 0x51, 0x9F, 0x30, 0x80, 0x5F, 0xE9, 0x28, 0x28, 0x24, 0xAF, 0x81, 0x1E, 0x57, 0xE9, 0x05, 0x47, 0x57, 0xBF, 0x0D, 0x47, 0x4F, 0xBF, 0x88, 0x80, 0x58, 0xE9, 0x1B, 0x29, 0x1B, 0xDF, 0x30, 0x1D, 0x6F, 0x8F, 0x3A, 0x30, 0x4F, 0xE9, 0x1C, 0x30, 0x26, 0xDF, 0x09, 0xE3, 0x3B, 0x05, 0x3E, 0x50, 0x56, 0x9F, 0x3B, 0x3F, 0x4F, 0xE9, 0x1E, 0x8F, 0x51, 0x9F, 0x00, 0xE0, 0xAC, 0x20, 0x2D, 0x44, 0x4C, 0xB4, 0x2C, 0x1C, 0xC0, 0xAF, 0x25, 0x44, 0x54, 0xB4, 0x00, 0xE0, 0xC8, 0x30, 0x30, 0x46, 0x30, 0xAF, 0x1B, 0x1B, 0x48, 0xAF, 0x00, 0xE0, 0x25, 0x20, 0x38, 0x2C, 0x4F, 0xE9, 0x86, 0x80, 0x57, 0xE9, 0x38, 0x1D, 0x6F, 0x8F, 0x28, 0x74, 0x00, 0xE0, 0x0D, 0x44, 0x4C, 0xB0, 0x05, 0x44, 0x54, 0xB0, 0x2D, 0x20, 0x9B, 0x10, 0x82, 0x3E, 0x57, 0xE9, 0x32, 0xF0, 0x1B, 0xCD, 0x1E, 0xBD, 0x59, 0x9F, 0x83, 0x1E, 0x57, 0xE9, 0x38, 0x47, 0x38, 0xAF, 0x34, 0x20, 0x2A, 0x30, 0x00, 0xE0, 0x0D, 0x20, 0x32, 0x20, 0x05, 0x20, 0x87, 0x80, 0x57, 0xE9, 0x1F, 0x54, 0x57, 0x9F, 0x17, 0x42, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x6A, 0x3F, 0x8F, 0x51, 0x9F, 0x37, 0x1E, 0x4F, 0xE9, 0x37, 0x32, 0x2A, 0xAF, 0x00, 0xE0, 0x32, 0x00, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xC0, 0x44, 0xC0, 0x36, 0x1F, 0x4F, 0xE9, 0x1F, 0x1F, 0x26, 0xDF, 0x37, 0x1B, 0x37, 0xBF, 0x17, 0x26, 0x17, 0xDF, 0x3E, 0x17, 0x4F, 0xE9, 0x3F, 0x3F, 0x4F, 0xE9, 0x34, 0x1F, 0x34, 0xAF, 0x2B, 0x05, 0xA7, 0x20, 0x33, 0x2B, 0x37, 0xDF, 0x27, 0x17, 0xC0, 0xAF, 0x34, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0D, 0x21, 0x1A, 0xB6, 0x05, 0x21, 0x31, 0xB6, 0x03, 0x80, 0x2A, 0xEA, 0x17, 0xC1, 0x2B, 0xBD, 0x0D, 0x20, 0x05, 0x20, 0x2F, 0xC0, 0x21, 0xC6, 0xB3, 0x68, 0x97, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x33, 0xC0, 0x33, 0xAF, 0x3C, 0x27, 0x4F, 0xE9, 0x17, 0x50, 0x56, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0xE0, 0x2F, 0x20, 0x00, 0x80, 0x00, 0xE8, 0x28, 0x19, 0x60, 0xEC, 0xB3, 0x05, 0x00, 0xE0, 0x00, 0x80, 0x00, 0xE8, 0x23, 0x3B, 0x33, 0xAD, 0x00, 0x80, 0x00, 0xE8, 0x17, 0x26, 0x17, 0xDF, 0x35, 0x17, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x39, 0x37, 0x4F, 0xE9, 0x2F, 0x2F, 0x17, 0xAF, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x31, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x57, 0x39, 0x20, 0xE9, 0x16, 0x28, 0x20, 0xE9, 0x1D, 0x3B, 0x20, 0xE9, 0x1E, 0x2B, 0x20, 0xE9, 0x2B, 0x32, 0x20, 0xE9, 0x1C, 0x23, 0x20, 0xE9, 0x57, 0x36, 0x20, 0xE9, 0x00, 0x80, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x90, 0xE2, 0x00, 0xE0, 0x78, 0xFF, 0x20, 0xEA, 0x19, 0xC8, 0xC1, 0xCD, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x9F, 0x41, 0x49, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x41, 0x49, 0xBD, 0x2D, 0x41, 0x51, 0xBD, 0x0D, 0x80, 0x07, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x35, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x30, 0x2D, 0x30, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0xA7, 0x5B, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x77, 0xFF, 0x0A, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0xC9, 0x41, 0xC8, 0xEC, 0x42, 0xE1, 0x00, 0xE0, 0x75, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xC8, 0x40, 0xC0, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x72, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, }; static unsigned char warp_g200_tgzs[] = { 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x98, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x81, 0x04, 0x89, 0x04, 0x01, 0x04, 0x09, 0x04, 0xC9, 0x41, 0xC0, 0xEC, 0x11, 0x04, 0x00, 0xE0, 0x41, 0xCC, 0x41, 0xCD, 0x49, 0xCC, 0x49, 0xCD, 0xD1, 0x41, 0xC0, 0xEC, 0x51, 0xCC, 0x51, 0xCD, 0x80, 0x04, 0x10, 0x04, 0x08, 0x04, 0x00, 0xE0, 0x00, 0xCC, 0xC0, 0xCD, 0xD1, 0x49, 0xC0, 0xEC, 0x8A, 0x1F, 0x20, 0xE9, 0x8B, 0x3F, 0x20, 0xE9, 0x41, 0x3C, 0x41, 0xAD, 0x49, 0x3C, 0x49, 0xAD, 0x10, 0xCC, 0x10, 0xCD, 0x08, 0xCC, 0x08, 0xCD, 0xB9, 0x41, 0x49, 0xBB, 0x1F, 0xF0, 0x41, 0xCD, 0x51, 0x3C, 0x51, 0xAD, 0x00, 0x98, 0x80, 0xE9, 0x8B, 0x80, 0x07, 0xEA, 0x24, 0x1F, 0x20, 0xE9, 0x21, 0x45, 0x80, 0xE8, 0x1A, 0x4D, 0x80, 0xE8, 0x31, 0x55, 0x80, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0x41, 0x49, 0xBD, 0x1D, 0x41, 0x51, 0xBD, 0x2E, 0x41, 0x2A, 0xB8, 0x34, 0x53, 0xA0, 0xE8, 0x15, 0x30, 0x1D, 0x30, 0x58, 0xE3, 0x00, 0xE0, 0xB5, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x24, 0x43, 0xA0, 0xE8, 0x2C, 0x4B, 0xA0, 0xE8, 0x15, 0x72, 0x09, 0xE3, 0x00, 0xE0, 0x1D, 0x72, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0x97, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x6C, 0x64, 0xC8, 0xEC, 0x98, 0xE1, 0xB5, 0x05, 0xBD, 0x05, 0x2E, 0x30, 0x32, 0xC0, 0xA0, 0xE8, 0x33, 0xC0, 0xA0, 0xE8, 0x74, 0x64, 0xC8, 0xEC, 0x40, 0x3C, 0x40, 0xAD, 0x32, 0x6A, 0x2A, 0x30, 0x20, 0x73, 0x33, 0x6A, 0x00, 0xE0, 0x28, 0x73, 0x1C, 0x72, 0x83, 0xE2, 0x77, 0x80, 0x15, 0xEA, 0xB8, 0x3D, 0x28, 0xDF, 0x30, 0x35, 0x20, 0xDF, 0x40, 0x30, 0x00, 0xE0, 0xCC, 0xE2, 0x64, 0x72, 0x25, 0x42, 0x52, 0xBF, 0x2D, 0x42, 0x4A, 0xBF, 0x30, 0x2E, 0x30, 0xDF, 0x38, 0x2E, 0x38, 0xDF, 0x18, 0x1D, 0x45, 0xE9, 0x1E, 0x15, 0x45, 0xE9, 0x2B, 0x49, 0x51, 0xBD, 0x00, 0xE0, 0x1F, 0x73, 0x38, 0x38, 0x40, 0xAF, 0x30, 0x30, 0x40, 0xAF, 0x24, 0x1F, 0x24, 0xDF, 0x1D, 0x32, 0x20, 0xE9, 0x2C, 0x1F, 0x2C, 0xDF, 0x1A, 0x33, 0x20, 0xE9, 0xB0, 0x10, 0x08, 0xE3, 0x40, 0x10, 0xB8, 0x10, 0x26, 0xF0, 0x30, 0xCD, 0x2F, 0xF0, 0x38, 0xCD, 0x2B, 0x80, 0x20, 0xE9, 0x2A, 0x80, 0x20, 0xE9, 0xA6, 0x20, 0x88, 0xE2, 0x00, 0xE0, 0xAF, 0x20, 0x28, 0x2A, 0x26, 0xAF, 0x20, 0x2A, 0xC0, 0xAF, 0x34, 0x1F, 0x34, 0xDF, 0x46, 0x24, 0x46, 0xDF, 0x28, 0x30, 0x80, 0xBF, 0x20, 0x38, 0x80, 0xBF, 0x47, 0x24, 0x47, 0xDF, 0x4E, 0x2C, 0x4E, 0xDF, 0x4F, 0x2C, 0x4F, 0xDF, 0x56, 0x34, 0x56, 0xDF, 0x28, 0x15, 0x28, 0xDF, 0x20, 0x1D, 0x20, 0xDF, 0x57, 0x34, 0x57, 0xDF, 0x00, 0xE0, 0x1D, 0x05, 0x04, 0x80, 0x10, 0xEA, 0x89, 0xE2, 0x2B, 0x30, 0x3F, 0xC1, 0x1D, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x68, 0xBF, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x20, 0xC0, 0x20, 0xAF, 0x28, 0x05, 0x97, 0x74, 0x00, 0xE0, 0x2A, 0x10, 0x16, 0xC0, 0x20, 0xE9, 0x04, 0x80, 0x10, 0xEA, 0x8C, 0xE2, 0x95, 0x05, 0x28, 0xC1, 0x28, 0xAD, 0x1F, 0xC1, 0x15, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA8, 0x67, 0x9F, 0x6B, 0x00, 0x80, 0x00, 0xE8, 0x28, 0xC0, 0x28, 0xAD, 0x1D, 0x25, 0x20, 0x05, 0x28, 0x32, 0x80, 0xAD, 0x40, 0x2A, 0x40, 0xBD, 0x1C, 0x80, 0x20, 0xE9, 0x20, 0x33, 0x20, 0xAD, 0x20, 0x73, 0x00, 0xE0, 0xB6, 0x49, 0x51, 0xBB, 0x26, 0x2F, 0xB0, 0xE8, 0x19, 0x20, 0x20, 0xE9, 0x35, 0x20, 0x35, 0xDF, 0x3D, 0x20, 0x3D, 0xDF, 0x15, 0x20, 0x15, 0xDF, 0x1D, 0x20, 0x1D, 0xDF, 0x26, 0xD0, 0x26, 0xCD, 0x29, 0x49, 0x2A, 0xB8, 0x26, 0x40, 0x80, 0xBD, 0x3B, 0x48, 0x50, 0xBD, 0x3E, 0x54, 0x57, 0x9F, 0x00, 0xE0, 0x82, 0xE1, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x26, 0x30, 0x29, 0x30, 0x48, 0x3C, 0x48, 0xAD, 0x2B, 0x72, 0xC2, 0xE1, 0x2C, 0xC0, 0x44, 0xC2, 0x05, 0x24, 0x34, 0xBF, 0x0D, 0x24, 0x2C, 0xBF, 0x2D, 0x46, 0x4E, 0xBF, 0x25, 0x46, 0x56, 0xBF, 0x20, 0x1D, 0x6F, 0x8F, 0x32, 0x3E, 0x5F, 0xE9, 0x3E, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x30, 0x1E, 0x8F, 0x51, 0x9F, 0x33, 0x1E, 0x5F, 0xE9, 0x05, 0x44, 0x54, 0xB2, 0x0D, 0x44, 0x4C, 0xB2, 0x19, 0xC0, 0xB0, 0xE8, 0x34, 0xC0, 0x44, 0xC4, 0x33, 0x73, 0x00, 0xE0, 0x3E, 0x62, 0x57, 0x9F, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0xE0, 0x0D, 0x20, 0x84, 0x3E, 0x58, 0xE9, 0x28, 0x1D, 0x6F, 0x8F, 0x05, 0x20, 0x00, 0xE0, 0x85, 0x1E, 0x58, 0xE9, 0x9B, 0x3B, 0x33, 0xDF, 0x20, 0x20, 0x42, 0xAF, 0x30, 0x42, 0x56, 0x9F, 0x80, 0x3E, 0x57, 0xE9, 0x3F, 0x8F, 0x51, 0x9F, 0x30, 0x80, 0x5F, 0xE9, 0x28, 0x28, 0x24, 0xAF, 0x81, 0x1E, 0x57, 0xE9, 0x05, 0x47, 0x57, 0xBF, 0x0D, 0x47, 0x4F, 0xBF, 0x88, 0x80, 0x58, 0xE9, 0x1B, 0x29, 0x1B, 0xDF, 0x30, 0x1D, 0x6F, 0x8F, 0x3A, 0x30, 0x4F, 0xE9, 0x1C, 0x30, 0x26, 0xDF, 0x09, 0xE3, 0x3B, 0x05, 0x3E, 0x50, 0x56, 0x9F, 0x3B, 0x3F, 0x4F, 0xE9, 0x1E, 0x8F, 0x51, 0x9F, 0x00, 0xE0, 0xAC, 0x20, 0x2D, 0x44, 0x4C, 0xB4, 0x2C, 0x1C, 0xC0, 0xAF, 0x25, 0x44, 0x54, 0xB4, 0x00, 0xE0, 0xC8, 0x30, 0x30, 0x46, 0x30, 0xAF, 0x1B, 0x1B, 0x48, 0xAF, 0x00, 0xE0, 0x25, 0x20, 0x38, 0x2C, 0x4F, 0xE9, 0x86, 0x80, 0x57, 0xE9, 0x38, 0x1D, 0x6F, 0x8F, 0x28, 0x74, 0x00, 0xE0, 0x0D, 0x44, 0x4C, 0xB0, 0x05, 0x44, 0x54, 0xB0, 0x2D, 0x20, 0x9B, 0x10, 0x82, 0x3E, 0x57, 0xE9, 0x32, 0xF0, 0x1B, 0xCD, 0x1E, 0xBD, 0x59, 0x9F, 0x83, 0x1E, 0x57, 0xE9, 0x38, 0x47, 0x38, 0xAF, 0x34, 0x20, 0x2A, 0x30, 0x00, 0xE0, 0x0D, 0x20, 0x32, 0x20, 0x05, 0x20, 0x87, 0x80, 0x57, 0xE9, 0x1F, 0x54, 0x57, 0x9F, 0x17, 0x42, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x6A, 0x3F, 0x8F, 0x51, 0x9F, 0x37, 0x1E, 0x4F, 0xE9, 0x37, 0x32, 0x2A, 0xAF, 0x00, 0xE0, 0x32, 0x00, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xC0, 0x44, 0xC0, 0x36, 0x1F, 0x4F, 0xE9, 0x1F, 0x1F, 0x26, 0xDF, 0x37, 0x1B, 0x37, 0xBF, 0x17, 0x26, 0x17, 0xDF, 0x3E, 0x17, 0x4F, 0xE9, 0x3F, 0x3F, 0x4F, 0xE9, 0x34, 0x1F, 0x34, 0xAF, 0x2B, 0x05, 0xA7, 0x20, 0x33, 0x2B, 0x37, 0xDF, 0x27, 0x17, 0xC0, 0xAF, 0x34, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2D, 0x21, 0x1A, 0xB0, 0x25, 0x21, 0x31, 0xB0, 0x0D, 0x21, 0x1A, 0xB2, 0x05, 0x21, 0x31, 0xB2, 0x03, 0x80, 0x2A, 0xEA, 0x17, 0xC1, 0x2B, 0xBD, 0x2D, 0x20, 0x25, 0x20, 0x05, 0x20, 0x0D, 0x20, 0xB3, 0x68, 0x97, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x33, 0xC0, 0x33, 0xAF, 0x2F, 0xC0, 0x21, 0xC0, 0x16, 0x42, 0x56, 0x9F, 0x3C, 0x27, 0x4F, 0xE9, 0x1E, 0x62, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x21, 0x31, 0xB4, 0x2D, 0x21, 0x1A, 0xB4, 0x3F, 0x2F, 0x5D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x33, 0x05, 0x00, 0xE0, 0x28, 0x19, 0x60, 0xEC, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0xE0, 0x2F, 0x20, 0x23, 0x3B, 0x33, 0xAD, 0x1E, 0x26, 0x1E, 0xDF, 0xA7, 0x1E, 0x4F, 0xE9, 0x17, 0x26, 0x16, 0xDF, 0x2D, 0x20, 0x00, 0xE0, 0xA8, 0x3F, 0x4F, 0xE9, 0x2F, 0x2F, 0x1E, 0xAF, 0x25, 0x20, 0x00, 0xE0, 0xA4, 0x16, 0x4F, 0xE9, 0x0F, 0xC0, 0x21, 0xC2, 0xA6, 0x80, 0x4F, 0xE9, 0x1F, 0x62, 0x57, 0x9F, 0x3F, 0x2F, 0x5D, 0x9F, 0x00, 0xE0, 0x8F, 0x20, 0xA5, 0x37, 0x4F, 0xE9, 0x0F, 0x17, 0x0F, 0xAF, 0x06, 0xC0, 0x21, 0xC4, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA3, 0x80, 0x4F, 0xE9, 0x06, 0x20, 0x00, 0xE0, 0x1F, 0x26, 0x1F, 0xDF, 0xA1, 0x1F, 0x4F, 0xE9, 0xA2, 0x3F, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x06, 0x06, 0x1F, 0xAF, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x57, 0x39, 0x20, 0xE9, 0x16, 0x28, 0x20, 0xE9, 0x1D, 0x3B, 0x20, 0xE9, 0x1E, 0x2B, 0x20, 0xE9, 0x2B, 0x32, 0x20, 0xE9, 0x1C, 0x23, 0x20, 0xE9, 0x57, 0x36, 0x20, 0xE9, 0x00, 0x80, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x90, 0xE2, 0x00, 0xE0, 0x6C, 0xFF, 0x20, 0xEA, 0x19, 0xC8, 0xC1, 0xCD, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x9F, 0x41, 0x49, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x41, 0x49, 0xBD, 0x2D, 0x41, 0x51, 0xBD, 0x0D, 0x80, 0x07, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x35, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x30, 0x2D, 0x30, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0xA7, 0x5B, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x6B, 0xFF, 0x0A, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0xC9, 0x41, 0xC8, 0xEC, 0x42, 0xE1, 0x00, 0xE0, 0x69, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xC8, 0x40, 0xC0, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x66, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, }; static unsigned char warp_g200_tgzsa[] = { 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x98, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x81, 0x04, 0x89, 0x04, 0x01, 0x04, 0x09, 0x04, 0xC9, 0x41, 0xC0, 0xEC, 0x11, 0x04, 0x00, 0xE0, 0x41, 0xCC, 0x41, 0xCD, 0x49, 0xCC, 0x49, 0xCD, 0xD1, 0x41, 0xC0, 0xEC, 0x51, 0xCC, 0x51, 0xCD, 0x80, 0x04, 0x10, 0x04, 0x08, 0x04, 0x00, 0xE0, 0x00, 0xCC, 0xC0, 0xCD, 0xD1, 0x49, 0xC0, 0xEC, 0x8A, 0x1F, 0x20, 0xE9, 0x8B, 0x3F, 0x20, 0xE9, 0x41, 0x3C, 0x41, 0xAD, 0x49, 0x3C, 0x49, 0xAD, 0x10, 0xCC, 0x10, 0xCD, 0x08, 0xCC, 0x08, 0xCD, 0xB9, 0x41, 0x49, 0xBB, 0x1F, 0xF0, 0x41, 0xCD, 0x51, 0x3C, 0x51, 0xAD, 0x00, 0x98, 0x80, 0xE9, 0x8F, 0x80, 0x07, 0xEA, 0x24, 0x1F, 0x20, 0xE9, 0x21, 0x45, 0x80, 0xE8, 0x1A, 0x4D, 0x80, 0xE8, 0x31, 0x55, 0x80, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0x41, 0x49, 0xBD, 0x1D, 0x41, 0x51, 0xBD, 0x2E, 0x41, 0x2A, 0xB8, 0x34, 0x53, 0xA0, 0xE8, 0x15, 0x30, 0x1D, 0x30, 0x58, 0xE3, 0x00, 0xE0, 0xB5, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x24, 0x43, 0xA0, 0xE8, 0x2C, 0x4B, 0xA0, 0xE8, 0x15, 0x72, 0x09, 0xE3, 0x00, 0xE0, 0x1D, 0x72, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0x97, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x6C, 0x64, 0xC8, 0xEC, 0x98, 0xE1, 0xB5, 0x05, 0xBD, 0x05, 0x2E, 0x30, 0x32, 0xC0, 0xA0, 0xE8, 0x33, 0xC0, 0xA0, 0xE8, 0x74, 0x64, 0xC8, 0xEC, 0x40, 0x3C, 0x40, 0xAD, 0x32, 0x6A, 0x2A, 0x30, 0x20, 0x73, 0x33, 0x6A, 0x00, 0xE0, 0x28, 0x73, 0x1C, 0x72, 0x83, 0xE2, 0x7B, 0x80, 0x15, 0xEA, 0xB8, 0x3D, 0x28, 0xDF, 0x30, 0x35, 0x20, 0xDF, 0x40, 0x30, 0x00, 0xE0, 0xCC, 0xE2, 0x64, 0x72, 0x25, 0x42, 0x52, 0xBF, 0x2D, 0x42, 0x4A, 0xBF, 0x30, 0x2E, 0x30, 0xDF, 0x38, 0x2E, 0x38, 0xDF, 0x18, 0x1D, 0x45, 0xE9, 0x1E, 0x15, 0x45, 0xE9, 0x2B, 0x49, 0x51, 0xBD, 0x00, 0xE0, 0x1F, 0x73, 0x38, 0x38, 0x40, 0xAF, 0x30, 0x30, 0x40, 0xAF, 0x24, 0x1F, 0x24, 0xDF, 0x1D, 0x32, 0x20, 0xE9, 0x2C, 0x1F, 0x2C, 0xDF, 0x1A, 0x33, 0x20, 0xE9, 0xB0, 0x10, 0x08, 0xE3, 0x40, 0x10, 0xB8, 0x10, 0x26, 0xF0, 0x30, 0xCD, 0x2F, 0xF0, 0x38, 0xCD, 0x2B, 0x80, 0x20, 0xE9, 0x2A, 0x80, 0x20, 0xE9, 0xA6, 0x20, 0x88, 0xE2, 0x00, 0xE0, 0xAF, 0x20, 0x28, 0x2A, 0x26, 0xAF, 0x20, 0x2A, 0xC0, 0xAF, 0x34, 0x1F, 0x34, 0xDF, 0x46, 0x24, 0x46, 0xDF, 0x28, 0x30, 0x80, 0xBF, 0x20, 0x38, 0x80, 0xBF, 0x47, 0x24, 0x47, 0xDF, 0x4E, 0x2C, 0x4E, 0xDF, 0x4F, 0x2C, 0x4F, 0xDF, 0x56, 0x34, 0x56, 0xDF, 0x28, 0x15, 0x28, 0xDF, 0x20, 0x1D, 0x20, 0xDF, 0x57, 0x34, 0x57, 0xDF, 0x00, 0xE0, 0x1D, 0x05, 0x04, 0x80, 0x10, 0xEA, 0x89, 0xE2, 0x2B, 0x30, 0x3F, 0xC1, 0x1D, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x68, 0xBF, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x20, 0xC0, 0x20, 0xAF, 0x28, 0x05, 0x97, 0x74, 0x00, 0xE0, 0x2A, 0x10, 0x16, 0xC0, 0x20, 0xE9, 0x04, 0x80, 0x10, 0xEA, 0x8C, 0xE2, 0x95, 0x05, 0x28, 0xC1, 0x28, 0xAD, 0x1F, 0xC1, 0x15, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA8, 0x67, 0x9F, 0x6B, 0x00, 0x80, 0x00, 0xE8, 0x28, 0xC0, 0x28, 0xAD, 0x1D, 0x25, 0x20, 0x05, 0x28, 0x32, 0x80, 0xAD, 0x40, 0x2A, 0x40, 0xBD, 0x1C, 0x80, 0x20, 0xE9, 0x20, 0x33, 0x20, 0xAD, 0x20, 0x73, 0x00, 0xE0, 0xB6, 0x49, 0x51, 0xBB, 0x26, 0x2F, 0xB0, 0xE8, 0x19, 0x20, 0x20, 0xE9, 0x35, 0x20, 0x35, 0xDF, 0x3D, 0x20, 0x3D, 0xDF, 0x15, 0x20, 0x15, 0xDF, 0x1D, 0x20, 0x1D, 0xDF, 0x26, 0xD0, 0x26, 0xCD, 0x29, 0x49, 0x2A, 0xB8, 0x26, 0x40, 0x80, 0xBD, 0x3B, 0x48, 0x50, 0xBD, 0x3E, 0x54, 0x57, 0x9F, 0x00, 0xE0, 0x82, 0xE1, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x26, 0x30, 0x29, 0x30, 0x48, 0x3C, 0x48, 0xAD, 0x2B, 0x72, 0xC2, 0xE1, 0x2C, 0xC0, 0x44, 0xC2, 0x05, 0x24, 0x34, 0xBF, 0x0D, 0x24, 0x2C, 0xBF, 0x2D, 0x46, 0x4E, 0xBF, 0x25, 0x46, 0x56, 0xBF, 0x20, 0x1D, 0x6F, 0x8F, 0x32, 0x3E, 0x5F, 0xE9, 0x3E, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x30, 0x1E, 0x8F, 0x51, 0x9F, 0x33, 0x1E, 0x5F, 0xE9, 0x05, 0x44, 0x54, 0xB2, 0x0D, 0x44, 0x4C, 0xB2, 0x19, 0xC0, 0xB0, 0xE8, 0x34, 0xC0, 0x44, 0xC4, 0x33, 0x73, 0x00, 0xE0, 0x3E, 0x62, 0x57, 0x9F, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0xE0, 0x0D, 0x20, 0x84, 0x3E, 0x58, 0xE9, 0x28, 0x1D, 0x6F, 0x8F, 0x05, 0x20, 0x00, 0xE0, 0x85, 0x1E, 0x58, 0xE9, 0x9B, 0x3B, 0x33, 0xDF, 0x20, 0x20, 0x42, 0xAF, 0x30, 0x42, 0x56, 0x9F, 0x80, 0x3E, 0x57, 0xE9, 0x3F, 0x8F, 0x51, 0x9F, 0x30, 0x80, 0x5F, 0xE9, 0x28, 0x28, 0x24, 0xAF, 0x81, 0x1E, 0x57, 0xE9, 0x05, 0x47, 0x57, 0xBF, 0x0D, 0x47, 0x4F, 0xBF, 0x88, 0x80, 0x58, 0xE9, 0x1B, 0x29, 0x1B, 0xDF, 0x30, 0x1D, 0x6F, 0x8F, 0x3A, 0x30, 0x4F, 0xE9, 0x1C, 0x30, 0x26, 0xDF, 0x09, 0xE3, 0x3B, 0x05, 0x3E, 0x50, 0x56, 0x9F, 0x3B, 0x3F, 0x4F, 0xE9, 0x1E, 0x8F, 0x51, 0x9F, 0x00, 0xE0, 0xAC, 0x20, 0x2D, 0x44, 0x4C, 0xB4, 0x2C, 0x1C, 0xC0, 0xAF, 0x25, 0x44, 0x54, 0xB4, 0x00, 0xE0, 0xC8, 0x30, 0x30, 0x46, 0x30, 0xAF, 0x1B, 0x1B, 0x48, 0xAF, 0x00, 0xE0, 0x25, 0x20, 0x38, 0x2C, 0x4F, 0xE9, 0x86, 0x80, 0x57, 0xE9, 0x38, 0x1D, 0x6F, 0x8F, 0x28, 0x74, 0x00, 0xE0, 0x0D, 0x44, 0x4C, 0xB0, 0x05, 0x44, 0x54, 0xB0, 0x2D, 0x20, 0x9B, 0x10, 0x82, 0x3E, 0x57, 0xE9, 0x32, 0xF0, 0x1B, 0xCD, 0x1E, 0xBD, 0x59, 0x9F, 0x83, 0x1E, 0x57, 0xE9, 0x38, 0x47, 0x38, 0xAF, 0x34, 0x20, 0x2A, 0x30, 0x00, 0xE0, 0x0D, 0x20, 0x32, 0x20, 0x05, 0x20, 0x87, 0x80, 0x57, 0xE9, 0x1F, 0x54, 0x57, 0x9F, 0x17, 0x42, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x6A, 0x3F, 0x8F, 0x51, 0x9F, 0x37, 0x1E, 0x4F, 0xE9, 0x37, 0x32, 0x2A, 0xAF, 0x00, 0xE0, 0x32, 0x00, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xC0, 0x44, 0xC0, 0x36, 0x1F, 0x4F, 0xE9, 0x1F, 0x1F, 0x26, 0xDF, 0x37, 0x1B, 0x37, 0xBF, 0x17, 0x26, 0x17, 0xDF, 0x3E, 0x17, 0x4F, 0xE9, 0x3F, 0x3F, 0x4F, 0xE9, 0x34, 0x1F, 0x34, 0xAF, 0x2B, 0x05, 0xA7, 0x20, 0x33, 0x2B, 0x37, 0xDF, 0x27, 0x17, 0xC0, 0xAF, 0x34, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2D, 0x21, 0x1A, 0xB0, 0x25, 0x21, 0x31, 0xB0, 0x0D, 0x21, 0x1A, 0xB2, 0x05, 0x21, 0x31, 0xB2, 0x03, 0x80, 0x2A, 0xEA, 0x17, 0xC1, 0x2B, 0xBD, 0x2D, 0x20, 0x25, 0x20, 0x05, 0x20, 0x0D, 0x20, 0xB3, 0x68, 0x97, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x33, 0xC0, 0x33, 0xAF, 0x2F, 0xC0, 0x21, 0xC0, 0x16, 0x42, 0x56, 0x9F, 0x3C, 0x27, 0x4F, 0xE9, 0x1E, 0x62, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x21, 0x31, 0xB4, 0x2D, 0x21, 0x1A, 0xB4, 0x3F, 0x2F, 0x5D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x33, 0x05, 0x00, 0xE0, 0x28, 0x19, 0x60, 0xEC, 0x0D, 0x44, 0x4C, 0xB6, 0x05, 0x44, 0x54, 0xB6, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0xE0, 0x2F, 0x20, 0x23, 0x3B, 0x33, 0xAD, 0x1E, 0x26, 0x1E, 0xDF, 0xA7, 0x1E, 0x4F, 0xE9, 0x17, 0x26, 0x16, 0xDF, 0x2D, 0x20, 0x00, 0xE0, 0xA8, 0x3F, 0x4F, 0xE9, 0x2F, 0x2F, 0x1E, 0xAF, 0x25, 0x20, 0x00, 0xE0, 0xA4, 0x16, 0x4F, 0xE9, 0x0F, 0xC0, 0x21, 0xC2, 0xA6, 0x80, 0x4F, 0xE9, 0x1F, 0x62, 0x57, 0x9F, 0x0D, 0x20, 0x05, 0x20, 0x00, 0x80, 0x00, 0xE8, 0x3F, 0x2F, 0x5D, 0x9F, 0x00, 0xE0, 0x0F, 0x20, 0x17, 0x50, 0x56, 0x9F, 0xA5, 0x37, 0x4F, 0xE9, 0x06, 0xC0, 0x21, 0xC4, 0x0F, 0x17, 0x0F, 0xAF, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x2F, 0xC0, 0x44, 0xC6, 0xA3, 0x80, 0x4F, 0xE9, 0x06, 0x20, 0x00, 0xE0, 0x1F, 0x26, 0x1F, 0xDF, 0x17, 0x26, 0x17, 0xDF, 0x9D, 0x17, 0x4F, 0xE9, 0xA1, 0x1F, 0x4F, 0xE9, 0xA2, 0x3F, 0x4F, 0xE9, 0x06, 0x06, 0x1F, 0xAF, 0x00, 0xE0, 0xAF, 0x20, 0x9E, 0x37, 0x4F, 0xE9, 0x2F, 0x17, 0x2F, 0xAF, 0xA0, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x9C, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x57, 0x39, 0x20, 0xE9, 0x16, 0x28, 0x20, 0xE9, 0x1D, 0x3B, 0x20, 0xE9, 0x1E, 0x2B, 0x20, 0xE9, 0x2B, 0x32, 0x20, 0xE9, 0x1C, 0x23, 0x20, 0xE9, 0x57, 0x36, 0x20, 0xE9, 0x00, 0x80, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x90, 0xE2, 0x00, 0xE0, 0x68, 0xFF, 0x20, 0xEA, 0x19, 0xC8, 0xC1, 0xCD, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x9F, 0x41, 0x49, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x41, 0x49, 0xBD, 0x2D, 0x41, 0x51, 0xBD, 0x0D, 0x80, 0x07, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x35, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x30, 0x2D, 0x30, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0xA7, 0x5B, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x67, 0xFF, 0x0A, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0xC9, 0x41, 0xC8, 0xEC, 0x42, 0xE1, 0x00, 0xE0, 0x65, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xC8, 0x40, 0xC0, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x62, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, }; static unsigned char warp_g200_tgzsaf[] = { 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x98, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x81, 0x04, 0x89, 0x04, 0x01, 0x04, 0x09, 0x04, 0xC9, 0x41, 0xC0, 0xEC, 0x11, 0x04, 0x00, 0xE0, 0x41, 0xCC, 0x41, 0xCD, 0x49, 0xCC, 0x49, 0xCD, 0xD1, 0x41, 0xC0, 0xEC, 0x51, 0xCC, 0x51, 0xCD, 0x80, 0x04, 0x10, 0x04, 0x08, 0x04, 0x00, 0xE0, 0x00, 0xCC, 0xC0, 0xCD, 0xD1, 0x49, 0xC0, 0xEC, 0x8A, 0x1F, 0x20, 0xE9, 0x8B, 0x3F, 0x20, 0xE9, 0x41, 0x3C, 0x41, 0xAD, 0x49, 0x3C, 0x49, 0xAD, 0x10, 0xCC, 0x10, 0xCD, 0x08, 0xCC, 0x08, 0xCD, 0xB9, 0x41, 0x49, 0xBB, 0x1F, 0xF0, 0x41, 0xCD, 0x51, 0x3C, 0x51, 0xAD, 0x00, 0x98, 0x80, 0xE9, 0x94, 0x80, 0x07, 0xEA, 0x24, 0x1F, 0x20, 0xE9, 0x21, 0x45, 0x80, 0xE8, 0x1A, 0x4D, 0x80, 0xE8, 0x31, 0x55, 0x80, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0x41, 0x49, 0xBD, 0x1D, 0x41, 0x51, 0xBD, 0x2E, 0x41, 0x2A, 0xB8, 0x34, 0x53, 0xA0, 0xE8, 0x15, 0x30, 0x1D, 0x30, 0x58, 0xE3, 0x00, 0xE0, 0xB5, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x24, 0x43, 0xA0, 0xE8, 0x2C, 0x4B, 0xA0, 0xE8, 0x15, 0x72, 0x09, 0xE3, 0x00, 0xE0, 0x1D, 0x72, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0x97, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x6C, 0x64, 0xC8, 0xEC, 0x98, 0xE1, 0xB5, 0x05, 0xBD, 0x05, 0x2E, 0x30, 0x32, 0xC0, 0xA0, 0xE8, 0x33, 0xC0, 0xA0, 0xE8, 0x74, 0x64, 0xC8, 0xEC, 0x40, 0x3C, 0x40, 0xAD, 0x32, 0x6A, 0x2A, 0x30, 0x20, 0x73, 0x33, 0x6A, 0x00, 0xE0, 0x28, 0x73, 0x1C, 0x72, 0x83, 0xE2, 0x80, 0x80, 0x15, 0xEA, 0xB8, 0x3D, 0x28, 0xDF, 0x30, 0x35, 0x20, 0xDF, 0x40, 0x30, 0x00, 0xE0, 0xCC, 0xE2, 0x64, 0x72, 0x25, 0x42, 0x52, 0xBF, 0x2D, 0x42, 0x4A, 0xBF, 0x30, 0x2E, 0x30, 0xDF, 0x38, 0x2E, 0x38, 0xDF, 0x18, 0x1D, 0x45, 0xE9, 0x1E, 0x15, 0x45, 0xE9, 0x2B, 0x49, 0x51, 0xBD, 0x00, 0xE0, 0x1F, 0x73, 0x38, 0x38, 0x40, 0xAF, 0x30, 0x30, 0x40, 0xAF, 0x24, 0x1F, 0x24, 0xDF, 0x1D, 0x32, 0x20, 0xE9, 0x2C, 0x1F, 0x2C, 0xDF, 0x1A, 0x33, 0x20, 0xE9, 0xB0, 0x10, 0x08, 0xE3, 0x40, 0x10, 0xB8, 0x10, 0x26, 0xF0, 0x30, 0xCD, 0x2F, 0xF0, 0x38, 0xCD, 0x2B, 0x80, 0x20, 0xE9, 0x2A, 0x80, 0x20, 0xE9, 0xA6, 0x20, 0x88, 0xE2, 0x00, 0xE0, 0xAF, 0x20, 0x28, 0x2A, 0x26, 0xAF, 0x20, 0x2A, 0xC0, 0xAF, 0x34, 0x1F, 0x34, 0xDF, 0x46, 0x24, 0x46, 0xDF, 0x28, 0x30, 0x80, 0xBF, 0x20, 0x38, 0x80, 0xBF, 0x47, 0x24, 0x47, 0xDF, 0x4E, 0x2C, 0x4E, 0xDF, 0x4F, 0x2C, 0x4F, 0xDF, 0x56, 0x34, 0x56, 0xDF, 0x28, 0x15, 0x28, 0xDF, 0x20, 0x1D, 0x20, 0xDF, 0x57, 0x34, 0x57, 0xDF, 0x00, 0xE0, 0x1D, 0x05, 0x04, 0x80, 0x10, 0xEA, 0x89, 0xE2, 0x2B, 0x30, 0x3F, 0xC1, 0x1D, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x68, 0xBF, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x20, 0xC0, 0x20, 0xAF, 0x28, 0x05, 0x97, 0x74, 0x00, 0xE0, 0x2A, 0x10, 0x16, 0xC0, 0x20, 0xE9, 0x04, 0x80, 0x10, 0xEA, 0x8C, 0xE2, 0x95, 0x05, 0x28, 0xC1, 0x28, 0xAD, 0x1F, 0xC1, 0x15, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA8, 0x67, 0x9F, 0x6B, 0x00, 0x80, 0x00, 0xE8, 0x28, 0xC0, 0x28, 0xAD, 0x1D, 0x25, 0x20, 0x05, 0x28, 0x32, 0x80, 0xAD, 0x40, 0x2A, 0x40, 0xBD, 0x1C, 0x80, 0x20, 0xE9, 0x20, 0x33, 0x20, 0xAD, 0x20, 0x73, 0x00, 0xE0, 0xB6, 0x49, 0x51, 0xBB, 0x26, 0x2F, 0xB0, 0xE8, 0x19, 0x20, 0x20, 0xE9, 0x35, 0x20, 0x35, 0xDF, 0x3D, 0x20, 0x3D, 0xDF, 0x15, 0x20, 0x15, 0xDF, 0x1D, 0x20, 0x1D, 0xDF, 0x26, 0xD0, 0x26, 0xCD, 0x29, 0x49, 0x2A, 0xB8, 0x26, 0x40, 0x80, 0xBD, 0x3B, 0x48, 0x50, 0xBD, 0x3E, 0x54, 0x57, 0x9F, 0x00, 0xE0, 0x82, 0xE1, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x26, 0x30, 0x29, 0x30, 0x48, 0x3C, 0x48, 0xAD, 0x2B, 0x72, 0xC2, 0xE1, 0x2C, 0xC0, 0x44, 0xC2, 0x05, 0x24, 0x34, 0xBF, 0x0D, 0x24, 0x2C, 0xBF, 0x2D, 0x46, 0x4E, 0xBF, 0x25, 0x46, 0x56, 0xBF, 0x20, 0x1D, 0x6F, 0x8F, 0x32, 0x3E, 0x5F, 0xE9, 0x3E, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x30, 0x1E, 0x8F, 0x51, 0x9F, 0x33, 0x1E, 0x5F, 0xE9, 0x05, 0x44, 0x54, 0xB2, 0x0D, 0x44, 0x4C, 0xB2, 0x19, 0xC0, 0xB0, 0xE8, 0x34, 0xC0, 0x44, 0xC4, 0x33, 0x73, 0x00, 0xE0, 0x3E, 0x62, 0x57, 0x9F, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0xE0, 0x0D, 0x20, 0x84, 0x3E, 0x58, 0xE9, 0x28, 0x1D, 0x6F, 0x8F, 0x05, 0x20, 0x00, 0xE0, 0x85, 0x1E, 0x58, 0xE9, 0x9B, 0x3B, 0x33, 0xDF, 0x20, 0x20, 0x42, 0xAF, 0x30, 0x42, 0x56, 0x9F, 0x80, 0x3E, 0x57, 0xE9, 0x3F, 0x8F, 0x51, 0x9F, 0x30, 0x80, 0x5F, 0xE9, 0x28, 0x28, 0x24, 0xAF, 0x81, 0x1E, 0x57, 0xE9, 0x05, 0x47, 0x57, 0xBF, 0x0D, 0x47, 0x4F, 0xBF, 0x88, 0x80, 0x58, 0xE9, 0x1B, 0x29, 0x1B, 0xDF, 0x30, 0x1D, 0x6F, 0x8F, 0x3A, 0x30, 0x4F, 0xE9, 0x1C, 0x30, 0x26, 0xDF, 0x09, 0xE3, 0x3B, 0x05, 0x3E, 0x50, 0x56, 0x9F, 0x3B, 0x3F, 0x4F, 0xE9, 0x1E, 0x8F, 0x51, 0x9F, 0x00, 0xE0, 0xAC, 0x20, 0x2D, 0x44, 0x4C, 0xB4, 0x2C, 0x1C, 0xC0, 0xAF, 0x25, 0x44, 0x54, 0xB4, 0x00, 0xE0, 0xC8, 0x30, 0x30, 0x46, 0x30, 0xAF, 0x1B, 0x1B, 0x48, 0xAF, 0x00, 0xE0, 0x25, 0x20, 0x38, 0x2C, 0x4F, 0xE9, 0x86, 0x80, 0x57, 0xE9, 0x38, 0x1D, 0x6F, 0x8F, 0x28, 0x74, 0x00, 0xE0, 0x0D, 0x44, 0x4C, 0xB0, 0x05, 0x44, 0x54, 0xB0, 0x2D, 0x20, 0x9B, 0x10, 0x82, 0x3E, 0x57, 0xE9, 0x32, 0xF0, 0x1B, 0xCD, 0x1E, 0xBD, 0x59, 0x9F, 0x83, 0x1E, 0x57, 0xE9, 0x38, 0x47, 0x38, 0xAF, 0x34, 0x20, 0x2A, 0x30, 0x00, 0xE0, 0x0D, 0x20, 0x32, 0x20, 0x05, 0x20, 0x87, 0x80, 0x57, 0xE9, 0x1F, 0x54, 0x57, 0x9F, 0x17, 0x42, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x6A, 0x3F, 0x8F, 0x51, 0x9F, 0x37, 0x1E, 0x4F, 0xE9, 0x37, 0x32, 0x2A, 0xAF, 0x00, 0xE0, 0x32, 0x00, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xC0, 0x44, 0xC0, 0x36, 0x1F, 0x4F, 0xE9, 0x1F, 0x1F, 0x26, 0xDF, 0x37, 0x1B, 0x37, 0xBF, 0x17, 0x26, 0x17, 0xDF, 0x3E, 0x17, 0x4F, 0xE9, 0x3F, 0x3F, 0x4F, 0xE9, 0x34, 0x1F, 0x34, 0xAF, 0x2B, 0x05, 0xA7, 0x20, 0x33, 0x2B, 0x37, 0xDF, 0x27, 0x17, 0xC0, 0xAF, 0x34, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2D, 0x21, 0x1A, 0xB0, 0x25, 0x21, 0x31, 0xB0, 0x0D, 0x21, 0x1A, 0xB2, 0x05, 0x21, 0x31, 0xB2, 0x03, 0x80, 0x2A, 0xEA, 0x17, 0xC1, 0x2B, 0xBD, 0x2D, 0x20, 0x25, 0x20, 0x05, 0x20, 0x0D, 0x20, 0xB3, 0x68, 0x97, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x33, 0xC0, 0x33, 0xAF, 0x2F, 0xC0, 0x21, 0xC0, 0x16, 0x42, 0x56, 0x9F, 0x3C, 0x27, 0x4F, 0xE9, 0x1E, 0x62, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x21, 0x31, 0xB4, 0x2D, 0x21, 0x1A, 0xB4, 0x3F, 0x2F, 0x5D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x33, 0x05, 0x00, 0xE0, 0x28, 0x19, 0x60, 0xEC, 0x0D, 0x21, 0x1A, 0xB6, 0x05, 0x21, 0x31, 0xB6, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0xE0, 0x2F, 0x20, 0x23, 0x3B, 0x33, 0xAD, 0x1E, 0x26, 0x1E, 0xDF, 0xA7, 0x1E, 0x4F, 0xE9, 0x17, 0x26, 0x16, 0xDF, 0x2D, 0x20, 0x00, 0xE0, 0xA8, 0x3F, 0x4F, 0xE9, 0x2F, 0x2F, 0x1E, 0xAF, 0x25, 0x20, 0x00, 0xE0, 0xA4, 0x16, 0x4F, 0xE9, 0x0F, 0xC0, 0x21, 0xC2, 0xA6, 0x80, 0x4F, 0xE9, 0x1F, 0x62, 0x57, 0x9F, 0x0D, 0x20, 0x05, 0x20, 0x2F, 0xC0, 0x21, 0xC6, 0x2D, 0x44, 0x4C, 0xB6, 0x25, 0x44, 0x54, 0xB6, 0x3F, 0x2F, 0x5D, 0x9F, 0x00, 0xE0, 0x0F, 0x20, 0x2D, 0x20, 0x25, 0x20, 0x07, 0xC0, 0x44, 0xC6, 0x17, 0x50, 0x56, 0x9F, 0xA5, 0x37, 0x4F, 0xE9, 0x06, 0xC0, 0x21, 0xC4, 0x0F, 0x17, 0x0F, 0xAF, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x1E, 0x62, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x3E, 0x3D, 0x5D, 0x9F, 0x00, 0xE0, 0x07, 0x20, 0x2F, 0x20, 0x00, 0xE0, 0xA3, 0x0F, 0x4F, 0xE9, 0x06, 0x20, 0x00, 0xE0, 0x1F, 0x26, 0x1F, 0xDF, 0x17, 0x26, 0x17, 0xDF, 0xA1, 0x1F, 0x4F, 0xE9, 0x1E, 0x26, 0x1E, 0xDF, 0x9D, 0x1E, 0x4F, 0xE9, 0x35, 0x17, 0x4F, 0xE9, 0xA2, 0x3F, 0x4F, 0xE9, 0x06, 0x06, 0x1F, 0xAF, 0x39, 0x37, 0x4F, 0xE9, 0x2F, 0x2F, 0x17, 0xAF, 0x07, 0x07, 0x1E, 0xAF, 0xA0, 0x80, 0x4F, 0xE9, 0x9E, 0x3E, 0x4F, 0xE9, 0x31, 0x80, 0x4F, 0xE9, 0x9C, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x57, 0x39, 0x20, 0xE9, 0x16, 0x28, 0x20, 0xE9, 0x1D, 0x3B, 0x20, 0xE9, 0x1E, 0x2B, 0x20, 0xE9, 0x2B, 0x32, 0x20, 0xE9, 0x1C, 0x23, 0x20, 0xE9, 0x57, 0x36, 0x20, 0xE9, 0x00, 0x80, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x90, 0xE2, 0x00, 0xE0, 0x63, 0xFF, 0x20, 0xEA, 0x19, 0xC8, 0xC1, 0xCD, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x9F, 0x41, 0x49, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x41, 0x49, 0xBD, 0x2D, 0x41, 0x51, 0xBD, 0x0D, 0x80, 0x07, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x35, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x30, 0x2D, 0x30, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0xA7, 0x5B, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x62, 0xFF, 0x0A, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0xC9, 0x41, 0xC8, 0xEC, 0x42, 0xE1, 0x00, 0xE0, 0x60, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xC8, 0x40, 0xC0, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x5D, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, }; static unsigned char warp_g200_tgzsf[] = { 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x98, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x81, 0x04, 0x89, 0x04, 0x01, 0x04, 0x09, 0x04, 0xC9, 0x41, 0xC0, 0xEC, 0x11, 0x04, 0x00, 0xE0, 0x41, 0xCC, 0x41, 0xCD, 0x49, 0xCC, 0x49, 0xCD, 0xD1, 0x41, 0xC0, 0xEC, 0x51, 0xCC, 0x51, 0xCD, 0x80, 0x04, 0x10, 0x04, 0x08, 0x04, 0x00, 0xE0, 0x00, 0xCC, 0xC0, 0xCD, 0xD1, 0x49, 0xC0, 0xEC, 0x8A, 0x1F, 0x20, 0xE9, 0x8B, 0x3F, 0x20, 0xE9, 0x41, 0x3C, 0x41, 0xAD, 0x49, 0x3C, 0x49, 0xAD, 0x10, 0xCC, 0x10, 0xCD, 0x08, 0xCC, 0x08, 0xCD, 0xB9, 0x41, 0x49, 0xBB, 0x1F, 0xF0, 0x41, 0xCD, 0x51, 0x3C, 0x51, 0xAD, 0x00, 0x98, 0x80, 0xE9, 0x8F, 0x80, 0x07, 0xEA, 0x24, 0x1F, 0x20, 0xE9, 0x21, 0x45, 0x80, 0xE8, 0x1A, 0x4D, 0x80, 0xE8, 0x31, 0x55, 0x80, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0x41, 0x49, 0xBD, 0x1D, 0x41, 0x51, 0xBD, 0x2E, 0x41, 0x2A, 0xB8, 0x34, 0x53, 0xA0, 0xE8, 0x15, 0x30, 0x1D, 0x30, 0x58, 0xE3, 0x00, 0xE0, 0xB5, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x24, 0x43, 0xA0, 0xE8, 0x2C, 0x4B, 0xA0, 0xE8, 0x15, 0x72, 0x09, 0xE3, 0x00, 0xE0, 0x1D, 0x72, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0x97, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x6C, 0x64, 0xC8, 0xEC, 0x98, 0xE1, 0xB5, 0x05, 0xBD, 0x05, 0x2E, 0x30, 0x32, 0xC0, 0xA0, 0xE8, 0x33, 0xC0, 0xA0, 0xE8, 0x74, 0x64, 0xC8, 0xEC, 0x40, 0x3C, 0x40, 0xAD, 0x32, 0x6A, 0x2A, 0x30, 0x20, 0x73, 0x33, 0x6A, 0x00, 0xE0, 0x28, 0x73, 0x1C, 0x72, 0x83, 0xE2, 0x7B, 0x80, 0x15, 0xEA, 0xB8, 0x3D, 0x28, 0xDF, 0x30, 0x35, 0x20, 0xDF, 0x40, 0x30, 0x00, 0xE0, 0xCC, 0xE2, 0x64, 0x72, 0x25, 0x42, 0x52, 0xBF, 0x2D, 0x42, 0x4A, 0xBF, 0x30, 0x2E, 0x30, 0xDF, 0x38, 0x2E, 0x38, 0xDF, 0x18, 0x1D, 0x45, 0xE9, 0x1E, 0x15, 0x45, 0xE9, 0x2B, 0x49, 0x51, 0xBD, 0x00, 0xE0, 0x1F, 0x73, 0x38, 0x38, 0x40, 0xAF, 0x30, 0x30, 0x40, 0xAF, 0x24, 0x1F, 0x24, 0xDF, 0x1D, 0x32, 0x20, 0xE9, 0x2C, 0x1F, 0x2C, 0xDF, 0x1A, 0x33, 0x20, 0xE9, 0xB0, 0x10, 0x08, 0xE3, 0x40, 0x10, 0xB8, 0x10, 0x26, 0xF0, 0x30, 0xCD, 0x2F, 0xF0, 0x38, 0xCD, 0x2B, 0x80, 0x20, 0xE9, 0x2A, 0x80, 0x20, 0xE9, 0xA6, 0x20, 0x88, 0xE2, 0x00, 0xE0, 0xAF, 0x20, 0x28, 0x2A, 0x26, 0xAF, 0x20, 0x2A, 0xC0, 0xAF, 0x34, 0x1F, 0x34, 0xDF, 0x46, 0x24, 0x46, 0xDF, 0x28, 0x30, 0x80, 0xBF, 0x20, 0x38, 0x80, 0xBF, 0x47, 0x24, 0x47, 0xDF, 0x4E, 0x2C, 0x4E, 0xDF, 0x4F, 0x2C, 0x4F, 0xDF, 0x56, 0x34, 0x56, 0xDF, 0x28, 0x15, 0x28, 0xDF, 0x20, 0x1D, 0x20, 0xDF, 0x57, 0x34, 0x57, 0xDF, 0x00, 0xE0, 0x1D, 0x05, 0x04, 0x80, 0x10, 0xEA, 0x89, 0xE2, 0x2B, 0x30, 0x3F, 0xC1, 0x1D, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x68, 0xBF, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x20, 0xC0, 0x20, 0xAF, 0x28, 0x05, 0x97, 0x74, 0x00, 0xE0, 0x2A, 0x10, 0x16, 0xC0, 0x20, 0xE9, 0x04, 0x80, 0x10, 0xEA, 0x8C, 0xE2, 0x95, 0x05, 0x28, 0xC1, 0x28, 0xAD, 0x1F, 0xC1, 0x15, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xA8, 0x67, 0x9F, 0x6B, 0x00, 0x80, 0x00, 0xE8, 0x28, 0xC0, 0x28, 0xAD, 0x1D, 0x25, 0x20, 0x05, 0x28, 0x32, 0x80, 0xAD, 0x40, 0x2A, 0x40, 0xBD, 0x1C, 0x80, 0x20, 0xE9, 0x20, 0x33, 0x20, 0xAD, 0x20, 0x73, 0x00, 0xE0, 0xB6, 0x49, 0x51, 0xBB, 0x26, 0x2F, 0xB0, 0xE8, 0x19, 0x20, 0x20, 0xE9, 0x35, 0x20, 0x35, 0xDF, 0x3D, 0x20, 0x3D, 0xDF, 0x15, 0x20, 0x15, 0xDF, 0x1D, 0x20, 0x1D, 0xDF, 0x26, 0xD0, 0x26, 0xCD, 0x29, 0x49, 0x2A, 0xB8, 0x26, 0x40, 0x80, 0xBD, 0x3B, 0x48, 0x50, 0xBD, 0x3E, 0x54, 0x57, 0x9F, 0x00, 0xE0, 0x82, 0xE1, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x26, 0x30, 0x29, 0x30, 0x48, 0x3C, 0x48, 0xAD, 0x2B, 0x72, 0xC2, 0xE1, 0x2C, 0xC0, 0x44, 0xC2, 0x05, 0x24, 0x34, 0xBF, 0x0D, 0x24, 0x2C, 0xBF, 0x2D, 0x46, 0x4E, 0xBF, 0x25, 0x46, 0x56, 0xBF, 0x20, 0x1D, 0x6F, 0x8F, 0x32, 0x3E, 0x5F, 0xE9, 0x3E, 0x50, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x30, 0x1E, 0x8F, 0x51, 0x9F, 0x33, 0x1E, 0x5F, 0xE9, 0x05, 0x44, 0x54, 0xB2, 0x0D, 0x44, 0x4C, 0xB2, 0x19, 0xC0, 0xB0, 0xE8, 0x34, 0xC0, 0x44, 0xC4, 0x33, 0x73, 0x00, 0xE0, 0x3E, 0x62, 0x57, 0x9F, 0x1E, 0xAF, 0x59, 0x9F, 0x00, 0xE0, 0x0D, 0x20, 0x84, 0x3E, 0x58, 0xE9, 0x28, 0x1D, 0x6F, 0x8F, 0x05, 0x20, 0x00, 0xE0, 0x85, 0x1E, 0x58, 0xE9, 0x9B, 0x3B, 0x33, 0xDF, 0x20, 0x20, 0x42, 0xAF, 0x30, 0x42, 0x56, 0x9F, 0x80, 0x3E, 0x57, 0xE9, 0x3F, 0x8F, 0x51, 0x9F, 0x30, 0x80, 0x5F, 0xE9, 0x28, 0x28, 0x24, 0xAF, 0x81, 0x1E, 0x57, 0xE9, 0x05, 0x47, 0x57, 0xBF, 0x0D, 0x47, 0x4F, 0xBF, 0x88, 0x80, 0x58, 0xE9, 0x1B, 0x29, 0x1B, 0xDF, 0x30, 0x1D, 0x6F, 0x8F, 0x3A, 0x30, 0x4F, 0xE9, 0x1C, 0x30, 0x26, 0xDF, 0x09, 0xE3, 0x3B, 0x05, 0x3E, 0x50, 0x56, 0x9F, 0x3B, 0x3F, 0x4F, 0xE9, 0x1E, 0x8F, 0x51, 0x9F, 0x00, 0xE0, 0xAC, 0x20, 0x2D, 0x44, 0x4C, 0xB4, 0x2C, 0x1C, 0xC0, 0xAF, 0x25, 0x44, 0x54, 0xB4, 0x00, 0xE0, 0xC8, 0x30, 0x30, 0x46, 0x30, 0xAF, 0x1B, 0x1B, 0x48, 0xAF, 0x00, 0xE0, 0x25, 0x20, 0x38, 0x2C, 0x4F, 0xE9, 0x86, 0x80, 0x57, 0xE9, 0x38, 0x1D, 0x6F, 0x8F, 0x28, 0x74, 0x00, 0xE0, 0x0D, 0x44, 0x4C, 0xB0, 0x05, 0x44, 0x54, 0xB0, 0x2D, 0x20, 0x9B, 0x10, 0x82, 0x3E, 0x57, 0xE9, 0x32, 0xF0, 0x1B, 0xCD, 0x1E, 0xBD, 0x59, 0x9F, 0x83, 0x1E, 0x57, 0xE9, 0x38, 0x47, 0x38, 0xAF, 0x34, 0x20, 0x2A, 0x30, 0x00, 0xE0, 0x0D, 0x20, 0x32, 0x20, 0x05, 0x20, 0x87, 0x80, 0x57, 0xE9, 0x1F, 0x54, 0x57, 0x9F, 0x17, 0x42, 0x56, 0x9F, 0x00, 0xE0, 0x3B, 0x6A, 0x3F, 0x8F, 0x51, 0x9F, 0x37, 0x1E, 0x4F, 0xE9, 0x37, 0x32, 0x2A, 0xAF, 0x00, 0xE0, 0x32, 0x00, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xC0, 0x44, 0xC0, 0x36, 0x1F, 0x4F, 0xE9, 0x1F, 0x1F, 0x26, 0xDF, 0x37, 0x1B, 0x37, 0xBF, 0x17, 0x26, 0x17, 0xDF, 0x3E, 0x17, 0x4F, 0xE9, 0x3F, 0x3F, 0x4F, 0xE9, 0x34, 0x1F, 0x34, 0xAF, 0x2B, 0x05, 0xA7, 0x20, 0x33, 0x2B, 0x37, 0xDF, 0x27, 0x17, 0xC0, 0xAF, 0x34, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2D, 0x21, 0x1A, 0xB0, 0x25, 0x21, 0x31, 0xB0, 0x0D, 0x21, 0x1A, 0xB2, 0x05, 0x21, 0x31, 0xB2, 0x03, 0x80, 0x2A, 0xEA, 0x17, 0xC1, 0x2B, 0xBD, 0x2D, 0x20, 0x25, 0x20, 0x05, 0x20, 0x0D, 0x20, 0xB3, 0x68, 0x97, 0x25, 0x00, 0x80, 0x00, 0xE8, 0x33, 0xC0, 0x33, 0xAF, 0x2F, 0xC0, 0x21, 0xC0, 0x16, 0x42, 0x56, 0x9F, 0x3C, 0x27, 0x4F, 0xE9, 0x1E, 0x62, 0x57, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x21, 0x31, 0xB4, 0x2D, 0x21, 0x1A, 0xB4, 0x3F, 0x2F, 0x5D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x33, 0x05, 0x00, 0xE0, 0x28, 0x19, 0x60, 0xEC, 0x0D, 0x21, 0x1A, 0xB6, 0x05, 0x21, 0x31, 0xB6, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0xE0, 0x2F, 0x20, 0x23, 0x3B, 0x33, 0xAD, 0x1E, 0x26, 0x1E, 0xDF, 0xA7, 0x1E, 0x4F, 0xE9, 0x17, 0x26, 0x16, 0xDF, 0x2D, 0x20, 0x00, 0xE0, 0xA8, 0x3F, 0x4F, 0xE9, 0x2F, 0x2F, 0x1E, 0xAF, 0x25, 0x20, 0x00, 0xE0, 0xA4, 0x16, 0x4F, 0xE9, 0x0F, 0xC0, 0x21, 0xC2, 0xA6, 0x80, 0x4F, 0xE9, 0x1F, 0x62, 0x57, 0x9F, 0x0D, 0x20, 0x05, 0x20, 0x2F, 0xC0, 0x21, 0xC6, 0x3F, 0x2F, 0x5D, 0x9F, 0x00, 0xE0, 0x0F, 0x20, 0x17, 0x50, 0x56, 0x9F, 0xA5, 0x37, 0x4F, 0xE9, 0x06, 0xC0, 0x21, 0xC4, 0x0F, 0x17, 0x0F, 0xAF, 0x37, 0x0F, 0x5C, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x2F, 0x20, 0x00, 0xE0, 0xA3, 0x80, 0x4F, 0xE9, 0x06, 0x20, 0x00, 0xE0, 0x1F, 0x26, 0x1F, 0xDF, 0x17, 0x26, 0x17, 0xDF, 0x35, 0x17, 0x4F, 0xE9, 0xA1, 0x1F, 0x4F, 0xE9, 0xA2, 0x3F, 0x4F, 0xE9, 0x06, 0x06, 0x1F, 0xAF, 0x39, 0x37, 0x4F, 0xE9, 0x2F, 0x2F, 0x17, 0xAF, 0x00, 0x80, 0x00, 0xE8, 0xA0, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x31, 0x80, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x57, 0x39, 0x20, 0xE9, 0x16, 0x28, 0x20, 0xE9, 0x1D, 0x3B, 0x20, 0xE9, 0x1E, 0x2B, 0x20, 0xE9, 0x2B, 0x32, 0x20, 0xE9, 0x1C, 0x23, 0x20, 0xE9, 0x57, 0x36, 0x20, 0xE9, 0x00, 0x80, 0xA0, 0xE9, 0x40, 0x40, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x90, 0xE2, 0x00, 0xE0, 0x68, 0xFF, 0x20, 0xEA, 0x19, 0xC8, 0xC1, 0xCD, 0x1F, 0xD7, 0x18, 0xBD, 0x3F, 0xD7, 0x22, 0xBD, 0x9F, 0x41, 0x49, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x41, 0x49, 0xBD, 0x2D, 0x41, 0x51, 0xBD, 0x0D, 0x80, 0x07, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x35, 0x40, 0x48, 0xBD, 0x3D, 0x40, 0x50, 0xBD, 0x00, 0x80, 0x00, 0xE8, 0x25, 0x30, 0x2D, 0x30, 0x35, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0x3D, 0x30, 0x9C, 0xA7, 0x5B, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x67, 0xFF, 0x0A, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0xC9, 0x41, 0xC8, 0xEC, 0x42, 0xE1, 0x00, 0xE0, 0x65, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0xC8, 0x40, 0xC0, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x62, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, }; static unsigned char warp_g400_t2gz[] = { 0x00, 0x8A, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0A, 0x40, 0x50, 0xBF, 0x2A, 0x40, 0x60, 0xBF, 0x32, 0x41, 0x51, 0xBF, 0x3A, 0x41, 0x61, 0xBF, 0xC3, 0x6B, 0xD3, 0x6B, 0x00, 0x8A, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x53, 0xA0, 0xE8, 0xAD, 0xEE, 0x23, 0x9F, 0x00, 0xE0, 0x51, 0x04, 0x90, 0xE2, 0x61, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x51, 0x41, 0xE0, 0xEC, 0x39, 0x67, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x63, 0xA0, 0xE8, 0x61, 0x41, 0xE0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x78, 0x80, 0x15, 0xEA, 0x10, 0x04, 0x20, 0x04, 0x61, 0x51, 0xE0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x52, 0xBF, 0x0F, 0x52, 0xA0, 0xE8, 0x1A, 0x42, 0x62, 0xBF, 0x1E, 0x51, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x0E, 0x61, 0x60, 0xEA, 0x32, 0x40, 0x50, 0xBD, 0x22, 0x40, 0x60, 0xBD, 0x12, 0x41, 0x51, 0xBD, 0x3A, 0x41, 0x61, 0xBD, 0xBF, 0x2F, 0x0E, 0xBD, 0x97, 0xE2, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x35, 0x48, 0xB1, 0xE8, 0x3D, 0x59, 0xB1, 0xE8, 0x46, 0x31, 0x46, 0xBF, 0x56, 0x31, 0x56, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x66, 0x31, 0x66, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x67, 0x39, 0x67, 0xBF, 0x69, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x35, 0x00, 0x3D, 0x00, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0x8D, 0x2F, 0x1E, 0xBD, 0x43, 0x75, 0xF8, 0xEC, 0x35, 0x20, 0x3D, 0x20, 0x43, 0x43, 0x2D, 0xDF, 0x53, 0x53, 0x2D, 0xDF, 0xAE, 0x1E, 0x0E, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x48, 0x35, 0x48, 0xBF, 0x58, 0x35, 0x58, 0xBF, 0x68, 0x35, 0x68, 0xBF, 0x49, 0x3D, 0x49, 0xBF, 0x59, 0x3D, 0x59, 0xBF, 0x69, 0x3D, 0x69, 0xBF, 0x63, 0x63, 0x2D, 0xDF, 0x4D, 0x7D, 0xF8, 0xEC, 0x59, 0xE3, 0x00, 0xE0, 0xB8, 0x38, 0x33, 0xBF, 0x2D, 0x73, 0x30, 0x76, 0x18, 0x3A, 0x41, 0xE9, 0x3F, 0x53, 0xA0, 0xE8, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x63, 0xA0, 0xE8, 0x50, 0x70, 0xF8, 0xEC, 0x2B, 0x50, 0x3C, 0xE9, 0x1F, 0x0F, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x59, 0x78, 0xF8, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x46, 0x37, 0x46, 0xDF, 0x56, 0x3F, 0x56, 0xDF, 0x2B, 0x40, 0x3D, 0xE9, 0x66, 0x3D, 0x66, 0xDF, 0x1D, 0x32, 0x41, 0xE9, 0x67, 0x3D, 0x67, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3F, 0x57, 0xDF, 0x2A, 0x40, 0x20, 0xE9, 0x59, 0x3F, 0x59, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x69, 0x3D, 0x69, 0xDF, 0x48, 0x37, 0x48, 0xDF, 0x58, 0x3F, 0x58, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x68, 0x3D, 0x68, 0xDF, 0x49, 0x37, 0x49, 0xDF, 0x3D, 0xCF, 0x74, 0xC0, 0x37, 0xCF, 0x74, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0x34, 0x80, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x0A, 0x44, 0x54, 0xB0, 0x02, 0x44, 0x64, 0xB0, 0x2A, 0x44, 0x54, 0xB2, 0x1A, 0x44, 0x64, 0xB2, 0x25, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x3D, 0xCF, 0x74, 0xC2, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x2A, 0x44, 0x54, 0xB4, 0x1A, 0x44, 0x64, 0xB4, 0x39, 0xE5, 0x2C, 0x9F, 0x38, 0x3D, 0x20, 0xE9, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x56, 0xBF, 0x1A, 0x46, 0x66, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x0A, 0x47, 0x57, 0xBF, 0x02, 0x47, 0x67, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x43, 0x53, 0xBF, 0x1A, 0x43, 0x63, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x0A, 0x48, 0x58, 0xBF, 0x02, 0x48, 0x68, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x2A, 0x49, 0x59, 0xBF, 0x1A, 0x49, 0x69, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x82, 0x30, 0x57, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x83, 0x38, 0x57, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x84, 0x31, 0x5E, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x85, 0x39, 0x5E, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8A, 0x36, 0x20, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x8B, 0x3E, 0xBF, 0xEA, 0x80, 0x30, 0x57, 0xE9, 0x81, 0x38, 0x57, 0xE9, 0x82, 0x31, 0x57, 0xE9, 0x86, 0x78, 0x57, 0xE9, 0x83, 0x39, 0x57, 0xE9, 0x87, 0x79, 0x57, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x8A, 0x34, 0x20, 0xE9, 0x8B, 0x3C, 0x20, 0xE9, 0x37, 0x50, 0x60, 0xBD, 0x57, 0x0D, 0x20, 0xE9, 0x35, 0x51, 0x61, 0xBD, 0x2B, 0x50, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x0E, 0x77, 0x24, 0x51, 0x20, 0xE9, 0x9F, 0xFF, 0x20, 0xEA, 0x16, 0x0E, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x0B, 0x46, 0xA0, 0xE8, 0x1B, 0x56, 0xA0, 0xE8, 0x2B, 0x66, 0xA0, 0xE8, 0x0C, 0x47, 0xA0, 0xE8, 0x1C, 0x57, 0xA0, 0xE8, 0x2C, 0x67, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x57, 0x80, 0x57, 0xCF, 0x66, 0x33, 0x66, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x67, 0x3B, 0x67, 0xCF, 0x0B, 0x48, 0xA0, 0xE8, 0x1B, 0x58, 0xA0, 0xE8, 0x2B, 0x68, 0xA0, 0xE8, 0x0C, 0x49, 0xA0, 0xE8, 0x1C, 0x59, 0xA0, 0xE8, 0x2C, 0x69, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x34, 0xD7, 0x34, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3C, 0xD7, 0x3C, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x34, 0x80, 0x34, 0xBD, 0x3C, 0x80, 0x3C, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x48, 0x80, 0x48, 0xCF, 0x59, 0x80, 0x59, 0xCF, 0x68, 0x33, 0x68, 0xCF, 0x49, 0x3B, 0x49, 0xCF, 0xBE, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x58, 0x33, 0x58, 0xCF, 0x69, 0x3B, 0x69, 0xCF, 0x7D, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_t2gza[] = { 0x00, 0x8A, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0A, 0x40, 0x50, 0xBF, 0x2A, 0x40, 0x60, 0xBF, 0x32, 0x41, 0x51, 0xBF, 0x3A, 0x41, 0x61, 0xBF, 0xC3, 0x6B, 0xD3, 0x6B, 0x00, 0x8A, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x53, 0xA0, 0xE8, 0xAD, 0xEE, 0x23, 0x9F, 0x00, 0xE0, 0x51, 0x04, 0x90, 0xE2, 0x61, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x51, 0x41, 0xE0, 0xEC, 0x39, 0x67, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x63, 0xA0, 0xE8, 0x61, 0x41, 0xE0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x7C, 0x80, 0x15, 0xEA, 0x10, 0x04, 0x20, 0x04, 0x61, 0x51, 0xE0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x52, 0xBF, 0x0F, 0x52, 0xA0, 0xE8, 0x1A, 0x42, 0x62, 0xBF, 0x1E, 0x51, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x0E, 0x61, 0x60, 0xEA, 0x32, 0x40, 0x50, 0xBD, 0x22, 0x40, 0x60, 0xBD, 0x12, 0x41, 0x51, 0xBD, 0x3A, 0x41, 0x61, 0xBD, 0xBF, 0x2F, 0x0E, 0xBD, 0x97, 0xE2, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x35, 0x48, 0xB1, 0xE8, 0x3D, 0x59, 0xB1, 0xE8, 0x46, 0x31, 0x46, 0xBF, 0x56, 0x31, 0x56, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x66, 0x31, 0x66, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x67, 0x39, 0x67, 0xBF, 0x6D, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x35, 0x00, 0x3D, 0x00, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0x8D, 0x2F, 0x1E, 0xBD, 0x43, 0x75, 0xF8, 0xEC, 0x35, 0x20, 0x3D, 0x20, 0x43, 0x43, 0x2D, 0xDF, 0x53, 0x53, 0x2D, 0xDF, 0xAE, 0x1E, 0x0E, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x48, 0x35, 0x48, 0xBF, 0x58, 0x35, 0x58, 0xBF, 0x68, 0x35, 0x68, 0xBF, 0x49, 0x3D, 0x49, 0xBF, 0x59, 0x3D, 0x59, 0xBF, 0x69, 0x3D, 0x69, 0xBF, 0x63, 0x63, 0x2D, 0xDF, 0x4D, 0x7D, 0xF8, 0xEC, 0x59, 0xE3, 0x00, 0xE0, 0xB8, 0x38, 0x33, 0xBF, 0x2D, 0x73, 0x30, 0x76, 0x18, 0x3A, 0x41, 0xE9, 0x3F, 0x53, 0xA0, 0xE8, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x63, 0xA0, 0xE8, 0x50, 0x70, 0xF8, 0xEC, 0x2B, 0x50, 0x3C, 0xE9, 0x1F, 0x0F, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x59, 0x78, 0xF8, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x46, 0x37, 0x46, 0xDF, 0x56, 0x3F, 0x56, 0xDF, 0x2B, 0x40, 0x3D, 0xE9, 0x66, 0x3D, 0x66, 0xDF, 0x1D, 0x32, 0x41, 0xE9, 0x67, 0x3D, 0x67, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3F, 0x57, 0xDF, 0x2A, 0x40, 0x20, 0xE9, 0x59, 0x3F, 0x59, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x69, 0x3D, 0x69, 0xDF, 0x48, 0x37, 0x48, 0xDF, 0x58, 0x3F, 0x58, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x68, 0x3D, 0x68, 0xDF, 0x49, 0x37, 0x49, 0xDF, 0x3D, 0xCF, 0x74, 0xC0, 0x37, 0xCF, 0x74, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0x34, 0x80, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x0A, 0x44, 0x54, 0xB0, 0x02, 0x44, 0x64, 0xB0, 0x2A, 0x44, 0x54, 0xB2, 0x1A, 0x44, 0x64, 0xB2, 0x29, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x0F, 0xCF, 0x74, 0xC6, 0x3D, 0xCF, 0x74, 0xC2, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x9C, 0x0F, 0x20, 0xE9, 0x0A, 0x44, 0x54, 0xB4, 0x02, 0x44, 0x64, 0xB4, 0x2A, 0x44, 0x54, 0xB6, 0x1A, 0x44, 0x64, 0xB6, 0x39, 0xE5, 0x2C, 0x9F, 0x38, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x20, 0x1A, 0x20, 0x0A, 0x47, 0x57, 0xBF, 0x02, 0x47, 0x67, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x2A, 0x46, 0x56, 0xBF, 0x1A, 0x46, 0x66, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x36, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x37, 0x38, 0x4F, 0xE9, 0x2A, 0x43, 0x53, 0xBF, 0x1A, 0x43, 0x63, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x9D, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x9E, 0x39, 0x4F, 0xE9, 0x0A, 0x48, 0x58, 0xBF, 0x02, 0x48, 0x68, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x2A, 0x49, 0x59, 0xBF, 0x1A, 0x49, 0x69, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x82, 0x30, 0x57, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x83, 0x38, 0x57, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x84, 0x31, 0x5E, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x85, 0x39, 0x5E, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8A, 0x36, 0x20, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x8B, 0x3E, 0xBF, 0xEA, 0x80, 0x30, 0x57, 0xE9, 0x81, 0x38, 0x57, 0xE9, 0x82, 0x31, 0x57, 0xE9, 0x86, 0x78, 0x57, 0xE9, 0x83, 0x39, 0x57, 0xE9, 0x87, 0x79, 0x57, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x8A, 0x34, 0x20, 0xE9, 0x8B, 0x3C, 0x20, 0xE9, 0x37, 0x50, 0x60, 0xBD, 0x57, 0x0D, 0x20, 0xE9, 0x35, 0x51, 0x61, 0xBD, 0x2B, 0x50, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x0E, 0x77, 0x24, 0x51, 0x20, 0xE9, 0x9B, 0xFF, 0x20, 0xEA, 0x16, 0x0E, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x0B, 0x46, 0xA0, 0xE8, 0x1B, 0x56, 0xA0, 0xE8, 0x2B, 0x66, 0xA0, 0xE8, 0x0C, 0x47, 0xA0, 0xE8, 0x1C, 0x57, 0xA0, 0xE8, 0x2C, 0x67, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x57, 0x80, 0x57, 0xCF, 0x66, 0x33, 0x66, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x67, 0x3B, 0x67, 0xCF, 0x0B, 0x48, 0xA0, 0xE8, 0x1B, 0x58, 0xA0, 0xE8, 0x2B, 0x68, 0xA0, 0xE8, 0x0C, 0x49, 0xA0, 0xE8, 0x1C, 0x59, 0xA0, 0xE8, 0x2C, 0x69, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x34, 0xD7, 0x34, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3C, 0xD7, 0x3C, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x34, 0x80, 0x34, 0xBD, 0x3C, 0x80, 0x3C, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x48, 0x80, 0x48, 0xCF, 0x59, 0x80, 0x59, 0xCF, 0x68, 0x33, 0x68, 0xCF, 0x49, 0x3B, 0x49, 0xCF, 0xBA, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x58, 0x33, 0x58, 0xCF, 0x69, 0x3B, 0x69, 0xCF, 0x79, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_t2gzaf[] = { 0x00, 0x8A, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0A, 0x40, 0x50, 0xBF, 0x2A, 0x40, 0x60, 0xBF, 0x32, 0x41, 0x51, 0xBF, 0x3A, 0x41, 0x61, 0xBF, 0xC3, 0x6B, 0xD3, 0x6B, 0x00, 0x8A, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x53, 0xA0, 0xE8, 0xAD, 0xEE, 0x23, 0x9F, 0x00, 0xE0, 0x51, 0x04, 0x90, 0xE2, 0x61, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x51, 0x41, 0xE0, 0xEC, 0x39, 0x67, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x63, 0xA0, 0xE8, 0x61, 0x41, 0xE0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x81, 0x80, 0x15, 0xEA, 0x10, 0x04, 0x20, 0x04, 0x61, 0x51, 0xE0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x52, 0xBF, 0x0F, 0x52, 0xA0, 0xE8, 0x1A, 0x42, 0x62, 0xBF, 0x1E, 0x51, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x0E, 0x61, 0x60, 0xEA, 0x32, 0x40, 0x50, 0xBD, 0x22, 0x40, 0x60, 0xBD, 0x12, 0x41, 0x51, 0xBD, 0x3A, 0x41, 0x61, 0xBD, 0xBF, 0x2F, 0x0E, 0xBD, 0x97, 0xE2, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x35, 0x48, 0xB1, 0xE8, 0x3D, 0x59, 0xB1, 0xE8, 0x46, 0x31, 0x46, 0xBF, 0x56, 0x31, 0x56, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x66, 0x31, 0x66, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x67, 0x39, 0x67, 0xBF, 0x72, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x35, 0x00, 0x3D, 0x00, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0x8D, 0x2F, 0x1E, 0xBD, 0x43, 0x75, 0xF8, 0xEC, 0x35, 0x20, 0x3D, 0x20, 0x43, 0x43, 0x2D, 0xDF, 0x53, 0x53, 0x2D, 0xDF, 0xAE, 0x1E, 0x0E, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x48, 0x35, 0x48, 0xBF, 0x58, 0x35, 0x58, 0xBF, 0x68, 0x35, 0x68, 0xBF, 0x49, 0x3D, 0x49, 0xBF, 0x59, 0x3D, 0x59, 0xBF, 0x69, 0x3D, 0x69, 0xBF, 0x63, 0x63, 0x2D, 0xDF, 0x4D, 0x7D, 0xF8, 0xEC, 0x59, 0xE3, 0x00, 0xE0, 0xB8, 0x38, 0x33, 0xBF, 0x2D, 0x73, 0x30, 0x76, 0x18, 0x3A, 0x41, 0xE9, 0x3F, 0x53, 0xA0, 0xE8, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x63, 0xA0, 0xE8, 0x50, 0x70, 0xF8, 0xEC, 0x2B, 0x50, 0x3C, 0xE9, 0x1F, 0x0F, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x59, 0x78, 0xF8, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x46, 0x37, 0x46, 0xDF, 0x56, 0x3F, 0x56, 0xDF, 0x2B, 0x40, 0x3D, 0xE9, 0x66, 0x3D, 0x66, 0xDF, 0x1D, 0x32, 0x41, 0xE9, 0x67, 0x3D, 0x67, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3F, 0x57, 0xDF, 0x2A, 0x40, 0x20, 0xE9, 0x59, 0x3F, 0x59, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x69, 0x3D, 0x69, 0xDF, 0x48, 0x37, 0x48, 0xDF, 0x58, 0x3F, 0x58, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x68, 0x3D, 0x68, 0xDF, 0x49, 0x37, 0x49, 0xDF, 0x3D, 0xCF, 0x74, 0xC0, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x54, 0xB0, 0x02, 0x44, 0x64, 0xB0, 0x31, 0x53, 0x2F, 0x9F, 0x34, 0x37, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB2, 0x1A, 0x44, 0x64, 0xB2, 0x2E, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0x3D, 0xCF, 0x74, 0xC2, 0x0F, 0xCF, 0x74, 0xC6, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x9C, 0x0F, 0x20, 0xE9, 0x0A, 0x44, 0x54, 0xB4, 0x02, 0x44, 0x64, 0xB4, 0x2A, 0x44, 0x54, 0xB6, 0x1A, 0x44, 0x64, 0xB6, 0x39, 0xE5, 0x2C, 0x9F, 0x38, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x20, 0x1A, 0x20, 0x3D, 0xCF, 0x75, 0xC6, 0x00, 0x80, 0x00, 0xE8, 0x30, 0x50, 0x2E, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x0A, 0x45, 0x55, 0xB6, 0x02, 0x45, 0x65, 0xB6, 0x31, 0x53, 0x2F, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x31, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x46, 0x56, 0xBF, 0x1A, 0x46, 0x66, 0xBF, 0x0A, 0x47, 0x57, 0xBF, 0x02, 0x47, 0x67, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x38, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x9D, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x9E, 0x39, 0x4F, 0xE9, 0x2A, 0x43, 0x53, 0xBF, 0x1A, 0x43, 0x63, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x35, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x39, 0x38, 0x4F, 0xE9, 0x0A, 0x48, 0x58, 0xBF, 0x02, 0x48, 0x68, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x2A, 0x49, 0x59, 0xBF, 0x1A, 0x49, 0x69, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x82, 0x30, 0x57, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x83, 0x38, 0x57, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x84, 0x31, 0x5E, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x85, 0x39, 0x5E, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8A, 0x36, 0x20, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x8B, 0x3E, 0xBF, 0xEA, 0x80, 0x30, 0x57, 0xE9, 0x81, 0x38, 0x57, 0xE9, 0x82, 0x31, 0x57, 0xE9, 0x86, 0x78, 0x57, 0xE9, 0x83, 0x39, 0x57, 0xE9, 0x87, 0x79, 0x57, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x8A, 0x34, 0x20, 0xE9, 0x8B, 0x3C, 0x20, 0xE9, 0x37, 0x50, 0x60, 0xBD, 0x57, 0x0D, 0x20, 0xE9, 0x35, 0x51, 0x61, 0xBD, 0x2B, 0x50, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x0E, 0x77, 0x24, 0x51, 0x20, 0xE9, 0x96, 0xFF, 0x20, 0xEA, 0x16, 0x0E, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x0B, 0x46, 0xA0, 0xE8, 0x1B, 0x56, 0xA0, 0xE8, 0x2B, 0x66, 0xA0, 0xE8, 0x0C, 0x47, 0xA0, 0xE8, 0x1C, 0x57, 0xA0, 0xE8, 0x2C, 0x67, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x57, 0x80, 0x57, 0xCF, 0x66, 0x33, 0x66, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x67, 0x3B, 0x67, 0xCF, 0x0B, 0x48, 0xA0, 0xE8, 0x1B, 0x58, 0xA0, 0xE8, 0x2B, 0x68, 0xA0, 0xE8, 0x0C, 0x49, 0xA0, 0xE8, 0x1C, 0x59, 0xA0, 0xE8, 0x2C, 0x69, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x34, 0xD7, 0x34, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3C, 0xD7, 0x3C, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x34, 0x80, 0x34, 0xBD, 0x3C, 0x80, 0x3C, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x48, 0x80, 0x48, 0xCF, 0x59, 0x80, 0x59, 0xCF, 0x68, 0x33, 0x68, 0xCF, 0x49, 0x3B, 0x49, 0xCF, 0xB5, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x58, 0x33, 0x58, 0xCF, 0x69, 0x3B, 0x69, 0xCF, 0x74, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_t2gzf[] = { 0x00, 0x8A, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0A, 0x40, 0x50, 0xBF, 0x2A, 0x40, 0x60, 0xBF, 0x32, 0x41, 0x51, 0xBF, 0x3A, 0x41, 0x61, 0xBF, 0xC3, 0x6B, 0xD3, 0x6B, 0x00, 0x8A, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x53, 0xA0, 0xE8, 0xAD, 0xEE, 0x23, 0x9F, 0x00, 0xE0, 0x51, 0x04, 0x90, 0xE2, 0x61, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x51, 0x41, 0xE0, 0xEC, 0x39, 0x67, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x63, 0xA0, 0xE8, 0x61, 0x41, 0xE0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x7D, 0x80, 0x15, 0xEA, 0x10, 0x04, 0x20, 0x04, 0x61, 0x51, 0xE0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x52, 0xBF, 0x0F, 0x52, 0xA0, 0xE8, 0x1A, 0x42, 0x62, 0xBF, 0x1E, 0x51, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x0E, 0x61, 0x60, 0xEA, 0x32, 0x40, 0x50, 0xBD, 0x22, 0x40, 0x60, 0xBD, 0x12, 0x41, 0x51, 0xBD, 0x3A, 0x41, 0x61, 0xBD, 0xBF, 0x2F, 0x0E, 0xBD, 0x97, 0xE2, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x35, 0x48, 0xB1, 0xE8, 0x3D, 0x59, 0xB1, 0xE8, 0x46, 0x31, 0x46, 0xBF, 0x56, 0x31, 0x56, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x66, 0x31, 0x66, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x67, 0x39, 0x67, 0xBF, 0x6E, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x35, 0x00, 0x3D, 0x00, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0x8D, 0x2F, 0x1E, 0xBD, 0x43, 0x75, 0xF8, 0xEC, 0x35, 0x20, 0x3D, 0x20, 0x43, 0x43, 0x2D, 0xDF, 0x53, 0x53, 0x2D, 0xDF, 0xAE, 0x1E, 0x0E, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x48, 0x35, 0x48, 0xBF, 0x58, 0x35, 0x58, 0xBF, 0x68, 0x35, 0x68, 0xBF, 0x49, 0x3D, 0x49, 0xBF, 0x59, 0x3D, 0x59, 0xBF, 0x69, 0x3D, 0x69, 0xBF, 0x63, 0x63, 0x2D, 0xDF, 0x4D, 0x7D, 0xF8, 0xEC, 0x59, 0xE3, 0x00, 0xE0, 0xB8, 0x38, 0x33, 0xBF, 0x2D, 0x73, 0x30, 0x76, 0x18, 0x3A, 0x41, 0xE9, 0x3F, 0x53, 0xA0, 0xE8, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x63, 0xA0, 0xE8, 0x50, 0x70, 0xF8, 0xEC, 0x2B, 0x50, 0x3C, 0xE9, 0x1F, 0x0F, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x59, 0x78, 0xF8, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x46, 0x37, 0x46, 0xDF, 0x56, 0x3F, 0x56, 0xDF, 0x2B, 0x40, 0x3D, 0xE9, 0x66, 0x3D, 0x66, 0xDF, 0x1D, 0x32, 0x41, 0xE9, 0x67, 0x3D, 0x67, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3F, 0x57, 0xDF, 0x2A, 0x40, 0x20, 0xE9, 0x59, 0x3F, 0x59, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x69, 0x3D, 0x69, 0xDF, 0x48, 0x37, 0x48, 0xDF, 0x58, 0x3F, 0x58, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x68, 0x3D, 0x68, 0xDF, 0x49, 0x37, 0x49, 0xDF, 0x3D, 0xCF, 0x74, 0xC0, 0x37, 0xCF, 0x74, 0xC4, 0x39, 0xE5, 0x2C, 0x9F, 0x34, 0x80, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x88, 0x73, 0x5E, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0F, 0xCF, 0x75, 0xC6, 0x3C, 0x3D, 0x20, 0xE9, 0x0A, 0x44, 0x54, 0xB0, 0x02, 0x44, 0x64, 0xB0, 0x2A, 0x44, 0x54, 0xB2, 0x1A, 0x44, 0x64, 0xB2, 0x28, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x3D, 0xCF, 0x74, 0xC2, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x31, 0x0F, 0x20, 0xE9, 0x0A, 0x44, 0x54, 0xB4, 0x02, 0x44, 0x64, 0xB4, 0x2A, 0x45, 0x55, 0xB6, 0x1A, 0x45, 0x65, 0xB6, 0x39, 0xE5, 0x2C, 0x9F, 0x38, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x20, 0x1A, 0x20, 0x0A, 0x47, 0x57, 0xBF, 0x02, 0x47, 0x67, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x2A, 0x46, 0x56, 0xBF, 0x1A, 0x46, 0x66, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x36, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x37, 0x38, 0x4F, 0xE9, 0x2A, 0x43, 0x53, 0xBF, 0x1A, 0x43, 0x63, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x35, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x39, 0x39, 0x4F, 0xE9, 0x0A, 0x48, 0x58, 0xBF, 0x02, 0x48, 0x68, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x2A, 0x49, 0x59, 0xBF, 0x1A, 0x49, 0x69, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x82, 0x30, 0x57, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x83, 0x38, 0x57, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x84, 0x31, 0x5E, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x85, 0x39, 0x5E, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8A, 0x36, 0x20, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x8B, 0x3E, 0xBF, 0xEA, 0x80, 0x30, 0x57, 0xE9, 0x81, 0x38, 0x57, 0xE9, 0x82, 0x31, 0x57, 0xE9, 0x86, 0x78, 0x57, 0xE9, 0x83, 0x39, 0x57, 0xE9, 0x87, 0x79, 0x57, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x8A, 0x34, 0x20, 0xE9, 0x8B, 0x3C, 0x20, 0xE9, 0x37, 0x50, 0x60, 0xBD, 0x57, 0x0D, 0x20, 0xE9, 0x35, 0x51, 0x61, 0xBD, 0x2B, 0x50, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x0E, 0x77, 0x24, 0x51, 0x20, 0xE9, 0x9A, 0xFF, 0x20, 0xEA, 0x16, 0x0E, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x0B, 0x46, 0xA0, 0xE8, 0x1B, 0x56, 0xA0, 0xE8, 0x2B, 0x66, 0xA0, 0xE8, 0x0C, 0x47, 0xA0, 0xE8, 0x1C, 0x57, 0xA0, 0xE8, 0x2C, 0x67, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x57, 0x80, 0x57, 0xCF, 0x66, 0x33, 0x66, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x67, 0x3B, 0x67, 0xCF, 0x0B, 0x48, 0xA0, 0xE8, 0x1B, 0x58, 0xA0, 0xE8, 0x2B, 0x68, 0xA0, 0xE8, 0x0C, 0x49, 0xA0, 0xE8, 0x1C, 0x59, 0xA0, 0xE8, 0x2C, 0x69, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x34, 0xD7, 0x34, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3C, 0xD7, 0x3C, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x34, 0x80, 0x34, 0xBD, 0x3C, 0x80, 0x3C, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x48, 0x80, 0x48, 0xCF, 0x59, 0x80, 0x59, 0xCF, 0x68, 0x33, 0x68, 0xCF, 0x49, 0x3B, 0x49, 0xCF, 0xBB, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x58, 0x33, 0x58, 0xCF, 0x69, 0x3B, 0x69, 0xCF, 0x78, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_t2gzs[] = { 0x00, 0x8A, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0A, 0x40, 0x50, 0xBF, 0x2A, 0x40, 0x60, 0xBF, 0x32, 0x41, 0x51, 0xBF, 0x3A, 0x41, 0x61, 0xBF, 0xC3, 0x6B, 0xD3, 0x6B, 0x00, 0x8A, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x53, 0xA0, 0xE8, 0xAD, 0xEE, 0x23, 0x9F, 0x00, 0xE0, 0x51, 0x04, 0x90, 0xE2, 0x61, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x51, 0x41, 0xE0, 0xEC, 0x39, 0x67, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x63, 0xA0, 0xE8, 0x61, 0x41, 0xE0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x85, 0x80, 0x15, 0xEA, 0x10, 0x04, 0x20, 0x04, 0x61, 0x51, 0xE0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x52, 0xBF, 0x0F, 0x52, 0xA0, 0xE8, 0x1A, 0x42, 0x62, 0xBF, 0x1E, 0x51, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x0E, 0x61, 0x60, 0xEA, 0x32, 0x40, 0x50, 0xBD, 0x22, 0x40, 0x60, 0xBD, 0x12, 0x41, 0x51, 0xBD, 0x3A, 0x41, 0x61, 0xBD, 0xBF, 0x2F, 0x0E, 0xBD, 0x97, 0xE2, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x35, 0x48, 0xB1, 0xE8, 0x3D, 0x59, 0xB1, 0xE8, 0x46, 0x31, 0x46, 0xBF, 0x56, 0x31, 0x56, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x66, 0x31, 0x66, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x67, 0x39, 0x67, 0xBF, 0x76, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x35, 0x00, 0x3D, 0x00, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0x8D, 0x2F, 0x1E, 0xBD, 0x43, 0x75, 0xF8, 0xEC, 0x35, 0x20, 0x3D, 0x20, 0x43, 0x43, 0x2D, 0xDF, 0x53, 0x53, 0x2D, 0xDF, 0xAE, 0x1E, 0x0E, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x48, 0x35, 0x48, 0xBF, 0x58, 0x35, 0x58, 0xBF, 0x68, 0x35, 0x68, 0xBF, 0x49, 0x3D, 0x49, 0xBF, 0x59, 0x3D, 0x59, 0xBF, 0x69, 0x3D, 0x69, 0xBF, 0x63, 0x63, 0x2D, 0xDF, 0x4D, 0x7D, 0xF8, 0xEC, 0x59, 0xE3, 0x00, 0xE0, 0xB8, 0x38, 0x33, 0xBF, 0x2D, 0x73, 0x30, 0x76, 0x18, 0x3A, 0x41, 0xE9, 0x3F, 0x53, 0xA0, 0xE8, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x63, 0xA0, 0xE8, 0x50, 0x70, 0xF8, 0xEC, 0x2B, 0x50, 0x3C, 0xE9, 0x1F, 0x0F, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x59, 0x78, 0xF8, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x46, 0x37, 0x46, 0xDF, 0x56, 0x3F, 0x56, 0xDF, 0x2B, 0x40, 0x3D, 0xE9, 0x66, 0x3D, 0x66, 0xDF, 0x1D, 0x32, 0x41, 0xE9, 0x67, 0x3D, 0x67, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3F, 0x57, 0xDF, 0x2A, 0x40, 0x20, 0xE9, 0x59, 0x3F, 0x59, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x69, 0x3D, 0x69, 0xDF, 0x48, 0x37, 0x48, 0xDF, 0x58, 0x3F, 0x58, 0xDF, 0x68, 0x3D, 0x68, 0xDF, 0x49, 0x37, 0x49, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x0F, 0xCF, 0x74, 0xC2, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x54, 0xB0, 0x02, 0x44, 0x64, 0xB0, 0x3D, 0xCF, 0x74, 0xC0, 0x34, 0x37, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x38, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB2, 0x1A, 0x44, 0x64, 0xB2, 0x31, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x0F, 0xCF, 0x75, 0xC0, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x3D, 0xCF, 0x75, 0xC2, 0x37, 0xCF, 0x75, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0xA6, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA3, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB4, 0x1A, 0x44, 0x64, 0xB4, 0x0A, 0x45, 0x55, 0xB0, 0x02, 0x45, 0x65, 0xB0, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0xA0, 0x37, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x2A, 0x45, 0x55, 0xB2, 0x1A, 0x45, 0x65, 0xB2, 0x0A, 0x45, 0x55, 0xB4, 0x02, 0x45, 0x65, 0xB4, 0x38, 0x21, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x46, 0x56, 0xBF, 0x1A, 0x46, 0x66, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0xA7, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0xA8, 0x38, 0x4F, 0xE9, 0x0A, 0x47, 0x57, 0xBF, 0x02, 0x47, 0x67, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA4, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA5, 0x39, 0x4F, 0xE9, 0x2A, 0x43, 0x53, 0xBF, 0x1A, 0x43, 0x63, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0xA1, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0xA2, 0x38, 0x4F, 0xE9, 0x0A, 0x48, 0x58, 0xBF, 0x02, 0x48, 0x68, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x2A, 0x49, 0x59, 0xBF, 0x1A, 0x49, 0x69, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x82, 0x30, 0x57, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x83, 0x38, 0x57, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x84, 0x31, 0x5E, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x85, 0x39, 0x5E, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8A, 0x36, 0x20, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x8B, 0x3E, 0xBF, 0xEA, 0x80, 0x30, 0x57, 0xE9, 0x81, 0x38, 0x57, 0xE9, 0x82, 0x31, 0x57, 0xE9, 0x86, 0x78, 0x57, 0xE9, 0x83, 0x39, 0x57, 0xE9, 0x87, 0x79, 0x57, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x8A, 0x34, 0x20, 0xE9, 0x8B, 0x3C, 0x20, 0xE9, 0x37, 0x50, 0x60, 0xBD, 0x57, 0x0D, 0x20, 0xE9, 0x35, 0x51, 0x61, 0xBD, 0x2B, 0x50, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x0E, 0x77, 0x24, 0x51, 0x20, 0xE9, 0x92, 0xFF, 0x20, 0xEA, 0x16, 0x0E, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x0B, 0x46, 0xA0, 0xE8, 0x1B, 0x56, 0xA0, 0xE8, 0x2B, 0x66, 0xA0, 0xE8, 0x0C, 0x47, 0xA0, 0xE8, 0x1C, 0x57, 0xA0, 0xE8, 0x2C, 0x67, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x57, 0x80, 0x57, 0xCF, 0x66, 0x33, 0x66, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x67, 0x3B, 0x67, 0xCF, 0x0B, 0x48, 0xA0, 0xE8, 0x1B, 0x58, 0xA0, 0xE8, 0x2B, 0x68, 0xA0, 0xE8, 0x0C, 0x49, 0xA0, 0xE8, 0x1C, 0x59, 0xA0, 0xE8, 0x2C, 0x69, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x34, 0xD7, 0x34, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3C, 0xD7, 0x3C, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x34, 0x80, 0x34, 0xBD, 0x3C, 0x80, 0x3C, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x48, 0x80, 0x48, 0xCF, 0x59, 0x80, 0x59, 0xCF, 0x68, 0x33, 0x68, 0xCF, 0x49, 0x3B, 0x49, 0xCF, 0xB2, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x58, 0x33, 0x58, 0xCF, 0x69, 0x3B, 0x69, 0xCF, 0x70, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_t2gzsa[] = { 0x00, 0x8A, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0A, 0x40, 0x50, 0xBF, 0x2A, 0x40, 0x60, 0xBF, 0x32, 0x41, 0x51, 0xBF, 0x3A, 0x41, 0x61, 0xBF, 0xC3, 0x6B, 0xD3, 0x6B, 0x00, 0x8A, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x53, 0xA0, 0xE8, 0xAD, 0xEE, 0x23, 0x9F, 0x00, 0xE0, 0x51, 0x04, 0x90, 0xE2, 0x61, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x51, 0x41, 0xE0, 0xEC, 0x39, 0x67, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x63, 0xA0, 0xE8, 0x61, 0x41, 0xE0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x8A, 0x80, 0x15, 0xEA, 0x10, 0x04, 0x20, 0x04, 0x61, 0x51, 0xE0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x52, 0xBF, 0x0F, 0x52, 0xA0, 0xE8, 0x1A, 0x42, 0x62, 0xBF, 0x1E, 0x51, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x0E, 0x61, 0x60, 0xEA, 0x32, 0x40, 0x50, 0xBD, 0x22, 0x40, 0x60, 0xBD, 0x12, 0x41, 0x51, 0xBD, 0x3A, 0x41, 0x61, 0xBD, 0xBF, 0x2F, 0x0E, 0xBD, 0x97, 0xE2, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x35, 0x48, 0xB1, 0xE8, 0x3D, 0x59, 0xB1, 0xE8, 0x46, 0x31, 0x46, 0xBF, 0x56, 0x31, 0x56, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x66, 0x31, 0x66, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x67, 0x39, 0x67, 0xBF, 0x7B, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x35, 0x00, 0x3D, 0x00, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0x8D, 0x2F, 0x1E, 0xBD, 0x43, 0x75, 0xF8, 0xEC, 0x35, 0x20, 0x3D, 0x20, 0x43, 0x43, 0x2D, 0xDF, 0x53, 0x53, 0x2D, 0xDF, 0xAE, 0x1E, 0x0E, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x48, 0x35, 0x48, 0xBF, 0x58, 0x35, 0x58, 0xBF, 0x68, 0x35, 0x68, 0xBF, 0x49, 0x3D, 0x49, 0xBF, 0x59, 0x3D, 0x59, 0xBF, 0x69, 0x3D, 0x69, 0xBF, 0x63, 0x63, 0x2D, 0xDF, 0x4D, 0x7D, 0xF8, 0xEC, 0x59, 0xE3, 0x00, 0xE0, 0xB8, 0x38, 0x33, 0xBF, 0x2D, 0x73, 0x30, 0x76, 0x18, 0x3A, 0x41, 0xE9, 0x3F, 0x53, 0xA0, 0xE8, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x63, 0xA0, 0xE8, 0x50, 0x70, 0xF8, 0xEC, 0x2B, 0x50, 0x3C, 0xE9, 0x1F, 0x0F, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x59, 0x78, 0xF8, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x46, 0x37, 0x46, 0xDF, 0x56, 0x3F, 0x56, 0xDF, 0x2B, 0x40, 0x3D, 0xE9, 0x66, 0x3D, 0x66, 0xDF, 0x1D, 0x32, 0x41, 0xE9, 0x67, 0x3D, 0x67, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3F, 0x57, 0xDF, 0x2A, 0x40, 0x20, 0xE9, 0x59, 0x3F, 0x59, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x69, 0x3D, 0x69, 0xDF, 0x48, 0x37, 0x48, 0xDF, 0x58, 0x3F, 0x58, 0xDF, 0x68, 0x3D, 0x68, 0xDF, 0x49, 0x37, 0x49, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x0F, 0xCF, 0x74, 0xC2, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x54, 0xB0, 0x02, 0x44, 0x64, 0xB0, 0x3D, 0xCF, 0x74, 0xC0, 0x34, 0x37, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x38, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB2, 0x1A, 0x44, 0x64, 0xB2, 0x36, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x0F, 0xCF, 0x75, 0xC0, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x3D, 0xCF, 0x75, 0xC2, 0x37, 0xCF, 0x75, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0xA6, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA3, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB4, 0x1A, 0x44, 0x64, 0xB4, 0x0A, 0x45, 0x55, 0xB0, 0x02, 0x45, 0x65, 0xB0, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0xA0, 0x37, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x45, 0x55, 0xB2, 0x1A, 0x45, 0x65, 0xB2, 0x0A, 0x45, 0x55, 0xB4, 0x02, 0x45, 0x65, 0xB4, 0x0F, 0xCF, 0x74, 0xC6, 0x2A, 0x20, 0x1A, 0x20, 0xA7, 0x30, 0x4F, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x9C, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA8, 0x38, 0x4F, 0xE9, 0x2A, 0x44, 0x54, 0xB6, 0x1A, 0x44, 0x64, 0xB6, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x56, 0xBF, 0x1A, 0x46, 0x66, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA4, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA5, 0x39, 0x4F, 0xE9, 0x0A, 0x47, 0x57, 0xBF, 0x02, 0x47, 0x67, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA1, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA2, 0x38, 0x4F, 0xE9, 0x2A, 0x43, 0x53, 0xBF, 0x1A, 0x43, 0x63, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x9D, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x9E, 0x39, 0x4F, 0xE9, 0x0A, 0x48, 0x58, 0xBF, 0x02, 0x48, 0x68, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x2A, 0x49, 0x59, 0xBF, 0x1A, 0x49, 0x69, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x82, 0x30, 0x57, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x83, 0x38, 0x57, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x84, 0x31, 0x5E, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x85, 0x39, 0x5E, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8A, 0x36, 0x20, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x8B, 0x3E, 0xBF, 0xEA, 0x80, 0x30, 0x57, 0xE9, 0x81, 0x38, 0x57, 0xE9, 0x82, 0x31, 0x57, 0xE9, 0x86, 0x78, 0x57, 0xE9, 0x83, 0x39, 0x57, 0xE9, 0x87, 0x79, 0x57, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x8A, 0x34, 0x20, 0xE9, 0x8B, 0x3C, 0x20, 0xE9, 0x37, 0x50, 0x60, 0xBD, 0x57, 0x0D, 0x20, 0xE9, 0x35, 0x51, 0x61, 0xBD, 0x2B, 0x50, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x0E, 0x77, 0x24, 0x51, 0x20, 0xE9, 0x8D, 0xFF, 0x20, 0xEA, 0x16, 0x0E, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x0B, 0x46, 0xA0, 0xE8, 0x1B, 0x56, 0xA0, 0xE8, 0x2B, 0x66, 0xA0, 0xE8, 0x0C, 0x47, 0xA0, 0xE8, 0x1C, 0x57, 0xA0, 0xE8, 0x2C, 0x67, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x57, 0x80, 0x57, 0xCF, 0x66, 0x33, 0x66, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x67, 0x3B, 0x67, 0xCF, 0x0B, 0x48, 0xA0, 0xE8, 0x1B, 0x58, 0xA0, 0xE8, 0x2B, 0x68, 0xA0, 0xE8, 0x0C, 0x49, 0xA0, 0xE8, 0x1C, 0x59, 0xA0, 0xE8, 0x2C, 0x69, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x34, 0xD7, 0x34, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3C, 0xD7, 0x3C, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x34, 0x80, 0x34, 0xBD, 0x3C, 0x80, 0x3C, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x48, 0x80, 0x48, 0xCF, 0x59, 0x80, 0x59, 0xCF, 0x68, 0x33, 0x68, 0xCF, 0x49, 0x3B, 0x49, 0xCF, 0xAD, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x58, 0x33, 0x58, 0xCF, 0x69, 0x3B, 0x69, 0xCF, 0x6B, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_t2gzsaf[] = { 0x00, 0x8A, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0A, 0x40, 0x50, 0xBF, 0x2A, 0x40, 0x60, 0xBF, 0x32, 0x41, 0x51, 0xBF, 0x3A, 0x41, 0x61, 0xBF, 0xC3, 0x6B, 0xD3, 0x6B, 0x00, 0x8A, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x53, 0xA0, 0xE8, 0xAD, 0xEE, 0x23, 0x9F, 0x00, 0xE0, 0x51, 0x04, 0x90, 0xE2, 0x61, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x51, 0x41, 0xE0, 0xEC, 0x39, 0x67, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x63, 0xA0, 0xE8, 0x61, 0x41, 0xE0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x8E, 0x80, 0x15, 0xEA, 0x10, 0x04, 0x20, 0x04, 0x61, 0x51, 0xE0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x52, 0xBF, 0x0F, 0x52, 0xA0, 0xE8, 0x1A, 0x42, 0x62, 0xBF, 0x1E, 0x51, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x0E, 0x61, 0x60, 0xEA, 0x32, 0x40, 0x50, 0xBD, 0x22, 0x40, 0x60, 0xBD, 0x12, 0x41, 0x51, 0xBD, 0x3A, 0x41, 0x61, 0xBD, 0xBF, 0x2F, 0x0E, 0xBD, 0x97, 0xE2, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x35, 0x48, 0xB1, 0xE8, 0x3D, 0x59, 0xB1, 0xE8, 0x46, 0x31, 0x46, 0xBF, 0x56, 0x31, 0x56, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x66, 0x31, 0x66, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x67, 0x39, 0x67, 0xBF, 0x7F, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x35, 0x00, 0x3D, 0x00, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0x8D, 0x2F, 0x1E, 0xBD, 0x43, 0x75, 0xF8, 0xEC, 0x35, 0x20, 0x3D, 0x20, 0x43, 0x43, 0x2D, 0xDF, 0x53, 0x53, 0x2D, 0xDF, 0xAE, 0x1E, 0x0E, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x48, 0x35, 0x48, 0xBF, 0x58, 0x35, 0x58, 0xBF, 0x68, 0x35, 0x68, 0xBF, 0x49, 0x3D, 0x49, 0xBF, 0x59, 0x3D, 0x59, 0xBF, 0x69, 0x3D, 0x69, 0xBF, 0x63, 0x63, 0x2D, 0xDF, 0x4D, 0x7D, 0xF8, 0xEC, 0x59, 0xE3, 0x00, 0xE0, 0xB8, 0x38, 0x33, 0xBF, 0x2D, 0x73, 0x30, 0x76, 0x18, 0x3A, 0x41, 0xE9, 0x3F, 0x53, 0xA0, 0xE8, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x63, 0xA0, 0xE8, 0x50, 0x70, 0xF8, 0xEC, 0x2B, 0x50, 0x3C, 0xE9, 0x1F, 0x0F, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x59, 0x78, 0xF8, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x46, 0x37, 0x46, 0xDF, 0x56, 0x3F, 0x56, 0xDF, 0x2B, 0x40, 0x3D, 0xE9, 0x66, 0x3D, 0x66, 0xDF, 0x1D, 0x32, 0x41, 0xE9, 0x67, 0x3D, 0x67, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3F, 0x57, 0xDF, 0x2A, 0x40, 0x20, 0xE9, 0x59, 0x3F, 0x59, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x69, 0x3D, 0x69, 0xDF, 0x48, 0x37, 0x48, 0xDF, 0x58, 0x3F, 0x58, 0xDF, 0x68, 0x3D, 0x68, 0xDF, 0x49, 0x37, 0x49, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x0F, 0xCF, 0x74, 0xC2, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x54, 0xB0, 0x02, 0x44, 0x64, 0xB0, 0x3D, 0xCF, 0x74, 0xC0, 0x34, 0x37, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x38, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB2, 0x1A, 0x44, 0x64, 0xB2, 0x3A, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x0F, 0xCF, 0x75, 0xC0, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x3D, 0xCF, 0x75, 0xC2, 0x37, 0xCF, 0x75, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0xA6, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA3, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB4, 0x1A, 0x44, 0x64, 0xB4, 0x0A, 0x45, 0x55, 0xB0, 0x02, 0x45, 0x65, 0xB0, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0xA0, 0x37, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x45, 0x55, 0xB2, 0x1A, 0x45, 0x65, 0xB2, 0x0A, 0x45, 0x55, 0xB4, 0x02, 0x45, 0x65, 0xB4, 0x0F, 0xCF, 0x74, 0xC6, 0x2A, 0x20, 0x1A, 0x20, 0xA7, 0x30, 0x4F, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x9C, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA8, 0x38, 0x4F, 0xE9, 0x2A, 0x44, 0x54, 0xB6, 0x1A, 0x44, 0x64, 0xB6, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x0A, 0x45, 0x55, 0xB6, 0x02, 0x45, 0x65, 0xB6, 0x3D, 0xCF, 0x75, 0xC6, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x56, 0xBF, 0x1A, 0x46, 0x66, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA4, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA5, 0x39, 0x4F, 0xE9, 0x31, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x0A, 0x47, 0x57, 0xBF, 0x02, 0x47, 0x67, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0xA1, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0xA2, 0x38, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x9D, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x9E, 0x39, 0x4F, 0xE9, 0x2A, 0x43, 0x53, 0xBF, 0x1A, 0x43, 0x63, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x35, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x39, 0x38, 0x4F, 0xE9, 0x0A, 0x48, 0x58, 0xBF, 0x02, 0x48, 0x68, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x2A, 0x49, 0x59, 0xBF, 0x1A, 0x49, 0x69, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x82, 0x30, 0x57, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x83, 0x38, 0x57, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x84, 0x31, 0x5E, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x85, 0x39, 0x5E, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8A, 0x36, 0x20, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x8B, 0x3E, 0xBF, 0xEA, 0x80, 0x30, 0x57, 0xE9, 0x81, 0x38, 0x57, 0xE9, 0x82, 0x31, 0x57, 0xE9, 0x86, 0x78, 0x57, 0xE9, 0x83, 0x39, 0x57, 0xE9, 0x87, 0x79, 0x57, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x8A, 0x34, 0x20, 0xE9, 0x8B, 0x3C, 0x20, 0xE9, 0x37, 0x50, 0x60, 0xBD, 0x57, 0x0D, 0x20, 0xE9, 0x35, 0x51, 0x61, 0xBD, 0x2B, 0x50, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x0E, 0x77, 0x24, 0x51, 0x20, 0xE9, 0x89, 0xFF, 0x20, 0xEA, 0x16, 0x0E, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x0B, 0x46, 0xA0, 0xE8, 0x1B, 0x56, 0xA0, 0xE8, 0x2B, 0x66, 0xA0, 0xE8, 0x0C, 0x47, 0xA0, 0xE8, 0x1C, 0x57, 0xA0, 0xE8, 0x2C, 0x67, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x57, 0x80, 0x57, 0xCF, 0x66, 0x33, 0x66, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x67, 0x3B, 0x67, 0xCF, 0x0B, 0x48, 0xA0, 0xE8, 0x1B, 0x58, 0xA0, 0xE8, 0x2B, 0x68, 0xA0, 0xE8, 0x0C, 0x49, 0xA0, 0xE8, 0x1C, 0x59, 0xA0, 0xE8, 0x2C, 0x69, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x34, 0xD7, 0x34, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3C, 0xD7, 0x3C, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x34, 0x80, 0x34, 0xBD, 0x3C, 0x80, 0x3C, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x48, 0x80, 0x48, 0xCF, 0x59, 0x80, 0x59, 0xCF, 0x68, 0x33, 0x68, 0xCF, 0x49, 0x3B, 0x49, 0xCF, 0xA9, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x58, 0x33, 0x58, 0xCF, 0x69, 0x3B, 0x69, 0xCF, 0x67, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_t2gzsf[] = { 0x00, 0x8A, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x0A, 0x40, 0x50, 0xBF, 0x2A, 0x40, 0x60, 0xBF, 0x32, 0x41, 0x51, 0xBF, 0x3A, 0x41, 0x61, 0xBF, 0xC3, 0x6B, 0xD3, 0x6B, 0x00, 0x8A, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x53, 0xA0, 0xE8, 0xAD, 0xEE, 0x23, 0x9F, 0x00, 0xE0, 0x51, 0x04, 0x90, 0xE2, 0x61, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x51, 0x41, 0xE0, 0xEC, 0x39, 0x67, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x63, 0xA0, 0xE8, 0x61, 0x41, 0xE0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x8A, 0x80, 0x15, 0xEA, 0x10, 0x04, 0x20, 0x04, 0x61, 0x51, 0xE0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x52, 0xBF, 0x0F, 0x52, 0xA0, 0xE8, 0x1A, 0x42, 0x62, 0xBF, 0x1E, 0x51, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x0E, 0x61, 0x60, 0xEA, 0x32, 0x40, 0x50, 0xBD, 0x22, 0x40, 0x60, 0xBD, 0x12, 0x41, 0x51, 0xBD, 0x3A, 0x41, 0x61, 0xBD, 0xBF, 0x2F, 0x0E, 0xBD, 0x97, 0xE2, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x35, 0x48, 0xB1, 0xE8, 0x3D, 0x59, 0xB1, 0xE8, 0x46, 0x31, 0x46, 0xBF, 0x56, 0x31, 0x56, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x66, 0x31, 0x66, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x67, 0x39, 0x67, 0xBF, 0x7B, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x35, 0x00, 0x3D, 0x00, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0x8D, 0x2F, 0x1E, 0xBD, 0x43, 0x75, 0xF8, 0xEC, 0x35, 0x20, 0x3D, 0x20, 0x43, 0x43, 0x2D, 0xDF, 0x53, 0x53, 0x2D, 0xDF, 0xAE, 0x1E, 0x0E, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x48, 0x35, 0x48, 0xBF, 0x58, 0x35, 0x58, 0xBF, 0x68, 0x35, 0x68, 0xBF, 0x49, 0x3D, 0x49, 0xBF, 0x59, 0x3D, 0x59, 0xBF, 0x69, 0x3D, 0x69, 0xBF, 0x63, 0x63, 0x2D, 0xDF, 0x4D, 0x7D, 0xF8, 0xEC, 0x59, 0xE3, 0x00, 0xE0, 0xB8, 0x38, 0x33, 0xBF, 0x2D, 0x73, 0x30, 0x76, 0x18, 0x3A, 0x41, 0xE9, 0x3F, 0x53, 0xA0, 0xE8, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x63, 0xA0, 0xE8, 0x50, 0x70, 0xF8, 0xEC, 0x2B, 0x50, 0x3C, 0xE9, 0x1F, 0x0F, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x59, 0x78, 0xF8, 0xEC, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x46, 0x37, 0x46, 0xDF, 0x56, 0x3F, 0x56, 0xDF, 0x2B, 0x40, 0x3D, 0xE9, 0x66, 0x3D, 0x66, 0xDF, 0x1D, 0x32, 0x41, 0xE9, 0x67, 0x3D, 0x67, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3F, 0x57, 0xDF, 0x2A, 0x40, 0x20, 0xE9, 0x59, 0x3F, 0x59, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x69, 0x3D, 0x69, 0xDF, 0x48, 0x37, 0x48, 0xDF, 0x58, 0x3F, 0x58, 0xDF, 0x68, 0x3D, 0x68, 0xDF, 0x49, 0x37, 0x49, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x0F, 0xCF, 0x74, 0xC2, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x54, 0xB0, 0x02, 0x44, 0x64, 0xB0, 0x3D, 0xCF, 0x74, 0xC0, 0x34, 0x37, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x38, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB2, 0x1A, 0x44, 0x64, 0xB2, 0x36, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x0F, 0xCF, 0x75, 0xC0, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x3D, 0xCF, 0x75, 0xC2, 0x37, 0xCF, 0x75, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0xA6, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA3, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x54, 0xB4, 0x1A, 0x44, 0x64, 0xB4, 0x0A, 0x45, 0x55, 0xB0, 0x02, 0x45, 0x65, 0xB0, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0xA0, 0x37, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x45, 0x55, 0xB2, 0x1A, 0x45, 0x65, 0xB2, 0x0A, 0x45, 0x55, 0xB4, 0x02, 0x45, 0x65, 0xB4, 0x0F, 0xCF, 0x75, 0xC6, 0x2A, 0x20, 0x1A, 0x20, 0xA7, 0x30, 0x4F, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x31, 0x0F, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA8, 0x38, 0x4F, 0xE9, 0x2A, 0x45, 0x55, 0xB6, 0x1A, 0x45, 0x65, 0xB6, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x56, 0xBF, 0x1A, 0x46, 0x66, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA4, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA5, 0x39, 0x4F, 0xE9, 0x0A, 0x47, 0x57, 0xBF, 0x02, 0x47, 0x67, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA1, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA2, 0x38, 0x4F, 0xE9, 0x2A, 0x43, 0x53, 0xBF, 0x1A, 0x43, 0x63, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x35, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x39, 0x39, 0x4F, 0xE9, 0x0A, 0x48, 0x58, 0xBF, 0x02, 0x48, 0x68, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x2A, 0x49, 0x59, 0xBF, 0x1A, 0x49, 0x69, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x82, 0x30, 0x57, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x83, 0x38, 0x57, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x84, 0x31, 0x5E, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x85, 0x39, 0x5E, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8A, 0x36, 0x20, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x8B, 0x3E, 0xBF, 0xEA, 0x80, 0x30, 0x57, 0xE9, 0x81, 0x38, 0x57, 0xE9, 0x82, 0x31, 0x57, 0xE9, 0x86, 0x78, 0x57, 0xE9, 0x83, 0x39, 0x57, 0xE9, 0x87, 0x79, 0x57, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x8A, 0x34, 0x20, 0xE9, 0x8B, 0x3C, 0x20, 0xE9, 0x37, 0x50, 0x60, 0xBD, 0x57, 0x0D, 0x20, 0xE9, 0x35, 0x51, 0x61, 0xBD, 0x2B, 0x50, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x0E, 0x77, 0x24, 0x51, 0x20, 0xE9, 0x8D, 0xFF, 0x20, 0xEA, 0x16, 0x0E, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x0B, 0x46, 0xA0, 0xE8, 0x1B, 0x56, 0xA0, 0xE8, 0x2B, 0x66, 0xA0, 0xE8, 0x0C, 0x47, 0xA0, 0xE8, 0x1C, 0x57, 0xA0, 0xE8, 0x2C, 0x67, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x57, 0x80, 0x57, 0xCF, 0x66, 0x33, 0x66, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x67, 0x3B, 0x67, 0xCF, 0x0B, 0x48, 0xA0, 0xE8, 0x1B, 0x58, 0xA0, 0xE8, 0x2B, 0x68, 0xA0, 0xE8, 0x0C, 0x49, 0xA0, 0xE8, 0x1C, 0x59, 0xA0, 0xE8, 0x2C, 0x69, 0xA0, 0xE8, 0x0B, 0x00, 0x1B, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x1C, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x0B, 0x65, 0x1B, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x0C, 0x65, 0x1C, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x0B, 0x1B, 0x60, 0xEC, 0x34, 0xD7, 0x34, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x0C, 0x1C, 0x60, 0xEC, 0x3C, 0xD7, 0x3C, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x0B, 0x2B, 0xDE, 0xE8, 0x1B, 0x80, 0xDE, 0xE8, 0x34, 0x80, 0x34, 0xBD, 0x3C, 0x80, 0x3C, 0xBD, 0x33, 0xD7, 0x0B, 0xBD, 0x3B, 0xD7, 0x1B, 0xBD, 0x48, 0x80, 0x48, 0xCF, 0x59, 0x80, 0x59, 0xCF, 0x68, 0x33, 0x68, 0xCF, 0x49, 0x3B, 0x49, 0xCF, 0xAD, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x58, 0x33, 0x58, 0xCF, 0x69, 0x3B, 0x69, 0xCF, 0x6B, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_tgz[] = { 0x00, 0x88, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x22, 0x40, 0x48, 0xBF, 0x2A, 0x40, 0x50, 0xBF, 0x32, 0x41, 0x49, 0xBF, 0x3A, 0x41, 0x51, 0xBF, 0xC3, 0x6B, 0xCB, 0x6B, 0x00, 0x88, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x4B, 0xA0, 0xE8, 0xAD, 0xEE, 0x29, 0x9F, 0x00, 0xE0, 0x49, 0x04, 0x90, 0xE2, 0x51, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x49, 0x41, 0xC0, 0xEC, 0x39, 0x57, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x53, 0xA0, 0xE8, 0x51, 0x41, 0xC0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x58, 0x80, 0x15, 0xEA, 0x08, 0x04, 0x10, 0x04, 0x51, 0x49, 0xC0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x4A, 0xBF, 0x27, 0x4A, 0xA0, 0xE8, 0x1A, 0x42, 0x52, 0xBF, 0x1E, 0x49, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x26, 0x51, 0x60, 0xEA, 0x32, 0x40, 0x48, 0xBD, 0x22, 0x40, 0x50, 0xBD, 0x12, 0x41, 0x49, 0xBD, 0x3A, 0x41, 0x51, 0xBD, 0xBF, 0x2F, 0x26, 0xBD, 0x00, 0xE0, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x46, 0x31, 0x46, 0xBF, 0x4E, 0x31, 0x4E, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x56, 0x31, 0x56, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x4F, 0x39, 0x4F, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x4A, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x42, 0x73, 0xF8, 0xEC, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0xA5, 0x2F, 0x1E, 0xBD, 0x43, 0x43, 0x2D, 0xDF, 0x4B, 0x4B, 0x2D, 0xDF, 0xAE, 0x1E, 0x26, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x53, 0x53, 0x2D, 0xDF, 0x00, 0x80, 0x00, 0xE8, 0xB8, 0x38, 0x33, 0xBF, 0x00, 0xE0, 0x59, 0xE3, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x2B, 0x40, 0x3D, 0xE9, 0x3F, 0x4B, 0xA0, 0xE8, 0x2D, 0x73, 0x30, 0x76, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x53, 0xA0, 0xE8, 0x48, 0x70, 0xF8, 0xEC, 0x2B, 0x48, 0x3C, 0xE9, 0x1F, 0x27, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x18, 0x3A, 0x41, 0xE9, 0x1D, 0x32, 0x41, 0xE9, 0x2A, 0x40, 0x20, 0xE9, 0x56, 0x3D, 0x56, 0xDF, 0x46, 0x37, 0x46, 0xDF, 0x4E, 0x3F, 0x4E, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x4F, 0x3F, 0x4F, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3D, 0x57, 0xDF, 0x3D, 0xCF, 0x74, 0xC0, 0x37, 0xCF, 0x74, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0x34, 0x80, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x0A, 0x44, 0x4C, 0xB0, 0x02, 0x44, 0x54, 0xB0, 0x2A, 0x44, 0x4C, 0xB2, 0x1A, 0x44, 0x54, 0xB2, 0x1D, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x3D, 0xCF, 0x74, 0xC2, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x2A, 0x44, 0x4C, 0xB4, 0x1A, 0x44, 0x54, 0xB4, 0x39, 0xE5, 0x2C, 0x9F, 0x38, 0x3D, 0x20, 0xE9, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x4E, 0xBF, 0x1A, 0x46, 0x56, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x0A, 0x47, 0x4F, 0xBF, 0x02, 0x47, 0x57, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x43, 0x4B, 0xBF, 0x1A, 0x43, 0x53, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x37, 0x48, 0x50, 0xBD, 0x8A, 0x36, 0x20, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8B, 0x3E, 0x20, 0xE9, 0x82, 0x30, 0x57, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x83, 0x38, 0x57, 0xE9, 0x35, 0x49, 0x51, 0xBD, 0x84, 0x31, 0x5E, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x85, 0x39, 0x5E, 0xE9, 0x57, 0x25, 0x20, 0xE9, 0x2B, 0x48, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x26, 0x77, 0x24, 0x49, 0x20, 0xE9, 0xAF, 0xFF, 0x20, 0xEA, 0x16, 0x26, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x1C, 0x46, 0xA0, 0xE8, 0x23, 0x4E, 0xA0, 0xE8, 0x2B, 0x56, 0xA0, 0xE8, 0x1D, 0x47, 0xA0, 0xE8, 0x24, 0x4F, 0xA0, 0xE8, 0x2C, 0x57, 0xA0, 0xE8, 0x1C, 0x00, 0x23, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x24, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x1C, 0x65, 0x23, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x1D, 0x65, 0x24, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x1C, 0x23, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x1D, 0x24, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x1C, 0x2B, 0xDE, 0xE8, 0x23, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x1C, 0xBD, 0x3B, 0xD7, 0x23, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x4F, 0x80, 0x4F, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0xD6, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x4E, 0x33, 0x4E, 0xCF, 0x57, 0x3B, 0x57, 0xCF, 0x9D, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_tgza[] = { 0x00, 0x88, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x22, 0x40, 0x48, 0xBF, 0x2A, 0x40, 0x50, 0xBF, 0x32, 0x41, 0x49, 0xBF, 0x3A, 0x41, 0x51, 0xBF, 0xC3, 0x6B, 0xCB, 0x6B, 0x00, 0x88, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x4B, 0xA0, 0xE8, 0xAD, 0xEE, 0x29, 0x9F, 0x00, 0xE0, 0x49, 0x04, 0x90, 0xE2, 0x51, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x49, 0x41, 0xC0, 0xEC, 0x39, 0x57, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x53, 0xA0, 0xE8, 0x51, 0x41, 0xC0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x5C, 0x80, 0x15, 0xEA, 0x08, 0x04, 0x10, 0x04, 0x51, 0x49, 0xC0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x4A, 0xBF, 0x27, 0x4A, 0xA0, 0xE8, 0x1A, 0x42, 0x52, 0xBF, 0x1E, 0x49, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x26, 0x51, 0x60, 0xEA, 0x32, 0x40, 0x48, 0xBD, 0x22, 0x40, 0x50, 0xBD, 0x12, 0x41, 0x49, 0xBD, 0x3A, 0x41, 0x51, 0xBD, 0xBF, 0x2F, 0x26, 0xBD, 0x00, 0xE0, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x46, 0x31, 0x46, 0xBF, 0x4E, 0x31, 0x4E, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x56, 0x31, 0x56, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x4F, 0x39, 0x4F, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x4E, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x42, 0x73, 0xF8, 0xEC, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0xA5, 0x2F, 0x1E, 0xBD, 0x43, 0x43, 0x2D, 0xDF, 0x4B, 0x4B, 0x2D, 0xDF, 0xAE, 0x1E, 0x26, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x53, 0x53, 0x2D, 0xDF, 0x00, 0x80, 0x00, 0xE8, 0xB8, 0x38, 0x33, 0xBF, 0x00, 0xE0, 0x59, 0xE3, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x2B, 0x40, 0x3D, 0xE9, 0x3F, 0x4B, 0xA0, 0xE8, 0x2D, 0x73, 0x30, 0x76, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x53, 0xA0, 0xE8, 0x48, 0x70, 0xF8, 0xEC, 0x2B, 0x48, 0x3C, 0xE9, 0x1F, 0x27, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x18, 0x3A, 0x41, 0xE9, 0x1D, 0x32, 0x41, 0xE9, 0x2A, 0x40, 0x20, 0xE9, 0x56, 0x3D, 0x56, 0xDF, 0x46, 0x37, 0x46, 0xDF, 0x4E, 0x3F, 0x4E, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x4F, 0x3F, 0x4F, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3D, 0x57, 0xDF, 0x3D, 0xCF, 0x74, 0xC0, 0x37, 0xCF, 0x74, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0x34, 0x80, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x27, 0xCF, 0x74, 0xC6, 0x3D, 0xCF, 0x74, 0xC2, 0x0A, 0x44, 0x4C, 0xB0, 0x02, 0x44, 0x54, 0xB0, 0x2A, 0x44, 0x4C, 0xB2, 0x1A, 0x44, 0x54, 0xB2, 0x20, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x9C, 0x27, 0x20, 0xE9, 0x0A, 0x44, 0x4C, 0xB4, 0x02, 0x44, 0x54, 0xB4, 0x2A, 0x44, 0x4C, 0xB6, 0x1A, 0x44, 0x54, 0xB6, 0x39, 0xE5, 0x2C, 0x9F, 0x38, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x20, 0x1A, 0x20, 0x0A, 0x47, 0x4F, 0xBF, 0x02, 0x47, 0x57, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x2A, 0x46, 0x4E, 0xBF, 0x1A, 0x46, 0x56, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x36, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x37, 0x38, 0x4F, 0xE9, 0x2A, 0x43, 0x4B, 0xBF, 0x1A, 0x43, 0x53, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x9D, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x9E, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x37, 0x48, 0x50, 0xBD, 0x8A, 0x36, 0x20, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8B, 0x3E, 0x20, 0xE9, 0x82, 0x30, 0x57, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x83, 0x38, 0x57, 0xE9, 0x35, 0x49, 0x51, 0xBD, 0x84, 0x31, 0x5E, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x85, 0x39, 0x5E, 0xE9, 0x57, 0x25, 0x20, 0xE9, 0x2B, 0x48, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x26, 0x77, 0x24, 0x49, 0x20, 0xE9, 0xAB, 0xFF, 0x20, 0xEA, 0x16, 0x26, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x1C, 0x46, 0xA0, 0xE8, 0x23, 0x4E, 0xA0, 0xE8, 0x2B, 0x56, 0xA0, 0xE8, 0x1D, 0x47, 0xA0, 0xE8, 0x24, 0x4F, 0xA0, 0xE8, 0x2C, 0x57, 0xA0, 0xE8, 0x1C, 0x00, 0x23, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x24, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x1C, 0x65, 0x23, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x1D, 0x65, 0x24, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x1C, 0x23, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x1D, 0x24, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x1C, 0x2B, 0xDE, 0xE8, 0x23, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x1C, 0xBD, 0x3B, 0xD7, 0x23, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x4F, 0x80, 0x4F, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0xD3, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x4E, 0x33, 0x4E, 0xCF, 0x57, 0x3B, 0x57, 0xCF, 0x99, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_tgzaf[] = { 0x00, 0x88, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x22, 0x40, 0x48, 0xBF, 0x2A, 0x40, 0x50, 0xBF, 0x32, 0x41, 0x49, 0xBF, 0x3A, 0x41, 0x51, 0xBF, 0xC3, 0x6B, 0xCB, 0x6B, 0x00, 0x88, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x4B, 0xA0, 0xE8, 0xAD, 0xEE, 0x29, 0x9F, 0x00, 0xE0, 0x49, 0x04, 0x90, 0xE2, 0x51, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x49, 0x41, 0xC0, 0xEC, 0x39, 0x57, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x53, 0xA0, 0xE8, 0x51, 0x41, 0xC0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x61, 0x80, 0x15, 0xEA, 0x08, 0x04, 0x10, 0x04, 0x51, 0x49, 0xC0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x4A, 0xBF, 0x27, 0x4A, 0xA0, 0xE8, 0x1A, 0x42, 0x52, 0xBF, 0x1E, 0x49, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x26, 0x51, 0x60, 0xEA, 0x32, 0x40, 0x48, 0xBD, 0x22, 0x40, 0x50, 0xBD, 0x12, 0x41, 0x49, 0xBD, 0x3A, 0x41, 0x51, 0xBD, 0xBF, 0x2F, 0x26, 0xBD, 0x00, 0xE0, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x46, 0x31, 0x46, 0xBF, 0x4E, 0x31, 0x4E, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x56, 0x31, 0x56, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x4F, 0x39, 0x4F, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x53, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x42, 0x73, 0xF8, 0xEC, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0xA5, 0x2F, 0x1E, 0xBD, 0x43, 0x43, 0x2D, 0xDF, 0x4B, 0x4B, 0x2D, 0xDF, 0xAE, 0x1E, 0x26, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x53, 0x53, 0x2D, 0xDF, 0x00, 0x80, 0x00, 0xE8, 0xB8, 0x38, 0x33, 0xBF, 0x00, 0xE0, 0x59, 0xE3, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x2B, 0x40, 0x3D, 0xE9, 0x3F, 0x4B, 0xA0, 0xE8, 0x2D, 0x73, 0x30, 0x76, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x53, 0xA0, 0xE8, 0x48, 0x70, 0xF8, 0xEC, 0x2B, 0x48, 0x3C, 0xE9, 0x1F, 0x27, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x18, 0x3A, 0x41, 0xE9, 0x1D, 0x32, 0x41, 0xE9, 0x2A, 0x40, 0x20, 0xE9, 0x56, 0x3D, 0x56, 0xDF, 0x46, 0x37, 0x46, 0xDF, 0x4E, 0x3F, 0x4E, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x4F, 0x3F, 0x4F, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3D, 0x57, 0xDF, 0x3D, 0xCF, 0x74, 0xC0, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x4C, 0xB0, 0x02, 0x44, 0x54, 0xB0, 0x31, 0x53, 0x2F, 0x9F, 0x34, 0x37, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB2, 0x1A, 0x44, 0x54, 0xB2, 0x26, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0x3D, 0xCF, 0x74, 0xC2, 0x27, 0xCF, 0x74, 0xC6, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x9C, 0x27, 0x20, 0xE9, 0x0A, 0x44, 0x4C, 0xB4, 0x02, 0x44, 0x54, 0xB4, 0x2A, 0x44, 0x4C, 0xB6, 0x1A, 0x44, 0x54, 0xB6, 0x39, 0xE5, 0x2C, 0x9F, 0x38, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x20, 0x1A, 0x20, 0x3D, 0xCF, 0x75, 0xC6, 0x00, 0x80, 0x00, 0xE8, 0x30, 0x50, 0x2E, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x0A, 0x45, 0x4D, 0xB6, 0x02, 0x45, 0x55, 0xB6, 0x31, 0x53, 0x2F, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x31, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x46, 0x4E, 0xBF, 0x1A, 0x46, 0x56, 0xBF, 0x0A, 0x47, 0x4F, 0xBF, 0x02, 0x47, 0x57, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x38, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x9D, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x9E, 0x39, 0x4F, 0xE9, 0x2A, 0x43, 0x4B, 0xBF, 0x1A, 0x43, 0x53, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x35, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x39, 0x38, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x37, 0x48, 0x50, 0xBD, 0x8A, 0x36, 0x20, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8B, 0x3E, 0x20, 0xE9, 0x82, 0x30, 0x57, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x83, 0x38, 0x57, 0xE9, 0x35, 0x49, 0x51, 0xBD, 0x84, 0x31, 0x5E, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x85, 0x39, 0x5E, 0xE9, 0x57, 0x25, 0x20, 0xE9, 0x2B, 0x48, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x26, 0x77, 0x24, 0x49, 0x20, 0xE9, 0xA6, 0xFF, 0x20, 0xEA, 0x16, 0x26, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x1C, 0x46, 0xA0, 0xE8, 0x23, 0x4E, 0xA0, 0xE8, 0x2B, 0x56, 0xA0, 0xE8, 0x1D, 0x47, 0xA0, 0xE8, 0x24, 0x4F, 0xA0, 0xE8, 0x2C, 0x57, 0xA0, 0xE8, 0x1C, 0x00, 0x23, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x24, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x1C, 0x65, 0x23, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x1D, 0x65, 0x24, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x1C, 0x23, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x1D, 0x24, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x1C, 0x2B, 0xDE, 0xE8, 0x23, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x1C, 0xBD, 0x3B, 0xD7, 0x23, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x4F, 0x80, 0x4F, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0xCD, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x4E, 0x33, 0x4E, 0xCF, 0x57, 0x3B, 0x57, 0xCF, 0x94, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_tgzf[] = { 0x00, 0x88, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x22, 0x40, 0x48, 0xBF, 0x2A, 0x40, 0x50, 0xBF, 0x32, 0x41, 0x49, 0xBF, 0x3A, 0x41, 0x51, 0xBF, 0xC3, 0x6B, 0xCB, 0x6B, 0x00, 0x88, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x4B, 0xA0, 0xE8, 0xAD, 0xEE, 0x29, 0x9F, 0x00, 0xE0, 0x49, 0x04, 0x90, 0xE2, 0x51, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x49, 0x41, 0xC0, 0xEC, 0x39, 0x57, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x53, 0xA0, 0xE8, 0x51, 0x41, 0xC0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x5D, 0x80, 0x15, 0xEA, 0x08, 0x04, 0x10, 0x04, 0x51, 0x49, 0xC0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x4A, 0xBF, 0x27, 0x4A, 0xA0, 0xE8, 0x1A, 0x42, 0x52, 0xBF, 0x1E, 0x49, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x26, 0x51, 0x60, 0xEA, 0x32, 0x40, 0x48, 0xBD, 0x22, 0x40, 0x50, 0xBD, 0x12, 0x41, 0x49, 0xBD, 0x3A, 0x41, 0x51, 0xBD, 0xBF, 0x2F, 0x26, 0xBD, 0x00, 0xE0, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x46, 0x31, 0x46, 0xBF, 0x4E, 0x31, 0x4E, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x56, 0x31, 0x56, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x4F, 0x39, 0x4F, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x4F, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x42, 0x73, 0xF8, 0xEC, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0xA5, 0x2F, 0x1E, 0xBD, 0x43, 0x43, 0x2D, 0xDF, 0x4B, 0x4B, 0x2D, 0xDF, 0xAE, 0x1E, 0x26, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x53, 0x53, 0x2D, 0xDF, 0x00, 0x80, 0x00, 0xE8, 0xB8, 0x38, 0x33, 0xBF, 0x00, 0xE0, 0x59, 0xE3, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x2B, 0x40, 0x3D, 0xE9, 0x3F, 0x4B, 0xA0, 0xE8, 0x2D, 0x73, 0x30, 0x76, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x53, 0xA0, 0xE8, 0x48, 0x70, 0xF8, 0xEC, 0x2B, 0x48, 0x3C, 0xE9, 0x1F, 0x27, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x18, 0x3A, 0x41, 0xE9, 0x1D, 0x32, 0x41, 0xE9, 0x2A, 0x40, 0x20, 0xE9, 0x56, 0x3D, 0x56, 0xDF, 0x46, 0x37, 0x46, 0xDF, 0x4E, 0x3F, 0x4E, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x4F, 0x3F, 0x4F, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3D, 0x57, 0xDF, 0x3D, 0xCF, 0x74, 0xC0, 0x37, 0xCF, 0x74, 0xC4, 0x39, 0xE5, 0x2C, 0x9F, 0x34, 0x80, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x88, 0x73, 0x5E, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x27, 0xCF, 0x75, 0xC6, 0x3C, 0x3D, 0x20, 0xE9, 0x0A, 0x44, 0x4C, 0xB0, 0x02, 0x44, 0x54, 0xB0, 0x2A, 0x44, 0x4C, 0xB2, 0x1A, 0x44, 0x54, 0xB2, 0x20, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x3D, 0xCF, 0x74, 0xC2, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x31, 0x27, 0x20, 0xE9, 0x0A, 0x44, 0x4C, 0xB4, 0x02, 0x44, 0x54, 0xB4, 0x2A, 0x45, 0x4D, 0xB6, 0x1A, 0x45, 0x55, 0xB6, 0x39, 0xE5, 0x2C, 0x9F, 0x38, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x20, 0x1A, 0x20, 0x0A, 0x47, 0x4F, 0xBF, 0x02, 0x47, 0x57, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x2A, 0x46, 0x4E, 0xBF, 0x1A, 0x46, 0x56, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x36, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x37, 0x38, 0x4F, 0xE9, 0x2A, 0x43, 0x4B, 0xBF, 0x1A, 0x43, 0x53, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x35, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x39, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x37, 0x48, 0x50, 0xBD, 0x8A, 0x36, 0x20, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8B, 0x3E, 0x20, 0xE9, 0x82, 0x30, 0x57, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x83, 0x38, 0x57, 0xE9, 0x35, 0x49, 0x51, 0xBD, 0x84, 0x31, 0x5E, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x85, 0x39, 0x5E, 0xE9, 0x57, 0x25, 0x20, 0xE9, 0x2B, 0x48, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x26, 0x77, 0x24, 0x49, 0x20, 0xE9, 0xAA, 0xFF, 0x20, 0xEA, 0x16, 0x26, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x1C, 0x46, 0xA0, 0xE8, 0x23, 0x4E, 0xA0, 0xE8, 0x2B, 0x56, 0xA0, 0xE8, 0x1D, 0x47, 0xA0, 0xE8, 0x24, 0x4F, 0xA0, 0xE8, 0x2C, 0x57, 0xA0, 0xE8, 0x1C, 0x00, 0x23, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x24, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x1C, 0x65, 0x23, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x1D, 0x65, 0x24, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x1C, 0x23, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x1D, 0x24, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x1C, 0x2B, 0xDE, 0xE8, 0x23, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x1C, 0xBD, 0x3B, 0xD7, 0x23, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x4F, 0x80, 0x4F, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0xD3, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x4E, 0x33, 0x4E, 0xCF, 0x57, 0x3B, 0x57, 0xCF, 0x98, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_tgzs[] = { 0x00, 0x88, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x22, 0x40, 0x48, 0xBF, 0x2A, 0x40, 0x50, 0xBF, 0x32, 0x41, 0x49, 0xBF, 0x3A, 0x41, 0x51, 0xBF, 0xC3, 0x6B, 0xCB, 0x6B, 0x00, 0x88, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x4B, 0xA0, 0xE8, 0xAD, 0xEE, 0x29, 0x9F, 0x00, 0xE0, 0x49, 0x04, 0x90, 0xE2, 0x51, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x49, 0x41, 0xC0, 0xEC, 0x39, 0x57, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x53, 0xA0, 0xE8, 0x51, 0x41, 0xC0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x65, 0x80, 0x15, 0xEA, 0x08, 0x04, 0x10, 0x04, 0x51, 0x49, 0xC0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x4A, 0xBF, 0x27, 0x4A, 0xA0, 0xE8, 0x1A, 0x42, 0x52, 0xBF, 0x1E, 0x49, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x26, 0x51, 0x60, 0xEA, 0x32, 0x40, 0x48, 0xBD, 0x22, 0x40, 0x50, 0xBD, 0x12, 0x41, 0x49, 0xBD, 0x3A, 0x41, 0x51, 0xBD, 0xBF, 0x2F, 0x26, 0xBD, 0x00, 0xE0, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x46, 0x31, 0x46, 0xBF, 0x4E, 0x31, 0x4E, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x56, 0x31, 0x56, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x4F, 0x39, 0x4F, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x57, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x42, 0x73, 0xF8, 0xEC, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0xA5, 0x2F, 0x1E, 0xBD, 0x43, 0x43, 0x2D, 0xDF, 0x4B, 0x4B, 0x2D, 0xDF, 0xAE, 0x1E, 0x26, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x53, 0x53, 0x2D, 0xDF, 0x00, 0x80, 0x00, 0xE8, 0xB8, 0x38, 0x33, 0xBF, 0x00, 0xE0, 0x59, 0xE3, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x2B, 0x40, 0x3D, 0xE9, 0x3F, 0x4B, 0xA0, 0xE8, 0x2D, 0x73, 0x30, 0x76, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x53, 0xA0, 0xE8, 0x48, 0x70, 0xF8, 0xEC, 0x2B, 0x48, 0x3C, 0xE9, 0x1F, 0x27, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x18, 0x3A, 0x41, 0xE9, 0x1D, 0x32, 0x41, 0xE9, 0x2A, 0x40, 0x20, 0xE9, 0x56, 0x3D, 0x56, 0xDF, 0x46, 0x37, 0x46, 0xDF, 0x4E, 0x3F, 0x4E, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x4F, 0x3F, 0x4F, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3D, 0x57, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x27, 0xCF, 0x74, 0xC2, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x4C, 0xB0, 0x02, 0x44, 0x54, 0xB0, 0x3D, 0xCF, 0x74, 0xC0, 0x34, 0x37, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x38, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB2, 0x1A, 0x44, 0x54, 0xB2, 0x29, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x27, 0xCF, 0x75, 0xC0, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x3D, 0xCF, 0x75, 0xC2, 0x37, 0xCF, 0x75, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0xA6, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA3, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB4, 0x1A, 0x44, 0x54, 0xB4, 0x0A, 0x45, 0x4D, 0xB0, 0x02, 0x45, 0x55, 0xB0, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0xA0, 0x37, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x2A, 0x45, 0x4D, 0xB2, 0x1A, 0x45, 0x55, 0xB2, 0x0A, 0x45, 0x4D, 0xB4, 0x02, 0x45, 0x55, 0xB4, 0x38, 0x21, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x4E, 0xBF, 0x1A, 0x46, 0x56, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0xA7, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0xA8, 0x38, 0x4F, 0xE9, 0x0A, 0x47, 0x4F, 0xBF, 0x02, 0x47, 0x57, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA4, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA5, 0x39, 0x4F, 0xE9, 0x2A, 0x43, 0x4B, 0xBF, 0x1A, 0x43, 0x53, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0xA1, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0xA2, 0x38, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x37, 0x48, 0x50, 0xBD, 0x8A, 0x36, 0x20, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8B, 0x3E, 0x20, 0xE9, 0x82, 0x30, 0x57, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x83, 0x38, 0x57, 0xE9, 0x35, 0x49, 0x51, 0xBD, 0x84, 0x31, 0x5E, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x85, 0x39, 0x5E, 0xE9, 0x57, 0x25, 0x20, 0xE9, 0x2B, 0x48, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x26, 0x77, 0x24, 0x49, 0x20, 0xE9, 0xA2, 0xFF, 0x20, 0xEA, 0x16, 0x26, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x1C, 0x46, 0xA0, 0xE8, 0x23, 0x4E, 0xA0, 0xE8, 0x2B, 0x56, 0xA0, 0xE8, 0x1D, 0x47, 0xA0, 0xE8, 0x24, 0x4F, 0xA0, 0xE8, 0x2C, 0x57, 0xA0, 0xE8, 0x1C, 0x00, 0x23, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x24, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x1C, 0x65, 0x23, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x1D, 0x65, 0x24, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x1C, 0x23, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x1D, 0x24, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x1C, 0x2B, 0xDE, 0xE8, 0x23, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x1C, 0xBD, 0x3B, 0xD7, 0x23, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x4F, 0x80, 0x4F, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0xCA, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x4E, 0x33, 0x4E, 0xCF, 0x57, 0x3B, 0x57, 0xCF, 0x90, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_tgzsa[] = { 0x00, 0x88, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x22, 0x40, 0x48, 0xBF, 0x2A, 0x40, 0x50, 0xBF, 0x32, 0x41, 0x49, 0xBF, 0x3A, 0x41, 0x51, 0xBF, 0xC3, 0x6B, 0xCB, 0x6B, 0x00, 0x88, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x4B, 0xA0, 0xE8, 0xAD, 0xEE, 0x29, 0x9F, 0x00, 0xE0, 0x49, 0x04, 0x90, 0xE2, 0x51, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x49, 0x41, 0xC0, 0xEC, 0x39, 0x57, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x53, 0xA0, 0xE8, 0x51, 0x41, 0xC0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x6A, 0x80, 0x15, 0xEA, 0x08, 0x04, 0x10, 0x04, 0x51, 0x49, 0xC0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x4A, 0xBF, 0x27, 0x4A, 0xA0, 0xE8, 0x1A, 0x42, 0x52, 0xBF, 0x1E, 0x49, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x26, 0x51, 0x60, 0xEA, 0x32, 0x40, 0x48, 0xBD, 0x22, 0x40, 0x50, 0xBD, 0x12, 0x41, 0x49, 0xBD, 0x3A, 0x41, 0x51, 0xBD, 0xBF, 0x2F, 0x26, 0xBD, 0x00, 0xE0, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x46, 0x31, 0x46, 0xBF, 0x4E, 0x31, 0x4E, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x56, 0x31, 0x56, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x4F, 0x39, 0x4F, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x5C, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x42, 0x73, 0xF8, 0xEC, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0xA5, 0x2F, 0x1E, 0xBD, 0x43, 0x43, 0x2D, 0xDF, 0x4B, 0x4B, 0x2D, 0xDF, 0xAE, 0x1E, 0x26, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x53, 0x53, 0x2D, 0xDF, 0x00, 0x80, 0x00, 0xE8, 0xB8, 0x38, 0x33, 0xBF, 0x00, 0xE0, 0x59, 0xE3, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x2B, 0x40, 0x3D, 0xE9, 0x3F, 0x4B, 0xA0, 0xE8, 0x2D, 0x73, 0x30, 0x76, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x53, 0xA0, 0xE8, 0x48, 0x70, 0xF8, 0xEC, 0x2B, 0x48, 0x3C, 0xE9, 0x1F, 0x27, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x18, 0x3A, 0x41, 0xE9, 0x1D, 0x32, 0x41, 0xE9, 0x2A, 0x40, 0x20, 0xE9, 0x56, 0x3D, 0x56, 0xDF, 0x46, 0x37, 0x46, 0xDF, 0x4E, 0x3F, 0x4E, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x4F, 0x3F, 0x4F, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3D, 0x57, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x27, 0xCF, 0x74, 0xC2, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x4C, 0xB0, 0x02, 0x44, 0x54, 0xB0, 0x3D, 0xCF, 0x74, 0xC0, 0x34, 0x37, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x38, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB2, 0x1A, 0x44, 0x54, 0xB2, 0x2E, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x27, 0xCF, 0x75, 0xC0, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x3D, 0xCF, 0x75, 0xC2, 0x37, 0xCF, 0x75, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0xA6, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA3, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB4, 0x1A, 0x44, 0x54, 0xB4, 0x0A, 0x45, 0x4D, 0xB0, 0x02, 0x45, 0x55, 0xB0, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0xA0, 0x37, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x45, 0x4D, 0xB2, 0x1A, 0x45, 0x55, 0xB2, 0x0A, 0x45, 0x4D, 0xB4, 0x02, 0x45, 0x55, 0xB4, 0x27, 0xCF, 0x74, 0xC6, 0x2A, 0x20, 0x1A, 0x20, 0xA7, 0x30, 0x4F, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x9C, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA8, 0x38, 0x4F, 0xE9, 0x2A, 0x44, 0x4C, 0xB6, 0x1A, 0x44, 0x54, 0xB6, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x4E, 0xBF, 0x1A, 0x46, 0x56, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA4, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA5, 0x39, 0x4F, 0xE9, 0x0A, 0x47, 0x4F, 0xBF, 0x02, 0x47, 0x57, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA1, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA2, 0x38, 0x4F, 0xE9, 0x2A, 0x43, 0x4B, 0xBF, 0x1A, 0x43, 0x53, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x9D, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x9E, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x37, 0x48, 0x50, 0xBD, 0x8A, 0x36, 0x20, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8B, 0x3E, 0x20, 0xE9, 0x82, 0x30, 0x57, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x83, 0x38, 0x57, 0xE9, 0x35, 0x49, 0x51, 0xBD, 0x84, 0x31, 0x5E, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x85, 0x39, 0x5E, 0xE9, 0x57, 0x25, 0x20, 0xE9, 0x2B, 0x48, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x26, 0x77, 0x24, 0x49, 0x20, 0xE9, 0x9D, 0xFF, 0x20, 0xEA, 0x16, 0x26, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x1C, 0x46, 0xA0, 0xE8, 0x23, 0x4E, 0xA0, 0xE8, 0x2B, 0x56, 0xA0, 0xE8, 0x1D, 0x47, 0xA0, 0xE8, 0x24, 0x4F, 0xA0, 0xE8, 0x2C, 0x57, 0xA0, 0xE8, 0x1C, 0x00, 0x23, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x24, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x1C, 0x65, 0x23, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x1D, 0x65, 0x24, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x1C, 0x23, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x1D, 0x24, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x1C, 0x2B, 0xDE, 0xE8, 0x23, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x1C, 0xBD, 0x3B, 0xD7, 0x23, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x4F, 0x80, 0x4F, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0xC5, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x4E, 0x33, 0x4E, 0xCF, 0x57, 0x3B, 0x57, 0xCF, 0x8B, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_tgzsaf[] = { 0x00, 0x88, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x22, 0x40, 0x48, 0xBF, 0x2A, 0x40, 0x50, 0xBF, 0x32, 0x41, 0x49, 0xBF, 0x3A, 0x41, 0x51, 0xBF, 0xC3, 0x6B, 0xCB, 0x6B, 0x00, 0x88, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x4B, 0xA0, 0xE8, 0xAD, 0xEE, 0x29, 0x9F, 0x00, 0xE0, 0x49, 0x04, 0x90, 0xE2, 0x51, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x49, 0x41, 0xC0, 0xEC, 0x39, 0x57, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x53, 0xA0, 0xE8, 0x51, 0x41, 0xC0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x6E, 0x80, 0x15, 0xEA, 0x08, 0x04, 0x10, 0x04, 0x51, 0x49, 0xC0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x4A, 0xBF, 0x27, 0x4A, 0xA0, 0xE8, 0x1A, 0x42, 0x52, 0xBF, 0x1E, 0x49, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x26, 0x51, 0x60, 0xEA, 0x32, 0x40, 0x48, 0xBD, 0x22, 0x40, 0x50, 0xBD, 0x12, 0x41, 0x49, 0xBD, 0x3A, 0x41, 0x51, 0xBD, 0xBF, 0x2F, 0x26, 0xBD, 0x00, 0xE0, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x46, 0x31, 0x46, 0xBF, 0x4E, 0x31, 0x4E, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x56, 0x31, 0x56, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x4F, 0x39, 0x4F, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x60, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x42, 0x73, 0xF8, 0xEC, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0xA5, 0x2F, 0x1E, 0xBD, 0x43, 0x43, 0x2D, 0xDF, 0x4B, 0x4B, 0x2D, 0xDF, 0xAE, 0x1E, 0x26, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x53, 0x53, 0x2D, 0xDF, 0x00, 0x80, 0x00, 0xE8, 0xB8, 0x38, 0x33, 0xBF, 0x00, 0xE0, 0x59, 0xE3, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x2B, 0x40, 0x3D, 0xE9, 0x3F, 0x4B, 0xA0, 0xE8, 0x2D, 0x73, 0x30, 0x76, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x53, 0xA0, 0xE8, 0x48, 0x70, 0xF8, 0xEC, 0x2B, 0x48, 0x3C, 0xE9, 0x1F, 0x27, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x18, 0x3A, 0x41, 0xE9, 0x1D, 0x32, 0x41, 0xE9, 0x2A, 0x40, 0x20, 0xE9, 0x56, 0x3D, 0x56, 0xDF, 0x46, 0x37, 0x46, 0xDF, 0x4E, 0x3F, 0x4E, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x4F, 0x3F, 0x4F, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3D, 0x57, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x27, 0xCF, 0x74, 0xC2, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x4C, 0xB0, 0x02, 0x44, 0x54, 0xB0, 0x3D, 0xCF, 0x74, 0xC0, 0x34, 0x37, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x38, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB2, 0x1A, 0x44, 0x54, 0xB2, 0x32, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x27, 0xCF, 0x75, 0xC0, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x3D, 0xCF, 0x75, 0xC2, 0x37, 0xCF, 0x75, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0xA6, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA3, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB4, 0x1A, 0x44, 0x54, 0xB4, 0x0A, 0x45, 0x4D, 0xB0, 0x02, 0x45, 0x55, 0xB0, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0xA0, 0x37, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x45, 0x4D, 0xB2, 0x1A, 0x45, 0x55, 0xB2, 0x0A, 0x45, 0x4D, 0xB4, 0x02, 0x45, 0x55, 0xB4, 0x27, 0xCF, 0x74, 0xC6, 0x2A, 0x20, 0x1A, 0x20, 0xA7, 0x30, 0x4F, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x9C, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA8, 0x38, 0x4F, 0xE9, 0x2A, 0x44, 0x4C, 0xB6, 0x1A, 0x44, 0x54, 0xB6, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x0A, 0x45, 0x4D, 0xB6, 0x02, 0x45, 0x55, 0xB6, 0x3D, 0xCF, 0x75, 0xC6, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x4E, 0xBF, 0x1A, 0x46, 0x56, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA4, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA5, 0x39, 0x4F, 0xE9, 0x31, 0x3D, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x0A, 0x47, 0x4F, 0xBF, 0x02, 0x47, 0x57, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0xA1, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0xA2, 0x38, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x9D, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x9E, 0x39, 0x4F, 0xE9, 0x2A, 0x43, 0x4B, 0xBF, 0x1A, 0x43, 0x53, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x35, 0x30, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x39, 0x38, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x37, 0x48, 0x50, 0xBD, 0x8A, 0x36, 0x20, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8B, 0x3E, 0x20, 0xE9, 0x82, 0x30, 0x57, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x83, 0x38, 0x57, 0xE9, 0x35, 0x49, 0x51, 0xBD, 0x84, 0x31, 0x5E, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x85, 0x39, 0x5E, 0xE9, 0x57, 0x25, 0x20, 0xE9, 0x2B, 0x48, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x26, 0x77, 0x24, 0x49, 0x20, 0xE9, 0x99, 0xFF, 0x20, 0xEA, 0x16, 0x26, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x1C, 0x46, 0xA0, 0xE8, 0x23, 0x4E, 0xA0, 0xE8, 0x2B, 0x56, 0xA0, 0xE8, 0x1D, 0x47, 0xA0, 0xE8, 0x24, 0x4F, 0xA0, 0xE8, 0x2C, 0x57, 0xA0, 0xE8, 0x1C, 0x00, 0x23, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x24, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x1C, 0x65, 0x23, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x1D, 0x65, 0x24, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x1C, 0x23, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x1D, 0x24, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x1C, 0x2B, 0xDE, 0xE8, 0x23, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x1C, 0xBD, 0x3B, 0xD7, 0x23, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x4F, 0x80, 0x4F, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0xC1, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x4E, 0x33, 0x4E, 0xCF, 0x57, 0x3B, 0x57, 0xCF, 0x87, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; static unsigned char warp_g400_tgzsf[] = { 0x00, 0x88, 0x98, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, 0xFF, 0x80, 0xC0, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x22, 0x40, 0x48, 0xBF, 0x2A, 0x40, 0x50, 0xBF, 0x32, 0x41, 0x49, 0xBF, 0x3A, 0x41, 0x51, 0xBF, 0xC3, 0x6B, 0xCB, 0x6B, 0x00, 0x88, 0x98, 0xE9, 0x73, 0x7B, 0xC8, 0xEC, 0x96, 0xE2, 0x41, 0x04, 0x7B, 0x43, 0xA0, 0xE8, 0x73, 0x4B, 0xA0, 0xE8, 0xAD, 0xEE, 0x29, 0x9F, 0x00, 0xE0, 0x49, 0x04, 0x90, 0xE2, 0x51, 0x04, 0x31, 0x46, 0xB1, 0xE8, 0x49, 0x41, 0xC0, 0xEC, 0x39, 0x57, 0xB1, 0xE8, 0x00, 0x04, 0x46, 0xE2, 0x73, 0x53, 0xA0, 0xE8, 0x51, 0x41, 0xC0, 0xEC, 0x31, 0x00, 0x39, 0x00, 0x6A, 0x80, 0x15, 0xEA, 0x08, 0x04, 0x10, 0x04, 0x51, 0x49, 0xC0, 0xEC, 0x2F, 0x41, 0x60, 0xEA, 0x31, 0x20, 0x39, 0x20, 0x1F, 0x42, 0xA0, 0xE8, 0x2A, 0x42, 0x4A, 0xBF, 0x27, 0x4A, 0xA0, 0xE8, 0x1A, 0x42, 0x52, 0xBF, 0x1E, 0x49, 0x60, 0xEA, 0x73, 0x7B, 0xC8, 0xEC, 0x26, 0x51, 0x60, 0xEA, 0x32, 0x40, 0x48, 0xBD, 0x22, 0x40, 0x50, 0xBD, 0x12, 0x41, 0x49, 0xBD, 0x3A, 0x41, 0x51, 0xBD, 0xBF, 0x2F, 0x26, 0xBD, 0x00, 0xE0, 0x7B, 0x72, 0x32, 0x20, 0x22, 0x20, 0x12, 0x20, 0x3A, 0x20, 0x46, 0x31, 0x46, 0xBF, 0x4E, 0x31, 0x4E, 0xBF, 0xB3, 0xE2, 0x2D, 0x9F, 0x00, 0x80, 0x00, 0xE8, 0x56, 0x31, 0x56, 0xBF, 0x47, 0x39, 0x47, 0xBF, 0x4F, 0x39, 0x4F, 0xBF, 0x57, 0x39, 0x57, 0xBF, 0x5C, 0x80, 0x07, 0xEA, 0x24, 0x41, 0x20, 0xE9, 0x42, 0x73, 0xF8, 0xEC, 0x00, 0xE0, 0x2D, 0x73, 0x33, 0x72, 0x0C, 0xE3, 0xA5, 0x2F, 0x1E, 0xBD, 0x43, 0x43, 0x2D, 0xDF, 0x4B, 0x4B, 0x2D, 0xDF, 0xAE, 0x1E, 0x26, 0xBD, 0x58, 0xE3, 0x33, 0x66, 0x53, 0x53, 0x2D, 0xDF, 0x00, 0x80, 0x00, 0xE8, 0xB8, 0x38, 0x33, 0xBF, 0x00, 0xE0, 0x59, 0xE3, 0x1E, 0x12, 0x41, 0xE9, 0x1A, 0x22, 0x41, 0xE9, 0x2B, 0x40, 0x3D, 0xE9, 0x3F, 0x4B, 0xA0, 0xE8, 0x2D, 0x73, 0x30, 0x76, 0x05, 0x80, 0x3D, 0xEA, 0x37, 0x43, 0xA0, 0xE8, 0x3D, 0x53, 0xA0, 0xE8, 0x48, 0x70, 0xF8, 0xEC, 0x2B, 0x48, 0x3C, 0xE9, 0x1F, 0x27, 0xBC, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x00, 0x80, 0x00, 0xE8, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x15, 0xC0, 0x20, 0xE9, 0x18, 0x3A, 0x41, 0xE9, 0x1D, 0x32, 0x41, 0xE9, 0x2A, 0x40, 0x20, 0xE9, 0x56, 0x3D, 0x56, 0xDF, 0x46, 0x37, 0x46, 0xDF, 0x4E, 0x3F, 0x4E, 0xDF, 0x16, 0x30, 0x20, 0xE9, 0x4F, 0x3F, 0x4F, 0xDF, 0x47, 0x37, 0x47, 0xDF, 0x57, 0x3D, 0x57, 0xDF, 0x32, 0x32, 0x2D, 0xDF, 0x22, 0x22, 0x2D, 0xDF, 0x12, 0x12, 0x2D, 0xDF, 0x3A, 0x3A, 0x2D, 0xDF, 0x27, 0xCF, 0x74, 0xC2, 0x37, 0xCF, 0x74, 0xC4, 0x0A, 0x44, 0x4C, 0xB0, 0x02, 0x44, 0x54, 0xB0, 0x3D, 0xCF, 0x74, 0xC0, 0x34, 0x37, 0x20, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x38, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3C, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB2, 0x1A, 0x44, 0x54, 0xB2, 0x2E, 0x80, 0x3A, 0xEA, 0x0A, 0x20, 0x02, 0x20, 0x27, 0xCF, 0x75, 0xC0, 0x2A, 0x20, 0x1A, 0x20, 0x30, 0x50, 0x2E, 0x9F, 0x32, 0x31, 0x5F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x33, 0x39, 0x5F, 0xE9, 0x3D, 0xCF, 0x75, 0xC2, 0x37, 0xCF, 0x75, 0xC4, 0x31, 0x53, 0x2F, 0x9F, 0xA6, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA3, 0x3D, 0x20, 0xE9, 0x2A, 0x44, 0x4C, 0xB4, 0x1A, 0x44, 0x54, 0xB4, 0x0A, 0x45, 0x4D, 0xB0, 0x02, 0x45, 0x55, 0xB0, 0x88, 0x73, 0x5E, 0xE9, 0x2A, 0x20, 0x1A, 0x20, 0xA0, 0x37, 0x20, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x3E, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x3F, 0x38, 0x4F, 0xE9, 0x30, 0x50, 0x2E, 0x9F, 0x3A, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x3B, 0x39, 0x4F, 0xE9, 0x2A, 0x45, 0x4D, 0xB2, 0x1A, 0x45, 0x55, 0xB2, 0x0A, 0x45, 0x4D, 0xB4, 0x02, 0x45, 0x55, 0xB4, 0x27, 0xCF, 0x75, 0xC6, 0x2A, 0x20, 0x1A, 0x20, 0xA7, 0x30, 0x4F, 0xE9, 0x0A, 0x20, 0x02, 0x20, 0x31, 0x53, 0x2F, 0x9F, 0x31, 0x27, 0x20, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA8, 0x38, 0x4F, 0xE9, 0x2A, 0x45, 0x4D, 0xB6, 0x1A, 0x45, 0x55, 0xB6, 0x30, 0x50, 0x2E, 0x9F, 0x36, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x37, 0x39, 0x4F, 0xE9, 0x00, 0x80, 0x00, 0xE8, 0x2A, 0x20, 0x1A, 0x20, 0x2A, 0x46, 0x4E, 0xBF, 0x1A, 0x46, 0x56, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA4, 0x31, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA5, 0x39, 0x4F, 0xE9, 0x0A, 0x47, 0x4F, 0xBF, 0x02, 0x47, 0x57, 0xBF, 0x31, 0x53, 0x2F, 0x9F, 0xA1, 0x30, 0x4F, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0xA2, 0x38, 0x4F, 0xE9, 0x2A, 0x43, 0x4B, 0xBF, 0x1A, 0x43, 0x53, 0xBF, 0x30, 0x50, 0x2E, 0x9F, 0x35, 0x31, 0x4F, 0xE9, 0x38, 0x21, 0x2C, 0x9F, 0x39, 0x39, 0x4F, 0xE9, 0x31, 0x53, 0x2F, 0x9F, 0x80, 0x31, 0x57, 0xE9, 0x39, 0xE5, 0x2C, 0x9F, 0x81, 0x39, 0x57, 0xE9, 0x37, 0x48, 0x50, 0xBD, 0x8A, 0x36, 0x20, 0xE9, 0x86, 0x76, 0x57, 0xE9, 0x8B, 0x3E, 0x20, 0xE9, 0x82, 0x30, 0x57, 0xE9, 0x87, 0x77, 0x57, 0xE9, 0x83, 0x38, 0x57, 0xE9, 0x35, 0x49, 0x51, 0xBD, 0x84, 0x31, 0x5E, 0xE9, 0x30, 0x1F, 0x5F, 0xE9, 0x85, 0x39, 0x5E, 0xE9, 0x57, 0x25, 0x20, 0xE9, 0x2B, 0x48, 0x20, 0xE9, 0x1D, 0x37, 0xE1, 0xEA, 0x1E, 0x35, 0xE1, 0xEA, 0x00, 0xE0, 0x26, 0x77, 0x24, 0x49, 0x20, 0xE9, 0x9D, 0xFF, 0x20, 0xEA, 0x16, 0x26, 0x20, 0xE9, 0x57, 0x2E, 0xBF, 0xEA, 0x1C, 0x46, 0xA0, 0xE8, 0x23, 0x4E, 0xA0, 0xE8, 0x2B, 0x56, 0xA0, 0xE8, 0x1D, 0x47, 0xA0, 0xE8, 0x24, 0x4F, 0xA0, 0xE8, 0x2C, 0x57, 0xA0, 0xE8, 0x1C, 0x00, 0x23, 0x00, 0x2B, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x24, 0x00, 0x2C, 0x00, 0x00, 0xE0, 0x1C, 0x65, 0x23, 0x65, 0x2B, 0x65, 0x00, 0xE0, 0x1D, 0x65, 0x24, 0x65, 0x2C, 0x65, 0x00, 0xE0, 0x1C, 0x23, 0x60, 0xEC, 0x36, 0xD7, 0x36, 0xAD, 0x2B, 0x80, 0x60, 0xEC, 0x1D, 0x24, 0x60, 0xEC, 0x3E, 0xD7, 0x3E, 0xAD, 0x2C, 0x80, 0x60, 0xEC, 0x1C, 0x2B, 0xDE, 0xE8, 0x23, 0x80, 0xDE, 0xE8, 0x36, 0x80, 0x36, 0xBD, 0x3E, 0x80, 0x3E, 0xBD, 0x33, 0xD7, 0x1C, 0xBD, 0x3B, 0xD7, 0x23, 0xBD, 0x46, 0x80, 0x46, 0xCF, 0x4F, 0x80, 0x4F, 0xCF, 0x56, 0x33, 0x56, 0xCF, 0x47, 0x3B, 0x47, 0xCF, 0xC5, 0xFF, 0x20, 0xEA, 0x00, 0x80, 0x00, 0xE8, 0x4E, 0x33, 0x4E, 0xCF, 0x57, 0x3B, 0x57, 0xCF, 0x8B, 0xFF, 0x20, 0xEA, 0x57, 0xC0, 0xBF, 0xEA, 0x00, 0x80, 0xA0, 0xE9, 0x00, 0x00, 0xD8, 0xEC, }; Index: head/sys/dev/drm/mga_warp.c =================================================================== --- head/sys/dev/drm/mga_warp.c (revision 152908) +++ head/sys/dev/drm/mga_warp.c (revision 152909) @@ -1,207 +1,201 @@ /* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*- - * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com */ + * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com + */ /*- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/mga_drm.h" #include "dev/drm/mga_drv.h" #include "dev/drm/mga_ucode.h" #define MGA_WARP_CODE_ALIGN 256 /* in bytes */ #define WARP_UCODE_SIZE( which ) \ ((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN) #define WARP_UCODE_INSTALL( which, where ) \ do { \ DRM_DEBUG( " pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase );\ dev_priv->warp_pipe_phys[where] = pcbase; \ memcpy( vcbase, which, sizeof(which) ); \ pcbase += WARP_UCODE_SIZE( which ); \ vcbase += WARP_UCODE_SIZE( which ); \ } while (0) -static unsigned int mga_warp_g400_microcode_size(drm_mga_private_t * dev_priv) -{ - unsigned int size; - - size = (WARP_UCODE_SIZE(warp_g400_tgz) + +static const unsigned int mga_warp_g400_microcode_size = + (WARP_UCODE_SIZE(warp_g400_tgz) + WARP_UCODE_SIZE(warp_g400_tgza) + WARP_UCODE_SIZE(warp_g400_tgzaf) + WARP_UCODE_SIZE(warp_g400_tgzf) + WARP_UCODE_SIZE(warp_g400_tgzs) + WARP_UCODE_SIZE(warp_g400_tgzsa) + WARP_UCODE_SIZE(warp_g400_tgzsaf) + WARP_UCODE_SIZE(warp_g400_tgzsf) + WARP_UCODE_SIZE(warp_g400_t2gz) + WARP_UCODE_SIZE(warp_g400_t2gza) + WARP_UCODE_SIZE(warp_g400_t2gzaf) + WARP_UCODE_SIZE(warp_g400_t2gzf) + WARP_UCODE_SIZE(warp_g400_t2gzs) + WARP_UCODE_SIZE(warp_g400_t2gzsa) + WARP_UCODE_SIZE(warp_g400_t2gzsaf) + WARP_UCODE_SIZE(warp_g400_t2gzsf)); - size = PAGE_ALIGN(size); - - DRM_DEBUG("G400 ucode size = %d bytes\n", size); - return size; -} - -static unsigned int mga_warp_g200_microcode_size(drm_mga_private_t * dev_priv) -{ - unsigned int size; - - size = (WARP_UCODE_SIZE(warp_g200_tgz) + +static const unsigned int mga_warp_g200_microcode_size = + (WARP_UCODE_SIZE(warp_g200_tgz) + WARP_UCODE_SIZE(warp_g200_tgza) + WARP_UCODE_SIZE(warp_g200_tgzaf) + WARP_UCODE_SIZE(warp_g200_tgzf) + WARP_UCODE_SIZE(warp_g200_tgzs) + WARP_UCODE_SIZE(warp_g200_tgzsa) + WARP_UCODE_SIZE(warp_g200_tgzsaf) + WARP_UCODE_SIZE(warp_g200_tgzsf)); - size = PAGE_ALIGN(size); - DRM_DEBUG("G200 ucode size = %d bytes\n", size); - return size; +unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv) +{ + switch (dev_priv->chipset) { + case MGA_CARD_TYPE_G400: + case MGA_CARD_TYPE_G550: + return PAGE_ALIGN(mga_warp_g400_microcode_size); + case MGA_CARD_TYPE_G200: + return PAGE_ALIGN(mga_warp_g200_microcode_size); + default: + DRM_ERROR("Unknown chipset value: 0x%x\n", dev_priv->chipset); + return 0; + } } static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv) { unsigned char *vcbase = dev_priv->warp->handle; unsigned long pcbase = dev_priv->warp->offset; - unsigned int size; - size = mga_warp_g400_microcode_size(dev_priv); - if (size > dev_priv->warp->size) { - DRM_ERROR("microcode too large! (%u > %lu)\n", - size, dev_priv->warp->size); - return DRM_ERR(ENOMEM); - } - memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ); WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF); WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA); WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF); WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS); WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF); WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA); WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF); WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ); WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF); WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA); WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF); WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS); WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF); WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA); WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF); return 0; } static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv) { unsigned char *vcbase = dev_priv->warp->handle; unsigned long pcbase = dev_priv->warp->offset; - unsigned int size; - size = mga_warp_g200_microcode_size(dev_priv); - if (size > dev_priv->warp->size) { - DRM_ERROR("microcode too large! (%u > %lu)\n", - size, dev_priv->warp->size); - return DRM_ERR(ENOMEM); - } - memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ); WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF); WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA); WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF); WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS); WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF); WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA); WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF); return 0; } int mga_warp_install_microcode(drm_mga_private_t * dev_priv) { + const unsigned int size = mga_warp_microcode_size(dev_priv); + + DRM_DEBUG("MGA ucode size = %d bytes\n", size); + if (size > dev_priv->warp->size) { + DRM_ERROR("microcode too large! (%u > %lu)\n", + size, dev_priv->warp->size); + return DRM_ERR(ENOMEM); + } + switch (dev_priv->chipset) { case MGA_CARD_TYPE_G400: + case MGA_CARD_TYPE_G550: return mga_warp_install_g400_microcode(dev_priv); case MGA_CARD_TYPE_G200: return mga_warp_install_g200_microcode(dev_priv); default: return DRM_ERR(EINVAL); } } #define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE) int mga_warp_init(drm_mga_private_t * dev_priv) { u32 wmisc; /* FIXME: Get rid of these damned magic numbers... */ switch (dev_priv->chipset) { case MGA_CARD_TYPE_G400: + case MGA_CARD_TYPE_G550: MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND); MGA_WRITE(MGA_WGETMSB, 0x00000E00); MGA_WRITE(MGA_WVRTXSZ, 0x00001807); MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000); break; case MGA_CARD_TYPE_G200: MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND); MGA_WRITE(MGA_WGETMSB, 0x1606); MGA_WRITE(MGA_WVRTXSZ, 7); break; default: return DRM_ERR(EINVAL); } MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE)); wmisc = MGA_READ(MGA_WMISC); if (wmisc != WMISC_EXPECTED) { DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n", wmisc, WMISC_EXPECTED); return DRM_ERR(EINVAL); } return 0; } Index: head/sys/dev/drm/r128_cce.c =================================================================== --- head/sys/dev/drm/r128_cce.c (revision 152908) +++ head/sys/dev/drm/r128_cce.c (revision 152909) @@ -1,945 +1,951 @@ /* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- - * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com */ + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + */ /*- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/r128_drm.h" #include "dev/drm/r128_drv.h" #define R128_FIFO_DEBUG 0 /* CCE microcode (from ATI) */ static u32 r128_cce_microcode[] = { 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1, 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11, 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28, 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071, 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2, 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1, 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1, 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1, 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82, 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729, 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008, 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0, 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0, 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370, 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1, 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793, 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1, 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1, 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1, 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894, 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14, 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1, 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, 409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static int R128_READ_PLL(drm_device_t * dev, int addr) { drm_r128_private_t *dev_priv = dev->dev_private; R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); return R128_READ(R128_CLOCK_CNTL_DATA); } #if R128_FIFO_DEBUG static void r128_status(drm_r128_private_t * dev_priv) { printk("GUI_STAT = 0x%08x\n", (unsigned int)R128_READ(R128_GUI_STAT)); printk("PM4_STAT = 0x%08x\n", (unsigned int)R128_READ(R128_PM4_STAT)); printk("PM4_BUFFER_DL_WPTR = 0x%08x\n", (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR)); printk("PM4_BUFFER_DL_RPTR = 0x%08x\n", (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR)); printk("PM4_MICRO_CNTL = 0x%08x\n", (unsigned int)R128_READ(R128_PM4_MICRO_CNTL)); printk("PM4_BUFFER_CNTL = 0x%08x\n", (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL)); } #endif /* ================================================================ * Engine, FIFO control */ static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv) { u32 tmp; int i; tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL; R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp); for (i = 0; i < dev_priv->usec_timeout; i++) { if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) { return 0; } DRM_UDELAY(1); } #if R128_FIFO_DEBUG DRM_ERROR("failed!\n"); #endif return DRM_ERR(EBUSY); } static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries) { int i; for (i = 0; i < dev_priv->usec_timeout; i++) { int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; if (slots >= entries) return 0; DRM_UDELAY(1); } #if R128_FIFO_DEBUG DRM_ERROR("failed!\n"); #endif return DRM_ERR(EBUSY); } static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv) { int i, ret; ret = r128_do_wait_for_fifo(dev_priv, 64); if (ret) return ret; for (i = 0; i < dev_priv->usec_timeout; i++) { if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) { r128_do_pixcache_flush(dev_priv); return 0; } DRM_UDELAY(1); } #if R128_FIFO_DEBUG DRM_ERROR("failed!\n"); #endif return DRM_ERR(EBUSY); } /* ================================================================ * CCE control, initialization */ /* Load the microcode for the CCE */ static void r128_cce_load_microcode(drm_r128_private_t * dev_priv) { int i; DRM_DEBUG("\n"); r128_do_wait_for_idle(dev_priv); R128_WRITE(R128_PM4_MICROCODE_ADDR, 0); for (i = 0; i < 256; i++) { R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]); R128_WRITE(R128_PM4_MICROCODE_DATAL, r128_cce_microcode[i * 2 + 1]); } } /* Flush any pending commands to the CCE. This should only be used just * prior to a wait for idle, as it informs the engine that the command * stream is ending. */ static void r128_do_cce_flush(drm_r128_private_t * dev_priv) { u32 tmp; tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE; R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp); } /* Wait for the CCE to go idle. */ int r128_do_cce_idle(drm_r128_private_t * dev_priv) { int i; for (i = 0; i < dev_priv->usec_timeout; i++) { if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) { int pm4stat = R128_READ(R128_PM4_STAT); if (((pm4stat & R128_PM4_FIFOCNT_MASK) >= dev_priv->cce_fifo_size) && !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { return r128_do_pixcache_flush(dev_priv); } } DRM_UDELAY(1); } #if R128_FIFO_DEBUG DRM_ERROR("failed!\n"); r128_status(dev_priv); #endif return DRM_ERR(EBUSY); } /* Start the Concurrent Command Engine. */ static void r128_do_cce_start(drm_r128_private_t * dev_priv) { r128_do_wait_for_idle(dev_priv); R128_WRITE(R128_PM4_BUFFER_CNTL, dev_priv->cce_mode | dev_priv->ring.size_l2qw | R128_PM4_BUFFER_CNTL_NOUPDATE); R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */ R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); dev_priv->cce_running = 1; } /* Reset the Concurrent Command Engine. This will not flush any pending * commands, so you must wait for the CCE command stream to complete * before calling this routine. */ static void r128_do_cce_reset(drm_r128_private_t * dev_priv) { R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); dev_priv->ring.tail = 0; } /* Stop the Concurrent Command Engine. This will not flush any pending * commands, so you must flush the command stream and wait for the CCE * to go idle before calling this routine. */ static void r128_do_cce_stop(drm_r128_private_t * dev_priv) { R128_WRITE(R128_PM4_MICRO_CNTL, 0); R128_WRITE(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE); dev_priv->cce_running = 0; } /* Reset the engine. This will stop the CCE if it is running. */ static int r128_do_engine_reset(drm_device_t * dev) { drm_r128_private_t *dev_priv = dev->dev_private; u32 clock_cntl_index, mclk_cntl, gen_reset_cntl; r128_do_pixcache_flush(dev_priv); clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX); mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL); R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP); gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL); /* Taken from the sample code - do not change */ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); R128_READ(R128_GEN_RESET_CNTL); R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI); R128_READ(R128_GEN_RESET_CNTL); R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl); R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index); R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl); /* Reset the CCE ring */ r128_do_cce_reset(dev_priv); /* The CCE is no longer running after an engine reset */ dev_priv->cce_running = 0; /* Reset any pending vertex, indirect buffers */ r128_freelist_reset(dev); return 0; } static void r128_cce_init_ring_buffer(drm_device_t * dev, drm_r128_private_t * dev_priv) { u32 ring_start; u32 tmp; DRM_DEBUG("\n"); /* The manual (p. 2) says this address is in "VM space". This * means it's an offset from the start of AGP space. */ #if __OS_HAS_AGP if (!dev_priv->is_pci) ring_start = dev_priv->cce_ring->offset - dev->agp->base; else #endif - ring_start = dev_priv->cce_ring->offset - dev->sg->handle; + ring_start = dev_priv->cce_ring->offset - + (unsigned long)dev->sg->virtual; R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET); R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); /* Set watermark control */ R128_WRITE(R128_PM4_BUFFER_WM_CNTL, ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT) | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT) | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT) | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT)); /* Force read. Why? Because it's in the examples... */ R128_READ(R128_PM4_BUFFER_ADDR); /* Turn on bus mastering */ tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS; R128_WRITE(R128_BUS_CNTL, tmp); } static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) { drm_r128_private_t *dev_priv; DRM_DEBUG("\n"); dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return DRM_ERR(ENOMEM); memset(dev_priv, 0, sizeof(drm_r128_private_t)); dev_priv->is_pci = init->is_pci; if (dev_priv->is_pci && !dev->sg) { DRM_ERROR("PCI GART memory not allocated!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } dev_priv->usec_timeout = init->usec_timeout; if (dev_priv->usec_timeout < 1 || dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) { DRM_DEBUG("TIMEOUT problem!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } dev_priv->cce_mode = init->cce_mode; /* GH: Simple idle check. */ atomic_set(&dev_priv->idle_count, 0); /* We don't support anything other than bus-mastering ring mode, * but the ring can be in either AGP or PCI space for the ring * read pointer. */ if ((init->cce_mode != R128_PM4_192BM) && (init->cce_mode != R128_PM4_128BM_64INDBM) && (init->cce_mode != R128_PM4_64BM_128INDBM) && (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) { DRM_DEBUG("Bad cce_mode!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } switch (init->cce_mode) { case R128_PM4_NONPM4: dev_priv->cce_fifo_size = 0; break; case R128_PM4_192PIO: case R128_PM4_192BM: dev_priv->cce_fifo_size = 192; break; case R128_PM4_128PIO_64INDBM: case R128_PM4_128BM_64INDBM: dev_priv->cce_fifo_size = 128; break; case R128_PM4_64PIO_128INDBM: case R128_PM4_64BM_128INDBM: case R128_PM4_64PIO_64VCBM_64INDBM: case R128_PM4_64BM_64VCBM_64INDBM: case R128_PM4_64PIO_64VCPIO_64INDPIO: dev_priv->cce_fifo_size = 64; break; } switch (init->fb_bpp) { case 16: dev_priv->color_fmt = R128_DATATYPE_RGB565; break; case 32: default: dev_priv->color_fmt = R128_DATATYPE_ARGB8888; break; } dev_priv->front_offset = init->front_offset; dev_priv->front_pitch = init->front_pitch; dev_priv->back_offset = init->back_offset; dev_priv->back_pitch = init->back_pitch; switch (init->depth_bpp) { case 16: dev_priv->depth_fmt = R128_DATATYPE_RGB565; break; case 24: case 32: default: dev_priv->depth_fmt = R128_DATATYPE_ARGB8888; break; } dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; dev_priv->span_offset = init->span_offset; dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) | (dev_priv->front_offset >> 5)); dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) | (dev_priv->back_offset >> 5)); dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) | (dev_priv->depth_offset >> 5) | R128_DST_TILE); dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) | (dev_priv->span_offset >> 5)); DRM_GETSAREA(); if (!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio) { DRM_ERROR("could not find mmio region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset); if (!dev_priv->cce_ring) { DRM_ERROR("could not find cce ring region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); if (!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("could not find dma buffer region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } if (!dev_priv->is_pci) { dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset); if (!dev_priv->agp_textures) { DRM_ERROR("could not find agp texture region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } } dev_priv->sarea_priv = (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); #if __OS_HAS_AGP if (!dev_priv->is_pci) { drm_core_ioremap(dev_priv->cce_ring, dev); drm_core_ioremap(dev_priv->ring_rptr, dev); drm_core_ioremap(dev->agp_buffer_map, dev); if (!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || !dev->agp_buffer_map->handle) { DRM_ERROR("Could not ioremap agp regions!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(ENOMEM); } } else #endif { dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset; dev_priv->ring_rptr->handle = (void *)dev_priv->ring_rptr->offset; dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset; } #if __OS_HAS_AGP if (!dev_priv->is_pci) dev_priv->cce_buffers_offset = dev->agp->base; else #endif - dev_priv->cce_buffers_offset = dev->sg->handle; + dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual; dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle; dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle + init->ring_size / sizeof(u32)); dev_priv->ring.size = init->ring_size; dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = 128; dev_priv->sarea_priv->last_frame = 0; R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); dev_priv->sarea_priv->last_dispatch = 0; R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch); #if __OS_HAS_AGP if (dev_priv->is_pci) { #endif - if (!drm_ati_pcigart_init(dev, &dev_priv->phys_pci_gart, - &dev_priv->bus_pci_gart, 0)) { + dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + dev_priv->gart_info.addr = NULL; + dev_priv->gart_info.bus_addr = 0; + dev_priv->gart_info.is_pcie = 0; + if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { DRM_ERROR("failed to init PCI GART!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return DRM_ERR(ENOMEM); } - R128_WRITE(R128_PCI_GART_PAGE, dev_priv->bus_pci_gart); + R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr); #if __OS_HAS_AGP } #endif r128_cce_init_ring_buffer(dev, dev_priv); r128_cce_load_microcode(dev_priv); dev->dev_private = (void *)dev_priv; r128_do_engine_reset(dev); return 0; } int r128_do_cleanup_cce(drm_device_t * dev) { /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if (dev->irq_enabled) drm_irq_uninstall(dev); if (dev->dev_private) { drm_r128_private_t *dev_priv = dev->dev_private; #if __OS_HAS_AGP if (!dev_priv->is_pci) { if (dev_priv->cce_ring != NULL) drm_core_ioremapfree(dev_priv->cce_ring, dev); if (dev_priv->ring_rptr != NULL) drm_core_ioremapfree(dev_priv->ring_rptr, dev); if (dev->agp_buffer_map != NULL) { drm_core_ioremapfree(dev->agp_buffer_map, dev); dev->agp_buffer_map = NULL; } } else #endif { - if (!drm_ati_pcigart_cleanup(dev, - dev_priv->phys_pci_gart, - dev_priv->bus_pci_gart)) - DRM_ERROR("failed to cleanup PCI GART!\n"); + if (dev_priv->gart_info.bus_addr) + if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) + DRM_ERROR("failed to cleanup PCI GART!\n"); } drm_free(dev->dev_private, sizeof(drm_r128_private_t), DRM_MEM_DRIVER); dev->dev_private = NULL; } return 0; } int r128_cce_init(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_init_t init; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(init, (drm_r128_init_t __user *) data, sizeof(init)); switch (init.func) { case R128_INIT_CCE: return r128_do_init_cce(dev, &init); case R128_CLEANUP_CCE: return r128_do_cleanup_cce(dev); } return DRM_ERR(EINVAL); } int r128_cce_start(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { DRM_DEBUG("%s while CCE running\n", __FUNCTION__); return 0; } r128_do_cce_start(dev_priv); return 0; } /* Stop the CCE. The engine must have been idled before calling this * routine. */ int r128_cce_stop(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_cce_stop_t stop; int ret; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *) data, sizeof(stop)); /* Flush any pending CCE commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ if (stop.flush) { r128_do_cce_flush(dev_priv); } /* If we fail to make the engine go idle, we return an error * code so that the DRM ioctl wrapper can try again. */ if (stop.idle) { ret = r128_do_cce_idle(dev_priv); if (ret) return ret; } /* Finally, we can turn off the CCE. If the engine isn't idle, * we will get some dropped triangles as they won't be fully * rendered before the CCE is shut down. */ r128_do_cce_stop(dev_priv); /* Reset the engine */ r128_do_engine_reset(dev); return 0; } /* Just reset the CCE ring. Called as part of an X Server engine reset. */ int r128_cce_reset(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_DEBUG("%s called before init done\n", __FUNCTION__); return DRM_ERR(EINVAL); } r128_do_cce_reset(dev_priv); /* The CCE is no longer running after an engine reset */ dev_priv->cce_running = 0; return 0; } int r128_cce_idle(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); if (dev_priv->cce_running) { r128_do_cce_flush(dev_priv); } return r128_do_cce_idle(dev_priv); } int r128_engine_reset(DRM_IOCTL_ARGS) { DRM_DEVICE; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); return r128_do_engine_reset(dev); } int r128_fullscreen(DRM_IOCTL_ARGS) { return DRM_ERR(EINVAL); } /* ================================================================ * Freelist management */ #define R128_BUFFER_USED 0xffffffff #define R128_BUFFER_FREE 0 #if 0 static int r128_freelist_init(drm_device_t * dev) { drm_device_dma_t *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_freelist_t *entry; int i; dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); if (dev_priv->head == NULL) return DRM_ERR(ENOMEM); memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t)); dev_priv->head->age = R128_BUFFER_USED; for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); if (!entry) return DRM_ERR(ENOMEM); entry->age = R128_BUFFER_FREE; entry->buf = buf; entry->prev = dev_priv->head; entry->next = dev_priv->head->next; if (!entry->next) dev_priv->tail = entry; buf_priv->discard = 0; buf_priv->dispatched = 0; buf_priv->list_entry = entry; dev_priv->head->next = entry; if (dev_priv->head->next) dev_priv->head->next->prev = entry; } return 0; } #endif static drm_buf_t *r128_freelist_get(drm_device_t * dev) { drm_device_dma_t *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv; drm_buf_t *buf; int i, t; /* FIXME: Optimize -- use freelist code */ for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if (buf->filp == 0) return buf; } for (t = 0; t < dev_priv->usec_timeout; t++) { u32 done_age = R128_READ(R128_LAST_DISPATCH_REG); for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if (buf->pending && buf_priv->age <= done_age) { /* The buffer has been processed, so it * can now be used. */ buf->pending = 0; return buf; } } DRM_UDELAY(1); } DRM_DEBUG("returning NULL!\n"); return NULL; } void r128_freelist_reset(drm_device_t * dev) { drm_device_dma_t *dma = dev->dma; int i; for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[i]; drm_r128_buf_priv_t *buf_priv = buf->dev_private; buf_priv->age = 0; } } /* ================================================================ * CCE command submission */ int r128_wait_ring(drm_r128_private_t * dev_priv, int n) { drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; for (i = 0; i < dev_priv->usec_timeout; i++) { r128_update_ring_snapshot(dev_priv); if (ring->space >= n) return 0; DRM_UDELAY(1); } /* FIXME: This is being ignored... */ DRM_ERROR("failed!\n"); return DRM_ERR(EBUSY); } static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d) { int i; drm_buf_t *buf; for (i = d->granted_count; i < d->request_count; i++) { buf = r128_freelist_get(dev); if (!buf) return DRM_ERR(EAGAIN); buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return DRM_ERR(EFAULT); d->granted_count++; } return 0; } int r128_cce_buffers(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; int ret = 0; drm_dma_t __user *argp = (void __user *)data; drm_dma_t d; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); /* Please don't send us buffers. */ if (d.send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", DRM_CURRENTPID, d.send_count); return DRM_ERR(EINVAL); } /* We'll send you buffers. */ if (d.request_count < 0 || d.request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", DRM_CURRENTPID, d.request_count, dma->buf_count); return DRM_ERR(EINVAL); } d.granted_count = 0; if (d.request_count) { ret = r128_cce_get_buffers(filp, dev, &d); } DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); return ret; } Index: head/sys/dev/drm/r128_drm.h =================================================================== --- head/sys/dev/drm/r128_drm.h (revision 152908) +++ head/sys/dev/drm/r128_drm.h (revision 152909) @@ -1,345 +1,347 @@ /* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- - * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com */ + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + */ /*- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * Kevin E. Martin - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef __R128_DRM_H__ #define __R128_DRM_H__ /* WARNING: If you change any of these defines, make sure to change the * defines in the X server file (r128_sarea.h) */ #ifndef __R128_SAREA_DEFINES__ #define __R128_SAREA_DEFINES__ /* What needs to be changed for the current vertex buffer? */ #define R128_UPLOAD_CONTEXT 0x001 #define R128_UPLOAD_SETUP 0x002 #define R128_UPLOAD_TEX0 0x004 #define R128_UPLOAD_TEX1 0x008 #define R128_UPLOAD_TEX0IMAGES 0x010 #define R128_UPLOAD_TEX1IMAGES 0x020 #define R128_UPLOAD_CORE 0x040 #define R128_UPLOAD_MASKS 0x080 #define R128_UPLOAD_WINDOW 0x100 #define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */ #define R128_REQUIRE_QUIESCENCE 0x400 #define R128_UPLOAD_ALL 0x7ff #define R128_FRONT 0x1 #define R128_BACK 0x2 #define R128_DEPTH 0x4 /* Primitive types */ #define R128_POINTS 0x1 #define R128_LINES 0x2 #define R128_LINE_STRIP 0x3 #define R128_TRIANGLES 0x4 #define R128_TRIANGLE_FAN 0x5 #define R128_TRIANGLE_STRIP 0x6 /* Vertex/indirect buffer size */ #define R128_BUFFER_SIZE 16384 /* Byte offsets for indirect buffer data */ #define R128_INDEX_PRIM_OFFSET 20 #define R128_HOSTDATA_BLIT_OFFSET 32 /* Keep these small for testing. */ #define R128_NR_SAREA_CLIPRECTS 12 /* There are 2 heaps (local/AGP). Each region within a heap is a * minimum of 64k, and there are at most 64 of them per heap. */ #define R128_LOCAL_TEX_HEAP 0 #define R128_AGP_TEX_HEAP 1 #define R128_NR_TEX_HEAPS 2 #define R128_NR_TEX_REGIONS 64 #define R128_LOG_TEX_GRANULARITY 16 #define R128_NR_CONTEXT_REGS 12 #define R128_MAX_TEXTURE_LEVELS 11 #define R128_MAX_TEXTURE_UNITS 2 #endif /* __R128_SAREA_DEFINES__ */ typedef struct { /* Context state - can be written in one large chunk */ unsigned int dst_pitch_offset_c; unsigned int dp_gui_master_cntl_c; unsigned int sc_top_left_c; unsigned int sc_bottom_right_c; unsigned int z_offset_c; unsigned int z_pitch_c; unsigned int z_sten_cntl_c; unsigned int tex_cntl_c; unsigned int misc_3d_state_cntl_reg; unsigned int texture_clr_cmp_clr_c; unsigned int texture_clr_cmp_msk_c; unsigned int fog_color_c; /* Texture state */ unsigned int tex_size_pitch_c; unsigned int constant_color_c; /* Setup state */ unsigned int pm4_vc_fpu_setup; unsigned int setup_cntl; /* Mask state */ unsigned int dp_write_mask; unsigned int sten_ref_mask_c; unsigned int plane_3d_mask_c; /* Window state */ unsigned int window_xy_offset; /* Core state */ unsigned int scale_3d_cntl; } drm_r128_context_regs_t; /* Setup registers for each texture unit */ typedef struct { unsigned int tex_cntl; unsigned int tex_combine_cntl; unsigned int tex_size_pitch; unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS]; unsigned int tex_border_color; } drm_r128_texture_regs_t; typedef struct drm_r128_sarea { /* The channel for communication of state information to the kernel * on firing a vertex buffer. */ drm_r128_context_regs_t context_state; drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS]; unsigned int dirty; unsigned int vertsize; unsigned int vc_format; /* The current cliprects, or a subset thereof. */ drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS]; unsigned int nbox; /* Counters for client-side throttling of rendering clients. */ unsigned int last_frame; unsigned int last_dispatch; drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1]; unsigned int tex_age[R128_NR_TEX_HEAPS]; int ctx_owner; int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */ int pfCurrentPage; /* which buffer is being displayed? */ } drm_r128_sarea_t; /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (xf86drmR128.h) */ /* Rage 128 specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ #define DRM_R128_INIT 0x00 #define DRM_R128_CCE_START 0x01 #define DRM_R128_CCE_STOP 0x02 #define DRM_R128_CCE_RESET 0x03 #define DRM_R128_CCE_IDLE 0x04 /* 0x05 not used */ #define DRM_R128_RESET 0x06 #define DRM_R128_SWAP 0x07 #define DRM_R128_CLEAR 0x08 #define DRM_R128_VERTEX 0x09 #define DRM_R128_INDICES 0x0a #define DRM_R128_BLIT 0x0b #define DRM_R128_DEPTH 0x0c #define DRM_R128_STIPPLE 0x0d /* 0x0e not used */ #define DRM_R128_INDIRECT 0x0f #define DRM_R128_FULLSCREEN 0x10 #define DRM_R128_CLEAR2 0x11 #define DRM_R128_GETPARAM 0x12 #define DRM_R128_FLIP 0x13 #define DRM_IOCTL_R128_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t) #define DRM_IOCTL_R128_CCE_START DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_START) #define DRM_IOCTL_R128_CCE_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t) #define DRM_IOCTL_R128_CCE_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_RESET) #define DRM_IOCTL_R128_CCE_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_IDLE) /* 0x05 not used */ #define DRM_IOCTL_R128_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_RESET) #define DRM_IOCTL_R128_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_R128_SWAP) #define DRM_IOCTL_R128_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t) #define DRM_IOCTL_R128_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t) #define DRM_IOCTL_R128_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t) #define DRM_IOCTL_R128_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t) #define DRM_IOCTL_R128_DEPTH DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t) #define DRM_IOCTL_R128_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t) /* 0x0e not used */ #define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t) #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t) #define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t) -#define DRM_IOCTL_R128_GETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t) #define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP) typedef struct drm_r128_init { enum { R128_INIT_CCE = 0x01, R128_CLEANUP_CCE = 0x02 } func; #if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) int sarea_priv_offset; #else unsigned long sarea_priv_offset; #endif int is_pci; int cce_mode; int cce_secure; int ring_size; int usec_timeout; unsigned int fb_bpp; unsigned int front_offset, front_pitch; unsigned int back_offset, back_pitch; unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; unsigned int span_offset; #if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) unsigned int fb_offset; unsigned int mmio_offset; unsigned int ring_offset; unsigned int ring_rptr_offset; unsigned int buffers_offset; unsigned int agp_textures_offset; #else unsigned long fb_offset; unsigned long mmio_offset; unsigned long ring_offset; unsigned long ring_rptr_offset; unsigned long buffers_offset; unsigned long agp_textures_offset; #endif } drm_r128_init_t; typedef struct drm_r128_cce_stop { int flush; int idle; } drm_r128_cce_stop_t; typedef struct drm_r128_clear { unsigned int flags; #if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) int x, y, w, h; #endif unsigned int clear_color; unsigned int clear_depth; #if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0) unsigned int color_mask; unsigned int depth_mask; #endif } drm_r128_clear_t; typedef struct drm_r128_vertex { int prim; int idx; /* Index of vertex buffer */ int count; /* Number of vertices in buffer */ int discard; /* Client finished with buffer? */ } drm_r128_vertex_t; typedef struct drm_r128_indices { int prim; int idx; int start; int end; int discard; /* Client finished with buffer? */ } drm_r128_indices_t; typedef struct drm_r128_blit { int idx; int pitch; int offset; int format; unsigned short x, y; unsigned short width, height; } drm_r128_blit_t; typedef struct drm_r128_depth { enum { R128_WRITE_SPAN = 0x01, R128_WRITE_PIXELS = 0x02, R128_READ_SPAN = 0x03, R128_READ_PIXELS = 0x04 } func; int n; int __user *x; int __user *y; unsigned int __user *buffer; unsigned char __user *mask; } drm_r128_depth_t; typedef struct drm_r128_stipple { unsigned int __user *mask; } drm_r128_stipple_t; typedef struct drm_r128_indirect { int idx; int start; int end; int discard; } drm_r128_indirect_t; typedef struct drm_r128_fullscreen { enum { R128_INIT_FULLSCREEN = 0x01, R128_CLEANUP_FULLSCREEN = 0x02 } func; } drm_r128_fullscreen_t; /* 2.3: An ioctl to get parameters that aren't available to the 3d * client any other way. */ #define R128_PARAM_IRQ_NR 1 typedef struct drm_r128_getparam { int param; void __user *value; } drm_r128_getparam_t; #endif Index: head/sys/dev/drm/r128_drv.c =================================================================== --- head/sys/dev/drm/r128_drv.c (revision 152908) +++ head/sys/dev/drm/r128_drv.c (revision 152909) @@ -1,118 +1,122 @@ /* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/r128_drm.h" #include "dev/drm/r128_drv.h" #include "dev/drm/drm_pciids.h" /* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */ static drm_pci_id_list_t r128_pciidlist[] = { r128_PCI_IDS }; -extern drm_ioctl_desc_t r128_ioctls[]; -extern int r128_max_ioctl; - static void r128_configure(drm_device_t *dev) { - dev->dev_priv_size = sizeof(drm_r128_buf_priv_t); - dev->prerelease = r128_driver_prerelease; - dev->pretakedown = r128_driver_pretakedown; - dev->vblank_wait = r128_driver_vblank_wait; - dev->irq_preinstall = r128_driver_irq_preinstall; - dev->irq_postinstall = r128_driver_irq_postinstall; - dev->irq_uninstall = r128_driver_irq_uninstall; - dev->irq_handler = r128_driver_irq_handler; - dev->dma_ioctl = r128_cce_buffers; + dev->driver.buf_priv_size = sizeof(drm_r128_buf_priv_t); + dev->driver.preclose = r128_driver_preclose; + dev->driver.lastclose = r128_driver_lastclose; + dev->driver.vblank_wait = r128_driver_vblank_wait; + dev->driver.irq_preinstall = r128_driver_irq_preinstall; + dev->driver.irq_postinstall = r128_driver_irq_postinstall; + dev->driver.irq_uninstall = r128_driver_irq_uninstall; + dev->driver.irq_handler = r128_driver_irq_handler; + dev->driver.dma_ioctl = r128_cce_buffers; - dev->driver_ioctls = r128_ioctls; - dev->max_driver_ioctl = r128_max_ioctl; + dev->driver.ioctls = r128_ioctls; + dev->driver.max_ioctl = r128_max_ioctl; - dev->driver_name = DRIVER_NAME; - dev->driver_desc = DRIVER_DESC; - dev->driver_date = DRIVER_DATE; - dev->driver_major = DRIVER_MAJOR; - dev->driver_minor = DRIVER_MINOR; - dev->driver_patchlevel = DRIVER_PATCHLEVEL; + dev->driver.name = DRIVER_NAME; + dev->driver.desc = DRIVER_DESC; + dev->driver.date = DRIVER_DATE; + dev->driver.major = DRIVER_MAJOR; + dev->driver.minor = DRIVER_MINOR; + dev->driver.patchlevel = DRIVER_PATCHLEVEL; - dev->use_agp = 1; - dev->use_mtrr = 1; - dev->use_pci_dma = 1; - dev->use_sg = 1; - dev->use_dma = 1; - dev->use_irq = 1; - dev->use_vbl_irq = 1; + dev->driver.use_agp = 1; + dev->driver.use_mtrr = 1; + dev->driver.use_pci_dma = 1; + dev->driver.use_sg = 1; + dev->driver.use_dma = 1; + dev->driver.use_irq = 1; + dev->driver.use_vbl_irq = 1; } #ifdef __FreeBSD__ static int r128_probe(device_t dev) { return drm_probe(dev, r128_pciidlist); } static int r128_attach(device_t nbdev) { drm_device_t *dev = device_get_softc(nbdev); bzero(dev, sizeof(drm_device_t)); r128_configure(dev); return drm_attach(nbdev, r128_pciidlist); } static device_method_t r128_methods[] = { /* Device interface */ DEVMETHOD(device_probe, r128_probe), DEVMETHOD(device_attach, r128_attach), DEVMETHOD(device_detach, drm_detach), { 0, 0 } }; static driver_t r128_driver = { "drm", r128_methods, sizeof(drm_device_t) }; extern devclass_t drm_devclass; DRIVER_MODULE(r128, pci, r128_driver, drm_devclass, 0, 0); MODULE_DEPEND(r128, drm, 1, 1, 1); #elif defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef _LKM CFDRIVER_DECL(r128, DV_TTY, NULL); +#else +CFATTACH_DECL(r128, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach, + drm_activate); +#endif #endif Index: head/sys/dev/drm/r128_drv.h =================================================================== --- head/sys/dev/drm/r128_drv.h (revision 152908) +++ head/sys/dev/drm/r128_drv.h (revision 152909) @@ -1,516 +1,523 @@ /* r128_drv.h -- Private header for r128 driver -*- linux-c -*- - * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com */ + * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com + */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Rickard E. (Rik) Faith * Kevin E. Martin * Gareth Hughes * Michel D�zer - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef __R128_DRV_H__ #define __R128_DRV_H__ /* General customization: */ #define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." #define DRIVER_NAME "r128" #define DRIVER_DESC "ATI Rage 128" #define DRIVER_DATE "20030725" /* Interface history: * * ?? - ?? * 2.4 - Add support for ycbcr textures (no new ioctls) * 2.5 - Add FLIP ioctl, disable FULLSCREEN. */ #define DRIVER_MAJOR 2 #define DRIVER_MINOR 5 #define DRIVER_PATCHLEVEL 0 #define GET_RING_HEAD(dev_priv) R128_READ( R128_PM4_BUFFER_DL_RPTR ) typedef struct drm_r128_freelist { unsigned int age; drm_buf_t *buf; struct drm_r128_freelist *next; struct drm_r128_freelist *prev; } drm_r128_freelist_t; typedef struct drm_r128_ring_buffer { u32 *start; u32 *end; int size; int size_l2qw; u32 tail; u32 tail_mask; int space; int high_mark; } drm_r128_ring_buffer_t; typedef struct drm_r128_private { drm_r128_ring_buffer_t ring; drm_r128_sarea_t *sarea_priv; int cce_mode; int cce_fifo_size; int cce_running; drm_r128_freelist_t *head; drm_r128_freelist_t *tail; int usec_timeout; int is_pci; - unsigned long phys_pci_gart; - dma_addr_t bus_pci_gart; unsigned long cce_buffers_offset; atomic_t idle_count; int page_flipping; int current_page; u32 crtc_offset; u32 crtc_offset_cntl; u32 color_fmt; unsigned int front_offset; unsigned int front_pitch; unsigned int back_offset; unsigned int back_pitch; u32 depth_fmt; unsigned int depth_offset; unsigned int depth_pitch; unsigned int span_offset; u32 front_pitch_offset_c; u32 back_pitch_offset_c; u32 depth_pitch_offset_c; u32 span_pitch_offset_c; drm_local_map_t *sarea; drm_local_map_t *mmio; drm_local_map_t *cce_ring; drm_local_map_t *ring_rptr; drm_local_map_t *agp_textures; + drm_ati_pcigart_info gart_info; } drm_r128_private_t; typedef struct drm_r128_buf_priv { u32 age; int prim; int discard; int dispatched; drm_r128_freelist_t *list_entry; } drm_r128_buf_priv_t; +extern drm_ioctl_desc_t r128_ioctls[]; +extern int r128_max_ioctl; + /* r128_cce.c */ extern int r128_cce_init(DRM_IOCTL_ARGS); extern int r128_cce_start(DRM_IOCTL_ARGS); extern int r128_cce_stop(DRM_IOCTL_ARGS); extern int r128_cce_reset(DRM_IOCTL_ARGS); extern int r128_cce_idle(DRM_IOCTL_ARGS); extern int r128_engine_reset(DRM_IOCTL_ARGS); extern int r128_fullscreen(DRM_IOCTL_ARGS); extern int r128_cce_buffers(DRM_IOCTL_ARGS); extern void r128_freelist_reset(drm_device_t * dev); extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n); extern int r128_do_cce_idle(drm_r128_private_t * dev_priv); extern int r128_do_cleanup_cce(drm_device_t * dev); extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS); extern void r128_driver_irq_preinstall(drm_device_t * dev); extern void r128_driver_irq_postinstall(drm_device_t * dev); extern void r128_driver_irq_uninstall(drm_device_t * dev); -extern void r128_driver_pretakedown(drm_device_t * dev); -extern void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp); +extern void r128_driver_lastclose(drm_device_t * dev); +extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp); + +extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); /* Register definitions, register access macros and drmAddMap constants * for Rage 128 kernel driver. */ #define R128_AUX_SC_CNTL 0x1660 # define R128_AUX1_SC_EN (1 << 0) # define R128_AUX1_SC_MODE_OR (0 << 1) # define R128_AUX1_SC_MODE_NAND (1 << 1) # define R128_AUX2_SC_EN (1 << 2) # define R128_AUX2_SC_MODE_OR (0 << 3) # define R128_AUX2_SC_MODE_NAND (1 << 3) # define R128_AUX3_SC_EN (1 << 4) # define R128_AUX3_SC_MODE_OR (0 << 5) # define R128_AUX3_SC_MODE_NAND (1 << 5) #define R128_AUX1_SC_LEFT 0x1664 #define R128_AUX1_SC_RIGHT 0x1668 #define R128_AUX1_SC_TOP 0x166c #define R128_AUX1_SC_BOTTOM 0x1670 #define R128_AUX2_SC_LEFT 0x1674 #define R128_AUX2_SC_RIGHT 0x1678 #define R128_AUX2_SC_TOP 0x167c #define R128_AUX2_SC_BOTTOM 0x1680 #define R128_AUX3_SC_LEFT 0x1684 #define R128_AUX3_SC_RIGHT 0x1688 #define R128_AUX3_SC_TOP 0x168c #define R128_AUX3_SC_BOTTOM 0x1690 #define R128_BRUSH_DATA0 0x1480 #define R128_BUS_CNTL 0x0030 # define R128_BUS_MASTER_DIS (1 << 6) #define R128_CLOCK_CNTL_INDEX 0x0008 #define R128_CLOCK_CNTL_DATA 0x000c # define R128_PLL_WR_EN (1 << 7) #define R128_CONSTANT_COLOR_C 0x1d34 #define R128_CRTC_OFFSET 0x0224 #define R128_CRTC_OFFSET_CNTL 0x0228 # define R128_CRTC_OFFSET_FLIP_CNTL (1 << 16) #define R128_DP_GUI_MASTER_CNTL 0x146c # define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) # define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) # define R128_GMC_BRUSH_SOLID_COLOR (13 << 4) # define R128_GMC_BRUSH_NONE (15 << 4) # define R128_GMC_DST_16BPP (4 << 8) # define R128_GMC_DST_24BPP (5 << 8) # define R128_GMC_DST_32BPP (6 << 8) # define R128_GMC_DST_DATATYPE_SHIFT 8 # define R128_GMC_SRC_DATATYPE_COLOR (3 << 12) # define R128_DP_SRC_SOURCE_MEMORY (2 << 24) # define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24) # define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28) # define R128_GMC_AUX_CLIP_DIS (1 << 29) # define R128_GMC_WR_MSK_DIS (1 << 30) # define R128_ROP3_S 0x00cc0000 # define R128_ROP3_P 0x00f00000 #define R128_DP_WRITE_MASK 0x16cc #define R128_DST_PITCH_OFFSET_C 0x1c80 # define R128_DST_TILE (1 << 31) #define R128_GEN_INT_CNTL 0x0040 # define R128_CRTC_VBLANK_INT_EN (1 << 0) #define R128_GEN_INT_STATUS 0x0044 # define R128_CRTC_VBLANK_INT (1 << 0) # define R128_CRTC_VBLANK_INT_AK (1 << 0) #define R128_GEN_RESET_CNTL 0x00f0 # define R128_SOFT_RESET_GUI (1 << 0) #define R128_GUI_SCRATCH_REG0 0x15e0 #define R128_GUI_SCRATCH_REG1 0x15e4 #define R128_GUI_SCRATCH_REG2 0x15e8 #define R128_GUI_SCRATCH_REG3 0x15ec #define R128_GUI_SCRATCH_REG4 0x15f0 #define R128_GUI_SCRATCH_REG5 0x15f4 #define R128_GUI_STAT 0x1740 # define R128_GUI_FIFOCNT_MASK 0x0fff # define R128_GUI_ACTIVE (1 << 31) #define R128_MCLK_CNTL 0x000f # define R128_FORCE_GCP (1 << 16) # define R128_FORCE_PIPE3D_CP (1 << 17) # define R128_FORCE_RCP (1 << 18) #define R128_PC_GUI_CTLSTAT 0x1748 #define R128_PC_NGUI_CTLSTAT 0x0184 # define R128_PC_FLUSH_GUI (3 << 0) # define R128_PC_RI_GUI (1 << 2) # define R128_PC_FLUSH_ALL 0x00ff # define R128_PC_BUSY (1 << 31) #define R128_PCI_GART_PAGE 0x017c #define R128_PRIM_TEX_CNTL_C 0x1cb0 #define R128_SCALE_3D_CNTL 0x1a00 #define R128_SEC_TEX_CNTL_C 0x1d00 #define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c #define R128_SETUP_CNTL 0x1bc4 #define R128_STEN_REF_MASK_C 0x1d40 #define R128_TEX_CNTL_C 0x1c9c # define R128_TEX_CACHE_FLUSH (1 << 23) #define R128_WAIT_UNTIL 0x1720 # define R128_EVENT_CRTC_OFFSET (1 << 0) #define R128_WINDOW_XY_OFFSET 0x1bcc /* CCE registers */ #define R128_PM4_BUFFER_OFFSET 0x0700 #define R128_PM4_BUFFER_CNTL 0x0704 # define R128_PM4_MASK (15 << 28) # define R128_PM4_NONPM4 (0 << 28) # define R128_PM4_192PIO (1 << 28) # define R128_PM4_192BM (2 << 28) # define R128_PM4_128PIO_64INDBM (3 << 28) # define R128_PM4_128BM_64INDBM (4 << 28) # define R128_PM4_64PIO_128INDBM (5 << 28) # define R128_PM4_64BM_128INDBM (6 << 28) # define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) # define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) # define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) # define R128_PM4_BUFFER_CNTL_NOUPDATE (1 << 27) #define R128_PM4_BUFFER_WM_CNTL 0x0708 # define R128_WMA_SHIFT 0 # define R128_WMB_SHIFT 8 # define R128_WMC_SHIFT 16 # define R128_WB_WM_SHIFT 24 #define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c #define R128_PM4_BUFFER_DL_RPTR 0x0710 #define R128_PM4_BUFFER_DL_WPTR 0x0714 # define R128_PM4_BUFFER_DL_DONE (1 << 31) #define R128_PM4_VC_FPU_SETUP 0x071c #define R128_PM4_IW_INDOFF 0x0738 #define R128_PM4_IW_INDSIZE 0x073c #define R128_PM4_STAT 0x07b8 # define R128_PM4_FIFOCNT_MASK 0x0fff # define R128_PM4_BUSY (1 << 16) # define R128_PM4_GUI_ACTIVE (1 << 31) #define R128_PM4_MICROCODE_ADDR 0x07d4 #define R128_PM4_MICROCODE_RADDR 0x07d8 #define R128_PM4_MICROCODE_DATAH 0x07dc #define R128_PM4_MICROCODE_DATAL 0x07e0 #define R128_PM4_BUFFER_ADDR 0x07f0 #define R128_PM4_MICRO_CNTL 0x07fc # define R128_PM4_MICRO_FREERUN (1 << 30) #define R128_PM4_FIFO_DATA_EVEN 0x1000 #define R128_PM4_FIFO_DATA_ODD 0x1004 /* CCE command packets */ #define R128_CCE_PACKET0 0x00000000 #define R128_CCE_PACKET1 0x40000000 #define R128_CCE_PACKET2 0x80000000 #define R128_CCE_PACKET3 0xC0000000 # define R128_CNTL_HOSTDATA_BLT 0x00009400 # define R128_CNTL_PAINT_MULTI 0x00009A00 # define R128_CNTL_BITBLT_MULTI 0x00009B00 # define R128_3D_RNDR_GEN_INDX_PRIM 0x00002300 #define R128_CCE_PACKET_MASK 0xC0000000 #define R128_CCE_PACKET_COUNT_MASK 0x3fff0000 #define R128_CCE_PACKET0_REG_MASK 0x000007ff #define R128_CCE_PACKET1_REG0_MASK 0x000007ff #define R128_CCE_PACKET1_REG1_MASK 0x003ff800 #define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000 #define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001 #define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002 #define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003 #define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 #define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 #define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 #define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007 #define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010 #define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020 #define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030 #define R128_CCE_VC_CNTL_NUM_SHIFT 16 #define R128_DATATYPE_VQ 0 #define R128_DATATYPE_CI4 1 #define R128_DATATYPE_CI8 2 #define R128_DATATYPE_ARGB1555 3 #define R128_DATATYPE_RGB565 4 #define R128_DATATYPE_RGB888 5 #define R128_DATATYPE_ARGB8888 6 #define R128_DATATYPE_RGB332 7 #define R128_DATATYPE_Y8 8 #define R128_DATATYPE_RGB8 9 #define R128_DATATYPE_CI16 10 #define R128_DATATYPE_YVYU422 11 #define R128_DATATYPE_VYUY422 12 #define R128_DATATYPE_AYUV444 14 #define R128_DATATYPE_ARGB4444 15 /* Constants */ #define R128_AGP_OFFSET 0x02000000 #define R128_WATERMARK_L 16 #define R128_WATERMARK_M 8 #define R128_WATERMARK_N 8 #define R128_WATERMARK_K 128 #define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */ #define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0 #define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1 #define R128_MAX_VB_AGE 0x7fffffff #define R128_MAX_VB_VERTS (0xffff) #define R128_RING_HIGH_MARK 128 #define R128_PERFORMANCE_BOXES 0 #define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) #define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) #define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) #define R128_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) #define R128_WRITE_PLL(addr,val) \ do { \ R128_WRITE8(R128_CLOCK_CNTL_INDEX, \ ((addr) & 0x1f) | R128_PLL_WR_EN); \ R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \ } while (0) #define CCE_PACKET0( reg, n ) (R128_CCE_PACKET0 | \ ((n) << 16) | ((reg) >> 2)) #define CCE_PACKET1( reg0, reg1 ) (R128_CCE_PACKET1 | \ (((reg1) >> 2) << 11) | ((reg0) >> 2)) #define CCE_PACKET2() (R128_CCE_PACKET2) #define CCE_PACKET3( pkt, n ) (R128_CCE_PACKET3 | \ (pkt) | ((n) << 16)) static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv) { drm_r128_ring_buffer_t *ring = &dev_priv->ring; ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32); if (ring->space <= 0) ring->space += ring->size; } /* ================================================================ * Misc helper macros */ #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ do { \ drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \ if ( ring->space < ring->high_mark ) { \ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \ r128_update_ring_snapshot( dev_priv ); \ if ( ring->space >= ring->high_mark ) \ goto __ring_space_done; \ DRM_UDELAY(1); \ } \ DRM_ERROR( "ring space check failed!\n" ); \ return DRM_ERR(EBUSY); \ } \ __ring_space_done: \ ; \ } while (0) #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ do { \ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; \ if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) { \ int __ret = r128_do_cce_idle( dev_priv ); \ if ( __ret ) return __ret; \ sarea_priv->last_dispatch = 0; \ r128_freelist_reset( dev ); \ } \ } while (0) #define R128_WAIT_UNTIL_PAGE_FLIPPED() do { \ OUT_RING( CCE_PACKET0( R128_WAIT_UNTIL, 0 ) ); \ OUT_RING( R128_EVENT_CRTC_OFFSET ); \ } while (0) /* ================================================================ * Ring control */ #define R128_VERBOSE 0 #define RING_LOCALS \ int write, _nr; unsigned int tail_mask; volatile u32 *ring; #define BEGIN_RING( n ) do { \ if ( R128_VERBOSE ) { \ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ (n), __FUNCTION__ ); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ COMMIT_RING(); \ r128_wait_ring( dev_priv, (n) * sizeof(u32) ); \ } \ _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ tail_mask = dev_priv->ring.tail_mask; \ } while (0) /* You can set this to zero if you want. If the card locks up, you'll * need to keep this set. It works around a bug in early revs of the * Rage 128 chipset, where the CCE would read 32 dwords past the end of * the ring buffer before wrapping around. */ #define R128_BROKEN_CCE 1 #define ADVANCE_RING() do { \ if ( R128_VERBOSE ) { \ DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ write, dev_priv->ring.tail ); \ } \ if ( R128_BROKEN_CCE && write < 32 ) { \ memcpy( dev_priv->ring.end, \ dev_priv->ring.start, \ write * sizeof(u32) ); \ } \ if (((dev_priv->ring.tail + _nr) & tail_mask) != write) { \ DRM_ERROR( \ "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ ((dev_priv->ring.tail + _nr) & tail_mask), \ write, __LINE__); \ } else \ dev_priv->ring.tail = write; \ } while (0) #define COMMIT_RING() do { \ if ( R128_VERBOSE ) { \ DRM_INFO( "COMMIT_RING() tail=0x%06x\n", \ dev_priv->ring.tail ); \ } \ DRM_MEMORYBARRIER(); \ R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail ); \ R128_READ( R128_PM4_BUFFER_DL_WPTR ); \ } while (0) #define OUT_RING( x ) do { \ if ( R128_VERBOSE ) { \ DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ (unsigned int)(x), write ); \ } \ ring[write++] = cpu_to_le32( x ); \ write &= tail_mask; \ } while (0) #endif /* __R128_DRV_H__ */ Index: head/sys/dev/drm/r128_irq.c =================================================================== --- head/sys/dev/drm/r128_irq.c (revision 152908) +++ head/sys/dev/drm/r128_irq.c (revision 152909) @@ -1,103 +1,105 @@ -/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- */ +/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- + */ /*- * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. * * The Weather Channel (TM) funded Tungsten Graphics to develop the * initial release of the Radeon 8500 driver under the XFree86 license. * This notice must be preserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Keith Whitwell * Eric Anholt - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/r128_drm.h" #include "dev/drm/r128_drv.h" irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; int status; status = R128_READ(R128_GEN_INT_STATUS); /* VBLANK interrupt */ if (status & R128_CRTC_VBLANK_INT) { R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); return IRQ_HANDLED; } return IRQ_NONE; } int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) { unsigned int cur_vblank; int ret = 0; /* Assume that the user has missed the current sequence number * by about a day rather than she wants to wait for years * using vertical blanks... */ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, (((cur_vblank = atomic_read(&dev->vbl_received)) - *sequence) <= (1 << 23))); *sequence = cur_vblank; return ret; } void r128_driver_irq_preinstall(drm_device_t * dev) { drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; /* Disable *all* interrupts */ R128_WRITE(R128_GEN_INT_CNTL, 0); /* Clear vblank bit if it's already high */ R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); } void r128_driver_irq_postinstall(drm_device_t * dev) { drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; /* Turn on VBL interrupt */ R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); } void r128_driver_irq_uninstall(drm_device_t * dev) { drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; if (!dev_priv) return; /* Disable *all* interrupts */ R128_WRITE(R128_GEN_INT_CNTL, 0); } Index: head/sys/dev/drm/r128_state.c =================================================================== --- head/sys/dev/drm/r128_state.c (revision 152908) +++ head/sys/dev/drm/r128_state.c (revision 152909) @@ -1,1710 +1,1716 @@ /* r128_state.c -- State support for r128 -*- linux-c -*- - * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com */ + * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com + */ /*- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/r128_drm.h" #include "dev/drm/r128_drv.h" /* ================================================================ * CCE hardware state programming functions */ static void r128_emit_clip_rects(drm_r128_private_t * dev_priv, drm_clip_rect_t * boxes, int count) { u32 aux_sc_cntl = 0x00000000; RING_LOCALS; DRM_DEBUG(" %s\n", __FUNCTION__); BEGIN_RING((count < 3 ? count : 3) * 5 + 2); if (count >= 1) { OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3)); OUT_RING(boxes[0].x1); OUT_RING(boxes[0].x2 - 1); OUT_RING(boxes[0].y1); OUT_RING(boxes[0].y2 - 1); aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR); } if (count >= 2) { OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3)); OUT_RING(boxes[1].x1); OUT_RING(boxes[1].x2 - 1); OUT_RING(boxes[1].y1); OUT_RING(boxes[1].y2 - 1); aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR); } if (count >= 3) { OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3)); OUT_RING(boxes[2].x1); OUT_RING(boxes[2].x2 - 1); OUT_RING(boxes[2].y1); OUT_RING(boxes[2].y2 - 1); aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR); } OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0)); OUT_RING(aux_sc_cntl); ADVANCE_RING(); } static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; DRM_DEBUG(" %s\n", __FUNCTION__); BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0)); OUT_RING(ctx->scale_3d_cntl); ADVANCE_RING(); } static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; DRM_DEBUG(" %s\n", __FUNCTION__); BEGIN_RING(13); OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11)); OUT_RING(ctx->dst_pitch_offset_c); OUT_RING(ctx->dp_gui_master_cntl_c); OUT_RING(ctx->sc_top_left_c); OUT_RING(ctx->sc_bottom_right_c); OUT_RING(ctx->z_offset_c); OUT_RING(ctx->z_pitch_c); OUT_RING(ctx->z_sten_cntl_c); OUT_RING(ctx->tex_cntl_c); OUT_RING(ctx->misc_3d_state_cntl_reg); OUT_RING(ctx->texture_clr_cmp_clr_c); OUT_RING(ctx->texture_clr_cmp_msk_c); OUT_RING(ctx->fog_color_c); ADVANCE_RING(); } static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; DRM_DEBUG(" %s\n", __FUNCTION__); BEGIN_RING(3); OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP)); OUT_RING(ctx->setup_cntl); OUT_RING(ctx->pm4_vc_fpu_setup); ADVANCE_RING(); } static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; DRM_DEBUG(" %s\n", __FUNCTION__); BEGIN_RING(5); OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0)); OUT_RING(ctx->dp_write_mask); OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1)); OUT_RING(ctx->sten_ref_mask_c); OUT_RING(ctx->plane_3d_mask_c); ADVANCE_RING(); } static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; DRM_DEBUG(" %s\n", __FUNCTION__); BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0)); OUT_RING(ctx->window_xy_offset); ADVANCE_RING(); } static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0]; int i; RING_LOCALS; DRM_DEBUG(" %s\n", __FUNCTION__); BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS); OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C, 2 + R128_MAX_TEXTURE_LEVELS)); OUT_RING(tex->tex_cntl); OUT_RING(tex->tex_combine_cntl); OUT_RING(ctx->tex_size_pitch_c); for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) { OUT_RING(tex->tex_offset[i]); } OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1)); OUT_RING(ctx->constant_color_c); OUT_RING(tex->tex_border_color); ADVANCE_RING(); } static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1]; int i; RING_LOCALS; DRM_DEBUG(" %s\n", __FUNCTION__); BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS); OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS)); OUT_RING(tex->tex_cntl); OUT_RING(tex->tex_combine_cntl); for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) { OUT_RING(tex->tex_offset[i]); } OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0)); OUT_RING(tex->tex_border_color); ADVANCE_RING(); } static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty); if (dirty & R128_UPLOAD_CORE) { r128_emit_core(dev_priv); sarea_priv->dirty &= ~R128_UPLOAD_CORE; } if (dirty & R128_UPLOAD_CONTEXT) { r128_emit_context(dev_priv); sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT; } if (dirty & R128_UPLOAD_SETUP) { r128_emit_setup(dev_priv); sarea_priv->dirty &= ~R128_UPLOAD_SETUP; } if (dirty & R128_UPLOAD_MASKS) { r128_emit_masks(dev_priv); sarea_priv->dirty &= ~R128_UPLOAD_MASKS; } if (dirty & R128_UPLOAD_WINDOW) { r128_emit_window(dev_priv); sarea_priv->dirty &= ~R128_UPLOAD_WINDOW; } if (dirty & R128_UPLOAD_TEX0) { r128_emit_tex0(dev_priv); sarea_priv->dirty &= ~R128_UPLOAD_TEX0; } if (dirty & R128_UPLOAD_TEX1) { r128_emit_tex1(dev_priv); sarea_priv->dirty &= ~R128_UPLOAD_TEX1; } /* Turn off the texture cache flushing */ sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH; sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE; } #if R128_PERFORMANCE_BOXES /* ================================================================ * Performance monitoring functions */ static void r128_clear_box(drm_r128_private_t * dev_priv, int x, int y, int w, int h, int r, int g, int b) { u32 pitch, offset; u32 fb_bpp, color; RING_LOCALS; switch (dev_priv->fb_bpp) { case 16: fb_bpp = R128_GMC_DST_16BPP; color = (((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); break; case 24: fb_bpp = R128_GMC_DST_24BPP; color = ((r << 16) | (g << 8) | b); break; case 32: fb_bpp = R128_GMC_DST_32BPP; color = (((0xff) << 24) | (r << 16) | (g << 8) | b); break; default: return; } offset = dev_priv->back_offset; pitch = dev_priv->back_pitch >> 3; BEGIN_RING(6); OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | fb_bpp | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS); OUT_RING((pitch << 21) | (offset >> 5)); OUT_RING(color); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } static void r128_cce_performance_boxes(drm_r128_private_t * dev_priv) { if (atomic_read(&dev_priv->idle_count) == 0) { r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0); } else { atomic_set(&dev_priv->idle_count, 0); } } #endif /* ================================================================ * CCE command dispatch functions */ static void r128_print_dirty(const char *msg, unsigned int flags) { DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n", msg, flags, (flags & R128_UPLOAD_CORE) ? "core, " : "", (flags & R128_UPLOAD_CONTEXT) ? "context, " : "", (flags & R128_UPLOAD_SETUP) ? "setup, " : "", (flags & R128_UPLOAD_TEX0) ? "tex0, " : "", (flags & R128_UPLOAD_TEX1) ? "tex1, " : "", (flags & R128_UPLOAD_MASKS) ? "masks, " : "", (flags & R128_UPLOAD_WINDOW) ? "window, " : "", (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "", (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : ""); } static void r128_cce_dispatch_clear(drm_device_t * dev, drm_r128_clear_t * clear) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; unsigned int flags = clear->flags; int i; RING_LOCALS; DRM_DEBUG("%s\n", __FUNCTION__); if (dev_priv->page_flipping && dev_priv->current_page == 1) { unsigned int tmp = flags; flags &= ~(R128_FRONT | R128_BACK); if (tmp & R128_FRONT) flags |= R128_BACK; if (tmp & R128_BACK) flags |= R128_FRONT; } for (i = 0; i < nbox; i++) { int x = pbox[i].x1; int y = pbox[i].y1; int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2, flags); if (flags & (R128_FRONT | R128_BACK)) { BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0)); OUT_RING(clear->color_mask); ADVANCE_RING(); } if (flags & R128_FRONT) { BEGIN_RING(6); OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | (dev_priv->color_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS); OUT_RING(dev_priv->front_pitch_offset_c); OUT_RING(clear->clear_color); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } if (flags & R128_BACK) { BEGIN_RING(6); OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | (dev_priv->color_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS); OUT_RING(dev_priv->back_pitch_offset_c); OUT_RING(clear->clear_color); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } if (flags & R128_DEPTH) { BEGIN_RING(6); OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS); OUT_RING(dev_priv->depth_pitch_offset_c); OUT_RING(clear->clear_depth); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } } } static void r128_cce_dispatch_swap(drm_device_t * dev) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; int i; RING_LOCALS; DRM_DEBUG("%s\n", __FUNCTION__); #if R128_PERFORMANCE_BOXES /* Do some trivial performance monitoring... */ r128_cce_performance_boxes(dev_priv); #endif for (i = 0; i < nbox; i++) { int x = pbox[i].x1; int y = pbox[i].y1; int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; BEGIN_RING(7); OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_NONE | (dev_priv->color_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_S | R128_DP_SRC_SOURCE_MEMORY | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS); /* Make this work even if front & back are flipped: */ if (dev_priv->current_page == 0) { OUT_RING(dev_priv->back_pitch_offset_c); OUT_RING(dev_priv->front_pitch_offset_c); } else { OUT_RING(dev_priv->front_pitch_offset_c); OUT_RING(dev_priv->back_pitch_offset_c); } OUT_RING((x << 16) | y); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } /* Increment the frame counter. The client-side 3D driver must * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0)); OUT_RING(dev_priv->sarea_priv->last_frame); ADVANCE_RING(); } static void r128_cce_dispatch_flip(drm_device_t * dev) { drm_r128_private_t *dev_priv = dev->dev_private; RING_LOCALS; DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); #if R128_PERFORMANCE_BOXES /* Do some trivial performance monitoring... */ r128_cce_performance_boxes(dev_priv); #endif BEGIN_RING(4); R128_WAIT_UNTIL_PAGE_FLIPPED(); OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0)); if (dev_priv->current_page == 0) { OUT_RING(dev_priv->back_offset); } else { OUT_RING(dev_priv->front_offset); } ADVANCE_RING(); /* Increment the frame counter. The client-side 3D driver must * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = 1 - dev_priv->current_page; BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0)); OUT_RING(dev_priv->sarea_priv->last_frame); ADVANCE_RING(); } static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv = buf->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; int format = sarea_priv->vc_format; int offset = buf->bus_address; int size = buf->used; int prim = buf_priv->prim; int i = 0; RING_LOCALS; DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox); if (0) r128_print_dirty("dispatch_vertex", sarea_priv->dirty); if (buf->used) { buf_priv->dispatched = 1; if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) { r128_emit_state(dev_priv); } do { /* Emit the next set of up to three cliprects */ if (i < sarea_priv->nbox) { r128_emit_clip_rects(dev_priv, &sarea_priv->boxes[i], sarea_priv->nbox - i); } /* Emit the vertex buffer rendering commands */ BEGIN_RING(5); OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3)); OUT_RING(offset); OUT_RING(size); OUT_RING(format); OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST | (size << R128_CCE_VC_CNTL_NUM_SHIFT)); ADVANCE_RING(); i += 3; } while (i < sarea_priv->nbox); } if (buf_priv->discard) { buf_priv->age = dev_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); OUT_RING(buf_priv->age); ADVANCE_RING(); buf->pending = 1; buf->used = 0; /* FIXME: Check dispatched field */ buf_priv->dispatched = 0; } dev_priv->sarea_priv->last_dispatch++; sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; sarea_priv->nbox = 0; } static void r128_cce_dispatch_indirect(drm_device_t * dev, drm_buf_t * buf, int start, int end) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv = buf->dev_private; RING_LOCALS; DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); if (start != end) { int offset = buf->bus_address + start; int dwords = (end - start + 3) / sizeof(u32); /* Indirect buffer data must be an even number of * dwords, so if we've been given an odd number we must * pad the data with a Type-2 CCE packet. */ if (dwords & 1) { u32 *data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset + start); data[dwords++] = cpu_to_le32(R128_CCE_PACKET2); } buf_priv->dispatched = 1; /* Fire off the indirect buffer */ BEGIN_RING(3); OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1)); OUT_RING(offset); OUT_RING(dwords); ADVANCE_RING(); } if (buf_priv->discard) { buf_priv->age = dev_priv->sarea_priv->last_dispatch; /* Emit the indirect buffer age */ BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); OUT_RING(buf_priv->age); ADVANCE_RING(); buf->pending = 1; buf->used = 0; /* FIXME: Check dispatched field */ buf_priv->dispatched = 0; } dev_priv->sarea_priv->last_dispatch++; } static void r128_cce_dispatch_indices(drm_device_t * dev, drm_buf_t * buf, int start, int end, int count) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv = buf->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; int format = sarea_priv->vc_format; int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset; int prim = buf_priv->prim; u32 *data; int dwords; int i = 0; RING_LOCALS; DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count); if (0) r128_print_dirty("dispatch_indices", sarea_priv->dirty); if (start != end) { buf_priv->dispatched = 1; if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) { r128_emit_state(dev_priv); } dwords = (end - start + 3) / sizeof(u32); data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset + start); data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, dwords - 2)); data[1] = cpu_to_le32(offset); data[2] = cpu_to_le32(R128_MAX_VB_VERTS); data[3] = cpu_to_le32(format); data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND | (count << 16))); if (count & 0x1) { #ifdef __LITTLE_ENDIAN data[dwords - 1] &= 0x0000ffff; #else data[dwords - 1] &= 0xffff0000; #endif } do { /* Emit the next set of up to three cliprects */ if (i < sarea_priv->nbox) { r128_emit_clip_rects(dev_priv, &sarea_priv->boxes[i], sarea_priv->nbox - i); } r128_cce_dispatch_indirect(dev, buf, start, end); i += 3; } while (i < sarea_priv->nbox); } if (buf_priv->discard) { buf_priv->age = dev_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); OUT_RING(buf_priv->age); ADVANCE_RING(); buf->pending = 1; /* FIXME: Check dispatched field */ buf_priv->dispatched = 0; } dev_priv->sarea_priv->last_dispatch++; sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; sarea_priv->nbox = 0; } static int r128_cce_dispatch_blit(DRMFILE filp, drm_device_t * dev, drm_r128_blit_t * blit) { drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; u32 *data; int dword_shift, dwords; RING_LOCALS; DRM_DEBUG("\n"); /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll * use a shift instead. */ switch (blit->format) { case R128_DATATYPE_ARGB8888: dword_shift = 0; break; case R128_DATATYPE_ARGB1555: case R128_DATATYPE_RGB565: case R128_DATATYPE_ARGB4444: case R128_DATATYPE_YVYU422: case R128_DATATYPE_VYUY422: dword_shift = 1; break; case R128_DATATYPE_CI8: case R128_DATATYPE_RGB8: dword_shift = 2; break; default: DRM_ERROR("invalid blit format %d\n", blit->format); return DRM_ERR(EINVAL); } /* Flush the pixel cache, and mark the contents as Read Invalid. * This ensures no pixel data gets mixed up with the texture * data from the host data blit, otherwise part of the texture * image may be corrupted. */ BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0)); OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI); ADVANCE_RING(); /* Dispatch the indirect buffer. */ buf = dma->buflist[blit->idx]; buf_priv = buf->dev_private; if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", blit->idx); return DRM_ERR(EINVAL); } buf_priv->discard = 1; dwords = (blit->width * blit->height) >> dword_shift; data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6)); data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_NONE | (blit->format << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_S | R128_DP_SRC_SOURCE_HOST_DATA | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS)); data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5)); data[3] = cpu_to_le32(0xffffffff); data[4] = cpu_to_le32(0xffffffff); data[5] = cpu_to_le32((blit->y << 16) | blit->x); data[6] = cpu_to_le32((blit->height << 16) | blit->width); data[7] = cpu_to_le32(dwords); buf->used = (dwords + 8) * sizeof(u32); r128_cce_dispatch_indirect(dev, buf, 0, buf->used); /* Flush the pixel cache after the blit completes. This ensures * the texture data is written out to memory before rendering * continues. */ BEGIN_RING(2); OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0)); OUT_RING(R128_PC_FLUSH_GUI); ADVANCE_RING(); return 0; } /* ================================================================ * Tiled depth buffer management * * FIXME: These should all set the destination write mask for when we * have hardware stencil support. */ static int r128_cce_dispatch_write_span(drm_device_t * dev, drm_r128_depth_t * depth) { drm_r128_private_t *dev_priv = dev->dev_private; int count, x, y; u32 *buffer; u8 *mask; int i, buffer_size, mask_size; RING_LOCALS; DRM_DEBUG("\n"); count = depth->n; if (count > 4096 || count <= 0) return DRM_ERR(EMSGSIZE); if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) { return DRM_ERR(EFAULT); } if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) { return DRM_ERR(EFAULT); } buffer_size = depth->n * sizeof(u32); buffer = drm_alloc(buffer_size, DRM_MEM_BUFS); if (buffer == NULL) return DRM_ERR(ENOMEM); if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { drm_free(buffer, buffer_size, DRM_MEM_BUFS); return DRM_ERR(EFAULT); } mask_size = depth->n * sizeof(u8); if (depth->mask) { mask = drm_alloc(mask_size, DRM_MEM_BUFS); if (mask == NULL) { drm_free(buffer, buffer_size, DRM_MEM_BUFS); return DRM_ERR(ENOMEM); } if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) { drm_free(buffer, buffer_size, DRM_MEM_BUFS); drm_free(mask, mask_size, DRM_MEM_BUFS); return DRM_ERR(EFAULT); } for (i = 0; i < count; i++, x++) { if (mask[i]) { BEGIN_RING(6); OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); OUT_RING(dev_priv->depth_pitch_offset_c); OUT_RING(buffer[i]); OUT_RING((x << 16) | y); OUT_RING((1 << 16) | 1); ADVANCE_RING(); } } drm_free(mask, mask_size, DRM_MEM_BUFS); } else { for (i = 0; i < count; i++, x++) { BEGIN_RING(6); OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); OUT_RING(dev_priv->depth_pitch_offset_c); OUT_RING(buffer[i]); OUT_RING((x << 16) | y); OUT_RING((1 << 16) | 1); ADVANCE_RING(); } } drm_free(buffer, buffer_size, DRM_MEM_BUFS); return 0; } static int r128_cce_dispatch_write_pixels(drm_device_t * dev, drm_r128_depth_t * depth) { drm_r128_private_t *dev_priv = dev->dev_private; int count, *x, *y; u32 *buffer; u8 *mask; int i, xbuf_size, ybuf_size, buffer_size, mask_size; RING_LOCALS; DRM_DEBUG("\n"); count = depth->n; if (count > 4096 || count <= 0) return DRM_ERR(EMSGSIZE); xbuf_size = count * sizeof(*x); ybuf_size = count * sizeof(*y); x = drm_alloc(xbuf_size, DRM_MEM_BUFS); if (x == NULL) { return DRM_ERR(ENOMEM); } y = drm_alloc(ybuf_size, DRM_MEM_BUFS); if (y == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); return DRM_ERR(ENOMEM); } if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); return DRM_ERR(EFAULT); } if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); return DRM_ERR(EFAULT); } buffer_size = depth->n * sizeof(u32); buffer = drm_alloc(buffer_size, DRM_MEM_BUFS); if (buffer == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); return DRM_ERR(ENOMEM); } if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); drm_free(buffer, buffer_size, DRM_MEM_BUFS); return DRM_ERR(EFAULT); } if (depth->mask) { mask_size = depth->n * sizeof(u8); mask = drm_alloc(mask_size, DRM_MEM_BUFS); if (mask == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); drm_free(buffer, buffer_size, DRM_MEM_BUFS); return DRM_ERR(ENOMEM); } if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); drm_free(buffer, buffer_size, DRM_MEM_BUFS); drm_free(mask, mask_size, DRM_MEM_BUFS); return DRM_ERR(EFAULT); } for (i = 0; i < count; i++) { if (mask[i]) { BEGIN_RING(6); OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); OUT_RING(dev_priv->depth_pitch_offset_c); OUT_RING(buffer[i]); OUT_RING((x[i] << 16) | y[i]); OUT_RING((1 << 16) | 1); ADVANCE_RING(); } } drm_free(mask, mask_size, DRM_MEM_BUFS); } else { for (i = 0; i < count; i++) { BEGIN_RING(6); OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); OUT_RING(dev_priv->depth_pitch_offset_c); OUT_RING(buffer[i]); OUT_RING((x[i] << 16) | y[i]); OUT_RING((1 << 16) | 1); ADVANCE_RING(); } } drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); drm_free(buffer, buffer_size, DRM_MEM_BUFS); return 0; } static int r128_cce_dispatch_read_span(drm_device_t * dev, drm_r128_depth_t * depth) { drm_r128_private_t *dev_priv = dev->dev_private; int count, x, y; RING_LOCALS; DRM_DEBUG("\n"); count = depth->n; if (count > 4096 || count <= 0) return DRM_ERR(EMSGSIZE); if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) { return DRM_ERR(EFAULT); } if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) { return DRM_ERR(EFAULT); } BEGIN_RING(7); OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_NONE | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_S | R128_DP_SRC_SOURCE_MEMORY | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); OUT_RING(dev_priv->depth_pitch_offset_c); OUT_RING(dev_priv->span_pitch_offset_c); OUT_RING((x << 16) | y); OUT_RING((0 << 16) | 0); OUT_RING((count << 16) | 1); ADVANCE_RING(); return 0; } static int r128_cce_dispatch_read_pixels(drm_device_t * dev, drm_r128_depth_t * depth) { drm_r128_private_t *dev_priv = dev->dev_private; int count, *x, *y; int i, xbuf_size, ybuf_size; RING_LOCALS; DRM_DEBUG("%s\n", __FUNCTION__); count = depth->n; if (count > 4096 || count <= 0) return DRM_ERR(EMSGSIZE); if (count > dev_priv->depth_pitch) { count = dev_priv->depth_pitch; } xbuf_size = count * sizeof(*x); ybuf_size = count * sizeof(*y); x = drm_alloc(xbuf_size, DRM_MEM_BUFS); if (x == NULL) { return DRM_ERR(ENOMEM); } y = drm_alloc(ybuf_size, DRM_MEM_BUFS); if (y == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); return DRM_ERR(ENOMEM); } if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); return DRM_ERR(EFAULT); } if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); return DRM_ERR(EFAULT); } for (i = 0; i < count; i++) { BEGIN_RING(7); OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_NONE | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_S | R128_DP_SRC_SOURCE_MEMORY | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); OUT_RING(dev_priv->depth_pitch_offset_c); OUT_RING(dev_priv->span_pitch_offset_c); OUT_RING((x[i] << 16) | y[i]); OUT_RING((i << 16) | 0); OUT_RING((1 << 16) | 1); ADVANCE_RING(); } drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); return 0; } /* ================================================================ * Polygon stipple */ static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple) { drm_r128_private_t *dev_priv = dev->dev_private; int i; RING_LOCALS; DRM_DEBUG("%s\n", __FUNCTION__); BEGIN_RING(33); OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31)); for (i = 0; i < 32; i++) { OUT_RING(stipple[i]); } ADVANCE_RING(); } /* ================================================================ * IOCTL functions */ static int r128_cce_clear(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_clear_t clear; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(clear, (drm_r128_clear_t __user *) data, sizeof(clear)); RING_SPACE_TEST_WITH_RETURN(dev_priv); if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; r128_cce_dispatch_clear(dev, &clear); COMMIT_RING(); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; return 0; } static int r128_do_init_pageflip(drm_device_t * dev) { drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET); dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL); R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset); R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL); dev_priv->page_flipping = 1; dev_priv->current_page = 0; dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; return 0; } static int r128_do_cleanup_pageflip(drm_device_t * dev) { drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset); R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl); if (dev_priv->current_page != 0) { r128_cce_dispatch_flip(dev); COMMIT_RING(); } dev_priv->page_flipping = 0; return 0; } /* Swapping and flipping are different operations, need different ioctls. * They can & should be intermixed to support multiple 3d windows. */ static int r128_cce_flip(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); LOCK_TEST_WITH_RETURN(dev, filp); RING_SPACE_TEST_WITH_RETURN(dev_priv); if (!dev_priv->page_flipping) r128_do_init_pageflip(dev); r128_cce_dispatch_flip(dev); COMMIT_RING(); return 0; } static int r128_cce_swap(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG("%s\n", __FUNCTION__); LOCK_TEST_WITH_RETURN(dev, filp); RING_SPACE_TEST_WITH_RETURN(dev_priv); if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; r128_cce_dispatch_swap(dev); dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS); COMMIT_RING(); return 0; } static int r128_cce_vertex(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_vertex_t vertex; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(vertex, (drm_r128_vertex_t __user *) data, sizeof(vertex)); DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard); if (vertex.idx < 0 || vertex.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", vertex.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } if (vertex.prim < 0 || vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { DRM_ERROR("buffer prim %d\n", vertex.prim); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); buf = dma->buflist[vertex.idx]; buf_priv = buf->dev_private; if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", vertex.idx); return DRM_ERR(EINVAL); } buf->used = vertex.count; buf_priv->prim = vertex.prim; buf_priv->discard = vertex.discard; r128_cce_dispatch_vertex(dev, buf); COMMIT_RING(); return 0; } static int r128_cce_indices(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_indices_t elts; int count; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(elts, (drm_r128_indices_t __user *) data, sizeof(elts)); DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard); if (elts.idx < 0 || elts.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", elts.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } if (elts.prim < 0 || elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { DRM_ERROR("buffer prim %d\n", elts.prim); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); buf = dma->buflist[elts.idx]; buf_priv = buf->dev_private; if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", elts.idx); return DRM_ERR(EINVAL); } count = (elts.end - elts.start) / sizeof(u16); elts.start -= R128_INDEX_PRIM_OFFSET; if (elts.start & 0x7) { DRM_ERROR("misaligned buffer 0x%x\n", elts.start); return DRM_ERR(EINVAL); } if (elts.start < buf->used) { DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used); return DRM_ERR(EINVAL); } buf->used = elts.end; buf_priv->prim = elts.prim; buf_priv->discard = elts.discard; r128_cce_dispatch_indices(dev, buf, elts.start, elts.end, count); COMMIT_RING(); return 0; } static int r128_cce_blit(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_blit_t blit; int ret; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(blit, (drm_r128_blit_t __user *) data, sizeof(blit)); DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit.idx); if (blit.idx < 0 || blit.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", blit.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); ret = r128_cce_dispatch_blit(filp, dev, &blit); COMMIT_RING(); return ret; } static int r128_cce_depth(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_depth_t depth; int ret; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(depth, (drm_r128_depth_t __user *) data, sizeof(depth)); RING_SPACE_TEST_WITH_RETURN(dev_priv); ret = DRM_ERR(EINVAL); switch (depth.func) { case R128_WRITE_SPAN: ret = r128_cce_dispatch_write_span(dev, &depth); + break; case R128_WRITE_PIXELS: ret = r128_cce_dispatch_write_pixels(dev, &depth); + break; case R128_READ_SPAN: ret = r128_cce_dispatch_read_span(dev, &depth); + break; case R128_READ_PIXELS: ret = r128_cce_dispatch_read_pixels(dev, &depth); + break; } COMMIT_RING(); return ret; } static int r128_cce_stipple(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_stipple_t stipple; u32 mask[32]; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(stipple, (drm_r128_stipple_t __user *) data, sizeof(stipple)); if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32))) return DRM_ERR(EFAULT); RING_SPACE_TEST_WITH_RETURN(dev_priv); r128_cce_dispatch_stipple(dev, mask); COMMIT_RING(); return 0; } static int r128_cce_indirect(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_indirect_t indirect; #if 0 RING_LOCALS; #endif LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(indirect, (drm_r128_indirect_t __user *) data, sizeof(indirect)); DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n", indirect.idx, indirect.start, indirect.end, indirect.discard); if (indirect.idx < 0 || indirect.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", indirect.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } buf = dma->buflist[indirect.idx]; buf_priv = buf->dev_private; if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", indirect.idx); return DRM_ERR(EINVAL); } if (indirect.start < buf->used) { DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", indirect.start, buf->used); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); buf->used = indirect.end; buf_priv->discard = indirect.discard; #if 0 /* Wait for the 3D stream to idle before the indirect buffer * containing 2D acceleration commands is processed. */ BEGIN_RING(2); RADEON_WAIT_UNTIL_3D_IDLE(); ADVANCE_RING(); #endif /* Dispatch the indirect buffer full of commands from the * X server. This is insecure and is thus only available to * privileged clients. */ r128_cce_dispatch_indirect(dev, buf, indirect.start, indirect.end); COMMIT_RING(); return 0; } static int r128_getparam(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_getparam_t param; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(param, (drm_r128_getparam_t __user *) data, sizeof(param)); DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); switch (param.param) { case R128_PARAM_IRQ_NR: value = dev->irq; break; default: return DRM_ERR(EINVAL); } if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; } -void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp) +void r128_driver_preclose(drm_device_t * dev, DRMFILE filp) { if (dev->dev_private) { drm_r128_private_t *dev_priv = dev->dev_private; if (dev_priv->page_flipping) { r128_do_cleanup_pageflip(dev); } } } -void r128_driver_pretakedown(drm_device_t * dev) +void r128_driver_lastclose(drm_device_t * dev) { r128_do_cleanup_cce(dev); } drm_ioctl_desc_t r128_ioctls[] = { - [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, 1, 1}, - [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, 1, 1}, - [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, 1, 1}, - [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, 1, 1}, - [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, 1, 0}, - [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, 1, 1}, - [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, 1, 0}, + [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, DRM_AUTH}, }; int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls); Index: head/sys/dev/drm/r300_cmdbuf.c =================================================================== --- head/sys/dev/drm/r300_cmdbuf.c (revision 152908) +++ head/sys/dev/drm/r300_cmdbuf.c (revision 152909) @@ -1,803 +1,804 @@ /* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*- * * Copyright (C) The Weather Channel, Inc. 2002. * Copyright (C) 2004 Nicolai Haehnle. * All Rights Reserved. * * The Weather Channel (TM) funded Tungsten Graphics to develop the * initial release of the Radeon 8500 driver under the XFree86 license. * This notice must be preserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Nicolai Haehnle - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" #include "dev/drm/r300_reg.h" #define R300_SIMULTANEOUS_CLIPRECTS 4 /* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects */ static const int r300_cliprect_cntl[4] = { 0xAAAA, 0xEEEE, 0xFEFE, 0xFFFE }; /** * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command * buffer, starting with index n. */ static int r300_emit_cliprects(drm_radeon_private_t* dev_priv, drm_radeon_cmd_buffer_t* cmdbuf, int n) { drm_clip_rect_t box; int nr; int i; RING_LOCALS; nr = cmdbuf->nbox - n; if (nr > R300_SIMULTANEOUS_CLIPRECTS) nr = R300_SIMULTANEOUS_CLIPRECTS; DRM_DEBUG("%i cliprects\n", nr); if (nr) { BEGIN_RING(6 + nr*2); OUT_RING( CP_PACKET0( R300_RE_CLIPRECT_TL_0, nr*2 - 1 ) ); for(i = 0; i < nr; ++i) { if (DRM_COPY_FROM_USER_UNCHECKED(&box, &cmdbuf->boxes[n+i], sizeof(box))) { DRM_ERROR("copy cliprect faulted\n"); return DRM_ERR(EFAULT); } box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | (box.y1 << R300_CLIPRECT_Y_SHIFT)); OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | (box.y2 << R300_CLIPRECT_Y_SHIFT)); } OUT_RING_REG( R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr-1] ); /* TODO/SECURITY: Force scissors to a safe value, otherwise the * client might be able to trample over memory. * The impact should be very limited, but I'd rather be safe than * sorry. */ OUT_RING( CP_PACKET0( R300_RE_SCISSORS_TL, 1 ) ); OUT_RING( 0 ); OUT_RING( R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK ); ADVANCE_RING(); } else { /* Why we allow zero cliprect rendering: * There are some commands in a command buffer that must be submitted * even when there are no cliprects, e.g. DMA buffer discard * or state setting (though state setting could be avoided by * simulating a loss of context). * * Now since the cmdbuf interface is so chaotic right now (and is * bound to remain that way for a bit until things settle down), * it is basically impossible to filter out the commands that are * necessary and those that aren't. * * So I choose the safe way and don't do any filtering at all; * instead, I simply set up the engine so that all rendering * can't produce any fragments. */ BEGIN_RING(2); OUT_RING_REG( R300_RE_CLIPRECT_CNTL, 0 ); ADVANCE_RING(); } return 0; } u8 r300_reg_flags[0x10000>>2]; void r300_init_reg_flags(void) { int i; memset(r300_reg_flags, 0, 0x10000>>2); #define ADD_RANGE_MARK(reg, count,mark) \ for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\ r300_reg_flags[i]|=(mark); #define MARK_SAFE 1 #define MARK_CHECK_OFFSET 2 #define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE) /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */ ADD_RANGE(R300_SE_VPORT_XSCALE, 6); ADD_RANGE(0x2080, 1); ADD_RANGE(R300_SE_VTE_CNTL, 2); ADD_RANGE(0x2134, 2); ADD_RANGE(0x2140, 1); ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2); ADD_RANGE(0x21DC, 1); ADD_RANGE(0x221C, 1); ADD_RANGE(0x2220, 4); ADD_RANGE(0x2288, 1); ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); ADD_RANGE(R300_GB_ENABLE, 1); ADD_RANGE(R300_GB_MSPOS0, 5); ADD_RANGE(R300_TX_ENABLE, 1); ADD_RANGE(0x4200, 4); ADD_RANGE(0x4214, 1); ADD_RANGE(R300_RE_POINTSIZE, 1); ADD_RANGE(0x4230, 3); ADD_RANGE(R300_RE_LINE_CNT, 1); ADD_RANGE(0x4238, 1); ADD_RANGE(0x4260, 3); ADD_RANGE(0x4274, 4); ADD_RANGE(0x4288, 5); ADD_RANGE(0x42A0, 1); ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4); ADD_RANGE(0x42B4, 1); ADD_RANGE(R300_RE_CULL_CNTL, 1); ADD_RANGE(0x42C0, 2); ADD_RANGE(R300_RS_CNTL_0, 2); ADD_RANGE(R300_RS_INTERP_0, 8); ADD_RANGE(R300_RS_ROUTE_0, 8); ADD_RANGE(0x43A4, 2); ADD_RANGE(0x43E8, 1); ADD_RANGE(R300_PFS_CNTL_0, 3); ADD_RANGE(R300_PFS_NODE_0, 4); ADD_RANGE(R300_PFS_TEXI_0, 64); ADD_RANGE(0x46A4, 5); ADD_RANGE(R300_PFS_INSTR0_0, 64); ADD_RANGE(R300_PFS_INSTR1_0, 64); ADD_RANGE(R300_PFS_INSTR2_0, 64); ADD_RANGE(R300_PFS_INSTR3_0, 64); ADD_RANGE(0x4BC0, 1); ADD_RANGE(0x4BC8, 3); ADD_RANGE(R300_PP_ALPHA_TEST, 2); ADD_RANGE(0x4BD8, 1); ADD_RANGE(R300_PFS_PARAM_0_X, 64); ADD_RANGE(0x4E00, 1); ADD_RANGE(R300_RB3D_CBLEND, 2); ADD_RANGE(R300_RB3D_COLORMASK, 1); ADD_RANGE(0x4E10, 3); ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */ ADD_RANGE(R300_RB3D_COLORPITCH0, 1); ADD_RANGE(0x4E50, 9); ADD_RANGE(0x4E88, 1); ADD_RANGE(0x4EA0, 2); ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3); ADD_RANGE(0x4F10, 4); ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */ ADD_RANGE(R300_RB3D_DEPTHPITCH, 1); ADD_RANGE(0x4F28, 1); ADD_RANGE(0x4F30, 2); ADD_RANGE(0x4F44, 1); ADD_RANGE(0x4F54, 1); ADD_RANGE(R300_TX_FILTER_0, 16); ADD_RANGE(R300_TX_UNK1_0, 16); ADD_RANGE(R300_TX_SIZE_0, 16); ADD_RANGE(R300_TX_FORMAT_0, 16); /* Texture offset is dangerous and needs more checking */ ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); ADD_RANGE(R300_TX_UNK4_0, 16); ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); /* Sporadic registers used as primitives are emitted */ ADD_RANGE(0x4f18, 1); ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1); ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8); ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8); } static __inline__ int r300_check_range(unsigned reg, int count) { int i; if(reg & ~0xffff)return -1; for(i=(reg>>2);i<(reg>>2)+count;i++) if(r300_reg_flags[i]!=MARK_SAFE)return 1; return 0; } /* we expect offsets passed to the framebuffer to be either within video memory or within AGP space */ static __inline__ int r300_check_offset(drm_radeon_private_t* dev_priv, u32 offset) { /* we realy want to check against end of video aperture but this value is not being kept. This code is correct for now (does the same thing as the code that sets MC_FB_LOCATION) in radeon_cp.c */ if((offset>=dev_priv->fb_location) && (offsetgart_vm_start))return 0; if((offset>=dev_priv->gart_vm_start) && (offsetgart_vm_start+dev_priv->gart_size))return 0; return 1; } static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t* dev_priv, drm_radeon_cmd_buffer_t* cmdbuf, drm_r300_cmd_header_t header) { int reg; int sz; int i; int values[64]; RING_LOCALS; sz = header.packet0.count; reg = (header.packet0.reghi << 8) | header.packet0.reglo; if((sz>64)||(sz<0)){ DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n", reg, sz); return DRM_ERR(EINVAL); } for(i=0;ibuf)[i]; switch(r300_reg_flags[(reg>>2)+i]){ case MARK_SAFE: break; case MARK_CHECK_OFFSET: if(r300_check_offset(dev_priv, (u32)values[i])){ DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n", reg, sz); return DRM_ERR(EINVAL); } break; default: DRM_ERROR("Register %04x failed check as flag=%02x\n", reg+i*4, r300_reg_flags[(reg>>2)+i]); return DRM_ERR(EINVAL); } } BEGIN_RING(1+sz); OUT_RING( CP_PACKET0( reg, sz-1 ) ); OUT_RING_TABLE( values, sz ); ADVANCE_RING(); cmdbuf->buf += sz*4; cmdbuf->bufsz -= sz*4; return 0; } /** * Emits a packet0 setting arbitrary registers. * Called by r300_do_cp_cmdbuf. * * Note that checks are performed on contents and addresses of the registers */ static __inline__ int r300_emit_packet0(drm_radeon_private_t* dev_priv, drm_radeon_cmd_buffer_t* cmdbuf, drm_r300_cmd_header_t header) { int reg; int sz; RING_LOCALS; sz = header.packet0.count; reg = (header.packet0.reghi << 8) | header.packet0.reglo; if (!sz) return 0; if (sz*4 > cmdbuf->bufsz) return DRM_ERR(EINVAL); if (reg+sz*4 >= 0x10000){ DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, sz); return DRM_ERR(EINVAL); } if(r300_check_range(reg, sz)){ /* go and check everything */ return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf, header); } /* the rest of the data is safe to emit, whatever the values the user passed */ BEGIN_RING(1+sz); OUT_RING( CP_PACKET0( reg, sz-1 ) ); OUT_RING_TABLE( (int __user*)cmdbuf->buf, sz ); ADVANCE_RING(); cmdbuf->buf += sz*4; cmdbuf->bufsz -= sz*4; return 0; } /** * Uploads user-supplied vertex program instructions or parameters onto * the graphics card. * Called by r300_do_cp_cmdbuf. */ static __inline__ int r300_emit_vpu(drm_radeon_private_t* dev_priv, drm_radeon_cmd_buffer_t* cmdbuf, drm_r300_cmd_header_t header) { int sz; int addr; RING_LOCALS; sz = header.vpu.count; addr = (header.vpu.adrhi << 8) | header.vpu.adrlo; if (!sz) return 0; if (sz*16 > cmdbuf->bufsz) return DRM_ERR(EINVAL); BEGIN_RING(5+sz*4); /* Wait for VAP to come to senses.. */ /* there is no need to emit it multiple times, (only once before VAP is programmed, but this optimization is for later */ OUT_RING_REG( R300_VAP_PVS_WAITIDLE, 0 ); OUT_RING_REG( R300_VAP_PVS_UPLOAD_ADDRESS, addr ); OUT_RING( CP_PACKET0_TABLE( R300_VAP_PVS_UPLOAD_DATA, sz*4 - 1 ) ); OUT_RING_TABLE( (int __user*)cmdbuf->buf, sz*4 ); ADVANCE_RING(); cmdbuf->buf += sz*16; cmdbuf->bufsz -= sz*16; return 0; } /** * Emit a clear packet from userspace. * Called by r300_emit_packet3. */ static __inline__ int r300_emit_clear(drm_radeon_private_t* dev_priv, drm_radeon_cmd_buffer_t* cmdbuf) { RING_LOCALS; if (8*4 > cmdbuf->bufsz) return DRM_ERR(EINVAL); BEGIN_RING(10); OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 8 ) ); OUT_RING( R300_PRIM_TYPE_POINT|R300_PRIM_WALK_RING| (1<buf, 8 ); ADVANCE_RING(); cmdbuf->buf += 8*4; cmdbuf->bufsz -= 8*4; return 0; } static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t* dev_priv, drm_radeon_cmd_buffer_t* cmdbuf, u32 header) { int count, i,k; #define MAX_ARRAY_PACKET 64 u32 payload[MAX_ARRAY_PACKET]; u32 narrays; RING_LOCALS; count=(header>>16) & 0x3fff; if((count+1)>MAX_ARRAY_PACKET){ DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", count); return DRM_ERR(EINVAL); } memset(payload, 0, MAX_ARRAY_PACKET*4); memcpy(payload, cmdbuf->buf+4, (count+1)*4); /* carefully check packet contents */ narrays=payload[0]; k=0; i=1; while((kbuf += (count+2)*4; cmdbuf->bufsz -= (count+2)*4; return 0; } static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t* dev_priv, drm_radeon_cmd_buffer_t* cmdbuf) { u32 header; int count; RING_LOCALS; if (4 > cmdbuf->bufsz) return DRM_ERR(EINVAL); /* Fixme !! This simply emits a packet without much checking. We need to be smarter. */ /* obtain first word - actual packet3 header */ header = *(u32 __user*)cmdbuf->buf; /* Is it packet 3 ? */ if( (header>>30)!=0x3 ) { DRM_ERROR("Not a packet3 header (0x%08x)\n", header); return DRM_ERR(EINVAL); } count=(header>>16) & 0x3fff; /* Check again now that we know how much data to expect */ if ((count+2)*4 > cmdbuf->bufsz){ DRM_ERROR("Expected packet3 of length %d but have only %d bytes left\n", (count+2)*4, cmdbuf->bufsz); return DRM_ERR(EINVAL); } /* Is it a packet type we know about ? */ switch(header & 0xff00){ case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header); case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ case RADEON_WAIT_FOR_IDLE: case RADEON_CP_NOP: /* these packets are safe */ break; default: DRM_ERROR("Unknown packet3 header (0x%08x)\n", header); return DRM_ERR(EINVAL); } BEGIN_RING(count+2); OUT_RING(header); OUT_RING_TABLE( (int __user*)(cmdbuf->buf+4), count+1); ADVANCE_RING(); cmdbuf->buf += (count+2)*4; cmdbuf->bufsz -= (count+2)*4; return 0; } /** * Emit a rendering packet3 from userspace. * Called by r300_do_cp_cmdbuf. */ static __inline__ int r300_emit_packet3(drm_radeon_private_t* dev_priv, drm_radeon_cmd_buffer_t* cmdbuf, drm_r300_cmd_header_t header) { int n; int ret; char __user* orig_buf = cmdbuf->buf; int orig_bufsz = cmdbuf->bufsz; /* This is a do-while-loop so that we run the interior at least once, * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale. */ n = 0; do { if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) { ret = r300_emit_cliprects(dev_priv, cmdbuf, n); if (ret) return ret; cmdbuf->buf = orig_buf; cmdbuf->bufsz = orig_bufsz; } switch(header.packet3.packet) { case R300_CMD_PACKET3_CLEAR: DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n"); ret = r300_emit_clear(dev_priv, cmdbuf); if (ret) { DRM_ERROR("r300_emit_clear failed\n"); return ret; } break; case R300_CMD_PACKET3_RAW: DRM_DEBUG("R300_CMD_PACKET3_RAW\n"); ret = r300_emit_raw_packet3(dev_priv, cmdbuf); if (ret) { DRM_ERROR("r300_emit_raw_packet3 failed\n"); return ret; } break; default: DRM_ERROR("bad packet3 type %i at %p\n", header.packet3.packet, cmdbuf->buf - sizeof(header)); return DRM_ERR(EINVAL); } n += R300_SIMULTANEOUS_CLIPRECTS; } while(n < cmdbuf->nbox); return 0; } /* Some of the R300 chips seem to be extremely touchy about the two registers * that are configured in r300_pacify. * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace * sends a command buffer that contains only state setting commands and a * vertex program/parameter upload sequence, this will eventually lead to a * lockup, unless the sequence is bracketed by calls to r300_pacify. * So we should take great care to *always* call r300_pacify before * *anything* 3D related, and again afterwards. This is what the * call bracket in r300_do_cp_cmdbuf is for. */ /** * Emit the sequence to pacify R300. */ static __inline__ void r300_pacify(drm_radeon_private_t* dev_priv) { RING_LOCALS; BEGIN_RING(6); OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) ); OUT_RING( 0xa ); OUT_RING( CP_PACKET0( 0x4f18, 0 ) ); OUT_RING( 0x3 ); OUT_RING( CP_PACKET3( RADEON_CP_NOP, 0 ) ); OUT_RING( 0x0 ); ADVANCE_RING(); } /** * Called by r300_do_cp_cmdbuf to update the internal buffer age and state. * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must * be careful about how this function is called. */ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; buf->pending = 1; buf->used = 0; } /** * Parses and validates a user-supplied command buffer and emits appropriate * commands on the DMA ring buffer. * Called by the ioctl handler function radeon_cp_cmdbuf. */ int r300_do_cp_cmdbuf(drm_device_t* dev, DRMFILE filp, drm_file_t* filp_priv, drm_radeon_cmd_buffer_t* cmdbuf) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf = NULL; int emit_dispatch_age = 0; int ret = 0; DRM_DEBUG("\n"); /* See the comment above r300_emit_begin3d for why this call must be here, * and what the cleanup gotos are for. */ r300_pacify(dev_priv); if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { ret = r300_emit_cliprects(dev_priv, cmdbuf, 0); if (ret) goto cleanup; } while(cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) { int idx; drm_r300_cmd_header_t header; header.u = *(unsigned int *)cmdbuf->buf; cmdbuf->buf += sizeof(header); cmdbuf->bufsz -= sizeof(header); switch(header.header.cmd_type) { case R300_CMD_PACKET0: DRM_DEBUG("R300_CMD_PACKET0\n"); ret = r300_emit_packet0(dev_priv, cmdbuf, header); if (ret) { DRM_ERROR("r300_emit_packet0 failed\n"); goto cleanup; } break; case R300_CMD_VPU: DRM_DEBUG("R300_CMD_VPU\n"); ret = r300_emit_vpu(dev_priv, cmdbuf, header); if (ret) { DRM_ERROR("r300_emit_vpu failed\n"); goto cleanup; } break; case R300_CMD_PACKET3: DRM_DEBUG("R300_CMD_PACKET3\n"); ret = r300_emit_packet3(dev_priv, cmdbuf, header); if (ret) { DRM_ERROR("r300_emit_packet3 failed\n"); goto cleanup; } break; case R300_CMD_END3D: DRM_DEBUG("R300_CMD_END3D\n"); /* TODO: Ideally userspace driver should not need to issue this call, i.e. the drm driver should issue it automatically and prevent lockups. In practice, we do not understand why this call is needed and what it does (except for some vague guesses that it has to do with cache coherence) and so the user space driver does it. Once we are sure which uses prevent lockups the code could be moved into the kernel and the userspace driver will not need to use this command. Note that issuing this command does not hurt anything except, possibly, performance */ r300_pacify(dev_priv); break; case R300_CMD_CP_DELAY: /* simple enough, we can do it here */ DRM_DEBUG("R300_CMD_CP_DELAY\n"); { int i; RING_LOCALS; BEGIN_RING(header.delay.count); for(i=0;i= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", idx, dma->buf_count - 1); ret = DRM_ERR(EINVAL); goto cleanup; } buf = dma->buflist[idx]; if (buf->filp != filp || buf->pending) { DRM_ERROR("bad buffer %p %p %d\n", buf->filp, filp, buf->pending); ret = DRM_ERR(EINVAL); goto cleanup; } emit_dispatch_age = 1; r300_discard_buffer(dev, buf); break; case R300_CMD_WAIT: /* simple enough, we can do it here */ DRM_DEBUG("R300_CMD_WAIT\n"); if(header.wait.flags==0)break; /* nothing to do */ { RING_LOCALS; BEGIN_RING(2); OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); OUT_RING( (header.wait.flags & 0xf)<<14 ); ADVANCE_RING(); } break; default: DRM_ERROR("bad cmd_type %i at %p\n", header.header.cmd_type, cmdbuf->buf - sizeof(header)); ret = DRM_ERR(EINVAL); goto cleanup; } } DRM_DEBUG("END\n"); cleanup: r300_pacify(dev_priv); /* We emit the vertex buffer age here, outside the pacifier "brackets" * for two reasons: * (1) This may coalesce multiple age emissions into a single one and * (2) more importantly, some chips lock up hard when scratch registers * are written inside the pacifier bracket. */ if (emit_dispatch_age) { RING_LOCALS; /* Emit the vertex buffer age */ BEGIN_RING(2); RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch); ADVANCE_RING(); } COMMIT_RING(); return ret; } Index: head/sys/dev/drm/r300_reg.h =================================================================== --- head/sys/dev/drm/r300_reg.h (revision 152908) +++ head/sys/dev/drm/r300_reg.h (revision 152909) @@ -1,1416 +1,1415 @@ /************************************************************************** Copyright (C) 2004-2005 Nicolai Haehnle et al. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation on the rights to use, copy, modify, merge, publish, distribute, sub license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -/* - * $FreeBSD$ - */ +#include +__FBSDID("$FreeBSD$"); #ifndef _R300_REG_H #define _R300_REG_H #define R300_MC_INIT_MISC_LAT_TIMER 0x180 # define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0 # define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4 # define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT 8 # define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT 12 # define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT 16 # define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT 20 # define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT 24 # define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT 28 #define R300_MC_INIT_GFX_LAT_TIMER 0x154 # define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT 0 # define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT 4 # define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT 8 # define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT 12 # define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT 16 # define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT 20 # define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT 24 # define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT 28 /* This file contains registers and constants for the R300. They have been found mostly by examining command buffers captured using glxtest, as well as by extrapolating some known registers and constants from the R200. I am fairly certain that they are correct unless stated otherwise in comments. */ #define R300_SE_VPORT_XSCALE 0x1D98 #define R300_SE_VPORT_XOFFSET 0x1D9C #define R300_SE_VPORT_YSCALE 0x1DA0 #define R300_SE_VPORT_YOFFSET 0x1DA4 #define R300_SE_VPORT_ZSCALE 0x1DA8 #define R300_SE_VPORT_ZOFFSET 0x1DAC /* This register is written directly and also starts data section in many 3d CP_PACKET3's */ #define R300_VAP_VF_CNTL 0x2084 # define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0 # define R300_VAP_VF_CNTL__PRIM_NONE (0<<0) # define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0) # define R300_VAP_VF_CNTL__PRIM_LINES (2<<0) # define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0) # define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0) # define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0) # define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0) # define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0) # define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0) # define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0) # define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0) # define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4 /* State based - direct writes to registers trigger vertex generation */ # define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4) # define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4) # define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4) # define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4) /* I don't think I saw these three used.. */ # define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6 # define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9 # define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10 /* index size - when not set the indices are assumed to be 16 bit */ # define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11) /* number of vertices */ # define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16 /* BEGIN: Wild guesses */ #define R300_VAP_OUTPUT_VTX_FMT_0 0x2090 # define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0) # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT (1<<1) # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */ # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */ # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */ # define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */ #define R300_VAP_OUTPUT_VTX_FMT_1 0x2094 # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9 # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12 # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15 # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18 # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21 /* END */ #define R300_SE_VTE_CNTL 0x20b0 # define R300_VPORT_X_SCALE_ENA 0x00000001 # define R300_VPORT_X_OFFSET_ENA 0x00000002 # define R300_VPORT_Y_SCALE_ENA 0x00000004 # define R300_VPORT_Y_OFFSET_ENA 0x00000008 # define R300_VPORT_Z_SCALE_ENA 0x00000010 # define R300_VPORT_Z_OFFSET_ENA 0x00000020 # define R300_VTX_XY_FMT 0x00000100 # define R300_VTX_Z_FMT 0x00000200 # define R300_VTX_W0_FMT 0x00000400 # define R300_VTX_W0_NORMALIZE 0x00000800 # define R300_VTX_ST_DENORMALIZED 0x00001000 /* BEGIN: Vertex data assembly - lots of uncertainties */ /* gap */ /* Where do we get our vertex data? // // Vertex data either comes either from immediate mode registers or from // vertex arrays. // There appears to be no mixed mode (though we can force the pitch of // vertex arrays to 0, effectively reusing the same element over and over // again). // // Immediate mode is controlled by the INPUT_CNTL registers. I am not sure // if these registers influence vertex array processing. // // Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3. // // In both cases, vertex attributes are then passed through INPUT_ROUTE. // Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data // into the vertex processor's input registers. // The first word routes the first input, the second word the second, etc. // The corresponding input is routed into the register with the given index. // The list is ended by a word with INPUT_ROUTE_END set. // // Always set COMPONENTS_4 in immediate mode. */ #define R300_VAP_INPUT_ROUTE_0_0 0x2150 # define R300_INPUT_ROUTE_COMPONENTS_1 (0 << 0) # define R300_INPUT_ROUTE_COMPONENTS_2 (1 << 0) # define R300_INPUT_ROUTE_COMPONENTS_3 (2 << 0) # define R300_INPUT_ROUTE_COMPONENTS_4 (3 << 0) # define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */ # define R300_VAP_INPUT_ROUTE_IDX_SHIFT 8 # define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */ # define R300_VAP_INPUT_ROUTE_END (1 << 13) # define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */ # define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */ # define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */ # define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */ #define R300_VAP_INPUT_ROUTE_0_1 0x2154 #define R300_VAP_INPUT_ROUTE_0_2 0x2158 #define R300_VAP_INPUT_ROUTE_0_3 0x215C #define R300_VAP_INPUT_ROUTE_0_4 0x2160 #define R300_VAP_INPUT_ROUTE_0_5 0x2164 #define R300_VAP_INPUT_ROUTE_0_6 0x2168 #define R300_VAP_INPUT_ROUTE_0_7 0x216C /* gap */ /* Notes: // - always set up to produce at least two attributes: // if vertex program uses only position, fglrx will set normal, too // - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal */ #define R300_VAP_INPUT_CNTL_0 0x2180 # define R300_INPUT_CNTL_0_COLOR 0x00000001 #define R300_VAP_INPUT_CNTL_1 0x2184 # define R300_INPUT_CNTL_POS 0x00000001 # define R300_INPUT_CNTL_NORMAL 0x00000002 # define R300_INPUT_CNTL_COLOR 0x00000004 # define R300_INPUT_CNTL_TC0 0x00000400 # define R300_INPUT_CNTL_TC1 0x00000800 # define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */ # define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */ # define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */ # define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */ # define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */ # define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */ /* gap */ /* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0 // are set to a swizzling bit pattern, other words are 0. // // In immediate mode, the pattern is always set to xyzw. In vertex array // mode, the swizzling pattern is e.g. used to set zw components in texture // coordinates with only tweo components. */ #define R300_VAP_INPUT_ROUTE_1_0 0x21E0 # define R300_INPUT_ROUTE_SELECT_X 0 # define R300_INPUT_ROUTE_SELECT_Y 1 # define R300_INPUT_ROUTE_SELECT_Z 2 # define R300_INPUT_ROUTE_SELECT_W 3 # define R300_INPUT_ROUTE_SELECT_ZERO 4 # define R300_INPUT_ROUTE_SELECT_ONE 5 # define R300_INPUT_ROUTE_SELECT_MASK 7 # define R300_INPUT_ROUTE_X_SHIFT 0 # define R300_INPUT_ROUTE_Y_SHIFT 3 # define R300_INPUT_ROUTE_Z_SHIFT 6 # define R300_INPUT_ROUTE_W_SHIFT 9 # define R300_INPUT_ROUTE_ENABLE (15 << 12) #define R300_VAP_INPUT_ROUTE_1_1 0x21E4 #define R300_VAP_INPUT_ROUTE_1_2 0x21E8 #define R300_VAP_INPUT_ROUTE_1_3 0x21EC #define R300_VAP_INPUT_ROUTE_1_4 0x21F0 #define R300_VAP_INPUT_ROUTE_1_5 0x21F4 #define R300_VAP_INPUT_ROUTE_1_6 0x21F8 #define R300_VAP_INPUT_ROUTE_1_7 0x21FC /* END */ /* gap */ /* BEGIN: Upload vertex program and data // The programmable vertex shader unit has a memory bank of unknown size // that can be written to in 16 byte units by writing the address into // UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs). // // Pointers into the memory bank are always in multiples of 16 bytes. // // The memory bank is divided into areas with fixed meaning. // // Starting at address UPLOAD_PROGRAM: Vertex program instructions. // Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB), // whereas the difference between known addresses suggests size 512. // // Starting at address UPLOAD_PARAMETERS: Vertex program parameters. // Native reported limits and the VPI layout suggest size 256, whereas // difference between known addresses suggests size 512. // // At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the // floating point pointsize. The exact purpose of this state is uncertain, // as there is also the R300_RE_POINTSIZE register. // // Multiple vertex programs and parameter sets can be loaded at once, // which could explain the size discrepancy. */ #define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200 # define R300_PVS_UPLOAD_PROGRAM 0x00000000 # define R300_PVS_UPLOAD_PARAMETERS 0x00000200 # define R300_PVS_UPLOAD_POINTSIZE 0x00000406 /* gap */ #define R300_VAP_PVS_UPLOAD_DATA 0x2208 /* END */ /* gap */ /* I do not know the purpose of this register. However, I do know that // it is set to 221C_CLEAR for clear operations and to 221C_NORMAL // for normal rendering. */ #define R300_VAP_UNKNOWN_221C 0x221C # define R300_221C_NORMAL 0x00000000 # define R300_221C_CLEAR 0x0001C000 /* gap */ /* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between // rendering commands and overwriting vertex program parameters. // Therefore, I suspect writing zero to 0x2284 synchronizes the engine and // avoids bugs caused by still running shaders reading bad data from memory. */ #define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */ /* Absolutely no clue what this register is about. */ #define R300_VAP_UNKNOWN_2288 0x2288 # define R300_2288_R300 0x00750000 /* -- nh */ # define R300_2288_RV350 0x0000FFFF /* -- Vladimir */ /* gap */ /* Addresses are relative to the vertex program instruction area of the // memory bank. PROGRAM_END points to the last instruction of the active // program // // The meaning of the two UNKNOWN fields is obviously not known. However, // experiments so far have shown that both *must* point to an instruction // inside the vertex program, otherwise the GPU locks up. // fglrx usually sets CNTL_3_UNKNOWN to the end of the program and // CNTL_1_UNKNOWN points to instruction where last write to position takes place. // Most likely this is used to ignore rest of the program in cases where group of verts arent visible. // For some reason this "section" is sometimes accepted other instruction that have // no relationship with position calculations. */ #define R300_VAP_PVS_CNTL_1 0x22D0 # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 # define R300_PVS_CNTL_1_POS_END_SHIFT 10 # define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 /* Addresses are relative the the vertex program parameters area. */ #define R300_VAP_PVS_CNTL_2 0x22D4 # define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 # define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 #define R300_VAP_PVS_CNTL_3 0x22D8 # define R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT 10 # define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0 /* The entire range from 0x2300 to 0x2AC inclusive seems to be used for // immediate vertices */ #define R300_VAP_VTX_COLOR_R 0x2464 #define R300_VAP_VTX_COLOR_G 0x2468 #define R300_VAP_VTX_COLOR_B 0x246C #define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */ #define R300_VAP_VTX_POS_0_Y_1 0x2494 #define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */ #define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */ #define R300_VAP_VTX_POS_0_Y_2 0x24A4 #define R300_VAP_VTX_POS_0_Z_2 0x24A8 #define R300_VAP_VTX_END_OF_PKT 0x24AC /* write 0 to indicate end of packet? */ /* gap */ /* These are values from r300_reg/r300_reg.h - they are known to be correct and are here so we can use one register file instead of several - Vladimir */ #define R300_GB_VAP_RASTER_VTX_FMT_0 0x4000 # define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT (1<<0) # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT (1<<1) # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT (1<<2) # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT (1<<3) # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT (1<<4) # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE (0xf<<5) # define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT (0x1<<16) #define R300_GB_VAP_RASTER_VTX_FMT_1 0x4004 /* each of the following is 3 bits wide, specifies number of components */ # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9 # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12 # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15 # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18 # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21 /* UNK30 seems to enables point to quad transformation on textures (or something closely related to that). This bit is rather fatal at the time being due to lackings at pixel shader side */ #define R300_GB_ENABLE 0x4008 # define R300_GB_POINT_STUFF_ENABLE (1<<0) # define R300_GB_LINE_STUFF_ENABLE (1<<1) # define R300_GB_TRIANGLE_STUFF_ENABLE (1<<2) # define R300_GB_STENCIL_AUTO_ENABLE (1<<4) # define R300_GB_UNK30 (1<<30) /* each of the following is 2 bits wide */ #define R300_GB_TEX_REPLICATE 0 #define R300_GB_TEX_ST 1 #define R300_GB_TEX_STR 2 # define R300_GB_TEX0_SOURCE_SHIFT 16 # define R300_GB_TEX1_SOURCE_SHIFT 18 # define R300_GB_TEX2_SOURCE_SHIFT 20 # define R300_GB_TEX3_SOURCE_SHIFT 22 # define R300_GB_TEX4_SOURCE_SHIFT 24 # define R300_GB_TEX5_SOURCE_SHIFT 26 # define R300_GB_TEX6_SOURCE_SHIFT 28 # define R300_GB_TEX7_SOURCE_SHIFT 30 /* MSPOS - positions for multisample antialiasing (?) */ #define R300_GB_MSPOS0 0x4010 /* shifts - each of the fields is 4 bits */ # define R300_GB_MSPOS0__MS_X0_SHIFT 0 # define R300_GB_MSPOS0__MS_Y0_SHIFT 4 # define R300_GB_MSPOS0__MS_X1_SHIFT 8 # define R300_GB_MSPOS0__MS_Y1_SHIFT 12 # define R300_GB_MSPOS0__MS_X2_SHIFT 16 # define R300_GB_MSPOS0__MS_Y2_SHIFT 20 # define R300_GB_MSPOS0__MSBD0_Y 24 # define R300_GB_MSPOS0__MSBD0_X 28 #define R300_GB_MSPOS1 0x4014 # define R300_GB_MSPOS1__MS_X3_SHIFT 0 # define R300_GB_MSPOS1__MS_Y3_SHIFT 4 # define R300_GB_MSPOS1__MS_X4_SHIFT 8 # define R300_GB_MSPOS1__MS_Y4_SHIFT 12 # define R300_GB_MSPOS1__MS_X5_SHIFT 16 # define R300_GB_MSPOS1__MS_Y5_SHIFT 20 # define R300_GB_MSPOS1__MSBD1 24 #define R300_GB_TILE_CONFIG 0x4018 # define R300_GB_TILE_ENABLE (1<<0) # define R300_GB_TILE_PIPE_COUNT_RV300 0 # define R300_GB_TILE_PIPE_COUNT_R300 (3<<1) # define R300_GB_TILE_PIPE_COUNT_R420 (7<<1) # define R300_GB_TILE_SIZE_8 0 # define R300_GB_TILE_SIZE_16 (1<<4) # define R300_GB_TILE_SIZE_32 (2<<4) # define R300_GB_SUPER_SIZE_1 (0<<6) # define R300_GB_SUPER_SIZE_2 (1<<6) # define R300_GB_SUPER_SIZE_4 (2<<6) # define R300_GB_SUPER_SIZE_8 (3<<6) # define R300_GB_SUPER_SIZE_16 (4<<6) # define R300_GB_SUPER_SIZE_32 (5<<6) # define R300_GB_SUPER_SIZE_64 (6<<6) # define R300_GB_SUPER_SIZE_128 (7<<6) # define R300_GB_SUPER_X_SHIFT 9 /* 3 bits wide */ # define R300_GB_SUPER_Y_SHIFT 12 /* 3 bits wide */ # define R300_GB_SUPER_TILE_A 0 # define R300_GB_SUPER_TILE_B (1<<15) # define R300_GB_SUBPIXEL_1_12 0 # define R300_GB_SUBPIXEL_1_16 (1<<16) #define R300_GB_FIFO_SIZE 0x4024 /* each of the following is 2 bits wide */ #define R300_GB_FIFO_SIZE_32 0 #define R300_GB_FIFO_SIZE_64 1 #define R300_GB_FIFO_SIZE_128 2 #define R300_GB_FIFO_SIZE_256 3 # define R300_SC_IFIFO_SIZE_SHIFT 0 # define R300_SC_TZFIFO_SIZE_SHIFT 2 # define R300_SC_BFIFO_SIZE_SHIFT 4 # define R300_US_OFIFO_SIZE_SHIFT 12 # define R300_US_WFIFO_SIZE_SHIFT 14 /* the following use the same constants as above, but meaning is is times 2 (i.e. instead of 32 words it means 64 */ # define R300_RS_TFIFO_SIZE_SHIFT 6 # define R300_RS_CFIFO_SIZE_SHIFT 8 # define R300_US_RAM_SIZE_SHIFT 10 /* watermarks, 3 bits wide */ # define R300_RS_HIGHWATER_COL_SHIFT 16 # define R300_RS_HIGHWATER_TEX_SHIFT 19 # define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */ # define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24 #define R300_GB_SELECT 0x401C # define R300_GB_FOG_SELECT_C0A 0 # define R300_GB_FOG_SELECT_C1A 1 # define R300_GB_FOG_SELECT_C2A 2 # define R300_GB_FOG_SELECT_C3A 3 # define R300_GB_FOG_SELECT_1_1_W 4 # define R300_GB_FOG_SELECT_Z 5 # define R300_GB_DEPTH_SELECT_Z 0 # define R300_GB_DEPTH_SELECT_1_1_W (1<<3) # define R300_GB_W_SELECT_1_W 0 # define R300_GB_W_SELECT_1 (1<<4) #define R300_GB_AA_CONFIG 0x4020 # define R300_AA_ENABLE 0x01 # define R300_AA_SUBSAMPLES_2 0 # define R300_AA_SUBSAMPLES_3 (1<<1) # define R300_AA_SUBSAMPLES_4 (2<<1) # define R300_AA_SUBSAMPLES_6 (3<<1) /* END */ /* gap */ /* The upper enable bits are guessed, based on fglrx reported limits. */ #define R300_TX_ENABLE 0x4104 # define R300_TX_ENABLE_0 (1 << 0) # define R300_TX_ENABLE_1 (1 << 1) # define R300_TX_ENABLE_2 (1 << 2) # define R300_TX_ENABLE_3 (1 << 3) # define R300_TX_ENABLE_4 (1 << 4) # define R300_TX_ENABLE_5 (1 << 5) # define R300_TX_ENABLE_6 (1 << 6) # define R300_TX_ENABLE_7 (1 << 7) # define R300_TX_ENABLE_8 (1 << 8) # define R300_TX_ENABLE_9 (1 << 9) # define R300_TX_ENABLE_10 (1 << 10) # define R300_TX_ENABLE_11 (1 << 11) # define R300_TX_ENABLE_12 (1 << 12) # define R300_TX_ENABLE_13 (1 << 13) # define R300_TX_ENABLE_14 (1 << 14) # define R300_TX_ENABLE_15 (1 << 15) /* The pointsize is given in multiples of 6. The pointsize can be // enormous: Clear() renders a single point that fills the entire // framebuffer. */ #define R300_RE_POINTSIZE 0x421C # define R300_POINTSIZE_Y_SHIFT 0 # define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */ # define R300_POINTSIZE_X_SHIFT 16 # define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */ # define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6) /* The line width is given in multiples of 6. In default mode lines are classified as vertical lines. HO: horizontal VE: vertical or horizontal HO & VE: no classification */ #define R300_RE_LINE_CNT 0x4234 # define R300_LINESIZE_SHIFT 0 # define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */ # define R300_LINESIZE_MAX (R300_LINESIZE_MASK / 6) # define R300_LINE_CNT_HO (1 << 16) # define R300_LINE_CNT_VE (1 << 17) /* Some sort of scale or clamp value for texcoordless textures. */ #define R300_RE_UNK4238 0x4238 #define R300_RE_SHADE_MODEL 0x4278 # define R300_RE_SHADE_MODEL_SMOOTH 0x3aaaa # define R300_RE_SHADE_MODEL_FLAT 0x39595 /* Dangerous */ #define R300_RE_POLYGON_MODE 0x4288 # define R300_PM_ENABLED (1 << 0) # define R300_PM_FRONT_POINT (0 << 0) # define R300_PM_BACK_POINT (0 << 0) # define R300_PM_FRONT_LINE (1 << 4) # define R300_PM_FRONT_FILL (1 << 5) # define R300_PM_BACK_LINE (1 << 7) # define R300_PM_BACK_FILL (1 << 8) /* Not sure why there are duplicate of factor and constant values. My best guess so far is that there are seperate zbiases for test and write. Ordering might be wrong. Some of the tests indicate that fgl has a fallback implementation of zbias via pixel shaders. */ #define R300_RE_ZBIAS_T_FACTOR 0x42A4 #define R300_RE_ZBIAS_T_CONSTANT 0x42A8 #define R300_RE_ZBIAS_W_FACTOR 0x42AC #define R300_RE_ZBIAS_W_CONSTANT 0x42B0 /* This register needs to be set to (1<<1) for RV350 to correctly perform depth test (see --vb-triangles in r300_demo) Don't know about other chips. - Vladimir This is set to 3 when GL_POLYGON_OFFSET_FILL is on. My guess is that there are two bits for each zbias primitive (FILL, LINE, POINT). One to enable depth test and one for depth write. Yet this doesnt explain why depth writes work ... */ #define R300_RE_OCCLUSION_CNTL 0x42B4 # define R300_OCCLUSION_ON (1<<1) #define R300_RE_CULL_CNTL 0x42B8 # define R300_CULL_FRONT (1 << 0) # define R300_CULL_BACK (1 << 1) # define R300_FRONT_FACE_CCW (0 << 2) # define R300_FRONT_FACE_CW (1 << 2) /* BEGIN: Rasterization / Interpolators - many guesses // 0_UNKNOWN_18 has always been set except for clear operations. // TC_CNT is the number of incoming texture coordinate sets (i.e. it depends // on the vertex program, *not* the fragment program) */ #define R300_RS_CNTL_0 0x4300 # define R300_RS_CNTL_TC_CNT_SHIFT 2 # define R300_RS_CNTL_TC_CNT_MASK (7 << 2) # define R300_RS_CNTL_CI_CNT_SHIFT 7 /* number of color interpolators used */ # define R300_RS_CNTL_0_UNKNOWN_18 (1 << 18) /* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n register. */ #define R300_RS_CNTL_1 0x4304 /* gap */ /* Only used for texture coordinates. // Use the source field to route texture coordinate input from the vertex program // to the desired interpolator. Note that the source field is relative to the // outputs the vertex program *actually* writes. If a vertex program only writes // texcoord[1], this will be source index 0. // Set INTERP_USED on all interpolators that produce data used by the // fragment program. INTERP_USED looks like a swizzling mask, but // I haven't seen it used that way. // // Note: The _UNKNOWN constants are always set in their respective register. // I don't know if this is necessary. */ #define R300_RS_INTERP_0 0x4310 #define R300_RS_INTERP_1 0x4314 # define R300_RS_INTERP_1_UNKNOWN 0x40 #define R300_RS_INTERP_2 0x4318 # define R300_RS_INTERP_2_UNKNOWN 0x80 #define R300_RS_INTERP_3 0x431C # define R300_RS_INTERP_3_UNKNOWN 0xC0 #define R300_RS_INTERP_4 0x4320 #define R300_RS_INTERP_5 0x4324 #define R300_RS_INTERP_6 0x4328 #define R300_RS_INTERP_7 0x432C # define R300_RS_INTERP_SRC_SHIFT 2 # define R300_RS_INTERP_SRC_MASK (7 << 2) # define R300_RS_INTERP_USED 0x00D10000 /* These DWORDs control how vertex data is routed into fragment program // registers, after interpolators. */ #define R300_RS_ROUTE_0 0x4330 #define R300_RS_ROUTE_1 0x4334 #define R300_RS_ROUTE_2 0x4338 #define R300_RS_ROUTE_3 0x433C /* GUESS */ #define R300_RS_ROUTE_4 0x4340 /* GUESS */ #define R300_RS_ROUTE_5 0x4344 /* GUESS */ #define R300_RS_ROUTE_6 0x4348 /* GUESS */ #define R300_RS_ROUTE_7 0x434C /* GUESS */ # define R300_RS_ROUTE_SOURCE_INTERP_0 0 # define R300_RS_ROUTE_SOURCE_INTERP_1 1 # define R300_RS_ROUTE_SOURCE_INTERP_2 2 # define R300_RS_ROUTE_SOURCE_INTERP_3 3 # define R300_RS_ROUTE_SOURCE_INTERP_4 4 # define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */ # define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */ # define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */ # define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */ # define R300_RS_ROUTE_DEST_SHIFT 6 # define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */ /* Special handling for color: When the fragment program uses color, // the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the // color register index. */ # define R300_RS_ROUTE_0_COLOR (1 << 14) # define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17 # define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */ /* As above, but for secondary color */ # define R300_RS_ROUTE_1_COLOR1 (1 << 14) # define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17 # define R300_RS_ROUTE_1_COLOR1_DEST_MASK (31 << 17) # define R300_RS_ROUTE_1_UNKNOWN11 (1 << 11) /* END */ /* BEGIN: Scissors and cliprects // There are four clipping rectangles. Their corner coordinates are inclusive. // Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending // on whether the pixel is inside cliprects 0-3, respectively. For example, // if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned // the number 3 (binary 0011). // Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set, // the pixel is rasterized. // // In addition to this, there is a scissors rectangle. Only pixels inside the // scissors rectangle are drawn. (coordinates are inclusive) // // For some reason, the top-left corner of the framebuffer is at (1440, 1440) // for the purpose of clipping and scissors. */ #define R300_RE_CLIPRECT_TL_0 0x43B0 #define R300_RE_CLIPRECT_BR_0 0x43B4 #define R300_RE_CLIPRECT_TL_1 0x43B8 #define R300_RE_CLIPRECT_BR_1 0x43BC #define R300_RE_CLIPRECT_TL_2 0x43C0 #define R300_RE_CLIPRECT_BR_2 0x43C4 #define R300_RE_CLIPRECT_TL_3 0x43C8 #define R300_RE_CLIPRECT_BR_3 0x43CC # define R300_CLIPRECT_OFFSET 1440 # define R300_CLIPRECT_MASK 0x1FFF # define R300_CLIPRECT_X_SHIFT 0 # define R300_CLIPRECT_X_MASK (0x1FFF << 0) # define R300_CLIPRECT_Y_SHIFT 13 # define R300_CLIPRECT_Y_MASK (0x1FFF << 13) #define R300_RE_CLIPRECT_CNTL 0x43D0 # define R300_CLIP_OUT (1 << 0) # define R300_CLIP_0 (1 << 1) # define R300_CLIP_1 (1 << 2) # define R300_CLIP_10 (1 << 3) # define R300_CLIP_2 (1 << 4) # define R300_CLIP_20 (1 << 5) # define R300_CLIP_21 (1 << 6) # define R300_CLIP_210 (1 << 7) # define R300_CLIP_3 (1 << 8) # define R300_CLIP_30 (1 << 9) # define R300_CLIP_31 (1 << 10) # define R300_CLIP_310 (1 << 11) # define R300_CLIP_32 (1 << 12) # define R300_CLIP_320 (1 << 13) # define R300_CLIP_321 (1 << 14) # define R300_CLIP_3210 (1 << 15) /* gap */ #define R300_RE_SCISSORS_TL 0x43E0 #define R300_RE_SCISSORS_BR 0x43E4 # define R300_SCISSORS_OFFSET 1440 # define R300_SCISSORS_X_SHIFT 0 # define R300_SCISSORS_X_MASK (0x1FFF << 0) # define R300_SCISSORS_Y_SHIFT 13 # define R300_SCISSORS_Y_MASK (0x1FFF << 13) /* END */ /* BEGIN: Texture specification // The texture specification dwords are grouped by meaning and not by texture unit. // This means that e.g. the offset for texture image unit N is found in register // TX_OFFSET_0 + (4*N) */ #define R300_TX_FILTER_0 0x4400 # define R300_TX_REPEAT 0 # define R300_TX_MIRRORED 1 # define R300_TX_CLAMP 4 # define R300_TX_CLAMP_TO_EDGE 2 # define R300_TX_CLAMP_TO_BORDER 6 # define R300_TX_WRAP_S_SHIFT 0 # define R300_TX_WRAP_S_MASK (7 << 0) # define R300_TX_WRAP_T_SHIFT 3 # define R300_TX_WRAP_T_MASK (7 << 3) # define R300_TX_WRAP_Q_SHIFT 6 # define R300_TX_WRAP_Q_MASK (7 << 6) # define R300_TX_MAG_FILTER_NEAREST (1 << 9) # define R300_TX_MAG_FILTER_LINEAR (2 << 9) # define R300_TX_MAG_FILTER_MASK (3 << 9) # define R300_TX_MIN_FILTER_NEAREST (1 << 11) # define R300_TX_MIN_FILTER_LINEAR (2 << 11) # define R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST (5 << 11) # define R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR (9 << 11) # define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 11) # define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR (10 << 11) /* NOTE: NEAREST doesnt seem to exist. Im not seting MAG_FILTER_MASK and (3 << 11) on for all anisotropy modes because that would void selected mag filter */ # define R300_TX_MIN_FILTER_ANISO_NEAREST ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/) # define R300_TX_MIN_FILTER_ANISO_LINEAR ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/) # define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST ((1 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/) # define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR ((2 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/) # define R300_TX_MIN_FILTER_MASK ( (15 << 11) | (3 << 13) ) # define R300_TX_MAX_ANISO_1_TO_1 (0 << 21) # define R300_TX_MAX_ANISO_2_TO_1 (2 << 21) # define R300_TX_MAX_ANISO_4_TO_1 (4 << 21) # define R300_TX_MAX_ANISO_8_TO_1 (6 << 21) # define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) # define R300_TX_MAX_ANISO_MASK (14 << 21) #define R300_TX_UNK1_0 0x4440 # define R300_LOD_BIAS_MASK 0x1fff #define R300_TX_SIZE_0 0x4480 # define R300_TX_WIDTHMASK_SHIFT 0 # define R300_TX_WIDTHMASK_MASK (2047 << 0) # define R300_TX_HEIGHTMASK_SHIFT 11 # define R300_TX_HEIGHTMASK_MASK (2047 << 11) # define R300_TX_UNK23 (1 << 23) # define R300_TX_SIZE_SHIFT 26 /* largest of width, height */ # define R300_TX_SIZE_MASK (15 << 26) #define R300_TX_FORMAT_0 0x44C0 /* The interpretation of the format word by Wladimir van der Laan */ /* The X, Y, Z and W refer to the layout of the components. They are given meanings as R, G, B and Alpha by the swizzle specification */ # define R300_TX_FORMAT_X8 0x0 # define R300_TX_FORMAT_X16 0x1 # define R300_TX_FORMAT_Y4X4 0x2 # define R300_TX_FORMAT_Y8X8 0x3 # define R300_TX_FORMAT_Y16X16 0x4 # define R300_TX_FORMAT_Z3Y3X2 0x5 # define R300_TX_FORMAT_Z5Y6X5 0x6 # define R300_TX_FORMAT_Z6Y5X5 0x7 # define R300_TX_FORMAT_Z11Y11X10 0x8 # define R300_TX_FORMAT_Z10Y11X11 0x9 # define R300_TX_FORMAT_W4Z4Y4X4 0xA # define R300_TX_FORMAT_W1Z5Y5X5 0xB # define R300_TX_FORMAT_W8Z8Y8X8 0xC # define R300_TX_FORMAT_W2Z10Y10X10 0xD # define R300_TX_FORMAT_W16Z16Y16X16 0xE # define R300_TX_FORMAT_DXT1 0xF # define R300_TX_FORMAT_DXT3 0x10 # define R300_TX_FORMAT_DXT5 0x11 # define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */ # define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */ # define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ # define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ /* 0x16 - some 16 bit green format.. ?? */ # define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ /* gap */ /* Floating point formats */ /* Note - hardware supports both 16 and 32 bit floating point */ # define R300_TX_FORMAT_FL_I16 0x18 # define R300_TX_FORMAT_FL_I16A16 0x19 # define R300_TX_FORMAT_FL_R16G16B16A16 0x1A # define R300_TX_FORMAT_FL_I32 0x1B # define R300_TX_FORMAT_FL_I32A32 0x1C # define R300_TX_FORMAT_FL_R32G32B32A32 0x1D /* alpha modes, convenience mostly */ /* if you have alpha, pick constant appropriate to the number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ # define R300_TX_FORMAT_ALPHA_1CH 0x000 # define R300_TX_FORMAT_ALPHA_2CH 0x200 # define R300_TX_FORMAT_ALPHA_4CH 0x600 # define R300_TX_FORMAT_ALPHA_NONE 0xA00 /* Swizzling */ /* constants */ # define R300_TX_FORMAT_X 0 # define R300_TX_FORMAT_Y 1 # define R300_TX_FORMAT_Z 2 # define R300_TX_FORMAT_W 3 # define R300_TX_FORMAT_ZERO 4 # define R300_TX_FORMAT_ONE 5 # define R300_TX_FORMAT_CUT_Z 6 /* 2.0*Z, everything above 1.0 is set to 0.0 */ # define R300_TX_FORMAT_CUT_W 7 /* 2.0*W, everything above 1.0 is set to 0.0 */ # define R300_TX_FORMAT_B_SHIFT 18 # define R300_TX_FORMAT_G_SHIFT 15 # define R300_TX_FORMAT_R_SHIFT 12 # define R300_TX_FORMAT_A_SHIFT 9 /* Convenience macro to take care of layout and swizzling */ # define R300_EASY_TX_FORMAT(B, G, R, A, FMT) (\ ((R300_TX_FORMAT_##B)< * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" #include "dev/drm/r300_reg.h" #define RADEON_FIFO_DEBUG 0 static int radeon_do_cleanup_cp(drm_device_t * dev); /* CP microcode (from ATI) */ static u32 R200_cp_microcode[][2] = { {0x21007000, 0000000000}, {0x20007000, 0000000000}, {0x000000ab, 0x00000004}, {0x000000af, 0x00000004}, {0x66544a49, 0000000000}, {0x49494174, 0000000000}, {0x54517d83, 0000000000}, {0x498d8b64, 0000000000}, {0x49494949, 0000000000}, {0x49da493c, 0000000000}, {0x49989898, 0000000000}, {0xd34949d5, 0000000000}, {0x9dc90e11, 0000000000}, {0xce9b9b9b, 0000000000}, {0x000f0000, 0x00000016}, {0x352e232c, 0000000000}, {0x00000013, 0x00000004}, {0x000f0000, 0x00000016}, {0x352e272c, 0000000000}, {0x000f0001, 0x00000016}, {0x3239362f, 0000000000}, {0x000077ef, 0x00000002}, {0x00061000, 0x00000002}, {0x00000020, 0x0000001a}, {0x00004000, 0x0000001e}, {0x00061000, 0x00000002}, {0x00000020, 0x0000001a}, {0x00004000, 0x0000001e}, {0x00061000, 0x00000002}, {0x00000020, 0x0000001a}, {0x00004000, 0x0000001e}, {0x00000016, 0x00000004}, {0x0003802a, 0x00000002}, {0x040067e0, 0x00000002}, {0x00000016, 0x00000004}, {0x000077e0, 0x00000002}, {0x00065000, 0x00000002}, {0x000037e1, 0x00000002}, {0x040067e1, 0x00000006}, {0x000077e0, 0x00000002}, {0x000077e1, 0x00000002}, {0x000077e1, 0x00000006}, {0xffffffff, 0000000000}, {0x10000000, 0000000000}, {0x0003802a, 0x00000002}, {0x040067e0, 0x00000006}, {0x00007675, 0x00000002}, {0x00007676, 0x00000002}, {0x00007677, 0x00000002}, {0x00007678, 0x00000006}, {0x0003802b, 0x00000002}, {0x04002676, 0x00000002}, {0x00007677, 0x00000002}, {0x00007678, 0x00000006}, {0x0000002e, 0x00000018}, {0x0000002e, 0x00000018}, {0000000000, 0x00000006}, {0x0000002f, 0x00000018}, {0x0000002f, 0x00000018}, {0000000000, 0x00000006}, {0x01605000, 0x00000002}, {0x00065000, 0x00000002}, {0x00098000, 0x00000002}, {0x00061000, 0x00000002}, {0x64c0603d, 0x00000004}, {0x00080000, 0x00000016}, {0000000000, 0000000000}, {0x0400251d, 0x00000002}, {0x00007580, 0x00000002}, {0x00067581, 0x00000002}, {0x04002580, 0x00000002}, {0x00067581, 0x00000002}, {0x00000046, 0x00000004}, {0x00005000, 0000000000}, {0x00061000, 0x00000002}, {0x0000750e, 0x00000002}, {0x00019000, 0x00000002}, {0x00011055, 0x00000014}, {0x00000055, 0x00000012}, {0x0400250f, 0x00000002}, {0x0000504a, 0x00000004}, {0x00007565, 0x00000002}, {0x00007566, 0x00000002}, {0x00000051, 0x00000004}, {0x01e655b4, 0x00000002}, {0x4401b0dc, 0x00000002}, {0x01c110dc, 0x00000002}, {0x2666705d, 0x00000018}, {0x040c2565, 0x00000002}, {0x0000005d, 0x00000018}, {0x04002564, 0x00000002}, {0x00007566, 0x00000002}, {0x00000054, 0x00000004}, {0x00401060, 0x00000008}, {0x00101000, 0x00000002}, {0x000d80ff, 0x00000002}, {0x00800063, 0x00000008}, {0x000f9000, 0x00000002}, {0x000e00ff, 0x00000002}, {0000000000, 0x00000006}, {0x00000080, 0x00000018}, {0x00000054, 0x00000004}, {0x00007576, 0x00000002}, {0x00065000, 0x00000002}, {0x00009000, 0x00000002}, {0x00041000, 0x00000002}, {0x0c00350e, 0x00000002}, {0x00049000, 0x00000002}, {0x00051000, 0x00000002}, {0x01e785f8, 0x00000002}, {0x00200000, 0x00000002}, {0x00600073, 0x0000000c}, {0x00007563, 0x00000002}, {0x006075f0, 0x00000021}, {0x20007068, 0x00000004}, {0x00005068, 0x00000004}, {0x00007576, 0x00000002}, {0x00007577, 0x00000002}, {0x0000750e, 0x00000002}, {0x0000750f, 0x00000002}, {0x00a05000, 0x00000002}, {0x00600076, 0x0000000c}, {0x006075f0, 0x00000021}, {0x000075f8, 0x00000002}, {0x00000076, 0x00000004}, {0x000a750e, 0x00000002}, {0x0020750f, 0x00000002}, {0x00600079, 0x00000004}, {0x00007570, 0x00000002}, {0x00007571, 0x00000002}, {0x00007572, 0x00000006}, {0x00005000, 0x00000002}, {0x00a05000, 0x00000002}, {0x00007568, 0x00000002}, {0x00061000, 0x00000002}, {0x00000084, 0x0000000c}, {0x00058000, 0x00000002}, {0x0c607562, 0x00000002}, {0x00000086, 0x00000004}, {0x00600085, 0x00000004}, {0x400070dd, 0000000000}, {0x000380dd, 0x00000002}, {0x00000093, 0x0000001c}, {0x00065095, 0x00000018}, {0x040025bb, 0x00000002}, {0x00061096, 0x00000018}, {0x040075bc, 0000000000}, {0x000075bb, 0x00000002}, {0x000075bc, 0000000000}, {0x00090000, 0x00000006}, {0x00090000, 0x00000002}, {0x000d8002, 0x00000006}, {0x00005000, 0x00000002}, {0x00007821, 0x00000002}, {0x00007800, 0000000000}, {0x00007821, 0x00000002}, {0x00007800, 0000000000}, {0x01665000, 0x00000002}, {0x000a0000, 0x00000002}, {0x000671cc, 0x00000002}, {0x0286f1cd, 0x00000002}, {0x000000a3, 0x00000010}, {0x21007000, 0000000000}, {0x000000aa, 0x0000001c}, {0x00065000, 0x00000002}, {0x000a0000, 0x00000002}, {0x00061000, 0x00000002}, {0x000b0000, 0x00000002}, {0x38067000, 0x00000002}, {0x000a00a6, 0x00000004}, {0x20007000, 0000000000}, {0x01200000, 0x00000002}, {0x20077000, 0x00000002}, {0x01200000, 0x00000002}, {0x20007000, 0000000000}, {0x00061000, 0x00000002}, {0x0120751b, 0x00000002}, {0x8040750a, 0x00000002}, {0x8040750b, 0x00000002}, {0x00110000, 0x00000002}, {0x000380dd, 0x00000002}, {0x000000bd, 0x0000001c}, {0x00061096, 0x00000018}, {0x844075bd, 0x00000002}, {0x00061095, 0x00000018}, {0x840075bb, 0x00000002}, {0x00061096, 0x00000018}, {0x844075bc, 0x00000002}, {0x000000c0, 0x00000004}, {0x804075bd, 0x00000002}, {0x800075bb, 0x00000002}, {0x804075bc, 0x00000002}, {0x00108000, 0x00000002}, {0x01400000, 0x00000002}, {0x006000c4, 0x0000000c}, {0x20c07000, 0x00000020}, {0x000000c6, 0x00000012}, {0x00800000, 0x00000006}, {0x0080751d, 0x00000006}, {0x000025bb, 0x00000002}, {0x000040c0, 0x00000004}, {0x0000775c, 0x00000002}, {0x00a05000, 0x00000002}, {0x00661000, 0x00000002}, {0x0460275d, 0x00000020}, {0x00004000, 0000000000}, {0x00007999, 0x00000002}, {0x00a05000, 0x00000002}, {0x00661000, 0x00000002}, {0x0460299b, 0x00000020}, {0x00004000, 0000000000}, {0x01e00830, 0x00000002}, {0x21007000, 0000000000}, {0x00005000, 0x00000002}, {0x00038042, 0x00000002}, {0x040025e0, 0x00000002}, {0x000075e1, 0000000000}, {0x00000001, 0000000000}, {0x000380d9, 0x00000002}, {0x04007394, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, }; static u32 radeon_cp_microcode[][2] = { {0x21007000, 0000000000}, {0x20007000, 0000000000}, {0x000000b4, 0x00000004}, {0x000000b8, 0x00000004}, {0x6f5b4d4c, 0000000000}, {0x4c4c427f, 0000000000}, {0x5b568a92, 0000000000}, {0x4ca09c6d, 0000000000}, {0xad4c4c4c, 0000000000}, {0x4ce1af3d, 0000000000}, {0xd8afafaf, 0000000000}, {0xd64c4cdc, 0000000000}, {0x4cd10d10, 0000000000}, {0x000f0000, 0x00000016}, {0x362f242d, 0000000000}, {0x00000012, 0x00000004}, {0x000f0000, 0x00000016}, {0x362f282d, 0000000000}, {0x000380e7, 0x00000002}, {0x04002c97, 0x00000002}, {0x000f0001, 0x00000016}, {0x333a3730, 0000000000}, {0x000077ef, 0x00000002}, {0x00061000, 0x00000002}, {0x00000021, 0x0000001a}, {0x00004000, 0x0000001e}, {0x00061000, 0x00000002}, {0x00000021, 0x0000001a}, {0x00004000, 0x0000001e}, {0x00061000, 0x00000002}, {0x00000021, 0x0000001a}, {0x00004000, 0x0000001e}, {0x00000017, 0x00000004}, {0x0003802b, 0x00000002}, {0x040067e0, 0x00000002}, {0x00000017, 0x00000004}, {0x000077e0, 0x00000002}, {0x00065000, 0x00000002}, {0x000037e1, 0x00000002}, {0x040067e1, 0x00000006}, {0x000077e0, 0x00000002}, {0x000077e1, 0x00000002}, {0x000077e1, 0x00000006}, {0xffffffff, 0000000000}, {0x10000000, 0000000000}, {0x0003802b, 0x00000002}, {0x040067e0, 0x00000006}, {0x00007675, 0x00000002}, {0x00007676, 0x00000002}, {0x00007677, 0x00000002}, {0x00007678, 0x00000006}, {0x0003802c, 0x00000002}, {0x04002676, 0x00000002}, {0x00007677, 0x00000002}, {0x00007678, 0x00000006}, {0x0000002f, 0x00000018}, {0x0000002f, 0x00000018}, {0000000000, 0x00000006}, {0x00000030, 0x00000018}, {0x00000030, 0x00000018}, {0000000000, 0x00000006}, {0x01605000, 0x00000002}, {0x00065000, 0x00000002}, {0x00098000, 0x00000002}, {0x00061000, 0x00000002}, {0x64c0603e, 0x00000004}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x00080000, 0x00000016}, {0000000000, 0000000000}, {0x0400251d, 0x00000002}, {0x00007580, 0x00000002}, {0x00067581, 0x00000002}, {0x04002580, 0x00000002}, {0x00067581, 0x00000002}, {0x00000049, 0x00000004}, {0x00005000, 0000000000}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x00061000, 0x00000002}, {0x0000750e, 0x00000002}, {0x00019000, 0x00000002}, {0x00011055, 0x00000014}, {0x00000055, 0x00000012}, {0x0400250f, 0x00000002}, {0x0000504f, 0x00000004}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x00007565, 0x00000002}, {0x00007566, 0x00000002}, {0x00000058, 0x00000004}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x01e655b4, 0x00000002}, {0x4401b0e4, 0x00000002}, {0x01c110e4, 0x00000002}, {0x26667066, 0x00000018}, {0x040c2565, 0x00000002}, {0x00000066, 0x00000018}, {0x04002564, 0x00000002}, {0x00007566, 0x00000002}, {0x0000005d, 0x00000004}, {0x00401069, 0x00000008}, {0x00101000, 0x00000002}, {0x000d80ff, 0x00000002}, {0x0080006c, 0x00000008}, {0x000f9000, 0x00000002}, {0x000e00ff, 0x00000002}, {0000000000, 0x00000006}, {0x0000008f, 0x00000018}, {0x0000005b, 0x00000004}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x00007576, 0x00000002}, {0x00065000, 0x00000002}, {0x00009000, 0x00000002}, {0x00041000, 0x00000002}, {0x0c00350e, 0x00000002}, {0x00049000, 0x00000002}, {0x00051000, 0x00000002}, {0x01e785f8, 0x00000002}, {0x00200000, 0x00000002}, {0x0060007e, 0x0000000c}, {0x00007563, 0x00000002}, {0x006075f0, 0x00000021}, {0x20007073, 0x00000004}, {0x00005073, 0x00000004}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x00007576, 0x00000002}, {0x00007577, 0x00000002}, {0x0000750e, 0x00000002}, {0x0000750f, 0x00000002}, {0x00a05000, 0x00000002}, {0x00600083, 0x0000000c}, {0x006075f0, 0x00000021}, {0x000075f8, 0x00000002}, {0x00000083, 0x00000004}, {0x000a750e, 0x00000002}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x0020750f, 0x00000002}, {0x00600086, 0x00000004}, {0x00007570, 0x00000002}, {0x00007571, 0x00000002}, {0x00007572, 0x00000006}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x00005000, 0x00000002}, {0x00a05000, 0x00000002}, {0x00007568, 0x00000002}, {0x00061000, 0x00000002}, {0x00000095, 0x0000000c}, {0x00058000, 0x00000002}, {0x0c607562, 0x00000002}, {0x00000097, 0x00000004}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x00600096, 0x00000004}, {0x400070e5, 0000000000}, {0x000380e6, 0x00000002}, {0x040025c5, 0x00000002}, {0x000380e5, 0x00000002}, {0x000000a8, 0x0000001c}, {0x000650aa, 0x00000018}, {0x040025bb, 0x00000002}, {0x000610ab, 0x00000018}, {0x040075bc, 0000000000}, {0x000075bb, 0x00000002}, {0x000075bc, 0000000000}, {0x00090000, 0x00000006}, {0x00090000, 0x00000002}, {0x000d8002, 0x00000006}, {0x00007832, 0x00000002}, {0x00005000, 0x00000002}, {0x000380e7, 0x00000002}, {0x04002c97, 0x00000002}, {0x00007820, 0x00000002}, {0x00007821, 0x00000002}, {0x00007800, 0000000000}, {0x01200000, 0x00000002}, {0x20077000, 0x00000002}, {0x01200000, 0x00000002}, {0x20007000, 0x00000002}, {0x00061000, 0x00000002}, {0x0120751b, 0x00000002}, {0x8040750a, 0x00000002}, {0x8040750b, 0x00000002}, {0x00110000, 0x00000002}, {0x000380e5, 0x00000002}, {0x000000c6, 0x0000001c}, {0x000610ab, 0x00000018}, {0x844075bd, 0x00000002}, {0x000610aa, 0x00000018}, {0x840075bb, 0x00000002}, {0x000610ab, 0x00000018}, {0x844075bc, 0x00000002}, {0x000000c9, 0x00000004}, {0x804075bd, 0x00000002}, {0x800075bb, 0x00000002}, {0x804075bc, 0x00000002}, {0x00108000, 0x00000002}, {0x01400000, 0x00000002}, {0x006000cd, 0x0000000c}, {0x20c07000, 0x00000020}, {0x000000cf, 0x00000012}, {0x00800000, 0x00000006}, {0x0080751d, 0x00000006}, {0000000000, 0000000000}, {0x0000775c, 0x00000002}, {0x00a05000, 0x00000002}, {0x00661000, 0x00000002}, {0x0460275d, 0x00000020}, {0x00004000, 0000000000}, {0x01e00830, 0x00000002}, {0x21007000, 0000000000}, {0x6464614d, 0000000000}, {0x69687420, 0000000000}, {0x00000073, 0000000000}, {0000000000, 0000000000}, {0x00005000, 0x00000002}, {0x000380d0, 0x00000002}, {0x040025e0, 0x00000002}, {0x000075e1, 0000000000}, {0x00000001, 0000000000}, {0x000380e0, 0x00000002}, {0x04002394, 0x00000002}, {0x00005000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0x00000008, 0000000000}, {0x00000004, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, {0000000000, 0000000000}, }; static u32 R300_cp_microcode[][2] = { { 0x4200e000, 0000000000 }, { 0x4000e000, 0000000000 }, { 0x000000af, 0x00000008 }, { 0x000000b3, 0x00000008 }, { 0x6c5a504f, 0000000000 }, { 0x4f4f497a, 0000000000 }, { 0x5a578288, 0000000000 }, { 0x4f91906a, 0000000000 }, { 0x4f4f4f4f, 0000000000 }, { 0x4fe24f44, 0000000000 }, { 0x4f9c9c9c, 0000000000 }, { 0xdc4f4fde, 0000000000 }, { 0xa1cd4f4f, 0000000000 }, { 0xd29d9d9d, 0000000000 }, { 0x4f0f9fd7, 0000000000 }, { 0x000ca000, 0x00000004 }, { 0x000d0012, 0x00000038 }, { 0x0000e8b4, 0x00000004 }, { 0x000d0014, 0x00000038 }, { 0x0000e8b6, 0x00000004 }, { 0x000d0016, 0x00000038 }, { 0x0000e854, 0x00000004 }, { 0x000d0018, 0x00000038 }, { 0x0000e855, 0x00000004 }, { 0x000d001a, 0x00000038 }, { 0x0000e856, 0x00000004 }, { 0x000d001c, 0x00000038 }, { 0x0000e857, 0x00000004 }, { 0x000d001e, 0x00000038 }, { 0x0000e824, 0x00000004 }, { 0x000d0020, 0x00000038 }, { 0x0000e825, 0x00000004 }, { 0x000d0022, 0x00000038 }, { 0x0000e830, 0x00000004 }, { 0x000d0024, 0x00000038 }, { 0x0000f0c0, 0x00000004 }, { 0x000d0026, 0x00000038 }, { 0x0000f0c1, 0x00000004 }, { 0x000d0028, 0x00000038 }, { 0x0000f041, 0x00000004 }, { 0x000d002a, 0x00000038 }, { 0x0000f184, 0x00000004 }, { 0x000d002c, 0x00000038 }, { 0x0000f185, 0x00000004 }, { 0x000d002e, 0x00000038 }, { 0x0000f186, 0x00000004 }, { 0x000d0030, 0x00000038 }, { 0x0000f187, 0x00000004 }, { 0x000d0032, 0x00000038 }, { 0x0000f180, 0x00000004 }, { 0x000d0034, 0x00000038 }, { 0x0000f393, 0x00000004 }, { 0x000d0036, 0x00000038 }, { 0x0000f38a, 0x00000004 }, { 0x000d0038, 0x00000038 }, { 0x0000f38e, 0x00000004 }, { 0x0000e821, 0x00000004 }, { 0x0140a000, 0x00000004 }, { 0x00000043, 0x00000018 }, { 0x00cce800, 0x00000004 }, { 0x001b0001, 0x00000004 }, { 0x08004800, 0x00000004 }, { 0x001b0001, 0x00000004 }, { 0x08004800, 0x00000004 }, { 0x001b0001, 0x00000004 }, { 0x08004800, 0x00000004 }, { 0x0000003a, 0x00000008 }, { 0x0000a000, 0000000000 }, { 0x02c0a000, 0x00000004 }, { 0x000ca000, 0x00000004 }, { 0x00130000, 0x00000004 }, { 0x000c2000, 0x00000004 }, { 0xc980c045, 0x00000008 }, { 0x2000451d, 0x00000004 }, { 0x0000e580, 0x00000004 }, { 0x000ce581, 0x00000004 }, { 0x08004580, 0x00000004 }, { 0x000ce581, 0x00000004 }, { 0x0000004c, 0x00000008 }, { 0x0000a000, 0000000000 }, { 0x000c2000, 0x00000004 }, { 0x0000e50e, 0x00000004 }, { 0x00032000, 0x00000004 }, { 0x00022056, 0x00000028 }, { 0x00000056, 0x00000024 }, { 0x0800450f, 0x00000004 }, { 0x0000a050, 0x00000008 }, { 0x0000e565, 0x00000004 }, { 0x0000e566, 0x00000004 }, { 0x00000057, 0x00000008 }, { 0x03cca5b4, 0x00000004 }, { 0x05432000, 0x00000004 }, { 0x00022000, 0x00000004 }, { 0x4ccce063, 0x00000030 }, { 0x08274565, 0x00000004 }, { 0x00000063, 0x00000030 }, { 0x08004564, 0x00000004 }, { 0x0000e566, 0x00000004 }, { 0x0000005a, 0x00000008 }, { 0x00802066, 0x00000010 }, { 0x00202000, 0x00000004 }, { 0x001b00ff, 0x00000004 }, { 0x01000069, 0x00000010 }, { 0x001f2000, 0x00000004 }, { 0x001c00ff, 0x00000004 }, { 0000000000, 0x0000000c }, { 0x00000085, 0x00000030 }, { 0x0000005a, 0x00000008 }, { 0x0000e576, 0x00000004 }, { 0x000ca000, 0x00000004 }, { 0x00012000, 0x00000004 }, { 0x00082000, 0x00000004 }, { 0x1800650e, 0x00000004 }, { 0x00092000, 0x00000004 }, { 0x000a2000, 0x00000004 }, { 0x000f0000, 0x00000004 }, { 0x00400000, 0x00000004 }, { 0x00000079, 0x00000018 }, { 0x0000e563, 0x00000004 }, { 0x00c0e5f9, 0x000000c2 }, { 0x0000006e, 0x00000008 }, { 0x0000a06e, 0x00000008 }, { 0x0000e576, 0x00000004 }, { 0x0000e577, 0x00000004 }, { 0x0000e50e, 0x00000004 }, { 0x0000e50f, 0x00000004 }, { 0x0140a000, 0x00000004 }, { 0x0000007c, 0x00000018 }, { 0x00c0e5f9, 0x000000c2 }, { 0x0000007c, 0x00000008 }, { 0x0014e50e, 0x00000004 }, { 0x0040e50f, 0x00000004 }, { 0x00c0007f, 0x00000008 }, { 0x0000e570, 0x00000004 }, { 0x0000e571, 0x00000004 }, { 0x0000e572, 0x0000000c }, { 0x0000a000, 0x00000004 }, { 0x0140a000, 0x00000004 }, { 0x0000e568, 0x00000004 }, { 0x000c2000, 0x00000004 }, { 0x00000089, 0x00000018 }, { 0x000b0000, 0x00000004 }, { 0x18c0e562, 0x00000004 }, { 0x0000008b, 0x00000008 }, { 0x00c0008a, 0x00000008 }, { 0x000700e4, 0x00000004 }, { 0x00000097, 0x00000038 }, { 0x000ca099, 0x00000030 }, { 0x080045bb, 0x00000004 }, { 0x000c209a, 0x00000030 }, { 0x0800e5bc, 0000000000 }, { 0x0000e5bb, 0x00000004 }, { 0x0000e5bc, 0000000000 }, { 0x00120000, 0x0000000c }, { 0x00120000, 0x00000004 }, { 0x001b0002, 0x0000000c }, { 0x0000a000, 0x00000004 }, { 0x0000e821, 0x00000004 }, { 0x0000e800, 0000000000 }, { 0x0000e821, 0x00000004 }, { 0x0000e82e, 0000000000 }, { 0x02cca000, 0x00000004 }, { 0x00140000, 0x00000004 }, { 0x000ce1cc, 0x00000004 }, { 0x050de1cd, 0x00000004 }, { 0x000000a7, 0x00000020 }, { 0x4200e000, 0000000000 }, { 0x000000ae, 0x00000038 }, { 0x000ca000, 0x00000004 }, { 0x00140000, 0x00000004 }, { 0x000c2000, 0x00000004 }, { 0x00160000, 0x00000004 }, { 0x700ce000, 0x00000004 }, { 0x001400aa, 0x00000008 }, { 0x4000e000, 0000000000 }, { 0x02400000, 0x00000004 }, { 0x400ee000, 0x00000004 }, { 0x02400000, 0x00000004 }, { 0x4000e000, 0000000000 }, { 0x000c2000, 0x00000004 }, { 0x0240e51b, 0x00000004 }, { 0x0080e50a, 0x00000005 }, { 0x0080e50b, 0x00000005 }, { 0x00220000, 0x00000004 }, { 0x000700e4, 0x00000004 }, { 0x000000c1, 0x00000038 }, { 0x000c209a, 0x00000030 }, { 0x0880e5bd, 0x00000005 }, { 0x000c2099, 0x00000030 }, { 0x0800e5bb, 0x00000005 }, { 0x000c209a, 0x00000030 }, { 0x0880e5bc, 0x00000005 }, { 0x000000c4, 0x00000008 }, { 0x0080e5bd, 0x00000005 }, { 0x0000e5bb, 0x00000005 }, { 0x0080e5bc, 0x00000005 }, { 0x00210000, 0x00000004 }, { 0x02800000, 0x00000004 }, { 0x00c000c8, 0x00000018 }, { 0x4180e000, 0x00000040 }, { 0x000000ca, 0x00000024 }, { 0x01000000, 0x0000000c }, { 0x0100e51d, 0x0000000c }, { 0x000045bb, 0x00000004 }, { 0x000080c4, 0x00000008 }, { 0x0000f3ce, 0x00000004 }, { 0x0140a000, 0x00000004 }, { 0x00cc2000, 0x00000004 }, { 0x08c053cf, 0x00000040 }, { 0x00008000, 0000000000 }, { 0x0000f3d2, 0x00000004 }, { 0x0140a000, 0x00000004 }, { 0x00cc2000, 0x00000004 }, { 0x08c053d3, 0x00000040 }, { 0x00008000, 0000000000 }, { 0x0000f39d, 0x00000004 }, { 0x0140a000, 0x00000004 }, { 0x00cc2000, 0x00000004 }, { 0x08c0539e, 0x00000040 }, { 0x00008000, 0000000000 }, { 0x03c00830, 0x00000004 }, { 0x4200e000, 0000000000 }, { 0x0000a000, 0x00000004 }, { 0x200045e0, 0x00000004 }, { 0x0000e5e1, 0000000000 }, { 0x00000001, 0000000000 }, { 0x000700e1, 0x00000004 }, { 0x0800e394, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, { 0000000000, 0000000000 }, }; static int RADEON_READ_PLL(drm_device_t * dev, int addr) { drm_radeon_private_t *dev_priv = dev->dev_private; RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f); return RADEON_READ(RADEON_CLOCK_CNTL_DATA); } static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) { RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); return RADEON_READ(RADEON_PCIE_DATA); } #if RADEON_FIFO_DEBUG static void radeon_status(drm_radeon_private_t * dev_priv) { printk("%s:\n", __FUNCTION__); printk("RBBM_STATUS = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_RBBM_STATUS)); printk("CP_RB_RTPR = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR)); printk("CP_RB_WTPR = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR)); printk("AIC_CNTL = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_CNTL)); printk("AIC_STAT = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_STAT)); printk("AIC_PT_BASE = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE)); printk("TLB_ADDR = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR)); printk("TLB_DATA = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA)); } #endif /* ================================================================ * Engine, FIFO control */ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) { u32 tmp; int i; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT); tmp |= RADEON_RB2D_DC_FLUSH_ALL; RADEON_WRITE(RADEON_RB2D_DSTCACHE_CTLSTAT, tmp); for (i = 0; i < dev_priv->usec_timeout; i++) { if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY)) { return 0; } DRM_UDELAY(1); } #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif return DRM_ERR(EBUSY); } static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) { int i; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; for (i = 0; i < dev_priv->usec_timeout; i++) { int slots = (RADEON_READ(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK); if (slots >= entries) return 0; DRM_UDELAY(1); } #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif return DRM_ERR(EBUSY); } static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) { int i, ret; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; ret = radeon_do_wait_for_fifo(dev_priv, 64); if (ret) return ret; for (i = 0; i < dev_priv->usec_timeout; i++) { if (!(RADEON_READ(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) { radeon_do_pixcache_flush(dev_priv); return 0; } DRM_UDELAY(1); } #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif return DRM_ERR(EBUSY); } /* ================================================================ * CP control, initialization */ /* Load the microcode for the CP */ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv) { int i; DRM_DEBUG("\n"); radeon_do_wait_for_idle(dev_priv); RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0); if (dev_priv->microcode_version==UCODE_R200) { DRM_INFO("Loading R200 Microcode\n"); for (i = 0; i < 256; i++) { RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, R200_cp_microcode[i][1]); RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, R200_cp_microcode[i][0]); } } else if (dev_priv->microcode_version==UCODE_R300) { DRM_INFO("Loading R300 Microcode\n"); for ( i = 0 ; i < 256 ; i++ ) { RADEON_WRITE( RADEON_CP_ME_RAM_DATAH, R300_cp_microcode[i][1] ); RADEON_WRITE( RADEON_CP_ME_RAM_DATAL, R300_cp_microcode[i][0] ); } } else { for (i = 0; i < 256; i++) { RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, radeon_cp_microcode[i][1]); RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, radeon_cp_microcode[i][0]); } } } /* Flush any pending commands to the CP. This should only be used just * prior to a wait for idle, as it informs the engine that the command * stream is ending. */ static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv) { DRM_DEBUG("\n"); #if 0 u32 tmp; tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31); RADEON_WRITE(RADEON_CP_RB_WPTR, tmp); #endif } /* Wait for the CP to go idle. */ int radeon_do_cp_idle(drm_radeon_private_t * dev_priv) { RING_LOCALS; DRM_DEBUG("\n"); BEGIN_RING(6); RADEON_PURGE_CACHE(); RADEON_PURGE_ZCACHE(); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); COMMIT_RING(); return radeon_do_wait_for_idle(dev_priv); } /* Start the Command Processor. */ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) { RING_LOCALS; DRM_DEBUG("\n"); radeon_do_wait_for_idle(dev_priv); RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode); dev_priv->cp_running = 1; BEGIN_RING(6); RADEON_PURGE_CACHE(); RADEON_PURGE_ZCACHE(); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); COMMIT_RING(); } /* Reset the Command Processor. This will not flush any pending * commands, so you must wait for the CP command stream to complete * before calling this routine. */ static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv) { u32 cur_read_ptr; DRM_DEBUG("\n"); cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); SET_RING_HEAD(dev_priv, cur_read_ptr); dev_priv->ring.tail = cur_read_ptr; } /* Stop the Command Processor. This will not flush any pending * commands, so you must flush the command stream and wait for the CP * to go idle before calling this routine. */ static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv) { DRM_DEBUG("\n"); RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS); dev_priv->cp_running = 0; } /* Reset the engine. This will stop the CP if it is running. */ static int radeon_do_engine_reset(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; DRM_DEBUG("\n"); radeon_do_pixcache_flush(dev_priv); clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX); mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL); RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl | RADEON_FORCEON_MCLKA | RADEON_FORCEON_MCLKB | RADEON_FORCEON_YCLKA | RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC | RADEON_FORCEON_AIC)); rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET); RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | RADEON_SOFT_RESET_CP | RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | RADEON_SOFT_RESET_E2 | RADEON_SOFT_RESET_RB)); RADEON_READ(RADEON_RBBM_SOFT_RESET); RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & ~(RADEON_SOFT_RESET_CP | RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | RADEON_SOFT_RESET_E2 | RADEON_SOFT_RESET_RB))); RADEON_READ(RADEON_RBBM_SOFT_RESET); RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl); RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); /* Reset the CP ring */ radeon_do_cp_reset(dev_priv); /* The CP is no longer running after an engine reset */ dev_priv->cp_running = 0; /* Reset any pending vertex, indirect buffers */ radeon_freelist_reset(dev); return 0; } static void radeon_cp_init_ring_buffer(drm_device_t * dev, drm_radeon_private_t * dev_priv) { u32 ring_start, cur_read_ptr; u32 tmp; /* Initialize the memory controller */ RADEON_WRITE(RADEON_MC_FB_LOCATION, ((dev_priv->gart_vm_start - 1) & 0xffff0000) | (dev_priv->fb_location >> 16)); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { RADEON_WRITE(RADEON_MC_AGP_LOCATION, (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 0xffff0000) | (dev_priv->gart_vm_start >> 16))); ring_start = (dev_priv->cp_ring->offset - dev->agp->base + dev_priv->gart_vm_start); } else #endif ring_start = (dev_priv->cp_ring->offset - - dev->sg->handle + dev_priv->gart_vm_start); + - (unsigned long)dev->sg->virtual + dev_priv->gart_vm_start); RADEON_WRITE(RADEON_CP_RB_BASE, ring_start); /* Set the write pointer delay */ RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0); /* Initialize the ring buffer's read and write pointers */ cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); SET_RING_HEAD(dev_priv, cur_read_ptr); dev_priv->ring.tail = cur_read_ptr; #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { /* set RADEON_AGP_BASE here instead of relying on X from user space */ RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset - dev->agp->base + dev_priv->gart_vm_start); } else #endif { drm_sg_mem_t *entry = dev->sg; unsigned long tmp_ofs, page_ofs; - tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle; + tmp_ofs = dev_priv->ring_rptr->offset - (unsigned long)dev->sg->virtual; page_ofs = tmp_ofs >> PAGE_SHIFT; RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n", (unsigned long)entry->busaddr[page_ofs], entry->handle + tmp_ofs); } /* Initialize the scratch register pointer. This will cause * the scratch register values to be written out to memory * whenever they are updated. * * We simply put this behind the ring read pointer, this works * with PCI GART as well as (whatever kind of) AGP GART */ RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR) + RADEON_SCRATCH_REG_OFFSET); dev_priv->scratch = ((__volatile__ u32 *) dev_priv->ring_rptr->handle + (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); /* Writeback doesn't seem to work everywhere, test it first */ DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == 0xdeadbeef) break; DRM_UDELAY(1); } if (tmp < dev_priv->usec_timeout) { dev_priv->writeback_works = 1; DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp); } else { dev_priv->writeback_works = 0; DRM_DEBUG("writeback test failed\n"); } + if (radeon_no_wb == 1) { + dev_priv->writeback_works = 0; + DRM_DEBUG("writeback forced off\n"); + } dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0; RADEON_WRITE(RADEON_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch); dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); /* Set ring buffer size */ #ifdef __BIG_ENDIAN RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); #else RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); #endif radeon_do_wait_for_idle(dev_priv); /* Turn on bus mastering */ tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; RADEON_WRITE(RADEON_BUS_CNTL, tmp); /* Sync everything up */ RADEON_WRITE(RADEON_ISYNC_CNTL, (RADEON_ISYNC_ANY2D_IDLE3D | RADEON_ISYNC_ANY3D_IDLE2D | RADEON_ISYNC_WAIT_IDLEGUI | RADEON_ISYNC_CPSCRATCH_IDLEGUI)); } /* Enable or disable PCI-E GART on the chip */ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) { u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); if (on) { - DRM_DEBUG("programming pcie %08X %08lX %08X\n", dev_priv->gart_vm_start, dev_priv->bus_pci_gart,dev_priv->gart_size); + DRM_DEBUG("programming pcie %08X %08lX %08X\n", + dev_priv->gart_vm_start, (long)dev_priv->gart_info.bus_addr, + dev_priv->gart_size); RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, dev_priv->gart_vm_start); - RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, dev_priv->bus_pci_gart); + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, dev_priv->gart_info.bus_addr); RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO, dev_priv->gart_vm_start); RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO, dev_priv->gart_vm_start + dev_priv->gart_size - 1); RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0); /* ?? */ - RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, RADEON_PCIE_TX_GART_EN | RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD | RADEON_PCIE_TX_GART_CHK_RW_VALID_EN); + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, RADEON_PCIE_TX_GART_EN); } else { - RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, (tmp & ~RADEON_PCIE_TX_GART_EN) | RADEON_PCIE_TX_GART_INVALIDATE_TLB); } } /* Enable or disable PCI GART on the chip */ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) { - u32 tmp = RADEON_READ(RADEON_AIC_CNTL); + u32 tmp; if (dev_priv->flags & CHIP_IS_PCIE) { radeon_set_pciegart(dev_priv, on); return; } + tmp = RADEON_READ(RADEON_AIC_CNTL); + if (on) { RADEON_WRITE(RADEON_AIC_CNTL, tmp | RADEON_PCIGART_TRANSLATE_EN); /* set PCI GART page-table base address */ - RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart); + RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr); /* set address range for PCI address translate */ RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start); RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start + dev_priv->gart_size - 1); /* Turn off AGP aperture -- is this required for PCI GART? */ RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0); /* ?? */ RADEON_WRITE(RADEON_AGP_COMMAND, 0); /* clear AGP_COMMAND */ } else { RADEON_WRITE(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN); } } static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) { drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); + if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) + { + DRM_DEBUG("Forcing AGP card to PCI mode\n"); + dev_priv->flags &= ~CHIP_IS_AGP; + } + if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) { DRM_ERROR("PCI GART memory not allocated!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } dev_priv->usec_timeout = init->usec_timeout; if (dev_priv->usec_timeout < 1 || dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { DRM_DEBUG("TIMEOUT problem!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } switch(init->func) { case RADEON_INIT_R200_CP: dev_priv->microcode_version=UCODE_R200; break; case RADEON_INIT_R300_CP: dev_priv->microcode_version=UCODE_R300; break; default: dev_priv->microcode_version=UCODE_R100; break; } dev_priv->do_boxes = 0; dev_priv->cp_mode = init->cp_mode; /* We don't support anything other than bus-mastering ring mode, * but the ring can be in either AGP or PCI space for the ring * read pointer. */ if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } switch (init->fb_bpp) { case 16: dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565; break; case 32: default: dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; break; } dev_priv->front_offset = init->front_offset; dev_priv->front_pitch = init->front_pitch; dev_priv->back_offset = init->back_offset; dev_priv->back_pitch = init->back_pitch; switch (init->depth_bpp) { case 16: dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; break; case 32: default: dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; break; } dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; /* Hardware state for depth clears. Remove this if/when we no * longer clear the depth buffer with a 3D rectangle. Hard-code * all values to prevent unwanted 3D state from slipping through * and screwing with the clear operation. */ dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | (dev_priv->color_fmt << 10) | (dev_priv->microcode_version == UCODE_R100 ? RADEON_ZBLOCK16 : 0)); dev_priv->depth_clear.rb3d_zstencilcntl = (dev_priv->depth_fmt | RADEON_Z_TEST_ALWAYS | RADEON_STENCIL_TEST_ALWAYS | RADEON_STENCIL_S_FAIL_REPLACE | RADEON_STENCIL_ZPASS_REPLACE | RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE); dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW | RADEON_BFACE_SOLID | RADEON_FFACE_SOLID | RADEON_FLAT_SHADE_VTX_LAST | RADEON_DIFFUSE_SHADE_FLAT | RADEON_ALPHA_SHADE_FLAT | RADEON_SPECULAR_SHADE_FLAT | RADEON_FOG_SHADE_FLAT | RADEON_VTX_PIX_CENTER_OGL | RADEON_ROUND_MODE_TRUNC | RADEON_ROUND_PREC_8TH_PIX); DRM_GETSAREA(); - dev_priv->fb_offset = init->fb_offset; - dev_priv->mmio_offset = init->mmio_offset; dev_priv->ring_offset = init->ring_offset; dev_priv->ring_rptr_offset = init->ring_rptr_offset; dev_priv->buffers_offset = init->buffers_offset; dev_priv->gart_textures_offset = init->gart_textures_offset; if (!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } - dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); - if (!dev_priv->mmio) { - DRM_ERROR("could not find mmio region!\n"); - radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); - } dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); if (!dev_priv->cp_ring) { DRM_ERROR("could not find cp ring region!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); if (!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("could not find dma buffer region!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } if (init->gart_textures_offset) { dev_priv->gart_textures = drm_core_findmap(dev, init->gart_textures_offset); if (!dev_priv->gart_textures) { DRM_ERROR("could not find GART texture region!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } } dev_priv->sarea_priv = (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { drm_core_ioremap(dev_priv->cp_ring, dev); drm_core_ioremap(dev_priv->ring_rptr, dev); drm_core_ioremap(dev->agp_buffer_map, dev); if (!dev_priv->cp_ring->handle || !dev_priv->ring_rptr->handle || !dev->agp_buffer_map->handle) { DRM_ERROR("could not find ioremap agp regions!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } } else #endif { dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset; dev_priv->ring_rptr->handle = (void *)dev_priv->ring_rptr->offset; dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset; DRM_DEBUG("dev_priv->cp_ring->handle %p\n", dev_priv->cp_ring->handle); DRM_DEBUG("dev_priv->ring_rptr->handle %p\n", dev_priv->ring_rptr->handle); DRM_DEBUG("dev->agp_buffer_map->handle %p\n", dev->agp_buffer_map->handle); } dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff) << 16; dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | ((dev_priv->front_offset + dev_priv->fb_location) >> 10)); dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) | ((dev_priv->back_offset + dev_priv->fb_location) >> 10)); dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) | ((dev_priv->depth_offset + dev_priv->fb_location) >> 10)); dev_priv->gart_size = init->gart_size; dev_priv->gart_vm_start = dev_priv->fb_location + RADEON_READ(RADEON_CONFIG_APER_SIZE); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - dev->agp->base + dev_priv->gart_vm_start); else #endif dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - - dev->sg->handle + - (unsigned long)dev->sg->virtual + dev_priv->gart_vm_start); DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size); DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start); DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n", dev_priv->gart_buffers_offset); dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle; dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle + init->ring_size / sizeof(u32)); dev_priv->ring.size = init->ring_size; dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { /* Turn off PCI GART */ radeon_set_pcigart(dev_priv, 0); } else #endif { - if (!drm_ati_pcigart_init(dev, &dev_priv->phys_pci_gart, - &dev_priv->bus_pci_gart, (dev_priv->flags & CHIP_IS_PCIE))) { + /* if we have an offset set from userspace */ + if (dev_priv->pcigart_offset) { + dev_priv->gart_info.bus_addr = dev_priv->pcigart_offset + dev_priv->fb_location; + dev_priv->gart_info.mapping.offset = dev_priv->gart_info.bus_addr; + dev_priv->gart_info.mapping.size = RADEON_PCIGART_TABLE_SIZE; + drm_core_ioremap(&dev_priv->gart_info.mapping, dev); + dev_priv->gart_info.addr = dev_priv->gart_info.mapping.handle; + + dev_priv->gart_info.is_pcie = !!(dev_priv->flags & CHIP_IS_PCIE); + dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB; + + DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", dev_priv->gart_info.addr, dev_priv->pcigart_offset); + } + else { + dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + dev_priv->gart_info.addr = NULL; + dev_priv->gart_info.bus_addr = 0; + if (dev_priv->flags & CHIP_IS_PCIE) + { + DRM_ERROR("Cannot use PCI Express without GART in FB memory\n"); + radeon_do_cleanup_cp(dev); + return DRM_ERR(EINVAL); + } + } + + if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { DRM_ERROR("failed to init PCI GART!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(ENOMEM); } /* Turn on PCI GART */ radeon_set_pcigart(dev_priv, 1); } radeon_cp_load_microcode(dev_priv); radeon_cp_init_ring_buffer(dev, dev_priv); dev_priv->last_buf = 0; radeon_do_engine_reset(dev); return 0; } static int radeon_do_cleanup_cp(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if (dev->irq_enabled) drm_irq_uninstall(dev); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { if (dev_priv->cp_ring != NULL) { drm_core_ioremapfree(dev_priv->cp_ring, dev); dev_priv->cp_ring = NULL; } if (dev_priv->ring_rptr != NULL) { drm_core_ioremapfree(dev_priv->ring_rptr, dev); dev_priv->ring_rptr = NULL; } if (dev->agp_buffer_map != NULL) { drm_core_ioremapfree(dev->agp_buffer_map, dev); dev->agp_buffer_map = NULL; } } else #endif { - if (!drm_ati_pcigart_cleanup(dev, - dev_priv->phys_pci_gart, - dev_priv->bus_pci_gart)) - DRM_ERROR("failed to cleanup PCI GART!\n"); + + if (dev_priv->gart_info.bus_addr) { + /* Turn off PCI GART */ + radeon_set_pcigart(dev_priv, 0); + if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) + DRM_ERROR("failed to cleanup PCI GART!\n"); + } + + if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) + { + drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); + dev_priv->gart_info.addr = 0; + } } /* only clear to the start of flags */ memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); return 0; } /* This code will reinit the Radeon CP hardware after a resume from disc. * AFAIK, it would be very difficult to pickle the state at suspend time, so * here we make sure that all Radeon hardware initialisation is re-done without * affecting running applications. * * Charl P. Botha */ static int radeon_do_resume_cp(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; if (!dev_priv) { DRM_ERROR("Called with no initialization\n"); return DRM_ERR(EINVAL); } DRM_DEBUG("Starting radeon_do_resume_cp()\n"); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { /* Turn off PCI GART */ radeon_set_pcigart(dev_priv, 0); } else #endif { /* Turn on PCI GART */ radeon_set_pcigart(dev_priv, 1); } radeon_cp_load_microcode(dev_priv); radeon_cp_init_ring_buffer(dev, dev_priv); radeon_do_engine_reset(dev); DRM_DEBUG("radeon_do_resume_cp() complete\n"); return 0; } int radeon_cp_init(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_init_t init; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(init, (drm_radeon_init_t __user *) data, sizeof(init)); if(init.func == RADEON_INIT_R300_CP) r300_init_reg_flags(); switch (init.func) { case RADEON_INIT_CP: case RADEON_INIT_R200_CP: case RADEON_INIT_R300_CP: return radeon_do_init_cp(dev, &init); case RADEON_CLEANUP_CP: return radeon_do_cleanup_cp(dev); } return DRM_ERR(EINVAL); } int radeon_cp_start(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); if (dev_priv->cp_running) { DRM_DEBUG("%s while CP running\n", __FUNCTION__); return 0; } if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) { DRM_DEBUG("%s called with bogus CP mode (%d)\n", __FUNCTION__, dev_priv->cp_mode); return 0; } radeon_do_cp_start(dev_priv); return 0; } /* Stop the CP. The engine must have been idled before calling this * routine. */ int radeon_cp_stop(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_cp_stop_t stop; int ret; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(stop, (drm_radeon_cp_stop_t __user *) data, sizeof(stop)); if (!dev_priv->cp_running) return 0; /* Flush any pending CP commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ if (stop.flush) { radeon_do_cp_flush(dev_priv); } /* If we fail to make the engine go idle, we return an error * code so that the DRM ioctl wrapper can try again. */ if (stop.idle) { ret = radeon_do_cp_idle(dev_priv); if (ret) return ret; } /* Finally, we can turn off the CP. If the engine isn't idle, * we will get some dropped triangles as they won't be fully * rendered before the CP is shut down. */ radeon_do_cp_stop(dev_priv); /* Reset the engine */ radeon_do_engine_reset(dev); return 0; } void radeon_do_release(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; int i, ret; if (dev_priv) { if (dev_priv->cp_running) { /* Stop the cp */ while ((ret = radeon_do_cp_idle(dev_priv)) != 0) { DRM_DEBUG("radeon_do_cp_idle %d\n", ret); #ifdef __linux__ schedule(); #else +#if defined(__FreeBSD__) && __FreeBSD_version > 500000 + msleep(&ret, &dev->dev_lock, PZERO, "rdnrel", + 1); +#else tsleep(&ret, PZERO, "rdnrel", 1); #endif +#endif } radeon_do_cp_stop(dev_priv); radeon_do_engine_reset(dev); } /* Disable *all* interrupts */ if (dev_priv->mmio) /* remove this after permanent addmaps */ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); if (dev_priv->mmio) {/* remove all surfaces */ for (i = 0; i < RADEON_MAX_SURFACES; i++) { RADEON_WRITE(RADEON_SURFACE0_INFO + 16*i, 0); RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*i, 0); RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*i, 0); } } /* Free memory heap structures */ radeon_mem_takedown(&(dev_priv->gart_heap)); radeon_mem_takedown(&(dev_priv->fb_heap)); /* deallocate kernel resources */ radeon_do_cleanup_cp(dev); } } /* Just reset the CP ring. Called as part of an X Server engine reset. */ int radeon_cp_reset(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_DEBUG("%s called before init done\n", __FUNCTION__); return DRM_ERR(EINVAL); } radeon_do_cp_reset(dev_priv); /* The CP is no longer running after an engine reset */ dev_priv->cp_running = 0; return 0; } int radeon_cp_idle(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); return radeon_do_cp_idle(dev_priv); } /* Added by Charl P. Botha to call radeon_do_resume_cp(). */ int radeon_cp_resume(DRM_IOCTL_ARGS) { DRM_DEVICE; return radeon_do_resume_cp(dev); } int radeon_engine_reset(DRM_IOCTL_ARGS) { DRM_DEVICE; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); return radeon_do_engine_reset(dev); } /* ================================================================ * Fullscreen mode */ /* KW: Deprecated to say the least: */ int radeon_fullscreen(DRM_IOCTL_ARGS) { return 0; } /* ================================================================ * Freelist management */ /* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through * bufs until freelist code is used. Note this hides a problem with * the scratch register * (used to keep track of last buffer * completed) being written to before * the last buffer has actually * completed rendering. * * KW: It's also a good way to find free buffers quickly. * * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't * sleep. However, bugs in older versions of radeon_accel.c mean that * we essentially have to do this, else old clients will break. * * However, it does leave open a potential deadlock where all the * buffers are held by other clients, which can't release them because * they can't get the lock. */ drm_buf_t *radeon_freelist_get(drm_device_t * dev) { drm_device_dma_t *dma = dev->dma; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv; drm_buf_t *buf; int i, t; int start; if (++dev_priv->last_buf >= dma->buf_count) dev_priv->last_buf = 0; start = dev_priv->last_buf; for (t = 0; t < dev_priv->usec_timeout; t++) { u32 done_age = GET_SCRATCH(1); DRM_DEBUG("done_age = %d\n", done_age); for (i = start; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if (buf->filp == 0 || (buf->pending && buf_priv->age <= done_age)) { dev_priv->stats.requested_bufs++; buf->pending = 0; return buf; } start = 0; } if (t) { DRM_UDELAY(1); dev_priv->stats.freelist_loops++; } } DRM_DEBUG("returning NULL!\n"); return NULL; } #if 0 drm_buf_t *radeon_freelist_get(drm_device_t * dev) { drm_device_dma_t *dma = dev->dma; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv; drm_buf_t *buf; int i, t; int start; u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)); if (++dev_priv->last_buf >= dma->buf_count) dev_priv->last_buf = 0; start = dev_priv->last_buf; dev_priv->stats.freelist_loops++; for (t = 0; t < 2; t++) { for (i = start; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if (buf->filp == 0 || (buf->pending && buf_priv->age <= done_age)) { dev_priv->stats.requested_bufs++; buf->pending = 0; return buf; } } start = 0; } return NULL; } #endif void radeon_freelist_reset(drm_device_t * dev) { drm_device_dma_t *dma = dev->dma; drm_radeon_private_t *dev_priv = dev->dev_private; int i; dev_priv->last_buf = 0; for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[i]; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; buf_priv->age = 0; } } /* ================================================================ * CP command submission */ int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n) { drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; u32 last_head = GET_RING_HEAD(dev_priv); for (i = 0; i < dev_priv->usec_timeout; i++) { u32 head = GET_RING_HEAD(dev_priv); ring->space = (head - ring->tail) * sizeof(u32); if (ring->space <= 0) ring->space += ring->size; if (ring->space > n) return 0; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; if (head != last_head) i = 0; last_head = head; DRM_UDELAY(1); } /* FIXME: This return value is ignored in the BEGIN_RING macro! */ #if RADEON_FIFO_DEBUG radeon_status(dev_priv); DRM_ERROR("failed!\n"); #endif return DRM_ERR(EBUSY); } static int radeon_cp_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d) { int i; drm_buf_t *buf; for (i = d->granted_count; i < d->request_count; i++) { buf = radeon_freelist_get(dev); if (!buf) return DRM_ERR(EBUSY); /* NOTE: broken client */ buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return DRM_ERR(EFAULT); d->granted_count++; } return 0; } int radeon_cp_buffers(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; int ret = 0; drm_dma_t __user *argp = (void __user *)data; drm_dma_t d; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); /* Please don't send us buffers. */ if (d.send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", DRM_CURRENTPID, d.send_count); return DRM_ERR(EINVAL); } /* We'll send you buffers. */ if (d.request_count < 0 || d.request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", DRM_CURRENTPID, d.request_count, dma->buf_count); return DRM_ERR(EINVAL); } d.granted_count = 0; if (d.request_count) { ret = radeon_cp_get_buffers(filp, dev, &d); } DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); return ret; } -/* Always create a map record for MMIO and FB memory, done from DRIVER_POSTINIT */ -int radeon_preinit(struct drm_device *dev, unsigned long flags) +int radeon_driver_load(struct drm_device *dev, unsigned long flags) { drm_radeon_private_t *dev_priv; int ret = 0; dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return DRM_ERR(ENOMEM); memset(dev_priv, 0, sizeof(drm_radeon_private_t)); dev->dev_private = (void *)dev_priv; dev_priv->flags = flags; switch (flags & CHIP_FAMILY_MASK) { case CHIP_R100: case CHIP_RV200: case CHIP_R200: case CHIP_R300: case CHIP_R420: dev_priv->flags |= CHIP_HAS_HIERZ; break; default: /* all other chips have no hierarchical z buffer */ break; } - /* Disable initmaps because it is broken on FreeBSD, and results in - * crashes on startup for some. The proper fix will involve being - * smarter about allocating PCI resources. - */ - /* - ret = drm_initmap(dev, drm_get_resource_start(dev, 2), - drm_get_resource_len(dev, 2), 2, _DRM_REGISTERS, - _DRM_READ_ONLY); - if (ret != 0) - return ret; - - ret = drm_initmap(dev, drm_get_resource_start(dev, 0), - drm_get_resource_len(dev, 0), 0, _DRM_FRAME_BUFFER, - _DRM_WRITE_COMBINING); - if (ret != 0) - return ret; - */ - - /* The original method of detecting AGP is known to not work correctly, - * according to Mike Harris. The solution is to walk the capabilities - * list, which should be done in drm_device_is_agp(). - */ if (drm_device_is_agp(dev)) dev_priv->flags |= CHIP_IS_AGP; if (drm_device_is_pcie(dev)) dev_priv->flags |= CHIP_IS_PCIE; DRM_DEBUG("%s card detected\n", ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI")))); -#if defined(__linux__) - /* Check if we need a reset */ - if (! - (dev_priv->mmio = - drm_core_findmap(dev, pci_resource_start(dev->pdev, 2)))) - return DRM_ERR(ENOMEM); - - ret = radeon_create_i2c_busses(dev); -#endif return ret; } -int radeon_postcleanup(struct drm_device *dev) +/* Create mappings for registers and framebuffer so userland doesn't necessarily + * have to find them. + */ +int radeon_driver_firstopen(struct drm_device *dev) { + int ret; + drm_local_map_t *map; drm_radeon_private_t *dev_priv = dev->dev_private; + ret = drm_addmap(dev, drm_get_resource_start(dev, 2), + drm_get_resource_len(dev, 2), _DRM_REGISTERS, + _DRM_READ_ONLY, &dev_priv->mmio); + if (ret != 0) + return ret; + + ret = drm_addmap(dev, drm_get_resource_start(dev, 0), + drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, + _DRM_WRITE_COMBINING, &map); + if (ret != 0) + return ret; + + return 0; +} + +int radeon_driver_unload(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("\n"); -#if defined(__linux__) - radeon_delete_i2c_busses(dev); -#endif drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); dev->dev_private = NULL; return 0; } Index: head/sys/dev/drm/radeon_drm.h =================================================================== --- head/sys/dev/drm/radeon_drm.h (revision 152908) +++ head/sys/dev/drm/radeon_drm.h (revision 152909) @@ -1,700 +1,711 @@ -/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*- */ -/*- +/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*- + * * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Fremont, California. * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Kevin E. Martin * Gareth Hughes * Keith Whitwell - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef __RADEON_DRM_H__ #define __RADEON_DRM_H__ /* WARNING: If you change any of these defines, make sure to change the * defines in the X server file (radeon_sarea.h) */ #ifndef __RADEON_SAREA_DEFINES__ #define __RADEON_SAREA_DEFINES__ /* Old style state flags, required for sarea interface (1.1 and 1.2 * clears) and 1.2 drm_vertex2 ioctl. */ #define RADEON_UPLOAD_CONTEXT 0x00000001 #define RADEON_UPLOAD_VERTFMT 0x00000002 #define RADEON_UPLOAD_LINE 0x00000004 #define RADEON_UPLOAD_BUMPMAP 0x00000008 #define RADEON_UPLOAD_MASKS 0x00000010 #define RADEON_UPLOAD_VIEWPORT 0x00000020 #define RADEON_UPLOAD_SETUP 0x00000040 #define RADEON_UPLOAD_TCL 0x00000080 #define RADEON_UPLOAD_MISC 0x00000100 #define RADEON_UPLOAD_TEX0 0x00000200 #define RADEON_UPLOAD_TEX1 0x00000400 #define RADEON_UPLOAD_TEX2 0x00000800 #define RADEON_UPLOAD_TEX0IMAGES 0x00001000 #define RADEON_UPLOAD_TEX1IMAGES 0x00002000 #define RADEON_UPLOAD_TEX2IMAGES 0x00004000 #define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */ #define RADEON_REQUIRE_QUIESCENCE 0x00010000 #define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */ #define RADEON_UPLOAD_ALL 0x003effff #define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff /* New style per-packet identifiers for use in cmd_buffer ioctl with * the RADEON_EMIT_PACKET command. Comments relate new packets to old * state bits and the packet size: */ #define RADEON_EMIT_PP_MISC 0 /* context/7 */ #define RADEON_EMIT_PP_CNTL 1 /* context/3 */ #define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */ #define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */ #define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */ #define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */ #define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */ #define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */ #define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */ #define RADEON_EMIT_SE_CNTL 9 /* setup/2 */ #define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */ #define RADEON_EMIT_RE_MISC 11 /* misc/1 */ #define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */ #define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */ #define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */ #define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */ #define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */ #define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */ #define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */ #define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */ #define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */ #define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */ #define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */ #define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */ #define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */ #define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */ #define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */ #define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */ #define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */ #define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */ #define R200_EMIT_TFACTOR_0 30 /* tf/7 */ #define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */ #define R200_EMIT_VAP_CTL 32 /* vap/1 */ #define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */ #define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */ #define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */ #define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */ #define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */ #define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */ #define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */ #define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */ #define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */ #define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */ #define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */ #define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */ #define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */ #define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */ #define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */ #define R200_EMIT_VTE_CNTL 48 /* vte/1 */ #define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */ #define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */ #define R200_EMIT_PP_CNTL_X 51 /* cst/1 */ #define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */ #define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */ #define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */ #define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */ #define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */ #define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */ #define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */ #define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */ #define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */ #define R200_EMIT_PP_CUBIC_FACES_0 61 #define R200_EMIT_PP_CUBIC_OFFSETS_0 62 #define R200_EMIT_PP_CUBIC_FACES_1 63 #define R200_EMIT_PP_CUBIC_OFFSETS_1 64 #define R200_EMIT_PP_CUBIC_FACES_2 65 #define R200_EMIT_PP_CUBIC_OFFSETS_2 66 #define R200_EMIT_PP_CUBIC_FACES_3 67 #define R200_EMIT_PP_CUBIC_OFFSETS_3 68 #define R200_EMIT_PP_CUBIC_FACES_4 69 #define R200_EMIT_PP_CUBIC_OFFSETS_4 70 #define R200_EMIT_PP_CUBIC_FACES_5 71 #define R200_EMIT_PP_CUBIC_OFFSETS_5 72 #define RADEON_EMIT_PP_TEX_SIZE_0 73 #define RADEON_EMIT_PP_TEX_SIZE_1 74 #define RADEON_EMIT_PP_TEX_SIZE_2 75 #define R200_EMIT_RB3D_BLENDCOLOR 76 #define R200_EMIT_TCL_POINT_SPRITE_CNTL 77 #define RADEON_EMIT_PP_CUBIC_FACES_0 78 #define RADEON_EMIT_PP_CUBIC_OFFSETS_T0 79 #define RADEON_EMIT_PP_CUBIC_FACES_1 80 #define RADEON_EMIT_PP_CUBIC_OFFSETS_T1 81 #define RADEON_EMIT_PP_CUBIC_FACES_2 82 #define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83 #define R200_EMIT_PP_TRI_PERF_CNTL 84 -#define RADEON_MAX_STATE_PACKETS 85 +#define R200_EMIT_PP_AFS_0 85 +#define R200_EMIT_PP_AFS_1 86 +#define R200_EMIT_ATF_TFACTOR 87 +#define R200_EMIT_PP_TXCTLALL_0 88 +#define R200_EMIT_PP_TXCTLALL_1 89 +#define R200_EMIT_PP_TXCTLALL_2 90 +#define R200_EMIT_PP_TXCTLALL_3 91 +#define R200_EMIT_PP_TXCTLALL_4 92 +#define R200_EMIT_PP_TXCTLALL_5 93 +#define RADEON_MAX_STATE_PACKETS 94 /* Commands understood by cmd_buffer ioctl. More can be added but * obviously these can't be removed or changed: */ #define RADEON_CMD_PACKET 1 /* emit one of the register packets above */ #define RADEON_CMD_SCALARS 2 /* emit scalar data */ #define RADEON_CMD_VECTORS 3 /* emit vector data */ #define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */ #define RADEON_CMD_PACKET3 5 /* emit hw packet */ #define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ #define RADEON_CMD_SCALARS2 7 /* r200 stopgap */ #define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: * doesn't make the cpu wait, just * the graphics hardware */ typedef union { int i; struct { unsigned char cmd_type, pad0, pad1, pad2; } header; struct { unsigned char cmd_type, packet_id, pad0, pad1; } packet; struct { unsigned char cmd_type, offset, stride, count; } scalars; struct { unsigned char cmd_type, offset, stride, count; } vectors; struct { unsigned char cmd_type, buf_idx, pad0, pad1; } dma; struct { unsigned char cmd_type, flags, pad0, pad1; } wait; } drm_radeon_cmd_header_t; #define RADEON_WAIT_2D 0x1 #define RADEON_WAIT_3D 0x2 /* Allowed parameters for R300_CMD_PACKET3 */ #define R300_CMD_PACKET3_CLEAR 0 #define R300_CMD_PACKET3_RAW 1 /* Commands understood by cmd_buffer ioctl for R300. * The interface has not been stabilized, so some of these may be removed * and eventually reordered before stabilization. */ #define R300_CMD_PACKET0 1 #define R300_CMD_VPU 2 /* emit vertex program upload */ #define R300_CMD_PACKET3 3 /* emit a packet3 */ #define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */ #define R300_CMD_CP_DELAY 5 #define R300_CMD_DMA_DISCARD 6 #define R300_CMD_WAIT 7 # define R300_WAIT_2D 0x1 # define R300_WAIT_3D 0x2 # define R300_WAIT_2D_CLEAN 0x3 # define R300_WAIT_3D_CLEAN 0x4 typedef union { unsigned int u; struct { unsigned char cmd_type, pad0, pad1, pad2; } header; struct { unsigned char cmd_type, count, reglo, reghi; } packet0; struct { unsigned char cmd_type, count, adrlo, adrhi; } vpu; struct { unsigned char cmd_type, packet, pad0, pad1; } packet3; struct { unsigned char cmd_type, packet; unsigned short count; /* amount of packet2 to emit */ } delay; struct { unsigned char cmd_type, buf_idx, pad0, pad1; } dma; struct { unsigned char cmd_type, flags, pad0, pad1; } wait; } drm_r300_cmd_header_t; #define RADEON_FRONT 0x1 #define RADEON_BACK 0x2 #define RADEON_DEPTH 0x4 #define RADEON_STENCIL 0x8 #define RADEON_CLEAR_FASTZ 0x80000000 #define RADEON_USE_HIERZ 0x40000000 #define RADEON_USE_COMP_ZBUF 0x20000000 /* Primitive types */ #define RADEON_POINTS 0x1 #define RADEON_LINES 0x2 #define RADEON_LINE_STRIP 0x3 #define RADEON_TRIANGLES 0x4 #define RADEON_TRIANGLE_FAN 0x5 #define RADEON_TRIANGLE_STRIP 0x6 /* Vertex/indirect buffer size */ #define RADEON_BUFFER_SIZE 65536 /* Byte offsets for indirect buffer data */ #define RADEON_INDEX_PRIM_OFFSET 20 #define RADEON_SCRATCH_REG_OFFSET 32 #define RADEON_NR_SAREA_CLIPRECTS 12 /* There are 2 heaps (local/GART). Each region within a heap is a * minimum of 64k, and there are at most 64 of them per heap. */ #define RADEON_LOCAL_TEX_HEAP 0 #define RADEON_GART_TEX_HEAP 1 #define RADEON_NR_TEX_HEAPS 2 #define RADEON_NR_TEX_REGIONS 64 #define RADEON_LOG_TEX_GRANULARITY 16 #define RADEON_MAX_TEXTURE_LEVELS 12 #define RADEON_MAX_TEXTURE_UNITS 3 #define RADEON_MAX_SURFACES 8 /* Blits have strict offset rules. All blit offset must be aligned on * a 1K-byte boundary. */ #define RADEON_OFFSET_SHIFT 10 #define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT) #define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1) #endif /* __RADEON_SAREA_DEFINES__ */ typedef struct { unsigned int red; unsigned int green; unsigned int blue; unsigned int alpha; } radeon_color_regs_t; typedef struct { /* Context state */ unsigned int pp_misc; /* 0x1c14 */ unsigned int pp_fog_color; unsigned int re_solid_color; unsigned int rb3d_blendcntl; unsigned int rb3d_depthoffset; unsigned int rb3d_depthpitch; unsigned int rb3d_zstencilcntl; unsigned int pp_cntl; /* 0x1c38 */ unsigned int rb3d_cntl; unsigned int rb3d_coloroffset; unsigned int re_width_height; unsigned int rb3d_colorpitch; unsigned int se_cntl; /* Vertex format state */ unsigned int se_coord_fmt; /* 0x1c50 */ /* Line state */ unsigned int re_line_pattern; /* 0x1cd0 */ unsigned int re_line_state; unsigned int se_line_width; /* 0x1db8 */ /* Bumpmap state */ unsigned int pp_lum_matrix; /* 0x1d00 */ unsigned int pp_rot_matrix_0; /* 0x1d58 */ unsigned int pp_rot_matrix_1; /* Mask state */ unsigned int rb3d_stencilrefmask; /* 0x1d7c */ unsigned int rb3d_ropcntl; unsigned int rb3d_planemask; /* Viewport state */ unsigned int se_vport_xscale; /* 0x1d98 */ unsigned int se_vport_xoffset; unsigned int se_vport_yscale; unsigned int se_vport_yoffset; unsigned int se_vport_zscale; unsigned int se_vport_zoffset; /* Setup state */ unsigned int se_cntl_status; /* 0x2140 */ /* Misc state */ unsigned int re_top_left; /* 0x26c0 */ unsigned int re_misc; } drm_radeon_context_regs_t; typedef struct { /* Zbias state */ unsigned int se_zbias_factor; /* 0x1dac */ unsigned int se_zbias_constant; } drm_radeon_context2_regs_t; /* Setup registers for each texture unit */ typedef struct { unsigned int pp_txfilter; unsigned int pp_txformat; unsigned int pp_txoffset; unsigned int pp_txcblend; unsigned int pp_txablend; unsigned int pp_tfactor; unsigned int pp_border_color; } drm_radeon_texture_regs_t; typedef struct { unsigned int start; unsigned int finish; unsigned int prim:8; unsigned int stateidx:8; unsigned int numverts:16; /* overloaded as offset/64 for elt prims */ unsigned int vc_format; /* vertex format */ } drm_radeon_prim_t; typedef struct { drm_radeon_context_regs_t context; drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS]; drm_radeon_context2_regs_t context2; unsigned int dirty; } drm_radeon_state_t; typedef struct { /* The channel for communication of state information to the * kernel on firing a vertex buffer with either of the * obsoleted vertex/index ioctls. */ drm_radeon_context_regs_t context_state; drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS]; unsigned int dirty; unsigned int vertsize; unsigned int vc_format; /* The current cliprects, or a subset thereof. */ drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS]; unsigned int nbox; /* Counters for client-side throttling of rendering clients. */ unsigned int last_frame; unsigned int last_dispatch; unsigned int last_clear; drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS + 1]; unsigned int tex_age[RADEON_NR_TEX_HEAPS]; int ctx_owner; int pfState; /* number of 3d windows (0,1,2ormore) */ int pfCurrentPage; /* which buffer is being displayed? */ int crtc2_base; /* CRTC2 frame offset */ int tiling_enabled; /* set by drm, read by 2d + 3d clients */ } drm_radeon_sarea_t; /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (xf86drmRadeon.h) * * KW: actually it's illegal to change any of this (backwards compatibility). */ /* Radeon specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ #define DRM_RADEON_CP_INIT 0x00 #define DRM_RADEON_CP_START 0x01 #define DRM_RADEON_CP_STOP 0x02 #define DRM_RADEON_CP_RESET 0x03 #define DRM_RADEON_CP_IDLE 0x04 #define DRM_RADEON_RESET 0x05 #define DRM_RADEON_FULLSCREEN 0x06 #define DRM_RADEON_SWAP 0x07 #define DRM_RADEON_CLEAR 0x08 #define DRM_RADEON_VERTEX 0x09 #define DRM_RADEON_INDICES 0x0A #define DRM_RADEON_NOT_USED #define DRM_RADEON_STIPPLE 0x0C #define DRM_RADEON_INDIRECT 0x0D #define DRM_RADEON_TEXTURE 0x0E #define DRM_RADEON_VERTEX2 0x0F #define DRM_RADEON_CMDBUF 0x10 #define DRM_RADEON_GETPARAM 0x11 #define DRM_RADEON_FLIP 0x12 #define DRM_RADEON_ALLOC 0x13 #define DRM_RADEON_FREE 0x14 #define DRM_RADEON_INIT_HEAP 0x15 #define DRM_RADEON_IRQ_EMIT 0x16 #define DRM_RADEON_IRQ_WAIT 0x17 #define DRM_RADEON_CP_RESUME 0x18 #define DRM_RADEON_SETPARAM 0x19 #define DRM_RADEON_SURF_ALLOC 0x1a #define DRM_RADEON_SURF_FREE 0x1b #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) #define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t) #define DRM_IOCTL_RADEON_CP_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESET) #define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE) #define DRM_IOCTL_RADEON_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_RESET) #define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t) #define DRM_IOCTL_RADEON_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_SWAP) #define DRM_IOCTL_RADEON_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t) #define DRM_IOCTL_RADEON_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t) #define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t) #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t) #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t) #define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t) #define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t) #define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t) #define DRM_IOCTL_RADEON_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_FLIP) #define DRM_IOCTL_RADEON_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t) #define DRM_IOCTL_RADEON_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t) #define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t) #define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t) #define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t) #define DRM_IOCTL_RADEON_CP_RESUME DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME) #define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) #define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) #define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) typedef struct drm_radeon_init { enum { RADEON_INIT_CP = 0x01, RADEON_CLEANUP_CP = 0x02, RADEON_INIT_R200_CP = 0x03, RADEON_INIT_R300_CP = 0x04 } func; unsigned long sarea_priv_offset; - int is_pci; /* not used, driver asks hardware */ + int is_pci; /* for overriding only */ int cp_mode; int gart_size; int ring_size; int usec_timeout; unsigned int fb_bpp; unsigned int front_offset, front_pitch; unsigned int back_offset, back_pitch; unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; - unsigned long fb_offset; - unsigned long mmio_offset; + unsigned long fb_offset DEPRECATED; /* deprecated, driver asks hardware */ + unsigned long mmio_offset DEPRECATED; /* deprecated, driver asks hardware */ unsigned long ring_offset; unsigned long ring_rptr_offset; unsigned long buffers_offset; unsigned long gart_textures_offset; } drm_radeon_init_t; typedef struct drm_radeon_cp_stop { int flush; int idle; } drm_radeon_cp_stop_t; typedef struct drm_radeon_fullscreen { enum { RADEON_INIT_FULLSCREEN = 0x01, RADEON_CLEANUP_FULLSCREEN = 0x02 } func; } drm_radeon_fullscreen_t; #define CLEAR_X1 0 #define CLEAR_Y1 1 #define CLEAR_X2 2 #define CLEAR_Y2 3 #define CLEAR_DEPTH 4 typedef union drm_radeon_clear_rect { float f[5]; unsigned int ui[5]; } drm_radeon_clear_rect_t; typedef struct drm_radeon_clear { unsigned int flags; unsigned int clear_color; unsigned int clear_depth; unsigned int color_mask; unsigned int depth_mask; /* misnamed field: should be stencil */ drm_radeon_clear_rect_t __user *depth_boxes; } drm_radeon_clear_t; typedef struct drm_radeon_vertex { int prim; int idx; /* Index of vertex buffer */ int count; /* Number of vertices in buffer */ int discard; /* Client finished with buffer? */ } drm_radeon_vertex_t; typedef struct drm_radeon_indices { int prim; int idx; int start; int end; int discard; /* Client finished with buffer? */ } drm_radeon_indices_t; /* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices * - allows multiple primitives and state changes in a single ioctl * - supports driver change to emit native primitives */ typedef struct drm_radeon_vertex2 { int idx; /* Index of vertex buffer */ int discard; /* Client finished with buffer? */ int nr_states; drm_radeon_state_t __user *state; int nr_prims; drm_radeon_prim_t __user *prim; } drm_radeon_vertex2_t; /* v1.3 - obsoletes drm_radeon_vertex2 * - allows arbitarily large cliprect list * - allows updating of tcl packet, vector and scalar state * - allows memory-efficient description of state updates * - allows state to be emitted without a primitive * (for clears, ctx switches) * - allows more than one dma buffer to be referenced per ioctl * - supports tcl driver * - may be extended in future versions with new cmd types, packets */ typedef struct drm_radeon_cmd_buffer { int bufsz; char __user *buf; int nbox; drm_clip_rect_t __user *boxes; } drm_radeon_cmd_buffer_t; typedef struct drm_radeon_tex_image { unsigned int x, y; /* Blit coordinates */ unsigned int width, height; const void __user *data; } drm_radeon_tex_image_t; typedef struct drm_radeon_texture { unsigned int offset; int pitch; int format; int width; /* Texture image coordinates */ int height; drm_radeon_tex_image_t __user *image; } drm_radeon_texture_t; typedef struct drm_radeon_stipple { unsigned int __user *mask; } drm_radeon_stipple_t; typedef struct drm_radeon_indirect { int idx; int start; int end; int discard; } drm_radeon_indirect_t; /* 1.3: An ioctl to get parameters that aren't available to the 3d * client any other way. */ #define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */ #define RADEON_PARAM_LAST_FRAME 2 #define RADEON_PARAM_LAST_DISPATCH 3 #define RADEON_PARAM_LAST_CLEAR 4 /* Added with DRM version 1.6. */ #define RADEON_PARAM_IRQ_NR 5 #define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */ /* Added with DRM version 1.8. */ #define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */ #define RADEON_PARAM_STATUS_HANDLE 8 #define RADEON_PARAM_SAREA_HANDLE 9 #define RADEON_PARAM_GART_TEX_HANDLE 10 #define RADEON_PARAM_SCRATCH_OFFSET 11 typedef struct drm_radeon_getparam { int param; void __user *value; } drm_radeon_getparam_t; /* 1.6: Set up a memory manager for regions of shared memory: */ #define RADEON_MEM_REGION_GART 1 #define RADEON_MEM_REGION_FB 2 typedef struct drm_radeon_mem_alloc { int region; int alignment; int size; int __user *region_offset; /* offset from start of fb or GART */ } drm_radeon_mem_alloc_t; typedef struct drm_radeon_mem_free { int region; int region_offset; } drm_radeon_mem_free_t; typedef struct drm_radeon_mem_init_heap { int region; int size; int start; } drm_radeon_mem_init_heap_t; /* 1.6: Userspace can request & wait on irq's: */ typedef struct drm_radeon_irq_emit { int __user *irq_seq; } drm_radeon_irq_emit_t; typedef struct drm_radeon_irq_wait { int irq_seq; } drm_radeon_irq_wait_t; /* 1.10: Clients tell the DRM where they think the framebuffer is located in * the card's address space, via a new generic ioctl to set parameters */ typedef struct drm_radeon_setparam { unsigned int param; int64_t value; } drm_radeon_setparam_t; #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ +#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ /* 1.14: Clients can allocate/free a surface */ typedef struct drm_radeon_surface_alloc { unsigned int address; unsigned int size; unsigned int flags; } drm_radeon_surface_alloc_t; typedef struct drm_radeon_surface_free { unsigned int address; } drm_radeon_surface_free_t; #endif Index: head/sys/dev/drm/radeon_drv.c =================================================================== --- head/sys/dev/drm/radeon_drv.c (revision 152908) +++ head/sys/dev/drm/radeon_drv.c (revision 152909) @@ -1,120 +1,127 @@ /* radeon_drv.c -- ATI Radeon driver -*- linux-c -*- * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com */ /*- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" #include "dev/drm/drm_pciids.h" +int radeon_no_wb; + /* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */ static drm_pci_id_list_t radeon_pciidlist[] = { radeon_PCI_IDS }; -extern drm_ioctl_desc_t radeon_ioctls[]; -extern int radeon_max_ioctl; - static void radeon_configure(drm_device_t *dev) { - dev->dev_priv_size = sizeof(drm_radeon_buf_priv_t); - dev->preinit = radeon_preinit; - dev->postcleanup = radeon_postcleanup; - dev->prerelease = radeon_driver_prerelease; - dev->pretakedown = radeon_driver_pretakedown; - dev->open_helper = radeon_driver_open_helper; - dev->free_filp_priv = radeon_driver_free_filp_priv; - dev->vblank_wait = radeon_driver_vblank_wait; - dev->irq_preinstall = radeon_driver_irq_preinstall; - dev->irq_postinstall = radeon_driver_irq_postinstall; - dev->irq_uninstall = radeon_driver_irq_uninstall; - dev->irq_handler = radeon_driver_irq_handler; - dev->dma_ioctl = radeon_cp_buffers; + dev->driver.buf_priv_size = sizeof(drm_radeon_buf_priv_t); + dev->driver.load = radeon_driver_load; + dev->driver.unload = radeon_driver_unload; + dev->driver.firstopen = radeon_driver_firstopen; + dev->driver.open = radeon_driver_open; + dev->driver.preclose = radeon_driver_preclose; + dev->driver.postclose = radeon_driver_postclose; + dev->driver.lastclose = radeon_driver_lastclose; + dev->driver.vblank_wait = radeon_driver_vblank_wait; + dev->driver.irq_preinstall = radeon_driver_irq_preinstall; + dev->driver.irq_postinstall = radeon_driver_irq_postinstall; + dev->driver.irq_uninstall = radeon_driver_irq_uninstall; + dev->driver.irq_handler = radeon_driver_irq_handler; + dev->driver.dma_ioctl = radeon_cp_buffers; - dev->driver_ioctls = radeon_ioctls; - dev->max_driver_ioctl = radeon_max_ioctl; + dev->driver.ioctls = radeon_ioctls; + dev->driver.max_ioctl = radeon_max_ioctl; - dev->driver_name = DRIVER_NAME; - dev->driver_desc = DRIVER_DESC; - dev->driver_date = DRIVER_DATE; - dev->driver_major = DRIVER_MAJOR; - dev->driver_minor = DRIVER_MINOR; - dev->driver_patchlevel = DRIVER_PATCHLEVEL; + dev->driver.name = DRIVER_NAME; + dev->driver.desc = DRIVER_DESC; + dev->driver.date = DRIVER_DATE; + dev->driver.major = DRIVER_MAJOR; + dev->driver.minor = DRIVER_MINOR; + dev->driver.patchlevel = DRIVER_PATCHLEVEL; - dev->use_agp = 1; - dev->use_mtrr = 1; - dev->use_pci_dma = 1; - dev->use_sg = 1; - dev->use_dma = 1; - dev->use_irq = 1; - dev->use_vbl_irq = 1; + dev->driver.use_agp = 1; + dev->driver.use_mtrr = 1; + dev->driver.use_pci_dma = 1; + dev->driver.use_sg = 1; + dev->driver.use_dma = 1; + dev->driver.use_irq = 1; + dev->driver.use_vbl_irq = 1; } #ifdef __FreeBSD__ static int radeon_probe(device_t dev) { return drm_probe(dev, radeon_pciidlist); } static int radeon_attach(device_t nbdev) { drm_device_t *dev = device_get_softc(nbdev); bzero(dev, sizeof(drm_device_t)); radeon_configure(dev); return drm_attach(nbdev, radeon_pciidlist); } static device_method_t radeon_methods[] = { /* Device interface */ DEVMETHOD(device_probe, radeon_probe), DEVMETHOD(device_attach, radeon_attach), DEVMETHOD(device_detach, drm_detach), { 0, 0 } }; static driver_t radeon_driver = { "drm", radeon_methods, sizeof(drm_device_t) }; extern devclass_t drm_devclass; DRIVER_MODULE(radeon, pci, radeon_driver, drm_devclass, 0, 0); MODULE_DEPEND(radeon, drm, 1, 1, 1); #elif defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef _LKM CFDRIVER_DECL(radeon, DV_TTY, NULL); +#else +CFATTACH_DECL(radeon, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach, + drm_activate); +#endif #endif /* __FreeBSD__ */ Index: head/sys/dev/drm/radeon_drv.h =================================================================== --- head/sys/dev/drm/radeon_drv.h (revision 152908) +++ head/sys/dev/drm/radeon_drv.h (revision 152909) @@ -1,1098 +1,1134 @@ -/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*- */ -/*- +/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*- + * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Fremont, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Kevin E. Martin * Gareth Hughes - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef __RADEON_DRV_H__ #define __RADEON_DRV_H__ -#ifdef __linux__ -#include "radeon_i2c.h" -#endif /* __linux__ */ - /* General customization: */ #define DRIVER_AUTHOR "Gareth Hughes, Keith Whitwell, others." #define DRIVER_NAME "radeon" #define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20050311" +#define DRIVER_DATE "20050911" /* Interface history: * * 1.1 - ?? * 1.2 - Add vertex2 ioctl (keith) * - Add stencil capability to clear ioctl (gareth, keith) * - Increase MAX_TEXTURE_LEVELS (brian) * 1.3 - Add cmdbuf ioctl (keith) * - Add support for new radeon packets (keith) * - Add getparam ioctl (keith) * - Add flip-buffers ioctl, deprecate fullscreen foo (keith). * 1.4 - Add scratch registers to get_param ioctl. * 1.5 - Add r200 packets to cmdbuf ioctl * - Add r200 function to init ioctl * - Add 'scalar2' instruction to cmdbuf * 1.6 - Add static GART memory manager * Add irq handler (won't be turned on unless X server knows to) * Add irq ioctls and irq_active getparam. * Add wait command for cmdbuf ioctl * Add GART offset query for getparam * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5] * and R200_PP_CUBIC_OFFSET_F1_[0..5]. * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian) * 1.8 - Remove need to call cleanup ioctls on last client exit (keith) * Add 'GET' queries for starting additional clients on different VT's. * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl. * Add texture rectangle support for r100. * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which * clients use to tell the DRM where they think the framebuffer is * located in the card's address space * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color * and GL_EXT_blend_[func|equation]_separate on r200 * 1.12- Add R300 CP microcode support - this just loads the CP on r300 * (No 3D support yet - just microcode loading). * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters * - Add hyperz support, add hyperz flags to clear ioctl. * 1.14- Add support for color tiling * - Add R100/R200 surface allocation/free support * 1.15- Add support for texture micro tiling * - Add support for r100 cube maps * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear * texture filtering on r200 + * 1.17- Add initial support for R300 (3D). + * 1.18- Add support for GL_ATI_fragment_shader, new packets R200_EMIT_PP_AFS_0/1, + R200_EMIT_PP_TXCTLALL_0-5 (replaces R200_EMIT_PP_TXFILTER_0-5, 2 more regs) + and R200_EMIT_ATF_TFACTOR (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6) + * 1.19- Add support for gart table in FB memory and PCIE r300 */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 16 +#define DRIVER_MINOR 19 #define DRIVER_PATCHLEVEL 0 enum radeon_family { CHIP_R100, CHIP_RS100, CHIP_RV100, - CHIP_R200, CHIP_RV200, + CHIP_R200, CHIP_RS200, CHIP_R250, CHIP_RS250, CHIP_RV250, CHIP_RV280, CHIP_R300, CHIP_RS300, CHIP_R350, CHIP_RV350, CHIP_R420, CHIP_LAST, }; enum radeon_cp_microcode_version { UCODE_R100, UCODE_R200, UCODE_R300, }; /* * Chip flags */ enum radeon_chip_flags { CHIP_FAMILY_MASK = 0x0000ffffUL, CHIP_FLAGS_MASK = 0xffff0000UL, CHIP_IS_MOBILITY = 0x00010000UL, CHIP_IS_IGP = 0x00020000UL, CHIP_SINGLE_CRTC = 0x00040000UL, CHIP_IS_AGP = 0x00080000UL, CHIP_HAS_HIERZ = 0x00100000UL, CHIP_IS_PCIE = 0x00200000UL, }; #define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) typedef struct drm_radeon_freelist { unsigned int age; drm_buf_t *buf; struct drm_radeon_freelist *next; struct drm_radeon_freelist *prev; } drm_radeon_freelist_t; typedef struct drm_radeon_ring_buffer { u32 *start; u32 *end; int size; int size_l2qw; u32 tail; u32 tail_mask; int space; int high_mark; } drm_radeon_ring_buffer_t; typedef struct drm_radeon_depth_clear_t { u32 rb3d_cntl; u32 rb3d_zstencilcntl; u32 se_cntl; } drm_radeon_depth_clear_t; struct drm_radeon_driver_file_fields { int64_t radeon_fb_delta; }; struct mem_block { struct mem_block *next; struct mem_block *prev; int start; int size; DRMFILE filp; /* 0: free, -1: heap, other: real files */ }; struct radeon_surface { int refcount; u32 lower; u32 upper; u32 flags; }; struct radeon_virt_surface { int surface_index; u32 lower; u32 upper; u32 flags; DRMFILE filp; }; typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; u32 fb_location; int gart_size; u32 gart_vm_start; unsigned long gart_buffers_offset; int cp_mode; int cp_running; drm_radeon_freelist_t *head; drm_radeon_freelist_t *tail; int last_buf; volatile u32 *scratch; int writeback_works; int usec_timeout; int microcode_version; - unsigned long phys_pci_gart; - dma_addr_t bus_pci_gart; - struct { u32 boxes; int freelist_timeouts; int freelist_loops; int requested_bufs; int last_frame_reads; int last_clear_reads; int clears; int texture_uploads; } stats; int do_boxes; int page_flipping; int current_page; u32 color_fmt; unsigned int front_offset; unsigned int front_pitch; unsigned int back_offset; unsigned int back_pitch; u32 depth_fmt; unsigned int depth_offset; unsigned int depth_pitch; u32 front_pitch_offset; u32 back_pitch_offset; u32 depth_pitch_offset; drm_radeon_depth_clear_t depth_clear; - unsigned long fb_offset; - unsigned long mmio_offset; unsigned long ring_offset; unsigned long ring_rptr_offset; unsigned long buffers_offset; unsigned long gart_textures_offset; drm_local_map_t *sarea; drm_local_map_t *mmio; drm_local_map_t *cp_ring; drm_local_map_t *ring_rptr; drm_local_map_t *gart_textures; struct mem_block *gart_heap; struct mem_block *fb_heap; /* SW interrupt */ wait_queue_head_t swi_queue; atomic_t swi_emitted; struct radeon_surface surfaces[RADEON_MAX_SURFACES]; struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES]; - + + unsigned long pcigart_offset; + drm_ati_pcigart_info gart_info; /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ -#ifdef __linux__ - struct radeon_i2c_chan i2c[4]; -#endif /* __linux__ */ } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { u32 age; } drm_radeon_buf_priv_t; +extern int radeon_no_wb; +extern drm_ioctl_desc_t radeon_ioctls[]; +extern int radeon_max_ioctl; + /* radeon_cp.c */ extern int radeon_cp_init(DRM_IOCTL_ARGS); extern int radeon_cp_start(DRM_IOCTL_ARGS); extern int radeon_cp_stop(DRM_IOCTL_ARGS); extern int radeon_cp_reset(DRM_IOCTL_ARGS); extern int radeon_cp_idle(DRM_IOCTL_ARGS); extern int radeon_cp_resume(DRM_IOCTL_ARGS); extern int radeon_engine_reset(DRM_IOCTL_ARGS); extern int radeon_fullscreen(DRM_IOCTL_ARGS); extern int radeon_cp_buffers(DRM_IOCTL_ARGS); extern void radeon_freelist_reset(drm_device_t * dev); extern drm_buf_t *radeon_freelist_get(drm_device_t * dev); extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n); extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv); extern int radeon_mem_alloc(DRM_IOCTL_ARGS); extern int radeon_mem_free(DRM_IOCTL_ARGS); extern int radeon_mem_init_heap(DRM_IOCTL_ARGS); extern void radeon_mem_takedown(struct mem_block **heap); extern void radeon_mem_release(DRMFILE filp, struct mem_block *heap); /* radeon_irq.c */ extern int radeon_irq_emit(DRM_IOCTL_ARGS); extern int radeon_irq_wait(DRM_IOCTL_ARGS); extern void radeon_do_release(drm_device_t * dev); extern int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); extern void radeon_driver_irq_preinstall(drm_device_t * dev); extern void radeon_driver_irq_postinstall(drm_device_t * dev); extern void radeon_driver_irq_uninstall(drm_device_t * dev); -extern void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp); -extern void radeon_driver_pretakedown(drm_device_t * dev); -extern int radeon_driver_open_helper(drm_device_t * dev, - drm_file_t * filp_priv); -extern void radeon_driver_free_filp_priv(drm_device_t * dev, - drm_file_t * filp_priv); +extern int radeon_driver_load(struct drm_device *dev, unsigned long flags); +extern int radeon_driver_unload(struct drm_device *dev); +extern int radeon_driver_firstopen(struct drm_device *dev); +extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp); +extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp); +extern void radeon_driver_lastclose(drm_device_t * dev); +extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv); +extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); + /* r300_cmdbuf.c */ extern void r300_init_reg_flags(void); extern int r300_do_cp_cmdbuf( drm_device_t* dev, DRMFILE filp, drm_file_t* filp_priv, drm_radeon_cmd_buffer_t* cmdbuf ); /* Flags for stats.boxes */ #define RADEON_BOX_DMA_IDLE 0x1 #define RADEON_BOX_RING_FULL 0x2 #define RADEON_BOX_FLIP 0x4 #define RADEON_BOX_WAIT_IDLE 0x8 #define RADEON_BOX_TEXTURE_LOAD 0x10 /* Register definitions, register access macros and drmAddMap constants * for Radeon kernel driver. */ #define RADEON_AGP_COMMAND 0x0f60 #define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */ # define RADEON_AGP_ENABLE (1<<8) #define RADEON_AUX_SCISSOR_CNTL 0x26f0 # define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) # define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) # define RADEON_EXCLUSIVE_SCISSOR_2 (1 << 26) # define RADEON_SCISSOR_0_ENABLE (1 << 28) # define RADEON_SCISSOR_1_ENABLE (1 << 29) # define RADEON_SCISSOR_2_ENABLE (1 << 30) #define RADEON_BUS_CNTL 0x0030 # define RADEON_BUS_MASTER_DIS (1 << 6) #define RADEON_CLOCK_CNTL_DATA 0x000c # define RADEON_PLL_WR_EN (1 << 7) #define RADEON_CLOCK_CNTL_INDEX 0x0008 #define RADEON_CONFIG_APER_SIZE 0x0108 #define RADEON_CRTC_OFFSET 0x0224 #define RADEON_CRTC_OFFSET_CNTL 0x0228 # define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) #define RADEON_CRTC2_OFFSET 0x0324 #define RADEON_CRTC2_OFFSET_CNTL 0x0328 #define RADEON_PCIE_INDEX 0x0030 #define RADEON_PCIE_DATA 0x0034 #define RADEON_PCIE_TX_GART_CNTL 0x10 # define RADEON_PCIE_TX_GART_EN (1 << 0) # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0<<1) # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO (1<<1) # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD (3<<1) # define RADEON_PCIE_TX_GART_MODE_32_128_CACHE (0<<3) # define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE (1<<3) # define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN (1<<5) # define RADEON_PCIE_TX_GART_INVALIDATE_TLB (1<<8) #define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11 #define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12 #define RADEON_PCIE_TX_GART_BASE 0x13 #define RADEON_PCIE_TX_GART_START_LO 0x14 #define RADEON_PCIE_TX_GART_START_HI 0x15 #define RADEON_PCIE_TX_GART_END_LO 0x16 #define RADEON_PCIE_TX_GART_END_HI 0x17 #define RADEON_MPP_TB_CONFIG 0x01c0 #define RADEON_MEM_CNTL 0x0140 #define RADEON_MEM_SDRAM_MODE_REG 0x0158 #define RADEON_AGP_BASE 0x0170 #define RADEON_RB3D_COLOROFFSET 0x1c40 #define RADEON_RB3D_COLORPITCH 0x1c48 #define RADEON_DP_GUI_MASTER_CNTL 0x146c # define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) # define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) # define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) # define RADEON_GMC_BRUSH_NONE (15 << 4) # define RADEON_GMC_DST_16BPP (4 << 8) # define RADEON_GMC_DST_24BPP (5 << 8) # define RADEON_GMC_DST_32BPP (6 << 8) # define RADEON_GMC_DST_DATATYPE_SHIFT 8 # define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) # define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) # define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24) # define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) # define RADEON_GMC_WR_MSK_DIS (1 << 30) # define RADEON_ROP3_S 0x00cc0000 # define RADEON_ROP3_P 0x00f00000 #define RADEON_DP_WRITE_MASK 0x16cc #define RADEON_DST_PITCH_OFFSET 0x142c #define RADEON_DST_PITCH_OFFSET_C 0x1c80 # define RADEON_DST_TILE_LINEAR (0 << 30) # define RADEON_DST_TILE_MACRO (1 << 30) # define RADEON_DST_TILE_MICRO (2 << 30) # define RADEON_DST_TILE_BOTH (3 << 30) #define RADEON_SCRATCH_REG0 0x15e0 #define RADEON_SCRATCH_REG1 0x15e4 #define RADEON_SCRATCH_REG2 0x15e8 #define RADEON_SCRATCH_REG3 0x15ec #define RADEON_SCRATCH_REG4 0x15f0 #define RADEON_SCRATCH_REG5 0x15f4 #define RADEON_SCRATCH_UMSK 0x0770 #define RADEON_SCRATCH_ADDR 0x0774 #define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x)) #define GET_SCRATCH( x ) (dev_priv->writeback_works \ ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) #define RADEON_GEN_INT_CNTL 0x0040 # define RADEON_CRTC_VBLANK_MASK (1 << 0) # define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) # define RADEON_SW_INT_ENABLE (1 << 25) #define RADEON_GEN_INT_STATUS 0x0044 # define RADEON_CRTC_VBLANK_STAT (1 << 0) # define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) # define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19) # define RADEON_SW_INT_TEST (1 << 25) # define RADEON_SW_INT_TEST_ACK (1 << 25) # define RADEON_SW_INT_FIRE (1 << 26) #define RADEON_HOST_PATH_CNTL 0x0130 # define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) # define RADEON_HDP_WC_TIMEOUT_28BCLK (7 << 28) #define RADEON_ISYNC_CNTL 0x1724 # define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0) # define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1) # define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2) # define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3) # define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4) # define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5) #define RADEON_RBBM_GUICNTL 0x172c # define RADEON_HOST_DATA_SWAP_NONE (0 << 0) # define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) # define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) # define RADEON_HOST_DATA_SWAP_HDW (3 << 0) #define RADEON_MC_AGP_LOCATION 0x014c #define RADEON_MC_FB_LOCATION 0x0148 #define RADEON_MCLK_CNTL 0x0012 # define RADEON_FORCEON_MCLKA (1 << 16) # define RADEON_FORCEON_MCLKB (1 << 17) # define RADEON_FORCEON_YCLKA (1 << 18) # define RADEON_FORCEON_YCLKB (1 << 19) # define RADEON_FORCEON_MC (1 << 20) # define RADEON_FORCEON_AIC (1 << 21) #define RADEON_PP_BORDER_COLOR_0 0x1d40 #define RADEON_PP_BORDER_COLOR_1 0x1d44 #define RADEON_PP_BORDER_COLOR_2 0x1d48 #define RADEON_PP_CNTL 0x1c38 # define RADEON_SCISSOR_ENABLE (1 << 1) #define RADEON_PP_LUM_MATRIX 0x1d00 #define RADEON_PP_MISC 0x1c14 #define RADEON_PP_ROT_MATRIX_0 0x1d58 #define RADEON_PP_TXFILTER_0 0x1c54 #define RADEON_PP_TXOFFSET_0 0x1c5c #define RADEON_PP_TXFILTER_1 0x1c6c #define RADEON_PP_TXFILTER_2 0x1c84 #define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c # define RADEON_RB2D_DC_FLUSH (3 << 0) # define RADEON_RB2D_DC_FREE (3 << 2) # define RADEON_RB2D_DC_FLUSH_ALL 0xf # define RADEON_RB2D_DC_BUSY (1 << 31) #define RADEON_RB3D_CNTL 0x1c3c # define RADEON_ALPHA_BLEND_ENABLE (1 << 0) # define RADEON_PLANE_MASK_ENABLE (1 << 1) # define RADEON_DITHER_ENABLE (1 << 2) # define RADEON_ROUND_ENABLE (1 << 3) # define RADEON_SCALE_DITHER_ENABLE (1 << 4) # define RADEON_DITHER_INIT (1 << 5) # define RADEON_ROP_ENABLE (1 << 6) # define RADEON_STENCIL_ENABLE (1 << 7) # define RADEON_Z_ENABLE (1 << 8) # define RADEON_ZBLOCK16 (1 << 15) #define RADEON_RB3D_DEPTHOFFSET 0x1c24 #define RADEON_RB3D_DEPTHCLEARVALUE 0x3230 #define RADEON_RB3D_DEPTHPITCH 0x1c28 #define RADEON_RB3D_PLANEMASK 0x1d84 #define RADEON_RB3D_STENCILREFMASK 0x1d7c #define RADEON_RB3D_ZCACHE_MODE 0x3250 #define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254 # define RADEON_RB3D_ZC_FLUSH (1 << 0) # define RADEON_RB3D_ZC_FREE (1 << 2) # define RADEON_RB3D_ZC_FLUSH_ALL 0x5 # define RADEON_RB3D_ZC_BUSY (1 << 31) #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c # define RADEON_Z_TEST_MASK (7 << 4) # define RADEON_Z_TEST_ALWAYS (7 << 4) # define RADEON_Z_HIERARCHY_ENABLE (1 << 8) # define RADEON_STENCIL_TEST_ALWAYS (7 << 12) # define RADEON_STENCIL_S_FAIL_REPLACE (2 << 16) # define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) # define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) # define RADEON_Z_COMPRESSION_ENABLE (1 << 28) # define RADEON_FORCE_Z_DIRTY (1 << 29) # define RADEON_Z_WRITE_ENABLE (1 << 30) # define RADEON_Z_DECOMPRESSION_ENABLE (1 << 31) #define RADEON_RBBM_SOFT_RESET 0x00f0 # define RADEON_SOFT_RESET_CP (1 << 0) # define RADEON_SOFT_RESET_HI (1 << 1) # define RADEON_SOFT_RESET_SE (1 << 2) # define RADEON_SOFT_RESET_RE (1 << 3) # define RADEON_SOFT_RESET_PP (1 << 4) # define RADEON_SOFT_RESET_E2 (1 << 5) # define RADEON_SOFT_RESET_RB (1 << 6) # define RADEON_SOFT_RESET_HDP (1 << 7) #define RADEON_RBBM_STATUS 0x0e40 # define RADEON_RBBM_FIFOCNT_MASK 0x007f # define RADEON_RBBM_ACTIVE (1 << 31) #define RADEON_RE_LINE_PATTERN 0x1cd0 #define RADEON_RE_MISC 0x26c4 #define RADEON_RE_TOP_LEFT 0x26c0 #define RADEON_RE_WIDTH_HEIGHT 0x1c44 #define RADEON_RE_STIPPLE_ADDR 0x1cc8 #define RADEON_RE_STIPPLE_DATA 0x1ccc #define RADEON_SCISSOR_TL_0 0x1cd8 #define RADEON_SCISSOR_BR_0 0x1cdc #define RADEON_SCISSOR_TL_1 0x1ce0 #define RADEON_SCISSOR_BR_1 0x1ce4 #define RADEON_SCISSOR_TL_2 0x1ce8 #define RADEON_SCISSOR_BR_2 0x1cec #define RADEON_SE_COORD_FMT 0x1c50 #define RADEON_SE_CNTL 0x1c4c # define RADEON_FFACE_CULL_CW (0 << 0) # define RADEON_BFACE_SOLID (3 << 1) # define RADEON_FFACE_SOLID (3 << 3) # define RADEON_FLAT_SHADE_VTX_LAST (3 << 6) # define RADEON_DIFFUSE_SHADE_FLAT (1 << 8) # define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8) # define RADEON_ALPHA_SHADE_FLAT (1 << 10) # define RADEON_ALPHA_SHADE_GOURAUD (2 << 10) # define RADEON_SPECULAR_SHADE_FLAT (1 << 12) # define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12) # define RADEON_FOG_SHADE_FLAT (1 << 14) # define RADEON_FOG_SHADE_GOURAUD (2 << 14) # define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24) # define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25) # define RADEON_VTX_PIX_CENTER_OGL (1 << 27) # define RADEON_ROUND_MODE_TRUNC (0 << 28) # define RADEON_ROUND_PREC_8TH_PIX (1 << 30) #define RADEON_SE_CNTL_STATUS 0x2140 #define RADEON_SE_LINE_WIDTH 0x1db8 #define RADEON_SE_VPORT_XSCALE 0x1d98 #define RADEON_SE_ZBIAS_FACTOR 0x1db0 #define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 #define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 #define RADEON_SE_TCL_VECTOR_INDX_REG 0x2200 # define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16 # define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28 #define RADEON_SE_TCL_VECTOR_DATA_REG 0x2204 #define RADEON_SE_TCL_SCALAR_INDX_REG 0x2208 # define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16 #define RADEON_SE_TCL_SCALAR_DATA_REG 0x220C #define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8 #define RADEON_SURFACE_ACCESS_CLR 0x0bfc #define RADEON_SURFACE_CNTL 0x0b00 # define RADEON_SURF_TRANSLATION_DIS (1 << 8) # define RADEON_NONSURF_AP0_SWP_MASK (3 << 20) # define RADEON_NONSURF_AP0_SWP_LITTLE (0 << 20) # define RADEON_NONSURF_AP0_SWP_BIG16 (1 << 20) # define RADEON_NONSURF_AP0_SWP_BIG32 (2 << 20) # define RADEON_NONSURF_AP1_SWP_MASK (3 << 22) # define RADEON_NONSURF_AP1_SWP_LITTLE (0 << 22) # define RADEON_NONSURF_AP1_SWP_BIG16 (1 << 22) # define RADEON_NONSURF_AP1_SWP_BIG32 (2 << 22) #define RADEON_SURFACE0_INFO 0x0b0c # define RADEON_SURF_PITCHSEL_MASK (0x1ff << 0) # define RADEON_SURF_TILE_MODE_MASK (3 << 16) # define RADEON_SURF_TILE_MODE_MACRO (0 << 16) # define RADEON_SURF_TILE_MODE_MICRO (1 << 16) # define RADEON_SURF_TILE_MODE_32BIT_Z (2 << 16) # define RADEON_SURF_TILE_MODE_16BIT_Z (3 << 16) #define RADEON_SURFACE0_LOWER_BOUND 0x0b04 #define RADEON_SURFACE0_UPPER_BOUND 0x0b08 # define RADEON_SURF_ADDRESS_FIXED_MASK (0x3ff << 0) #define RADEON_SURFACE1_INFO 0x0b1c #define RADEON_SURFACE1_LOWER_BOUND 0x0b14 #define RADEON_SURFACE1_UPPER_BOUND 0x0b18 #define RADEON_SURFACE2_INFO 0x0b2c #define RADEON_SURFACE2_LOWER_BOUND 0x0b24 #define RADEON_SURFACE2_UPPER_BOUND 0x0b28 #define RADEON_SURFACE3_INFO 0x0b3c #define RADEON_SURFACE3_LOWER_BOUND 0x0b34 #define RADEON_SURFACE3_UPPER_BOUND 0x0b38 #define RADEON_SURFACE4_INFO 0x0b4c #define RADEON_SURFACE4_LOWER_BOUND 0x0b44 #define RADEON_SURFACE4_UPPER_BOUND 0x0b48 #define RADEON_SURFACE5_INFO 0x0b5c #define RADEON_SURFACE5_LOWER_BOUND 0x0b54 #define RADEON_SURFACE5_UPPER_BOUND 0x0b58 #define RADEON_SURFACE6_INFO 0x0b6c #define RADEON_SURFACE6_LOWER_BOUND 0x0b64 #define RADEON_SURFACE6_UPPER_BOUND 0x0b68 #define RADEON_SURFACE7_INFO 0x0b7c #define RADEON_SURFACE7_LOWER_BOUND 0x0b74 #define RADEON_SURFACE7_UPPER_BOUND 0x0b78 #define RADEON_SW_SEMAPHORE 0x013c #define RADEON_WAIT_UNTIL 0x1720 # define RADEON_WAIT_CRTC_PFLIP (1 << 0) # define RADEON_WAIT_2D_IDLE (1 << 14) # define RADEON_WAIT_3D_IDLE (1 << 15) # define RADEON_WAIT_2D_IDLECLEAN (1 << 16) # define RADEON_WAIT_3D_IDLECLEAN (1 << 17) # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) #define RADEON_RB3D_ZMASKOFFSET 0x3234 #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c # define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) # define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) /* CP registers */ #define RADEON_CP_ME_RAM_ADDR 0x07d4 #define RADEON_CP_ME_RAM_RADDR 0x07d8 #define RADEON_CP_ME_RAM_DATAH 0x07dc #define RADEON_CP_ME_RAM_DATAL 0x07e0 #define RADEON_CP_RB_BASE 0x0700 #define RADEON_CP_RB_CNTL 0x0704 # define RADEON_BUF_SWAP_32BIT (2 << 16) #define RADEON_CP_RB_RPTR_ADDR 0x070c #define RADEON_CP_RB_RPTR 0x0710 #define RADEON_CP_RB_WPTR 0x0714 #define RADEON_CP_RB_WPTR_DELAY 0x0718 # define RADEON_PRE_WRITE_TIMER_SHIFT 0 # define RADEON_PRE_WRITE_LIMIT_SHIFT 23 #define RADEON_CP_IB_BASE 0x0738 #define RADEON_CP_CSQ_CNTL 0x0740 # define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0) # define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) # define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) # define RADEON_CSQ_PRIBM_INDDIS (2 << 28) # define RADEON_CSQ_PRIPIO_INDBM (3 << 28) # define RADEON_CSQ_PRIBM_INDBM (4 << 28) # define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) #define RADEON_AIC_CNTL 0x01d0 # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) #define RADEON_AIC_STAT 0x01d4 #define RADEON_AIC_PT_BASE 0x01d8 #define RADEON_AIC_LO_ADDR 0x01dc #define RADEON_AIC_HI_ADDR 0x01e0 #define RADEON_AIC_TLB_ADDR 0x01e4 #define RADEON_AIC_TLB_DATA 0x01e8 /* CP command packets */ #define RADEON_CP_PACKET0 0x00000000 # define RADEON_ONE_REG_WR (1 << 15) #define RADEON_CP_PACKET1 0x40000000 #define RADEON_CP_PACKET2 0x80000000 #define RADEON_CP_PACKET3 0xC0000000 # define RADEON_CP_NOP 0x00001000 # define RADEON_CP_NEXT_CHAR 0x00001900 # define RADEON_CP_PLY_NEXTSCAN 0x00001D00 # define RADEON_CP_SET_SCISSORS 0x00001E00 /* GEN_INDX_PRIM is unsupported starting with R300 */ # define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300 # define RADEON_WAIT_FOR_IDLE 0x00002600 # define RADEON_3D_DRAW_VBUF 0x00002800 # define RADEON_3D_DRAW_IMMD 0x00002900 # define RADEON_3D_DRAW_INDX 0x00002A00 # define RADEON_CP_LOAD_PALETTE 0x00002C00 # define RADEON_3D_LOAD_VBPNTR 0x00002F00 # define RADEON_MPEG_IDCT_MACROBLOCK 0x00003000 # define RADEON_MPEG_IDCT_MACROBLOCK_REV 0x00003100 # define RADEON_3D_CLEAR_ZMASK 0x00003200 # define RADEON_CP_INDX_BUFFER 0x00003300 # define RADEON_CP_3D_DRAW_VBUF_2 0x00003400 # define RADEON_CP_3D_DRAW_IMMD_2 0x00003500 # define RADEON_CP_3D_DRAW_INDX_2 0x00003600 # define RADEON_3D_CLEAR_HIZ 0x00003700 # define RADEON_CP_3D_CLEAR_CMASK 0x00003802 # define RADEON_CNTL_HOSTDATA_BLT 0x00009400 # define RADEON_CNTL_PAINT_MULTI 0x00009A00 # define RADEON_CNTL_BITBLT_MULTI 0x00009B00 # define RADEON_CNTL_SET_SCISSORS 0xC0001E00 #define RADEON_CP_PACKET_MASK 0xC0000000 #define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 #define RADEON_CP_PACKET0_REG_MASK 0x000007ff #define RADEON_CP_PACKET1_REG0_MASK 0x000007ff #define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 #define RADEON_VTX_Z_PRESENT (1 << 31) #define RADEON_VTX_PKCOLOR_PRESENT (1 << 3) #define RADEON_PRIM_TYPE_NONE (0 << 0) #define RADEON_PRIM_TYPE_POINT (1 << 0) #define RADEON_PRIM_TYPE_LINE (2 << 0) #define RADEON_PRIM_TYPE_LINE_STRIP (3 << 0) #define RADEON_PRIM_TYPE_TRI_LIST (4 << 0) #define RADEON_PRIM_TYPE_TRI_FAN (5 << 0) #define RADEON_PRIM_TYPE_TRI_STRIP (6 << 0) #define RADEON_PRIM_TYPE_TRI_TYPE2 (7 << 0) #define RADEON_PRIM_TYPE_RECT_LIST (8 << 0) #define RADEON_PRIM_TYPE_3VRT_POINT_LIST (9 << 0) #define RADEON_PRIM_TYPE_3VRT_LINE_LIST (10 << 0) #define RADEON_PRIM_TYPE_MASK 0xf #define RADEON_PRIM_WALK_IND (1 << 4) #define RADEON_PRIM_WALK_LIST (2 << 4) #define RADEON_PRIM_WALK_RING (3 << 4) #define RADEON_COLOR_ORDER_BGRA (0 << 6) #define RADEON_COLOR_ORDER_RGBA (1 << 6) #define RADEON_MAOS_ENABLE (1 << 7) #define RADEON_VTX_FMT_R128_MODE (0 << 8) #define RADEON_VTX_FMT_RADEON_MODE (1 << 8) #define RADEON_NUM_VERTICES_SHIFT 16 #define RADEON_COLOR_FORMAT_CI8 2 #define RADEON_COLOR_FORMAT_ARGB1555 3 #define RADEON_COLOR_FORMAT_RGB565 4 #define RADEON_COLOR_FORMAT_ARGB8888 6 #define RADEON_COLOR_FORMAT_RGB332 7 #define RADEON_COLOR_FORMAT_RGB8 9 #define RADEON_COLOR_FORMAT_ARGB4444 15 #define RADEON_TXFORMAT_I8 0 #define RADEON_TXFORMAT_AI88 1 #define RADEON_TXFORMAT_RGB332 2 #define RADEON_TXFORMAT_ARGB1555 3 #define RADEON_TXFORMAT_RGB565 4 #define RADEON_TXFORMAT_ARGB4444 5 #define RADEON_TXFORMAT_ARGB8888 6 #define RADEON_TXFORMAT_RGBA8888 7 #define RADEON_TXFORMAT_Y8 8 #define RADEON_TXFORMAT_VYUY422 10 #define RADEON_TXFORMAT_YVYU422 11 #define RADEON_TXFORMAT_DXT1 12 #define RADEON_TXFORMAT_DXT23 14 #define RADEON_TXFORMAT_DXT45 15 #define R200_PP_TXCBLEND_0 0x2f00 #define R200_PP_TXCBLEND_1 0x2f10 #define R200_PP_TXCBLEND_2 0x2f20 #define R200_PP_TXCBLEND_3 0x2f30 #define R200_PP_TXCBLEND_4 0x2f40 #define R200_PP_TXCBLEND_5 0x2f50 #define R200_PP_TXCBLEND_6 0x2f60 #define R200_PP_TXCBLEND_7 0x2f70 #define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268 #define R200_PP_TFACTOR_0 0x2ee0 #define R200_SE_VTX_FMT_0 0x2088 #define R200_SE_VAP_CNTL 0x2080 #define R200_SE_TCL_MATRIX_SEL_0 0x2230 #define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8 #define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0 #define R200_PP_TXFILTER_5 0x2ca0 #define R200_PP_TXFILTER_4 0x2c80 #define R200_PP_TXFILTER_3 0x2c60 #define R200_PP_TXFILTER_2 0x2c40 #define R200_PP_TXFILTER_1 0x2c20 #define R200_PP_TXFILTER_0 0x2c00 #define R200_PP_TXOFFSET_5 0x2d78 #define R200_PP_TXOFFSET_4 0x2d60 #define R200_PP_TXOFFSET_3 0x2d48 #define R200_PP_TXOFFSET_2 0x2d30 #define R200_PP_TXOFFSET_1 0x2d18 #define R200_PP_TXOFFSET_0 0x2d00 #define R200_PP_CUBIC_FACES_0 0x2c18 #define R200_PP_CUBIC_FACES_1 0x2c38 #define R200_PP_CUBIC_FACES_2 0x2c58 #define R200_PP_CUBIC_FACES_3 0x2c78 #define R200_PP_CUBIC_FACES_4 0x2c98 #define R200_PP_CUBIC_FACES_5 0x2cb8 #define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 #define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 #define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c #define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 #define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 #define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c #define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 #define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 #define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 #define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c #define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 #define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 #define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c #define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 #define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 #define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c #define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 #define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 #define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 #define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c #define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 #define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 #define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c #define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 #define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 #define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c #define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 #define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 #define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 #define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c #define R200_RE_AUX_SCISSOR_CNTL 0x26f0 #define R200_SE_VTE_CNTL 0x20b0 #define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 #define R200_PP_TAM_DEBUG3 0x2d9c #define R200_PP_CNTL_X 0x2cc4 #define R200_SE_VAP_CNTL_STATUS 0x2140 #define R200_RE_SCISSOR_TL_0 0x1cd8 #define R200_RE_SCISSOR_TL_1 0x1ce0 #define R200_RE_SCISSOR_TL_2 0x1ce8 #define R200_RB3D_DEPTHXY_OFFSET 0x1d60 #define R200_RE_AUX_SCISSOR_CNTL 0x26f0 #define R200_SE_VTX_STATE_CNTL 0x2180 #define R200_RE_POINTSIZE 0x2648 #define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 #define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ #define RADEON_PP_TEX_SIZE_1 0x1d0c #define RADEON_PP_TEX_SIZE_2 0x1d14 #define RADEON_PP_CUBIC_FACES_0 0x1d24 #define RADEON_PP_CUBIC_FACES_1 0x1d28 #define RADEON_PP_CUBIC_FACES_2 0x1d2c #define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */ #define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 #define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 #define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 #define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012 #define SE_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100 #define SE_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200 #define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK 0x00000001 #define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK 0x00000002 #define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b #define R200_3D_DRAW_IMMD_2 0xC0003500 #define R200_SE_VTX_FMT_1 0x208c #define R200_RE_CNTL 0x1c50 #define R200_RB3D_BLENDCOLOR 0x3218 #define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4 #define R200_PP_TRI_PERF 0x2cf8 +#define R200_PP_AFS_0 0x2f80 +#define R200_PP_AFS_1 0x2f00 /* same as txcblend_0 */ + +/* MPEG settings from VHA code */ +#define RADEON_VHA_SETTO16_1 0x2694 +#define RADEON_VHA_SETTO16_2 0x2680 +#define RADEON_VHA_SETTO0_1 0x1840 +#define RADEON_VHA_FB_OFFSET 0x19e4 +#define RADEON_VHA_SETTO1AND70S 0x19d8 +#define RADEON_VHA_DST_PITCH 0x1408 + +// set as reference header +#define RADEON_VHA_BACKFRAME0_OFF_Y 0x1840 +#define RADEON_VHA_BACKFRAME1_OFF_PITCH_Y 0x1844 +#define RADEON_VHA_BACKFRAME0_OFF_U 0x1848 +#define RADEON_VHA_BACKFRAME1_OFF_PITCH_U 0x184c +#define RADOEN_VHA_BACKFRAME0_OFF_V 0x1850 +#define RADEON_VHA_BACKFRAME1_OFF_PITCH_V 0x1854 +#define RADEON_VHA_FORWFRAME0_OFF_Y 0x1858 +#define RADEON_VHA_FORWFRAME1_OFF_PITCH_Y 0x185c +#define RADEON_VHA_FORWFRAME0_OFF_U 0x1860 +#define RADEON_VHA_FORWFRAME1_OFF_PITCH_U 0x1864 +#define RADEON_VHA_FORWFRAME0_OFF_V 0x1868 +#define RADEON_VHA_FORWFRAME0_OFF_PITCH_V 0x1880 +#define RADEON_VHA_BACKFRAME0_OFF_Y_2 0x1884 +#define RADEON_VHA_BACKFRAME1_OFF_PITCH_Y_2 0x1888 +#define RADEON_VHA_BACKFRAME0_OFF_U_2 0x188c +#define RADEON_VHA_BACKFRAME1_OFF_PITCH_U_2 0x1890 +#define RADEON_VHA_BACKFRAME0_OFF_V_2 0x1894 +#define RADEON_VHA_BACKFRAME1_OFF_PITCH_V_2 0x1898 + + + /* Constants */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ #define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0 #define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1 #define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2 #define RADEON_LAST_SWI_REG RADEON_SCRATCH_REG3 #define RADEON_LAST_DISPATCH 1 #define RADEON_MAX_VB_AGE 0x7fffffff #define RADEON_MAX_VB_VERTS (0xffff) #define RADEON_RING_HIGH_MARK 128 +#define RADEON_PCIGART_TABLE_SIZE (32*1024) + #define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) #define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) #define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) #define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) #define RADEON_WRITE_PLL( addr, val ) \ do { \ RADEON_WRITE8( RADEON_CLOCK_CNTL_INDEX, \ ((addr) & 0x1f) | RADEON_PLL_WR_EN ); \ RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \ } while (0) #define RADEON_WRITE_PCIE( addr, val ) \ do { \ RADEON_WRITE8( RADEON_PCIE_INDEX, \ ((addr) & 0xff)); \ RADEON_WRITE( RADEON_PCIE_DATA, (val) ); \ } while (0) - -extern int radeon_preinit(struct drm_device *dev, unsigned long flags); -extern int radeon_postcleanup(struct drm_device *dev); #define CP_PACKET0( reg, n ) \ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) #define CP_PACKET0_TABLE( reg, n ) \ (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2)) #define CP_PACKET1( reg0, reg1 ) \ (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2)) #define CP_PACKET2() \ (RADEON_CP_PACKET2) #define CP_PACKET3( pkt, n ) \ (RADEON_CP_PACKET3 | (pkt) | ((n) << 16)) /* ================================================================ * Engine control helper macros */ #define RADEON_WAIT_UNTIL_2D_IDLE() do { \ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ RADEON_WAIT_HOST_IDLECLEAN) ); \ } while (0) #define RADEON_WAIT_UNTIL_3D_IDLE() do { \ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \ RADEON_WAIT_HOST_IDLECLEAN) ); \ } while (0) #define RADEON_WAIT_UNTIL_IDLE() do { \ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ RADEON_WAIT_3D_IDLECLEAN | \ RADEON_WAIT_HOST_IDLECLEAN) ); \ } while (0) #define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do { \ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \ } while (0) #define RADEON_FLUSH_CACHE() do { \ OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ OUT_RING( RADEON_RB2D_DC_FLUSH ); \ } while (0) #define RADEON_PURGE_CACHE() do { \ OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \ } while (0) #define RADEON_FLUSH_ZCACHE() do { \ OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \ OUT_RING( RADEON_RB3D_ZC_FLUSH ); \ } while (0) #define RADEON_PURGE_ZCACHE() do { \ OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \ OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \ } while (0) /* ================================================================ * Misc helper macros */ /* Perfbox functionality only. */ #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ do { \ if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) { \ u32 head = GET_RING_HEAD( dev_priv ); \ if (head == dev_priv->ring.tail) \ dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE; \ } \ } while (0) #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ do { \ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \ if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \ int __ret = radeon_do_cp_idle( dev_priv ); \ if ( __ret ) return __ret; \ sarea_priv->last_dispatch = 0; \ radeon_freelist_reset( dev ); \ } \ } while (0) #define RADEON_DISPATCH_AGE( age ) do { \ OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \ OUT_RING( age ); \ } while (0) #define RADEON_FRAME_AGE( age ) do { \ OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \ OUT_RING( age ); \ } while (0) #define RADEON_CLEAR_AGE( age ) do { \ OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \ OUT_RING( age ); \ } while (0) /* ================================================================ * Ring control */ #define RADEON_VERBOSE 0 #define RING_LOCALS int write, _nr; unsigned int mask; u32 *ring; #define BEGIN_RING( n ) do { \ if ( RADEON_VERBOSE ) { \ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ n, __FUNCTION__ ); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ COMMIT_RING(); \ radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \ } \ _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ mask = dev_priv->ring.tail_mask; \ } while (0) #define ADVANCE_RING() do { \ if ( RADEON_VERBOSE ) { \ DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ write, dev_priv->ring.tail ); \ } \ if (((dev_priv->ring.tail + _nr) & mask) != write) { \ DRM_ERROR( \ "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ ((dev_priv->ring.tail + _nr) & mask), \ write, __LINE__); \ } else \ dev_priv->ring.tail = write; \ } while (0) #define COMMIT_RING() do { \ /* Flush writes to ring */ \ DRM_MEMORYBARRIER(); \ GET_RING_HEAD( dev_priv ); \ RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \ /* read from PCI bus to ensure correct posting */ \ RADEON_READ( RADEON_CP_RB_RPTR ); \ } while (0) #define OUT_RING( x ) do { \ if ( RADEON_VERBOSE ) { \ DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ (unsigned int)(x), write ); \ } \ ring[write++] = (x); \ write &= mask; \ } while (0) #define OUT_RING_REG( reg, val ) do { \ OUT_RING( CP_PACKET0( reg, 0 ) ); \ OUT_RING( val ); \ } while (0) #define OUT_RING_TABLE( tab, sz ) do { \ int _size = (sz); \ int *_tab = (int *)(tab); \ \ if (write + _size > mask) { \ int _i = (mask+1) - write; \ _size -= _i; \ while (_i > 0) { \ *(int *)(ring + write) = *_tab++; \ write++; \ _i--; \ } \ write = 0; \ _tab += _i; \ } \ while (_size > 0) { \ *(ring + write) = *_tab++; \ write++; \ _size--; \ } \ write &= mask; \ } while (0) #endif /* __RADEON_DRV_H__ */ Index: head/sys/dev/drm/radeon_irq.c =================================================================== --- head/sys/dev/drm/radeon_irq.c (revision 152908) +++ head/sys/dev/drm/radeon_irq.c (revision 152909) @@ -1,251 +1,247 @@ /* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */ /*- * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. * * The Weather Channel (TM) funded Tungsten Graphics to develop the * initial release of the Radeon 8500 driver under the XFree86 license. * This notice must be preserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Keith Whitwell * Michel D�zer - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" +static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, + u32 mask) +{ + u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask; + if (irqs) + RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); + return irqs; +} + /* Interrupts - Used for device synchronization and flushing in the * following circumstances: * * - Exclusive FB access with hw idle: * - Wait for GUI Idle (?) interrupt, then do normal flush. * * - Frame throttling, NV_fence: * - Drop marker irq's into command stream ahead of time. * - Wait on irq's with lock *not held* * - Check each for termination condition * * - Internally in cp_getbuffer, etc: * - as above, but wait with lock held??? * * NOTE: These functions are misleadingly named -- the irq's aren't * tied to dma at all, this is just a hangover from dri prehistory. */ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; u32 stat; /* Only consider the bits we're interested in - others could be used * outside the DRM */ - stat = RADEON_READ(RADEON_GEN_INT_STATUS) - & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); + stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | + RADEON_CRTC_VBLANK_STAT)); if (!stat) return IRQ_NONE; /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) { DRM_WAKEUP(&dev_priv->swi_queue); } /* VBLANK interrupt */ if (stat & RADEON_CRTC_VBLANK_STAT) { atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); } - /* Acknowledge interrupts we handle */ - RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); return IRQ_HANDLED; } -static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv) -{ - u32 tmp = RADEON_READ(RADEON_GEN_INT_STATUS) - & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT); - if (tmp) - RADEON_WRITE(RADEON_GEN_INT_STATUS, tmp); -} - static int radeon_emit_irq(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; unsigned int ret; RING_LOCALS; atomic_inc(&dev_priv->swi_emitted); ret = atomic_read(&dev_priv->swi_emitted); BEGIN_RING(4); OUT_RING_REG(RADEON_LAST_SWI_REG, ret); OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); ADVANCE_RING(); COMMIT_RING(); return ret; } static int radeon_wait_irq(drm_device_t * dev, int swi_nr) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; int ret = 0; if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr) return 0; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - /* This is a hack to work around mysterious freezes on certain - * systems: - */ - radeon_acknowledge_irqs(dev_priv); - DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ, RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); return ret; } int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; unsigned int cur_vblank; int ret = 0; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } - radeon_acknowledge_irqs(dev_priv); + radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT); dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; /* Assume that the user has missed the current sequence number * by about a day rather than she wants to wait for years * using vertical blanks... */ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, (((cur_vblank = atomic_read(&dev->vbl_received)) - *sequence) <= (1 << 23))); *sequence = cur_vblank; return ret; } /* Needs the lock as it touches the ring. */ int radeon_irq_emit(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_irq_emit_t emit; int result; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(emit, (drm_radeon_irq_emit_t __user *) data, sizeof(emit)); result = radeon_emit_irq(dev); if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; } /* Doesn't need the hardware lock. */ int radeon_irq_wait(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_irq_wait_t irqwait; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_radeon_irq_wait_t __user *) data, sizeof(irqwait)); return radeon_wait_irq(dev, irqwait.irq_seq); } /* drm_dma.h hooks */ void radeon_driver_irq_preinstall(drm_device_t * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; /* Disable *all* interrupts */ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); /* Clear bits if they're already high */ - radeon_acknowledge_irqs(dev_priv); + radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | + RADEON_CRTC_VBLANK_STAT)); } void radeon_driver_irq_postinstall(drm_device_t * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; atomic_set(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); /* Turn on SW and VBL ints */ RADEON_WRITE(RADEON_GEN_INT_CNTL, RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE); } void radeon_driver_irq_uninstall(drm_device_t * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; if (!dev_priv) return; /* Disable *all* interrupts */ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); } Index: head/sys/dev/drm/radeon_mem.c =================================================================== --- head/sys/dev/drm/radeon_mem.c (revision 152908) +++ head/sys/dev/drm/radeon_mem.c (revision 152909) @@ -1,316 +1,317 @@ /* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */ /*- * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. * * The Weather Channel (TM) funded Tungsten Graphics to develop the * initial release of the Radeon 8500 driver under the XFree86 license. * This notice must be preserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Keith Whitwell - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" /* Very simple allocator for GART memory, working on a static range * already mapped into each client's address space. */ static struct mem_block *split_block(struct mem_block *p, int start, int size, DRMFILE filp) { /* Maybe cut off the start of an existing block */ if (start > p->start) { struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS); if (!newblock) goto out; newblock->start = start; newblock->size = p->size - (start - p->start); newblock->filp = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; p->next = newblock; p->size -= newblock->size; p = newblock; } /* Maybe cut off the end of an existing block */ if (size < p->size) { struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS); if (!newblock) goto out; newblock->start = start + size; newblock->size = p->size - size; newblock->filp = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; p->next = newblock; p->size = size; } out: /* Our block is in the middle */ p->filp = filp; return p; } static struct mem_block *alloc_block(struct mem_block *heap, int size, int align2, DRMFILE filp) { struct mem_block *p; int mask = (1 << align2) - 1; list_for_each(p, heap) { int start = (p->start + mask) & ~mask; if (p->filp == 0 && start + size <= p->start + p->size) return split_block(p, start, size, filp); } return NULL; } static struct mem_block *find_block(struct mem_block *heap, int start) { struct mem_block *p; list_for_each(p, heap) if (p->start == start) return p; return NULL; } static void free_block(struct mem_block *p) { p->filp = NULL; /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ if (p->next->filp == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; p->next->prev = p; drm_free(q, sizeof(*q), DRM_MEM_BUFS); } if (p->prev->filp == 0) { struct mem_block *q = p->prev; q->size += p->size; q->next = p->next; q->next->prev = q; drm_free(p, sizeof(*q), DRM_MEM_BUFS); } } /* Initialize. How to check for an uninitialized heap? */ static int init_heap(struct mem_block **heap, int start, int size) { struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS); if (!blocks) return DRM_ERR(ENOMEM); *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS); if (!*heap) { drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS); return DRM_ERR(ENOMEM); } blocks->start = start; blocks->size = size; blocks->filp = NULL; blocks->next = blocks->prev = *heap; memset(*heap, 0, sizeof(**heap)); (*heap)->filp = (DRMFILE) - 1; (*heap)->next = (*heap)->prev = blocks; return 0; } /* Free all blocks associated with the releasing file. */ void radeon_mem_release(DRMFILE filp, struct mem_block *heap) { struct mem_block *p; if (!heap || !heap->next) return; list_for_each(p, heap) { if (p->filp == filp) p->filp = NULL; } /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ list_for_each(p, heap) { while (p->filp == 0 && p->next->filp == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; p->next->prev = p; drm_free(q, sizeof(*q), DRM_MEM_DRIVER); } } } /* Shutdown. */ void radeon_mem_takedown(struct mem_block **heap) { struct mem_block *p; if (!*heap) return; for (p = (*heap)->next; p != *heap;) { struct mem_block *q = p; p = p->next; drm_free(q, sizeof(*q), DRM_MEM_DRIVER); } drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER); *heap = NULL; } /* IOCTL HANDLERS */ static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region) { switch (region) { case RADEON_MEM_REGION_GART: return &dev_priv->gart_heap; case RADEON_MEM_REGION_FB: return &dev_priv->fb_heap; default: return NULL; } } int radeon_mem_alloc(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_mem_alloc_t alloc; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_mem_alloc_t __user *) data, sizeof(alloc)); heap = get_heap(dev_priv, alloc.region); if (!heap || !*heap) return DRM_ERR(EFAULT); /* Make things easier on ourselves: all allocations at least * 4k aligned. */ if (alloc.alignment < 12) alloc.alignment = 12; block = alloc_block(*heap, alloc.size, alloc.alignment, filp); if (!block) return DRM_ERR(ENOMEM); if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; } int radeon_mem_free(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_mem_free_t memfree; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data, sizeof(memfree)); heap = get_heap(dev_priv, memfree.region); if (!heap || !*heap) return DRM_ERR(EFAULT); block = find_block(*heap, memfree.region_offset); if (!block) return DRM_ERR(EFAULT); if (block->filp != filp) return DRM_ERR(EPERM); free_block(block); return 0; } int radeon_mem_init_heap(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_mem_init_heap_t initheap; struct mem_block **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(initheap, (drm_radeon_mem_init_heap_t __user *) data, sizeof(initheap)); heap = get_heap(dev_priv, initheap.region); if (!heap) return DRM_ERR(EFAULT); if (*heap) { DRM_ERROR("heap already initialized?"); return DRM_ERR(EFAULT); } return init_heap(heap, initheap.start, initheap.size); } Index: head/sys/dev/drm/radeon_state.c =================================================================== --- head/sys/dev/drm/radeon_state.c (revision 152908) +++ head/sys/dev/drm/radeon_state.c (revision 152909) @@ -1,3090 +1,3103 @@ /* radeon_state.c -- State support for Radeon -*- linux-c -*- */ /*- * Copyright 2000 VA Linux Systems, Inc., Fremont, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Gareth Hughes * Kevin E. Martin - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/drm_sarea.h" #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" /* ================================================================ * Helper functions for client state checking and fixup */ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * dev_priv, drm_file_t * filp_priv, u32 * offset) { u32 off = *offset; struct drm_radeon_driver_file_fields *radeon_priv; if (off >= dev_priv->fb_location && off < (dev_priv->gart_vm_start + dev_priv->gart_size)) return 0; radeon_priv = filp_priv->driver_priv; off += radeon_priv->radeon_fb_delta; DRM_DEBUG("offset fixed up to 0x%x\n", off); if (off < dev_priv->fb_location || off >= (dev_priv->gart_vm_start + dev_priv->gart_size)) return DRM_ERR(EINVAL); *offset = off; return 0; } static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * dev_priv, drm_file_t * filp_priv, int id, u32 __user * data) { switch (id) { case RADEON_EMIT_PP_MISC: if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) { DRM_ERROR("Invalid depth buffer offset\n"); return DRM_ERR(EINVAL); } break; case RADEON_EMIT_PP_CNTL: if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) { DRM_ERROR("Invalid colour buffer offset\n"); return DRM_ERR(EINVAL); } break; case R200_EMIT_PP_TXOFFSET_0: case R200_EMIT_PP_TXOFFSET_1: case R200_EMIT_PP_TXOFFSET_2: case R200_EMIT_PP_TXOFFSET_3: case R200_EMIT_PP_TXOFFSET_4: case R200_EMIT_PP_TXOFFSET_5: if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[0])) { DRM_ERROR("Invalid R200 texture offset\n"); return DRM_ERR(EINVAL); } break; case RADEON_EMIT_PP_TXFILTER_0: case RADEON_EMIT_PP_TXFILTER_1: case RADEON_EMIT_PP_TXFILTER_2: if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) { DRM_ERROR("Invalid R100 texture offset\n"); return DRM_ERR(EINVAL); } break; case R200_EMIT_PP_CUBIC_OFFSETS_0: case R200_EMIT_PP_CUBIC_OFFSETS_1: case R200_EMIT_PP_CUBIC_OFFSETS_2: case R200_EMIT_PP_CUBIC_OFFSETS_3: case R200_EMIT_PP_CUBIC_OFFSETS_4: case R200_EMIT_PP_CUBIC_OFFSETS_5:{ int i; for (i = 0; i < 5; i++) { if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[i])) { DRM_ERROR ("Invalid R200 cubic texture offset\n"); return DRM_ERR(EINVAL); } } break; } case RADEON_EMIT_PP_CUBIC_OFFSETS_T0: case RADEON_EMIT_PP_CUBIC_OFFSETS_T1: case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{ int i; for (i = 0; i < 5; i++) { if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[i])) { DRM_ERROR ("Invalid R100 cubic texture offset\n"); return DRM_ERR(EINVAL); } } } break; case RADEON_EMIT_RB3D_COLORPITCH: case RADEON_EMIT_RE_LINE_PATTERN: case RADEON_EMIT_SE_LINE_WIDTH: case RADEON_EMIT_PP_LUM_MATRIX: case RADEON_EMIT_PP_ROT_MATRIX_0: case RADEON_EMIT_RB3D_STENCILREFMASK: case RADEON_EMIT_SE_VPORT_XSCALE: case RADEON_EMIT_SE_CNTL: case RADEON_EMIT_SE_CNTL_STATUS: case RADEON_EMIT_RE_MISC: case RADEON_EMIT_PP_BORDER_COLOR_0: case RADEON_EMIT_PP_BORDER_COLOR_1: case RADEON_EMIT_PP_BORDER_COLOR_2: case RADEON_EMIT_SE_ZBIAS_FACTOR: case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT: case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED: case R200_EMIT_PP_TXCBLEND_0: case R200_EMIT_PP_TXCBLEND_1: case R200_EMIT_PP_TXCBLEND_2: case R200_EMIT_PP_TXCBLEND_3: case R200_EMIT_PP_TXCBLEND_4: case R200_EMIT_PP_TXCBLEND_5: case R200_EMIT_PP_TXCBLEND_6: case R200_EMIT_PP_TXCBLEND_7: case R200_EMIT_TCL_LIGHT_MODEL_CTL_0: case R200_EMIT_TFACTOR_0: case R200_EMIT_VTX_FMT_0: case R200_EMIT_VAP_CTL: case R200_EMIT_MATRIX_SELECT_0: case R200_EMIT_TEX_PROC_CTL_2: case R200_EMIT_TCL_UCP_VERT_BLEND_CTL: case R200_EMIT_PP_TXFILTER_0: case R200_EMIT_PP_TXFILTER_1: case R200_EMIT_PP_TXFILTER_2: case R200_EMIT_PP_TXFILTER_3: case R200_EMIT_PP_TXFILTER_4: case R200_EMIT_PP_TXFILTER_5: case R200_EMIT_VTE_CNTL: case R200_EMIT_OUTPUT_VTX_COMP_SEL: case R200_EMIT_PP_TAM_DEBUG3: case R200_EMIT_PP_CNTL_X: case R200_EMIT_RB3D_DEPTHXY_OFFSET: case R200_EMIT_RE_AUX_SCISSOR_CNTL: case R200_EMIT_RE_SCISSOR_TL_0: case R200_EMIT_RE_SCISSOR_TL_1: case R200_EMIT_RE_SCISSOR_TL_2: case R200_EMIT_SE_VAP_CNTL_STATUS: case R200_EMIT_SE_VTX_STATE_CNTL: case R200_EMIT_RE_POINTSIZE: case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0: case R200_EMIT_PP_CUBIC_FACES_0: case R200_EMIT_PP_CUBIC_FACES_1: case R200_EMIT_PP_CUBIC_FACES_2: case R200_EMIT_PP_CUBIC_FACES_3: case R200_EMIT_PP_CUBIC_FACES_4: case R200_EMIT_PP_CUBIC_FACES_5: case RADEON_EMIT_PP_TEX_SIZE_0: case RADEON_EMIT_PP_TEX_SIZE_1: case RADEON_EMIT_PP_TEX_SIZE_2: case R200_EMIT_RB3D_BLENDCOLOR: case R200_EMIT_TCL_POINT_SPRITE_CNTL: case RADEON_EMIT_PP_CUBIC_FACES_0: case RADEON_EMIT_PP_CUBIC_FACES_1: case RADEON_EMIT_PP_CUBIC_FACES_2: case R200_EMIT_PP_TRI_PERF_CNTL: + case R200_EMIT_PP_AFS_0: + case R200_EMIT_PP_AFS_1: + case R200_EMIT_ATF_TFACTOR: + case R200_EMIT_PP_TXCTLALL_0: + case R200_EMIT_PP_TXCTLALL_1: + case R200_EMIT_PP_TXCTLALL_2: + case R200_EMIT_PP_TXCTLALL_3: + case R200_EMIT_PP_TXCTLALL_4: + case R200_EMIT_PP_TXCTLALL_5: /* These packets don't contain memory offsets */ break; default: DRM_ERROR("Unknown state packet ID %d\n", id); return DRM_ERR(EINVAL); } return 0; } static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * dev_priv, drm_file_t * filp_priv, drm_radeon_cmd_buffer_t * cmdbuf, unsigned int *cmdsz) { u32 *cmd = (u32 *) cmdbuf->buf; *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) { DRM_ERROR("Not a type 3 packet\n"); return DRM_ERR(EINVAL); } if (4 * *cmdsz > cmdbuf->bufsz) { DRM_ERROR("Packet size larger than size of data provided\n"); return DRM_ERR(EINVAL); } /* Check client state and fix it up if necessary */ if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */ u32 offset; if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { offset = cmd[2] << 10; if (radeon_check_and_fixup_offset (dev_priv, filp_priv, &offset)) { DRM_ERROR("Invalid first packet offset\n"); return DRM_ERR(EINVAL); } cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10; } if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { offset = cmd[3] << 10; if (radeon_check_and_fixup_offset (dev_priv, filp_priv, &offset)) { DRM_ERROR("Invalid second packet offset\n"); return DRM_ERR(EINVAL); } cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; } } return 0; } /* ================================================================ * CP hardware state programming functions */ static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv, drm_clip_rect_t * box) { RING_LOCALS; DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n", box->x1, box->y1, box->x2, box->y2); BEGIN_RING(4); OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0)); OUT_RING((box->y1 << 16) | box->x1); OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0)); OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1)); ADVANCE_RING(); } /* Emit 1.1 state */ static int radeon_emit_state(drm_radeon_private_t * dev_priv, drm_file_t * filp_priv, drm_radeon_context_regs_t * ctx, drm_radeon_texture_regs_t * tex, unsigned int dirty) { RING_LOCALS; DRM_DEBUG("dirty=0x%08x\n", dirty); if (dirty & RADEON_UPLOAD_CONTEXT) { if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &ctx->rb3d_depthoffset)) { DRM_ERROR("Invalid depth buffer offset\n"); return DRM_ERR(EINVAL); } if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &ctx->rb3d_coloroffset)) { DRM_ERROR("Invalid depth buffer offset\n"); return DRM_ERR(EINVAL); } BEGIN_RING(14); OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6)); OUT_RING(ctx->pp_misc); OUT_RING(ctx->pp_fog_color); OUT_RING(ctx->re_solid_color); OUT_RING(ctx->rb3d_blendcntl); OUT_RING(ctx->rb3d_depthoffset); OUT_RING(ctx->rb3d_depthpitch); OUT_RING(ctx->rb3d_zstencilcntl); OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2)); OUT_RING(ctx->pp_cntl); OUT_RING(ctx->rb3d_cntl); OUT_RING(ctx->rb3d_coloroffset); OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0)); OUT_RING(ctx->rb3d_colorpitch); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_VERTFMT) { BEGIN_RING(2); OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0)); OUT_RING(ctx->se_coord_fmt); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_LINE) { BEGIN_RING(5); OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1)); OUT_RING(ctx->re_line_pattern); OUT_RING(ctx->re_line_state); OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0)); OUT_RING(ctx->se_line_width); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_BUMPMAP) { BEGIN_RING(5); OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0)); OUT_RING(ctx->pp_lum_matrix); OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1)); OUT_RING(ctx->pp_rot_matrix_0); OUT_RING(ctx->pp_rot_matrix_1); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_MASKS) { BEGIN_RING(4); OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2)); OUT_RING(ctx->rb3d_stencilrefmask); OUT_RING(ctx->rb3d_ropcntl); OUT_RING(ctx->rb3d_planemask); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_VIEWPORT) { BEGIN_RING(7); OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5)); OUT_RING(ctx->se_vport_xscale); OUT_RING(ctx->se_vport_xoffset); OUT_RING(ctx->se_vport_yscale); OUT_RING(ctx->se_vport_yoffset); OUT_RING(ctx->se_vport_zscale); OUT_RING(ctx->se_vport_zoffset); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_SETUP) { BEGIN_RING(4); OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0)); OUT_RING(ctx->se_cntl); OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0)); OUT_RING(ctx->se_cntl_status); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_MISC) { BEGIN_RING(2); OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0)); OUT_RING(ctx->re_misc); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_TEX0) { if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex[0].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 0\n"); return DRM_ERR(EINVAL); } BEGIN_RING(9); OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5)); OUT_RING(tex[0].pp_txfilter); OUT_RING(tex[0].pp_txformat); OUT_RING(tex[0].pp_txoffset); OUT_RING(tex[0].pp_txcblend); OUT_RING(tex[0].pp_txablend); OUT_RING(tex[0].pp_tfactor); OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0)); OUT_RING(tex[0].pp_border_color); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_TEX1) { if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex[1].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 1\n"); return DRM_ERR(EINVAL); } BEGIN_RING(9); OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5)); OUT_RING(tex[1].pp_txfilter); OUT_RING(tex[1].pp_txformat); OUT_RING(tex[1].pp_txoffset); OUT_RING(tex[1].pp_txcblend); OUT_RING(tex[1].pp_txablend); OUT_RING(tex[1].pp_tfactor); OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0)); OUT_RING(tex[1].pp_border_color); ADVANCE_RING(); } if (dirty & RADEON_UPLOAD_TEX2) { if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex[2].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 2\n"); return DRM_ERR(EINVAL); } BEGIN_RING(9); OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5)); OUT_RING(tex[2].pp_txfilter); OUT_RING(tex[2].pp_txformat); OUT_RING(tex[2].pp_txoffset); OUT_RING(tex[2].pp_txcblend); OUT_RING(tex[2].pp_txablend); OUT_RING(tex[2].pp_tfactor); OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0)); OUT_RING(tex[2].pp_border_color); ADVANCE_RING(); } return 0; } /* Emit 1.2 state */ static int radeon_emit_state2(drm_radeon_private_t * dev_priv, drm_file_t * filp_priv, drm_radeon_state_t * state) { RING_LOCALS; if (state->dirty & RADEON_UPLOAD_ZBIAS) { BEGIN_RING(3); OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1)); OUT_RING(state->context2.se_zbias_factor); OUT_RING(state->context2.se_zbias_constant); ADVANCE_RING(); } return radeon_emit_state(dev_priv, filp_priv, &state->context, state->tex, state->dirty); } /* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in * 1.3 cmdbuffers allow all previous state to be updated as well as * the tcl scalar and vector areas. */ static struct { int start; int len; const char *name; } packet[RADEON_MAX_STATE_PACKETS] = { - { - RADEON_PP_MISC, 7, "RADEON_PP_MISC"}, { - RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"}, { - RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"}, { - RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"}, { - RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"}, { - RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"}, { - RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"}, { - RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"}, { - RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"}, { - RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"}, { - RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"}, { - RADEON_RE_MISC, 1, "RADEON_RE_MISC"}, { - RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"}, { - RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"}, { - RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"}, { - RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"}, { - RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"}, { - RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"}, { - RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"}, { - RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"}, { - RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17, - "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"}, { - R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"}, { - R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"}, { - R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"}, { - R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"}, { - R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"}, { - R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"}, { - R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"}, { - R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"}, { - R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"}, - { - R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"}, { - R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"}, { - R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"}, { - R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"}, { - R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"}, { - R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"}, - { - R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"}, { - R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"}, { - R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"}, { - R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"}, { - R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"}, { - R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"}, { - R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"}, { - R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"}, { - R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"}, { - R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"}, { - R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, { - R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, { - R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, { - R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, - { - R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, { - R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, { - R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, { - R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"}, { - R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"}, { - R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"}, { - R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"}, { - R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"}, { - R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"}, { - R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"}, { - R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, - "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, { - R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ - { - R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ - { - R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, { - R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, { - R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, { - R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"}, { - R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"}, { - R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"}, { - R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"}, { - R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"}, { - R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"}, { - R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"}, { - RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"}, { - RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"}, { - RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"}, { - R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"}, { - R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"}, - { - RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"}, { - RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"}, { - RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"}, { - RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"}, { - RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, { - RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, { - R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, + {RADEON_PP_MISC, 7, "RADEON_PP_MISC"}, + {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"}, + {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"}, + {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"}, + {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"}, + {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"}, + {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"}, + {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"}, + {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"}, + {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"}, + {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"}, + {RADEON_RE_MISC, 1, "RADEON_RE_MISC"}, + {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"}, + {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"}, + {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"}, + {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"}, + {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"}, + {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"}, + {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"}, + {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"}, + {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17, + "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"}, + {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"}, + {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"}, + {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"}, + {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"}, + {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"}, + {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"}, + {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"}, + {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"}, + {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"}, + {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"}, + {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"}, + {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"}, + {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"}, + {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"}, + {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"}, + {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"}, + {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"}, + {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"}, + {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"}, + {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"}, + {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"}, + {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"}, + {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"}, + {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"}, + {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"}, + {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, + {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, + {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, + {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, + "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, + {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, + {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, + {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, + {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"}, + {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"}, + {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"}, + {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"}, + {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"}, + {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"}, + {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"}, + {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, + "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, + {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ + {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ + {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, + {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, + {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, + {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"}, + {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"}, + {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"}, + {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"}, + {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"}, + {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"}, + {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"}, + {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"}, + {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"}, + {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"}, + {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"}, + {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"}, + {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"}, + {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"}, + {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"}, + {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"}, + {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, + {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, + {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, + {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */ + {R200_PP_AFS_1, 32, "R200_PP_AFS_1"}, + {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, + {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, + {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"}, + {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"}, + {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, + {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, + {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, }; /* ================================================================ * Performance monitoring functions */ static void radeon_clear_box(drm_radeon_private_t * dev_priv, int x, int y, int w, int h, int r, int g, int b) { u32 color; RING_LOCALS; x += dev_priv->sarea_priv->boxes[0].x1; y += dev_priv->sarea_priv->boxes[0].y1; switch (dev_priv->color_fmt) { case RADEON_COLOR_FORMAT_RGB565: color = (((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); break; case RADEON_COLOR_FORMAT_ARGB8888: default: color = (((0xff) << 24) | (r << 16) | (g << 8) | b); break; } BEGIN_RING(4); RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0)); OUT_RING(0xffffffff); ADVANCE_RING(); BEGIN_RING(6); OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4)); OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_SOLID_COLOR | (dev_priv->color_fmt << 8) | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); if (dev_priv->page_flipping && dev_priv->current_page == 1) { OUT_RING(dev_priv->front_pitch_offset); } else { OUT_RING(dev_priv->back_pitch_offset); } OUT_RING(color); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) { /* Collapse various things into a wait flag -- trying to * guess if userspase slept -- better just to have them tell us. */ if (dev_priv->stats.last_frame_reads > 1 || dev_priv->stats.last_clear_reads > dev_priv->stats.clears) { dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; } if (dev_priv->stats.freelist_loops) { dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; } /* Purple box for page flipping */ if (dev_priv->stats.boxes & RADEON_BOX_FLIP) radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255); /* Red box if we have to wait for idle at any point */ if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE) radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0); /* Blue box: lost context? */ /* Yellow box for texture swaps */ if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD) radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0); /* Green box if hardware never idles (as far as we can tell) */ if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0); /* Draw bars indicating number of buffers allocated * (not a great measure, easily confused) */ if (dev_priv->stats.requested_bufs) { if (dev_priv->stats.requested_bufs > 100) dev_priv->stats.requested_bufs = 100; radeon_clear_box(dev_priv, 4, 16, dev_priv->stats.requested_bufs, 4, 196, 128, 128); } memset(&dev_priv->stats, 0, sizeof(dev_priv->stats)); } /* ================================================================ * CP command dispatch functions */ static void radeon_cp_dispatch_clear(drm_device_t * dev, drm_radeon_clear_t * clear, drm_radeon_clear_rect_t * depth_boxes) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; unsigned int flags = clear->flags; u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0; int i; RING_LOCALS; DRM_DEBUG("flags = 0x%x\n", flags); dev_priv->stats.clears++; if (dev_priv->page_flipping && dev_priv->current_page == 1) { unsigned int tmp = flags; flags &= ~(RADEON_FRONT | RADEON_BACK); if (tmp & RADEON_FRONT) flags |= RADEON_BACK; if (tmp & RADEON_BACK) flags |= RADEON_FRONT; } if (flags & (RADEON_FRONT | RADEON_BACK)) { BEGIN_RING(4); /* Ensure the 3D stream is idle before doing a * 2D fill to clear the front or back buffer. */ RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0)); OUT_RING(clear->color_mask); ADVANCE_RING(); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { int x = pbox[i].x1; int y = pbox[i].y1; int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", x, y, w, h, flags); if (flags & RADEON_FRONT) { BEGIN_RING(6); OUT_RING(CP_PACKET3 (RADEON_CNTL_PAINT_MULTI, 4)); OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_SOLID_COLOR | (dev_priv-> color_fmt << 8) | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); OUT_RING(dev_priv->front_pitch_offset); OUT_RING(clear->clear_color); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } if (flags & RADEON_BACK) { BEGIN_RING(6); OUT_RING(CP_PACKET3 (RADEON_CNTL_PAINT_MULTI, 4)); OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_SOLID_COLOR | (dev_priv-> color_fmt << 8) | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); OUT_RING(dev_priv->back_pitch_offset); OUT_RING(clear->clear_color); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } } } /* hyper z clear */ /* no docs available, based on reverse engeneering by Stephane Marchesin */ if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) && (flags & RADEON_CLEAR_FASTZ)) { int i; int depthpixperline = dev_priv->depth_fmt==RADEON_DEPTH_FORMAT_16BIT_INT_Z? (dev_priv->depth_pitch / 2): (dev_priv->depth_pitch / 4); u32 clearmask; u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth | ((clear->depth_mask & 0xff) << 24); /* Make sure we restore the 3D state next time. * we haven't touched any "normal" state - still need this? */ dev_priv->sarea_priv->ctx_owner = 0; if ((dev_priv->flags & CHIP_HAS_HIERZ) && (flags & RADEON_USE_HIERZ)) { /* FIXME : reverse engineer that for Rx00 cards */ /* FIXME : the mask supposedly contains low-res z values. So can't set just to the max (0xff? or actually 0x3fff?), need to take z clear value into account? */ /* pattern seems to work for r100, though get slight rendering errors with glxgears. If hierz is not enabled for r100, only 4 bits which indicate clear (15,16,31,32, all zero) matter, the other ones are ignored, and the same clear mask can be used. That's very different behaviour than R200 which needs different clear mask and different number of tiles to clear if hierz is enabled or not !?! */ clearmask = (0xff<<22)|(0xff<<6)| 0x003f003f; } else { /* clear mask : chooses the clearing pattern. rv250: could be used to clear only parts of macrotiles (but that would get really complicated...)? bit 0 and 1 (either or both of them ?!?!) are used to not clear tile (or maybe one of the bits indicates if the tile is compressed or not), bit 2 and 3 to not clear tile 1,...,. Pattern is as follows: | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29| bits ------------------------------------------------- | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31| rv100: clearmask covers 2x8 4x1 tiles, but one clear still covers 256 pixels ?!? */ clearmask = 0x0; } BEGIN_RING( 8 ); RADEON_WAIT_UNTIL_2D_IDLE(); OUT_RING_REG( RADEON_RB3D_DEPTHCLEARVALUE, tempRB3D_DEPTHCLEARVALUE); /* what offset is this exactly ? */ OUT_RING_REG( RADEON_RB3D_ZMASKOFFSET, 0 ); /* need ctlstat, otherwise get some strange black flickering */ OUT_RING_REG( RADEON_RB3D_ZCACHE_CTLSTAT, RADEON_RB3D_ZC_FLUSH_ALL ); ADVANCE_RING(); for (i = 0; i < nbox; i++) { int tileoffset, nrtilesx, nrtilesy, j; /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ if ((dev_priv->flags&CHIP_HAS_HIERZ) && !(dev_priv->microcode_version==UCODE_R200)) { /* FIXME : figure this out for r200 (when hierz is enabled). Or maybe r200 actually doesn't need to put the low-res z value into the tile cache like r100, but just needs to clear the hi-level z-buffer? Works for R100, both with hierz and without. R100 seems to operate on 2x1 8x8 tiles, but... odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially problematic with resolutions which are not 64 pix aligned? */ tileoffset = ((pbox[i].y1 >> 3) * depthpixperline + pbox[i].x1) >> 6; nrtilesx = ((pbox[i].x2 & ~63) - (pbox[i].x1 & ~63)) >> 4; nrtilesy = (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3); for (j = 0; j <= nrtilesy; j++) { BEGIN_RING( 4 ); OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) ); /* first tile */ OUT_RING( tileoffset * 8 ); /* the number of tiles to clear */ OUT_RING( nrtilesx + 4 ); /* clear mask : chooses the clearing pattern. */ OUT_RING( clearmask ); ADVANCE_RING(); tileoffset += depthpixperline >> 6; } } else if (dev_priv->microcode_version==UCODE_R200) { /* works for rv250. */ /* find first macro tile (8x2 4x4 z-pixels on rv250) */ tileoffset = ((pbox[i].y1 >> 3) * depthpixperline + pbox[i].x1) >> 5; nrtilesx = (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5); nrtilesy = (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3); for (j = 0; j <= nrtilesy; j++) { BEGIN_RING( 4 ); OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) ); /* first tile */ /* judging by the first tile offset needed, could possibly directly address/clear 4x4 tiles instead of 8x2 * 4x4 macro tiles, though would still need clear mask for right/bottom if truely 4x4 granularity is desired ? */ OUT_RING( tileoffset * 16 ); /* the number of tiles to clear */ OUT_RING( nrtilesx + 1 ); /* clear mask : chooses the clearing pattern. */ OUT_RING( clearmask ); ADVANCE_RING(); tileoffset += depthpixperline >> 5; } } else { /* rv 100 */ /* rv100 might not need 64 pix alignment, who knows */ /* offsets are, hmm, weird */ tileoffset = ((pbox[i].y1 >> 4) * depthpixperline + pbox[i].x1) >> 6; nrtilesx = ((pbox[i].x2 & ~63) - (pbox[i].x1 & ~63)) >> 4; nrtilesy = (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4); for (j = 0; j <= nrtilesy; j++) { BEGIN_RING( 4 ); OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) ); OUT_RING( tileoffset * 128 ); /* the number of tiles to clear */ OUT_RING( nrtilesx + 4 ); /* clear mask : chooses the clearing pattern. */ OUT_RING( clearmask ); ADVANCE_RING(); tileoffset += depthpixperline >> 6; } } } /* TODO don't always clear all hi-level z tiles */ if ((dev_priv->flags & CHIP_HAS_HIERZ) && (dev_priv->microcode_version==UCODE_R200) && (flags & RADEON_USE_HIERZ)) /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ /* FIXME : the mask supposedly contains low-res z values. So can't set just to the max (0xff? or actually 0x3fff?), need to take z clear value into account? */ { BEGIN_RING( 4 ); OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_HIZ, 2 ) ); OUT_RING( 0x0 ); /* First tile */ OUT_RING( 0x3cc0 ); OUT_RING( (0xff<<22)|(0xff<<6)| 0x003f003f); ADVANCE_RING(); } } /* We have to clear the depth and/or stencil buffers by * rendering a quad into just those buffers. Thus, we have to * make sure the 3D engine is configured correctly. */ else if ((dev_priv->microcode_version == UCODE_R200) && (flags & (RADEON_DEPTH | RADEON_STENCIL))) { int tempPP_CNTL; int tempRE_CNTL; int tempRB3D_CNTL; int tempRB3D_ZSTENCILCNTL; int tempRB3D_STENCILREFMASK; int tempRB3D_PLANEMASK; int tempSE_CNTL; int tempSE_VTE_CNTL; int tempSE_VTX_FMT_0; int tempSE_VTX_FMT_1; int tempSE_VAP_CNTL; int tempRE_AUX_SCISSOR_CNTL; tempPP_CNTL = 0; tempRE_CNTL = 0; tempRB3D_CNTL = depth_clear->rb3d_cntl; tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; tempRB3D_STENCILREFMASK = 0x0; tempSE_CNTL = depth_clear->se_cntl; /* Disable TCL */ tempSE_VAP_CNTL = ( /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */ (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT)); tempRB3D_PLANEMASK = 0x0; tempRE_AUX_SCISSOR_CNTL = 0x0; tempSE_VTE_CNTL = SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK; /* Vertex format (X, Y, Z, W) */ tempSE_VTX_FMT_0 = SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK | SE_VTX_FMT_0__VTX_W0_PRESENT_MASK; tempSE_VTX_FMT_1 = 0x0; /* * Depth buffer specific enables */ if (flags & RADEON_DEPTH) { /* Enable depth buffer */ tempRB3D_CNTL |= RADEON_Z_ENABLE; } else { /* Disable depth buffer */ tempRB3D_CNTL &= ~RADEON_Z_ENABLE; } /* * Stencil buffer specific enables */ if (flags & RADEON_STENCIL) { tempRB3D_CNTL |= RADEON_STENCIL_ENABLE; tempRB3D_STENCILREFMASK = clear->depth_mask; } else { tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE; tempRB3D_STENCILREFMASK = 0x00000000; } if (flags & RADEON_USE_COMP_ZBUF) { tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE | RADEON_Z_DECOMPRESSION_ENABLE; } if (flags & RADEON_USE_HIERZ) { tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE; } BEGIN_RING(26); RADEON_WAIT_UNTIL_2D_IDLE(); OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL); OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL); OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL); OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL); OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, tempRB3D_STENCILREFMASK); OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK); OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL); OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL); OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0); OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1); OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL); OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL); ADVANCE_RING(); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { /* Funny that this should be required -- * sets top-left? */ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); BEGIN_RING(14); OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12)); OUT_RING((RADEON_PRIM_TYPE_RECT_LIST | RADEON_PRIM_WALK_RING | (3 << RADEON_NUM_VERTICES_SHIFT))); OUT_RING(depth_boxes[i].ui[CLEAR_X1]); OUT_RING(depth_boxes[i].ui[CLEAR_Y1]); OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); OUT_RING(0x3f800000); OUT_RING(depth_boxes[i].ui[CLEAR_X1]); OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); OUT_RING(0x3f800000); OUT_RING(depth_boxes[i].ui[CLEAR_X2]); OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); OUT_RING(0x3f800000); ADVANCE_RING(); } } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) { int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; rb3d_cntl = depth_clear->rb3d_cntl; if (flags & RADEON_DEPTH) { rb3d_cntl |= RADEON_Z_ENABLE; } else { rb3d_cntl &= ~RADEON_Z_ENABLE; } if (flags & RADEON_STENCIL) { rb3d_cntl |= RADEON_STENCIL_ENABLE; rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */ } else { rb3d_cntl &= ~RADEON_STENCIL_ENABLE; rb3d_stencilrefmask = 0x00000000; } if (flags & RADEON_USE_COMP_ZBUF) { tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE | RADEON_Z_DECOMPRESSION_ENABLE; } if (flags & RADEON_USE_HIERZ) { tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE; } BEGIN_RING(13); RADEON_WAIT_UNTIL_2D_IDLE(); OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1)); OUT_RING(0x00000000); OUT_RING(rb3d_cntl); OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL); OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask); OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000); OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl); ADVANCE_RING(); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { /* Funny that this should be required -- * sets top-left? */ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); BEGIN_RING(15); OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13)); OUT_RING(RADEON_VTX_Z_PRESENT | RADEON_VTX_PKCOLOR_PRESENT); OUT_RING((RADEON_PRIM_TYPE_RECT_LIST | RADEON_PRIM_WALK_RING | RADEON_MAOS_ENABLE | RADEON_VTX_FMT_RADEON_MODE | (3 << RADEON_NUM_VERTICES_SHIFT))); OUT_RING(depth_boxes[i].ui[CLEAR_X1]); OUT_RING(depth_boxes[i].ui[CLEAR_Y1]); OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); OUT_RING(0x0); OUT_RING(depth_boxes[i].ui[CLEAR_X1]); OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); OUT_RING(0x0); OUT_RING(depth_boxes[i].ui[CLEAR_X2]); OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); OUT_RING(0x0); ADVANCE_RING(); } } /* Increment the clear counter. The client-side 3D driver must * wait on this value before performing the clear ioctl. We * need this because the card's so damned fast... */ dev_priv->sarea_priv->last_clear++; BEGIN_RING(4); RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); } static void radeon_cp_dispatch_swap(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; int i; RING_LOCALS; DRM_DEBUG("\n"); /* Do some trivial performance monitoring... */ if (dev_priv->do_boxes) radeon_cp_performance_boxes(dev_priv); /* Wait for the 3D stream to idle before dispatching the bitblt. * This will prevent data corruption between the two streams. */ BEGIN_RING(2); RADEON_WAIT_UNTIL_3D_IDLE(); ADVANCE_RING(); for (i = 0; i < nbox; i++) { int x = pbox[i].x1; int y = pbox[i].y1; int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h); BEGIN_RING(7); OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_NONE | (dev_priv->color_fmt << 8) | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_S | RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); /* Make this work even if front & back are flipped: */ if (dev_priv->current_page == 0) { OUT_RING(dev_priv->back_pitch_offset); OUT_RING(dev_priv->front_pitch_offset); } else { OUT_RING(dev_priv->front_pitch_offset); OUT_RING(dev_priv->back_pitch_offset); } OUT_RING((x << 16) | y); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); ADVANCE_RING(); } /* Increment the frame counter. The client-side 3D driver must * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; BEGIN_RING(4); RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); } static void radeon_cp_dispatch_flip(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle; int offset = (dev_priv->current_page == 1) ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); /* Do some trivial performance monitoring... */ if (dev_priv->do_boxes) { dev_priv->stats.boxes |= RADEON_BOX_FLIP; radeon_cp_performance_boxes(dev_priv); } /* Update the frame offsets for both CRTCs */ BEGIN_RING(6); RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING_REG(RADEON_CRTC_OFFSET, ((sarea->frame.y * dev_priv->front_pitch + sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7) + offset); OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + offset); ADVANCE_RING(); /* Increment the frame counter. The client-side 3D driver must * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = 1 - dev_priv->current_page; BEGIN_RING(2); RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); ADVANCE_RING(); } static int bad_prim_vertex_nr(int primitive, int nr) { switch (primitive & RADEON_PRIM_TYPE_MASK) { case RADEON_PRIM_TYPE_NONE: case RADEON_PRIM_TYPE_POINT: return nr < 1; case RADEON_PRIM_TYPE_LINE: return (nr & 1) || nr == 0; case RADEON_PRIM_TYPE_LINE_STRIP: return nr < 2; case RADEON_PRIM_TYPE_TRI_LIST: case RADEON_PRIM_TYPE_3VRT_POINT_LIST: case RADEON_PRIM_TYPE_3VRT_LINE_LIST: case RADEON_PRIM_TYPE_RECT_LIST: return nr % 3 || nr == 0; case RADEON_PRIM_TYPE_TRI_FAN: case RADEON_PRIM_TYPE_TRI_STRIP: return nr < 3; default: return 1; } } typedef struct { unsigned int start; unsigned int finish; unsigned int prim; unsigned int numverts; unsigned int offset; unsigned int vc_format; } drm_radeon_tcl_prim_t; static void radeon_cp_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf, drm_radeon_tcl_prim_t * prim) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start; int numverts = (int)prim->numverts; int nbox = sarea_priv->nbox; int i = 0; RING_LOCALS; DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n", prim->prim, prim->vc_format, prim->start, prim->finish, prim->numverts); if (bad_prim_vertex_nr(prim->prim, prim->numverts)) { DRM_ERROR("bad prim %x numverts %d\n", prim->prim, prim->numverts); return; } do { /* Emit the next cliprect */ if (i < nbox) { radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); } /* Emit the vertex buffer rendering commands */ BEGIN_RING(5); OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3)); OUT_RING(offset); OUT_RING(numverts); OUT_RING(prim->vc_format); OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST | RADEON_COLOR_ORDER_RGBA | RADEON_VTX_FMT_RADEON_MODE | (numverts << RADEON_NUM_VERTICES_SHIFT)); ADVANCE_RING(); i++; } while (i < nbox); } static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; RING_LOCALS; buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ BEGIN_RING(2); RADEON_DISPATCH_AGE(buf_priv->age); ADVANCE_RING(); buf->pending = 1; buf->used = 0; } static void radeon_cp_dispatch_indirect(drm_device_t * dev, drm_buf_t * buf, int start, int end) { drm_radeon_private_t *dev_priv = dev->dev_private; RING_LOCALS; DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); if (start != end) { int offset = (dev_priv->gart_buffers_offset + buf->offset + start); int dwords = (end - start + 3) / sizeof(u32); /* Indirect buffer data must be an even number of * dwords, so if we've been given an odd number we must * pad the data with a Type-2 CP packet. */ if (dwords & 1) { u32 *data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset + start); data[dwords++] = RADEON_CP_PACKET2; } /* Fire off the indirect buffer */ BEGIN_RING(3); OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); OUT_RING(offset); OUT_RING(dwords); ADVANCE_RING(); } } static void radeon_cp_dispatch_indices(drm_device_t * dev, drm_buf_t * elt_buf, drm_radeon_tcl_prim_t * prim) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; int offset = dev_priv->gart_buffers_offset + prim->offset; u32 *data; int dwords; int i = 0; int start = prim->start + RADEON_INDEX_PRIM_OFFSET; int count = (prim->finish - start) / sizeof(u16); int nbox = sarea_priv->nbox; DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", prim->prim, prim->vc_format, prim->start, prim->finish, prim->offset, prim->numverts); if (bad_prim_vertex_nr(prim->prim, count)) { DRM_ERROR("bad prim %x count %d\n", prim->prim, count); return; } if (start >= prim->finish || (prim->start & 0x7)) { DRM_ERROR("buffer prim %d\n", prim->prim); return; } dwords = (prim->finish - prim->start + 3) / sizeof(u32); data = (u32 *) ((char *)dev->agp_buffer_map->handle + elt_buf->offset + prim->start); data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2); data[1] = offset; data[2] = prim->numverts; data[3] = prim->vc_format; data[4] = (prim->prim | RADEON_PRIM_WALK_IND | RADEON_COLOR_ORDER_RGBA | RADEON_VTX_FMT_RADEON_MODE | (count << RADEON_NUM_VERTICES_SHIFT)); do { if (i < nbox) radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); radeon_cp_dispatch_indirect(dev, elt_buf, prim->start, prim->finish); i++; } while (i < nbox); } #define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE static int radeon_cp_dispatch_texture(DRMFILE filp, drm_device_t * dev, drm_radeon_texture_t * tex, drm_radeon_tex_image_t * image) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_file_t *filp_priv; drm_buf_t *buf; u32 format; u32 *buffer; const u8 __user *data; int size, dwords, tex_width, blit_width, spitch; u32 height; int i; u32 texpitch, microtile; u32 offset; RING_LOCALS; DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) { DRM_ERROR("Invalid destination offset\n"); return DRM_ERR(EINVAL); } dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; /* Flush the pixel cache. This ensures no pixel data gets mixed * up with the texture data from the host data blit, otherwise * part of the texture image may be corrupted. */ BEGIN_RING(4); RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll * use a shift instead. */ switch (tex->format) { case RADEON_TXFORMAT_ARGB8888: case RADEON_TXFORMAT_RGBA8888: format = RADEON_COLOR_FORMAT_ARGB8888; tex_width = tex->width * 4; blit_width = image->width * 4; break; case RADEON_TXFORMAT_AI88: case RADEON_TXFORMAT_ARGB1555: case RADEON_TXFORMAT_RGB565: case RADEON_TXFORMAT_ARGB4444: case RADEON_TXFORMAT_VYUY422: case RADEON_TXFORMAT_YVYU422: format = RADEON_COLOR_FORMAT_RGB565; tex_width = tex->width * 2; blit_width = image->width * 2; break; case RADEON_TXFORMAT_I8: case RADEON_TXFORMAT_RGB332: format = RADEON_COLOR_FORMAT_CI8; tex_width = tex->width * 1; blit_width = image->width * 1; break; default: DRM_ERROR("invalid texture format %d\n", tex->format); return DRM_ERR(EINVAL); } spitch = blit_width >> 6; if (spitch == 0 && image->height > 1) return DRM_ERR(EINVAL); texpitch = tex->pitch; if ((texpitch << 22) & RADEON_DST_TILE_MICRO) { microtile = 1; if (tex_width < 64) { texpitch &= ~(RADEON_DST_TILE_MICRO >> 22); /* we got tiled coordinates, untile them */ image->x *= 2; } } else microtile = 0; DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width); do { DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", tex->offset >> 10, tex->pitch, tex->format, image->x, image->y, image->width, image->height); /* Make a copy of some parameters in case we have to * update them for a multi-pass texture blit. */ height = image->height; data = (const u8 __user *)image->data; size = height * blit_width; if (size > RADEON_MAX_TEXTURE_SIZE) { height = RADEON_MAX_TEXTURE_SIZE / blit_width; size = height * blit_width; } else if (size < 4 && size > 0) { size = 4; } else if (size == 0) { return 0; } buf = radeon_freelist_get(dev); if (0 && !buf) { radeon_do_cp_idle(dev_priv); buf = radeon_freelist_get(dev); } if (!buf) { DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n"); if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) return DRM_ERR(EFAULT); return DRM_ERR(EAGAIN); } /* Dispatch the indirect buffer. */ buffer = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); dwords = size / 4; if (microtile) { /* texture micro tiling in use, minimum texture width is thus 16 bytes. however, we cannot use blitter directly for texture width < 64 bytes, since minimum tex pitch is 64 bytes and we need this to match the texture width, otherwise the blitter will tile it wrong. Thus, tiling manually in this case. Additionally, need to special case tex height = 1, since our actual image will have height 2 and we need to ensure we don't read beyond the texture size from user space. */ if (tex->height == 1) { if (tex_width >= 64 || tex_width <= 16) { if (DRM_COPY_FROM_USER(buffer, data, tex_width * sizeof(u32))) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } } else if (tex_width == 32) { if (DRM_COPY_FROM_USER(buffer, data, 16)) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } if (DRM_COPY_FROM_USER(buffer + 8, data + 16, 16)) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } } } else if (tex_width >= 64 || tex_width == 16) { if (DRM_COPY_FROM_USER(buffer, data, dwords * sizeof(u32))) { DRM_ERROR("EFAULT on data, %d dwords\n", dwords); return DRM_ERR(EFAULT); } } else if (tex_width < 16) { for (i = 0; i < tex->height; i++) { if (DRM_COPY_FROM_USER(buffer, data, tex_width)) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } buffer += 4; data += tex_width; } } else if (tex_width == 32) { /* TODO: make sure this works when not fitting in one buffer (i.e. 32bytes x 2048...) */ for (i = 0; i < tex->height; i += 2) { if (DRM_COPY_FROM_USER(buffer, data, 16)) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } data += 16; if (DRM_COPY_FROM_USER(buffer + 8, data, 16)) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } data += 16; if (DRM_COPY_FROM_USER(buffer + 4, data, 16)) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } data += 16; if (DRM_COPY_FROM_USER(buffer + 12, data, 16)) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } data += 16; buffer += 16; } } } else { if (tex_width >= 32) { /* Texture image width is larger than the minimum, so we * can upload it directly. */ if (DRM_COPY_FROM_USER(buffer, data, dwords * sizeof(u32))) { DRM_ERROR("EFAULT on data, %d dwords\n", dwords); return DRM_ERR(EFAULT); } } else { /* Texture image width is less than the minimum, so we * need to pad out each image scanline to the minimum * width. */ for (i = 0; i < tex->height; i++) { if (DRM_COPY_FROM_USER(buffer, data, tex_width)) { DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width); return DRM_ERR(EFAULT); } buffer += 8; data += tex_width; } } } buf->filp = filp; buf->used = size; offset = dev_priv->gart_buffers_offset + buf->offset; BEGIN_RING(9); OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_NONE | (format << 8) | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_S | RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS ); OUT_RING((spitch << 22) | (offset >> 10)); OUT_RING((texpitch << 22) | (tex->offset >> 10)); OUT_RING(0); OUT_RING((image->x << 16) | image->y); OUT_RING((image->width << 16) | height); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); radeon_cp_discard_buffer(dev, buf); /* Update the input parameters for next time */ image->y += height; image->height -= height; image->data = (const u8 __user *)image->data + size; } while (image->height > 0); /* Flush the pixel cache after the blit completes. This ensures * the texture data is written out to memory before rendering * continues. */ BEGIN_RING(4); RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); return 0; } static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple) { drm_radeon_private_t *dev_priv = dev->dev_private; int i; RING_LOCALS; DRM_DEBUG("\n"); BEGIN_RING(35); OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0)); OUT_RING(0x00000000); OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31)); for (i = 0; i < 32; i++) { OUT_RING(stipple[i]); } ADVANCE_RING(); } static void radeon_apply_surface_regs(int surf_index, drm_radeon_private_t *dev_priv) { if (!dev_priv->mmio) return; radeon_do_cp_idle(dev_priv); RADEON_WRITE(RADEON_SURFACE0_INFO + 16*surf_index, dev_priv->surfaces[surf_index].flags); RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*surf_index, dev_priv->surfaces[surf_index].lower); RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*surf_index, dev_priv->surfaces[surf_index].upper); } /* Allocates a virtual surface * doesn't always allocate a real surface, will stretch an existing * surface when possible. * * Note that refcount can be at most 2, since during a free refcount=3 * might mean we have to allocate a new surface which might not always * be available. * For example : we allocate three contigous surfaces ABC. If B is * freed, we suddenly need two surfaces to store A and C, which might * not always be available. */ static int alloc_surface(drm_radeon_surface_alloc_t* new, drm_radeon_private_t *dev_priv, DRMFILE filp) { struct radeon_virt_surface *s; int i; int virt_surface_index; uint32_t new_upper, new_lower; new_lower = new->address; new_upper = new_lower + new->size - 1; /* sanity check */ if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) || ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) != RADEON_SURF_ADDRESS_FIXED_MASK) || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0)) return -1; /* make sure there is no overlap with existing surfaces */ for (i = 0; i < RADEON_MAX_SURFACES; i++) { if ((dev_priv->surfaces[i].refcount != 0) && (( (new_lower >= dev_priv->surfaces[i].lower) && (new_lower < dev_priv->surfaces[i].upper) ) || ( (new_lower < dev_priv->surfaces[i].lower) && (new_upper > dev_priv->surfaces[i].lower) )) ){ return -1;} } /* find a virtual surface */ for (i = 0; i < 2*RADEON_MAX_SURFACES; i++) if (dev_priv->virt_surfaces[i].filp == 0) break; if (i == 2*RADEON_MAX_SURFACES) { return -1;} virt_surface_index = i; /* try to reuse an existing surface */ for (i = 0; i < RADEON_MAX_SURFACES; i++) { /* extend before */ if ((dev_priv->surfaces[i].refcount == 1) && (new->flags == dev_priv->surfaces[i].flags) && (new_upper + 1 == dev_priv->surfaces[i].lower)) { s = &(dev_priv->virt_surfaces[virt_surface_index]); s->surface_index = i; s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; s->filp = filp; dev_priv->surfaces[i].refcount++; dev_priv->surfaces[i].lower = s->lower; radeon_apply_surface_regs(s->surface_index, dev_priv); return virt_surface_index; } /* extend after */ if ((dev_priv->surfaces[i].refcount == 1) && (new->flags == dev_priv->surfaces[i].flags) && (new_lower == dev_priv->surfaces[i].upper + 1)) { s = &(dev_priv->virt_surfaces[virt_surface_index]); s->surface_index = i; s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; s->filp = filp; dev_priv->surfaces[i].refcount++; dev_priv->surfaces[i].upper = s->upper; radeon_apply_surface_regs(s->surface_index, dev_priv); return virt_surface_index; } } /* okay, we need a new one */ for (i = 0; i < RADEON_MAX_SURFACES; i++) { if (dev_priv->surfaces[i].refcount == 0) { s = &(dev_priv->virt_surfaces[virt_surface_index]); s->surface_index = i; s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; s->filp = filp; dev_priv->surfaces[i].refcount = 1; dev_priv->surfaces[i].lower = s->lower; dev_priv->surfaces[i].upper = s->upper; dev_priv->surfaces[i].flags = s->flags; radeon_apply_surface_regs(s->surface_index, dev_priv); return virt_surface_index; } } /* we didn't find anything */ return -1; } static int free_surface(DRMFILE filp, drm_radeon_private_t *dev_priv, int lower) { struct radeon_virt_surface *s; int i; /* find the virtual surface */ for(i = 0; i < 2*RADEON_MAX_SURFACES; i++) { s = &(dev_priv->virt_surfaces[i]); if (s->filp) { if ((lower == s->lower) && (filp == s->filp)) { if (dev_priv->surfaces[s->surface_index].lower == s->lower) dev_priv->surfaces[s->surface_index].lower = s->upper; if (dev_priv->surfaces[s->surface_index].upper == s->upper) dev_priv->surfaces[s->surface_index].upper = s->lower; dev_priv->surfaces[s->surface_index].refcount--; if (dev_priv->surfaces[s->surface_index].refcount == 0) dev_priv->surfaces[s->surface_index].flags = 0; s->filp = 0; radeon_apply_surface_regs(s->surface_index, dev_priv); return 0; } } } return 1; } static void radeon_surfaces_release(DRMFILE filp, drm_radeon_private_t *dev_priv) { int i; for( i = 0; i < 2*RADEON_MAX_SURFACES; i++) { if (dev_priv->virt_surfaces[i].filp == filp) free_surface(filp, dev_priv, dev_priv->virt_surfaces[i].lower); } } /* ================================================================ * IOCTL functions */ static int radeon_surface_alloc(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_alloc_t alloc; if (!dev_priv) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_surface_alloc_t __user *)data, sizeof(alloc)); if (alloc_surface(&alloc, dev_priv, filp) == -1) return DRM_ERR(EINVAL); else return 0; } static int radeon_surface_free(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_free_t memfree; if (!dev_priv) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *)data, sizeof(memfree) ); if (free_surface(filp, dev_priv, memfree.address)) return DRM_ERR(EINVAL); else return 0; } static int radeon_cp_clear(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_radeon_clear_t clear; drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data, sizeof(clear)); RING_SPACE_TEST_WITH_RETURN(dev_priv); if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes, sarea_priv->nbox * sizeof(depth_boxes[0]))) return DRM_ERR(EFAULT); radeon_cp_dispatch_clear(dev, &clear, depth_boxes); COMMIT_RING(); return 0; } /* Not sure why this isn't set all the time: */ static int radeon_do_init_pageflip(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; RING_LOCALS; DRM_DEBUG("\n"); BEGIN_RING(6); RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0)); OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) | RADEON_CRTC_OFFSET_FLIP_CNTL); OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0)); OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) | RADEON_CRTC_OFFSET_FLIP_CNTL); ADVANCE_RING(); dev_priv->page_flipping = 1; dev_priv->current_page = 0; dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; return 0; } /* Called whenever a client dies, from drm_release. * NOTE: Lock isn't necessarily held when this is called! */ static int radeon_do_cleanup_pageflip(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); if (dev_priv->current_page != 0) radeon_cp_dispatch_flip(dev); dev_priv->page_flipping = 0; return 0; } /* Swapping and flipping are different operations, need different ioctls. * They can & should be intermixed to support multiple 3d windows. */ static int radeon_cp_flip(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); RING_SPACE_TEST_WITH_RETURN(dev_priv); if (!dev_priv->page_flipping) radeon_do_init_pageflip(dev); radeon_cp_dispatch_flip(dev); COMMIT_RING(); return 0; } static int radeon_cp_swap(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); RING_SPACE_TEST_WITH_RETURN(dev_priv); if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; radeon_cp_dispatch_swap(dev); dev_priv->sarea_priv->ctx_owner = 0; COMMIT_RING(); return 0; } static int radeon_cp_vertex(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_file_t *filp_priv; - drm_radeon_sarea_t *sarea_priv; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_radeon_vertex_t vertex; drm_radeon_tcl_prim_t prim; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } - sarea_priv = dev_priv->sarea_priv; DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, sizeof(vertex)); DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard); if (vertex.idx < 0 || vertex.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", vertex.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { DRM_ERROR("buffer prim %d\n", vertex.prim); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); buf = dma->buflist[vertex.idx]; if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", vertex.idx); return DRM_ERR(EINVAL); } /* Build up a prim_t record: */ if (vertex.count) { buf->used = vertex.count; /* not used? */ if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { if (radeon_emit_state(dev_priv, filp_priv, &sarea_priv->context_state, sarea_priv->tex_state, sarea_priv->dirty)) { DRM_ERROR("radeon_emit_state failed\n"); return DRM_ERR(EINVAL); } sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | RADEON_UPLOAD_TEX1IMAGES | RADEON_UPLOAD_TEX2IMAGES | RADEON_REQUIRE_QUIESCENCE); } prim.start = 0; prim.finish = vertex.count; /* unused */ prim.prim = vertex.prim; prim.numverts = vertex.count; prim.vc_format = dev_priv->sarea_priv->vc_format; radeon_cp_dispatch_vertex(dev, buf, &prim); } if (vertex.discard) { radeon_cp_discard_buffer(dev, buf); } COMMIT_RING(); return 0; } static int radeon_cp_indices(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_file_t *filp_priv; - drm_radeon_sarea_t *sarea_priv; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_radeon_indices_t elts; drm_radeon_tcl_prim_t prim; int count; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } - sarea_priv = dev_priv->sarea_priv; DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data, sizeof(elts)); DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n", DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard); if (elts.idx < 0 || elts.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", elts.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { DRM_ERROR("buffer prim %d\n", elts.prim); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); buf = dma->buflist[elts.idx]; if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", elts.idx); return DRM_ERR(EINVAL); } count = (elts.end - elts.start) / sizeof(u16); elts.start -= RADEON_INDEX_PRIM_OFFSET; if (elts.start & 0x7) { DRM_ERROR("misaligned buffer 0x%x\n", elts.start); return DRM_ERR(EINVAL); } if (elts.start < buf->used) { DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used); return DRM_ERR(EINVAL); } buf->used = elts.end; if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { if (radeon_emit_state(dev_priv, filp_priv, &sarea_priv->context_state, sarea_priv->tex_state, sarea_priv->dirty)) { DRM_ERROR("radeon_emit_state failed\n"); return DRM_ERR(EINVAL); } sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | RADEON_UPLOAD_TEX1IMAGES | RADEON_UPLOAD_TEX2IMAGES | RADEON_REQUIRE_QUIESCENCE); } /* Build up a prim_t record: */ prim.start = elts.start; prim.finish = elts.end; prim.prim = elts.prim; prim.offset = 0; /* offset from start of dma buffers */ prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ prim.vc_format = dev_priv->sarea_priv->vc_format; radeon_cp_dispatch_indices(dev, buf, &prim); if (elts.discard) { radeon_cp_discard_buffer(dev, buf); } COMMIT_RING(); return 0; } static int radeon_cp_texture(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_texture_t tex; drm_radeon_tex_image_t image; int ret; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data, sizeof(tex)); if (tex.image == NULL) { DRM_ERROR("null texture image!\n"); return DRM_ERR(EINVAL); } if (DRM_COPY_FROM_USER(&image, (drm_radeon_tex_image_t __user *) tex.image, sizeof(image))) return DRM_ERR(EFAULT); RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image); COMMIT_RING(); return ret; } static int radeon_cp_stipple(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_stipple_t stipple; u32 mask[32]; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data, sizeof(stipple)); if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32))) return DRM_ERR(EFAULT); RING_SPACE_TEST_WITH_RETURN(dev_priv); radeon_cp_dispatch_stipple(dev, mask); COMMIT_RING(); return 0; } static int radeon_cp_indirect(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_radeon_indirect_t indirect; RING_LOCALS; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(indirect, (drm_radeon_indirect_t __user *) data, sizeof(indirect)); DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n", indirect.idx, indirect.start, indirect.end, indirect.discard); if (indirect.idx < 0 || indirect.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", indirect.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } buf = dma->buflist[indirect.idx]; if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", indirect.idx); return DRM_ERR(EINVAL); } if (indirect.start < buf->used) { DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", indirect.start, buf->used); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); buf->used = indirect.end; /* Wait for the 3D stream to idle before the indirect buffer * containing 2D acceleration commands is processed. */ BEGIN_RING(2); RADEON_WAIT_UNTIL_3D_IDLE(); ADVANCE_RING(); /* Dispatch the indirect buffer full of commands from the * X server. This is insecure and is thus only available to * privileged clients. */ radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end); if (indirect.discard) { radeon_cp_discard_buffer(dev, buf); } COMMIT_RING(); return 0; } static int radeon_cp_vertex2(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_file_t *filp_priv; - drm_radeon_sarea_t *sarea_priv; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_radeon_vertex2_t vertex; int i; unsigned char laststate; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } - sarea_priv = dev_priv->sarea_priv; DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data, sizeof(vertex)); DRM_DEBUG("pid=%d index=%d discard=%d\n", DRM_CURRENTPID, vertex.idx, vertex.discard); if (vertex.idx < 0 || vertex.idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", vertex.idx, dma->buf_count - 1); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); buf = dma->buflist[vertex.idx]; if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp); return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", vertex.idx); return DRM_ERR(EINVAL); } if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) return DRM_ERR(EINVAL); for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) { drm_radeon_prim_t prim; drm_radeon_tcl_prim_t tclprim; if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim))) return DRM_ERR(EFAULT); if (prim.stateidx != laststate) { drm_radeon_state_t state; if (DRM_COPY_FROM_USER(&state, &vertex.state[prim.stateidx], sizeof(state))) return DRM_ERR(EFAULT); if (radeon_emit_state2(dev_priv, filp_priv, &state)) { DRM_ERROR("radeon_emit_state2 failed\n"); return DRM_ERR(EINVAL); } laststate = prim.stateidx; } tclprim.start = prim.start; tclprim.finish = prim.finish; tclprim.prim = prim.prim; tclprim.vc_format = prim.vc_format; if (prim.prim & RADEON_PRIM_WALK_IND) { tclprim.offset = prim.numverts * 64; tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ radeon_cp_dispatch_indices(dev, buf, &tclprim); } else { tclprim.numverts = prim.numverts; tclprim.offset = 0; /* not used */ radeon_cp_dispatch_vertex(dev, buf, &tclprim); } if (sarea_priv->nbox == 1) sarea_priv->nbox = 0; } if (vertex.discard) { radeon_cp_discard_buffer(dev, buf); } COMMIT_RING(); return 0; } static int radeon_emit_packets(drm_radeon_private_t * dev_priv, drm_file_t * filp_priv, drm_radeon_cmd_header_t header, drm_radeon_cmd_buffer_t * cmdbuf) { int id = (int)header.packet.packet_id; int sz, reg; int *data = (int *)cmdbuf->buf; RING_LOCALS; if (id >= RADEON_MAX_STATE_PACKETS) return DRM_ERR(EINVAL); sz = packet[id].len; reg = packet[id].start; if (sz * sizeof(int) > cmdbuf->bufsz) { DRM_ERROR("Packet size provided larger than data provided\n"); return DRM_ERR(EINVAL); } if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) { DRM_ERROR("Packet verification failed\n"); return DRM_ERR(EINVAL); } BEGIN_RING(sz + 1); OUT_RING(CP_PACKET0(reg, (sz - 1))); OUT_RING_TABLE(data, sz); ADVANCE_RING(); cmdbuf->buf += sz * sizeof(int); cmdbuf->bufsz -= sz * sizeof(int); return 0; } static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv, drm_radeon_cmd_header_t header, drm_radeon_cmd_buffer_t * cmdbuf) { int sz = header.scalars.count; int start = header.scalars.offset; int stride = header.scalars.stride; RING_LOCALS; BEGIN_RING(3 + sz); OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); OUT_RING_TABLE(cmdbuf->buf, sz); ADVANCE_RING(); cmdbuf->buf += sz * sizeof(int); cmdbuf->bufsz -= sz * sizeof(int); return 0; } /* God this is ugly */ static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv, drm_radeon_cmd_header_t header, drm_radeon_cmd_buffer_t * cmdbuf) { int sz = header.scalars.count; int start = ((unsigned int)header.scalars.offset) + 0x100; int stride = header.scalars.stride; RING_LOCALS; BEGIN_RING(3 + sz); OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); OUT_RING_TABLE(cmdbuf->buf, sz); ADVANCE_RING(); cmdbuf->buf += sz * sizeof(int); cmdbuf->bufsz -= sz * sizeof(int); return 0; } static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv, drm_radeon_cmd_header_t header, drm_radeon_cmd_buffer_t * cmdbuf) { int sz = header.vectors.count; int start = header.vectors.offset; int stride = header.vectors.stride; RING_LOCALS; BEGIN_RING(3 + sz); OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); OUT_RING_TABLE(cmdbuf->buf, sz); ADVANCE_RING(); cmdbuf->buf += sz * sizeof(int); cmdbuf->bufsz -= sz * sizeof(int); return 0; } static int radeon_emit_packet3(drm_device_t * dev, drm_file_t * filp_priv, drm_radeon_cmd_buffer_t * cmdbuf) { drm_radeon_private_t *dev_priv = dev->dev_private; unsigned int cmdsz; int ret; RING_LOCALS; DRM_DEBUG("\n"); if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv, cmdbuf, &cmdsz))) { DRM_ERROR("Packet verification failed\n"); return ret; } BEGIN_RING(cmdsz); OUT_RING_TABLE(cmdbuf->buf, cmdsz); ADVANCE_RING(); cmdbuf->buf += cmdsz * 4; cmdbuf->bufsz -= cmdsz * 4; return 0; } static int radeon_emit_packet3_cliprect(drm_device_t * dev, drm_file_t * filp_priv, drm_radeon_cmd_buffer_t * cmdbuf, int orig_nbox) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_clip_rect_t box; unsigned int cmdsz; int ret; drm_clip_rect_t __user *boxes = cmdbuf->boxes; int i = 0; RING_LOCALS; DRM_DEBUG("\n"); if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv, cmdbuf, &cmdsz))) { DRM_ERROR("Packet verification failed\n"); return ret; } if (!orig_nbox) goto out; do { if (i < cmdbuf->nbox) { if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box))) return DRM_ERR(EFAULT); /* FIXME The second and subsequent times round * this loop, send a WAIT_UNTIL_3D_IDLE before * calling emit_clip_rect(). This fixes a * lockup on fast machines when sending * several cliprects with a cmdbuf, as when * waving a 2D window over a 3D * window. Something in the commands from user * space seems to hang the card when they're * sent several times in a row. That would be * the correct place to fix it but this works * around it until I can figure that out - Tim * Smith */ if (i) { BEGIN_RING(2); RADEON_WAIT_UNTIL_3D_IDLE(); ADVANCE_RING(); } radeon_emit_clip_rect(dev_priv, &box); } BEGIN_RING(cmdsz); OUT_RING_TABLE(cmdbuf->buf, cmdsz); ADVANCE_RING(); } while (++i < cmdbuf->nbox); if (cmdbuf->nbox == 1) cmdbuf->nbox = 0; out: cmdbuf->buf += cmdsz * 4; cmdbuf->bufsz -= cmdsz * 4; return 0; } static int radeon_emit_wait(drm_device_t * dev, int flags) { drm_radeon_private_t *dev_priv = dev->dev_private; RING_LOCALS; DRM_DEBUG("%s: %x\n", __FUNCTION__, flags); switch (flags) { case RADEON_WAIT_2D: BEGIN_RING(2); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); break; case RADEON_WAIT_3D: BEGIN_RING(2); RADEON_WAIT_UNTIL_3D_IDLE(); ADVANCE_RING(); break; case RADEON_WAIT_2D | RADEON_WAIT_3D: BEGIN_RING(2); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); break; default: return DRM_ERR(EINVAL); } return 0; } static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_file_t *filp_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf = NULL; int idx; drm_radeon_cmd_buffer_t cmdbuf; drm_radeon_cmd_header_t header; int orig_nbox, orig_bufsz; char *kbuf = NULL; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_radeon_cmd_buffer_t __user *) data, sizeof(cmdbuf)); RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) { return DRM_ERR(EINVAL); } /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid * races between checking values and using those values in other code, * and simply to avoid a lot of function calls to copy in data. */ orig_bufsz = cmdbuf.bufsz; if (orig_bufsz != 0) { kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER); if (kbuf == NULL) return DRM_ERR(ENOMEM); if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz)) { drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); return DRM_ERR(EFAULT); } cmdbuf.buf = kbuf; } orig_nbox = cmdbuf.nbox; if(dev_priv->microcode_version == UCODE_R300) { int temp; temp=r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf); if (orig_bufsz != 0) drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); return temp; } /* microcode_version != r300 */ while (cmdbuf.bufsz >= sizeof(header)) { header.i = *(int *)cmdbuf.buf; cmdbuf.buf += sizeof(header); cmdbuf.bufsz -= sizeof(header); switch (header.header.cmd_type) { case RADEON_CMD_PACKET: DRM_DEBUG("RADEON_CMD_PACKET\n"); if (radeon_emit_packets (dev_priv, filp_priv, header, &cmdbuf)) { DRM_ERROR("radeon_emit_packets failed\n"); goto err; } break; case RADEON_CMD_SCALARS: DRM_DEBUG("RADEON_CMD_SCALARS\n"); if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) { DRM_ERROR("radeon_emit_scalars failed\n"); goto err; } break; case RADEON_CMD_VECTORS: DRM_DEBUG("RADEON_CMD_VECTORS\n"); if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) { DRM_ERROR("radeon_emit_vectors failed\n"); goto err; } break; case RADEON_CMD_DMA_DISCARD: DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); idx = header.dma.buf_idx; if (idx < 0 || idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", idx, dma->buf_count - 1); goto err; } buf = dma->buflist[idx]; if (buf->filp != filp || buf->pending) { DRM_ERROR("bad buffer %p %p %d\n", buf->filp, filp, buf->pending); goto err; } radeon_cp_discard_buffer(dev, buf); break; case RADEON_CMD_PACKET3: DRM_DEBUG("RADEON_CMD_PACKET3\n"); if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) { DRM_ERROR("radeon_emit_packet3 failed\n"); goto err; } break; case RADEON_CMD_PACKET3_CLIP: DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); if (radeon_emit_packet3_cliprect (dev, filp_priv, &cmdbuf, orig_nbox)) { DRM_ERROR("radeon_emit_packet3_clip failed\n"); goto err; } break; case RADEON_CMD_SCALARS2: DRM_DEBUG("RADEON_CMD_SCALARS2\n"); if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) { DRM_ERROR("radeon_emit_scalars2 failed\n"); goto err; } break; case RADEON_CMD_WAIT: DRM_DEBUG("RADEON_CMD_WAIT\n"); if (radeon_emit_wait(dev, header.wait.flags)) { DRM_ERROR("radeon_emit_wait failed\n"); goto err; } break; default: DRM_ERROR("bad cmd_type %d at %p\n", header.header.cmd_type, cmdbuf.buf - sizeof(header)); goto err; } } if (orig_bufsz != 0) drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); DRM_DEBUG("DONE\n"); COMMIT_RING(); return 0; err: if (orig_bufsz != 0) drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); return DRM_ERR(EINVAL); } static int radeon_cp_getparam(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_getparam_t param; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data, sizeof(param)); DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); switch (param.param) { case RADEON_PARAM_GART_BUFFER_OFFSET: value = dev_priv->gart_buffers_offset; break; case RADEON_PARAM_LAST_FRAME: dev_priv->stats.last_frame_reads++; value = GET_SCRATCH(0); break; case RADEON_PARAM_LAST_DISPATCH: value = GET_SCRATCH(1); break; case RADEON_PARAM_LAST_CLEAR: dev_priv->stats.last_clear_reads++; value = GET_SCRATCH(2); break; case RADEON_PARAM_IRQ_NR: value = dev->irq; break; case RADEON_PARAM_GART_BASE: value = dev_priv->gart_vm_start; break; case RADEON_PARAM_REGISTER_HANDLE: - value = dev_priv->mmio_offset; + value = dev_priv->mmio->offset; break; case RADEON_PARAM_STATUS_HANDLE: value = dev_priv->ring_rptr_offset; break; #if BITS_PER_LONG == 32 /* * This ioctl() doesn't work on 64-bit platforms because hw_lock is a * pointer which can't fit into an int-sized variable. According to * Michel Dänzer, the ioctl() is only used on embedded platforms, so * not supporting it shouldn't be a problem. If the same functionality * is needed on 64-bit platforms, a new ioctl() would have to be added, * so backwards-compatibility for the embedded platforms can be * maintained. --davidm 4-Feb-2004. */ case RADEON_PARAM_SAREA_HANDLE: /* The lock is the first dword in the sarea. */ value = (long)dev->lock.hw_lock; break; #endif case RADEON_PARAM_GART_TEX_HANDLE: value = dev_priv->gart_textures_offset; break; default: return DRM_ERR(EINVAL); } if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; } static int radeon_cp_setparam(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_file_t *filp_priv; drm_radeon_setparam_t sp; struct drm_radeon_driver_file_fields *radeon_priv; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data, sizeof(sp)); switch (sp.param) { case RADEON_SETPARAM_FB_LOCATION: radeon_priv = filp_priv->driver_priv; radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value; break; case RADEON_SETPARAM_SWITCH_TILING: if (sp.value == 0) { DRM_DEBUG( "color tiling disabled\n" ); dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO; dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO; dev_priv->sarea_priv->tiling_enabled = 0; } else if (sp.value == 1) { DRM_DEBUG( "color tiling enabled\n" ); dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO; dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO; dev_priv->sarea_priv->tiling_enabled = 1; } break; + case RADEON_SETPARAM_PCIGART_LOCATION: + dev_priv->pcigart_offset = sp.value; + break; default: DRM_DEBUG("Invalid parameter %d\n", sp.param); return DRM_ERR(EINVAL); } return 0; } /* When a client dies: * - Check for and clean up flipped page state * - Free any alloced GART memory. * - Free any alloced radeon surfaces. * * DRM infrastructure takes care of reclaiming dma buffers. */ -void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp) +void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp) { if (dev->dev_private) { drm_radeon_private_t *dev_priv = dev->dev_private; if (dev_priv->page_flipping) { radeon_do_cleanup_pageflip(dev); } radeon_mem_release(filp, dev_priv->gart_heap); radeon_mem_release(filp, dev_priv->fb_heap); radeon_surfaces_release(filp, dev_priv); } } -void radeon_driver_pretakedown(drm_device_t * dev) +void radeon_driver_lastclose(drm_device_t * dev) { radeon_do_release(dev); } -int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv) +int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_radeon_driver_file_fields *radeon_priv; DRM_DEBUG("\n"); radeon_priv = (struct drm_radeon_driver_file_fields *) drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES); if (!radeon_priv) return -ENOMEM; filp_priv->driver_priv = radeon_priv; if (dev_priv) radeon_priv->radeon_fb_delta = dev_priv->fb_location; else radeon_priv->radeon_fb_delta = 0; return 0; } -void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv) +void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv) { struct drm_radeon_driver_file_fields *radeon_priv = filp_priv->driver_priv; drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES); } drm_ioctl_desc_t radeon_ioctls[] = { - [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, 1, 1}, - [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, 1, 1}, - [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, 1, 1}, - [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, 1, 1}, - [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, 1, 1}, - [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, 1, 1}, - [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, 1, 0}, - [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, 1, 0} + [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, DRM_AUTH} }; int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); Index: head/sys/dev/drm/savage_bci.c =================================================================== --- head/sys/dev/drm/savage_bci.c (revision 152908) +++ head/sys/dev/drm/savage_bci.c (revision 152909) @@ -1,1089 +1,1113 @@ /* savage_bci.c -- BCI support for Savage * * Copyright 2004 Felix Kuehling * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ -#include "drmP.h" -#include "savage_drm.h" -#include "savage_drv.h" +#include +__FBSDID("$FreeBSD$"); +#include "dev/drm/drmP.h" +#include "dev/drm/savage_drm.h" +#include "dev/drm/savage_drv.h" /* Need a long timeout for shadow status updates can take a while * and so can waiting for events when the queue is full. */ #define SAVAGE_DEFAULT_USEC_TIMEOUT 1000000 /* 1s */ #define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */ #define SAVAGE_FREELIST_DEBUG 0 static int savage_bci_wait_fifo_shadow(drm_savage_private_t *dev_priv, unsigned int n) { uint32_t mask = dev_priv->status_used_mask; uint32_t threshold = dev_priv->bci_threshold_hi; uint32_t status; int i; #if SAVAGE_BCI_DEBUG if (n > dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - threshold) DRM_ERROR("Trying to emit %d words " "(more than guaranteed space in COB)\n", n); #endif for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) { DRM_MEMORYBARRIER(); status = dev_priv->status_ptr[0]; if ((status & mask) < threshold) return 0; DRM_UDELAY(1); } #if SAVAGE_BCI_DEBUG DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x, threshold=0x%08x\n", status, threshold); #endif return DRM_ERR(EBUSY); } static int savage_bci_wait_fifo_s3d(drm_savage_private_t *dev_priv, unsigned int n) { uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n; uint32_t status; int i; for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) { status = SAVAGE_READ(SAVAGE_STATUS_WORD0); if ((status & SAVAGE_FIFO_USED_MASK_S3D) <= maxUsed) return 0; DRM_UDELAY(1); } #if SAVAGE_BCI_DEBUG DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x\n", status); #endif return DRM_ERR(EBUSY); } static int savage_bci_wait_fifo_s4(drm_savage_private_t *dev_priv, unsigned int n) { uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n; uint32_t status; int i; for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) { status = SAVAGE_READ(SAVAGE_ALT_STATUS_WORD0); if ((status & SAVAGE_FIFO_USED_MASK_S4) <= maxUsed) return 0; DRM_UDELAY(1); } #if SAVAGE_BCI_DEBUG DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x\n", status); #endif return DRM_ERR(EBUSY); } /* * Waiting for events. * * The BIOSresets the event tag to 0 on mode changes. Therefore we * never emit 0 to the event tag. If we find a 0 event tag we know the * BIOS stomped on it and return success assuming that the BIOS waited * for engine idle. * * Note: if the Xserver uses the event tag it has to follow the same * rule. Otherwise there may be glitches every 2^16 events. */ static int savage_bci_wait_event_shadow(drm_savage_private_t *dev_priv, uint16_t e) { uint32_t status; int i; for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) { DRM_MEMORYBARRIER(); status = dev_priv->status_ptr[1]; if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff || (status & 0xffff) == 0) return 0; DRM_UDELAY(1); } #if SAVAGE_BCI_DEBUG DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e); #endif return DRM_ERR(EBUSY); } static int savage_bci_wait_event_reg(drm_savage_private_t *dev_priv, uint16_t e) { uint32_t status; int i; for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) { status = SAVAGE_READ(SAVAGE_STATUS_WORD1); if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff || (status & 0xffff) == 0) return 0; DRM_UDELAY(1); } #if SAVAGE_BCI_DEBUG DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e); #endif return DRM_ERR(EBUSY); } uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv, unsigned int flags) { - BCI_LOCALS; uint16_t count; + BCI_LOCALS; if (dev_priv->status_ptr) { /* coordinate with Xserver */ count = dev_priv->status_ptr[1023]; if (count < dev_priv->event_counter) dev_priv->event_wrap++; } else { count = dev_priv->event_counter; } count = (count + 1) & 0xffff; if (count == 0) { count++; /* See the comment above savage_wait_event_*. */ dev_priv->event_wrap++; } dev_priv->event_counter = count; if (dev_priv->status_ptr) dev_priv->status_ptr[1023] = (uint32_t)count; if ((flags & (SAVAGE_WAIT_2D | SAVAGE_WAIT_3D))) { unsigned int wait_cmd = BCI_CMD_WAIT; if ((flags & SAVAGE_WAIT_2D)) wait_cmd |= BCI_CMD_WAIT_2D; if ((flags & SAVAGE_WAIT_3D)) wait_cmd |= BCI_CMD_WAIT_3D; BEGIN_BCI(2); BCI_WRITE(wait_cmd); } else { BEGIN_BCI(1); } BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t)count); return count; } /* * Freelist management */ static int savage_freelist_init(drm_device_t *dev) { drm_savage_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_savage_buf_priv_t *entry; int i; DRM_DEBUG("count=%d\n", dma->buf_count); dev_priv->head.next = &dev_priv->tail; dev_priv->head.prev = NULL; dev_priv->head.buf = NULL; dev_priv->tail.next = NULL; dev_priv->tail.prev = &dev_priv->head; dev_priv->tail.buf = NULL; for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; entry = buf->dev_private; SET_AGE(&entry->age, 0, 0); entry->buf = buf; entry->next = dev_priv->head.next; entry->prev = &dev_priv->head; dev_priv->head.next->prev = entry; dev_priv->head.next = entry; } return 0; } static drm_buf_t *savage_freelist_get(drm_device_t *dev) { drm_savage_private_t *dev_priv = dev->dev_private; drm_savage_buf_priv_t *tail = dev_priv->tail.prev; uint16_t event; unsigned int wrap; DRM_DEBUG("\n"); UPDATE_EVENT_COUNTER(); if (dev_priv->status_ptr) event = dev_priv->status_ptr[1] & 0xffff; else event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff; wrap = dev_priv->event_wrap; if (event > dev_priv->event_counter) wrap--; /* hardware hasn't passed the last wrap yet */ DRM_DEBUG(" tail=0x%04x %d\n", tail->age.event, tail->age.wrap); DRM_DEBUG(" head=0x%04x %d\n", event, wrap); if (tail->buf && (TEST_AGE(&tail->age, event, wrap) || event == 0)) { drm_savage_buf_priv_t *next = tail->next; drm_savage_buf_priv_t *prev = tail->prev; prev->next = next; next->prev = prev; tail->next = tail->prev = NULL; return tail->buf; } DRM_DEBUG("returning NULL, tail->buf=%p!\n", tail->buf); return NULL; } void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf) { drm_savage_private_t *dev_priv = dev->dev_private; drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next; DRM_DEBUG("age=0x%04x wrap=%d\n", entry->age.event, entry->age.wrap); if (entry->next != NULL || entry->prev != NULL) { DRM_ERROR("entry already on freelist.\n"); return; } prev = &dev_priv->head; next = prev->next; prev->next = entry; next->prev = entry; entry->prev = prev; entry->next = next; } /* * Command DMA */ static int savage_dma_init(drm_savage_private_t *dev_priv) { unsigned int i; dev_priv->nr_dma_pages = dev_priv->cmd_dma->size / (SAVAGE_DMA_PAGE_SIZE*4); dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) * dev_priv->nr_dma_pages, DRM_MEM_DRIVER); if (dev_priv->dma_pages == NULL) return DRM_ERR(ENOMEM); for (i = 0; i < dev_priv->nr_dma_pages; ++i) { SET_AGE(&dev_priv->dma_pages[i].age, 0, 0); dev_priv->dma_pages[i].used = 0; dev_priv->dma_pages[i].flushed = 0; } SET_AGE(&dev_priv->last_dma_age, 0, 0); dev_priv->first_dma_page = 0; dev_priv->current_dma_page = 0; return 0; } void savage_dma_reset(drm_savage_private_t *dev_priv) { uint16_t event; unsigned int wrap, i; event = savage_bci_emit_event(dev_priv, 0); wrap = dev_priv->event_wrap; for (i = 0; i < dev_priv->nr_dma_pages; ++i) { SET_AGE(&dev_priv->dma_pages[i].age, event, wrap); dev_priv->dma_pages[i].used = 0; dev_priv->dma_pages[i].flushed = 0; } SET_AGE(&dev_priv->last_dma_age, event, wrap); dev_priv->first_dma_page = dev_priv->current_dma_page = 0; } void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page) { uint16_t event; unsigned int wrap; /* Faked DMA buffer pages don't age. */ if (dev_priv->cmd_dma == &dev_priv->fake_dma) return; UPDATE_EVENT_COUNTER(); if (dev_priv->status_ptr) event = dev_priv->status_ptr[1] & 0xffff; else event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff; wrap = dev_priv->event_wrap; if (event > dev_priv->event_counter) wrap--; /* hardware hasn't passed the last wrap yet */ if (dev_priv->dma_pages[page].age.wrap > wrap || (dev_priv->dma_pages[page].age.wrap == wrap && dev_priv->dma_pages[page].age.event > event)) { if (dev_priv->wait_evnt(dev_priv, dev_priv->dma_pages[page].age.event) < 0) DRM_ERROR("wait_evnt failed!\n"); } } uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv, unsigned int n) { unsigned int cur = dev_priv->current_dma_page; unsigned int rest = SAVAGE_DMA_PAGE_SIZE - dev_priv->dma_pages[cur].used; unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE-1) / SAVAGE_DMA_PAGE_SIZE; uint32_t *dma_ptr; unsigned int i; DRM_DEBUG("cur=%u, cur->used=%u, n=%u, rest=%u, nr_pages=%u\n", cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages); if (cur + nr_pages < dev_priv->nr_dma_pages) { dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle + cur*SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used; if (n < rest) rest = n; dev_priv->dma_pages[cur].used += rest; n -= rest; cur++; } else { dev_priv->dma_flush(dev_priv); nr_pages = (n + SAVAGE_DMA_PAGE_SIZE-1) / SAVAGE_DMA_PAGE_SIZE; for (i = cur; i < dev_priv->nr_dma_pages; ++i) { dev_priv->dma_pages[i].age = dev_priv->last_dma_age; dev_priv->dma_pages[i].used = 0; dev_priv->dma_pages[i].flushed = 0; } dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle; dev_priv->first_dma_page = cur = 0; } for (i = cur; nr_pages > 0; ++i, --nr_pages) { #if SAVAGE_DMA_DEBUG if (dev_priv->dma_pages[i].used) { DRM_ERROR("unflushed page %u: used=%u\n", i, dev_priv->dma_pages[i].used); } #endif if (n > SAVAGE_DMA_PAGE_SIZE) dev_priv->dma_pages[i].used = SAVAGE_DMA_PAGE_SIZE; else dev_priv->dma_pages[i].used = n; n -= SAVAGE_DMA_PAGE_SIZE; } dev_priv->current_dma_page = --i; DRM_DEBUG("cur=%u, cur->used=%u, n=%u\n", i, dev_priv->dma_pages[i].used, n); savage_dma_wait(dev_priv, dev_priv->current_dma_page); return dma_ptr; } static void savage_dma_flush(drm_savage_private_t *dev_priv) { - BCI_LOCALS; unsigned int first = dev_priv->first_dma_page; unsigned int cur = dev_priv->current_dma_page; uint16_t event; unsigned int wrap, pad, align, len, i; unsigned long phys_addr; + BCI_LOCALS; if (first == cur && dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed) return; /* pad length to multiples of 2 entries * align start of next DMA block to multiles of 8 entries */ pad = -dev_priv->dma_pages[cur].used & 1; align = -(dev_priv->dma_pages[cur].used + pad) & 7; DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, " "pad=%u, align=%u\n", first, cur, dev_priv->dma_pages[first].flushed, dev_priv->dma_pages[cur].used, pad, align); /* pad with noops */ if (pad) { uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle + cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used; dev_priv->dma_pages[cur].used += pad; while(pad != 0) { *dma_ptr++ = BCI_CMD_WAIT; pad--; } } DRM_MEMORYBARRIER(); /* do flush ... */ phys_addr = dev_priv->cmd_dma->offset + (first * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[first].flushed) * 4; len = (cur - first) * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used - dev_priv->dma_pages[first].flushed; DRM_DEBUG("phys_addr=%lx, len=%u\n", phys_addr | dev_priv->dma_type, len); BEGIN_BCI(3); BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1); BCI_WRITE(phys_addr | dev_priv->dma_type); BCI_DMA(len); /* fix alignment of the start of the next block */ dev_priv->dma_pages[cur].used += align; /* age DMA pages */ event = savage_bci_emit_event(dev_priv, 0); wrap = dev_priv->event_wrap; for (i = first; i < cur; ++i) { SET_AGE(&dev_priv->dma_pages[i].age, event, wrap); dev_priv->dma_pages[i].used = 0; dev_priv->dma_pages[i].flushed = 0; } /* age the current page only when it's full */ if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) { SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap); dev_priv->dma_pages[cur].used = 0; dev_priv->dma_pages[cur].flushed = 0; /* advance to next page */ cur++; if (cur == dev_priv->nr_dma_pages) cur = 0; dev_priv->first_dma_page = dev_priv->current_dma_page = cur; } else { dev_priv->first_dma_page = cur; dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used; } SET_AGE(&dev_priv->last_dma_age, event, wrap); DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur, dev_priv->dma_pages[cur].used, dev_priv->dma_pages[cur].flushed); } static void savage_fake_dma_flush(drm_savage_private_t *dev_priv) { - BCI_LOCALS; unsigned int i, j; + BCI_LOCALS; + if (dev_priv->first_dma_page == dev_priv->current_dma_page && dev_priv->dma_pages[dev_priv->current_dma_page].used == 0) return; DRM_DEBUG("first=%u, cur=%u, cur->used=%u\n", dev_priv->first_dma_page, dev_priv->current_dma_page, dev_priv->dma_pages[dev_priv->current_dma_page].used); for (i = dev_priv->first_dma_page; i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used; ++i) { uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle + i * SAVAGE_DMA_PAGE_SIZE; #if SAVAGE_DMA_DEBUG /* Sanity check: all pages except the last one must be full. */ if (i < dev_priv->current_dma_page && dev_priv->dma_pages[i].used != SAVAGE_DMA_PAGE_SIZE) { DRM_ERROR("partial DMA page %u: used=%u", i, dev_priv->dma_pages[i].used); } #endif BEGIN_BCI(dev_priv->dma_pages[i].used); for (j = 0; j < dev_priv->dma_pages[i].used; ++j) { BCI_WRITE(dma_ptr[j]); } dev_priv->dma_pages[i].used = 0; } /* reset to first page */ dev_priv->first_dma_page = dev_priv->current_dma_page = 0; } -/* - * Initalize permanent mappings. On Savage4 and SavageIX the alignment - * and size of the aperture is not suitable for automatic MTRR setup - * in drm_initmap. Therefore we do it manually before the maps are - * initialized. We also need to take care of deleting the MTRRs in - * postcleanup. - * - * FIXME: this is linux-specific - */ -int savage_preinit(drm_device_t *dev, unsigned long chipset) +int savage_driver_load(drm_device_t *dev, unsigned long chipset) { drm_savage_private_t *dev_priv; - unsigned long mmio_base, fb_base, fb_size, aperture_base; - unsigned int fb_rsrc, aper_rsrc; - int ret = 0; dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return DRM_ERR(ENOMEM); memset(dev_priv, 0, sizeof(drm_savage_private_t)); dev->dev_private = (void *)dev_priv; + dev_priv->chipset = (enum savage_family)chipset; + return 0; +} + +/* + * Initalize mappings. On Savage4 and SavageIX the alignment + * and size of the aperture is not suitable for automatic MTRR setup + * in drm_addmap. Therefore we add them manually before the maps are + * initialized, and tear them down on last close. + */ +int savage_driver_firstopen(drm_device_t *dev) +{ + drm_savage_private_t *dev_priv = dev->dev_private; + unsigned long mmio_base, fb_base, fb_size, aperture_base; + /* fb_rsrc and aper_rsrc aren't really used currently, but still exist + * in case we decide we need information on the BAR for BSD in the + * future. + */ + unsigned int fb_rsrc, aper_rsrc; + int ret = 0; + dev_priv->mtrr[0].handle = -1; dev_priv->mtrr[1].handle = -1; dev_priv->mtrr[2].handle = -1; if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { fb_rsrc = 0; fb_base = drm_get_resource_start(dev, 0); fb_size = SAVAGE_FB_SIZE_S3; mmio_base = fb_base + SAVAGE_FB_SIZE_S3; aper_rsrc = 0; aperture_base = fb_base + SAVAGE_APERTURE_OFFSET; /* this should always be true */ if (drm_get_resource_len(dev, 0) == 0x08000000) { /* Don't make MMIO write-cobining! We need 3 * MTRRs. */ dev_priv->mtrr[0].base = fb_base; dev_priv->mtrr[0].size = 0x01000000; - dev_priv->mtrr[0].handle = mtrr_add( + dev_priv->mtrr[0].handle = drm_mtrr_add( dev_priv->mtrr[0].base, dev_priv->mtrr[0].size, - MTRR_TYPE_WRCOMB, 1); + DRM_MTRR_WC); dev_priv->mtrr[1].base = fb_base+0x02000000; dev_priv->mtrr[1].size = 0x02000000; - dev_priv->mtrr[1].handle = mtrr_add( + dev_priv->mtrr[1].handle = drm_mtrr_add( dev_priv->mtrr[1].base, dev_priv->mtrr[1].size, - MTRR_TYPE_WRCOMB, 1); + DRM_MTRR_WC); dev_priv->mtrr[2].base = fb_base+0x04000000; dev_priv->mtrr[2].size = 0x04000000; - dev_priv->mtrr[2].handle = mtrr_add( + dev_priv->mtrr[2].handle = drm_mtrr_add( dev_priv->mtrr[2].base, dev_priv->mtrr[2].size, - MTRR_TYPE_WRCOMB, 1); + DRM_MTRR_WC); } else { DRM_ERROR("strange pci_resource_len %08lx\n", drm_get_resource_len(dev, 0)); } - } else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) { + } else if (dev_priv->chipset != S3_SUPERSAVAGE && + dev_priv->chipset != S3_SAVAGE2000) { mmio_base = drm_get_resource_start(dev, 0); fb_rsrc = 1; fb_base = drm_get_resource_start(dev, 1); fb_size = SAVAGE_FB_SIZE_S4; aper_rsrc = 1; aperture_base = fb_base + SAVAGE_APERTURE_OFFSET; /* this should always be true */ if (drm_get_resource_len(dev, 1) == 0x08000000) { /* Can use one MTRR to cover both fb and * aperture. */ dev_priv->mtrr[0].base = fb_base; dev_priv->mtrr[0].size = 0x08000000; - dev_priv->mtrr[0].handle = mtrr_add( + dev_priv->mtrr[0].handle = drm_mtrr_add( dev_priv->mtrr[0].base, dev_priv->mtrr[0].size, - MTRR_TYPE_WRCOMB, 1); + DRM_MTRR_WC); } else { DRM_ERROR("strange pci_resource_len %08lx\n", drm_get_resource_len(dev, 1)); } } else { mmio_base = drm_get_resource_start(dev, 0); fb_rsrc = 1; fb_base = drm_get_resource_start(dev, 1); fb_size = drm_get_resource_len(dev, 1); aper_rsrc = 2; aperture_base = drm_get_resource_start(dev, 2); /* Automatic MTRR setup will do the right thing. */ } - if ((ret = drm_initmap(dev, mmio_base, SAVAGE_MMIO_SIZE, 0, - _DRM_REGISTERS, 0))) + ret = drm_addmap(dev, mmio_base, SAVAGE_MMIO_SIZE, _DRM_REGISTERS, + _DRM_READ_ONLY, &dev_priv->mmio); + if (ret) return ret; - if (!(dev_priv->mmio = drm_core_findmap (dev, mmio_base))) - return DRM_ERR(ENOMEM); - if ((ret = drm_initmap(dev, fb_base, fb_size, fb_rsrc, - _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING))) + ret = drm_addmap(dev, fb_base, fb_size, _DRM_FRAME_BUFFER, + _DRM_WRITE_COMBINING, &dev_priv->fb); + if (ret) return ret; - if (!(dev_priv->fb = drm_core_findmap (dev, fb_base))) - return DRM_ERR(ENOMEM); - if ((ret = drm_initmap(dev, aperture_base, SAVAGE_APERTURE_SIZE, - aper_rsrc, - _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING))) + ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE, + _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, + &dev_priv->aperture); + if (ret) return ret; - if (!(dev_priv->aperture = drm_core_findmap (dev, aperture_base))) - return DRM_ERR(ENOMEM); return ret; } /* * Delete MTRRs and free device-private data. */ -int savage_postcleanup(drm_device_t *dev) +void savage_driver_lastclose(drm_device_t *dev) { drm_savage_private_t *dev_priv = dev->dev_private; int i; for (i = 0; i < 3; ++i) if (dev_priv->mtrr[i].handle >= 0) - mtrr_del(dev_priv->mtrr[i].handle, - dev_priv->mtrr[i].base, - dev_priv->mtrr[i].size); + drm_mtrr_del(dev_priv->mtrr[i].handle, + dev_priv->mtrr[i].base, + dev_priv->mtrr[i].size, + DRM_MTRR_WC); +} +int savage_driver_unload(drm_device_t *dev) +{ + drm_savage_private_t *dev_priv = dev->dev_private; + drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER); return 0; } static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init) { drm_savage_private_t *dev_priv = dev->dev_private; if (init->fb_bpp != 16 && init->fb_bpp != 32) { DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp); return DRM_ERR(EINVAL); } if (init->depth_bpp != 16 && init->depth_bpp != 32) { DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp); return DRM_ERR(EINVAL); } if (init->dma_type != SAVAGE_DMA_AGP && init->dma_type != SAVAGE_DMA_PCI) { DRM_ERROR("invalid dma memory type %d!\n", init->dma_type); return DRM_ERR(EINVAL); } dev_priv->cob_size = init->cob_size; dev_priv->bci_threshold_lo = init->bci_threshold_lo; dev_priv->bci_threshold_hi = init->bci_threshold_hi; dev_priv->dma_type = init->dma_type; dev_priv->fb_bpp = init->fb_bpp; dev_priv->front_offset = init->front_offset; dev_priv->front_pitch = init->front_pitch; dev_priv->back_offset = init->back_offset; dev_priv->back_pitch = init->back_pitch; dev_priv->depth_bpp = init->depth_bpp; dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; dev_priv->texture_offset = init->texture_offset; dev_priv->texture_size = init->texture_size; DRM_GETSAREA(); if (!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } if (init->status_offset != 0) { dev_priv->status = drm_core_findmap(dev, init->status_offset); if (!dev_priv->status) { DRM_ERROR("could not find shadow status region!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } } else { dev_priv->status = NULL; } if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("could not find DMA buffer region!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } drm_core_ioremap(dev->agp_buffer_map, dev); if (!dev->agp_buffer_map) { DRM_ERROR("failed to ioremap DMA buffer region!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(ENOMEM); } } if (init->agp_textures_offset) { dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset); if (!dev_priv->agp_textures) { DRM_ERROR("could not find agp texture region!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } } else { dev_priv->agp_textures = NULL; } if (init->cmd_dma_offset) { if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { DRM_ERROR("command DMA not supported on " "Savage3D/MX/IX.\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } if (dev->dma && dev->dma->buflist) { DRM_ERROR("command and vertex DMA not supported " "at the same time.\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } dev_priv->cmd_dma = drm_core_findmap(dev, init->cmd_dma_offset); if (!dev_priv->cmd_dma) { DRM_ERROR("could not find command DMA region!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } if (dev_priv->dma_type == SAVAGE_DMA_AGP) { if (dev_priv->cmd_dma->type != _DRM_AGP) { DRM_ERROR("AGP command DMA region is not a " "_DRM_AGP map!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } drm_core_ioremap(dev_priv->cmd_dma, dev); if (!dev_priv->cmd_dma->handle) { DRM_ERROR("failed to ioremap command " "DMA region!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(ENOMEM); } } else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) { DRM_ERROR("PCI command DMA region is not a " "_DRM_CONSISTENT map!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(EINVAL); } } else { dev_priv->cmd_dma = NULL; } dev_priv->dma_flush = savage_dma_flush; if (!dev_priv->cmd_dma) { DRM_DEBUG("falling back to faked command DMA.\n"); dev_priv->fake_dma.offset = 0; dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE; dev_priv->fake_dma.type = _DRM_SHM; dev_priv->fake_dma.handle = drm_alloc(SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER); if (!dev_priv->fake_dma.handle) { DRM_ERROR("could not allocate faked DMA buffer!\n"); savage_do_cleanup_bci(dev); return DRM_ERR(ENOMEM); } dev_priv->cmd_dma = &dev_priv->fake_dma; dev_priv->dma_flush = savage_fake_dma_flush; } dev_priv->sarea_priv = (drm_savage_sarea_t *)((uint8_t *)dev_priv->sarea->handle + init->sarea_priv_offset); /* setup bitmap descriptors */ { unsigned int color_tile_format; unsigned int depth_tile_format; unsigned int front_stride, back_stride, depth_stride; if (dev_priv->chipset <= S3_SAVAGE4) { color_tile_format = dev_priv->fb_bpp == 16 ? SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP; depth_tile_format = dev_priv->depth_bpp == 16 ? SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP; } else { color_tile_format = SAVAGE_BD_TILE_DEST; depth_tile_format = SAVAGE_BD_TILE_DEST; } front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp/8); back_stride = dev_priv-> back_pitch / (dev_priv->fb_bpp/8); depth_stride = dev_priv->depth_pitch / (dev_priv->depth_bpp/8); dev_priv->front_bd = front_stride | SAVAGE_BD_BW_DISABLE | (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) | (color_tile_format << SAVAGE_BD_TILE_SHIFT); dev_priv-> back_bd = back_stride | SAVAGE_BD_BW_DISABLE | (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) | (color_tile_format << SAVAGE_BD_TILE_SHIFT); dev_priv->depth_bd = depth_stride | SAVAGE_BD_BW_DISABLE | (dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) | (depth_tile_format << SAVAGE_BD_TILE_SHIFT); } /* setup status and bci ptr */ dev_priv->event_counter = 0; dev_priv->event_wrap = 0; dev_priv->bci_ptr = (volatile uint32_t *) ((uint8_t *)dev_priv->mmio->handle + SAVAGE_BCI_OFFSET); if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S3D; } else { dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S4; } if (dev_priv->status != NULL) { dev_priv->status_ptr = (volatile uint32_t *)dev_priv->status->handle; dev_priv->wait_fifo = savage_bci_wait_fifo_shadow; dev_priv->wait_evnt = savage_bci_wait_event_shadow; dev_priv->status_ptr[1023] = dev_priv->event_counter; } else { dev_priv->status_ptr = NULL; if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { dev_priv->wait_fifo = savage_bci_wait_fifo_s3d; } else { dev_priv->wait_fifo = savage_bci_wait_fifo_s4; } dev_priv->wait_evnt = savage_bci_wait_event_reg; } /* cliprect functions */ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) dev_priv->emit_clip_rect = savage_emit_clip_rect_s3d; else dev_priv->emit_clip_rect = savage_emit_clip_rect_s4; if (savage_freelist_init(dev) < 0) { DRM_ERROR("could not initialize freelist\n"); savage_do_cleanup_bci(dev); return DRM_ERR(ENOMEM); } if (savage_dma_init(dev_priv) < 0) { DRM_ERROR("could not initialize command DMA\n"); savage_do_cleanup_bci(dev); return DRM_ERR(ENOMEM); } return 0; } int savage_do_cleanup_bci(drm_device_t *dev) { drm_savage_private_t *dev_priv = dev->dev_private; if (dev_priv->cmd_dma == &dev_priv->fake_dma) { if (dev_priv->fake_dma.handle) drm_free(dev_priv->fake_dma.handle, SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER); } else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle && dev_priv->cmd_dma->type == _DRM_AGP && dev_priv->dma_type == SAVAGE_DMA_AGP) drm_core_ioremapfree(dev_priv->cmd_dma, dev); if (dev_priv->dma_type == SAVAGE_DMA_AGP && dev->agp_buffer_map && dev->agp_buffer_map->handle) { drm_core_ioremapfree(dev->agp_buffer_map, dev); /* make sure the next instance (which may be running * in PCI mode) doesn't try to use an old * agp_buffer_map. */ dev->agp_buffer_map = NULL; } if (dev_priv->dma_pages) drm_free(dev_priv->dma_pages, sizeof(drm_savage_dma_page_t)*dev_priv->nr_dma_pages, DRM_MEM_DRIVER); return 0; } -int savage_bci_init(DRM_IOCTL_ARGS) +static int savage_bci_init(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_savage_init_t init; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *)data, sizeof(init)); switch (init.func) { case SAVAGE_INIT_BCI: return savage_do_init_bci(dev, &init); case SAVAGE_CLEANUP_BCI: return savage_do_cleanup_bci(dev); } return DRM_ERR(EINVAL); } -int savage_bci_event_emit(DRM_IOCTL_ARGS) +static int savage_bci_event_emit(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; drm_savage_event_emit_t event; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *)data, sizeof(event)); event.count = savage_bci_emit_event(dev_priv, event.flags); event.count |= dev_priv->event_wrap << 16; - DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *)data)->count, - event.count, sizeof(event.count)); + DRM_COPY_TO_USER_IOCTL((drm_savage_event_emit_t __user *)data, + event, sizeof(event)); return 0; } -int savage_bci_event_wait(DRM_IOCTL_ARGS) +static int savage_bci_event_wait(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; drm_savage_event_wait_t event; unsigned int event_e, hw_e; unsigned int event_w, hw_w; DRM_DEBUG("\n"); DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *)data, sizeof(event)); UPDATE_EVENT_COUNTER(); if (dev_priv->status_ptr) hw_e = dev_priv->status_ptr[1] & 0xffff; else hw_e = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff; hw_w = dev_priv->event_wrap; if (hw_e > dev_priv->event_counter) hw_w--; /* hardware hasn't passed the last wrap yet */ event_e = event.count & 0xffff; event_w = event.count >> 16; /* Don't need to wait if * - event counter wrapped since the event was emitted or * - the hardware has advanced up to or over the event to wait for. */ if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e) ) return 0; else return dev_priv->wait_evnt(dev_priv, event_e); } /* * DMA buffer management */ static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d) { drm_buf_t *buf; int i; for (i = d->granted_count; i < d->request_count; i++) { buf = savage_freelist_get(dev); if (!buf) return DRM_ERR(EAGAIN); buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return DRM_ERR(EFAULT); d->granted_count++; } return 0; } int savage_bci_buffers(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_dma_t d; int ret = 0; LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *)data, sizeof(d)); /* Please don't send us buffers. */ if (d.send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", DRM_CURRENTPID, d.send_count); return DRM_ERR(EINVAL); } /* We'll send you buffers. */ if (d.request_count < 0 || d.request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", DRM_CURRENTPID, d.request_count, dma->buf_count); return DRM_ERR(EINVAL); } d.granted_count = 0; if (d.request_count) { ret = savage_bci_get_buffers(filp, dev, &d); } DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *)data, d, sizeof(d)); return ret; } void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp) { drm_device_dma_t *dma = dev->dma; drm_savage_private_t *dev_priv = dev->dev_private; int i; if (!dma) return; if (!dev_priv) return; if (!dma->buflist) return; /*i830_flush_queue(dev);*/ for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[i]; drm_savage_buf_priv_t *buf_priv = buf->dev_private; if (buf->filp == filp && buf_priv && buf_priv->next == NULL && buf_priv->prev == NULL) { uint16_t event; DRM_DEBUG("reclaimed from client\n"); event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D); SET_AGE(&buf_priv->age, event, dev_priv->event_wrap); savage_freelist_put(dev, buf); } } drm_core_reclaim_buffers(dev, filp); } + +drm_ioctl_desc_t savage_ioctls[] = { + [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, DRM_AUTH}, +}; + +int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls); + Index: head/sys/dev/drm/savage_drm.h =================================================================== --- head/sys/dev/drm/savage_drm.h (revision 152908) +++ head/sys/dev/drm/savage_drm.h (revision 152909) @@ -1,211 +1,212 @@ /* savage_drm.h -- Public header for the savage driver * * Copyright 2004 Felix Kuehling * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #ifndef __SAVAGE_DRM_H__ #define __SAVAGE_DRM_H__ #ifndef __SAVAGE_SAREA_DEFINES__ #define __SAVAGE_SAREA_DEFINES__ /* 2 heaps (1 for card, 1 for agp), each divided into upto 128 * regions, subject to a minimum region size of (1<<16) == 64k. * * Clients may subdivide regions internally, but when sharing between * clients, the region size is the minimum granularity. */ #define SAVAGE_CARD_HEAP 0 #define SAVAGE_AGP_HEAP 1 #define SAVAGE_NR_TEX_HEAPS 2 #define SAVAGE_NR_TEX_REGIONS 16 #define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16 #endif /* __SAVAGE_SAREA_DEFINES__ */ typedef struct _drm_savage_sarea { /* LRU lists for texture memory in agp space and on the card. */ drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS+1]; unsigned int texAge[SAVAGE_NR_TEX_HEAPS]; /* Mechanism to validate card state. */ int ctxOwner; } drm_savage_sarea_t, *drm_savage_sarea_ptr; /* Savage-specific ioctls */ #define DRM_SAVAGE_BCI_INIT 0x00 #define DRM_SAVAGE_BCI_CMDBUF 0x01 #define DRM_SAVAGE_BCI_EVENT_EMIT 0x02 #define DRM_SAVAGE_BCI_EVENT_WAIT 0x03 #define DRM_IOCTL_SAVAGE_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) #define DRM_IOCTL_SAVAGE_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) #define DRM_IOCTL_SAVAGE_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) #define DRM_IOCTL_SAVAGE_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) #define SAVAGE_DMA_PCI 1 #define SAVAGE_DMA_AGP 3 typedef struct drm_savage_init { enum { SAVAGE_INIT_BCI = 1, SAVAGE_CLEANUP_BCI = 2 } func; unsigned int sarea_priv_offset; /* some parameters */ unsigned int cob_size; unsigned int bci_threshold_lo, bci_threshold_hi; unsigned int dma_type; /* frame buffer layout */ unsigned int fb_bpp; unsigned int front_offset, front_pitch; unsigned int back_offset, back_pitch; unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; /* local textures */ unsigned int texture_offset; unsigned int texture_size; /* physical locations of non-permanent maps */ unsigned long status_offset; unsigned long buffers_offset; unsigned long agp_textures_offset; unsigned long cmd_dma_offset; } drm_savage_init_t; typedef union drm_savage_cmd_header drm_savage_cmd_header_t; typedef struct drm_savage_cmdbuf { /* command buffer in client's address space */ drm_savage_cmd_header_t __user *cmd_addr; unsigned int size; /* size of the command buffer in 64bit units */ unsigned int dma_idx; /* DMA buffer index to use */ int discard; /* discard DMA buffer when done */ /* vertex buffer in client's address space */ unsigned int __user *vb_addr; unsigned int vb_size; /* size of client vertex buffer in bytes */ unsigned int vb_stride; /* stride of vertices in 32bit words */ /* boxes in client's address space */ drm_clip_rect_t __user *box_addr; unsigned int nbox; /* number of clipping boxes */ } drm_savage_cmdbuf_t; #define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */ #define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */ #define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */ typedef struct drm_savage_event { unsigned int count; unsigned int flags; } drm_savage_event_emit_t, drm_savage_event_wait_t; /* Commands for the cmdbuf ioctl */ #define SAVAGE_CMD_STATE 0 /* a range of state registers */ #define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */ #define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */ #define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */ #define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */ #define SAVAGE_CMD_CLEAR 5 /* clear buffers */ #define SAVAGE_CMD_SWAP 6 /* swap buffers */ /* Primitive types */ #define SAVAGE_PRIM_TRILIST 0 /* triangle list */ #define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */ #define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */ #define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat * shading on s3d */ /* Skip flags (vertex format) */ #define SAVAGE_SKIP_Z 0x01 #define SAVAGE_SKIP_W 0x02 #define SAVAGE_SKIP_C0 0x04 #define SAVAGE_SKIP_C1 0x08 #define SAVAGE_SKIP_S0 0x10 #define SAVAGE_SKIP_T0 0x20 #define SAVAGE_SKIP_ST0 0x30 #define SAVAGE_SKIP_S1 0x40 #define SAVAGE_SKIP_T1 0x80 #define SAVAGE_SKIP_ST1 0xc0 #define SAVAGE_SKIP_ALL_S3D 0x3f #define SAVAGE_SKIP_ALL_S4 0xff /* Buffer names for clear command */ #define SAVAGE_FRONT 0x1 #define SAVAGE_BACK 0x2 #define SAVAGE_DEPTH 0x4 /* 64-bit command header */ union drm_savage_cmd_header { struct { unsigned char cmd; /* command */ unsigned char pad0; unsigned short pad1; unsigned short pad2; unsigned short pad3; } cmd; /* generic */ struct { unsigned char cmd; unsigned char global; /* need idle engine? */ unsigned short count; /* number of consecutive registers */ unsigned short start; /* first register */ unsigned short pad3; } state; /* SAVAGE_CMD_STATE */ struct { unsigned char cmd; unsigned char prim; /* primitive type */ unsigned short skip; /* vertex format (skip flags) */ unsigned short count; /* number of vertices */ unsigned short start; /* first vertex in DMA/vertex buffer */ } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */ struct { unsigned char cmd; unsigned char prim; unsigned short skip; unsigned short count; /* number of indices that follow */ unsigned short pad3; } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */ struct { unsigned char cmd; unsigned char pad0; unsigned short pad1; unsigned int flags; } clear0; /* SAVAGE_CMD_CLEAR */ struct { unsigned int mask; unsigned int value; } clear1; /* SAVAGE_CMD_CLEAR data */ }; #endif Index: head/sys/dev/drm/savage_drv.c =================================================================== --- head/sys/dev/drm/savage_drv.c (revision 152908) +++ head/sys/dev/drm/savage_drv.c (revision 152909) @@ -1,107 +1,107 @@ /* savage_drv.c -- Savage DRI driver */ /*- * Copyright 2005 Eric Anholt * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Eric Anholt - * - * $FreeBSD$ */ -#include "drmP.h" -#include "drm.h" -#include "savage_drm.h" -#include "savage_drv.h" -#include "drm_pciids.h" +#include +__FBSDID("$FreeBSD$"); +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/savage_drm.h" +#include "dev/drm/savage_drv.h" +#include "dev/drm/drm_pciids.h" + /* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */ static drm_pci_id_list_t savage_pciidlist[] = { savage_PCI_IDS }; -extern drm_ioctl_desc_t savage_ioctls[]; -extern int savage_max_ioctl; - static void savage_configure(drm_device_t *dev) { - dev->dev_priv_size = sizeof(drm_savage_buf_priv_t); - dev->preinit = savage_preinit; - dev->postcleanup = savage_postcleanup; - dev->reclaim_buffers = savage_reclaim_buffers; - dev->dma_ioctl = savage_bci_buffers; + dev->driver.buf_priv_size = sizeof(drm_savage_buf_priv_t); + dev->driver.load = savage_driver_load; + dev->driver.firstopen = savage_driver_firstopen; + dev->driver.lastclose = savage_driver_lastclose; + dev->driver.unload = savage_driver_unload; + dev->driver.reclaim_buffers_locked = savage_reclaim_buffers; + dev->driver.dma_ioctl = savage_bci_buffers; - dev->driver_ioctls = savage_ioctls; - dev->max_driver_ioctl = savage_max_ioctl; + dev->driver.ioctls = savage_ioctls; + dev->driver.max_ioctl = savage_max_ioctl; - dev->driver_name = DRIVER_NAME; - dev->driver_desc = DRIVER_DESC; - dev->driver_date = DRIVER_DATE; - dev->driver_major = DRIVER_MAJOR; - dev->driver_minor = DRIVER_MINOR; - dev->driver_patchlevel = DRIVER_PATCHLEVEL; + dev->driver.name = DRIVER_NAME; + dev->driver.desc = DRIVER_DESC; + dev->driver.date = DRIVER_DATE; + dev->driver.major = DRIVER_MAJOR; + dev->driver.minor = DRIVER_MINOR; + dev->driver.patchlevel = DRIVER_PATCHLEVEL; - dev->use_agp = 1; - dev->use_mtrr = 1; - dev->use_pci_dma = 1; - dev->use_dma = 1; + dev->driver.use_agp = 1; + dev->driver.use_mtrr = 1; + dev->driver.use_pci_dma = 1; + dev->driver.use_dma = 1; } #ifdef __FreeBSD__ static int savage_probe(device_t dev) { return drm_probe(dev, savage_pciidlist); } static int savage_attach(device_t nbdev) { drm_device_t *dev = device_get_softc(nbdev); bzero(dev, sizeof(drm_device_t)); savage_configure(dev); return drm_attach(nbdev, savage_pciidlist); } static device_method_t savage_methods[] = { /* Device interface */ DEVMETHOD(device_probe, savage_probe), DEVMETHOD(device_attach, savage_attach), DEVMETHOD(device_detach, drm_detach), { 0, 0 } }; static driver_t savage_driver = { "drm", savage_methods, sizeof(drm_device_t) }; extern devclass_t drm_devclass; DRIVER_MODULE(savage, pci, savage_driver, drm_devclass, 0, 0); MODULE_DEPEND(savage, drm, 1, 1, 1); #elif defined(__NetBSD__) || defined(__OpenBSD__) CFDRIVER_DECL(savage, DV_TTY, NULL); #endif Index: head/sys/dev/drm/savage_drv.h =================================================================== --- head/sys/dev/drm/savage_drv.h (revision 152908) +++ head/sys/dev/drm/savage_drv.h (revision 152909) @@ -1,584 +1,578 @@ -/* savage_drv.h -- Private header for the savage driver - * +/* savage_drv.h -- Private header for the savage driver */ +/*- * Copyright 2004 Felix Kuehling * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef __SAVAGE_DRV_H__ #define __SAVAGE_DRV_H__ #define DRIVER_AUTHOR "Felix Kuehling" #define DRIVER_NAME "savage" #define DRIVER_DESC "Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]" #define DRIVER_DATE "20050313" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 4 #define DRIVER_PATCHLEVEL 1 /* Interface history: * * 1.x The DRM driver from the VIA/S3 code drop, basically a dummy * 2.0 The first real DRM * 2.1 Scissors registers managed by the DRM, 3D operations clipped by * cliprects of the cmdbuf ioctl * 2.2 Implemented SAVAGE_CMD_DMA_IDX and SAVAGE_CMD_VB_IDX * 2.3 Event counters used by BCI_EVENT_EMIT/WAIT ioctls are now 32 bits * wide and thus very long lived (unlikely to ever wrap). The size * in the struct was 32 bits before, but only 16 bits were used * 2.4 Implemented command DMA. Now drm_savage_init_t.cmd_dma_offset is * actually used */ typedef struct drm_savage_age { uint16_t event; unsigned int wrap; } drm_savage_age_t; typedef struct drm_savage_buf_priv { struct drm_savage_buf_priv *next; struct drm_savage_buf_priv *prev; drm_savage_age_t age; drm_buf_t *buf; } drm_savage_buf_priv_t; typedef struct drm_savage_dma_page { drm_savage_age_t age; unsigned int used, flushed; } drm_savage_dma_page_t; #define SAVAGE_DMA_PAGE_SIZE 1024 /* in dwords */ /* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command * size of 16kbytes or 4k entries. Minimum requirement would be * 10kbytes for 255 40-byte vertices in one drawing command. */ #define SAVAGE_FAKE_DMA_SIZE (SAVAGE_DMA_PAGE_SIZE*4*4) /* interesting bits of hardware state that are saved in dev_priv */ typedef union { struct drm_savage_common_state { uint32_t vbaddr; } common; struct { unsigned char pad[sizeof(struct drm_savage_common_state)]; uint32_t texctrl, texaddr; uint32_t scstart, new_scstart; uint32_t scend, new_scend; } s3d; struct { unsigned char pad[sizeof(struct drm_savage_common_state)]; uint32_t texdescr, texaddr0, texaddr1; uint32_t drawctrl0, new_drawctrl0; uint32_t drawctrl1, new_drawctrl1; } s4; } drm_savage_state_t; /* these chip tags should match the ones in the 2D driver in savage_regs.h. */ enum savage_family { S3_UNKNOWN = 0, S3_SAVAGE3D, S3_SAVAGE_MX, S3_SAVAGE4, S3_PROSAVAGE, S3_TWISTER, S3_PROSAVAGEDDR, S3_SUPERSAVAGE, S3_SAVAGE2000, S3_LAST }; +extern drm_ioctl_desc_t savage_ioctls[]; +extern int savage_max_ioctl; + #define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX)) #define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) \ || (chip==S3_PROSAVAGE) \ || (chip==S3_TWISTER) \ || (chip==S3_PROSAVAGEDDR)) #define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE)) #define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) #define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) \ ||(chip==S3_PROSAVAGEDDR)) /* flags */ #define SAVAGE_IS_AGP 1 typedef struct drm_savage_private { drm_savage_sarea_t *sarea_priv; drm_savage_buf_priv_t head, tail; /* who am I? */ enum savage_family chipset; unsigned int cob_size; unsigned int bci_threshold_lo, bci_threshold_hi; unsigned int dma_type; /* frame buffer layout */ unsigned int fb_bpp; unsigned int front_offset, front_pitch; unsigned int back_offset, back_pitch; unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; /* bitmap descriptors for swap and clear */ unsigned int front_bd, back_bd, depth_bd; /* local textures */ unsigned int texture_offset; unsigned int texture_size; /* memory regions in physical memory */ drm_local_map_t *sarea; drm_local_map_t *mmio; drm_local_map_t *fb; drm_local_map_t *aperture; drm_local_map_t *status; drm_local_map_t *agp_textures; drm_local_map_t *cmd_dma; drm_local_map_t fake_dma; struct { int handle; unsigned long base, size; } mtrr[3]; /* BCI and status-related stuff */ volatile uint32_t *status_ptr, *bci_ptr; uint32_t status_used_mask; uint16_t event_counter; unsigned int event_wrap; /* Savage4 command DMA */ drm_savage_dma_page_t *dma_pages; unsigned int nr_dma_pages, first_dma_page, current_dma_page; drm_savage_age_t last_dma_age; /* saved hw state for global/local check on S3D */ uint32_t hw_draw_ctrl, hw_zbuf_ctrl; /* and for scissors (global, so don't emit if not changed) */ uint32_t hw_scissors_start, hw_scissors_end; drm_savage_state_t state; /* after emitting a wait cmd Savage3D needs 63 nops before next DMA */ unsigned int waiting; /* config/hardware-dependent function pointers */ int (*wait_fifo)(struct drm_savage_private *dev_priv, unsigned int n); int (*wait_evnt)(struct drm_savage_private *dev_priv, uint16_t e); /* Err, there is a macro wait_event in include/linux/wait.h. * Avoid unwanted macro expansion. */ void (*emit_clip_rect)(struct drm_savage_private *dev_priv, - drm_clip_rect_t *pbox); + const drm_clip_rect_t *pbox); void (*dma_flush)(struct drm_savage_private *dev_priv); } drm_savage_private_t; /* ioctls */ -extern int savage_bci_init(DRM_IOCTL_ARGS); extern int savage_bci_cmdbuf(DRM_IOCTL_ARGS); -extern int savage_bci_event_emit(DRM_IOCTL_ARGS); -extern int savage_bci_event_wait(DRM_IOCTL_ARGS); extern int savage_bci_buffers(DRM_IOCTL_ARGS); /* BCI functions */ extern uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv, unsigned int flags); extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf); extern void savage_dma_reset(drm_savage_private_t *dev_priv); extern void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page); extern uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv, unsigned int n); -extern int savage_preinit(drm_device_t *dev, unsigned long chipset); -extern int savage_postcleanup(drm_device_t *dev); +extern int savage_driver_load(drm_device_t *dev, unsigned long chipset); +extern int savage_driver_firstopen(drm_device_t *dev); +extern void savage_driver_lastclose(drm_device_t *dev); +extern int savage_driver_unload(drm_device_t *dev); extern int savage_do_cleanup_bci(drm_device_t *dev); extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp); /* state functions */ extern void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv, - drm_clip_rect_t *pbox); + const drm_clip_rect_t *pbox); extern void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv, - drm_clip_rect_t *pbox); + const drm_clip_rect_t *pbox); #define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */ #define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */ #define SAVAGE_MMIO_SIZE 0x00080000 /* 512kB */ #define SAVAGE_APERTURE_OFFSET 0x02000000 /* 32MB */ #define SAVAGE_APERTURE_SIZE 0x05000000 /* 5 tiled surfaces, 16MB each */ #define SAVAGE_BCI_OFFSET 0x00010000 /* offset of the BCI region * inside the MMIO region */ #define SAVAGE_BCI_FIFO_SIZE 32 /* number of entries in on-chip * BCI FIFO */ /* * MMIO registers */ #define SAVAGE_STATUS_WORD0 0x48C00 #define SAVAGE_STATUS_WORD1 0x48C04 #define SAVAGE_ALT_STATUS_WORD0 0x48C60 #define SAVAGE_FIFO_USED_MASK_S3D 0x0001ffff #define SAVAGE_FIFO_USED_MASK_S4 0x001fffff /* Copied from savage_bci.h in the 2D driver with some renaming. */ /* Bitmap descriptors */ #define SAVAGE_BD_STRIDE_SHIFT 0 #define SAVAGE_BD_BPP_SHIFT 16 #define SAVAGE_BD_TILE_SHIFT 24 #define SAVAGE_BD_BW_DISABLE (1<<28) /* common: */ #define SAVAGE_BD_TILE_LINEAR 0 /* savage4, MX, IX, 3D */ #define SAVAGE_BD_TILE_16BPP 2 #define SAVAGE_BD_TILE_32BPP 3 /* twister, prosavage, DDR, supersavage, 2000 */ #define SAVAGE_BD_TILE_DEST 1 #define SAVAGE_BD_TILE_TEXTURE 2 /* GBD - BCI enable */ /* savage4, MX, IX, 3D */ #define SAVAGE_GBD_BCI_ENABLE 8 /* twister, prosavage, DDR, supersavage, 2000 */ #define SAVAGE_GBD_BCI_ENABLE_TWISTER 0 #define SAVAGE_GBD_BIG_ENDIAN 4 #define SAVAGE_GBD_LITTLE_ENDIAN 0 #define SAVAGE_GBD_64 1 /* Global Bitmap Descriptor */ #define SAVAGE_BCI_GLB_BD_LOW 0x8168 #define SAVAGE_BCI_GLB_BD_HIGH 0x816C /* * BCI registers */ /* Savage4/Twister/ProSavage 3D registers */ #define SAVAGE_DRAWLOCALCTRL_S4 0x1e #define SAVAGE_TEXPALADDR_S4 0x1f #define SAVAGE_TEXCTRL0_S4 0x20 #define SAVAGE_TEXCTRL1_S4 0x21 #define SAVAGE_TEXADDR0_S4 0x22 #define SAVAGE_TEXADDR1_S4 0x23 #define SAVAGE_TEXBLEND0_S4 0x24 #define SAVAGE_TEXBLEND1_S4 0x25 #define SAVAGE_TEXXPRCLR_S4 0x26 /* never used */ #define SAVAGE_TEXDESCR_S4 0x27 #define SAVAGE_FOGTABLE_S4 0x28 #define SAVAGE_FOGCTRL_S4 0x30 #define SAVAGE_STENCILCTRL_S4 0x31 #define SAVAGE_ZBUFCTRL_S4 0x32 #define SAVAGE_ZBUFOFF_S4 0x33 #define SAVAGE_DESTCTRL_S4 0x34 #define SAVAGE_DRAWCTRL0_S4 0x35 #define SAVAGE_DRAWCTRL1_S4 0x36 #define SAVAGE_ZWATERMARK_S4 0x37 #define SAVAGE_DESTTEXRWWATERMARK_S4 0x38 #define SAVAGE_TEXBLENDCOLOR_S4 0x39 /* Savage3D/MX/IX 3D registers */ #define SAVAGE_TEXPALADDR_S3D 0x18 #define SAVAGE_TEXXPRCLR_S3D 0x19 /* never used */ #define SAVAGE_TEXADDR_S3D 0x1A #define SAVAGE_TEXDESCR_S3D 0x1B #define SAVAGE_TEXCTRL_S3D 0x1C #define SAVAGE_FOGTABLE_S3D 0x20 #define SAVAGE_FOGCTRL_S3D 0x30 #define SAVAGE_DRAWCTRL_S3D 0x31 #define SAVAGE_ZBUFCTRL_S3D 0x32 #define SAVAGE_ZBUFOFF_S3D 0x33 #define SAVAGE_DESTCTRL_S3D 0x34 #define SAVAGE_SCSTART_S3D 0x35 #define SAVAGE_SCEND_S3D 0x36 #define SAVAGE_ZWATERMARK_S3D 0x37 #define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38 /* common stuff */ #define SAVAGE_VERTBUFADDR 0x3e #define SAVAGE_BITPLANEWTMASK 0xd7 #define SAVAGE_DMABUFADDR 0x51 /* texture enable bits (needed for tex addr checking) */ #define SAVAGE_TEXCTRL_TEXEN_MASK 0x00010000 /* S3D */ #define SAVAGE_TEXDESCR_TEX0EN_MASK 0x02000000 /* S4 */ #define SAVAGE_TEXDESCR_TEX1EN_MASK 0x04000000 /* S4 */ /* Global fields in Savage4/Twister/ProSavage 3D registers: * * All texture registers and DrawLocalCtrl are local. All other * registers are global. */ /* Global fields in Savage3D/MX/IX 3D registers: * * All texture registers are local. DrawCtrl and ZBufCtrl are * partially local. All other registers are global. * * DrawCtrl global fields: cullMode, alphaTestCmpFunc, alphaTestEn, alphaRefVal * ZBufCtrl global fields: zCmpFunc, zBufEn */ #define SAVAGE_DRAWCTRL_S3D_GLOBAL 0x03f3c00c #define SAVAGE_ZBUFCTRL_S3D_GLOBAL 0x00000027 /* Masks for scissor bits (drawCtrl[01] on s4, scissorStart/End on s3d) */ #define SAVAGE_SCISSOR_MASK_S4 0x00fff7ff #define SAVAGE_SCISSOR_MASK_S3D 0x07ff07ff /* * BCI commands */ #define BCI_CMD_NOP 0x40000000 #define BCI_CMD_RECT 0x48000000 #define BCI_CMD_RECT_XP 0x01000000 #define BCI_CMD_RECT_YP 0x02000000 #define BCI_CMD_SCANLINE 0x50000000 #define BCI_CMD_LINE 0x5C000000 #define BCI_CMD_LINE_LAST_PIXEL 0x58000000 #define BCI_CMD_BYTE_TEXT 0x63000000 #define BCI_CMD_NT_BYTE_TEXT 0x67000000 #define BCI_CMD_BIT_TEXT 0x6C000000 #define BCI_CMD_GET_ROP(cmd) (((cmd) >> 16) & 0xFF) #define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16)) #define BCI_CMD_SEND_COLOR 0x00008000 #define BCI_CMD_CLIP_NONE 0x00000000 #define BCI_CMD_CLIP_CURRENT 0x00002000 #define BCI_CMD_CLIP_LR 0x00004000 #define BCI_CMD_CLIP_NEW 0x00006000 #define BCI_CMD_DEST_GBD 0x00000000 #define BCI_CMD_DEST_PBD 0x00000800 #define BCI_CMD_DEST_PBD_NEW 0x00000C00 #define BCI_CMD_DEST_SBD 0x00001000 #define BCI_CMD_DEST_SBD_NEW 0x00001400 #define BCI_CMD_SRC_TRANSPARENT 0x00000200 #define BCI_CMD_SRC_SOLID 0x00000000 #define BCI_CMD_SRC_GBD 0x00000020 #define BCI_CMD_SRC_COLOR 0x00000040 #define BCI_CMD_SRC_MONO 0x00000060 #define BCI_CMD_SRC_PBD_COLOR 0x00000080 #define BCI_CMD_SRC_PBD_MONO 0x000000A0 #define BCI_CMD_SRC_PBD_COLOR_NEW 0x000000C0 #define BCI_CMD_SRC_PBD_MONO_NEW 0x000000E0 #define BCI_CMD_SRC_SBD_COLOR 0x00000100 #define BCI_CMD_SRC_SBD_MONO 0x00000120 #define BCI_CMD_SRC_SBD_COLOR_NEW 0x00000140 #define BCI_CMD_SRC_SBD_MONO_NEW 0x00000160 #define BCI_CMD_PAT_TRANSPARENT 0x00000010 #define BCI_CMD_PAT_NONE 0x00000000 #define BCI_CMD_PAT_COLOR 0x00000002 #define BCI_CMD_PAT_MONO 0x00000003 #define BCI_CMD_PAT_PBD_COLOR 0x00000004 #define BCI_CMD_PAT_PBD_MONO 0x00000005 #define BCI_CMD_PAT_PBD_COLOR_NEW 0x00000006 #define BCI_CMD_PAT_PBD_MONO_NEW 0x00000007 #define BCI_CMD_PAT_SBD_COLOR 0x00000008 #define BCI_CMD_PAT_SBD_MONO 0x00000009 #define BCI_CMD_PAT_SBD_COLOR_NEW 0x0000000A #define BCI_CMD_PAT_SBD_MONO_NEW 0x0000000B #define BCI_BD_BW_DISABLE 0x10000000 #define BCI_BD_TILE_MASK 0x03000000 #define BCI_BD_TILE_NONE 0x00000000 #define BCI_BD_TILE_16 0x02000000 #define BCI_BD_TILE_32 0x03000000 #define BCI_BD_GET_BPP(bd) (((bd) >> 16) & 0xFF) #define BCI_BD_SET_BPP(bd, bpp) ((bd) |= (((bpp) & 0xFF) << 16)) #define BCI_BD_GET_STRIDE(bd) ((bd) & 0xFFFF) #define BCI_BD_SET_STRIDE(bd, st) ((bd) |= ((st) & 0xFFFF)) #define BCI_CMD_SET_REGISTER 0x96000000 #define BCI_CMD_WAIT 0xC0000000 #define BCI_CMD_WAIT_3D 0x00010000 #define BCI_CMD_WAIT_2D 0x00020000 #define BCI_CMD_UPDATE_EVENT_TAG 0x98000000 #define BCI_CMD_DRAW_PRIM 0x80000000 #define BCI_CMD_DRAW_INDEXED_PRIM 0x88000000 #define BCI_CMD_DRAW_CONT 0x01000000 #define BCI_CMD_DRAW_TRILIST 0x00000000 #define BCI_CMD_DRAW_TRISTRIP 0x02000000 #define BCI_CMD_DRAW_TRIFAN 0x04000000 #define BCI_CMD_DRAW_SKIPFLAGS 0x000000ff #define BCI_CMD_DRAW_NO_Z 0x00000001 #define BCI_CMD_DRAW_NO_W 0x00000002 #define BCI_CMD_DRAW_NO_CD 0x00000004 #define BCI_CMD_DRAW_NO_CS 0x00000008 #define BCI_CMD_DRAW_NO_U0 0x00000010 #define BCI_CMD_DRAW_NO_V0 0x00000020 #define BCI_CMD_DRAW_NO_UV0 0x00000030 #define BCI_CMD_DRAW_NO_U1 0x00000040 #define BCI_CMD_DRAW_NO_V1 0x00000080 #define BCI_CMD_DRAW_NO_UV1 0x000000c0 #define BCI_CMD_DMA 0xa8000000 #define BCI_W_H(w, h) ((((h) << 16) | (w)) & 0x0FFF0FFF) #define BCI_X_Y(x, y) ((((y) << 16) | (x)) & 0x0FFF0FFF) #define BCI_X_W(x, y) ((((w) << 16) | (x)) & 0x0FFF0FFF) #define BCI_CLIP_LR(l, r) ((((r) << 16) | (l)) & 0x0FFF0FFF) #define BCI_CLIP_TL(t, l) ((((t) << 16) | (l)) & 0x0FFF0FFF) #define BCI_CLIP_BR(b, r) ((((b) << 16) | (r)) & 0x0FFF0FFF) #define BCI_LINE_X_Y(x, y) (((y) << 16) | ((x) & 0xFFFF)) #define BCI_LINE_STEPS(diag, axi) (((axi) << 16) | ((diag) & 0xFFFF)) #define BCI_LINE_MISC(maj, ym, xp, yp, err) \ (((maj) & 0x1FFF) | \ ((ym) ? 1<<13 : 0) | \ ((xp) ? 1<<14 : 0) | \ ((yp) ? 1<<15 : 0) | \ ((err) << 16)) /* * common commands */ #define BCI_SET_REGISTERS( first, n ) \ BCI_WRITE(BCI_CMD_SET_REGISTER | \ ((uint32_t)(n) & 0xff) << 16 | \ ((uint32_t)(first) & 0xffff)) #define DMA_SET_REGISTERS( first, n ) \ DMA_WRITE(BCI_CMD_SET_REGISTER | \ ((uint32_t)(n) & 0xff) << 16 | \ ((uint32_t)(first) & 0xffff)) #define BCI_DRAW_PRIMITIVE(n, type, skip) \ BCI_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \ ((n) << 16)) #define DMA_DRAW_PRIMITIVE(n, type, skip) \ DMA_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \ ((n) << 16)) #define BCI_DRAW_INDICES_S3D(n, type, i0) \ BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \ ((n) << 16) | (i0)) #define BCI_DRAW_INDICES_S4(n, type, skip) \ BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \ (skip) | ((n) << 16)) #define BCI_DMA(n) \ BCI_WRITE(BCI_CMD_DMA | (((n) >> 1) - 1)) /* * access to MMIO */ #define SAVAGE_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) #define SAVAGE_WRITE(reg) DRM_WRITE32( dev_priv->mmio, (reg) ) /* * access to the burst command interface (BCI) */ #define SAVAGE_BCI_DEBUG 1 #define BCI_LOCALS volatile uint32_t *bci_ptr; #define BEGIN_BCI( n ) do { \ dev_priv->wait_fifo(dev_priv, (n)); \ bci_ptr = dev_priv->bci_ptr; \ } while(0) #define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val) -#define BCI_COPY_FROM_USER(src,n) do { \ - unsigned int i; \ - for (i = 0; i < n; ++i) { \ - uint32_t val; \ - DRM_GET_USER_UNCHECKED(val, &((uint32_t*)(src))[i]); \ - BCI_WRITE(val); \ - } \ -} while(0) - /* * command DMA support */ #define SAVAGE_DMA_DEBUG 1 #define DMA_LOCALS uint32_t *dma_ptr; #define BEGIN_DMA( n ) do { \ unsigned int cur = dev_priv->current_dma_page; \ unsigned int rest = SAVAGE_DMA_PAGE_SIZE - \ dev_priv->dma_pages[cur].used; \ if ((n) > rest) { \ dma_ptr = savage_dma_alloc(dev_priv, (n)); \ } else { /* fast path for small allocations */ \ dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle + \ cur * SAVAGE_DMA_PAGE_SIZE + \ dev_priv->dma_pages[cur].used; \ if (dev_priv->dma_pages[cur].used == 0) \ savage_dma_wait(dev_priv, cur); \ dev_priv->dma_pages[cur].used += (n); \ } \ } while(0) #define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val) -#define DMA_COPY_FROM_USER(src,n) do { \ - DRM_COPY_FROM_USER_UNCHECKED(dma_ptr, (src), (n)*4); \ +#define DMA_COPY(src, n) do { \ + memcpy(dma_ptr, (src), (n)*4); \ dma_ptr += n; \ } while(0) #if SAVAGE_DMA_DEBUG #define DMA_COMMIT() do { \ unsigned int cur = dev_priv->current_dma_page; \ uint32_t *expected = (uint32_t *)dev_priv->cmd_dma->handle + \ cur * SAVAGE_DMA_PAGE_SIZE + \ dev_priv->dma_pages[cur].used; \ if (dma_ptr != expected) { \ DRM_ERROR("DMA allocation and use don't match: " \ "%p != %p\n", expected, dma_ptr); \ savage_dma_reset(dev_priv); \ } \ } while(0) #else #define DMA_COMMIT() do {/* nothing */} while(0) #endif #define DMA_FLUSH() dev_priv->dma_flush(dev_priv) /* Buffer aging via event tag */ #define UPDATE_EVENT_COUNTER( ) do { \ if (dev_priv->status_ptr) { \ uint16_t count; \ /* coordinate with Xserver */ \ count = dev_priv->status_ptr[1023]; \ if (count < dev_priv->event_counter) \ dev_priv->event_wrap++; \ dev_priv->event_counter = count; \ } \ } while(0) #define SET_AGE( age, e, w ) do { \ (age)->event = e; \ (age)->wrap = w; \ } while(0) #define TEST_AGE( age, e, w ) \ ( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) ) #endif /* __SAVAGE_DRV_H__ */ Index: head/sys/dev/drm/savage_state.c =================================================================== --- head/sys/dev/drm/savage_state.c (revision 152908) +++ head/sys/dev/drm/savage_state.c (revision 152909) @@ -1,1149 +1,1167 @@ /* savage_state.c -- State and drawing support for Savage * * Copyright 2004 Felix Kuehling * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * $FreeBSD$ */ -#include "drmP.h" -#include "savage_drm.h" -#include "savage_drv.h" +#include +__FBSDID("$FreeBSD$"); +#include "dev/drm/drmP.h" +#include "dev/drm/savage_drm.h" +#include "dev/drm/savage_drv.h" void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv, - drm_clip_rect_t *pbox) + const drm_clip_rect_t *pbox) { uint32_t scstart = dev_priv->state.s3d.new_scstart; uint32_t scend = dev_priv->state.s3d.new_scend; scstart = (scstart & ~SAVAGE_SCISSOR_MASK_S3D) | ((uint32_t)pbox->x1 & 0x000007ff) | (((uint32_t)pbox->y1 << 16) & 0x07ff0000); scend = (scend & ~SAVAGE_SCISSOR_MASK_S3D) | (((uint32_t)pbox->x2-1) & 0x000007ff) | ((((uint32_t)pbox->y2-1) << 16) & 0x07ff0000); if (scstart != dev_priv->state.s3d.scstart || scend != dev_priv->state.s3d.scend) { DMA_LOCALS; BEGIN_DMA(4); DMA_WRITE(BCI_CMD_WAIT|BCI_CMD_WAIT_3D); DMA_SET_REGISTERS(SAVAGE_SCSTART_S3D, 2); DMA_WRITE(scstart); DMA_WRITE(scend); dev_priv->state.s3d.scstart = scstart; dev_priv->state.s3d.scend = scend; dev_priv->waiting = 1; DMA_COMMIT(); } } void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv, - drm_clip_rect_t *pbox) + const drm_clip_rect_t *pbox) { uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0; uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1; drawctrl0 = (drawctrl0 & ~SAVAGE_SCISSOR_MASK_S4) | ((uint32_t)pbox->x1 & 0x000007ff) | (((uint32_t)pbox->y1 << 12) & 0x00fff000); drawctrl1 = (drawctrl1 & ~SAVAGE_SCISSOR_MASK_S4) | (((uint32_t)pbox->x2-1) & 0x000007ff) | ((((uint32_t)pbox->y2-1) << 12) & 0x00fff000); if (drawctrl0 != dev_priv->state.s4.drawctrl0 || drawctrl1 != dev_priv->state.s4.drawctrl1) { DMA_LOCALS; BEGIN_DMA(4); DMA_WRITE(BCI_CMD_WAIT|BCI_CMD_WAIT_3D); DMA_SET_REGISTERS(SAVAGE_DRAWCTRL0_S4, 2); DMA_WRITE(drawctrl0); DMA_WRITE(drawctrl1); dev_priv->state.s4.drawctrl0 = drawctrl0; dev_priv->state.s4.drawctrl1 = drawctrl1; dev_priv->waiting = 1; DMA_COMMIT(); } } static int savage_verify_texaddr(drm_savage_private_t *dev_priv, int unit, uint32_t addr) { if ((addr & 6) != 2) { /* reserved bits */ DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr); return DRM_ERR(EINVAL); } if (!(addr & 1)) { /* local */ addr &= ~7; if (addr < dev_priv->texture_offset || addr >= dev_priv->texture_offset+dev_priv->texture_size) { DRM_ERROR("bad texAddr%d %08x (local addr out of range)\n", unit, addr); return DRM_ERR(EINVAL); } } else { /* AGP */ if (!dev_priv->agp_textures) { DRM_ERROR("bad texAddr%d %08x (AGP not available)\n", unit, addr); return DRM_ERR(EINVAL); } addr &= ~7; if (addr < dev_priv->agp_textures->offset || addr >= (dev_priv->agp_textures->offset + dev_priv->agp_textures->size)) { DRM_ERROR("bad texAddr%d %08x (AGP addr out of range)\n", unit, addr); return DRM_ERR(EINVAL); } } return 0; } #define SAVE_STATE(reg,where) \ if(start <= reg && start+count > reg) \ - DRM_GET_USER_UNCHECKED(dev_priv->state.where, ®s[reg-start]) + dev_priv->state.where = regs[reg - start] #define SAVE_STATE_MASK(reg,where,mask) do { \ if(start <= reg && start+count > reg) { \ uint32_t tmp; \ - DRM_GET_USER_UNCHECKED(tmp, ®s[reg-start]); \ + tmp = regs[reg - start]; \ dev_priv->state.where = (tmp & (mask)) | \ (dev_priv->state.where & ~(mask)); \ } \ } while (0) static int savage_verify_state_s3d(drm_savage_private_t *dev_priv, unsigned int start, unsigned int count, - const uint32_t __user *regs) + const uint32_t *regs) { if (start < SAVAGE_TEXPALADDR_S3D || start+count-1 > SAVAGE_DESTTEXRWWATERMARK_S3D) { DRM_ERROR("invalid register range (0x%04x-0x%04x)\n", start, start+count-1); return DRM_ERR(EINVAL); } SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart, ~SAVAGE_SCISSOR_MASK_S3D); SAVE_STATE_MASK(SAVAGE_SCEND_S3D, s3d.new_scend, ~SAVAGE_SCISSOR_MASK_S3D); /* if any texture regs were changed ... */ if (start <= SAVAGE_TEXCTRL_S3D && start+count > SAVAGE_TEXPALADDR_S3D) { /* ... check texture state */ SAVE_STATE(SAVAGE_TEXCTRL_S3D, s3d.texctrl); SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr); if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK) return savage_verify_texaddr( dev_priv, 0, dev_priv->state.s3d.texaddr); } return 0; } static int savage_verify_state_s4(drm_savage_private_t *dev_priv, unsigned int start, unsigned int count, - const uint32_t __user *regs) + const uint32_t *regs) { int ret = 0; if (start < SAVAGE_DRAWLOCALCTRL_S4 || start+count-1 > SAVAGE_TEXBLENDCOLOR_S4) { DRM_ERROR("invalid register range (0x%04x-0x%04x)\n", start, start+count-1); return DRM_ERR(EINVAL); } SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0, ~SAVAGE_SCISSOR_MASK_S4); SAVE_STATE_MASK(SAVAGE_DRAWCTRL1_S4, s4.new_drawctrl1, ~SAVAGE_SCISSOR_MASK_S4); /* if any texture regs were changed ... */ if (start <= SAVAGE_TEXDESCR_S4 && start+count > SAVAGE_TEXPALADDR_S4) { /* ... check texture state */ SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr); SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0); SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1); if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK) ret |= savage_verify_texaddr( dev_priv, 0, dev_priv->state.s4.texaddr0); if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK) ret |= savage_verify_texaddr( dev_priv, 1, dev_priv->state.s4.texaddr1); } return ret; } #undef SAVE_STATE #undef SAVE_STATE_MASK static int savage_dispatch_state(drm_savage_private_t *dev_priv, const drm_savage_cmd_header_t *cmd_header, - const uint32_t __user *regs) + const uint32_t *regs) { - DMA_LOCALS; unsigned int count = cmd_header->state.count; unsigned int start = cmd_header->state.start; unsigned int count2 = 0; unsigned int bci_size; int ret; + DMA_LOCALS; if (!count) return 0; - if (DRM_VERIFYAREA_READ(regs, count*4)) - return DRM_ERR(EFAULT); - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { ret = savage_verify_state_s3d(dev_priv, start, count, regs); if (ret != 0) return ret; /* scissor regs are emitted in savage_dispatch_draw */ if (start < SAVAGE_SCSTART_S3D) { if (start+count > SAVAGE_SCEND_S3D+1) count2 = count - (SAVAGE_SCEND_S3D+1 - start); if (start+count > SAVAGE_SCSTART_S3D) count = SAVAGE_SCSTART_S3D - start; } else if (start <= SAVAGE_SCEND_S3D) { if (start+count > SAVAGE_SCEND_S3D+1) { count -= SAVAGE_SCEND_S3D+1 - start; start = SAVAGE_SCEND_S3D+1; } else return 0; } } else { ret = savage_verify_state_s4(dev_priv, start, count, regs); if (ret != 0) return ret; /* scissor regs are emitted in savage_dispatch_draw */ if (start < SAVAGE_DRAWCTRL0_S4) { if (start+count > SAVAGE_DRAWCTRL1_S4+1) count2 = count - (SAVAGE_DRAWCTRL1_S4+1 - start); if (start+count > SAVAGE_DRAWCTRL0_S4) count = SAVAGE_DRAWCTRL0_S4 - start; } else if (start <= SAVAGE_DRAWCTRL1_S4) { if (start+count > SAVAGE_DRAWCTRL1_S4+1) { count -= SAVAGE_DRAWCTRL1_S4+1 - start; start = SAVAGE_DRAWCTRL1_S4+1; } else return 0; } } bci_size = count + (count+254)/255 + count2 + (count2+254)/255; if (cmd_header->state.global) { BEGIN_DMA(bci_size+1); DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D); dev_priv->waiting = 1; } else { BEGIN_DMA(bci_size); } do { while (count > 0) { unsigned int n = count < 255 ? count : 255; DMA_SET_REGISTERS(start, n); - DMA_COPY_FROM_USER(regs, n); + DMA_COPY(regs, n); count -= n; start += n; regs += n; } start += 2; regs += 2; count = count2; count2 = 0; } while (count); DMA_COMMIT(); return 0; } static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv, const drm_savage_cmd_header_t *cmd_header, const drm_buf_t *dmabuf) { - BCI_LOCALS; unsigned char reorder = 0; unsigned int prim = cmd_header->prim.prim; unsigned int skip = cmd_header->prim.skip; unsigned int n = cmd_header->prim.count; unsigned int start = cmd_header->prim.start; unsigned int i; + BCI_LOCALS; if (!dmabuf) { DRM_ERROR("called without dma buffers!\n"); return DRM_ERR(EINVAL); } if (!n) return 0; switch (prim) { case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of vertices %u in TRILIST\n", n); return DRM_ERR(EINVAL); } break; case SAVAGE_PRIM_TRISTRIP: case SAVAGE_PRIM_TRIFAN: if (n < 3) { DRM_ERROR("wrong number of vertices %u in TRIFAN/STRIP\n", n); return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip != 0) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); return DRM_ERR(EINVAL); } } else { unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) - (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) - (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1); if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); return DRM_ERR(EINVAL); } if (reorder) { DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); return DRM_ERR(EINVAL); } } if (start + n > dmabuf->total/32) { DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n", start, start + n - 1, dmabuf->total/32); return DRM_ERR(EINVAL); } /* Vertex DMA doesn't work with command DMA at the same time, * so we use BCI_... to submit commands here. Flush buffered * faked DMA first. */ DMA_FLUSH(); if (dmabuf->bus_address != dev_priv->state.common.vbaddr) { BEGIN_BCI(2); BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1); BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type); dev_priv->state.common.vbaddr = dmabuf->bus_address; } if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) { /* Workaround for what looks like a hardware bug. If a * WAIT_3D_IDLE was emitted some time before the * indexed drawing command then the engine will lock * up. There are two known workarounds: * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */ BEGIN_BCI(63); for (i = 0; i < 63; ++i) BCI_WRITE(BCI_CMD_WAIT); dev_priv->waiting = 0; } prim <<= 25; while (n != 0) { /* Can emit up to 255 indices (85 triangles) at once. */ unsigned int count = n > 255 ? 255 : n; if (reorder) { /* Need to reorder indices for correct flat * shading while preserving the clock sense * for correct culling. Only on Savage3D. */ int reorder[3] = {-1, -1, -1}; reorder[start%3] = 2; BEGIN_BCI((count+1+1)/2); BCI_DRAW_INDICES_S3D(count, prim, start+2); for (i = start+1; i+1 < start+count; i += 2) BCI_WRITE((i + reorder[i % 3]) | ((i+1 + reorder[(i+1) % 3]) << 16)); if (i < start+count) BCI_WRITE(i + reorder[i%3]); } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { BEGIN_BCI((count+1+1)/2); BCI_DRAW_INDICES_S3D(count, prim, start); for (i = start+1; i+1 < start+count; i += 2) BCI_WRITE(i | ((i+1) << 16)); if (i < start+count) BCI_WRITE(i); } else { BEGIN_BCI((count+2+1)/2); BCI_DRAW_INDICES_S4(count, prim, skip); for (i = start; i+1 < start+count; i += 2) BCI_WRITE(i | ((i+1) << 16)); if (i < start+count) BCI_WRITE(i); } start += count; n -= count; prim |= BCI_CMD_DRAW_CONT; } return 0; } static int savage_dispatch_vb_prim(drm_savage_private_t *dev_priv, const drm_savage_cmd_header_t *cmd_header, - const uint32_t __user *vtxbuf, - unsigned int vb_size, + const uint32_t *vtxbuf, unsigned int vb_size, unsigned int vb_stride) { - DMA_LOCALS; unsigned char reorder = 0; unsigned int prim = cmd_header->prim.prim; unsigned int skip = cmd_header->prim.skip; unsigned int n = cmd_header->prim.count; unsigned int start = cmd_header->prim.start; unsigned int vtx_size; unsigned int i; + DMA_LOCALS; if (!n) return 0; switch (prim) { case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of vertices %u in TRILIST\n", n); return DRM_ERR(EINVAL); } break; case SAVAGE_PRIM_TRISTRIP: case SAVAGE_PRIM_TRIFAN: if (n < 3) { DRM_ERROR("wrong number of vertices %u in TRIFAN/STRIP\n", n); return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip > SAVAGE_SKIP_ALL_S3D) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); return DRM_ERR(EINVAL); } vtx_size = 8; /* full vertex */ } else { if (skip > SAVAGE_SKIP_ALL_S4) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); return DRM_ERR(EINVAL); } vtx_size = 10; /* full vertex */ } vtx_size -= (skip & 1) + (skip >> 1 & 1) + (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) + (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1); if (vtx_size > vb_stride) { DRM_ERROR("vertex size greater than vb stride (%u > %u)\n", vtx_size, vb_stride); return DRM_ERR(EINVAL); } if (start + n > vb_size / (vb_stride*4)) { DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n", start, start + n - 1, vb_size / (vb_stride*4)); return DRM_ERR(EINVAL); } prim <<= 25; while (n != 0) { /* Can emit up to 255 vertices (85 triangles) at once. */ unsigned int count = n > 255 ? 255 : n; if (reorder) { /* Need to reorder vertices for correct flat * shading while preserving the clock sense * for correct culling. Only on Savage3D. */ int reorder[3] = {-1, -1, -1}; reorder[start%3] = 2; BEGIN_DMA(count*vtx_size+1); DMA_DRAW_PRIMITIVE(count, prim, skip); for (i = start; i < start+count; ++i) { unsigned int j = i + reorder[i % 3]; - DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j], - vtx_size); + DMA_COPY(&vtxbuf[vb_stride*j], vtx_size); } DMA_COMMIT(); } else { BEGIN_DMA(count*vtx_size+1); DMA_DRAW_PRIMITIVE(count, prim, skip); if (vb_stride == vtx_size) { - DMA_COPY_FROM_USER(&vtxbuf[vb_stride*start], - vtx_size*count); + DMA_COPY(&vtxbuf[vb_stride*start], + vtx_size*count); } else { for (i = start; i < start+count; ++i) { - DMA_COPY_FROM_USER( - &vtxbuf[vb_stride*i], - vtx_size); + DMA_COPY(&vtxbuf[vb_stride*i], + vtx_size); } } DMA_COMMIT(); } start += count; n -= count; prim |= BCI_CMD_DRAW_CONT; } return 0; } static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv, const drm_savage_cmd_header_t *cmd_header, - const uint16_t __user *usr_idx, + const uint16_t *idx, const drm_buf_t *dmabuf) { - BCI_LOCALS; unsigned char reorder = 0; unsigned int prim = cmd_header->idx.prim; unsigned int skip = cmd_header->idx.skip; unsigned int n = cmd_header->idx.count; unsigned int i; + BCI_LOCALS; if (!dmabuf) { DRM_ERROR("called without dma buffers!\n"); return DRM_ERR(EINVAL); } if (!n) return 0; switch (prim) { case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of indices %u in TRILIST\n", n); return DRM_ERR(EINVAL); } break; case SAVAGE_PRIM_TRISTRIP: case SAVAGE_PRIM_TRIFAN: if (n < 3) { DRM_ERROR("wrong number of indices %u in TRIFAN/STRIP\n", n); return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip != 0) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); return DRM_ERR(EINVAL); } } else { unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) - (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) - (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1); if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); return DRM_ERR(EINVAL); } if (reorder) { DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); return DRM_ERR(EINVAL); } } /* Vertex DMA doesn't work with command DMA at the same time, * so we use BCI_... to submit commands here. Flush buffered * faked DMA first. */ DMA_FLUSH(); if (dmabuf->bus_address != dev_priv->state.common.vbaddr) { BEGIN_BCI(2); BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1); BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type); dev_priv->state.common.vbaddr = dmabuf->bus_address; } if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) { /* Workaround for what looks like a hardware bug. If a * WAIT_3D_IDLE was emitted some time before the * indexed drawing command then the engine will lock * up. There are two known workarounds: * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */ BEGIN_BCI(63); for (i = 0; i < 63; ++i) BCI_WRITE(BCI_CMD_WAIT); dev_priv->waiting = 0; } prim <<= 25; while (n != 0) { /* Can emit up to 255 indices (85 triangles) at once. */ unsigned int count = n > 255 ? 255 : n; - /* Is it ok to allocate 510 bytes on the stack in an ioctl? */ - uint16_t idx[255]; - /* Copy and check indices */ - DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count*2); + /* check indices */ for (i = 0; i < count; ++i) { if (idx[i] > dmabuf->total/32) { DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", i, idx[i], dmabuf->total/32); return DRM_ERR(EINVAL); } } if (reorder) { /* Need to reorder indices for correct flat * shading while preserving the clock sense * for correct culling. Only on Savage3D. */ int reorder[3] = {2, -1, -1}; BEGIN_BCI((count+1+1)/2); BCI_DRAW_INDICES_S3D(count, prim, idx[2]); for (i = 1; i+1 < count; i += 2) BCI_WRITE(idx[i + reorder[i % 3]] | (idx[i+1 + reorder[(i+1) % 3]] << 16)); if (i < count) BCI_WRITE(idx[i + reorder[i%3]]); } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { BEGIN_BCI((count+1+1)/2); BCI_DRAW_INDICES_S3D(count, prim, idx[0]); for (i = 1; i+1 < count; i += 2) BCI_WRITE(idx[i] | (idx[i+1] << 16)); if (i < count) BCI_WRITE(idx[i]); } else { BEGIN_BCI((count+2+1)/2); BCI_DRAW_INDICES_S4(count, prim, skip); for (i = 0; i+1 < count; i += 2) BCI_WRITE(idx[i] | (idx[i+1] << 16)); if (i < count) BCI_WRITE(idx[i]); } - usr_idx += count; + idx += count; n -= count; prim |= BCI_CMD_DRAW_CONT; } return 0; } static int savage_dispatch_vb_idx(drm_savage_private_t *dev_priv, const drm_savage_cmd_header_t *cmd_header, - const uint16_t __user *usr_idx, - const uint32_t __user *vtxbuf, + const uint16_t *idx, + const uint32_t *vtxbuf, unsigned int vb_size, unsigned int vb_stride) { - DMA_LOCALS; unsigned char reorder = 0; unsigned int prim = cmd_header->idx.prim; unsigned int skip = cmd_header->idx.skip; unsigned int n = cmd_header->idx.count; unsigned int vtx_size; unsigned int i; + DMA_LOCALS; if (!n) return 0; switch (prim) { case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of indices %u in TRILIST\n", n); return DRM_ERR(EINVAL); } break; case SAVAGE_PRIM_TRISTRIP: case SAVAGE_PRIM_TRIFAN: if (n < 3) { DRM_ERROR("wrong number of indices %u in TRIFAN/STRIP\n", n); return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip > SAVAGE_SKIP_ALL_S3D) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); return DRM_ERR(EINVAL); } vtx_size = 8; /* full vertex */ } else { if (skip > SAVAGE_SKIP_ALL_S4) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); return DRM_ERR(EINVAL); } vtx_size = 10; /* full vertex */ } vtx_size -= (skip & 1) + (skip >> 1 & 1) + (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) + (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1); if (vtx_size > vb_stride) { DRM_ERROR("vertex size greater than vb stride (%u > %u)\n", vtx_size, vb_stride); return DRM_ERR(EINVAL); } prim <<= 25; while (n != 0) { /* Can emit up to 255 vertices (85 triangles) at once. */ unsigned int count = n > 255 ? 255 : n; - /* Is it ok to allocate 510 bytes on the stack in an ioctl? */ - uint16_t idx[255]; - /* Copy and check indices */ - DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count*2); + /* Check indices */ for (i = 0; i < count; ++i) { if (idx[i] > vb_size / (vb_stride*4)) { DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", i, idx[i], vb_size / (vb_stride*4)); return DRM_ERR(EINVAL); } } if (reorder) { /* Need to reorder vertices for correct flat * shading while preserving the clock sense * for correct culling. Only on Savage3D. */ int reorder[3] = {2, -1, -1}; BEGIN_DMA(count*vtx_size+1); DMA_DRAW_PRIMITIVE(count, prim, skip); for (i = 0; i < count; ++i) { unsigned int j = idx[i + reorder[i % 3]]; - DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j], - vtx_size); + DMA_COPY(&vtxbuf[vb_stride*j], vtx_size); } DMA_COMMIT(); } else { BEGIN_DMA(count*vtx_size+1); DMA_DRAW_PRIMITIVE(count, prim, skip); for (i = 0; i < count; ++i) { unsigned int j = idx[i]; - DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j], - vtx_size); + DMA_COPY(&vtxbuf[vb_stride*j], vtx_size); } DMA_COMMIT(); } - usr_idx += count; + idx += count; n -= count; prim |= BCI_CMD_DRAW_CONT; } return 0; } static int savage_dispatch_clear(drm_savage_private_t *dev_priv, const drm_savage_cmd_header_t *cmd_header, - const drm_savage_cmd_header_t __user *data, + const drm_savage_cmd_header_t *data, unsigned int nbox, - const drm_clip_rect_t __user *usr_boxes) + const drm_clip_rect_t *boxes) { - DMA_LOCALS; - unsigned int flags = cmd_header->clear0.flags, mask, value; + unsigned int flags = cmd_header->clear0.flags; unsigned int clear_cmd; unsigned int i, nbufs; + DMA_LOCALS; if (nbox == 0) return 0; - DRM_GET_USER_UNCHECKED(mask, &((drm_savage_cmd_header_t*)data) - ->clear1.mask); - DRM_GET_USER_UNCHECKED(value, &((drm_savage_cmd_header_t*)data) - ->clear1.value); - clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP | BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW; BCI_CMD_SET_ROP(clear_cmd,0xCC); nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) + ((flags & SAVAGE_BACK) ? 1 : 0) + ((flags & SAVAGE_DEPTH) ? 1 : 0); if (nbufs == 0) return 0; - if (mask != 0xffffffff) { + if (data->clear1.mask != 0xffffffff) { /* set mask */ BEGIN_DMA(2); DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1); - DMA_WRITE(mask); + DMA_WRITE(data->clear1.mask); DMA_COMMIT(); } for (i = 0; i < nbox; ++i) { - drm_clip_rect_t box; unsigned int x, y, w, h; unsigned int buf; - DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box)); - x = box.x1, y = box.y1; - w = box.x2 - box.x1; - h = box.y2 - box.y1; + + x = boxes[i].x1, y = boxes[i].y1; + w = boxes[i].x2 - boxes[i].x1; + h = boxes[i].y2 - boxes[i].y1; BEGIN_DMA(nbufs*6); for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) { if (!(flags & buf)) continue; DMA_WRITE(clear_cmd); switch(buf) { case SAVAGE_FRONT: DMA_WRITE(dev_priv->front_offset); DMA_WRITE(dev_priv->front_bd); break; case SAVAGE_BACK: DMA_WRITE(dev_priv->back_offset); DMA_WRITE(dev_priv->back_bd); break; case SAVAGE_DEPTH: DMA_WRITE(dev_priv->depth_offset); DMA_WRITE(dev_priv->depth_bd); break; } - DMA_WRITE(value); + DMA_WRITE(data->clear1.value); DMA_WRITE(BCI_X_Y(x, y)); DMA_WRITE(BCI_W_H(w, h)); } DMA_COMMIT(); } - if (mask != 0xffffffff) { + if (data->clear1.mask != 0xffffffff) { /* reset mask */ BEGIN_DMA(2); DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1); DMA_WRITE(0xffffffff); DMA_COMMIT(); } return 0; } static int savage_dispatch_swap(drm_savage_private_t *dev_priv, - unsigned int nbox, - const drm_clip_rect_t __user *usr_boxes) + unsigned int nbox, const drm_clip_rect_t *boxes) { - DMA_LOCALS; unsigned int swap_cmd; unsigned int i; + DMA_LOCALS; if (nbox == 0) return 0; swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP | BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD; BCI_CMD_SET_ROP(swap_cmd,0xCC); for (i = 0; i < nbox; ++i) { - drm_clip_rect_t box; - DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box)); - BEGIN_DMA(6); DMA_WRITE(swap_cmd); DMA_WRITE(dev_priv->back_offset); DMA_WRITE(dev_priv->back_bd); - DMA_WRITE(BCI_X_Y(box.x1, box.y1)); - DMA_WRITE(BCI_X_Y(box.x1, box.y1)); - DMA_WRITE(BCI_W_H(box.x2-box.x1, box.y2-box.y1)); + DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1)); + DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1)); + DMA_WRITE(BCI_W_H(boxes[i].x2-boxes[i].x1, + boxes[i].y2-boxes[i].y1)); DMA_COMMIT(); } return 0; } static int savage_dispatch_draw(drm_savage_private_t *dev_priv, - const drm_savage_cmd_header_t __user *start, - const drm_savage_cmd_header_t __user *end, + const drm_savage_cmd_header_t *start, + const drm_savage_cmd_header_t *end, const drm_buf_t *dmabuf, - const unsigned int __user *usr_vtxbuf, + const unsigned int *vtxbuf, unsigned int vb_size, unsigned int vb_stride, unsigned int nbox, - const drm_clip_rect_t __user *usr_boxes) + const drm_clip_rect_t *boxes) { unsigned int i, j; int ret; for (i = 0; i < nbox; ++i) { - drm_clip_rect_t box; - const drm_savage_cmd_header_t __user *usr_cmdbuf; - DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box)); - dev_priv->emit_clip_rect(dev_priv, &box); + const drm_savage_cmd_header_t *cmdbuf; + dev_priv->emit_clip_rect(dev_priv, &boxes[i]); - usr_cmdbuf = start; - while (usr_cmdbuf < end) { + cmdbuf = start; + while (cmdbuf < end) { drm_savage_cmd_header_t cmd_header; - DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf, - sizeof(cmd_header)); - usr_cmdbuf++; + cmd_header = *cmdbuf; + cmdbuf++; switch (cmd_header.cmd.cmd) { case SAVAGE_CMD_DMA_PRIM: ret = savage_dispatch_dma_prim( dev_priv, &cmd_header, dmabuf); break; case SAVAGE_CMD_VB_PRIM: ret = savage_dispatch_vb_prim( dev_priv, &cmd_header, - (uint32_t __user *)usr_vtxbuf, - vb_size, vb_stride); + vtxbuf, vb_size, vb_stride); break; case SAVAGE_CMD_DMA_IDX: j = (cmd_header.idx.count + 3) / 4; /* j was check in savage_bci_cmdbuf */ - ret = savage_dispatch_dma_idx( - dev_priv, &cmd_header, - (uint16_t __user *)usr_cmdbuf, + ret = savage_dispatch_dma_idx(dev_priv, + &cmd_header, (const uint16_t *)cmdbuf, dmabuf); - usr_cmdbuf += j; + cmdbuf += j; break; case SAVAGE_CMD_VB_IDX: j = (cmd_header.idx.count + 3) / 4; /* j was check in savage_bci_cmdbuf */ - ret = savage_dispatch_vb_idx( - dev_priv, &cmd_header, - (uint16_t __user *)usr_cmdbuf, - (uint32_t __user *)usr_vtxbuf, - vb_size, vb_stride); - usr_cmdbuf += j; + ret = savage_dispatch_vb_idx(dev_priv, + &cmd_header, (const uint16_t *)cmdbuf, + (const uint32_t *)vtxbuf, vb_size, + vb_stride); + cmdbuf += j; break; default: /* What's the best return code? EFAULT? */ DRM_ERROR("IMPLEMENTATION ERROR: " "non-drawing-command %d\n", cmd_header.cmd.cmd); return DRM_ERR(EINVAL); } if (ret != 0) return ret; } } return 0; } int savage_bci_cmdbuf(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *dmabuf; drm_savage_cmdbuf_t cmdbuf; - drm_savage_cmd_header_t __user *usr_cmdbuf; - drm_savage_cmd_header_t __user *first_draw_cmd; - unsigned int __user *usr_vtxbuf; - drm_clip_rect_t __user *usr_boxes; + drm_savage_cmd_header_t *kcmd_addr = NULL; + drm_savage_cmd_header_t *first_draw_cmd; + unsigned int *kvb_addr = NULL; + drm_clip_rect_t *kbox_addr = NULL; unsigned int i, j; int ret = 0; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *)data, sizeof(cmdbuf)); if (dma && dma->buflist) { if (cmdbuf.dma_idx > dma->buf_count) { DRM_ERROR("vertex buffer index %u out of range (0-%u)\n", cmdbuf.dma_idx, dma->buf_count-1); return DRM_ERR(EINVAL); } dmabuf = dma->buflist[cmdbuf.dma_idx]; } else { dmabuf = NULL; } - usr_cmdbuf = (drm_savage_cmd_header_t __user *)cmdbuf.cmd_addr; - usr_vtxbuf = (unsigned int __user *)cmdbuf.vb_addr; - usr_boxes = (drm_clip_rect_t __user *)cmdbuf.box_addr; - if ((cmdbuf.size && DRM_VERIFYAREA_READ(usr_cmdbuf, cmdbuf.size*8)) || - (cmdbuf.vb_size && DRM_VERIFYAREA_READ( - usr_vtxbuf, cmdbuf.vb_size)) || - (cmdbuf.nbox && DRM_VERIFYAREA_READ( - usr_boxes, cmdbuf.nbox*sizeof(drm_clip_rect_t)))) - return DRM_ERR(EFAULT); + /* Copy the user buffers into kernel temporary areas. This hasn't been + * a performance loss compared to VERIFYAREA_READ/ + * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct + * for locking on FreeBSD. + */ + if (cmdbuf.size) { + kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); + if (kcmd_addr == NULL) + return ENOMEM; + if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, + cmdbuf.size * 8)) + { + drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER); + return DRM_ERR(EFAULT); + } + cmdbuf.cmd_addr = kcmd_addr; + } + if (cmdbuf.vb_size) { + kvb_addr = drm_alloc(cmdbuf.vb_size, DRM_MEM_DRIVER); + if (kvb_addr == NULL) { + ret = DRM_ERR(ENOMEM); + goto done; + } + + if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr, + cmdbuf.vb_size)) { + ret = DRM_ERR(EFAULT); + goto done; + } + cmdbuf.vb_addr = kvb_addr; + } + if (cmdbuf.nbox) { + kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t), + DRM_MEM_DRIVER); + if (kbox_addr == NULL) { + ret = DRM_ERR(ENOMEM); + goto done; + } + + if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr, + cmdbuf.nbox * sizeof(drm_clip_rect_t))) { + ret = DRM_ERR(EFAULT); + goto done; + } + cmdbuf.box_addr = kbox_addr; + } + /* Make sure writes to DMA buffers are finished before sending * DMA commands to the graphics hardware. */ DRM_MEMORYBARRIER(); /* Coming from user space. Don't know if the Xserver has * emitted wait commands. Assuming the worst. */ dev_priv->waiting = 1; i = 0; first_draw_cmd = NULL; while (i < cmdbuf.size) { drm_savage_cmd_header_t cmd_header; - DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf, - sizeof(cmd_header)); - usr_cmdbuf++; + cmd_header = *(drm_savage_cmd_header_t *)cmdbuf.cmd_addr; + cmdbuf.cmd_addr++; i++; /* Group drawing commands with same state to minimize * iterations over clip rects. */ j = 0; switch (cmd_header.cmd.cmd) { case SAVAGE_CMD_DMA_IDX: case SAVAGE_CMD_VB_IDX: j = (cmd_header.idx.count + 3) / 4; if (i + j > cmdbuf.size) { DRM_ERROR("indexed drawing command extends " "beyond end of command buffer\n"); DMA_FLUSH(); return DRM_ERR(EINVAL); } /* fall through */ case SAVAGE_CMD_DMA_PRIM: case SAVAGE_CMD_VB_PRIM: if (!first_draw_cmd) - first_draw_cmd = usr_cmdbuf-1; - usr_cmdbuf += j; + first_draw_cmd = cmdbuf.cmd_addr-1; + cmdbuf.cmd_addr += j; i += j; break; default: if (first_draw_cmd) { ret = savage_dispatch_draw ( - dev_priv, first_draw_cmd, usr_cmdbuf-1, - dmabuf, usr_vtxbuf, cmdbuf.vb_size, + dev_priv, first_draw_cmd, + cmdbuf.cmd_addr-1, + dmabuf, cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride, - cmdbuf.nbox, usr_boxes); + cmdbuf.nbox, cmdbuf.box_addr); if (ret != 0) return ret; first_draw_cmd = NULL; } } if (first_draw_cmd) continue; switch (cmd_header.cmd.cmd) { case SAVAGE_CMD_STATE: j = (cmd_header.state.count + 1) / 2; if (i + j > cmdbuf.size) { DRM_ERROR("command SAVAGE_CMD_STATE extends " "beyond end of command buffer\n"); DMA_FLUSH(); - return DRM_ERR(EINVAL); + ret = DRM_ERR(EINVAL); + goto done; } - ret = savage_dispatch_state( - dev_priv, &cmd_header, - (uint32_t __user *)usr_cmdbuf); - usr_cmdbuf += j; + ret = savage_dispatch_state(dev_priv, &cmd_header, + (const uint32_t *)cmdbuf.cmd_addr); + cmdbuf.cmd_addr += j; i += j; break; case SAVAGE_CMD_CLEAR: if (i + 1 > cmdbuf.size) { DRM_ERROR("command SAVAGE_CMD_CLEAR extends " "beyond end of command buffer\n"); DMA_FLUSH(); - return DRM_ERR(EINVAL); + ret = DRM_ERR(EINVAL); + goto done; } ret = savage_dispatch_clear(dev_priv, &cmd_header, - usr_cmdbuf, - cmdbuf.nbox, usr_boxes); - usr_cmdbuf++; + cmdbuf.cmd_addr, + cmdbuf.nbox, cmdbuf.box_addr); + cmdbuf.cmd_addr++; i++; break; case SAVAGE_CMD_SWAP: - ret = savage_dispatch_swap(dev_priv, - cmdbuf.nbox, usr_boxes); + ret = savage_dispatch_swap(dev_priv, cmdbuf.nbox, + cmdbuf.box_addr); break; default: DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd); DMA_FLUSH(); - return DRM_ERR(EINVAL); + ret = DRM_ERR(EINVAL); + goto done; } if (ret != 0) { DMA_FLUSH(); - return ret; + goto done; } } if (first_draw_cmd) { ret = savage_dispatch_draw ( - dev_priv, first_draw_cmd, usr_cmdbuf, dmabuf, - usr_vtxbuf, cmdbuf.vb_size, cmdbuf.vb_stride, - cmdbuf.nbox, usr_boxes); + dev_priv, first_draw_cmd, cmdbuf.cmd_addr, dmabuf, + cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride, + cmdbuf.nbox, cmdbuf.box_addr); if (ret != 0) { DMA_FLUSH(); - return ret; + goto done; } } DMA_FLUSH(); if (dmabuf && cmdbuf.discard) { drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private; uint16_t event; event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D); SET_AGE(&buf_priv->age, event, dev_priv->event_wrap); savage_freelist_put(dev, dmabuf); } - return 0; +done: + /* If we didn't need to allocate them, these'll be NULL */ + drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER); + drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER); + drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t), + DRM_MEM_DRIVER); + + return ret; } Index: head/sys/dev/drm/sis_drm.h =================================================================== --- head/sys/dev/drm/sis_drm.h (revision 152908) +++ head/sys/dev/drm/sis_drm.h (revision 152909) @@ -1,45 +1,70 @@ -/* - * $FreeBSD$ +/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */ +/*- + * Copyright 2005 Eric Anholt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * */ + +#include +__FBSDID("$FreeBSD$"); #ifndef __SIS_DRM_H__ #define __SIS_DRM_H__ /* SiS specific ioctls */ #define NOT_USED_0_3 #define DRM_SIS_FB_ALLOC 0x04 #define DRM_SIS_FB_FREE 0x05 #define NOT_USED_6_12 #define DRM_SIS_AGP_INIT 0x13 #define DRM_SIS_AGP_ALLOC 0x14 #define DRM_SIS_AGP_FREE 0x15 #define DRM_SIS_FB_INIT 0x16 #define DRM_IOCTL_SIS_FB_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_FB_ALLOC, drm_sis_mem_t) #define DRM_IOCTL_SIS_FB_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_FREE, drm_sis_mem_t) #define DRM_IOCTL_SIS_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_INIT, drm_sis_agp_t) #define DRM_IOCTL_SIS_AGP_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_ALLOC, drm_sis_mem_t) #define DRM_IOCTL_SIS_AGP_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_AGP_FREE, drm_sis_mem_t) #define DRM_IOCTL_SIS_FB_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_INIT, drm_sis_fb_t) /* #define DRM_IOCTL_SIS_FLIP DRM_IOW( 0x48, drm_sis_flip_t) #define DRM_IOCTL_SIS_FLIP_INIT DRM_IO( 0x49) #define DRM_IOCTL_SIS_FLIP_FINAL DRM_IO( 0x50) */ typedef struct { int context; unsigned int offset; unsigned int size; unsigned long free; } drm_sis_mem_t; typedef struct { unsigned int offset, size; } drm_sis_agp_t; typedef struct { unsigned int offset, size; } drm_sis_fb_t; #endif /* __SIS_DRM_H__ */ Index: head/sys/dev/drm/sis_drv.c =================================================================== --- head/sys/dev/drm/sis_drv.c (revision 152908) +++ head/sys/dev/drm/sis_drv.c (revision 152909) @@ -1,101 +1,105 @@ /* sis.c -- sis driver -*- linux-c -*- */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include "dev/drm/drmP.h" #include "dev/drm/sis_drm.h" #include "dev/drm/sis_drv.h" #include "dev/drm/drm_pciids.h" /* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */ static drm_pci_id_list_t sis_pciidlist[] = { sis_PCI_IDS }; -extern drm_ioctl_desc_t sis_ioctls[]; -extern int sis_max_ioctl; - static void sis_configure(drm_device_t *dev) { - dev->dev_priv_size = 1; /* No dev_priv */ - dev->context_ctor = sis_init_context; - dev->context_dtor = sis_final_context; + dev->driver.buf_priv_size = 1; /* No dev_priv */ + dev->driver.context_ctor = sis_init_context; + dev->driver.context_dtor = sis_final_context; - dev->driver_ioctls = sis_ioctls; - dev->max_driver_ioctl = sis_max_ioctl; + dev->driver.ioctls = sis_ioctls; + dev->driver.max_ioctl = sis_max_ioctl; - dev->driver_name = DRIVER_NAME; - dev->driver_desc = DRIVER_DESC; - dev->driver_date = DRIVER_DATE; - dev->driver_major = DRIVER_MAJOR; - dev->driver_minor = DRIVER_MINOR; - dev->driver_patchlevel = DRIVER_PATCHLEVEL; + dev->driver.name = DRIVER_NAME; + dev->driver.desc = DRIVER_DESC; + dev->driver.date = DRIVER_DATE; + dev->driver.major = DRIVER_MAJOR; + dev->driver.minor = DRIVER_MINOR; + dev->driver.patchlevel = DRIVER_PATCHLEVEL; - dev->use_agp = 1; - dev->use_mtrr = 1; + dev->driver.use_agp = 1; + dev->driver.use_mtrr = 1; } #ifdef __FreeBSD__ static int sis_probe(device_t dev) { return drm_probe(dev, sis_pciidlist); } static int sis_attach(device_t nbdev) { drm_device_t *dev = device_get_softc(nbdev); bzero(dev, sizeof(drm_device_t)); sis_configure(dev); return drm_attach(nbdev, sis_pciidlist); } static device_method_t sis_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sis_probe), DEVMETHOD(device_attach, sis_attach), DEVMETHOD(device_detach, drm_detach), { 0, 0 } }; static driver_t sis_driver = { "drm", sis_methods, sizeof(drm_device_t) }; extern devclass_t drm_devclass; DRIVER_MODULE(sisdrm, pci, sis_driver, drm_devclass, 0, 0); MODULE_DEPEND(sisdrm, drm, 1, 1, 1); #elif defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef _LKM CFDRIVER_DECL(sis, DV_TTY, NULL); +#else +CFATTACH_DECL(sis, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach, + drm_activate); +#endif #endif Index: head/sys/dev/drm/sis_drv.h =================================================================== --- head/sys/dev/drm/sis_drv.h (revision 152908) +++ head/sys/dev/drm/sis_drv.h (revision 152909) @@ -1,53 +1,58 @@ /* sis_drv.h -- Private header for sis driver -*- linux-c -*- */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #ifndef _SIS_DRV_H_ #define _SIS_DRV_H_ /* General customization: */ #define DRIVER_AUTHOR "SIS" #define DRIVER_NAME "sis" #define DRIVER_DESC "SIS 300/630/540" #define DRIVER_DATE "20030826" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 1 #define DRIVER_PATCHLEVEL 0 #include "dev/drm/sis_ds.h" typedef struct drm_sis_private { memHeap_t *AGPHeap; memHeap_t *FBHeap; } drm_sis_private_t; extern int sis_init_context(drm_device_t * dev, int context); extern int sis_final_context(drm_device_t * dev, int context); + +extern drm_ioctl_desc_t sis_ioctls[]; +extern int sis_max_ioctl; #endif Index: head/sys/dev/drm/sis_ds.c =================================================================== --- head/sys/dev/drm/sis_ds.c (revision 152908) +++ head/sys/dev/drm/sis_ds.c (revision 152909) @@ -1,300 +1,302 @@ /* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*- - * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw */ -/*- + * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw + * * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Sung-Ching Lin * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #include "dev/drm/drmP.h" #include "dev/drm/drm.h" #include "dev/drm/sis_ds.h" /* Set Data Structure, not check repeated value * temporarily used */ set_t *setInit(void) { int i; set_t *set; set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER); if (set != NULL) { for (i = 0; i < SET_SIZE; i++) { set->list[i].free_next = i + 1; set->list[i].alloc_next = -1; } set->list[SET_SIZE - 1].free_next = -1; set->free = 0; set->alloc = -1; set->trace = -1; } return set; } int setAdd(set_t * set, ITEM_TYPE item) { int free = set->free; if (free != -1) { set->list[free].val = item; set->free = set->list[free].free_next; } else { return 0; } set->list[free].alloc_next = set->alloc; set->alloc = free; set->list[free].free_next = -1; return 1; } int setDel(set_t * set, ITEM_TYPE item) { int alloc = set->alloc; int prev = -1; while (alloc != -1) { if (set->list[alloc].val == item) { if (prev != -1) set->list[prev].alloc_next = set->list[alloc].alloc_next; else set->alloc = set->list[alloc].alloc_next; break; } prev = alloc; alloc = set->list[alloc].alloc_next; } if (alloc == -1) return 0; set->list[alloc].free_next = set->free; set->free = alloc; set->list[alloc].alloc_next = -1; return 1; } /* setFirst -> setAdd -> setNext is wrong */ int setFirst(set_t * set, ITEM_TYPE * item) { if (set->alloc == -1) return 0; *item = set->list[set->alloc].val; set->trace = set->list[set->alloc].alloc_next; return 1; } int setNext(set_t * set, ITEM_TYPE * item) { if (set->trace == -1) return 0; *item = set->list[set->trace].val; set->trace = set->list[set->trace].alloc_next; return 1; } int setDestroy(set_t * set) { drm_free(set, sizeof(set_t), DRM_MEM_DRIVER); return 1; } /* * GLX Hardware Device Driver common code * Copyright (C) 1999 Wittawat Yamwong * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #define ISFREE(bptr) ((bptr)->free) memHeap_t *mmInit(int ofs, int size) { PMemBlock blocks; if (size <= 0) return NULL; blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER); if (blocks != NULL) { blocks->ofs = ofs; blocks->size = size; blocks->free = 1; return (memHeap_t *) blocks; } else return NULL; } /* Checks if a pointer 'b' is part of the heap 'heap' */ int mmBlockInHeap(memHeap_t * heap, PMemBlock b) { TMemBlock *p; if (heap == NULL || b == NULL) return 0; p = heap; while (p != NULL && p != b) { p = p->next; } if (p == b) return 1; else return 0; } static TMemBlock *SliceBlock(TMemBlock * p, int startofs, int size, int reserved, int alignment) { TMemBlock *newblock; /* break left */ if (startofs > p->ofs) { newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER); newblock->ofs = startofs; newblock->size = p->size - (startofs - p->ofs); newblock->free = 1; newblock->next = p->next; p->size -= newblock->size; p->next = newblock; p = newblock; } /* break right */ if (size < p->size) { newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER); newblock->ofs = startofs + size; newblock->size = p->size - size; newblock->free = 1; newblock->next = p->next; p->size = size; p->next = newblock; } /* p = middle block */ p->align = alignment; p->free = 0; p->reserved = reserved; return p; } PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch) { int mask, startofs, endofs; TMemBlock *p; if (heap == NULL || align2 < 0 || size <= 0) return NULL; mask = (1 << align2) - 1; startofs = 0; p = (TMemBlock *) heap; while (p != NULL) { if (ISFREE(p)) { startofs = (p->ofs + mask) & ~mask; if (startofs < startSearch) { startofs = startSearch; } endofs = startofs + size; if (endofs <= (p->ofs + p->size)) break; } p = p->next; } if (p == NULL) return NULL; p = SliceBlock(p, startofs, size, 0, mask + 1); p->heap = heap; return p; } static __inline__ int Join2Blocks(TMemBlock * p) { if (p->free && p->next && p->next->free) { TMemBlock *q = p->next; p->size += q->size; p->next = q->next; drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER); return 1; } return 0; } int mmFreeMem(PMemBlock b) { TMemBlock *p, *prev; if (b == NULL) return 0; if (b->heap == NULL) return -1; p = b->heap; prev = NULL; while (p != NULL && p != b) { prev = p; p = p->next; } if (p == NULL || p->free || p->reserved) return -1; p->free = 1; Join2Blocks(p); if (prev) Join2Blocks(prev); return 0; } Index: head/sys/dev/drm/sis_ds.h =================================================================== --- head/sys/dev/drm/sis_ds.h (revision 152908) +++ head/sys/dev/drm/sis_ds.h (revision 152909) @@ -1,146 +1,149 @@ /* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*- - * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw */ + * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw + */ /*- * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Sung-Ching Lin * - * $FreeBSD$ */ + +#include +__FBSDID("$FreeBSD$"); #ifndef __SIS_DS_H__ #define __SIS_DS_H__ /* Set Data Structure */ #define SET_SIZE 5000 typedef unsigned long ITEM_TYPE; typedef struct { ITEM_TYPE val; int alloc_next, free_next; } list_item_t; typedef struct { int alloc; int free; int trace; list_item_t list[SET_SIZE]; } set_t; set_t *setInit(void); int setAdd(set_t * set, ITEM_TYPE item); int setDel(set_t * set, ITEM_TYPE item); int setFirst(set_t * set, ITEM_TYPE * item); int setNext(set_t * set, ITEM_TYPE * item); int setDestroy(set_t * set); /* * GLX Hardware Device Driver common code * Copyright (C) 1999 Wittawat Yamwong * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ struct mem_block_t { struct mem_block_t *next; struct mem_block_t *heap; int ofs, size; int align; unsigned int free:1; unsigned int reserved:1; }; typedef struct mem_block_t TMemBlock; typedef struct mem_block_t *PMemBlock; /* a heap is just the first block in a chain */ typedef struct mem_block_t memHeap_t; static __inline__ int mmBlockSize(PMemBlock b) { return b->size; } static __inline__ int mmOffset(PMemBlock b) { return b->ofs; } static __inline__ void mmMarkReserved(PMemBlock b) { b->reserved = 1; } /* * input: total size in bytes * return: a heap pointer if OK, NULL if error */ memHeap_t *mmInit(int ofs, int size); /* * Allocate 'size' bytes with 2^align2 bytes alignment, * restrict the search to free memory after 'startSearch' * depth and back buffers should be in different 4mb banks * to get better page hits if possible * input: size = size of block * align2 = 2^align2 bytes alignment * startSearch = linear offset from start of heap to begin search * return: pointer to the allocated block, 0 if error */ PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch); /* * Returns 1 if the block 'b' is part of the heap 'heap' */ int mmBlockInHeap(PMemBlock heap, PMemBlock b); /* * Free block starts at offset * input: pointer to a block * return: 0 if OK, -1 if error */ int mmFreeMem(PMemBlock b); /* For debuging purpose. */ void mmDumpMemInfo(memHeap_t * mmInit); #endif /* __SIS_DS_H__ */ Index: head/sys/dev/drm/sis_mm.c =================================================================== --- head/sys/dev/drm/sis_mm.c (revision 152908) +++ head/sys/dev/drm/sis_mm.c (revision 152909) @@ -1,419 +1,421 @@ /* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*- - * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw */ -/*- + * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw + * * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Sung-Ching Lin * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #if defined(__linux__) && defined(CONFIG_FB_SIS) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include