diff -u --recursive --new-file v2.4.9/linux/Documentation/00-INDEX linux/Documentation/00-INDEX --- v2.4.9/linux/Documentation/00-INDEX Thu Feb 8 16:32:44 2001 +++ linux/Documentation/00-INDEX Mon Aug 27 07:44:15 2001 @@ -5,6 +5,11 @@ Please try and keep the descriptions small enough to fit on one line. Thanks -- Paul G. +Following translations are available on the WWW: + + - Japanese, maintained by the JF Project (JF@linux.or.jp), at + http://www.linux.or.jp/JF/ + 00-INDEX - this file. BUG-HUNTING diff -u --recursive --new-file v2.4.9/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.4.9/linux/Documentation/Configure.help Mon Aug 27 12:41:37 2001 +++ linux/Documentation/Configure.help Sat Sep 8 12:39:33 2001 @@ -1746,6 +1746,36 @@ similar) CPU, R4xx0 might be a safe bet. If the resulting Kernel does not work try to recompile with R3000. +CPU type +CONFIG_CPU_VR41XX + The options selects support for the NEC VR41xx series of processors. + Only choose this option if you have one of these processors as a + kernel built with this option will not run on any other type of + processor or vice versa. + +CPU feature configuration +CONFIG_CPU_ADVANCED + Saying yes here allows you to select support for various features your + CPU may or may not have. Most people should say N here. + +ll and sc instructions +CONFIG_CPU_HAS_LLSC + Say Y here if your CPU has the ll and sc instructions. Say Y here for + better performance, N if you don't know. You must say Y here for + multiprocessor machines. + +lld and scd instructions +CONFIG_CPU_HAS_LLDSCD + Say Y here if your CPU has the lld and scd instructions, the 64-bit + equivalents of ll and sc. Say Y here for better performance, N if + you don't know. You must say Y here for multiprocessor machines. + +Support for writebuffer flushing +CONFIG_CPU_HAS_WB + Say N here for slightly better performance. You must say Y here for + machines which require flushing of write buffers in software. Saying + Y is the safe option; N may result in kernel malfunction and crashes. + Support for large 64-bit configurations CONFIG_MIPS_INSANE_LARGE MIPS R10000 does support a 44 bit / 16TB address space as opposed to @@ -11478,6 +11508,45 @@ The module will be called pegasus.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +CONFIG_USB_KAWETH + Say Y here if you want to use one of the following 10Mbps only + USB Ethernet adapters based on the KLSI KL5KUSB101B chipset: + 3Com 3C19250 + ADS USB-10BT + ATEN USB Ethernet + ASANTE USB To Ethernet Adapter + AOX Endpoints USB Ethernet + Correga K.K. + D-Link DSB-650C and DU-E10 + Entrega / Portgear E45 + I-O DATA USB-ET/T + Jaton USB Ethernet Device Adapter + Kingston Technology USB Ethernet Adapter + Linksys USB10T + Mobility USB-Ethernet Adapter + NetGear EA-101 + Peracom Enet and Enet2 + Portsmith Express Ethernet Adapter + Shark Pocket Adapter + SMC 2202USB + Sony Vaio port extender + + This driver is likely to work with most 10Mbps only USB Ethernet + adapters, including some "no brand" devices. It does NOT work on + SmartBridges smartNIC or on Belkin F5U111 devices - you should use + the CATC NetMate driver for those. If you are not sure which one + you need, select both, and the correct one should be selected for + you. + + This driver makes the adapter appear as a normal Ethernet interface, + typically on eth0, if it is the only ethernet device, or perhaps on + eth1, if you have a PCI or ISA ethernet card installed. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called kaweth.o. If you want to compile it as a + module, say M here and read . + USB CATC NetMate-based Ethernet device support CONFIG_USB_CATC Say Y if you want to use one of the following 10Mbps USB Ethernet @@ -11532,6 +11601,20 @@ Say Y here in order to have the USB Mass Storage code generate verbose debugging messages. +ISD-200 USB/ATA driver +CONFIG_USB_STORAGE_ISD200 + Say Y here if you want to use USB Mass Store devices based + on the In-Systems Design ISD-200 USB/ATA bridge. + + Some of the products that use this chip are: + + - Archos Jukebox 6000 + - ISD SmartCable for Storage + - Taiwan Skymaster CD530U/DEL-0241 IDE bridge + - Sony CRX10U CD-R/RW drive + - CyQ've CQ8060A CDRW drive + - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U) + USS720 parport driver CONFIG_USB_USS720 This driver is for USB parallel port adapters that use the Lucent @@ -11604,18 +11687,22 @@ The module will be called dabusb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -PLUSB driver -CONFIG_USB_PLUSB - A driver for the Prolific PL-2302 USB-to-USB network device. This - 'USB cable' connects two hosts via a point-to-point network with - bandwidth of 5 Mbit/s. Configure this driver after connecting the - USB cable via ifconfig plusb0 10.0.0.1 pointopoint 10.0.0.2 (and - vice versa on the other host). +Host-to-Host USB networking +CONFIG_USB_USBNET + This driver supports network links over USB with USB "Network" + or "data transfer" cables, often used to network laptops to PCs. + Such cables have chips from suppliers such as NetChip and Prolific. + Intelligent USB devices could also use this approach to provide + Internet access, using standard USB cabling. + + These links will have names like "usb0", "usb1", etc. They act + like two-node Ethernets, so you can use 802.1d Ethernet Bridging + (CONFIG_BRIDGE) to simplify your network routing. - This code is also available as a module ( = code which can be + This code is also available as a kernel module (code which can be inserted in and removed from the running kernel whenever you want). - The module will be called plusb.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + The module will be called usbnet.o. If you want to compile it as a + module, say M here and read . USB Diamond Rio500 support CONFIG_USB_RIO500 @@ -15754,6 +15841,14 @@ better 32 MB RAM to avoid excessive linking time. This is only useful for kernel hackers. If unsure, say N. +Run uncached +CONFIG_MIPS_UNCACHED + If you say Y here there kernel will disable all CPU caches. This will + reduce the system's performance dramatically but can help finding + otherwise hard to track bugs. It can also useful if you're doing + hardware debugging with a logic analyzer and need to see all traffic + on the bus. + Magic System Request Key support CONFIG_MAGIC_SYSRQ If you say Y here, you will have some control over the system even @@ -16960,12 +17055,12 @@ Motorola MPC8260 CPM support CONFIG_8260 - The MPC8260 CPM (Communications Processor Module) is a typically - embedded CPU made by Motorola. Selecting this option means that - you wish to build a kernel for a machine with specifically an 8260 - for a CPU. + The MPC8260 CPM (Communications Processor Module) is a typical + embedded CPU made by Motorola. Selecting this option means that you + wish to build a kernel for a machine with specifically an 8260 for + a CPU. - If in doubt, say N. + If in doubt, say N. Workarounds for PPC601 bugs CONFIG_PPC601_SYNC_FIX @@ -16983,11 +17078,190 @@ CONFIG_ALL_PPC Linux currently supports several different kinds of PowerPC-based machines: Apple Power Macintoshes and clones (such as the Motorola - Starmax series), PReP (PowerPC Reference Platform) machines such as - the Motorola PowerStack, CHRP (Common Hardware Reference Platform), - the embedded MBX boards from Motorola and many others. Currently, - the default option is to build a kernel which works on the first - three. Support for other machines is currently incomplete. + Starmax series), PReP (PowerPC Reference Platform) machines (such + as the Motorola PowerStacks, Motorola cPCI/VME embedded systems, + and some IBM RS/6000 systems), CHRP (Common Hardware Reference + Platform), and several embedded PowerPC systems containing 4xx, 6xx, + 7xx, 8xx, 74xx, and 82xx processors. Currently, the default option + is to build a kernel which works on the first three. + +Embedded 8xx Board Type +CONFIG_RPXLITE + RPX-Lite: + Embedded Planet RPX Lite + + RPX-Classic: + Embedded Planet RPX Classic Low-fat. + + BSE-IP: + Bright Star Engineering ip-Engine. + + TQM823L: + TQM850L: + TQM855L: + TQM860L: + MPC8xx based family of mini modules, half credit card size, + up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports, + 2 x CAN bus interface, ... + Manufacturer: TQ Components, www.tq-group.de + Date of Release: October (?) 1999 + End of Life: not yet :-) + URL: + - module: http://www.denx.de/PDF/TQM8xxLHWM201.pdf + - starter kit: http://www.denx.de/PDF/STK8xxLHWM201.pdf + - images: http://www.denx.de/embedded-ppc-en.html + + FPS850L: + FingerPrint Sensor System (based on TQM850L) + Manufacturer: IKENDI AG, http://www.ikendi.com/ + Date of Release: November 1999 + End of life: end 2000 ? + URL: see TQM850L + + SPD823TS: + MPC823 based board used in the "Tele Server" product + Manufacturer: Speech Design, http://www.speech-design.de/ + Date of Release: Mid 2000 (?) + End of life: - + URL: http://www.speech-design.de/ + select "English", then "Teleteam Solutions", then "TeleServer" + + IVMS8: + MPC860 based board used in the "Integrated Voice Mail System", + Small Version (8 voice channels) + Manufacturer: Speech Design, http://www.speech-design.de/ + Date of Release: December 2000 (?) + End of life: - + URL: http://www.speech-design.de/ + + IVML24: + MPC860 based board used in the "Integrated Voice Mail System", + Large Version (24 voice channels) + Manufacturer: Speech Design, http://www.speech-design.de/ + Date of Release: March 2001 (?) + End of life: - + URL: http://www.speech-design.de/ + + SM850: + Service Module (based on TQM850L) + Manufacturer: Dependable Computer Systems, http://www.decomsys.com/ + Date of Release: end 2000 (?) + End of life: mid 2001 (?) + URL: http://www.tz-mikroelektronik.de/ServiceModule/index.html + + HERMES: + Hermes-Pro ISDN/LAN router with integrated 8 x hub + Manufacturer: Multidata Gesellschaft für Datentechnik und Informatik + http://www.multidata.de/ + Date of Release: 2000 (?) + End of life: - + URL: http://www.multidata.de/english/products/hpro.htm + + IP860: + VMEBus IP (Industry Pack) carrier board with MPC860 + Manufacturer: MicroSys GmbH, http://www.microsys.de/ + Date of Release: ? + End of life: - + URL: http://www.microsys.de/html/ip860.html + + PCU_E: + PCU = Peripheral Controller Unit, Extended + Manufacturer: Siemens AG, ICN (Information and Communication Networks) + http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html + Date of Release: April 2001 + End of life: August 2001 + URL: n. a. + +Embedded 82xx Board Type +CONFIG_EST8260 + EST8260: Wind River System, Inc. EST SBC8260 + + TQM8260: + MPC8260 based module, little larger than credit card, + up to 128 MB global + 64 MB local RAM, 32 MB Flash, + 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet, + 2 x serial ports, ... + Manufacturer: TQ Components, www.tq-group.de + Date of Release: June 2001 + End of Life: not yet :-) + URL: http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf + + PM826: + Modular system with MPC8260 CPU + Manufacturer: MicroSys GmbH, http://www.microsys.de/ + Date of Release: mid 2001 + End of life: - + URL: http://www.microsys.de/html/pm826.html + + CU824: + VMEBus Board with PCI extension with MPC8240 CPU + Manufacturer: MicroSys GmbH, http://www.microsys.de/ + Date of Release: early 2001 (?) + End of life: - + URL: http://www.microsys.de/html/cu824.html + +AltiVec Kernel Support +CONFIG_ALTIVEC + This option enables kernel support for the Altivec extensions to the + PowerPC processor. The kernel currently supports saving and restoring + altivec registers, and turning on the 'altivec enable' bit so user + processes can execute altivec instructions. + + This option is only usefully if you have a processor that supports + altivec (G4, otherwise known as 74xx series), but does not have + any affect on a non-altivec cpu (it does, however add code to the + kernel). + + If in doubt, say Y here. + +Thermal Management Support +CONFIG_TAU + G3 and G4 processors have an on-chip temperature sensor called the + 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die + temperature within 2-4 degrees celcius. This option shows the current + on-die temperature in /proc/cpuinfo if the cpu supports it. + + Unfortunately, on some chip revisions, this sensor is very inaccurate + and in some cases, does not work at all, so don't assume the cpu + temp is actually what /proc/cpuinfo says it is. + +Interrupt driven TAU driver +CONFIG_TAU_INT + The TAU supports an interrupt driven mode which causes an interrupt + whenever the temperature goes out of range. This is the fastest way + to get notified the temp has exceeded a range. With this option off, + a timer is used to re-check the temperature periodically. + + However, on some cpus it appears that the TAU interrupt hardware + is buggy and can cause a situation which would lead unexplained hard + lockups. + + Unless you are extending the TAU driver, or enjoy kernel/hardware + debugging, leave this option off. + +Average high and low temp +CONFIG_TAU_AVERAGE + The TAU hardware can compare the temperature to an upper and lower bound. + The default behavior is to show both the upper and lower bound in + /proc/cpuinfo. If the range is large, the temperature is either changing + a lot, or the TAU hardware is broken (likely on some G4's). If the range + is small (around 4 degrees), the temperature is relatively stable. + +Support for CUDA based PowerMacs +CONFIG_ADB_CUDA + This provides support for CUDA based Power Macintosh systems. This + includes most OldWorld PowerMacs, the first generation iMacs, the + Blue&White G3 and the Yikes G4 (PCI Graphics). All later models + should use CONFIG_ADB_PMU instead. + + If unsure say Y. + +Support for PMU based PowerMacs +CONFIG_ADB_PMU + This provides support for PMU based Power Macintosh systems. This + includes all PowerBooks and all AGP-based machines. + + If unsure say Y. Power management support for PowerBooks CONFIG_PMAC_PBOOK @@ -17004,13 +17278,6 @@ You may also want to compile the dma sound driver as a module and have it autoloaded. The act of removing the module shuts down the sound hardware for more power savings. - -Mac-on-Linux support -CONFIG_MOL - This option enables low-level support for Mac-on-Linux. - MOL lets you run MacOS and Linux simultaneously. Please - visit for more information. - If unsure, say Y. ADB raw keycode support CONFIG_MAC_ADBKEYCODES diff -u --recursive --new-file v2.4.9/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile --- v2.4.9/linux/Documentation/DocBook/Makefile Wed Jul 25 17:10:16 2001 +++ linux/Documentation/DocBook/Makefile Fri Sep 7 18:15:17 2001 @@ -24,10 +24,10 @@ html: $(HTML) %.eps: %.fig - -fig2dev -Leps $< $@ + fig2dev -Leps $< $@ %.jpeg: %.fig - -fig2dev -Ljpeg $< $@ + fig2dev -Ljpeg $< $@ %.sgml: %.c echo "" > $@ @@ -129,7 +129,7 @@ $(PERL) $(TOPDIR)/scripts/split-man $(TOPDIR)/Documentation/man parportbook: $(JPG-parportbook) -parportbook.ps: $(EPS-parportbook) +parportbook.ps parportbook.pdf: $(EPS-parportbook) parportbook.sgml: parportbook.tmpl $(TOPDIR)/drivers/parport/init.c $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/parport/init.c <$< >$@ diff -u --recursive --new-file v2.4.9/linux/Documentation/DocBook/parportbook.tmpl linux/Documentation/DocBook/parportbook.tmpl --- v2.4.9/linux/Documentation/DocBook/parportbook.tmpl Sun Aug 12 13:27:58 2001 +++ linux/Documentation/DocBook/parportbook.tmpl Fri Sep 7 18:15:17 2001 @@ -1654,6 +1654,16 @@ + PPGETMODE + + + + Retrieves the current IEEE 1284 mode to use for + read and write. + + + + PPGETTIME @@ -1681,6 +1691,36 @@ should be a pointer to a struct timeval. + + + + PPGETMODES + + + + Retrieves the capabilities of the hardware (i.e. the + modes field of the + parport structure). + + + + + PPSETFLAGS + + + + Sets flags on the ppdev device which can + affect future I/O operations. Available flags are: + + + + + PP_FASTWRITE + + PP_FASTREAD + + PP_W91284PIC + diff -u --recursive --new-file v2.4.9/linux/Documentation/DocBook/procfs-guide.tmpl linux/Documentation/DocBook/procfs-guide.tmpl --- v2.4.9/linux/Documentation/DocBook/procfs-guide.tmpl Tue Jul 3 17:08:18 2001 +++ linux/Documentation/DocBook/procfs-guide.tmpl Sat Sep 8 12:20:25 2001 @@ -207,7 +207,7 @@ will return NULL. describes how to do something useful with regular files. - + Note that it is specifically supported that you can pass a @@ -577,7 +577,7 @@ the owner field in the struct proc_dir_entry to THIS_MODULE. - + struct proc_dir_entry* entry; diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/Assabet linux/Documentation/arm/SA1100/Assabet --- v2.4.9/linux/Documentation/arm/SA1100/Assabet Fri May 12 11:21:20 2000 +++ linux/Documentation/arm/SA1100/Assabet Fri Sep 7 09:28:38 2001 @@ -9,38 +9,268 @@ http://www.cs.cmu.edu/~wearable/software/assabet.html -To build the kernel: +Building the kernel +------------------- + +To build the kernel with current defaults: make assabet_config - make config - [accept all defaults] + make oldconfig make dep make zImage -Typically, you'll need angelboot to load the kernel. -The following angelboot.opt file should be used: +The resulting kernel image should be available in linux/arch/arm/boot/zImage. + + +Installing a bootloader +----------------------- + +A couple of bootloaders able to boot Linux on Assabet are available: + +BLOB (http://www.lart.tudelft.nl/lartware/blob/) + + BLOB is a bootloader used within the LART project. Some contributed + patches were merged into BLOB to add support for Assabet. + +Compaq's Bootldr + John Dorsey's patch for Assabet support +(http://www.handhelds.org/Compaq/bootldr.html) +(http://www.wearablegroup.org/software/bootldr/) + + Bootldr is the bootloader developed by Compaq for the iPAQ Pocket PC. + John Dorsey has produced add-on patches to add support for Assabet and + the JFFS filesystem. + +RedBoot (http://sources.redhat.com/redboot/) + + RedBoot is a bootloader developed by Red Hat based on the eCos RTOS + hardware abstraction layer. It supports Assabet amongst many other + hardware platforms. + +RedBoot is currently the recommended choice since it's the only one to have +networking support, and is the most actively maintained. + +Brief examples on how to boot Linux with RedBoot are shown below. But first +you need to have RedBoot installed in your flash memory. A known to work +precompiled RedBoot binary is available from the following location: + +ftp://ftp.netwinder.org/users/n/nico/ +ftp://ftp.arm.linux.org.uk/pub/linux/arm/people/nico/ +ftp://ftp.handhelds.org/pub/linux/arm/sa-1100-patches/ + +Look for redboot-assabet*.tgz. Some installation infos are provided in +redboot-assabet*.txt. + + +Initial RedBoot configuration +----------------------------- + +The commands used here are explained in The RedBoot User's Guide available +on-line at http://sources.redhat.com/ecos/docs-latest/redboot/redboot.html. +Please refer to it for explanations. + +If you have a CF network card (my Assabet kit contained a CF+ LP-E from +Socket Communications Inc.), you should strongly consider using it for TFTP +file transfers. You must insert it before RedBoot runs since it can't detect +it dynamically. + +To initialize the flash directory: + + fis init -f + +To initialize the non-volatile settings, like whether you want to use BOOTP or +a static IP address, etc, use this command: + + fconfig -i + + +Writing a kernel image into flash +--------------------------------- + +First, the kernel image must be loaded into RAM. If you have the zImage file +available on a TFTP server: + + load zImage -r -b 0x100000 + +If you rather want to use Y-Modem upload over the serial port: + + load -m ymodem -r -b 0x100000 + +To write it to flash: + + fis create "Linux kernel" -b 0x100000 -l 0xc0000 + + +Booting the kernel +------------------ + +The kernel still requires a filesystem to boot. A ramdisk image can be loaded +as follows: + + load ramdisk_image.gz -r -b 0x800000 + +Again, Y-Modem upload can be used instead of TFTP by replacing the file name +by '-y ymodem'. + +Now the kernel can be retrieved from flash like this: + + fis load "Linux kernel" + +or loaded as described previously. To boot the kernel: + + exec -b 0x100000 -l 0xc0000 + +The ramdisk image could be stored into flash as well, but there are better +solutions for on-flash filesystems as mentioned below. + + +Using JFFS2 +----------- + +Using JFFS2 (the Second Journaling Flash File System) is probably the most +convenient way to store a writable filesystem into flash. JFFS2 is used in +conjunction with the MTD layer which is responsible for low-level flash +management. More information on the Linux MTD can be found on-line at: +http://www.linux-mtd.infradead.org/. A JFFS howto with some infos about +creating JFFS/JFFS2 images is available from the same site. + +For instance, a sample JFFS2 image can be retrieved from the same FTP sites +mentioned below for the precompiled RedBoot image. + +To load this file: + + load sample_img.jffs2 -r -b 0x100000 + +The result should look like: + +RedBoot> load sample_img.jffs2 -r -b 0x100000 +Raw file loaded 0x00100000-0x00377424 + +Now we must know the size of the unallocated flash: + + fis free + +Result: + +RedBoot> fis free + 0x500E0000 .. 0x503C0000 + +The values above may be different depending on the size of the filesystem and +the type of flash. See their usage below as an example and take care of +substituting yours appropriately. + +We must determine some values: + +size of unallocated flash: 0x503c0000 - 0x500e0000 = 0x2e0000 +size of the filesystem image: 0x00377424 - 0x00100000 = 0x277424 + +We want to fit the filesystem image of course, but we also want to give it all +the remaining flash space as well. To write it: + + fis unlock -f 0x500E0000 -l 0x2e0000 + fis erase -f 0x500E0000 -l 0x2e0000 + fis write -b 0x100000 -l 0x277424 -f 0x500E0000 + fis create "JFFS2" -n -f 0x500E0000 -l 0x2e0000 + +Now the filesystem is associated to a MTD "partition" once Linux has discovered +what they are in the boot process. From Redboot, the 'fis list' command +displays them: + +RedBoot> fis list +Name FLASH addr Mem addr Length Entry point +RedBoot 0x50000000 0x50000000 0x00020000 0x00000000 +RedBoot config 0x503C0000 0x503C0000 0x00020000 0x00000000 +FIS directory 0x503E0000 0x503E0000 0x00020000 0x00000000 +Linux kernel 0x50020000 0x00100000 0x000C0000 0x00000000 +JFFS2 0x500E0000 0x500E0000 0x002E0000 0x00000000 + +However Linux should display something like: + +SA1100 flash: probing 32-bit flash bus +SA1100 flash: Found 2 x16 devices at 0x0 in 32-bit mode +Using RedBoot partition definition +Creating 5 MTD partitions on "SA1100 flash": +0x00000000-0x00020000 : "RedBoot" +0x00020000-0x000e0000 : "Linux kernel" +0x000e0000-0x003c0000 : "JFFS2" +0x003c0000-0x003e0000 : "RedBoot config" +0x003e0000-0x00400000 : "FIS directory" + +What's important here is the position of the partition we are interested in, +which is the third one. Within Linux, this correspond to /dev/mtdblock2. +Therefore to boot Linux with the kernel and its root filesystem in flash, we +need this RedBoot command: + + fis load "Linux kernel" + exec -b 0x100000 -l 0xc0000 -c "root=/dev/mtdblock2" + +Of course other filesystems than JFFS might be used, like cramfs for example. +You might want to boot with a root filesystem over NFS, etc. It is also +possible, and sometimes more convenient, to flash a filesystem directly from +within Linux while booted from a ramdisk or NFS. The Linux MTD repository has +many tools to deal with flash memory as well, to erase it for example. JFFS2 +can then be mounted directly on a freshly erased partition and files can be +copied over directly. Etc... + + +RedBoot scripting +----------------- + +All the commands above aren't so useful if they have to be typed in every +time the Assabet is rebooted. Therefore it's possible to automatize the boot +process using RedBoot's scripting capability. + +For example, I use this to boot Linux with both the kernel and the ramdisk +images retrieved from a TFTP server on the network: + +RedBoot> fconfig +Run script at boot: false true +Boot script: +Enter script, terminate with empty line +>> load zImage -r -b 0x100000 +>> load ramdisk_ks.gz -r -b 0x800000 +>> exec -b 0x100000 -l 0xc0000 +>> +Boot script timeout (1000ms resolution): 3 +Use BOOTP for network configuration: true +GDB connection port: 9000 +Network debug at boot time: false +Update RedBoot non-volatile configuration - are you sure (y/n)? y + +Then, rebooting the Assabet is just a matter of waiting for the login prompt. + + + +Nicolas Pitre +nico@cam.org +June 12, 2001 + + +Status of peripherals in -rmk tree +---------------------------------- + +Assabet: + Serial ports: + Radio: TX, RX, CTS, DSR, DCD, RI + COM: TX, RX, CTS, DSR, DCD, RTS, DTR, PM + I2C: TX, RX + L3: No + + Video: + LCD: PM + Video out: Not fully + Touchscreen: No + + Audio: + Codec: No + POTS: No + + Other: + PCMCIA: Yes + USB: No ------ begin angelboot.opt ----- -base 0xc0008000 -entry 0xc0008000 -r0 0x00000000 -r1 0x00000019 -device /dev/ttyS1 -options "9600 8N1" -baud 115200 -otherfile ramdisk_img.gz -otherbase 0xc0800000 -exec minicom ------ end angelboot.opt ----- - -Then load the kernel and ramdisk with: - - angelboot -f angelboot.opt zImage - -Here it is assumed that your Assabet is connected to ttyS1 and that -minicom is preconfigured with /dev/ttyS1, 9600 baud, 8N1, no flow control -by default. +Neponset: + Serial ports: + COM1,2: TX, RX, CTS, DSR, DCD, RTS, DTR -This is work in progress... +More stuff can be found in the -np (Nicolas Pitre's) tree. -Please send any patches to nico@cam.org. diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/DMA linux/Documentation/arm/SA1100/DMA --- v2.4.9/linux/Documentation/arm/SA1100/DMA Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/DMA Fri Sep 7 09:28:38 2001 @@ -0,0 +1,248 @@ +Support functions for the SA11x0 internal DMA channels +====================================================== + +Nicolas Pitre +Last updated: 2001/07/15 + + +The DMA controller consists of six independent DMA channels. Each channel +can be configured to service any of the serial controllers. Two channels +are required to service a full-duplex serial controller. The DMA +controller is intended to relieve the processor of the interrupt overhead +in servicing these ports with programmed I/ O. + +If desired, any or all peripherals (except the UDC) may be serviced with +programmed I/ O instead of DMA. Each peripheral is capable of requesting +processor service through its own interrupt lines or through a DMA +request. + +A set of functions is provided to support drivers working with DMA buffers +through a generic interface for (wishfully) all DMA usages. Those +functions will take care of buffer queueing and splitting, DMA register +management, interrupt handling, etc. + + +SA11x0 DMA API +-------------- + +Here is the description for the DMA API. + + +int sa1100_request_dma( dmach_t *channel, const char *device_id, + dma_device_t device ); + +This function will search for a free DMA channel and returns the channel +number in '*channel'. 'device_id' should point to a string identifying +the DMA usage or device (mainly for /proc). 'device' is the SA11x0 +peripheral's ports. Note that reading from a port and writing to the +same port are actually considered as two different streams requiring +two DMA channels with their own device type. All possible dma_device_t +are defined in include/asm-arm/arch-sa1100/dma.h. If no channel is +available, or if the desired device is already in use by another DMA +channel, then an error code is returned. This function must be called +before any other DMA calls. + + +int sa1100_dma_queue_buffer( dmach_t channel, void *buf_id, + dma_addr_t data, int size ); + +This function enqueue the specified buffer for DMA processing. The buffer +will be transmitted or filled with incoming data depending on the channel +configuration made through sa1100_dma_set_device(). If the queue is +empty, DMA starts immediately on the given buffer. + +Arguments are: + +dmach_t channel: the channel number. +void *buf_id: a buffer identification known by the caller. +dma_addr_t data: the buffer's physical address. +int size: the buffer size in bytes. + +Note here the dma_addr_t which is not the same as the virtual address as +returned by kmalloc() and friends. The DMA controller must be given a +physical address to a buffer which is not cached bye the CPU data cache. +To get such address, the DMA mapping functions (see +Documentation/DMA-mapping.txt) are recommended. The only relevant +functions are pci_alloc_consistent(), pci_map_single() and their unmap +counterparts. The PCI dev argument is NULL of course. + +There is no restriction on the buffer size. The DMA code will split it up +internally to acommodate the DMA controller as needed. If the buffer +can't be enqueued the appropriate error code is returned. + + +int sa1100_dma_set_callback( dmach_t channel, dma_callback_t cb ); + +As soon as the DMa completes with a buffer, a callback function is used to +notify the driver which would have registered one. The callback function +is prototyped as: + +void dma_callback( void *buf_id, int size ); + +The 'buf_id' argument is the buffer identifier as passed to +sa1100_dma_queue_buffer(). The 'size' argument is the number of bytes the +DMA processed (should be the same as the buffer size). + +Note that this callback function is called while in interrupt context. +So it has to be small and efficient while posponing more complex +processing to a bottom-half function or similar. All +restrictions for interrupt handlers still apply. + + +int sa1100_dma_get_current( dmach_t channel, void **buf_id, + dma_addr_t *addr ); + +This returns the buffer ID and the DMA address pointer within the buffer +currently being processed. If no such buffer is currently processed, an +error code is returned. This is useful for mmap()'ed buffers like in +audio drivers. + + +int sa1100_dma_stop( dmach_t channel ); + +This call stops any DMA transfer on the given channel. + + +int sa1100_dma_resume( dmach_t channel ); + +This call resumes a DMA transfer which would have been stopped through +sa1100_dma_stop(). + + +int sa1100_dma_flush_all( dmach_t channel ); + +This completely flushes all queued buffers and on-going DMA transfers on a +given channel. The next enqueued buffer following this call will be +processed right away. + + +int sa1100_dma_set_spin( dmach_t channel, dma_addr_t addr, int size ); + +Because there is at least one device out there that uses its receive +signal for its transmit clock reference, we need a mecanism to make the +DMA "spin" on a certain buffer for when there is no more actual buffer to +process. The 'addr' argument is the physical memory address to use, and +the 'size' argument determines the spin DMA chunk. This size can't be +larger than 8191 (if so, it is clamped to 4096). When the size is 0, +the spin function is turned off. + +When activated, DMA will "spin" until there is any buffer in the queue. +The current DMA chunk will terminate before a newly queued buffer is +processed. The spin buffer will only be reused when there is no more +acctual buffer to process. + +It is important not to choose a too small 'size' value since it will +greatly increase the interrupt load required to restart the spin. Since +this feature will typically be used on transmit DMAs, and because a buffer +full of zeros is probably the best thing to spin out, the 'addr' argument +may well be used with FLUSH_BASE_PHYS for which no allocation nor memory +bus request are needed. + +The spinning DMA is affected by sa1100_dma_stop() and sa1100_dma_resume() +but not bu sa1100_dma_flush_all(). + + +void sa1100_free_dma( dmach_t channel ); + +This clears all activities on a given DMA channel and releases it for +future requests. + + +Buffer allocation +----------------- + +Like mentionned above, it is the driver's responsibility to allocate, free +and keep track of buffer space with dma_addr_t type addresses. However the +driver must not change the state of any buffer after it has been sent to +sa1100-dma_queue_buffer(). When that function has been called, the buffer +becomes the DMA's ownership until one of these events occur: + +- The callback function is called by the DMA code with a buffer ID to + indicate that DMA processing terminated on that buffer. Then the + driver owns the buffer again. +- The sa1100-dma_flush_all() function is called by the driver at which + point *all* queued buffers are owned by the driver again. +- The sa1100-free_dma() does the same as sa1100-dma_flush_all(). + +This doesn't mean that you can't change the content of a queued buffer in +conjonction with the usage of pci_map_consistent() and +sa1100_dma_get_current()... but then you must be sure you know what you're +doing (this doesn't work with pci_map_single()). + + +Examples +-------- + +A real example of audio ring buffers is implemented in the +drivers/sound/sa1100-audio.c driver. The SA1110 USB client and the +SA11x0 FIR drivers are also using this interface to implement packetized +DMA. + +A transmit DMA for network packets could look like this (largely simplified): + +struct sk_buff *tx_ring_skb[RING_SIZE]; +dma_addr_t tx_ring_dma[RING_SIZE]; +int cur_tx; +... + +transmit function: + + tx_ring_skb[cur_tx] = skb; + tx_ring_dma[cur_tx] = pci_map_single(NULL, skb->data, skb->len, + PCI_DMA_TODEVICE); + sa1100_dma_queue_buffer(channel, (void*)cur_tx, + tx_ring_dma[cur_tx], skb->len); + cur_tx++; cur_tx %= RING_SIZE; + ... + +and the callback function: + +void tx_done_callback( void *buf_id, int size ) { + int done_tx = (int) buf_id; + struct sk_buff *skb = tx_ring_skb[done_tx]; + pci_unmap_single(NULL, tx_ring_dma[done_tx], skb->len, + PCI_DMA_TODEVICE); + stats.tx_packets++; + stats.tx_bytes += size; + dev_kfree_skb_irq(skb); + tx_ring_skb[done_tx] = NULL; +} + + +For drivers expecting variable length packets i.e. USB client, it is +necessary to register the appropriate IRQ to be notified when the receiver +is idle, the packet is complete, etc. We could use one buffer at a time +with its ID being the virtual address of the buffer. + +Then the sequence: + + /* be sure DMA won't continue under our feet */ + sa1100_dma_stop(channel); + /* get the actual DMA length */ + sa1100_get_current(channel, &data, &dma_ptr); + /* acquire ownership for the buffer */ + sa1100_dma_flush_all(channel); + /* unmap the DMA buffer (actually doing cache coherency on ARM) */ + pci_unmap_single (NULL, dma_addr, MAX_PKT_SIZE, PCI_DMA_FROMDEVICE); + /* get remaining bytes from the fifo */ + ptr = data + dma_ptr - dma_addr; + while (fifo_not_empty) + *ptr++ = get_byte_from_fifo; + /* feed another free buffer for the next packet */ + dma_addr2 = pci_map_single(NULL, data2, MAX_PKT_SIZE, + PCI_DMA_FROMDEVICE); + sa1100_dma_queue_buffer(channel, data2, dma_addr2, MAX_PKT_SIZE); + /* process the current packet */ + ... + +might do the trick. This looks a bit ugly but that's a starting point for +improvements. + + +TODO +---- + +- Create kernel-doc comments in the source to document the API and + let the documentation be generated automatically. + + diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/FreeBird linux/Documentation/arm/SA1100/FreeBird --- v2.4.9/linux/Documentation/arm/SA1100/FreeBird Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/FreeBird Fri Sep 7 09:28:38 2001 @@ -0,0 +1,21 @@ +Freebird-1.1 is produced by Legned(C) ,Inc. +(http://www.legend.com.cn) +and software/linux mainatined by Coventive(C),Inc. +(http://www.coventive.com) + +Based on the Nicolas's strongarm kernel tree. + +=============================================================== +Maintainer: + +Chester Kuo + + +Author : +Tim wu +CIH +Eric Peng +Jeff Lee +Allen Cheng +Tony Liu + diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/GraphicsClient linux/Documentation/arm/SA1100/GraphicsClient --- v2.4.9/linux/Documentation/arm/SA1100/GraphicsClient Mon Nov 27 17:07:59 2000 +++ linux/Documentation/arm/SA1100/GraphicsClient Fri Sep 7 09:28:38 2001 @@ -1,15 +1,18 @@ -ADS GraphicsClient/ThinClient Single Board Computer +ADS GraphicsClient Plus Single Board Computer For more details, contact Applied Data Systems or see -http://www.flatpanels.com/products.html +http://www.applieddata.net/products.html The original Linux support for this product has been provided by -Nicolas Pitre . +Nicolas Pitre . Continued development work by +Woojung Huh It's currently possible to mount a root filesystem via NFS providing a -complete Linux environment. Otherwise a ramdisk image may be used. Use -'make graphicsclient_config' before any 'make config'. This will set up -defaults for GraphicsClient/ThinClient support. +complete Linux environment. Otherwise a ramdisk image may be used. The +board supports MTD/JFFS, so you could also mount something on there. + +Use 'make graphicsclient_config' before any 'make config'. This will set up +defaults for GraphicsClient Plus support. The kernel zImage is linked to be loaded and executed at 0xc0200000. Also the following registers should have the specified values upon entry: @@ -17,8 +20,18 @@ r0 = 0 r1 = 29 (this is the GraphicsClient architecture number) -Here is a tipical angel.opt option file if the kernel is loaded through -the Angel Debug Monitor: +Linux can be used with the ADS BootLoader that ships with the +newer rev boards. See their documentation on how to load Linux. +Angel is not available for the GraphicsClient Plus AFAIK. + +There is a board known as just the GraphicsClient that ADS used to +produce but has end of lifed. This code will not work on the older +board with the ADS bootloader, but should still work with Angel, +as outlined below. In any case, if you're planning on deploying +something en masse, you should probably get the newer board. + +If using Angel on the older boards, here is a typical angel.opt option file +if the kernel is loaded through the Angel Debug Monitor: ----- begin angelboot.opt ----- base 0xc0200000 @@ -26,7 +39,7 @@ r0 0x00000000 r1 0x0000001d device /dev/ttyS1 -options "9600 8N1" +options "38400 8N1" baud 115200 #otherfile ramdisk.gz #otherbase 0xc0800000 @@ -39,7 +52,7 @@ angelboot -f angelboot.opt zImage Here it is assumed that the board is connected to ttyS1 on your PC -and that minicom is preconfigured with /dev/ttyS1, 9600 baud, 8N1, no flow +and that minicom is preconfigured with /dev/ttyS1, 38400 baud, 8N1, no flow control by default. If any other bootloader is used, ensure it accomplish the same, especially @@ -47,19 +60,39 @@ Supported peripherals: -- SA1100 LCD frame buffer (only 8bpp yet) -- on-board SMC 92C94 ethernet NIC +- SA1100 LCD frame buffer (8/16bpp...sort of) +- on-board SMC 92C96 ethernet NIC - SA1100 serial port -- flash memory access +- flash memory access (MTD/JFFS) - pcmcia -- possibly UCB1200 audio (not tested yet) +- touchscreen(ucb1200) +- ps/2 keyboard +- console on LCD screen +- serial ports (ttyS[0-2]) + - ttyS0 is default for serial console +- Smart I/O (ADC, keypad, digital inputs, etc) + See http://www.applieddata.com/developers/linux for IOCTL documentation + and example user space code. ps/2 keybd is multiplexed through this driver To do: -- touchscreen driver -- 16bpp frame buffer support -- extra (external) serial port driver -- some console keyboard support (maybe IR?) +- UCB1200 audio with new ucb_generic layer - everything else! :-) + +Notes: + +- The flash on board is divided into 3 partitions. mtd0 is where + the ADS boot ROM and zImage is stored. It's been marked as + read-only to keep you from blasting over the bootloader. :) mtd1 is + for the ramdisk.gz image. mtd2 is user flash space and can be + utilized for either JFFS or if you're feeling crazy, running ext2 + on top of it. If you're not using the ADS bootloader, you're + welcome to blast over the mtd1 partition also. + +- 16bpp mode requires a different cable than what ships with the board. + Contact ADS or look through the manual to wire your own. Currently, + if you compile with 16bit mode support and switch into a lower bpp + mode, the timing is off so the image is corrupted. This will be + fixed soon. Any contribution can be sent to nico@cam.org and will be greatly welcome! diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/HUW_WEBPANEL linux/Documentation/arm/SA1100/HUW_WEBPANEL --- v2.4.9/linux/Documentation/arm/SA1100/HUW_WEBPANEL Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/HUW_WEBPANEL Fri Sep 7 09:28:38 2001 @@ -0,0 +1,18 @@ +The HUW_WEBPANEL is a product of the german company Hoeft & Wessel AG + +If you want more information, please visit +http://www.hoeft-wessel.de + +To build the kernel: + make huw_webpanel_config + make oldconfig + [accept all defaults] + make dep + make zImage + +Mostly of the work is done by: +Roman Jordan jor@hoeft-wessel.de +Christoph Schulz schu@hoeft-wessel.de + +2000/12/18/ + diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/Itsy linux/Documentation/arm/SA1100/Itsy --- v2.4.9/linux/Documentation/arm/SA1100/Itsy Wed Oct 20 16:29:07 1999 +++ linux/Documentation/arm/SA1100/Itsy Fri Sep 7 09:28:38 2001 @@ -2,11 +2,38 @@ Research Center in Palo Alto, CA. The Itsy project is one of several research projects at Compaq that are related to pocket computing. -Itsy support has yet to be fully integrated in this kernel. Linux 2.0.x -support is available though. - For more information, see: http://www.research.digital.com/wrl/itsy/index.html +Notes on initial 2.4 Itsy support (8/27/2000) : +The port was done on an Itsy version 1.5 machine with a daughtercard with +64 Meg of DRAM and 32 Meg of Flash. The initial work includes support for +serial console (to see what you're doing). No other devices have been +enabled. + +To build, do a "make menuconfig" (or xmenuconfig) and select Itsy support. +Disable Flash and LCD support. and then do a make dep and a make zImage. +Finally, you will need to cd to arch/arm/boot/tools and execute a make there +to build the params-itsy program used to boot the kernel. + +In order to install the port of 2.4 to the itsy, You will need to set the +configuration parameters in the monitor as follows: +Arg 1:0x08340000, Arg2: 0xC0000000, Arg3:18 (0x12), Arg4:0 +Make sure the start-routine address is set to 0x00060000. + +Next, flash the params-itsy program to 0x00060000 ("p 1 0x00060000" in the +flash menu) Flash the kernel in arch/arm/boot/zImage into 0x08340000 +("p 1 0x00340000"). Finally flash an initial ramdisk into 0xC8000000 +("p 2 0x0") We used ramdisk-2-30.gz from the 0.11 version directory on +handhelds.org. + +The serial connection we established was at: + 8-bit data, no parity, 1 stop bit(s), 115200.00 b/s. in the monitor, in the +params-itsy program, and in the kernel itself. This can be changed, but +not easily. The monitor parameters are easily changed, the params program +setup is assembly outl's, and the kernel is a configuration item specific to +the itsy. (i.e. grep for CONFIG_SA1100_ITSY and you'll find where it is.) + +This should get you a properly booting 2.4 kernel on the itsy. diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/PCMCIA linux/Documentation/arm/SA1100/PCMCIA --- v2.4.9/linux/Documentation/arm/SA1100/PCMCIA Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/PCMCIA Fri Sep 7 09:28:38 2001 @@ -0,0 +1,374 @@ +Kernel Low-Level PCMCIA Interface Documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +John G Dorsey +Updated: 30 June, 2000 + + +Note: this interface has not been finalized! +See also: http://www.cs.cmu.edu/~wearable/software/pcmcia-arm.html + + +Introduction + +Early versions of PCMCIA Card Services for StrongARM were designed to +permit a single socket driver to run on a variety of SA-1100 boards by +using a userland configuration process. During the conversion to the 2.3 +kernel series, all of the configuration has moved into sub-drivers in the +kernel proper (see linux/drivers/pcmcia/sa1100*). This document describes +the low-level interface between those sub-drivers and the sa1100 socket +driver module. + +Presently, there are six operations which must be provided by the +board-specific code. Only functions whose implementation is likely to +differ across board designs are required at this level. Some examples +include: + + - configuring card detect lines to generate interrupts + - sensing the legal voltage levels for inserted cards + - asserting the reset signal for a card + +Functions which are assumed to be the same across all designs are +performed within the generic socket driver itself. Some examples of these +kinds of operations include: + + - configuring memory access times based on the core clock frequency + - reads/writes on memory, byte swizzling, ... + +The current implementation allows the specific per-board set of low-level +operations to be determined at run time. For each specific board, the +following structure should be filled in: + + struct pcmcia_low_level { + int (*init)(struct pcmcia_init *); + int (*shutdown)(void); + int (*socket_state)(struct pcmcia_state_array *); + int (*get_irq_info)(struct pcmcia_irq_info *); + int (*configure_socket)(const struct pcmcia_configure *); + }; + +The component functions are described in detail below. Using the +machine_is_*() tests, the pointer `pcmcia_low_level' should be assigned to +the location of the table for your board. + + +0. init(struct pcmcia_init *init) + +This operation has three responsibilities: + + - perform any board-specific initialization tasks + - associate the given handler with any interrupt-generating signals + such as card detection, or battery voltage detection + - set up any necessary edge detection for card ready signals + +Argument passing for this operation is implemented by the following +structure: + + struct pcmcia_init { + void (*handler)(int irq, void *dev, struct pt_regs *regs); + struct pcmcia_maps *maps; + }; + +Here, `handler' is provided by the socket driver, and `maps' must be +modified if the default mapping isn't appropriate. This operation should +return one of two values: + + - the highest-numbered socket available, plus one + - a negative number, indicating an error in configuration + +Note that the former case is _not_ the same as "the number of sockets +available." In particular, if your design uses SA-1100 slot "one" but +not slot "zero," you MUST report "2" to the socket driver. + + +1. shutdown(void) + +This operation takes no arguments, and will be called during cleanup for +the socket driver module. Any state associated with the socket controller, +including allocated data structures, reserved IRQs, etc. should be +released in this routine. + +The return value for this operation is not examined. + + +2. socket_state(struct pcmcia_state_array *state_array) + +This operation will be invoked from the interrupt handler which was set up +in the earlier call to init(). Note, however, that it should not include +any side effects which would be inappropriate if the operation were to +occur when no interrupt is pending. (An extra invocation of this operation +currently takes place to initialize state in the socket driver.) + +Argument passing for this operation is handled by a structure which +contains an array of the following type: + + struct pcmcia_state { + unsigned detect: 1, + ready: 1, + bvd1: 1, + bvd2: 1, + wrprot: 1, + vs_3v: 1, + vs_Xv: 1; + }; + +Upon return from the operation, a struct pcmcia_state should be filled in +for each socket available in the hardware. For every array element (up to +`size' in the struct pcmcia_state_saarray) which does not correspond to an +available socket, zero the element bits. (This includes element [0] if +socket zero is not used.) + +Regardless of how the various signals are routed to the SA-1100, the bits +in struct pcmcia_state always have the following semantics: + + detect - 1 if a card is fully inserted, 0 otherwise + ready - 1 if the card ready signal is asserted, 0 otherwise + bvd1 - the value of the Battery Voltage Detect 1 signal + bvd2 - the value of the Battery Voltage Detect 2 signal + wrprot - 1 if the card is write-protected, 0 otherwise + vs_3v - 1 if the card must be operated at 3.3V, 0 otherwise + vs_Xv - 1 if the card must be operated at X.XV, 0 otherwise + +A note about the BVD signals: if your board does not make both lines +directly observable to the processor, just return reasonable values. The +standard interpretation of the BVD signals is: + + BVD1 BVD2 + + 0 x battery is dead + 1 0 battery warning + 1 1 battery ok + +Regarding the voltage sense flags (vs_3v, vs_Xv), these bits should be set +based on a sampling of the Voltage Sense pins, if available. The standard +interpretation of the VS signals (for a "low-voltage" socket) is: + + VS1 VS2 + + 0 0 X.XV, else 3.3V, else none + 0 1 3.3V, else none + 1 0 X.XV, else none + 1 1 5V, else none + +More information about the BVD and VS conventions is available in chapter +5 of "PCMCIA System Architecture," 2nd ed., by Don Anderson. + +This operation should return 1 if an IRQ is actually pending for the +socket controller, 0 if no IRQ is pending (but no error condition exists, +such as an undersized state array), or -1 on any error. + + +3. get_irq_info(struct pcmcia_irq_info *info) + +This operation obtains the IRQ assignment which is legal for the given +socket. An argument of the following type is passed: + + struct pcmcia_irq_info { + unsigned int sock; + unsigned int irq ; + }; + +The `sock' field contains the socket index being queried. The `irq' field +should contain the IRQ number corresponding to the card ready signal from +the device. + +This operation should return 0 on success, or -1 on any error. + + +4. configure_socket(const struct pcmcia_configure *configure) + +This operation allows the caller to apply power to the socket, issue a +reset, or enable various outputs. The argument is of the following type: + + struct pcmcia_configure { + unsigned sock: 8, + vcc: 8, + vpp: 8, + output: 1, + speaker: 1, + reset: 1; + }; + +The `sock' field contains the index of the socket to be configured. The +`vcc' and `vpp' fields contain the voltages to be applied for Vcc and Vpp, +respectively, in units of 0.1V. (Note that vpp==120 indicates that +programming voltage should be applied.) + +The two output enables, `output' and `speaker', refer to the card data +signal enable and the card speaker enable, respectively. The `reset' bit, +when set, indicates that the card reset should be asserted. + +This operation should return 0 on success, or -1 on any error. + + +Board-Specific Notes + +The following information is known about various SA-11x0 board designs +which may be used as reference while adding support to the kernel. + + +Carnegie Mellon Itsy/Cue (http://www.cs.cmu.edu/~wearable/itsy/) + + Itsy Chip Select 3 (CS3) Interface + ("ITSY MEMORY/PCMCIA ADD-ON BOARD with BATTERY and CHARGER CIRCUITRY," + memo dated 5-20-99, from Tim Manns to Richard Martin, et. al) + + Read: + ABVD2 (SS)D0 A slot, Battery Voltage Detect + ABVD1 (SS)D1 + AVSS2 (SS)D2 A slot, Voltage Sense + AVSS1 (SS)D3 + GND (SS)D4 + GND (SS)D5 + GND (SS)D6 + GND (SS)D7 + + BBVD2 (SS)D8 B slot, Battery Voltage Detect + BBVD1 (SS)D9 + BVSS2 (SS)D10 B slot, Voltage Sense + BVSS1 (SS)D11 + GND (SS)D12 + GND (SS)D13 + GND (SS)D14 + GND (SS)D15 + + Write: + (SS)D0 A_VPP_VCC LTC1472 VPPEN1 + (SS)D1 A_VPP_PGM LTC1472 VPPEN0 + (SS)D2 A_VCC_3 LTC1472 VCCEN0 + (SS)D3 A_VCC_5 LTC1472 VCCEN1 + (SS)D4 RESET (A SLOT) + (SS)D5 GND + (SS)D6 GND + (SS)D7 GND + + (SS)D8 B_VPP_VCC LTC1472 VPPEN1 + (SS)D9 B_VPP_PGM LTC1472 VPPEN0 + (SS)D10 B_VCC_3 LTC1472 VCCEN0 + (SS)D11 B_VCC_5 LTC1472 VCCEN1 + (SS)D12 RESET (B SLOT) + (SS)D13 GND + (SS)D14 GND + (SS)D15 GND + + GPIO pin assignments are as follows: (from schematics) + + GPIO 10 Slot 0 Card Detect + GPIO 11 Slot 1 Card Detect + GPIO 12 Slot 0 Ready/Interrupt + GPIO 13 Slot 1 Ready/Interrupt + + + +Intel SA-1100 Multimedia Board (http://developer.intel.com/design/strong/) + + CPLD Registers + SA-1100 Multimedia Development Board with Companion SA-1101 Development + Board User's Guide, p.4-42 + + This SA-1100/1101 development package uses only one GPIO pin (24) to + signal changes in card status, and requires software to inspect a + PCMCIA status register to determine the source. + + Read: (PCMCIA Power Sense Register - 0x19400000) + S0VS1 0 Slot 0 voltage sense + S0VS2 1 + S0BVD1 2 Slot 0 battery voltage sense + S0BVD2 3 + S1VS1 4 Slot 1 voltage sense + S1VS2 5 + S1BVD1 6 Slot 1 battery voltage sense + S1BVD2 7 + + Read/Write: (PCMCIA Power Control Register - 0x19400002) + S0VPP0 0 Slot 0 Vpp + S0VPP1 1 + S0VCC0 2 Slot 0 Vcc + S0VCC1 3 + S1VPP0 4 Slot 1 Vpp + S1VPP1 5 + S1VCC0 6 Slot 1 Vcc + S1VCC1 7 + + Read: (PCMCIA Status Register - 0x19400004) + S0CD1 0 Slot 0 Card Detect 1 + S0RDY 1 Slot 0 Ready/Interrupt + S0STSCHG 2 Slot 0 Status Change + S0Reset 3 Slot 0 Reset (RW) + S1CD1 4 Slot 1 Card Detect 1 + S1RDY 5 Slot 1 Ready/Interrupt + S1STSCHG 6 Slot 1 Status Change + S1Reset 7 Slot 1 Reset (RW) + + + +Intel SA-1100 Evaluation Platform (http://developer.intel.com/design/strong/) + + Brutus I/O Pins and Chipselect Register + pcmcia-brutus.c, by Ivo Clarysse + (What's the official reference for this info?) + + This SA-1100 development board uses more GPIO pins than say, the Itsy + or the SA-1100/1101 multimedia package. The pin assignments are as + follows: + + GPIO 2 Slot 0 Battery Voltage Detect 1 + GPIO 3 Slot 0 Ready/Interrupt + GPIO 4 Slot 0 Card Detect + GPIO 5 Slot 1 Battery Voltage Detect 1 + GPIO 6 Slot 1 Ready/Interrupt + GPIO 7 Slot 1 Card Detect + + Like the Itsy, Brutus uses a chipselect register in static memory + bank 3 for the other signals, such as voltage sense or reset: + + Read: + P0_VS1 8 Slot 0 Voltage Sense + P0_VS2 9 + P0_STSCHG 10 Slot 0 Status Change + P1_VS1 12 Slot 1 Voltage Sense + P1_VS2 13 + P1_STSCHG 14 Slot 1 Status Change + + Read/Write: + P0_ 16 Slot 0 MAX1600EAI control line + P0_ 17 Slot 0 MAX1600EAI control line + P0_ 18 Slot 0 MAX1600EAI control line + P0_ 19 Slot 0 MAX1600EAI control line + P0_ 20 Slot 0 12V + P0_ 21 Slot 0 Vpp to Vcc (CONFIRM?) + P0_ 22 Slot 0 enable fan-out drivers & xcvrs + P0_SW_RST 23 Slot 0 Reset + P1_ 24 Slot 1 MAX1600EAI control line + P1_ 25 Slot 1 MAX1600EAI control line + P1_ 26 Slot 1 MAX1600EAI control line + P1_ 27 Slot 1 MAX1600EAI control line + P1_ 28 Slot 1 12V + P1_ 29 Slot 1 Vpp to Vcc (CONFIRM?) + P1_ 30 Slot 1 enable fan-out drivers & xcvrs + P1_SW_RST 31 Slot 1 Reset + + For each slot, the bits labelled "MAX1600EAI" should (apparently) + be written with the value 0101 for Vcc 3.3V, and 1001 for Vcc 5V. + + + +Intel SA-1110 Development Platform (http://developer.intel.com/design/strong/) + + GPIO Pin Descriptions and Board Control Register + SA-1110 Microprocessor Development Board User's Guide, p.4-7, 4-10 + + The Assabet board contains only a single Compact Flash slot, + attached to slot 1 on the SA-1110. Card detect, ready, and BVD + signals are routed through GPIO, with power and reset placed in a + control register. Note that the CF bus must be enabled before use. + + GPIO 21 Slot 1 Compact Flash interrupt + GPIO 22 Slot 1 card detect (CD1 NOR CD2) + GPIO 24 Slot 1 Battery Voltage Detect 2 + GPIO 25 Slot 1 Battery Voltage Detect 1 + + Write-only: (Board Control Register - 0x12000000) + CF_PWR 0 CF bus power (3.3V) + CF_RST 1 CF reset + CF_Bus_On 7 CF bus enable + diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/Pangolin linux/Documentation/arm/SA1100/Pangolin --- v2.4.9/linux/Documentation/arm/SA1100/Pangolin Mon Nov 27 17:07:59 2000 +++ linux/Documentation/arm/SA1100/Pangolin Fri Sep 7 09:28:38 2001 @@ -1,25 +1,20 @@ -Pangolin is a StrongARM 1110-based evaluation platform produced -by Dialogue Technoloy (http://www.dialogue.com.tw/). +Pangolin is a StrongARM 1110-based evaluation platform produced +by Dialogue Technology (http://www.dialogue.com.tw/). It has EISA slots for ease of configuration with SDRAM/Flash memory card, USB/Serial/Audio card, Compact Flash card, and TFT-LCD card. -This platform is currently under development. To compile for Pangolin, you must issue the following commands: make pangolin_config - make config - [accept all defaults] + make oldconfig make dep make zImage Supported peripherals: -- SA1110 serial port +- SA1110 serial port (UART1/UART2/UART3) - flash memory access - -Testing: -- pcmcia driver -- sound driver - -To do: -- MQ-200 driver +- compact flash driver +- UDA1341 sound driver +- SA1100 LCD controller for 800x600 16bpp TFT-LCD +- MQ-200 driver for 800x600 16bpp TFT-LCD diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/Yopy linux/Documentation/arm/SA1100/Yopy --- v2.4.9/linux/Documentation/arm/SA1100/Yopy Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/Yopy Fri Sep 7 09:28:38 2001 @@ -0,0 +1,2 @@ +See http://www.yopydeveloper.org for more. + diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/nanoEngine linux/Documentation/arm/SA1100/nanoEngine --- v2.4.9/linux/Documentation/arm/SA1100/nanoEngine Sun Aug 13 09:58:24 2000 +++ linux/Documentation/arm/SA1100/nanoEngine Fri Sep 7 09:28:38 2001 @@ -4,6 +4,8 @@ "nanoEngine" is a SA1110 based single board computer from Bright Star Engineering Inc. See www.brightstareng.com/arm for more info. +(Ref: Stuart Adams ) -Ref: Stuart Adams +Also visit Larry Doolittle's "Linux for the nanoEngine" site: +http://recycle.lbl.gov/~ldoolitt/bse/ diff -u --recursive --new-file v2.4.9/linux/Documentation/arm/SA1100/serial_UART linux/Documentation/arm/SA1100/serial_UART --- v2.4.9/linux/Documentation/arm/SA1100/serial_UART Mon Nov 27 17:07:59 2000 +++ linux/Documentation/arm/SA1100/serial_UART Fri Sep 7 09:28:38 2001 @@ -1,5 +1,4 @@ -The SA1100 serial port finally had its major/minor numbers officially -assigned: +The SA1100 serial port had its major/minor numbers officially assigned: > Date: Sun, 24 Sep 2000 21:40:27 -0700 > From: H. Peter Anvin @@ -25,7 +24,7 @@ > 7 = /dev/cusa2 Callout device for ttySA2 > -So, if you're not using devfs, you must create those inodes in /dev +If you're not using devfs, you must create those inodes in /dev on the root filesystem used by your SA1100-based device: mknod ttySA0 c 204 5 @@ -35,31 +34,14 @@ mknod cusa1 c 205 6 mknod cusa2 c 205 7 -Note that the old incorrect use of /dev/ttyS0 in order to use the serial port -won't work anymore. This device node is reserved to the conventionnal 16x50 -UART which may appear on devices like PCMCIA modem, etc. - -In addition to the creation of the appropriate device nodes above, you must -ensure your user space applications make use of the correct device name. -The classic example is the content of the /etc/inittab where you might have -a getty process started on ttyS0. In this case you have two choices: - -1- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc. - -2- in the occurence of 'ttyS0', you may consider replacing it with 'console'. - as in "T0:12345:respawn:/sbin/getty -L console 9600 vt100" - -(don't forget to add 'ttySA0', 'console', or the appropriate tty name - in /etc/securetty for root to be allowed to login as well.) - -The use of /dev/console has the advantage of being independent of the real -serial device used. The kernel automatically forward all operations on -/dev/console to the apropriate serial device. The nature of the console may -also be modified with a kernel command line parameter (see -Documentation/serial-console.txt for the details). Of course, -/dev/console must have been created as a char device with major 5 minor 1. - -Using /dev/console is also compatible with older kernels that used /dev/ttyS0. -Therefore it is handy for ramdisk images which are targetted for different -StrongARM platforms and older kernels. +In addition to the creation of the appropriate device nodes above, you +must ensure your user space applications make use of the correct device +name. The classic example is the content of the /etc/inittab file where +you might have a getty process started on ttyS0. In this case: + +- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc. + +- don't forget to add 'ttySA0', 'console', or the appropriate tty name + in /etc/securetty for root to be allowed to login as well. + diff -u --recursive --new-file v2.4.9/linux/Documentation/fb/README-sstfb.txt linux/Documentation/fb/README-sstfb.txt --- v2.4.9/linux/Documentation/fb/README-sstfb.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/fb/README-sstfb.txt Fri Sep 7 09:28:38 2001 @@ -0,0 +1,167 @@ + +Introduction + + This is a frame buffer device driver for 3dfx' Voodoo Graphics + (aka voodoo 1, aka sst1) and Voodoo² (aka Voodoo 2, aka CVG) based + video boards. It's highly experimental code, but is guaranteed to work + on my computer, with my "Maxi Gamer 3D" and "Maxi Gamer 3d²" boards, + and with me "between chair and keyboard". Some people tested other + combinations and it seems that it works. + The main page is located at , and if + you want the latest version, check out the CVS, as the driver is a work + in progress, i feel incomfortable with releasing tarballs of something + not completely working...Don't worry, it's still more than useable + (I eat my own dog food) + + Please read the Bug section, and report any success or failure to me + (Ghozlane Toumi ). + BTW, If you have only one monitor , and you don't feel like playing + with the vga passthrou cable, I can only suggest borrowing a screen + somewhere... + + +Installation + + This driver (should) work on ix86, with any 2.2.x kernel (tested + with x = 19) and "recent" 2.4.x kernel, as a module or compiled in. + You can apply the patches found in sstfb/kernel/*-2.{2|4}.x.patch, + and copy sstfb.c to linux/drivers/video/, or apply a single patch, + sstfb/patch-2.{2|4}.x-sstfb-yymmdd to your linux source tree. + + Then configure your kernel as usual: choose "m" or "y" to 3Dfx Voodoo + Graphics in section "console". Compile, install, have fun... and please + drop me a report :) + + +Module Usage + + Warnings. + # You should read completely this section before issuing any command. + # If you have only one monitor to play with, once you insmod the + module, the 3dfx takes control of the output, so you'll have to + plug the monitor to the "normal" video board in order to issue + the commands, or you can blindly use sst_dbg_vgapass + in the tools directory (See Tools). The latest option is pass the + parameter vgapass=1 when insmodding the driver. (See Kernel/Modules + Options) + + Module insertion: + # insmod sstfb.o + you should see some strange output frome the board: + a big blue square, a green and a red small squares and a vertical + white rectangle. why ? the function's name is self explanatory : + "sstfb_test()"... + (if you don't have a second monitor, you'll have to plug your monitor + directely to the 2D videocard to see what you're typing) + # con2fb /dev/fbx /dev/ttyx + bind a tty to the new frame buffer. if you already have a frame + buffer driver, the voodoo fb will likely be /dev/fb1. if not, + the device will be /dev/fb0. You can check this by doing a + cat /proc/fb. You can find a copy of con2fb in tools/ directory. + if you don't have another fb device, this step is superfluous, + as the console subsystem automagicaly binds ttys to the fb. + # switch to the virtual console you just mapped. "tadaaa" ... + + Module removal: + # con2fb /dev/fbx /dev/ttyx + bind the tty to the old frame buffer so the module can be removed. + (how does it work with vgacon ? short answer : it doesn't work) + # rmmod sstfb + + +Kernel/Modules Options + + You can pass some otions to sstfb module, and via the kernel command + line when the driver is compiled in : + for module : insmod sstfb.o option1=value1 option2=value2 ... + in kernel : video=sstfb:option1,option2:value2,option3 ... + + sstfb supports the folowing options : + module kernel description + + vgapass=1 vgapass enable or disable VGA passthrou cable + vgapass=0 vganopass when enabled, the monitor will + get the signal from the VGA board + and not from the voodoo. default nopass + + mem=x mem:x force frame buffer memory in MiB + allowed values: 1, 2, 4. default detect + + inverse=1 inverse suposed to enable inverse console. + doesn't work ... + + clipping=1 clipping enable or disable clipping . with + clipping=0 noclipping clipping enabled, all offscreen reads + and writes are disgarded. default: + enable clipping. + + gfxclk=x gfxclk:x force graphic clock frequency (in MHz) + becarefull with this option . + default is 50Mhz for voodoo1, 75MHz + for voodoo2. Be carefull, this one is + dangerous. default=auto + + slowpci=0 slowpci enable or disable fast PCI read/writes + slowpci=1 fastpci default : fastpci + + dev=x dev:x attach the driver to device number x + 0 is the first compatible board (in + lspci order) + +Tools + + These tools are mostly for debugging purposes, but you can + find some of these interesting : + - con2fb , maps a tty to a fbramebuffer . + con2fb /dev/fb1 /dev/tty5 + - sst_dbg_vgapass , changes vga passthrou. You have to recompile the + driver with SST_DEBUG and SST_DEBUG_IOCTL set to 1 + sst_dbg_vgapass /dev/fb1 1 (enables vga cable) + sst_dbg_vgapass /dev/fb1 0 (disables vga cable) + - glide_reset , resets the voodoo using glide + use this after rmmoding sstfb, if the module refuses to + reinsert . + +Bugs + + - DO NOT use glide while the sstfb module is in, you'll most likely + hang your computer. + - if you see some artefacts (pixels not cleaning and stuff like that), + try turning off clipping (clipping=0) + - the driver don't detect the 4Mb frame buffer voodoos, it seems that + the 2 last Mbs wrap around. looking into that . + - The driver is 16 bpp only, 24/32 won't work. + - The driver is not your_favorite_toy-safe. this includes SMP... + [Actually from inspection it seems to be safe - Alan] + - when using XFree86 FBdev (X over fbdev) you may see strange color + patterns at the border of your windows (the pixels loose the lowest + byte -> basicaly the blue component nd some of the green) . I'm unable + to reproduce this with XFree86-3.3, but one of the testers has this + problem with XFree86-4. I don't know yet if this is the drivers fault + or X's (most likely the driver, of course). + - I didn't really test changing the palette, so you may find some weird + things when playing with that. + - Sometimes the driver will not recognise the DAC , and the + initialisation will fail. this is specificaly true for + voodoo 2 boards , but it should be solved in recent versions. please + contact me . + - the 24/32 is not likely to work anytime soon , knowing that the + hardware does ... unusual thigs in 24/32 bpp + +Todo + + - Get rid of the previous paragraph. + - Buy more coffee. + - test/port to other arch. + - try to add panning using tweeks with front and back buffer . + - try to implement accel en voodoo2 , this board can actualy do a + lot in 2D even if it was sold as a 3D only board ... + +ghoz. + +-- +Ghozlane Toumi + + +$Date: 2001/08/29 00:21:11 $ +http://sstfb.sourceforge.net/README diff -u --recursive --new-file v2.4.9/linux/Documentation/filesystems/ntfs.txt linux/Documentation/filesystems/ntfs.txt --- v2.4.9/linux/Documentation/filesystems/ntfs.txt Mon Aug 27 12:41:37 2001 +++ linux/Documentation/filesystems/ntfs.txt Sat Sep 8 12:24:40 2001 @@ -64,6 +64,25 @@ Be careful not to write anything to them or you could crash the kernel and/or corrupt your file system! +mft_zone_multiplier= Set the MFT zone multiplier for the volume (this + setting is not persistent across mounts and can be + changed from mount to mount but cannot be changed on + remount). Values of 1 to 4 are allowed, 1 being the + default. The MFT zone multiplier determines how much + space is reserved for the MFT on the volume. If all + other space is used up, then the MFT zone will be + shrunk dynamically, so this has no impact on the + amount of free space. However, it can have an impact + on performance by affecting fragmentation of the MFT. + In general use the default. If you have a lot of small + files then use a higher value. The values have the + following meaning: + Value MFT zone size (% of volume size) + 1 12.5% + 2 25% + 3 37.5% + 4 50% + Known bugs and (mis-)features ============================= @@ -71,10 +90,6 @@ use it, get the Linux-NTFS tools and use the ntfsfix utility after dismounting a partition you wrote to. -- Use the show_sys_files mount option which should make things work generally - better. (It results in both the short and long file names being shown as well - as the sytem files.) - - Writing of extension records is not supported properly. Please send bug reports/comments/feed back/abuse to the Linux-NTFS development @@ -82,6 +97,86 @@ ChangeLog ========= + +NTFS 1.1.18: + + - Enhanced & bug fixed cluster deallocation (race fixes, etc.) + - Complete rewrite of cluster allocation, now race free. + - Fixed several bugs in the attribute modification codepaths. + - Hopefully fixed bug where the first sectors of some people's + partitions would be overwritten by the mft. And in general fixed up + mft extension code a bit (still incomplete though). + - Introduce splice_runlist() to allow generic splicing of two run + lists into one. + - MFT zone is now implemented. [Stage 2 of 3; only lack dynamic + growing of mft zone but that is AFAIK not even done by Windows, and + the overhead would be so large that it is probably not worth doing + at all, so Stage 3 might never happen...] + - Complete rewrite of $MFT extension and ntfs inode allocation code. + - Made the NTFS driver initialization string show the compile options + used (i.e. whether read-only or read-write, whether a module, and + whether with debug support). + - Modify ntfs_fill_mft_header() to set all fields and to accept more + arguments. + - Get rid of superfluous add_mft_header(). + - Get rid of some unused code. + - Fixed several bugs in and generally cleaned up ntfs_readdir, + ntfs_getdir_unsorted(), and ntfs_printcb. Now they spew out huge + amounts of debug output if debugging is enabled. This will be + removed once I know that this works for everyone. + - ntfs_readdir now shows hidden files. The only files that are now + hidden are the first 16 inodes (i.e. the hard coded system files), + which is consistent with Windows NT4. Using the show_sys_files mount + option, these files are then shown, too. + - Fixed the displaying of the "." and ".." directories. We still cannot + cope with more than 65536 files in a directory index block which is + not a problem and we now cannot cope with more than 32766 directory + index blocks which should not be a problem unless you have a + directory with an insanely large number of files in it. The exact + number depends on the length of the file names of the directory + entries and on the size of the dircetory index blocks. + - Fixed all problems with the last file in a directory (e.g. the last + file should no longer disappear and tab completion should work). If + there are still disappearing files or any other problems with the + last file in a directory, please report them! Thanks. + - Rewrote ntfs_extend_attr() to use the new cluster allocator and the + freshly introduced splice_runlists() function. This simplified + ntfs_extend_attr() a lot which in turn seems to have removed one or + more bugs from it. + - Probably other things I have forgotten... (-; + - Removed dollar signs from the names in the system file enumeration. + Apparently gcc doesn't support dollar signs on PPC architecture. + (Andrzej Krzysztofowicz) + +NTFS 1.1.17: + + - Fixed system file handling. No longer need to use show_sys_files + option for driver to work fine. System files are now always treated + the same, but without the option, they are made invisible to + directory listings. As a result system files can once again be opened + even without the show_sys_files option. This is important for the + statfs system call to work properly, for example. + - Implemented MFT zone including mount parameter to tune it (just like + in Windows via the registry, only we make it per mount rather than + global for the whole driver, so we are better but we have no way of + storing the value as we don't have a registry so either specify on + each mount or put it in /etc/fstab). [Stage 1 of 3, mount parameter + handling.] + - Fixed fixup functions to handle corruption cases and to return error + codes to the caller. + - Made fixup functions apply hotfixes where sensible. [Stage 1 of 2+, + in memory only.] + - Fixed ommission of "NTFS: " string in ntfs_error() output. + - Fixed stupid if statement bug in unistr.c. Thanks to Yann E. Morin + for spotting it. + - Get rid of all uses of max and min macros. This actually allowed for + optimizing the code in several places so it was a Good Thing(TM). + - Make ntfs use generic_file_open to enforce the O_LARGEFILE flag. + - Detect encrypted files and refuse to access them (return EACCES + error code to user space). + - Fix handling of encrypted & compressed files so that an encrypted + file no longer is considered to be compressed (this was causing + kernel segmentation faults). NTFS 1.1.16: diff -u --recursive --new-file v2.4.9/linux/Documentation/ide.txt linux/Documentation/ide.txt --- v2.4.9/linux/Documentation/ide.txt Sat Feb 26 20:32:12 2000 +++ linux/Documentation/ide.txt Fri Sep 7 09:28:38 2001 @@ -314,7 +314,7 @@ "ide0=ht6560b" : probe/support HT6560B interface "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip (not for PCI -- automatically detected) - "ide0=qd6580" : probe/support qd6580 interface + "ide0=qd65xx" : probe/support qd65xx interface "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439/M1445) "ide0=umc8672" : probe/support umc8672 chipsets diff -u --recursive --new-file v2.4.9/linux/Documentation/kernel-doc-nano-HOWTO.txt linux/Documentation/kernel-doc-nano-HOWTO.txt --- v2.4.9/linux/Documentation/kernel-doc-nano-HOWTO.txt Fri Mar 2 18:43:11 2001 +++ linux/Documentation/kernel-doc-nano-HOWTO.txt Fri Sep 7 18:15:17 2001 @@ -35,9 +35,9 @@ - Makefile - The targets 'sgmldocs', 'psdocs', and 'pdfdocs' are used to build - DocBook files, PostScript files, and PDF files in - Documentation/DocBook. + The targets 'sgmldocs', 'psdocs', 'pdfdocs', and 'htmldocs' are used + to build DocBook files, PostScript files, PDF files, and html files + in Documentation/DocBook. - Documentation/DocBook/Makefile @@ -49,10 +49,11 @@ If you just want to read the ready-made books on the various subsystems (see Documentation/DocBook/*.tmpl), just type 'make -psdocs', or 'make pdfdocs', depending on your preference. If you -would rather read a different format, you can type 'make sgmldocs' and -then use DocBook tools to convert Documentation/DocBook/*.sgml to a -format of your choice (for example, 'db2html ...'). +psdocs', or 'make pdfdocs', or 'make htmldocs', depending on your +preference. If you would rather read a different format, you can type +'make sgmldocs' and then use DocBook tools to convert +Documentation/DocBook/*.sgml to a format of your choice (for example, +'db2html ...' if 'make htmldocs' was not defined). If you want to see man pages instead, you can do this: @@ -111,7 +112,9 @@ (*)?*/ The short function description cannot be multiline, but the other -descriptions can be. +descriptions can be (and they can contain blank lines). Avoid putting a +spurious blank line after the function name, or else the description will +be repeated! All descriptive text is further processed, scanning for the following special patterns, which are highlighted appropriately. diff -u --recursive --new-file v2.4.9/linux/Documentation/mips/pci/pci.README linux/Documentation/mips/pci/pci.README --- v2.4.9/linux/Documentation/mips/pci/pci.README Wed Dec 31 16:00:00 1969 +++ linux/Documentation/mips/pci/pci.README Mon Aug 27 08:56:31 2001 @@ -0,0 +1,67 @@ + +Pete Popov, ppopov@pacbell.net +07/11/2001 + +This README briefly explains how to use the pci and pci_auto +code in arch/mips/kernel. The code was ported from PowerPC and +modified slightly. It has been tested pretty well on PPC on some +rather complex systems with multiple bridges and devices behind +each bridge. However, at the time this README was written, the +mips port was tested only on boards with a single pci bus and +no P2P bridges. It's very possible that on boards with P2P +bridges some modifications have to be made. The code will +evolve, no doubt, but currently every single mips board +is doing its own pcibios thing and it has become a big +mess. This generic pci code is meant to clean up the mips +pci mess and make it easier to add pci support to new boards. + +arch/mips/kernel/pci_auto.c has the pci bus enumeration code. +This code scans the pci bus(es) and assigns all of the resources. +Thus, you don't need the boot code to that, and many boot codes +don't do it correctly anyway. To enable the pci_auto code, add + +define_bool CONFIG_PCI_AUTO y + +inside the define for your board in arch/mips/config.in. +For example, the Galileo EV96100 board looks like this: + +if [ "$CONFIG_MIPS_EV96100" = "y" ]; then + define_bool CONFIG_PCI y + define_bool CONFIG_MIPS_GT96100 y + define_bool CONFIG_NEW_PCI y + define_bool CONFIG_PCI_AUTO y + define_bool CONFIG_SWAP_IO_SPACE y +fi + + +Next, if you want to use the arch/mips/kernel/pci code, which has the +pcibios_init() function, add + +define_bool CONFIG_NEW_PCI y + +inside the define for your board. Again, the EV96100 example above +show NEW_PCI turned on. + +Note that you can enable CONFIG_NEW_PCI code without enabling +CONFIG_PCI_AUTO. But you can't do the opposite because the pci_auto +routines are called from pcibios_init(), which is part of the +CONFIG_NEW_PCI code. + + +Now you need to add your files to hook in your pci configuration +cycles. Usually you'll need only a couple of files named something +like pci_fixups.c and pci_ops.c. You can copy the templates +provided and fill in the code. + +The file pci_ops.c should contain the pci configuration cycles routines. +It also has the mips_pci_channels[] array which contains the descriptors +of each pci controller. + +The file pci_fixups.c contains a few routines to do interrupt fixups, +resources fixups, and, if needed, pci bios fixups. + +Usually you'll put your pci_fixups.c file in your board specific directory, +since the functions in that file are board specific. The functions in +pci_ops.c, on the other hand, are usually pci controller specific so that +file could be shared among a few different boards using the same +pci controller. diff -u --recursive --new-file v2.4.9/linux/Documentation/s390/3270.txt linux/Documentation/s390/3270.txt --- v2.4.9/linux/Documentation/s390/3270.txt Thu May 24 15:14:08 2001 +++ linux/Documentation/s390/3270.txt Fri Sep 7 09:28:38 2001 @@ -34,17 +34,6 @@ dialed-in x3270. -HELP !!! - -The device name of e.g. /dev/3270/tty620 noted below is at variance -with "standard" Linux device names. What should it be? The portion -"/dev/3270" was recommended by H. Peter Anvin, maintainer of the -official Linux major-numbers list; the portion "tty620" was recommended -by me. Please send your thoughts on this issue at least to me at -rbh00@utsglobal.com. Even if you think it's okay as is, please let me -know. Thanks. - - INSTALLATION. You install the driver by installing a patch, doing a kernel build, and @@ -60,9 +49,14 @@ If you have chosen to make tub3270 a module, you add a line to /etc/modules.conf. If you are working on a VM virtual machine, you -can use DEF GRAF to define virtual 3270 devices. If you generate 3270 -console support, the driver automatically converts your console at boot -time to a 3270 if it is a 3215. +can use DEF GRAF to define virtual 3270 devices. + +You may generate both 3270 and 3215 console support, or one or the +other, or neither. If you generate both, the console type under VM is +not changed. Use #CP Q TERM to see what the current console type is. +Use #CP TERM CONMODE 3270 to change it to 3270. If you generate only +3270 console support, then the driver automatically converts your console +at boot time to a 3270 if it is a 3215. In brief, these are the steps: 1. Install the tub3270 patch @@ -78,21 +72,17 @@ Here are the installation steps in detail: - 0. Retrieve the patch file via anonymous ftp from - ftp://ftp.utsglobal.com/pub/tub3270. The patch is designed - to apply smoothly to an IBM 2.4.0 system with no other - UTS-Global patches applied. We know of some easily resolvable - conflicts between this and other of our patches. - - 1. Apply the patch. Then do + 1. The 3270 driver is a part of the official Linux kernel + source. Build a tree with the kernel source and any necessary + patches. Then do make oldconfig - (Reply "y" or "m" for CONFIG_3270; if "y", - reply "y" or "n" for CONFIG_3270_CONSOLE) + (If you wish to disable 3215 console support, edit + .config; change CONFIG_TN3215's value to "n"; + and rerun "make oldconfig".) make dep make image make modules make modules_install - 2. (Perform this step only if you have configured tub3270 as a module.) Add a line to /etc/modules.conf to automatically @@ -122,12 +112,17 @@ config3270.sh. Inspect the output script it produces, /tmp/mkdev3270, and then run that script. This will create the necessary character special device files and make the necessary - changes to /etc/inittab. Then notify /sbin/init that /etc/inittab - has changed, by issuing the telinit command with the q operand: + changes to /etc/inittab. If you have selected DEVFS, the driver + itself creates the device files, and /tmp/mkdev3270 only changes + /etc/inittab. + + Then notify /sbin/init that /etc/inittab has changed, by issuing + the telinit command with the q operand: cd /usr/src/linux/Documentation/s390 sh config3270.sh sh /tmp/mkdev3270 telinit q + This should be sufficient for your first time. If your 3270 configuration has changed and you're reusing config3270, you should follow these steps: diff -u --recursive --new-file v2.4.9/linux/Documentation/s390/config3270.sh linux/Documentation/s390/config3270.sh --- v2.4.9/linux/Documentation/s390/config3270.sh Wed Apr 11 19:02:27 2001 +++ linux/Documentation/s390/config3270.sh Fri Sep 7 09:28:38 2001 @@ -37,10 +37,14 @@ echo "#!/bin/sh" > $SCR || exit 1 echo " " >> $SCR echo "# Script built by /sbin/config3270" >> $SCR -echo rm -rf "$D/$SUBD/*" >> $SCR +if [ ! -d /dev/dasd ]; then + echo rm -rf "$D/$SUBD/*" >> $SCR +fi echo "grep -v $TTY $INITTAB > $NINITTAB" > $SCRTMP || exit 1 echo "echo $ADDNOTE >> $NINITTAB" >> $SCRTMP -echo mkdir -p $D/$SUBD >> $SCR +if [ ! -d /dev/dasd ]; then + echo mkdir -p $D/$SUBD >> $SCR +fi # Now query the tub3270 driver for 3270 device information # and add appropriate mknod and mingetty lines to our files @@ -48,13 +52,19 @@ while read devno maj min;do if [ $min = 0 ]; then fsmaj=$maj - echo mknod $D/$TUB c $fsmaj 0 >> $SCR - echo chmod 666 $D/$TUB >> $SCR + if [ ! -d /dev/dasd ]; then + echo mknod $D/$TUB c $fsmaj 0 >> $SCR + echo chmod 666 $D/$TUB >> $SCR + fi elif [ $maj = CONSOLE ]; then - echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR + if [ ! -d /dev/dasd ]; then + echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR + fi else - echo mknod $D/$TTY$devno c $maj $min >>$SCR - echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR + if [ ! -d /dev/dasd ]; then + echo mknod $D/$TTY$devno c $maj $min >>$SCR + echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR + fi echo "echo t$min$GETTYLINE $TTY$devno >> $NINITTAB" >> $SCRTMP fi done < $P diff -u --recursive --new-file v2.4.9/linux/Documentation/sound/CMI8338 linux/Documentation/sound/CMI8338 --- v2.4.9/linux/Documentation/sound/CMI8338 Wed Jul 25 17:10:17 2001 +++ linux/Documentation/sound/CMI8338 Fri Sep 7 09:28:38 2001 @@ -69,8 +69,8 @@ Some functions for the cm8738 can be configured in Kernel Configuration or modules parameters. Set these parameters to 1 to enable. - mpu_io: I/O ports base for MPU-401, 0 if disabled. - fm_io: I/O ports base for OPL-3, 0 if disabled. + mpuio: I/O ports base for MPU-401, 0 if disabled. + fmio: I/O ports base for OPL-3, 0 if disabled. spdif_inverse:Inverse the S/PDIF-in signal, this depends on your CD-ROM or DVD-ROM. spdif_loop: Enable S/PDIF loop, this route S/PDIF-in to S/PDIF-out @@ -80,8 +80,6 @@ rear-out. use_line_as_bass:Enable this if you want to use line-in as bass-out. - modem: You will need to set this parameter if you want to use - the HSP modem. You need install the pctel.o, the modem - driver itself. joystick: Enable joystick. You will need to install Linux joystick driver. + diff -u --recursive --new-file v2.4.9/linux/Documentation/sound/WaveArtist linux/Documentation/sound/WaveArtist --- v2.4.9/linux/Documentation/sound/WaveArtist Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sound/WaveArtist Fri Sep 7 09:28:38 2001 @@ -0,0 +1,170 @@ + + (the following is from the armlinux CVS) + + WaveArtist mixer and volume levels can be accessed via these commands: + + nn30 read registers nn, where nn = 00 - 09 for mixer settings + 0a - 13 for channel volumes + mm31 write the volume setting in pairs, where mm = (nn - 10) / 2 + rr32 write the mixer settings in pairs, where rr = nn/2 + xx33 reset all settings to default + 0y34 select mono source, y=0 = left, y=1 = right + + bits + nn 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 00 | 0 | 0 0 1 1 | left line mixer gain | left aux1 mixer gain |lmute| +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 01 | 0 | 0 1 0 1 | left aux2 mixer gain | right 2 left mic gain |mmute| +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 02 | 0 | 0 1 1 1 | left mic mixer gain | left mic | left mixer gain |dith | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 03 | 0 | 1 0 0 1 | left mixer input select |lrfg | left ADC gain | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 04 | 0 | 1 0 1 1 | right line mixer gain | right aux1 mixer gain |rmute| +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 05 | 0 | 1 1 0 1 | right aux2 mixer gain | left 2 right mic gain |test | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 06 | 0 | 1 1 1 1 | right mic mixer gain | right mic |right mixer gain |rbyps| +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 07 | 1 | 0 0 0 1 | right mixer select |rrfg | right ADC gain | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 08 | 1 | 0 0 1 1 | mono mixer gain |right ADC mux sel|left ADC mux sel | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 09 | 1 | 0 1 0 1 |loopb|left linout|loop|ADCch|TxFch|OffCD|test |loopb|loopb|osamp| +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 0a | 0 | left PCM channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 0b | 0 | right PCM channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 0c | 0 | left FM channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 0d | 0 | right FM channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 0e | 0 | left wavetable channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 0f | 0 | right wavetable channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 10 | 0 | left PCM expansion channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 11 | 0 | right PCM expansion channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 12 | 0 | left FM expansion channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + 13 | 0 | right FM expansion channel volume | +----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+ + + lmute: left mute + mmute: mono mute + dith: dithds + lrfg: + rmute: right mute + rbyps: right bypass + rrfg: + ADCch: + TxFch: + OffCD: + osamp: + + And the following diagram is derived from the description in the CVS archive: + + MIC L (mouthpiece) + +------+ + -->PreAmp>-\ + +--^---+ | + | | + r2b4-5 | +--------+ + /----*-------------------------------->5 | + | | | + | /----------------------------------->4 | + | | | | + | | /--------------------------------->3 1of5 | +---+ + | | | | mux >-->AMP>--> ADC L + | | | /------------------------------->2 | +-^-+ + | | | | | | | + Line | | | | +----+ +------+ +---+ /---->1 | r3b3-0 + ------------*->mute>--> Gain >--> | | | | + L | | | +----+ +------+ | | | *->0 | + | | | | | | +---^----+ + Aux2 | | | +----+ +------+ | | | | + ----------*--->mute>--> Gain >--> M | | r8b0-2 + L | | +----+ +------+ | | | + | | | | \------\ + Aux1 | | +----+ +------+ | | | + --------*----->mute>--> Gain >--> I | | + L | +----+ +------+ | | | + | | | | + | +----+ +------+ | | +---+ | + *------->mute>--> Gain >--> X >-->AMP>--* + | +----+ +------+ | | +-^-+ | + | | | | | + | +----+ +------+ | | r2b1-3 | + | /----->mute>--> Gain >--> E | | + | | +----+ +------+ | | | + | | | | | + | | +----+ +------+ | | | + | | /--->mute>--> Gain >--> R | | + | | | +----+ +------+ | | | + | | | | | | r9b8-9 + | | | +----+ +------+ | | | | + | | | /->mute>--> Gain >--> | | +---v---+ + | | | | +----+ +------+ +---+ /-*->0 | + DAC | | | | | | | + ------------*----------------------------------->? | +----+ + L | | | | | Mux >-->mute>--> L output + | | | | /->? | +--^-+ + | | | | | | | | + | | | /--------->? | r0b0 + | | | | | | +-------+ + | | | | | | + Mono | | | | | | +-------+ + ----------* | \---> | +----+ + | | | | | | Mix >-->mute>--> Mono output + | | | | *-> | +--^-+ + | | | | | +-------+ | + | | | | | r1b0 + DAC | | | | | +-------+ + ------------*-------------------------*--------->1 | +----+ + R | | | | | | Mux >-->mute>--> R output + | | | | +----+ +------+ +---+ *->0 | +--^-+ + | | | \->mute>--> Gain >--> | | +---^---+ | + | | | +----+ +------+ | | | | r5b0 + | | | | | | r6b0 + | | | +----+ +------+ | | | + | | \--->mute>--> Gain >--> M | | + | | +----+ +------+ | | | + | | | | | + | | +----+ +------+ | | | + | *----->mute>--> Gain >--> I | | + | | +----+ +------+ | | | + | | | | | + | | +----+ +------+ | | +---+ | + \------->mute>--> Gain >--> X >-->AMP>--* + | +----+ +------+ | | +-^-+ | + /--/ | | | | + Aux1 | +----+ +------+ | | r6b1-3 | + -------*------>mute>--> Gain >--> E | | + R | | +----+ +------+ | | | + | | | | | + Aux2 | | +----+ +------+ | | /------/ + ---------*---->mute>--> Gain >--> R | | + R | | | +----+ +------+ | | | + | | | | | | +--------+ + Line | | | +----+ +------+ | | | *->0 | + -----------*-->mute>--> Gain >--> | | | | + R | | | | +----+ +------+ +---+ \---->1 | + | | | | | | + | | | \-------------------------------->2 | +---+ + | | | | Mux >-->AMP>--> ADC R + | | \---------------------------------->3 | +-^-+ + | | | | | + | \------------------------------------>4 | r7b3-0 + | | | + \-----*-------------------------------->5 | + | +---^----+ + r6b4-5 | | + | | r8b3-5 + +--v---+ | + -->PreAmp>-/ + +------+ + MIC R (electret mic) diff -u --recursive --new-file v2.4.9/linux/Documentation/watchdog.txt linux/Documentation/watchdog.txt --- v2.4.9/linux/Documentation/watchdog.txt Fri Aug 11 15:57:57 2000 +++ linux/Documentation/watchdog.txt Fri Sep 7 09:28:38 2001 @@ -11,6 +11,7 @@ ICS WDT501-P (no fan tachometer) ICS WDT500-P Software Only + SA1100 Internal Watchdog Berkshire Products PC Watchdog Revision A & C (by Ken Hollis) @@ -35,6 +36,9 @@ The wdt card cannot be safely probed for. Instead you need to pass wdt=ioaddr,irq as a boot parameter - eg "wdt=0x240,11". +The SA1100 watchdog module can be configured with the "sa1100_margin" +commandline argument which specifies timeout value in seconds. + The i810 TCO watchdog modules can be configured with the "i810_margin" commandline argument which specifies the counter initial value. The counter is decremented every 0.6 seconds and default to 50 (30 seconds). Values can @@ -47,15 +51,15 @@ Features -------- - WDT501P WDT500P Software Berkshire i810 TCO -Reboot Timer X X X X X -External Reboot X X o o o -I/O Port Monitor o o o X o -Temperature X o o X o -Fan Speed X o o o o -Power Under X o o o o -Power Over X o o o o -Overheat X o o o o + WDT501P WDT500P Software Berkshire i810 TCO SA1100WD +Reboot Timer X X X X X X +External Reboot X X o o o X +I/O Port Monitor o o o X o o +Temperature X o o X o o +Fan Speed X o o o o o +Power Under X o o o o o +Power Over X o o o o o +Overheat X o o o o o The external event interfaces on the WDT boards are not currently supported. Minor numbers are however allocated for it. diff -u --recursive --new-file v2.4.9/linux/MAINTAINERS linux/MAINTAINERS --- v2.4.9/linux/MAINTAINERS Mon Aug 27 12:41:37 2001 +++ linux/MAINTAINERS Fri Sep 7 10:59:04 2001 @@ -689,8 +689,8 @@ S: Orphan IEEE 1394 OHCI DRIVER -P: Sebastien Rougeaux -M: sebastien.rougeaux@anu.edu.au +P: Ben Collins +M: bcollins@debian.org L: linux1394-devel@lists.sourceforge.net S: Maintained @@ -902,9 +902,9 @@ MIPS P: Ralf Baechle -M: ralf@gnu.ai.mit.edu -W: http://lena.fnet.fr/ -L: linux-mips@fnet.fr +M: ralf@gnu.org +W: http://oss.sgi.com/mips/mips-howto.html +L: linux-mips@oss.sgi.com S: Maintained MISCELLANEOUS MCA-SUPPORT @@ -1453,6 +1453,13 @@ L: linux-usb-devel@lists.sourceforge.net S: Maintained +USB KAWASAKI LSI DRIVER +P: Brad Hards +M: bradh@frogmouth.net +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Maintained + USB OHCI DRIVER P: Roman Weissgaerber M: weissg@vienna.at @@ -1467,6 +1474,14 @@ L: linux-usb-devel@lists.sourceforge.net W: http://alpha.dyndns.org/ov511/ S: Maintained + +USB SE401 DRIVER +P: Jeroen Vreeken +M: pe1rxq@amsat.org +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +W: http://www.chello.nl/~j.vreeken/se401/ +S: Maintained USB PEGASUS DRIVER P: Petko Manolov diff -u --recursive --new-file v2.4.9/linux/Makefile linux/Makefile --- v2.4.9/linux/Makefile Mon Aug 27 12:41:37 2001 +++ linux/Makefile Fri Sep 7 21:17:54 2001 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 -SUBLEVEL = 9 -EXTRAVERSION = +SUBLEVEL = 10 +EXTRAVERSION =-pre6 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.4.9/linux/arch/alpha/kernel/alpha_ksyms.c Mon Aug 27 12:41:37 2001 +++ linux/arch/alpha/kernel/alpha_ksyms.c Mon Aug 27 07:56:48 2001 @@ -77,6 +77,14 @@ EXPORT_SYMBOL(_writeb); EXPORT_SYMBOL(_writew); EXPORT_SYMBOL(_writel); +EXPORT_SYMBOL(___raw_readb); +EXPORT_SYMBOL(___raw_readw); +EXPORT_SYMBOL(___raw_readl); +EXPORT_SYMBOL(___raw_readq); +EXPORT_SYMBOL(___raw_writeb); +EXPORT_SYMBOL(___raw_writew); +EXPORT_SYMBOL(___raw_writel); +EXPORT_SYMBOL(___raw_writeq); EXPORT_SYMBOL(_memcpy_fromio); EXPORT_SYMBOL(_memcpy_toio); EXPORT_SYMBOL(_memset_c_io); diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/arthur.c linux/arch/arm/kernel/arthur.c --- v2.4.9/linux/arch/arm/kernel/arthur.c Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/kernel/arthur.c Fri Sep 7 09:28:38 2001 @@ -1,7 +1,7 @@ /* * linux/arch/arm/kernel/arthur.c * - * Copyright (C) 1998, 1999, 2000 Philip Blundell + * Copyright (C) 1998, 1999, 2000, 2001 Philip Blundell * * Arthur personality */ @@ -58,7 +58,7 @@ { struct siginfo info; info.si_signo = SIGSWI; - info.si_code = nr; + info.si_errno = nr; /* Bounce it to the emulator */ send_sig_info(SIGSWI, &info, current); } diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- v2.4.9/linux/arch/arm/kernel/process.c Mon Aug 27 12:41:38 2001 +++ linux/arch/arm/kernel/process.c Fri Sep 7 09:28:38 2001 @@ -124,7 +124,7 @@ pm_power_off(); } -void machine_restart(void * __unused) +void machine_restart(char * __unused) { /* * Clean and disable cache, and turn off interrupts diff -u --recursive --new-file v2.4.9/linux/arch/arm/lib/io-readsl-armv4.S linux/arch/arm/lib/io-readsl-armv4.S --- v2.4.9/linux/arch/arm/lib/io-readsl-armv4.S Mon Aug 27 12:41:38 2001 +++ linux/arch/arm/lib/io-readsl-armv4.S Fri Sep 7 09:28:38 2001 @@ -63,8 +63,8 @@ strne ip, [r1], #4 movne ip, r3, lsr #8 bne 7b - strb ip, [r1], #1 - mov ip, ip, lsr #8 strh ip, [r1], #2 + mov ip, ip, lsr #16 + strb ip, [r1] mov pc, lr diff -u --recursive --new-file v2.4.9/linux/arch/arm/lib/io-writesl.S linux/arch/arm/lib/io-writesl.S --- v2.4.9/linux/arch/arm/lib/io-writesl.S Mon Aug 27 12:41:38 2001 +++ linux/arch/arm/lib/io-writesl.S Fri Sep 7 09:28:38 2001 @@ -25,31 +25,30 @@ 2: bic r1, r1, #3 cmp ip, #2 - ldr ip, [r1], #4 - mov ip, ip, lsr #16 - blt 4f - bgt 5f + ldr r3, [r1], #4 + bgt 4f + blt 5f -3: ldr r3, [r1], #4 +3: mov ip, r3, lsr #16 + ldr r3, [r1], #4 orr ip, ip, r3, lsl #16 str ip, [r0] - mov ip, r3, lsr #16 subs r2, r2, #1 bne 3b mov pc, lr -4: ldr r3, [r1], #4 +4: mov ip, r3, lsr #24 + ldr r3, [r1], #4 orr ip, ip, r3, lsl #8 str ip, [r0] - mov ip, r3, lsr #24 subs r2, r2, #1 bne 4b mov pc, lr -5: ldr r3, [r1], #4 +5: mov ip, r3, lsr #8 + ldr r3, [r1], #4 orr ip, ip, r3, lsl #24 str ip, [r0] - mov ip, r3, lsr #8 subs r2, r2, #1 bne 5b mov pc, lr diff -u --recursive --new-file v2.4.9/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c --- v2.4.9/linux/arch/arm/mm/fault-armv.c Mon Aug 27 12:41:38 2001 +++ linux/arch/arm/mm/fault-armv.c Fri Sep 7 09:28:38 2001 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -366,8 +367,7 @@ ai_multi += 1; /* count the number of registers in the mask to be transferred */ - for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1) - nr_regs += 4; + nr_regs = hweight16(REGMASK_BITS(instr)) * 4; rn = RN_BITS(instr); newaddr = eaddr = regs->uregs[rn]; @@ -385,10 +385,12 @@ * This is a "hint" - we already have eaddr worked out by the * processor for us. */ - if (addr != eaddr) + if (addr != eaddr) { printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, " "addr = %08lx, eaddr = %08lx\n", instruction_pointer(regs), instr, addr, eaddr); + show_regs(regs); + } for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1) if (regbits & 1) { diff -u --recursive --new-file v2.4.9/linux/arch/arm/tools/Makefile linux/arch/arm/tools/Makefile --- v2.4.9/linux/arch/arm/tools/Makefile Tue Jul 3 17:08:18 2001 +++ linux/arch/arm/tools/Makefile Fri Sep 7 09:28:38 2001 @@ -26,7 +26,8 @@ # directories dep: - $(TOPDIR)/scripts/mkdep getconstants.c | sed s,getconstants.o,$(TOPDIR)/include/asm-arm/constants.h, > .depend + $(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS) -- getconstants.c |\ + sed s,getconstants.o,$(TOPDIR)/include/asm-arm/constants.h, > .depend $(MAKE) all .PHONY: all dep diff -u --recursive --new-file v2.4.9/linux/arch/arm/tools/mach-types linux/arch/arm/tools/mach-types --- v2.4.9/linux/arch/arm/tools/mach-types Mon Aug 27 12:41:38 2001 +++ linux/arch/arm/tools/mach-types Fri Sep 7 09:28:38 2001 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Thu Aug 9 22:46:02 2001 +# Last update: Thu Aug 23 12:38:13 2001 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -31,7 +31,7 @@ l7200 ARCH_L7200 L7200 19 pleb SA1100_PLEB PLEB 20 integrator ARCH_INTEGRATOR INTEGRATOR 21 -bitsy SA1100_BITSY BITSY 22 +h3600 SA1100_H3600 H3600 22 ixp1200 ARCH_IXP1200 IXP1200 23 p720t ARCH_P720T P720T 24 assabet SA1100_ASSABET ASSABET 25 @@ -89,7 +89,7 @@ tardis ARCH_TARDIS TARDIS 77 mercury ARCH_MERCURY MERCURY 78 empeg SA1100_EMPEG EMPEG 79 -adi_eb ARCH_I80200FCC I80200FCC 80 +adi_evb ARCH_I80200FCC I80200FCC 80 itt_cpb SA1100_ITT_CPB ITT_CPB 81 svc SA1100_SVC SVC 82 alpha2 SA1100_ALPHA2 ALPHA2 84 @@ -115,3 +115,10 @@ granite ARCH_GRANITE GRANITE 104 consus SA1100_CONSUS CONSUS 105 aaec2000_aaed20 ARCH_AAEC2000_AAED2000 AAEC2000_AAED2000 106 +cdb89712 ARCH_CDB89712 CDB89712 107 +graphicsmaster SA1100_GRAPHICSMASTER GRAPHICSMASTER 108 +adsbitsy SA1100_ADSBITSY ADSBITSY 109 +cotulla_idp ARCH_COTULLA_IDP COTULLA_IDP 110 +plce ARCH_PLCE PLCE 111 +pt_system3 SA1100_PT_SYSTEM3 PT_SYSTEM3 112 +medalb ARCH_MEDALB MEDALB 113 diff -u --recursive --new-file v2.4.9/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.4.9/linux/arch/i386/defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/i386/defconfig Fri Sep 7 15:32:57 2001 @@ -175,6 +175,7 @@ # # CONFIG_PHONE is not set # CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set # # ATA/IDE/MFM/RLL support @@ -705,6 +706,7 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set # CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -738,10 +740,10 @@ # # USB Network adaptors # -# CONFIG_USB_PLUSB is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_CATC is not set -# CONFIG_USB_NET1080 is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_USBNET is not set # # USB port drivers diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c --- v2.4.9/linux/arch/i386/kernel/bluesmoke.c Tue Jul 3 17:08:18 2001 +++ linux/arch/i386/kernel/bluesmoke.c Sat Sep 8 12:23:14 2001 @@ -19,7 +19,7 @@ u32 mcgstl, mcgsth; int i; - rdmsr(0x17a, mcgstl, mcgsth); + rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); if(mcgstl&(1<<0)) /* Recoverable ? */ recover=0; @@ -27,7 +27,7 @@ for(i=0;icr4val), "=q" (tmp) : : "memory"); + if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) { + ctxt->cr4val = read_cr4(); + write_cr4(ctxt->cr4val & (unsigned char) ~(1<<7)); + } /* Disable and flush caches. Note that wbinvd flushes the TLBs as a side-effect */ - asm volatile ("movl %%cr0, %0\n\t" - "orl $0x40000000, %0\n\t" - "wbinvd\n\t" - "movl %0, %%cr0\n\t" - "wbinvd\n\t" - : "=r" (tmp) : : "memory"); + { + unsigned int cr0 = read_cr0() | 0x40000000; + wbinvd(); + write_cr0( cr0 ); + wbinvd(); + } if ( mtrr_if == MTRR_IF_INTEL ) { /* Disable MTRRs, and set the default type to uncached */ @@ -420,15 +418,13 @@ /* Restore the processor after a set_mtrr_prepare */ static void set_mtrr_done (struct set_mtrr_context *ctxt) { - unsigned long tmp; - if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) { __restore_flags (ctxt->flags); return; } /* Flush caches and TLBs */ - asm volatile ("wbinvd" : : : "memory" ); + wbinvd(); /* Restore MTRRdefType */ if ( mtrr_if == MTRR_IF_INTEL ) { @@ -440,15 +436,11 @@ } /* Enable caches */ - asm volatile ("movl %%cr0, %0\n\t" - "andl $0xbfffffff, %0\n\t" - "movl %0, %%cr0\n\t" - : "=r" (tmp) : : "memory"); + write_cr0( read_cr0() & 0xbfffffff ); /* Restore value of CR4 */ if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) - asm volatile ("movl %0, %%cr4" - : : "r" (ctxt->cr4val) : "memory"); + write_cr4(ctxt->cr4val); /* Re-enable interrupts locally (if enabled previously) */ __restore_flags (ctxt->flags); @@ -607,7 +599,7 @@ { unsigned long low, high; - rdmsr (0xC0000085, low, high); + rdmsr (MSR_K6_UWCCR, low, high); /* Upper dword is region 1, lower is region 0 */ if (reg == 1) low = high; /* The base masks off on the right alignment */ @@ -771,7 +763,7 @@ /* * Low is MTRR0 , High MTRR 1 */ - rdmsr (0xC0000085, regs[0], regs[1]); + rdmsr (MSR_K6_UWCCR, regs[0], regs[1]); /* * Blank to disable */ @@ -792,8 +784,8 @@ * The writeback rule is quite specific. See the manual. Its * disable local interrupts, write back the cache, set the mtrr */ - __asm__ __volatile__ ("wbinvd" : : : "memory"); - wrmsr (0xC0000085, regs[0], regs[1]); + wbinvd(); + wrmsr (MSR_K6_UWCCR, regs[0], regs[1]); if (do_safe) set_mtrr_done (&ctxt); } /* End Function amd_set_mtrr_up */ @@ -826,7 +818,7 @@ } centaur_mcr[reg].high = high; centaur_mcr[reg].low = low; - wrmsr (0x110 + reg, low, high); + wrmsr (MSR_IDT_MCR0 + reg, low, high); if (do_safe) set_mtrr_done( &ctxt ); } /* End Function centaur_set_mtrr_up */ @@ -2012,12 +2004,12 @@ * find out what the bios might have done. */ - rdmsr(0x120, lo, hi); + rdmsr(MSR_IDT_MCR_CTRL, lo, hi); if(((lo>>17)&7)==1) /* Type 1 Winchip2 MCR */ { lo&= ~0x1C0; /* clear key */ lo|= 0x040; /* set key to 1 */ - wrmsr(0x120, lo, hi); /* unlock MCR */ + wrmsr(MSR_IDT_MCR_CTRL, lo, hi); /* unlock MCR */ } centaur_mcr_type = 1; @@ -2031,7 +2023,7 @@ if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0) { if(!(lo & (1<<(9+i)))) - wrmsr (0x110 + i , 0, 0); + wrmsr (MSR_IDT_MCR0 + i , 0, 0); else /* * If the BIOS set up an MCR we cannot see it @@ -2047,7 +2039,7 @@ */ lo |= 15; /* Write combine enables */ - wrmsr(0x120, lo, hi); + wrmsr(MSR_IDT_MCR_CTRL, lo, hi); } /* End Function centaur_mcr1_init */ /* @@ -2071,10 +2063,10 @@ for (i = 0; i < 8; ++i) { if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0) - wrmsr (0x110 + i , 0, 0); + wrmsr (MSR_IDT_MCR0 + i , 0, 0); } - wrmsr(0x120, 0x01F0001F, 0); /* Write only */ + wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0); /* Write only */ } /* End Function centaur_mcr0_init */ /* @@ -2230,6 +2222,8 @@ * :-) */ cyrix_arr_init_secondary (); + break; + case MTRR_IF_NONE: break; default: /* I see no MTRRs I can support in SMP mode... */ diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c --- v2.4.9/linux/arch/i386/kernel/pci-pc.c Mon Aug 27 12:41:39 2001 +++ linux/arch/i386/kernel/pci-pc.c Sat Sep 1 11:01:28 2001 @@ -20,65 +20,145 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2; int pcibios_last_bus = -1; -struct pci_bus *pci_root_bus; -struct pci_ops *pci_root_ops; +struct pci_bus *pci_root_bus = NULL; +struct pci_ops *pci_root_ops = NULL; + +int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL; +int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL; /* - * Direct access to PCI hardware... + * This interrupt-safe spinlock protects all accesses to PCI + * configuration space. */ +spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED; -#ifdef CONFIG_PCI_DIRECT /* * Functions for accessing PCI configuration space with type 1 accesses */ -#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3)) +#ifdef CONFIG_PCI_DIRECT + +#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \ + (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) + +static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) +{ + unsigned long flags; + + if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + return -EINVAL; + + spin_lock_irqsave(&pci_config_lock, flags); + + outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); + + switch (len) { + case 1: + *value = inb(0xCFC + (reg & 3)); + break; + case 2: + *value = inw(0xCFC + (reg & 2)); + break; + case 4: + *value = inl(0xCFC); + break; + } + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return 0; +} + +static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +{ + unsigned long flags; + + if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + return -EINVAL; + + spin_lock_irqsave(&pci_config_lock, flags); + + outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); + + switch (len) { + case 1: + outb((u8)value, 0xCFC + (reg & 3)); + break; + case 2: + outw((u16)value, 0xCFC + (reg & 2)); + break; + case 4: + outl((u32)value, 0xCFC); + break; + } + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return 0; +} + +#undef PCI_CONF1_ADDRESS static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - outl(CONFIG_CMD(dev,where), 0xCF8); - *value = inb(0xCFC + (where&3)); - return PCIBIOS_SUCCESSFUL; + int result; + u32 data; + + if (!value) + return -EINVAL; + + result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, &data); + + *value = (u8)data; + + return result; } static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value) { - outl(CONFIG_CMD(dev,where), 0xCF8); - *value = inw(0xCFC + (where&2)); - return PCIBIOS_SUCCESSFUL; + int result; + u32 data; + + if (!value) + return -EINVAL; + + result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, &data); + + *value = (u16)data; + + return result; } static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - outl(CONFIG_CMD(dev,where), 0xCF8); - *value = inl(0xCFC); - return PCIBIOS_SUCCESSFUL; + if (!value) + return -EINVAL; + + return pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); } static int pci_conf1_write_config_byte(struct pci_dev *dev, int where, u8 value) { - outl(CONFIG_CMD(dev,where), 0xCF8); - outb(value, 0xCFC + (where&3)); - return PCIBIOS_SUCCESSFUL; + return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, value); } static int pci_conf1_write_config_word(struct pci_dev *dev, int where, u16 value) { - outl(CONFIG_CMD(dev,where), 0xCF8); - outw(value, 0xCFC + (where&2)); - return PCIBIOS_SUCCESSFUL; + return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, value); } static int pci_conf1_write_config_dword(struct pci_dev *dev, int where, u32 value) { - outl(CONFIG_CMD(dev,where), 0xCF8); - outl(value, 0xCFC); - return PCIBIOS_SUCCESSFUL; + return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); } -#undef CONFIG_CMD - static struct pci_ops pci_direct_conf1 = { pci_conf1_read_config_byte, pci_conf1_read_config_word, @@ -88,68 +168,131 @@ pci_conf1_write_config_dword }; + /* * Functions for accessing PCI configuration space with type 2 accesses */ -#define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where) -#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0) -#define SET(dev) if (dev->devfn & 0x80) return PCIBIOS_DEVICE_NOT_FOUND; \ - outb(FUNC(dev->devfn), 0xCF8); \ - outb(dev->bus->number, 0xCFA); +#define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg) -static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value) +static int pci_conf2_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) { - SET(dev); - *value = inb(IOADDR(dev->devfn,where)); + unsigned long flags; + + if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + return -EINVAL; + + if (dev & 0x10) + return PCIBIOS_DEVICE_NOT_FOUND; + + spin_lock_irqsave(&pci_config_lock, flags); + + outb((u8)(0xF0 | (fn << 1)), 0xCF8); + outb((u8)bus, 0xCFA); + + switch (len) { + case 1: + *value = inb(PCI_CONF2_ADDRESS(dev, reg)); + break; + case 2: + *value = inw(PCI_CONF2_ADDRESS(dev, reg)); + break; + case 4: + *value = inl(PCI_CONF2_ADDRESS(dev, reg)); + break; + } + outb (0, 0xCF8); - return PCIBIOS_SUCCESSFUL; + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return 0; +} + +static int pci_conf2_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +{ + unsigned long flags; + + if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + return -EINVAL; + + if (dev & 0x10) + return PCIBIOS_DEVICE_NOT_FOUND; + + spin_lock_irqsave(&pci_config_lock, flags); + + outb((u8)(0xF0 | (fn << 1)), 0xCF8); + outb((u8)bus, 0xCFA); + + switch (len) { + case 1: + outb ((u8)value, PCI_CONF2_ADDRESS(dev, reg)); + break; + case 2: + outw ((u16)value, PCI_CONF2_ADDRESS(dev, reg)); + break; + case 4: + outl ((u32)value, PCI_CONF2_ADDRESS(dev, reg)); + break; + } + + outb (0, 0xCF8); + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return 0; +} + +#undef PCI_CONF2_ADDRESS + +static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value) +{ + int result; + u32 data; + result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, &data); + *value = (u8)data; + return result; } static int pci_conf2_read_config_word(struct pci_dev *dev, int where, u16 *value) { - SET(dev); - *value = inw(IOADDR(dev->devfn,where)); - outb (0, 0xCF8); - return PCIBIOS_SUCCESSFUL; + int result; + u32 data; + result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, &data); + *value = (u8)data; + return result; } static int pci_conf2_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - SET(dev); - *value = inl (IOADDR(dev->devfn,where)); - outb (0, 0xCF8); - return PCIBIOS_SUCCESSFUL; + int result; + u32 data; + result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, &data); + *value = (u8)data; + return result; } static int pci_conf2_write_config_byte(struct pci_dev *dev, int where, u8 value) { - SET(dev); - outb (value, IOADDR(dev->devfn,where)); - outb (0, 0xCF8); - return PCIBIOS_SUCCESSFUL; + return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, value); } static int pci_conf2_write_config_word(struct pci_dev *dev, int where, u16 value) { - SET(dev); - outw (value, IOADDR(dev->devfn,where)); - outb (0, 0xCF8); - return PCIBIOS_SUCCESSFUL; + return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, value); } static int pci_conf2_write_config_dword(struct pci_dev *dev, int where, u32 value) { - SET(dev); - outl (value, IOADDR(dev->devfn,where)); - outb (0, 0xCF8); - return PCIBIOS_SUCCESSFUL; + return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); } -#undef SET -#undef IOADDR -#undef FUNC - static struct pci_ops pci_direct_conf2 = { pci_conf2_read_config_byte, pci_conf2_read_config_word, @@ -159,6 +302,7 @@ pci_conf2_write_config_dword }; + /* * Before we decide to use direct hardware access mechanisms, we try to do some * trivial checks to ensure it at least _seems_ to be working -- we just test @@ -420,114 +564,176 @@ return (int) (ret & 0xff00) >> 8; } +static int pci_bios_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) +{ + unsigned long result = 0; + unsigned long flags; + unsigned long bx = ((bus << 8) | (dev << 3) | fn); + + if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + return -EINVAL; + + spin_lock_irqsave(&pci_config_lock, flags); + + switch (len) { + case 1: + __asm__("lcall (%%esi); cld\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (result) + : "1" (PCIBIOS_READ_CONFIG_BYTE), + "b" (bx), + "D" ((long)reg), + "S" (&pci_indirect)); + break; + case 2: + __asm__("lcall (%%esi); cld\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (result) + : "1" (PCIBIOS_READ_CONFIG_WORD), + "b" (bx), + "D" ((long)reg), + "S" (&pci_indirect)); + break; + case 4: + __asm__("lcall (%%esi); cld\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (result) + : "1" (PCIBIOS_READ_CONFIG_DWORD), + "b" (bx), + "D" ((long)reg), + "S" (&pci_indirect)); + break; + } + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return (int)((result & 0xff00) >> 8); +} + +static int pci_bios_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +{ + unsigned long result = 0; + unsigned long flags; + unsigned long bx = ((bus << 8) | (dev << 3) | fn); + + if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + return -EINVAL; + + spin_lock_irqsave(&pci_config_lock, flags); + + switch (len) { + case 1: + __asm__("lcall (%%esi); cld\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (result) + : "0" (PCIBIOS_WRITE_CONFIG_BYTE), + "c" (value), + "b" (bx), + "D" ((long)reg), + "S" (&pci_indirect)); + break; + case 2: + __asm__("lcall (%%esi); cld\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (result) + : "0" (PCIBIOS_WRITE_CONFIG_WORD), + "c" (value), + "b" (bx), + "D" ((long)reg), + "S" (&pci_indirect)); + break; + case 4: + __asm__("lcall (%%esi); cld\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (result) + : "0" (PCIBIOS_WRITE_CONFIG_DWORD), + "c" (value), + "b" (bx), + "D" ((long)reg), + "S" (&pci_indirect)); + break; + } + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return (int)((result & 0xff00) >> 8); +} + static int pci_bios_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long ret; - unsigned long bx = (dev->bus->number << 8) | dev->devfn; + int result; + u32 data; - __asm__("lcall (%%esi); cld\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_BYTE), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; + if (!value) + return -EINVAL; + + result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, &data); + + *value = (u8)data; + + return result; } static int pci_bios_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long ret; - unsigned long bx = (dev->bus->number << 8) | dev->devfn; + int result; + u32 data; - __asm__("lcall (%%esi); cld\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_WORD), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; + if (!value) + return -EINVAL; + + result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, &data); + + *value = (u16)data; + + return result; } static int pci_bios_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long ret; - unsigned long bx = (dev->bus->number << 8) | dev->devfn; - - __asm__("lcall (%%esi); cld\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_DWORD), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; + if (!value) + return -EINVAL; + + return pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); } static int pci_bios_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long ret; - unsigned long bx = (dev->bus->number << 8) | dev->devfn; - - __asm__("lcall (%%esi); cld\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_BYTE), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; + return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, value); } static int pci_bios_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long ret; - unsigned long bx = (dev->bus->number << 8) | dev->devfn; - - __asm__("lcall (%%esi); cld\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_WORD), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; + return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, value); } static int pci_bios_write_config_dword(struct pci_dev *dev, int where, u32 value) { - unsigned long ret; - unsigned long bx = (dev->bus->number << 8) | dev->devfn; - - __asm__("lcall (%%esi); cld\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_DWORD), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; + return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); } + /* * Function table for BIOS32 access */ @@ -981,34 +1187,47 @@ pci_read_bridge_bases(b); } -/* - * Initialization. Try all known PCI access methods. Note that we support - * using both PCI BIOS and direct access: in such cases, we use I/O ports - * to access config space, but we still keep BIOS order of cards to be - * compatible with 2.0.X. This should go away some day. - */ -void __init pcibios_init(void) +void __init pcibios_config_init(void) { - struct pci_ops *bios = NULL; - struct pci_ops *dir = NULL; + /* + * Try all known PCI access methods. Note that we support using + * both PCI BIOS and direct access, with a preference for direct. + */ #ifdef CONFIG_PCI_BIOS - if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) { + if ((pci_probe & PCI_PROBE_BIOS) + && ((pci_root_ops = pci_find_bios()))) { pci_probe |= PCI_BIOS_SORT; pci_bios_present = 1; + pci_config_read = pci_bios_read; + pci_config_write = pci_bios_write; } #endif + #ifdef CONFIG_PCI_DIRECT - if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2)) - dir = pci_check_direct(); + if ((pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2)) + && (pci_root_ops = pci_check_direct())) { + if (pci_root_ops == &pci_direct_conf1) { + pci_config_read = pci_conf1_read; + pci_config_write = pci_conf1_write; + } + else { + pci_config_read = pci_conf2_read; + pci_config_write = pci_conf2_write; + } + } #endif - if (dir) - pci_root_ops = dir; - else if (bios) - pci_root_ops = bios; - else { - printk("PCI: No PCI bus detected\n"); + + return; +} + +void __init pcibios_init(void) +{ + if (!pci_root_ops) + pcibios_config_init(); + if (!pci_root_ops) { + printk("PCI: System does not support PCI\n"); return; } diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.4.9/linux/arch/i386/kernel/setup.c Wed Jul 25 17:10:17 2001 +++ linux/arch/i386/kernel/setup.c Sat Sep 8 18:54:32 2001 @@ -64,6 +64,9 @@ * * VIA C3 Support. * Dave Jones , March 2001 + * + * AMD Athlon/Duron/Thunderbird bluesmoke support. + * Dave Jones , April 2001. */ /* @@ -93,6 +96,7 @@ #include #include #include +#include #include #include #include @@ -145,9 +149,9 @@ unsigned char aux_device_present; +extern void mcheck_init(struct cpuinfo_x86 *c); extern int root_mountflags; extern char _text, _etext, _edata, _end; -extern unsigned long cpu_khz; static int disable_x86_serial_nr __initdata = 1; static int disable_x86_fxsr __initdata = 0; @@ -1088,11 +1092,18 @@ l2size = ecx >> 16; /* AMD errata T13 (order #21922) */ - if (c->x86_vendor == X86_VENDOR_AMD && - c->x86 == 6 && - c->x86_model == 3 && - c->x86_mask == 0) { - l2size = 64; + if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) { + if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */ + l2size = 64; + if (c->x86_model == 4 && + (c->x86_mask==0 || c->x86_mask==1)) /* Tbird rev A1/A2 */ + l2size = 256; + } + + /* VIA C3 CPUs (670-68F) need further shifting. */ + if (c->x86_vendor == X86_VENDOR_CENTAUR && (c->x86 == 6) && + ((c->x86_model == 7) || (c->x86_model == 8))) { + l2size = l2size >> 8; } if ( l2size == 0 ) @@ -1109,7 +1120,7 @@ * misexecution of code under Linux. Owners of such processors should * contact AMD for precise details and a CPU swap. * - * See http://www.mygale.com/~poulot/k6bug.html + * See http://www.multimania.com/poulot/k6bug.html * http://www.amd.com/K6/k6docs/revgd.html * * The following test is erm.. interesting. AMD neglected to up @@ -1126,6 +1137,12 @@ int mbytes = max_mapnr >> (20-PAGE_SHIFT); int r; + /* + * FIXME: We should handle the K5 here. Set up the write + * range and also turn on MSR 83 bits 4 and 31 (write alloc, + * no bus pipeline) + */ + /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_bit(0*32+31, &c->x86_capability); @@ -1185,13 +1202,13 @@ if(mbytes>508) mbytes=508; - rdmsr(0xC0000082, l, h); + rdmsr(MSR_K6_WHCR, l, h); if ((l&0x0000FFFF)==0) { unsigned long flags; l=(1<<0)|((mbytes/4)<<1); local_irq_save(flags); - __asm__ __volatile__ ("wbinvd": : :"memory"); - wrmsr(0xC0000082, l, h); + wbinvd(); + wrmsr(MSR_K6_WHCR, l, h); local_irq_restore(flags); printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n", mbytes); @@ -1206,13 +1223,13 @@ if(mbytes>4092) mbytes=4092; - rdmsr(0xC0000082, l, h); + rdmsr(MSR_K6_WHCR, l, h); if ((l&0xFFFF0000)==0) { unsigned long flags; l=((mbytes>>2)<<22)|(1<<16); local_irq_save(flags); - __asm__ __volatile__ ("wbinvd": : :"memory"); - wrmsr(0xC0000082, l, h); + wbinvd(); + wrmsr(MSR_K6_WHCR, l, h); local_irq_restore(flags); printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n", mbytes); @@ -1226,10 +1243,10 @@ set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability); break; } - break; case 6: /* An Athlon/Duron. We can trust the BIOS probably */ + mcheck_init(c); break; } @@ -1312,9 +1329,10 @@ static void __init check_cx686_slop(struct cpuinfo_x86 *c) { + unsigned long flags; + if (Cx86_dir0_msb == 3) { unsigned char ccr3, ccr5; - unsigned long flags; local_irq_save(flags); ccr3 = getCx86(CX86_CCR3); @@ -1551,14 +1569,12 @@ name="??"; } - /* get FCR */ - rdmsr(0x107, lo, hi); - + rdmsr(MSR_IDT_FCR1, lo, hi); newlo=(lo|fcr_set) & (~fcr_clr); if (newlo!=lo) { printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo ); - wrmsr(0x107, newlo, hi ); + wrmsr(MSR_IDT_FCR1, newlo, hi ); } else { printk(KERN_INFO "Centaur FCR is 0x%X\n",lo); } @@ -1577,14 +1593,15 @@ c->x86_cache_size = (cc>>24)+(dd>>24); } sprintf( c->x86_model_id, "WinChip %s", name ); + mcheck_init(c); break; case 6: switch (c->x86_model) { case 6 ... 7: /* Cyrix III or C3 */ - rdmsr (0x1107, lo, hi); + rdmsr (MSR_VIA_FCR, lo, hi); lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */ - wrmsr (0x1107, lo, hi); + wrmsr (MSR_VIA_FCR, lo, hi); set_bit(X86_FEATURE_CX8, &c->x86_capability); set_bit(X86_FEATURE_3DNOW, &c->x86_capability); @@ -1595,7 +1612,6 @@ } break; } - } @@ -1668,7 +1684,6 @@ if (c->x86_model > 2) printk(" II"); printk("\n"); - printk("If you have one of these please email davej@suse.de\n"); /* Unhide possibly hidden capability flags The mp6 iDragon family don't have MSRs. @@ -1694,7 +1709,6 @@ #ifndef CONFIG_M686 static int f00f_workaround_enabled = 0; #endif - extern void mcheck_init(struct cpuinfo_x86 *c); char *p = NULL; unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ @@ -1989,9 +2003,9 @@ disable_x86_serial_nr ) { /* Disable processor serial number */ unsigned long lo,hi; - rdmsr(0x119,lo,hi); + rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi); lo |= 0x200000; - wrmsr(0x119,lo,hi); + wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi); printk(KERN_NOTICE "CPU serial number disabled.\n"); clear_bit(X86_FEATURE_PN, &c->x86_capability); diff -u --recursive --new-file v2.4.9/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.4.9/linux/arch/i386/mm/fault.c Tue May 15 00:16:51 2001 +++ linux/arch/i386/mm/fault.c Fri Sep 7 19:11:12 2001 @@ -313,7 +313,7 @@ tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; - info.si_code = SIGBUS; + info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_ADRERR; info.si_addr = (void *)address; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/ioctl32.c linux/arch/mips64/kernel/ioctl32.c --- v2.4.9/linux/arch/mips64/kernel/ioctl32.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/ioctl32.c Sat Sep 1 11:01:28 2001 @@ -770,6 +770,8 @@ IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans), IOCTL32_DEFAULT(BLKELVGET), IOCTL32_DEFAULT(BLKELVSET), + IOCTL32_DEFAULT(BLKBSZGET), + IOCTL32_DEFAULT(BLKBSZSET), #ifdef CONFIG_MD /* status */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/8xx_io/Config.in linux/arch/ppc/8xx_io/Config.in --- v2.4.9/linux/arch/ppc/8xx_io/Config.in Wed May 16 09:57:20 2001 +++ linux/arch/ppc/8xx_io/Config.in Sat Sep 8 12:39:33 2001 @@ -31,6 +31,7 @@ comment 'Generic MPC8xx Options' bool 'Copy-Back Data Cache (else Writethrough)' CONFIG_8xx_COPYBACK bool 'CPU6 Silicon Errata (860 Pre Rev. C)' CONFIG_8xx_CPU6 +bool 'I2C/SPI Microcode Patch' CONFIG_UCODE_PATCH if [ "$CONFIG_IDE" = "y" ]; then bool 'MPC8xx direct IDE support on PCMCIA port' CONFIG_BLK_DEV_MPC8xx_IDE diff -u --recursive --new-file v2.4.9/linux/arch/ppc/8xx_io/Makefile linux/arch/ppc/8xx_io/Makefile --- v2.4.9/linux/arch/ppc/8xx_io/Makefile Mon May 21 17:04:46 2001 +++ linux/arch/ppc/8xx_io/Makefile Sat Sep 8 12:39:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:20 cort +# BK Id: SCCS/s.Makefile 1.6 08/30/01 09:33:48 trini # # # Makefile for the linux MPC8xx ppc-specific parts of comm processor @@ -15,5 +15,6 @@ obj-$(CONFIG_FEC_ENET) += fec.o obj-$(CONFIG_SCC_ENET) += enet.o +obj-$(CONFIG_UCODE_PATCH) += micropatch.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c --- v2.4.9/linux/arch/ppc/8xx_io/enet.c Mon May 21 17:04:46 2001 +++ linux/arch/ppc/8xx_io/enet.c Sun Sep 2 07:48:02 2001 @@ -651,11 +651,10 @@ volatile scc_t *sccp; volatile scc_enet_t *ep; volatile immap_t *immap; - extern unsigned long _get_IMMR(void); cp = cpmp; /* Get pointer to Communication Processor */ - immap = (immap_t *)(_get_IMMR() & 0xFFFF0000); /* and to internal registers */ + immap = (immap_t *)(mfspr(IMMR) & 0xFFFF0000); /* and to internal registers */ bd = (bd_t *)__res; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c --- v2.4.9/linux/arch/ppc/8xx_io/fec.c Mon May 21 17:04:46 2001 +++ linux/arch/ppc/8xx_io/fec.c Sun Sep 2 07:48:02 2001 @@ -1509,7 +1509,6 @@ volatile immap_t *immap; volatile fec_t *fecp; bd_t *bd; - extern uint _get_IMMR(void); #ifdef CONFIG_SCC_ENET unsigned char tmpaddr[6]; #endif @@ -1680,7 +1679,7 @@ /* Bits moved from Rev. D onward. */ - if ((_get_IMMR() & 0xffff) < 0x0501) + if ((mfspr(IMMR) & 0xffff) < 0x0501) immap->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ else immap->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/8xx_io/micropatch.c linux/arch/ppc/8xx_io/micropatch.c --- v2.4.9/linux/arch/ppc/8xx_io/micropatch.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/8xx_io/micropatch.c Sat Sep 8 12:39:33 2001 @@ -0,0 +1,777 @@ + +/* Microcode patches for the CPM as supplied by Motorola. + * This is the one for IIC/SPI. There is a newer one that + * also relocates SMC2, but this would require additional changes + * to uart.c, so I am holding off on that for a moment. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "commproc.h" + +/* Define this to get SMC patches as well. You need to modify the uart + * driver as well...... +#define USE_SMC_PATCH 1 + */ + +#ifdef CONFIG_USB_MPC8xx +#define USE_USB_SOF_PATCH +#endif + +#ifdef USE_IIC_PATCH +#define PATCH_DEFINED + /* IIC/SPI */ +uint patch_2000[] = { + 0x7FFFEFD9, + 0x3FFD0000, + 0x7FFB49F7, + 0x7FF90000, + 0x5FEFADF7, + 0x5F89ADF7, + 0x5FEFAFF7, + 0x5F89AFF7, + 0x3A9CFBC8, + 0xE7C0EDF0, + 0x77C1E1BB, + 0xF4DC7F1D, + 0xABAD932F, + 0x4E08FDCF, + 0x6E0FAFF8, + 0x7CCF76CF, + 0xFD1FF9CF, + 0xABF88DC6, + 0xAB5679F7, + 0xB0937383, + 0xDFCE79F7, + 0xB091E6BB, + 0xE5BBE74F, + 0xB3FA6F0F, + 0x6FFB76CE, + 0xEE0DF9CF, + 0x2BFBEFEF, + 0xCFEEF9CF, + 0x76CEAD24, + 0x90B2DF9A, + 0x7FDDD0BF, + 0x4BF847FD, + 0x7CCF76CE, + 0xCFEF7E1F, + 0x7F1D7DFD, + 0xF0B6EF71, + 0x7FC177C1, + 0xFBC86079, + 0xE722FBC8, + 0x5FFFDFFF, + 0x5FB2FFFB, + 0xFBC8F3C8, + 0x94A67F01, + 0x7F1D5F39, + 0xAFE85F5E, + 0xFFDFDF96, + 0xCB9FAF7D, + 0x5FC1AFED, + 0x8C1C5FC1, + 0xAFDD5FC3, + 0xDF9A7EFD, + 0xB0B25FB2, + 0xFFFEABAD, + 0x5FB2FFFE, + 0x5FCE600B, + 0xE6BB600B, + 0x5FCEDFC6, + 0x27FBEFDF, + 0x5FC8CFDE, + 0x3A9CE7C0, + 0xEDF0F3C8, + 0x7F0154CD, + 0x7F1D2D3D, + 0x363A7570, + 0x7E0AF1CE, + 0x37EF2E68, + 0x7FEE10EC, + 0xADF8EFDE, + 0xCFEAE52F, + 0x7D0FE12B, + 0xF1CE5F65, + 0x7E0A4DF8, + 0xCFEA5F72, + 0x7D0BEFEE, + 0xCFEA5F74, + 0xE522EFDE, + 0x5F74CFDA, + 0x0B627385, + 0xDF627E0A, + 0x30D8145B, + 0xBFFFF3C8, + 0x5FFFDFFF, + 0xA7F85F5E, + 0xBFFE7F7D, + 0x10D31450, + 0x5F36BFFF, + 0xAF785F5E, + 0xBFFDA7F8, + 0x5F36BFFE, + 0x77FD30C0, + 0x4E08FDCF, + 0xE5FF6E0F, + 0xAFF87E1F, + 0x7E0FFD1F, + 0xF1CF5F1B, + 0xABF80D5E, + 0x5F5EFFEF, + 0x79F730A2, + 0xAFDD5F34, + 0x47F85F34, + 0xAFED7FDD, + 0x50B24978, + 0x47FD7F1D, + 0x7DFD70AD, + 0xEF717EC1, + 0x6BA47F01, + 0x2D267EFD, + 0x30DE5F5E, + 0xFFFD5F5E, + 0xFFEF5F5E, + 0xFFDF0CA0, + 0xAFED0A9E, + 0xAFDD0C3A, + 0x5F3AAFBD, + 0x7FBDB082, + 0x5F8247F8 +}; + +uint patch_2f00[] = { + 0x3E303430, + 0x34343737, + 0xABF7BF9B, + 0x994B4FBD, + 0xBD599493, + 0x349FFF37, + 0xFB9B177D, + 0xD9936956, + 0xBBFDD697, + 0xBDD2FD11, + 0x31DB9BB3, + 0x63139637, + 0x93733693, + 0x193137F7, + 0x331737AF, + 0x7BB9B999, + 0xBB197957, + 0x7FDFD3D5, + 0x73B773F7, + 0x37933B99, + 0x1D115316, + 0x99315315, + 0x31694BF4, + 0xFBDBD359, + 0x31497353, + 0x76956D69, + 0x7B9D9693, + 0x13131979, + 0x79376935 +}; +#endif + +#ifdef USE_SMC_PATCH +#define PATCH_DEFINED +/* SMC2/IIC/SPI Patch */ +/* This is the area from 0x2000 to 0x23ff. +*/ +uint patch_2000[] = { + 0x3fff0000, + 0x3ffd0000, + 0x3ffb0000, + 0x3ff90000, + 0x5f13eff8, + 0x5eb5eff8, + 0x5f88adf7, + 0x5fefadf7, + 0x3a9cfbc8, + 0x77cae1bb, + 0xf4de7fad, + 0xabae9330, + 0x4e08fdcf, + 0x6e0faff8, + 0x7ccf76cf, + 0xfdaff9cf, + 0xabf88dc8, + 0xab5879f7, + 0xb0925d8d, + 0xdfd079f7, + 0xb090e6bb, + 0xe5bbe74f, + 0x9e046f0f, + 0x6ffb76ce, + 0xee0cf9cf, + 0x2bfbefef, + 0xcfeef9cf, + 0x76cead23, + 0x90b3df99, + 0x7fddd0c1, + 0x4bf847fd, + 0x7ccf76ce, + 0xcfef77ca, + 0x7eaf7fad, + 0x7dfdf0b7, + 0xef7a7fca, + 0x77cafbc8, + 0x6079e722, + 0xfbc85fff, + 0xdfff5fb3, + 0xfffbfbc8, + 0xf3c894a5, + 0xe7c9edf9, + 0x7f9a7fad, + 0x5f36afe8, + 0x5f5bffdf, + 0xdf95cb9e, + 0xaf7d5fc3, + 0xafed8c1b, + 0x5fc3afdd, + 0x5fc5df99, + 0x7efdb0b3, + 0x5fb3fffe, + 0xabae5fb3, + 0xfffe5fd0, + 0x600be6bb, + 0x600b5fd0, + 0xdfc827fb, + 0xefdf5fca, + 0xcfde3a9c, + 0xe7c9edf9, + 0xf3c87f9e, + 0x54ca7fed, + 0x2d3a3637, + 0x756f7e9a, + 0xf1ce37ef, + 0x2e677fee, + 0x10ebadf8, + 0xefdecfea, + 0xe52f7d9f, + 0xe12bf1ce, + 0x5f647e9a, + 0x4df8cfea, + 0x5f717d9b, + 0xefeecfea, + 0x5f73e522, + 0xefde5f73, + 0xcfda0b61, + 0x5d8fdf61, + 0xe7c9edf9, + 0x7e9a30d5, + 0x1458bfff, + 0xf3c85fff, + 0xdfffa7f8, + 0x5f5bbffe, + 0x7f7d10d0, + 0x144d5f33, + 0xbfffaf78, + 0x5f5bbffd, + 0xa7f85f33, + 0xbffe77fd, + 0x30bd4e08, + 0xfdcfe5ff, + 0x6e0faff8, + 0x7eef7e9f, + 0xfdeff1cf, + 0x5f17abf8, + 0x0d5b5f5b, + 0xffef79f7, + 0x309eafdd, + 0x5f3147f8, + 0x5f31afed, + 0x7fdd50af, + 0x497847fd, + 0x7f9e7fed, + 0x7dfd70a9, + 0xef7e7ece, + 0x6ba07f9e, + 0x2d227efd, + 0x30db5f5b, + 0xfffd5f5b, + 0xffef5f5b, + 0xffdf0c9c, + 0xafed0a9a, + 0xafdd0c37, + 0x5f37afbd, + 0x7fbdb081, + 0x5f8147f8, + 0x3a11e710, + 0xedf0ccdd, + 0xf3186d0a, + 0x7f0e5f06, + 0x7fedbb38, + 0x3afe7468, + 0x7fedf4fc, + 0x8ffbb951, + 0xb85f77fd, + 0xb0df5ddd, + 0xdefe7fed, + 0x90e1e74d, + 0x6f0dcbf7, + 0xe7decfed, + 0xcb74cfed, + 0xcfeddf6d, + 0x91714f74, + 0x5dd2deef, + 0x9e04e7df, + 0xefbb6ffb, + 0xe7ef7f0e, + 0x9e097fed, + 0xebdbeffa, + 0xeb54affb, + 0x7fea90d7, + 0x7e0cf0c3, + 0xbffff318, + 0x5fffdfff, + 0xac59efea, + 0x7fce1ee5, + 0xe2ff5ee1, + 0xaffbe2ff, + 0x5ee3affb, + 0xf9cc7d0f, + 0xaef8770f, + 0x7d0fb0c6, + 0xeffbbfff, + 0xcfef5ede, + 0x7d0fbfff, + 0x5ede4cf8, + 0x7fddd0bf, + 0x49f847fd, + 0x7efdf0bb, + 0x7fedfffd, + 0x7dfdf0b7, + 0xef7e7e1e, + 0x5ede7f0e, + 0x3a11e710, + 0xedf0ccab, + 0xfb18ad2e, + 0x1ea9bbb8, + 0x74283b7e, + 0x73c2e4bb, + 0x2ada4fb8, + 0xdc21e4bb, + 0xb2a1ffbf, + 0x5e2c43f8, + 0xfc87e1bb, + 0xe74ffd91, + 0x6f0f4fe8, + 0xc7ba32e2, + 0xf396efeb, + 0x600b4f78, + 0xe5bb760b, + 0x53acaef8, + 0x4ef88b0e, + 0xcfef9e09, + 0xabf8751f, + 0xefef5bac, + 0x741f4fe8, + 0x751e760d, + 0x7fdbf081, + 0x741cafce, + 0xefcc7fce, + 0x751e70ac, + 0x741ce7bb, + 0x3372cfed, + 0xafdbefeb, + 0xe5bb760b, + 0x53f2aef8, + 0xafe8e7eb, + 0x4bf8771e, + 0x7e247fed, + 0x4fcbe2cc, + 0x7fbc30a9, + 0x7b0f7a0f, + 0x34d577fd, + 0x308b5db7, + 0xde553e5f, + 0xaf78741f, + 0x741f30f0, + 0xcfef5e2c, + 0x741f3eac, + 0xafb8771e, + 0x5e677fed, + 0x0bd3e2cc, + 0x741ccfec, + 0xe5ca53cd, + 0x6fcb4f74, + 0x5dadde4b, + 0x2ab63d38, + 0x4bb3de30, + 0x751f741c, + 0x6c42effa, + 0xefea7fce, + 0x6ffc30be, + 0xefec3fca, + 0x30b3de2e, + 0xadf85d9e, + 0xaf7daefd, + 0x5d9ede2e, + 0x5d9eafdd, + 0x761f10ac, + 0x1da07efd, + 0x30adfffe, + 0x4908fb18, + 0x5fffdfff, + 0xafbb709b, + 0x4ef85e67, + 0xadf814ad, + 0x7a0f70ad, + 0xcfef50ad, + 0x7a0fde30, + 0x5da0afed, + 0x3c12780f, + 0xefef780f, + 0xefef790f, + 0xa7f85e0f, + 0xffef790f, + 0xefef790f, + 0x14adde2e, + 0x5d9eadfd, + 0x5e2dfffb, + 0xe79addfd, + 0xeff96079, + 0x607ae79a, + 0xddfceff9, + 0x60795dff, + 0x607acfef, + 0xefefefdf, + 0xefbfef7f, + 0xeeffedff, + 0xebffe7ff, + 0xafefafdf, + 0xafbfaf7f, + 0xaeffadff, + 0xabffa7ff, + 0x6fef6fdf, + 0x6fbf6f7f, + 0x6eff6dff, + 0x6bff67ff, + 0x2fef2fdf, + 0x2fbf2f7f, + 0x2eff2dff, + 0x2bff27ff, + 0x4e08fd1f, + 0xe5ff6e0f, + 0xaff87eef, + 0x7e0ffdef, + 0xf11f6079, + 0xabf8f542, + 0x7e0af11c, + 0x37cfae3a, + 0x7fec90be, + 0xadf8efdc, + 0xcfeae52f, + 0x7d0fe12b, + 0xf11c6079, + 0x7e0a4df8, + 0xcfea5dc4, + 0x7d0befec, + 0xcfea5dc6, + 0xe522efdc, + 0x5dc6cfda, + 0x4e08fd1f, + 0x6e0faff8, + 0x7c1f761f, + 0xfdeff91f, + 0x6079abf8, + 0x761cee24, + 0xf91f2bfb, + 0xefefcfec, + 0xf91f6079, + 0x761c27fb, + 0xefdf5da7, + 0xcfdc7fdd, + 0xd09c4bf8, + 0x47fd7c1f, + 0x761ccfcf, + 0x7eef7fed, + 0x7dfdf093, + 0xef7e7f1e, + 0x771efb18, + 0x6079e722, + 0xe6bbe5bb, + 0xae0ae5bb, + 0x600bae85, + 0xe2bbe2bb, + 0xe2bbe2bb, + 0xaf02e2bb, + 0xe2bb2ff9, + 0x6079e2bb +}; + + /* This is from 0x2f00 to 0x2fff + */ +uint patch_2f00[] = { + 0x30303030, + 0x3e3e3434, + 0xabbf9b99, + 0x4b4fbdbd, + 0x59949334, + 0x9fff37fb, + 0x9b177dd9, + 0x936956bb, + 0xfbdd697b, + 0xdd2fd113, + 0x1db9f7bb, + 0x36313963, + 0x79373369, + 0x3193137f, + 0x7331737a, + 0xf7bb9b99, + 0x9bb19795, + 0x77fdfd3d, + 0x573b773f, + 0x737933f7, + 0xb991d115, + 0x31699315, + 0x31531694, + 0xbf4fbdbd, + 0x35931497, + 0x35376956, + 0xbd697b9d, + 0x96931313, + 0x19797937, + 0x6935af78, + 0xb9b3baa3, + 0xb8788683, + 0x368f78f7, + 0x87778733, + 0x3ffffb3b, + 0x8e8f78b8, + 0x1d118e13, + 0xf3ff3f8b, + 0x6bd8e173, + 0xd1366856, + 0x68d1687b, + 0x3daf78b8, + 0x3a3a3f87, + 0x8f81378f, + 0xf876f887, + 0x77fd8778, + 0x737de8d6, + 0xbbf8bfff, + 0xd8df87f7, + 0xfd876f7b, + 0x8bfff8bd, + 0x8683387d, + 0xb873d87b, + 0x3b8fd7f8, + 0xf7338883, + 0xbb8ee1f8, + 0xef837377, + 0x3337b836, + 0x817d11f8, + 0x7378b878, + 0xd3368b7d, + 0xed731b7d, + 0x833731f3, + 0xf22f3f23 +}; + +uint patch_2e00[] = { + /* This is from 0x2e00 to 0x2e3c + */ + 0x27eeeeee, + 0xeeeeeeee, + 0xeeeeeeee, + 0xeeeeeeee, + 0xee4bf4fb, + 0xdbd259bb, + 0x1979577f, + 0xdfd2d573, + 0xb773f737, + 0x4b4fbdbd, + 0x25b9b177, + 0xd2d17376, + 0x956bbfdd, + 0x697bdd2f, + 0xff9f79ff, + 0xff9ff22f +}; +#endif + +#ifdef USE_USB_SOF_PATCH +#define PATCH_DEFINED +uint patch_2000[] = { + 0x7fff0000, + 0x7ffd0000, + 0x7ffb0000, + 0x49f7ba5b, + 0xba383ffb, + 0xf9b8b46d, + 0xe5ab4e07, + 0xaf77bffe, + 0x3f7bbf79, + 0xba5bba38, + 0xe7676076, + 0x60750000 +}; + +uint patch_2f00[] = { + 0x3030304c, + 0xcab9e441, + 0xa1aaf220 +}; +#endif + +/* Load the microcode patch. This is called early in the CPM initialization + * with the controller in the reset state. We enable the processor after + * we load the patch. + */ +void +cpm_load_patch(volatile immap_t *immr) +{ +#ifdef PATCH_DEFINED + volatile uint *dp; + volatile cpm8xx_t *commproc; + volatile iic_t *iip; + volatile spi_t *spp; + int i; + + commproc = (cpm8xx_t *)&immr->im_cpm; + + /* We work closely with commproc.c. We know it only allocates + * from data only space. + * For this particular patch, we only use the bottom 512 bytes + * and the upper 256 byte extension. We will use the space + * starting at 1K for the relocated parameters, as the general + * CPM allocation won't come from that area. + */ + commproc->cp_rccr = 0; + + /* Copy the patch into DPRAM. + */ + dp = (uint *)(commproc->cp_dpmem); + for (i=0; i<(sizeof(patch_2000)/4); i++) + *dp++ = patch_2000[i]; + + dp = (uint *)&(commproc->cp_dpmem[0x0f00]); + for (i=0; i<(sizeof(patch_2f00)/4); i++) + *dp++ = patch_2f00[i]; + +#ifdef USE_USB_SOF_PATCH +#if 0 /* usb patch should not relocate iic */ + iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC]; +#define RPBASE 0x0030 + iip->iic_rpbase = RPBASE; + + /* Put SPI above the IIC, also 32-byte aligned. + */ + i = (RPBASE + sizeof(iic_t) + 31) & ~31; + spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI]; + spp->spi_rpbase = i; +#endif + + /* Enable uCode fetches from DPRAM. */ + commproc->cp_rccr = 0x0009; + + printk("USB uCode patch installed\n"); +#endif /* USE_USB_SOF_PATCH */ + +#if defined(USE_SMC_PATCH) || defined(USE_IIC_PATCH) + + iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC]; +#define RPBASE 0x0400 + iip->iic_rpbase = RPBASE; + + /* Put SPI above the IIC, also 32-byte aligned. + */ + i = (RPBASE + sizeof(iic_t) + 31) & ~31; + spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI]; + spp->spi_rpbase = i; + +#ifdef USE_SMC_PATCH + dp = (uint *)&(commproc->cp_dpmem[0x0e00]); + for (i=0; i<(sizeof(patch_2e00)/4); i++) + *dp++ = patch_2e00[i]; + + /* Enable the traps to get to it. + */ + commproc->cp_cpmcr1 = 0x8080; + commproc->cp_cpmcr2 = 0x808a; + commproc->cp_cpmcr3 = 0x8028; + commproc->cp_cpmcr4 = 0x802a; + + /* Enable uCode fetches from DPRAM. + */ + commproc->cp_rccr = 3; +#endif + +#ifdef USE_IIC_PATCH + /* Enable the traps to get to it. + */ + commproc->cp_cpmcr1 = 0x802a; + commproc->cp_cpmcr2 = 0x8028; + commproc->cp_cpmcr3 = 0x802e; + commproc->cp_cpmcr4 = 0x802c; + + /* Enable uCode fetches from DPRAM. + */ + commproc->cp_rccr = 1; + + printk("I2C uCode patch installed\n"); +#endif + + /* Relocate the IIC and SPI parameter areas. These have to + * aligned on 32-byte boundaries. + */ + iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC]; + iip->iic_rpbase = RPBASE; + + /* Put SPI above the IIC, also 32-byte aligned. + */ + i = (RPBASE + sizeof(iic_t) + 31) & ~31; + spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI]; + spp->spi_rpbase = i; + +#endif /* USE_SMC_PATCH || USE_IIC_PATCH */ +#endif /* PATCH_DEFINED */ +} + +void +verify_patch(volatile immap_t *immr) +{ +#ifdef PATCH_DEFINED + volatile uint *dp; + volatile cpm8xx_t *commproc; + int i; + + commproc = (cpm8xx_t *)&immr->im_cpm; + + printk("cp_rccr %x\n", commproc->cp_rccr); + commproc->cp_rccr = 0; + + dp = (uint *)(commproc->cp_dpmem); + for (i=0; i<(sizeof(patch_2000)/4); i++) + if (*dp++ != patch_2000[i]) { + printk("patch_2000 bad at %d\n", i); + dp--; + printk("found 0x%X, wanted 0x%X\n", *dp, patch_2000[i]); + break; + } + + dp = (uint *)&(commproc->cp_dpmem[0x0f00]); + for (i=0; i<(sizeof(patch_2f00)/4); i++) + if (*dp++ != patch_2f00[i]) { + printk("patch_2f00 bad at %d\n", i); + dp--; + printk("found 0x%X, wanted 0x%X\n", *dp, patch_2f00[i]); + break; + } + + commproc->cp_rccr = 0x0009; +#endif /* PATCH_DEFINED */ +} + diff -u --recursive --new-file v2.4.9/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.4.9/linux/arch/ppc/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.18 07/07/01 13:37:26 paulus +# BK Id: SCCS/s.Makefile 1.21 08/19/01 20:06:47 paulus # # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions @@ -14,6 +14,7 @@ # Rewritten by Cort Dougan and Paul Mackerras # +# Be sure to change PAGE_OFFSET in include/asm-ppc/page.h to match KERNELLOAD =0xc0000000 ifeq ($(shell uname -m),ppc) @@ -99,5 +100,5 @@ archmrproper: -archdep: +archdep: scripts/mkdep $(MAKEBOOT) fastdep diff -u --recursive --new-file v2.4.9/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c --- v2.4.9/linux/arch/ppc/amiga/config.c Mon May 21 17:04:46 2001 +++ linux/arch/ppc/amiga/config.c Fri Sep 7 09:28:38 2001 @@ -51,22 +51,22 @@ unsigned char amiga_psfreq; struct amiga_hw_present amiga_hw_present; -static const char s_a500[] __initdata = "A500"; -static const char s_a500p[] __initdata = "A500+"; -static const char s_a600[] __initdata = "A600"; -static const char s_a1000[] __initdata = "A1000"; -static const char s_a1200[] __initdata = "A1200"; -static const char s_a2000[] __initdata = "A2000"; -static const char s_a2500[] __initdata = "A2500"; -static const char s_a3000[] __initdata = "A3000"; -static const char s_a3000t[] __initdata = "A3000T"; -static const char s_a3000p[] __initdata = "A3000+"; -static const char s_a4000[] __initdata = "A4000"; -static const char s_a4000t[] __initdata = "A4000T"; -static const char s_cdtv[] __initdata = "CDTV"; -static const char s_cd32[] __initdata = "CD32"; -static const char s_draco[] __initdata = "Draco"; -static const char *amiga_models[] __initdata = { +static char s_a500[] __initdata = "A500"; +static char s_a500p[] __initdata = "A500+"; +static char s_a600[] __initdata = "A600"; +static char s_a1000[] __initdata = "A1000"; +static char s_a1200[] __initdata = "A1200"; +static char s_a2000[] __initdata = "A2000"; +static char s_a2500[] __initdata = "A2500"; +static char s_a3000[] __initdata = "A3000"; +static char s_a3000t[] __initdata = "A3000T"; +static char s_a3000p[] __initdata = "A3000+"; +static char s_a4000[] __initdata = "A4000"; +static char s_a4000t[] __initdata = "A4000T"; +static char s_cdtv[] __initdata = "CDTV"; +static char s_cd32[] __initdata = "CD32"; +static char s_draco[] __initdata = "Draco"; +static char *amiga_models[] __initdata = { s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000, s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco, }; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile --- v2.4.9/linux/arch/ppc/boot/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/Makefile Tue Aug 28 06:58:33 2001 @@ -12,8 +12,8 @@ GZIP_FLAGS = -v9f -CFLAGS := $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -D__BOOTER__ \ - -I$(TOPDIR)/arch/$(ARCH)/boot/include +CFLAGS += -fno-builtin -D__BOOTER__ -I$(TOPDIR)/arch/$(ARCH)/boot/include + AFLAGS += -D__BOOTER__ OBJCOPY_ARGS = -O elf32-powerpc diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/chrp/Makefile linux/arch/ppc/boot/chrp/Makefile --- v2.4.9/linux/arch/ppc/boot/chrp/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/chrp/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.10 07/19/01 09:11:27 trini +# BK Id: SCCS/s.Makefile 1.13 07/27/01 20:24:17 trini # # Makefile for making ELF bootable images for booting on CHRP # using Open Firmware. @@ -14,8 +14,6 @@ MSIZE= endif -CFLAGS += -fno-builtin - .c.o: $(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $< .S.o: @@ -23,7 +21,8 @@ LD_ARGS = -Ttext 0x00400000 -OBJS = ../common/crt0.o start.o main.o misc.o ../common/string.o image.o +OBJS = ../common/crt0.o start.o main.o misc.o ../common/string.o image.o \ + ../common/ofcommon.o LIBS = $(TOPDIR)/lib/lib.a ../lib/zlib.a ADDNOTE = ../utils/addnote PIGGYBACK = ../utils/piggyback diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/chrp/main.c linux/arch/ppc/boot/chrp/main.c --- v2.4.9/linux/arch/ppc/boot/chrp/main.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/boot/chrp/main.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.main.c 1.9 06/12/01 16:42:26 paulus + * BK Id: SCCS/s.main.c 1.13 07/27/01 20:24:17 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -10,14 +10,28 @@ * 2 of the License, or (at your option) any later version. */ #include "nonstdio.h" -#include "zlib.h" -#include #include -#include -extern void *finddevice(const char *); +extern char _end[]; +extern char initrd_data[]; +extern char image_data[]; +extern char sysmap_data[]; extern int getprop(void *, const char *, void *, int); -void gunzip(void *, int, unsigned char *, int *); +extern int initrd_len; +extern int image_len; +extern int sysmap_len; +extern unsigned int heap_max; +extern void claim(unsigned int virt, unsigned int size, unsigned int align); +extern void *finddevice(const char *); +extern void flush_cache(void *, unsigned long); +extern void gunzip(void *, int, unsigned char *, int *); +extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned int progend); +extern void pause(void); + +char *avail_ram; +char *begin_avail, *end_avail; +char *avail_high; #define RAM_START 0x00000000 #define RAM_END (64<<20) @@ -27,38 +41,28 @@ #define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF) #define PROG_START 0x00010000 +#define PROG_SIZE 0x00400000 /* 4MB */ -char *avail_ram; -char *end_avail; - -extern char _end[]; -extern char image_data[]; -extern int image_len; -extern char initrd_data[]; -extern int initrd_len; -extern char sysmap_data[]; -extern int sysmap_len; +#define SCRATCH_SIZE (128 << 10) -static char scratch[1024<<10]; /* 1MB of scratch space for gunzip */ +static char scratch[SCRATCH_SIZE]; /* 1MB of scratch space for gunzip */ +void chrpboot(int a1, int a2, void *prom) { - int ns, oh, i; unsigned sa, len; void *dst; unsigned char *im; - unsigned initrd_start, initrd_size; + unsigned initrd_start=0, initrd_size=0; extern char _start; - printf("chrpboot starting: loaded at 0x%x\n\r", &_start); + printf("chrpboot starting: loaded at 0x%p\n\r", &_start); if (initrd_len) { initrd_size = initrd_len; initrd_start = (RAM_END - initrd_size) & ~0xFFF; - a1 = initrd_start; - a2 = initrd_size; claim(initrd_start, RAM_END - initrd_start, 0); - printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r", + printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", initrd_start, initrd_data, initrd_size); memcpy((char *)initrd_start, initrd_data, initrd_size); } @@ -66,133 +70,31 @@ im = image_data; len = image_len; /* claim 4MB starting at PROG_START */ - claim(PROG_START, (4<<20) - PROG_START, 0); + claim(PROG_START, PROG_SIZE - PROG_START, 0); dst = (void *) PROG_START; if (im[0] == 0x1f && im[1] == 0x8b) { avail_ram = scratch; + begin_avail = avail_high = avail_ram; end_avail = scratch + sizeof(scratch); - printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); + printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); gunzip(dst, 0x400000, im, &len); printf("done %u bytes\n\r", len); + printf("%u bytes of heap consumed, max in use %u\n\r", + avail_high - begin_avail, heap_max); } else { memmove(dst, im, len); } flush_cache(dst, len); + make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp, + (PROG_START + PROG_SIZE)); sa = (unsigned long)PROG_START; printf("start address = 0x%x\n\r", sa); - { - struct bi_record *rec; - - rec = (struct bi_record *)_ALIGN((unsigned long)dst+len+(1<<20)-1,(1<<20)); - - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_BOOTLOADER_ID; - sprintf( (char *)rec->data, "chrpboot"); - rec->size = sizeof(struct bi_record) + strlen("chrpboot") + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_MACHTYPE; - rec->data[0] = _MACH_chrp; - rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -#if 0 - rec->tag = BI_SYSMAP; - rec->data[0] = (unsigned long)sysmap_data; - rec->data[1] = sysmap_len; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -#endif - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - } - (*(void (*)())sa)(a1, a2, prom); + (*(void (*)())sa)(a1, a2, prom, initrd_start, initrd_size); printf("returned?\n\r"); pause(); -} - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p = avail_ram; - - size *= items; - size = (size + 7) & -8; - avail_ram += size; - if (avail_ram > end_avail) { - printf("oops... out of memory\n\r"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ - nb = (nb + 7) & -8; - if (addr == (avail_ram - nb)) { - avail_ram -= nb; - } -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n\r"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n\r"); - exit(); - } - - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n\r", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d msg: %s\n\r", r, s.msg); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/chrp/start.c linux/arch/ppc/boot/chrp/start.c --- v2.4.9/linux/arch/ppc/boot/chrp/start.c Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/chrp/start.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.start.c 1.6 05/18/01 15:16:59 cort + * BK Id: SCCS/s.start.c 1.8 07/25/01 18:13:07 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -24,6 +24,9 @@ void printk(char *fmt, ...); +extern void chrpboot(int a1, int a2, void *prom); +extern int strlen(const char *s); + void start(int a1, int a2, void *promptr) { @@ -91,7 +94,7 @@ } void -exit() +exit(void) { struct prom_args { char *service; @@ -104,7 +107,7 @@ } void -pause() +pause(void) { struct prom_args { char *service; @@ -228,7 +231,7 @@ static int lineleft; int -getchar() +getchar(void) { int c; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/crt0.S linux/arch/ppc/boot/common/crt0.S --- v2.4.9/linux/arch/ppc/boot/common/crt0.S Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/common/crt0.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.crt0.S 1.10 05/21/01 00:49:49 cort + * BK Id: SCCS/s.crt0.S 1.12 08/09/01 17:09:10 paulus */ /* Copyright (c) 1997 Paul Mackerras * Initial Power Macintosh COFF version. @@ -34,7 +34,21 @@ .globl __start __start: #endif -#ifdef CONFIG_4xx + + ## Flush and invalidate the caches for the range in memory covering + ## the .text section of the boot loader + + lis r9,_start@h # r9 = &_start + lis r8,_etext@ha # + addi r8,r8,_etext@l # r8 = &_etext +3: dcbf r0,r9 # Flush the data cache + icbi r0,r9 # Invalidate the instruction cache + addi r9,r9,0x10 # Increment by one cache line + cmplw cr0,r9,r8 # Are we at the end yet? + blt 3b # No, keep flushing and invalidating + sync # sync ; isync after flushing the icache + isync + ## Clear out the BSS as per ANSI C requirements lis r7,_end@ha @@ -53,21 +67,7 @@ li r0,0 # r0 = 0 1: stwu r0,4(r8) # Clear out a word bdnz 1b # If we are not done yet, keep clearing -#endif - - ## Flush and invalidate the caches for the range in memory covering - ## the .text section of the boot loader - -2: lis r9,_start@h # r9 = &_start - lis r8,_etext@ha # - addi r8,r8,_etext@l # r8 = &_etext -3: dcbf r0,r9 # Flush the data cache - icbi r0,r9 # Invalidate the instruction cache - addi r9,r9,0x10 # Increment by one cache line - cmplw cr0,r9,r8 # Are we at the end yet? - blt 3b # No, keep flushing and invalidating - sync # sync ; isync after flushing the icache - isync +2: #ifdef CONFIG_4xx ## Set up the stack diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/misc-common.c linux/arch/ppc/boot/common/misc-common.c --- v2.4.9/linux/arch/ppc/boot/common/misc-common.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/common/misc-common.c Tue Aug 28 06:58:33 2001 @@ -31,9 +31,10 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include /* for va_ bits */ #include #include "zlib.h" -#include +#include "nonstdio.h" /* If we're on a ALL_PPC, assume we have a keyboard controller * Also note, if we're not ALL_PPC, we assume you are a serial @@ -71,14 +72,15 @@ void gunzip(void *, int, unsigned char *, int *); static int _cvt(unsigned long val, char *buf, long radix, char *digits); -void _vprintk(void(*)(const char), const char *, va_list); +void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap); +unsigned char *ISA_io = NULL; #if defined(CONFIG_SERIAL_CONSOLE) extern unsigned long com_port; -extern int serial_tstc(volatile unsigned long com_port); -extern unsigned char serial_getc(volatile unsigned long com_port); -extern void serial_putc(volatile unsigned long com_port, unsigned char c); +extern int serial_tstc(unsigned long com_port); +extern unsigned char serial_getc(unsigned long com_port); +extern void serial_putc(unsigned long com_port, unsigned char c); #endif void pause(void) @@ -301,7 +303,6 @@ #define FALSE 0 #define TRUE 1 -#include void _printk(char const *fmt, ...) @@ -528,6 +529,28 @@ { _printk("\n"); _dump_buf_with_offset(p, s, 0); +} + +/* Very simple inb/outb routines. We declare ISA_io to be 0 above, and + * then modify it on platforms which need to. We do it like this + * because on some platforms we give inb/outb an exact location, and + * on others it's an offset from a given location. -- Tom + */ + +void +outb(int port, unsigned char val) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + ISA_io[port] = val; +} + +unsigned char +inb(int port) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + return (ISA_io[port]); } /* diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/misc-simple.c linux/arch/ppc/boot/common/misc-simple.c --- v2.4.9/linux/arch/ppc/boot/common/misc-simple.c Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/common/misc-simple.c Tue Aug 28 06:58:33 2001 @@ -26,6 +26,7 @@ #include #include +#include "nonstdio.h" #include "zlib.h" unsigned long com_port; @@ -47,16 +48,8 @@ char *zimage_start; int zimage_size; -extern void puts(const char *); -extern void putc(const char c); -extern void puthex(unsigned long val); -extern void *memcpy(void * __dest, __const void * __src, - __kernel_size_t __n); extern void gunzip(void *, int, unsigned char *, int *); -extern void udelay(long delay); -extern int tstc(void); -extern int getc(void); -extern volatile unsigned long serial_init(int chan); +extern unsigned long serial_init(int chan); void decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/ns16550.c linux/arch/ppc/boot/common/ns16550.c --- v2.4.9/linux/arch/ppc/boot/common/ns16550.c Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/common/ns16550.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ns16550.c 1.7 05/18/01 06:20:29 patch + * BK Id: SCCS/s.ns16550.c 1.9 07/30/01 17:19:40 trini */ /* * COM1 NS16550 support @@ -10,12 +10,9 @@ #include #include -/* Some machines, such as ones with a PReP memory map, initally have - * their serial port at an offset of 0x80000000 from where they are - * in . This tries to take that into account. */ -#ifndef IOOFFSET -#define IOOFFSET 0 -#endif +extern void outb(int port, unsigned char val); +extern unsigned char inb(int port); +extern unsigned long ISA_io; static struct serial_state rs_table[RS_TABLE_SIZE] = { SERIAL_PORT_DFNS /* Defined in */ @@ -23,58 +20,67 @@ static int shift; -volatile unsigned long serial_init(int chan) { +unsigned long serial_init(int chan) { unsigned long com_port; - /* Get the base, and add any offset we need to deal with. */ - com_port = rs_table[chan].port + IOOFFSET; + /* We need to find out which type io we're expecting. If it's + * 'SERIAL_IO_PORT', we get an offset from the isa_io_base. + * If it's 'SERIAL_IO_MEM', we can the exact location. -- Tom */ + switch (rs_table[chan].io_type) { + case SERIAL_IO_PORT: + com_port = rs_table[chan].port; + break; + case SERIAL_IO_MEM: + com_port = (unsigned long)rs_table[chan].iomem_base; + break; + default: + /* We can't deal with it. */ + return -1; + } /* How far apart the registers are. */ shift = rs_table[chan].iomem_reg_shift; /* See if port is present */ - *((unsigned char *)com_port + (UART_LCR << shift)) = 0x00; - *((unsigned char *)com_port + (UART_IER << shift)) = 0x00; + outb(com_port + (UART_LCR << shift), 0x00); + outb(com_port + (UART_IER << shift), 0x00); /* Access baud rate */ - *((unsigned char *)com_port + (UART_LCR << shift)) = 0x00; + outb(com_port + (UART_LCR << shift), 0x80); #ifdef CONFIG_SERIAL_CONSOLE_NONSTD /* Input clock. */ - *((unsigned char *)com_port + (UART_DLL << shift)) = - (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD); - *((unsigned char *)com_port + (UART_DLM << shift)) = - (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8; + outb(com_port + (UART_DLL << shift), + (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD)); + outb(com_port + (UART_DLM << shift), + (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8); #endif /* 8 data, 1 stop, no parity */ - *((unsigned char *)com_port + (UART_LCR << shift)) = 0x03; + outb(com_port + (UART_LCR << shift), 0x03); /* RTS/DTR */ - *((unsigned char *)com_port + (UART_MCR << shift)) = 0x03; + outb(com_port + (UART_MCR << shift), 0x03); /* Clear & enable FIFOs */ - *((unsigned char *)com_port + (UART_FCR << shift)) = 0x07; + outb(com_port + (UART_FCR << shift), 0x07); return (com_port); } void -serial_putc(volatile unsigned long com_port, unsigned char c) +serial_putc(unsigned long com_port, unsigned char c) { - while ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) & - UART_LSR_THRE) == 0) + while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0) ; - *(volatile unsigned char *)com_port = c; + outb(com_port, c); } unsigned char -serial_getc(volatile unsigned long com_port) +serial_getc(unsigned long com_port) { - while ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) - & UART_LSR_DR) == 0) + while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0) ; - return (*(volatile unsigned char *)com_port); + return inb(com_port); } int -serial_tstc(volatile unsigned long com_port) +serial_tstc(unsigned long com_port) { - return ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) - & UART_LSR_DR) != 0); + return ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/ofcommon.c linux/arch/ppc/boot/common/ofcommon.c --- v2.4.9/linux/arch/ppc/boot/common/ofcommon.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/boot/common/ofcommon.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,171 @@ +/* + * BK Id: SCCS/s.ofcommon.c 1.1 07/27/01 20:24:18 trini + * + * Copyright (C) Paul Mackerras 1997. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "zlib.h" +#include "nonstdio.h" +#include +#include + +extern int strcmp(const char *s1, const char *s2); +extern char *avail_ram, *avail_high; +extern char *end_avail; +extern void claim(unsigned int virt, unsigned int size, unsigned int align); +extern void pause(void); + +unsigned int heap_use, heap_max; + +struct memchunk { + unsigned int size; + struct memchunk *next; +}; + +static struct memchunk *freechunks; + +static void *zalloc(void *x, unsigned items, unsigned size) +{ + void *p; + struct memchunk **mpp, *mp; + + size *= items; + size = (size + 7) & -8; + heap_use += size; + if (heap_use > heap_max) + heap_max = heap_use; + for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { + if (mp->size == size) { + *mpp = mp->next; + return mp; + } + } + p = avail_ram; + avail_ram += size; + if (avail_ram > avail_high) + avail_high = avail_ram; + if (avail_ram > end_avail) { + printf("oops... out of memory\n\r"); + pause(); + } + return p; +} + +static void zfree(void *x, void *addr, unsigned nb) +{ + struct memchunk *mp = addr; + + nb = (nb + 7) & -8; + heap_use -= nb; + if (avail_ram == addr + nb) { + avail_ram = addr; + return; + } + mp->size = nb; + mp->next = freechunks; + freechunks = mp; +} + +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 + +#define DEFLATED 8 + +void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) +{ + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + printf("bad gzipped data\n\r"); + exit(); + } + if ((flags & EXTRA_FIELD) != 0) + i = 12 + src[10] + (src[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (src[i++] != 0) + ; + if ((flags & COMMENT) != 0) + while (src[i++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + i += 2; + if (i >= *lenp) { + printf("gunzip: ran out of data in header\n\r"); + exit(); + } + + s.zalloc = zalloc; + s.zfree = zfree; + r = inflateInit2(&s, -MAX_WBITS); + if (r != Z_OK) { + printf("inflateInit2 returned %d\n\r", r); + exit(); + } + s.next_in = src + i; + s.avail_in = *lenp - i; + s.next_out = dst; + s.avail_out = dstlen; + r = inflate(&s, Z_FINISH); + if (r != Z_OK && r != Z_STREAM_END) { + printf("inflate returned %d msg: %s\n\r", r, s.msg); + exit(); + } + *lenp = s.next_out - (unsigned char *) dst; + inflateEnd(&s); +} + +/* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID, + * a machine type for BI_MACHTYPE, and the location where the end of the + * bootloader is (PROG_START + PROG_SIZE) + */ +void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned long progend) +{ + struct bi_record *rec; + + /* leave a 1MB gap then align to the next 1MB boundary */ + addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); + /* oldworld machine seem very unhappy about this. -- Tom */ + if (addr >= progend) + claim(addr, 0x1000, 0); + + rec = (struct bi_record *)addr; + rec->tag = BI_FIRST; + rec->size = sizeof(struct bi_record); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + rec->tag = BI_BOOTLOADER_ID; + sprintf( (char *)rec->data, name); + rec->size = sizeof(struct bi_record) + strlen(name) + 1; + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + rec->tag = BI_MACHTYPE; + rec->data[0] = mach; + rec->data[1] = 1; + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + +#ifdef SYSMAP_OFFSET + rec->tag = BI_SYSMAP; + rec->data[0] = SYSMAP_OFFSET; + rec->data[1] = SYSMAP_SIZE; + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); + rec = (struct bi_record *)((unsigned long)rec + rec->size); +#endif /* SYSMAP_OFFSET */ + + rec->tag = BI_LAST; + rec->size = sizeof(struct bi_record); + rec = (struct bi_record *)((unsigned long)rec + rec->size); +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/include/nonstdio.h linux/arch/ppc/boot/include/nonstdio.h --- v2.4.9/linux/arch/ppc/boot/include/nonstdio.h Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/include/nonstdio.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.nonstdio.h 1.7 05/18/01 15:17:23 cort + * BK Id: SCCS/s.nonstdio.h 1.9 07/25/01 18:13:07 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -8,14 +8,31 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. + * + * This is sort of a catchall for I/O related functions. Stuff that + * wouldn't be in 'stdio.h' normally is here, and it's 'nonstdio.h' + * for a reason. -- Tom */ -typedef int FILE; +typedef int FILE; extern FILE *stdin, *stdout; -#define NULL ((void *)0) -#define EOF (-1) -#define fopen(n, m) NULL -#define fflush(f) 0 -#define fclose(f) 0 -extern char *fgets(); +#define NULL ((void *)0) +#define EOF (-1) +#define fopen(n, m) NULL +#define fflush(f) 0 +#define fclose(f) 0 +#define perror(s) printf("%s: no files!\n", (s)) -#define perror(s) printf("%s: no files!\n", (s)) +extern int getc(void); +extern int printf(const char *format, ...); +extern int strlen(const char *s); +extern int sprintf(char *str, const char *format, ...); +extern int tstc(void); +extern void exit(void); +extern void *memcpy(void *dest, const void *src, int n); +extern void *memmove(void *dest, const void *src, int n); +extern void outb(int port, unsigned char val); +extern void putc(const char c); +extern void puthex(unsigned long val); +extern void puts(const char *); +extern void udelay(long delay); +extern unsigned char inb(int port); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/mbx/misc.c linux/arch/ppc/boot/mbx/misc.c --- v2.4.9/linux/arch/ppc/boot/mbx/misc.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/mbx/misc.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.misc.c 1.11 07/18/01 15:46:50 trini + * BK Id: SCCS/s.misc.c 1.13 07/27/01 11:44:37 trini */ /* * Adapted for PowerPC by Gary Thomas @@ -23,6 +23,8 @@ #include #endif +#include "nonstdio.h" + /* * The following references are needed to cause the linker to pull in the * gzimage.o and rdimage.o files. These object files are special, @@ -75,14 +77,7 @@ char *zimage_start; int zimage_size; -extern void puts(const char *); -extern void putc(const char c); -extern void udelay(long x); -extern void puthex(unsigned long val); -extern void * memcpy(void * __dest, __const void * __src, __kernel_size_t __n); extern void gunzip(void *, int, unsigned char *, int *); -extern int tstc(void); -extern int getc(void); unsigned long decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp) @@ -267,33 +262,4 @@ puts("done.\n"); puts("Now booting the kernel\n"); return (unsigned long)hold_residual; -} - -/* - * PCI/ISA I/O support - */ - -volatile unsigned char *ISA_io = (unsigned char *)0x80000000; -volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000; - -void -outb(int port, char val) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - ISA_io[port] = val; -} - -unsigned char -inb(int port) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - return (ISA_io[port]); -} - -unsigned long -local_to_PCI(unsigned long addr) -{ - return ((addr & 0x7FFFFFFF) | 0x80000000); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/pmac/Makefile linux/arch/ppc/boot/pmac/Makefile --- v2.4.9/linux/arch/ppc/boot/pmac/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/pmac/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.12 07/19/01 09:11:28 trini +# BK Id: SCCS/s.Makefile 1.14 07/27/01 20:24:17 trini # # Makefile for making XCOFF bootable images for booting on PowerMacs # using Open Firmware. @@ -12,12 +12,10 @@ COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic CHRP_LD_ARGS = -Ttext 0x01000000 -COMMONOBJS = start.o misc.o ../common/string.o image.o +COMMONOBJS = start.o misc.o ../common/string.o image.o ../common/ofcommon.o COFFOBJS = ../common/coffcrt0.o $(COMMONOBJS) coffmain.o CHRPOBJS = ../common/crt0.o $(COMMONOBJS) chrpmain.o LIBS = $(TOPDIR)/lib/lib.a ../lib/zlib.a - -CFLAGS += -fno-builtin MKNOTE := ../utils/mknote SIZE := ../utils/size diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/pmac/chrpmain.c linux/arch/ppc/boot/pmac/chrpmain.c --- v2.4.9/linux/arch/ppc/boot/pmac/chrpmain.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/boot/pmac/chrpmain.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrpmain.c 1.12 06/12/01 16:42:26 paulus + * BK Id: SCCS/s.chrpmain.c 1.16 07/27/01 20:24:18 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -11,21 +11,26 @@ */ #include "nonstdio.h" #include "zlib.h" -#include #include -#include -extern void *finddevice(const char *); +extern char _end[]; +extern char image_data[], initrd_data[]; +extern int image_len, initrd_len; extern int getprop(void *, const char *, void *, int); +extern unsigned int heap_max; extern void *claim(unsigned int, unsigned int, unsigned int); +extern void *finddevice(const char *); +extern void flush_cache(void *start, unsigned int len); +extern void gunzip(void *, int, unsigned char *, int *); +extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned int progend); +extern void pause(void); extern void release(void *ptr, unsigned int len); -void make_bi_recs(unsigned long); -void gunzip(void *, int, unsigned char *, int *); -void stop_imac_ethernet(void); -void stop_imac_usb(void); -#define get_16be(x) (*(unsigned short *)(x)) -#define get_32be(x) (*(unsigned *)(x)) +char *avail_ram; +char *begin_avail, *end_avail; +char *avail_high; + #define RAM_END (16 << 20) @@ -34,36 +39,22 @@ #define SCRATCH_SIZE (128 << 10) -char *avail_ram; -char *begin_avail, *end_avail; -char *avail_high; -unsigned int heap_use; -unsigned int heap_max; - -extern char _end[]; -extern char image_data[]; -extern int image_len; -extern char initrd_data[]; -extern int initrd_len; - - -boot(int a1, int a2, void *prom) +void boot(int a1, int a2, void *prom) { - int ns, oh, i; unsigned sa, len; void *dst; unsigned char *im; unsigned initrd_start, initrd_size; extern char _start; - printf("chrpboot starting: loaded at 0x%x\n", &_start); + printf("chrpboot starting: loaded at 0x%p\n", &_start); if (initrd_len) { initrd_size = initrd_len; initrd_start = (RAM_END - initrd_size) & ~0xFFF; a1 = initrd_start; a2 = initrd_size; claim(initrd_start, RAM_END - initrd_start, 0); - printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n", initrd_start, + printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n", initrd_start, initrd_data,initrd_size); memcpy((char *)initrd_start, initrd_data, initrd_size); } @@ -77,8 +68,8 @@ avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10); begin_avail = avail_high = avail_ram; end_avail = avail_ram + SCRATCH_SIZE; - printf("heap at 0x%x\n", avail_ram); - printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); + printf("heap at 0x%p\n", avail_ram); + printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); gunzip(dst, PROG_SIZE, im, &len); printf("done %u bytes\n", len); printf("%u bytes of heap consumed, max in use %u\n", @@ -89,7 +80,8 @@ } flush_cache(dst, len); - make_bi_recs((unsigned long) dst + len); + make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac, + (PROG_START + PROG_SIZE)); sa = (unsigned long)PROG_START; printf("start address = 0x%x\n", sa); @@ -99,199 +91,4 @@ printf("returned?\n"); pause(); -} - -void make_bi_recs(unsigned long addr) -{ - struct bi_record *rec; - - /* leave a 1MB gap then align to the next 1MB boundary */ - addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); - if (addr >= PROG_START + PROG_SIZE) - claim(addr, 0x1000, 0); - - rec = (struct bi_record *)addr; - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_BOOTLOADER_ID; - sprintf( (char *)rec->data, "coffboot"); - rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_MACHTYPE; - rec->data[0] = _MACH_Pmac; - rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - -#ifdef SYSMAP_OFFSET - rec->tag = BI_SYSMAP; - rec->data[0] = SYSMAP_OFFSET; - rec->data[1] = SYSMAP_SIZE; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -#endif /* SYSMAP_OFFSET */ - - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -} - -#if 0 -#define eieio() asm volatile("eieio"); - -void stop_imac_ethernet(void) -{ - void *macio, *enet; - unsigned int macio_addr[5], enet_reg[6]; - int len; - volatile unsigned int *dbdma; - - macio = finddevice("/pci/mac-io"); - enet = finddevice("/pci/mac-io/ethernet"); - if (macio == NULL || enet == NULL) - return; - len = getprop(macio, "assigned-addresses", macio_addr, sizeof(macio_addr)); - if (len != sizeof(macio_addr)) - return; - len = getprop(enet, "reg", enet_reg, sizeof(enet_reg)); - if (len != sizeof(enet_reg)) - return; - printf("macio base %x, dma at %x & %x\n", - macio_addr[2], enet_reg[2], enet_reg[4]); - - /* hope this is mapped... */ - dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[2]); - *dbdma = 0x80; /* clear the RUN bit */ - eieio(); - dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[4]); - *dbdma = 0x80; /* clear the RUN bit */ - eieio(); -} - -void stop_imac_usb(void) -{ - void *usb; - unsigned int usb_addr[5]; - int len; - volatile unsigned int *usb_ctrl; - - usb = finddevice("/pci/usb"); - if (usb == NULL) - return; - len = getprop(usb, "assigned-addresses", usb_addr, sizeof(usb_addr)); - if (len != sizeof(usb_addr)) - return; - printf("usb base %x\n", usb_addr[2]); - - usb_ctrl = (volatile unsigned int *) (usb_addr[2] + 8); - *usb_ctrl = 0x01000000; /* cpu_to_le32(1) */ - eieio(); -} -#endif - -struct memchunk { - unsigned int size; - struct memchunk *next; -}; - -static struct memchunk *freechunks; - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p; - struct memchunk **mpp, *mp; - - size *= items; - size = (size + 7) & -8; - heap_use += size; - if (heap_use > heap_max) - heap_max = heap_use; - for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { - if (mp->size == size) { - *mpp = mp->next; - return mp; - } - } - p = avail_ram; - avail_ram += size; - if (avail_ram > avail_high) - avail_high = avail_ram; - if (avail_ram > end_avail) { - printf("oops... out of memory\n"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ - struct memchunk *mp = addr; - - nb = (nb + 7) & -8; - heap_use -= nb; - if (avail_ram == addr + nb) { - avail_ram = addr; - return; - } - mp->size = nb; - mp->next = freechunks; - freechunks = mp; -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n"); - exit(); - } - - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d msg: %s\n", r, s.msg); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/pmac/coffmain.c linux/arch/ppc/boot/pmac/coffmain.c --- v2.4.9/linux/arch/ppc/boot/pmac/coffmain.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/boot/pmac/coffmain.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.coffmain.c 1.12 06/12/01 16:42:26 paulus + * BK Id: SCCS/s.coffmain.c 1.14 07/27/01 20:24:18 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -11,18 +11,25 @@ */ #include "nonstdio.h" #include "zlib.h" -#include #include -#include -extern void *finddevice(const char *); -extern int getprop(void *, const char *, void *, int); +extern char _start[], _end[]; extern char *claim(unsigned, unsigned, unsigned); -void make_bi_recs(unsigned long); -void gunzip(void *, int, unsigned char *, int *); +extern char image_data[], initrd_data[]; +extern int initrd_len, image_len; +extern int getprop(void *, const char *, void *, int); +extern unsigned int heap_max; +extern void *finddevice(const char *); +extern void flush_cache(void *start, unsigned int len); +extern void gunzip(void *, int, unsigned char *, int *); +extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned int progend); +extern void pause(void); +extern void setup_bats(unsigned long start); -#define get_16be(x) (*(unsigned short *)(x)) -#define get_32be(x) (*(unsigned *)(x)) +char *avail_ram; +char *begin_avail, *end_avail; +char *avail_high; #define RAM_START 0 #define RAM_END (RAM_START + 0x800000) /* only 8M mapped with BATs */ @@ -32,29 +39,16 @@ #define SCRATCH_SIZE (128 << 10) -char *avail_ram; -char *begin_avail, *end_avail; -char *avail_high; -unsigned int heap_use; -unsigned int heap_max; - -extern char _start[], _end[]; -extern char image_data[]; -extern int image_len; -extern char initrd_data[]; -extern int initrd_len; +static char heap[SCRATCH_SIZE]; -char heap[SCRATCH_SIZE]; - -boot(int a1, int a2, void *prom) +void boot(int a1, int a2, void *prom) { - int ns, oh, i; unsigned sa, len; void *dst; unsigned char *im; unsigned initrd_start, initrd_size; - printf("coffboot starting: loaded at 0x%x\n", _start); + printf("coffboot starting: loaded at 0x%p\n", &_start); setup_bats(RAM_START); if (initrd_len) { initrd_size = initrd_len; @@ -62,21 +56,21 @@ a1 = initrd_start; a2 = initrd_size; claim(initrd_start - RAM_START, RAM_END - initrd_start, 0); - printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n", + printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n", initrd_start, initrd_data, initrd_size); memcpy((char *)initrd_start, initrd_data, initrd_size); } im = image_data; len = image_len; - /* claim 3MB starting at 0 */ + /* claim 4MB starting at 0 */ claim(0, PROG_SIZE, 0); dst = (void *) RAM_START; if (im[0] == 0x1f && im[1] == 0x8b) { /* set up scratch space */ begin_avail = avail_high = avail_ram = heap; end_avail = heap + sizeof(heap); - printf("heap at 0x%x\n", avail_ram); - printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); + printf("heap at 0x%p\n", avail_ram); + printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); gunzip(dst, PROG_SIZE, im, &len); printf("done %u bytes\n", len); printf("%u bytes of heap consumed, max in use %u\n", @@ -86,8 +80,9 @@ } flush_cache(dst, len); - make_bi_recs((unsigned long)dst + len); - + make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac, + (PROG_START + PROG_SIZE)); + sa = (unsigned long)PROG_START; printf("start address = 0x%x\n", sa); @@ -96,139 +91,4 @@ printf("returned?\n"); pause(); -} - -void make_bi_recs(unsigned long addr) -{ - struct bi_record *rec; - - addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); -#if 0 - if (addr >= PROG_START + PROG_SIZE) - claim(addr, 0x1000, 0); -#endif - - rec = (struct bi_record *)addr; - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_BOOTLOADER_ID; - sprintf( (char *)rec->data, "coffboot"); - rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_MACHTYPE; - rec->data[0] = _MACH_Pmac; - rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -} - -struct memchunk { - unsigned int size; - struct memchunk *next; -}; - -static struct memchunk *freechunks; - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p; - struct memchunk **mpp, *mp; - - size *= items; - size = (size + 7) & -8; - heap_use += size; - if (heap_use > heap_max) - heap_max = heap_use; - for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { - if (mp->size == size) { - *mpp = mp->next; - return mp; - } - } - p = avail_ram; - avail_ram += size; - if (avail_ram > avail_high) - avail_high = avail_ram; - if (avail_ram > end_avail) { - printf("oops... out of memory\n"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ - struct memchunk *mp = addr; - - nb = (nb + 7) & -8; - heap_use -= nb; - if (avail_ram == addr + nb) { - avail_ram = addr; - return; - } - mp->size = nb; - mp->next = freechunks; - freechunks = mp; -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n"); - exit(); - } - - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d msg: %s\n", r, s.msg); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/pmac/start.c linux/arch/ppc/boot/pmac/start.c --- v2.4.9/linux/arch/ppc/boot/pmac/start.c Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/pmac/start.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.start.c 1.8 05/18/01 15:17:15 cort + * BK Id: SCCS/s.start.c 1.10 07/25/01 18:13:07 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -11,6 +11,9 @@ */ #include +extern int strlen(const char *s); +extern void boot(int a1, int a2, void *prom); + int (*prom)(); void *chosen_handle; @@ -109,7 +112,7 @@ } void -exit() +exit(void) { struct prom_args { char *service; @@ -122,7 +125,7 @@ } void -pause() +pause(void) { struct prom_args { char *service; @@ -243,7 +246,7 @@ } int -readchar() +readchar(void) { char ch; @@ -263,7 +266,7 @@ static int lineleft; int -getchar() +getchar(void) { int c; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/prep/Makefile linux/arch/ppc/boot/prep/Makefile --- v2.4.9/linux/arch/ppc/boot/prep/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/prep/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.19 07/19/01 09:11:28 trini +# BK Id: SCCS/s.Makefile 1.24 08/01/01 13:25:40 trini # # arch/ppc/boot/Makefile # @@ -17,8 +17,6 @@ USE_STANDARD_AS_RULE := true -CFLAGS += -fno-builtin - ifeq ($(CONFIG_SMP),y) TFTPIMAGE = /tftpboot/zImage.prep.smp else @@ -32,7 +30,7 @@ OBJCOPY_ARGS = -O elf32-powerpc LIBS = ../lib/zlib.a -obj-$(CONFIG_SERIAL_CONSOLE) += ns16550.o +obj-$(CONFIG_SERIAL_CONSOLE) += ../common/ns16550.o obj-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o # Tools @@ -45,9 +43,6 @@ misc.o: misc.c $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ -DZIMAGE_SIZE=0 -c -o $@ $*.c - -ns16550.o: ../common/ns16550.c - $(CC) $(CFLAGS) -DIOOFFSET=0x80000000 -c -o $@ ../common/$*.c zvmlinux.initrd: zvmlinux ../images/vmlinux.gz $(LD) $(ZLINKFLAGS) -o $@.tmp $(obj-y) $(LIBS) diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/prep/head.S linux/arch/ppc/boot/prep/head.S --- v2.4.9/linux/arch/ppc/boot/prep/head.S Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/prep/head.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head.S 1.8 05/18/01 06:20:29 patch + * BK Id: SCCS/s.head.S 1.11 07/31/01 16:36:06 trini */ #include "../../kernel/ppc_defs.h" #include "../../kernel/ppc_asm.tmpl" @@ -95,6 +95,11 @@ subi r1,r1,256 li r2,0x000F /* Mask pointer to 16-byte boundary */ andc r1,r1,r2 +/* Setup ISA_io */ + lis r3,ISA_io@h + ori r3,r3,ISA_io@l + lis r4,0x8000 + stw r4,0(r3) /* Run loader */ mr r3,r8 /* Load point */ mr r4,r7 /* Program length */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/prep/misc.c linux/arch/ppc/boot/prep/misc.c --- v2.4.9/linux/arch/ppc/boot/prep/misc.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/boot/prep/misc.c Tue Aug 28 06:58:33 2001 @@ -1,8 +1,7 @@ /* - * BK Id: SCCS/s.misc.c 1.14 06/16/01 20:43:20 trini - */ -/* - * misc.c + * BK Id: SCCS/s.misc.c 1.18 07/30/01 17:19:40 trini + * + * arch/ppc/boot/prep/misc.c * * Adapted for PowerPC by Gary Thomas * @@ -11,7 +10,6 @@ */ #include -#include "zlib.h" #include #include #include @@ -22,9 +20,8 @@ #include #include #include -#if defined(CONFIG_SERIAL_CONSOLE) -unsigned long com_port; -#endif /* CONFIG_SERIAL_CONSOLE */ +#include "nonstdio.h" +#include "zlib.h" /* * Please send me load/board info and such data for hardware not @@ -53,26 +50,28 @@ char *zimage_start; int zimage_size; +#if defined(CONFIG_SERIAL_CONSOLE) +unsigned long com_port; +#endif /* CONFIG_SERIAL_CONSOLE */ +#ifdef CONFIG_VGA_CONSOLE char *vidmem = (char *)0xC00B8000; -int lines, cols; -int orig_x, orig_y; +int lines = 25, cols = 80; +int orig_x, orig_y = 24; +#endif /* CONFIG_VGA_CONSOLE */ -extern void puts(const char *); -extern void putc(const char c); -extern int tstc(void); -extern int getc(void); -extern void puthex(unsigned long val); -extern void * memcpy(void * __dest, __const void * __src, __kernel_size_t __n); extern int CRT_tstc(void); extern void of_init(void *handler); extern int of_finddevice(const char *device_specifier, int *phandle); extern int of_getprop(int phandle, const char *name, void *buf, int buflen, int *size); -extern __kernel_size_t strlen(const char *s); extern int vga_init(unsigned char *ISA_mem); -extern void udelay(long x); -void gunzip(void *, int, unsigned char *, int *); -unsigned char inb(int); +extern void gunzip(void *, int, unsigned char *, int *); + +extern void _put_HID0(unsigned int val); +extern void _put_MSR(unsigned int val); +extern unsigned int _get_HID0(void); +extern unsigned int _get_MSR(void); +extern unsigned long serial_init(int chan); void writel(unsigned int val, unsigned int address) @@ -105,7 +104,7 @@ #ifdef CONFIG_VGA_CONSOLE void -scroll() +scroll(void) { int i; @@ -120,7 +119,7 @@ * Motorola dual processor platforms. */ void -park_cpus() +park_cpus(void) { volatile void (*go)(RESIDUAL *, int, int, char *, int); unsigned int i; @@ -154,11 +153,6 @@ unsigned char base_mod; int start_multi = 0; unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base; - - lines = 25; - cols = 80; - orig_x = 0; - orig_y = 24; /* * IBM's have the MMU on, so we have to disable it or @@ -438,28 +432,8 @@ /* * PCI/ISA I/O support */ - -volatile unsigned char *ISA_io = (unsigned char *)0x80000000; -volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000; - -void -outb(int port, char val) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - ISA_io[port] = val; -} - -unsigned char -inb(int port) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - return (ISA_io[port]); -} - unsigned long local_to_PCI(unsigned long addr) { - return ((addr & 0x7FFFFFFF) | 0x80000000); + return (addr | 0x80000000); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/prep/vreset.c linux/arch/ppc/boot/prep/vreset.c --- v2.4.9/linux/arch/ppc/boot/prep/vreset.c Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/prep/vreset.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.vreset.c 1.9 05/18/01 06:20:29 patch + * BK Id: SCCS/s.vreset.c 1.11 07/25/01 18:13:07 trini */ /* * vreset.c @@ -22,12 +22,10 @@ */ #include "iso_font.h" +#include "nonstdio.h" extern char *vidmem; extern int lines, cols; -extern void udelay(long x); -extern void outb(int port, char val); -extern unsigned char inb(int port); struct VaRegs; /* @@ -43,7 +41,7 @@ void unlockVideo(int slot); void setTextRegs(struct VgaRegs *svp); void setTextCLUT(int shift); -void clearVideoMemory(); +void clearVideoMemory(void); void loadFont(unsigned char *ISA_mem); static void mdelay(int ms) @@ -59,100 +57,100 @@ #define NREGS 54 #define ENDMK 0xFFFF /* End marker */ -#define S3Vendor 0x5333 +#define S3Vendor 0x5333 #define CirrusVendor 0x1013 #define DiamondVendor 0x100E #define MatroxVendor 0x102B #define ParadiseVendor 0x101C struct VgaRegs GenVgaTextRegs[NREGS+1] = { -/* port index value */ - /* SR Regs */ - 0x3c4, 0x1, 0x0, - 0x3c4, 0x2, 0x3, - 0x3c4, 0x3, 0x0, - 0x3c4, 0x4, 0x2, - /* CR Regs */ - 0x3d4, 0x0, 0x5f, - 0x3d4, 0x1, 0x4f, - 0x3d4, 0x2, 0x50, - 0x3d4, 0x3, 0x82, - 0x3d4, 0x4, 0x55, - 0x3d4, 0x5, 0x81, - 0x3d4, 0x6, 0xbf, - 0x3d4, 0x7, 0x1f, - 0x3d4, 0x8, 0x00, - 0x3d4, 0x9, 0x4f, - 0x3d4, 0xa, 0x0d, - 0x3d4, 0xb, 0x0e, - 0x3d4, 0xc, 0x00, - 0x3d4, 0xd, 0x00, - 0x3d4, 0xe, 0x00, - 0x3d4, 0xf, 0x00, - 0x3d4, 0x10, 0x9c, - 0x3d4, 0x11, 0x8e, - 0x3d4, 0x12, 0x8f, - 0x3d4, 0x13, 0x28, - 0x3d4, 0x14, 0x1f, - 0x3d4, 0x15, 0x96, - 0x3d4, 0x16, 0xb9, - 0x3d4, 0x17, 0xa3, - /* GR Regs */ - 0x3ce, 0x0, 0x0, - 0x3ce, 0x1, 0x0, - 0x3ce, 0x2, 0x0, - 0x3ce, 0x3, 0x0, - 0x3ce, 0x4, 0x0, - 0x3ce, 0x5, 0x10, - 0x3ce, 0x6, 0xe, - 0x3ce, 0x7, 0x0, - 0x3ce, 0x8, 0xff, - ENDMK + /* port index value */ + /* SR Regs */ + { 0x3c4, 0x1, 0x0 }, + { 0x3c4, 0x2, 0x3 }, + { 0x3c4, 0x3, 0x0 }, + { 0x3c4, 0x4, 0x2 }, + /* CR Regs */ + { 0x3d4, 0x0, 0x5f }, + { 0x3d4, 0x1, 0x4f }, + { 0x3d4, 0x2, 0x50 }, + { 0x3d4, 0x3, 0x82 }, + { 0x3d4, 0x4, 0x55 }, + { 0x3d4, 0x5, 0x81 }, + { 0x3d4, 0x6, 0xbf }, + { 0x3d4, 0x7, 0x1f }, + { 0x3d4, 0x8, 0x00 }, + { 0x3d4, 0x9, 0x4f }, + { 0x3d4, 0xa, 0x0d }, + { 0x3d4, 0xb, 0x0e }, + { 0x3d4, 0xc, 0x00 }, + { 0x3d4, 0xd, 0x00 }, + { 0x3d4, 0xe, 0x00 }, + { 0x3d4, 0xf, 0x00 }, + { 0x3d4, 0x10, 0x9c }, + { 0x3d4, 0x11, 0x8e }, + { 0x3d4, 0x12, 0x8f }, + { 0x3d4, 0x13, 0x28 }, + { 0x3d4, 0x14, 0x1f }, + { 0x3d4, 0x15, 0x96 }, + { 0x3d4, 0x16, 0xb9 }, + { 0x3d4, 0x17, 0xa3 }, + /* GR Regs */ + { 0x3ce, 0x0, 0x0 }, + { 0x3ce, 0x1, 0x0 }, + { 0x3ce, 0x2, 0x0 }, + { 0x3ce, 0x3, 0x0 }, + { 0x3ce, 0x4, 0x0 }, + { 0x3ce, 0x5, 0x10 }, + { 0x3ce, 0x6, 0xe }, + { 0x3ce, 0x7, 0x0 }, + { 0x3ce, 0x8, 0xff }, + { ENDMK } }; struct VgaRegs S3TextRegs[NREGS+1] = { -/* port index value */ - /* SR Regs */ - 0x3c4, 0x1, 0x0, - 0x3c4, 0x2, 0x3, - 0x3c4, 0x3, 0x0, - 0x3c4, 0x4, 0x2, - /* CR Regs */ - 0x3d4, 0x0, 0x5f, - 0x3d4, 0x1, 0x4f, - 0x3d4, 0x2, 0x50, - 0x3d4, 0x3, 0x82, - 0x3d4, 0x4, 0x55, - 0x3d4, 0x5, 0x81, - 0x3d4, 0x6, 0xbf, - 0x3d4, 0x7, 0x1f, - 0x3d4, 0x8, 0x00, - 0x3d4, 0x9, 0x4f, - 0x3d4, 0xa, 0x0d, - 0x3d4, 0xb, 0x0e, - 0x3d4, 0xc, 0x00, - 0x3d4, 0xd, 0x00, - 0x3d4, 0xe, 0x00, - 0x3d4, 0xf, 0x00, - 0x3d4, 0x10, 0x9c, - 0x3d4, 0x11, 0x8e, - 0x3d4, 0x12, 0x8f, - 0x3d4, 0x13, 0x28, - 0x3d4, 0x14, 0x1f, - 0x3d4, 0x15, 0x96, - 0x3d4, 0x16, 0xb9, - 0x3d4, 0x17, 0xa3, - /* GR Regs */ - 0x3ce, 0x0, 0x0, - 0x3ce, 0x1, 0x0, - 0x3ce, 0x2, 0x0, - 0x3ce, 0x3, 0x0, - 0x3ce, 0x4, 0x0, - 0x3ce, 0x5, 0x10, - 0x3ce, 0x6, 0xe, - 0x3ce, 0x7, 0x0, - 0x3ce, 0x8, 0xff, - ENDMK + /* port index value */ + /* SR Regs */ + { 0x3c4, 0x1, 0x0 }, + { 0x3c4, 0x2, 0x3 }, + { 0x3c4, 0x3, 0x0 }, + { 0x3c4, 0x4, 0x2 }, + /* CR Regs */ + { 0x3d4, 0x0, 0x5f }, + { 0x3d4, 0x1, 0x4f }, + { 0x3d4, 0x2, 0x50 }, + { 0x3d4, 0x3, 0x82 }, + { 0x3d4, 0x4, 0x55 }, + { 0x3d4, 0x5, 0x81 }, + { 0x3d4, 0x6, 0xbf }, + { 0x3d4, 0x7, 0x1f }, + { 0x3d4, 0x8, 0x00 }, + { 0x3d4, 0x9, 0x4f }, + { 0x3d4, 0xa, 0x0d }, + { 0x3d4, 0xb, 0x0e }, + { 0x3d4, 0xc, 0x00 }, + { 0x3d4, 0xd, 0x00 }, + { 0x3d4, 0xe, 0x00 }, + { 0x3d4, 0xf, 0x00 }, + { 0x3d4, 0x10, 0x9c }, + { 0x3d4, 0x11, 0x8e }, + { 0x3d4, 0x12, 0x8f }, + { 0x3d4, 0x13, 0x28 }, + { 0x3d4, 0x14, 0x1f }, + { 0x3d4, 0x15, 0x96 }, + { 0x3d4, 0x16, 0xb9 }, + { 0x3d4, 0x17, 0xa3 }, + /* GR Regs */ + { 0x3ce, 0x0, 0x0 }, + { 0x3ce, 0x1, 0x0 }, + { 0x3ce, 0x2, 0x0 }, + { 0x3ce, 0x3, 0x0 }, + { 0x3ce, 0x4, 0x0 }, + { 0x3ce, 0x5, 0x10 }, + { 0x3ce, 0x6, 0xe }, + { 0x3ce, 0x7, 0x0 }, + { 0x3ce, 0x8, 0xff }, + { ENDMK } }; struct RGBColors @@ -167,262 +165,262 @@ */ struct RGBColors TextCLUT[256] = { - /* red green blue */ - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2a, - 0x0, 0x2a, 0x0, - 0x0, 0x2a, 0x2a, - 0x2a, 0x0, 0x0, - 0x2a, 0x0, 0x2a, - 0x2a, 0x2a, 0x0, - 0x2a, 0x2a, 0x2a, - 0x0, 0x0, 0x15, - 0x0, 0x0, 0x3f, - 0x0, 0x2a, 0x15, - 0x0, 0x2a, 0x3f, - 0x2a, 0x0, 0x15, - 0x2a, 0x0, 0x3f, - 0x2a, 0x2a, 0x15, - 0x2a, 0x2a, 0x3f, - 0x0, 0x15, 0x0, - 0x0, 0x15, 0x2a, - 0x0, 0x3f, 0x0, - 0x0, 0x3f, 0x2a, - 0x2a, 0x15, 0x0, - 0x2a, 0x15, 0x2a, - 0x2a, 0x3f, 0x0, - 0x2a, 0x3f, 0x2a, - 0x0, 0x15, 0x15, - 0x0, 0x15, 0x3f, - 0x0, 0x3f, 0x15, - 0x0, 0x3f, 0x3f, - 0x2a, 0x15, 0x15, - 0x2a, 0x15, 0x3f, - 0x2a, 0x3f, 0x15, - 0x2a, 0x3f, 0x3f, - 0x15, 0x0, 0x0, - 0x15, 0x0, 0x2a, - 0x15, 0x2a, 0x0, - 0x15, 0x2a, 0x2a, - 0x3f, 0x0, 0x0, - 0x3f, 0x0, 0x2a, - 0x3f, 0x2a, 0x0, - 0x3f, 0x2a, 0x2a, - 0x15, 0x0, 0x15, - 0x15, 0x0, 0x3f, - 0x15, 0x2a, 0x15, - 0x15, 0x2a, 0x3f, - 0x3f, 0x0, 0x15, - 0x3f, 0x0, 0x3f, - 0x3f, 0x2a, 0x15, - 0x3f, 0x2a, 0x3f, - 0x15, 0x15, 0x0, - 0x15, 0x15, 0x2a, - 0x15, 0x3f, 0x0, - 0x15, 0x3f, 0x2a, - 0x3f, 0x15, 0x0, - 0x3f, 0x15, 0x2a, - 0x3f, 0x3f, 0x0, - 0x3f, 0x3f, 0x2a, - 0x15, 0x15, 0x15, - 0x15, 0x15, 0x3f, - 0x15, 0x3f, 0x15, - 0x15, 0x3f, 0x3f, - 0x3f, 0x15, 0x15, - 0x3f, 0x15, 0x3f, - 0x3f, 0x3f, 0x15, - 0x3f, 0x3f, 0x3f, - 0x39, 0xc, 0x5, - 0x15, 0x2c, 0xf, - 0x26, 0x10, 0x3d, - 0x29, 0x29, 0x38, - 0x4, 0x1a, 0xe, - 0x2, 0x1e, 0x3a, - 0x3c, 0x25, 0x33, - 0x3c, 0xc, 0x2c, - 0x3f, 0x3, 0x2b, - 0x1c, 0x9, 0x13, - 0x25, 0x2a, 0x35, - 0x1e, 0xa, 0x38, - 0x24, 0x8, 0x3, - 0x3, 0xe, 0x36, - 0xc, 0x6, 0x2a, - 0x26, 0x3, 0x32, - 0x5, 0x2f, 0x33, - 0x3c, 0x35, 0x2f, - 0x2d, 0x26, 0x3e, - 0xd, 0xa, 0x10, - 0x25, 0x3c, 0x11, - 0xd, 0x4, 0x2e, - 0x5, 0x19, 0x3e, - 0xc, 0x13, 0x34, - 0x2b, 0x6, 0x24, - 0x4, 0x3, 0xd, - 0x2f, 0x3c, 0xc, - 0x2a, 0x37, 0x1f, - 0xf, 0x12, 0x38, - 0x38, 0xe, 0x2a, - 0x12, 0x2f, 0x19, - 0x29, 0x2e, 0x31, - 0x25, 0x13, 0x3e, - 0x33, 0x3e, 0x33, - 0x1d, 0x2c, 0x25, - 0x15, 0x15, 0x5, - 0x32, 0x25, 0x39, - 0x1a, 0x7, 0x1f, - 0x13, 0xe, 0x1d, - 0x36, 0x17, 0x34, - 0xf, 0x15, 0x23, - 0x2, 0x35, 0xd, - 0x15, 0x3f, 0xc, - 0x14, 0x2f, 0xf, - 0x19, 0x21, 0x3e, - 0x27, 0x11, 0x2f, - 0x38, 0x3f, 0x3c, - 0x36, 0x2d, 0x15, - 0x16, 0x17, 0x2, - 0x1, 0xa, 0x3d, - 0x1b, 0x11, 0x3f, - 0x21, 0x3c, 0xd, - 0x1a, 0x39, 0x3d, - 0x8, 0xe, 0xe, - 0x22, 0x21, 0x23, - 0x1e, 0x30, 0x5, - 0x1f, 0x22, 0x3d, - 0x1e, 0x2f, 0xa, - 0x0, 0x1c, 0xe, - 0x0, 0x1c, 0x15, - 0x0, 0x1c, 0x1c, - 0x0, 0x15, 0x1c, - 0x0, 0xe, 0x1c, - 0x0, 0x7, 0x1c, - 0xe, 0xe, 0x1c, - 0x11, 0xe, 0x1c, - 0x15, 0xe, 0x1c, - 0x18, 0xe, 0x1c, - 0x1c, 0xe, 0x1c, - 0x1c, 0xe, 0x18, - 0x1c, 0xe, 0x15, - 0x1c, 0xe, 0x11, - 0x1c, 0xe, 0xe, - 0x1c, 0x11, 0xe, - 0x1c, 0x15, 0xe, - 0x1c, 0x18, 0xe, - 0x1c, 0x1c, 0xe, - 0x18, 0x1c, 0xe, - 0x15, 0x1c, 0xe, - 0x11, 0x1c, 0xe, - 0xe, 0x1c, 0xe, - 0xe, 0x1c, 0x11, - 0xe, 0x1c, 0x15, - 0xe, 0x1c, 0x18, - 0xe, 0x1c, 0x1c, - 0xe, 0x18, 0x1c, - 0xe, 0x15, 0x1c, - 0xe, 0x11, 0x1c, - 0x14, 0x14, 0x1c, - 0x16, 0x14, 0x1c, - 0x18, 0x14, 0x1c, - 0x1a, 0x14, 0x1c, - 0x1c, 0x14, 0x1c, - 0x1c, 0x14, 0x1a, - 0x1c, 0x14, 0x18, - 0x1c, 0x14, 0x16, - 0x1c, 0x14, 0x14, - 0x1c, 0x16, 0x14, - 0x1c, 0x18, 0x14, - 0x1c, 0x1a, 0x14, - 0x1c, 0x1c, 0x14, - 0x1a, 0x1c, 0x14, - 0x18, 0x1c, 0x14, - 0x16, 0x1c, 0x14, - 0x14, 0x1c, 0x14, - 0x14, 0x1c, 0x16, - 0x14, 0x1c, 0x18, - 0x14, 0x1c, 0x1a, - 0x14, 0x1c, 0x1c, - 0x14, 0x1a, 0x1c, - 0x14, 0x18, 0x1c, - 0x14, 0x16, 0x1c, - 0x0, 0x0, 0x10, - 0x4, 0x0, 0x10, - 0x8, 0x0, 0x10, - 0xc, 0x0, 0x10, - 0x10, 0x0, 0x10, - 0x10, 0x0, 0xc, - 0x10, 0x0, 0x8, - 0x10, 0x0, 0x4, - 0x10, 0x0, 0x0, - 0x10, 0x4, 0x0, - 0x10, 0x8, 0x0, - 0x10, 0xc, 0x0, - 0x10, 0x10, 0x0, - 0xc, 0x10, 0x0, - 0x8, 0x10, 0x0, - 0x4, 0x10, 0x0, - 0x0, 0x10, 0x0, - 0x0, 0x10, 0x4, - 0x0, 0x10, 0x8, - 0x0, 0x10, 0xc, - 0x0, 0x10, 0x10, - 0x0, 0xc, 0x10, - 0x0, 0x8, 0x10, - 0x0, 0x4, 0x10, - 0x8, 0x8, 0x10, - 0xa, 0x8, 0x10, - 0xc, 0x8, 0x10, - 0xe, 0x8, 0x10, - 0x10, 0x8, 0x10, - 0x10, 0x8, 0xe, - 0x10, 0x8, 0xc, - 0x10, 0x8, 0xa, - 0x10, 0x8, 0x8, - 0x10, 0xa, 0x8, - 0x10, 0xc, 0x8, - 0x10, 0xe, 0x8, - 0x10, 0x10, 0x8, - 0xe, 0x10, 0x8, - 0xc, 0x10, 0x8, - 0xa, 0x10, 0x8, - 0x8, 0x10, 0x8, - 0x8, 0x10, 0xa, - 0x8, 0x10, 0xc, - 0x8, 0x10, 0xe, - 0x8, 0x10, 0x10, - 0x8, 0xe, 0x10, - 0x8, 0xc, 0x10, - 0x8, 0xa, 0x10, - 0xb, 0xb, 0x10, - 0xc, 0xb, 0x10, - 0xd, 0xb, 0x10, - 0xf, 0xb, 0x10, - 0x10, 0xb, 0x10, - 0x10, 0xb, 0xf, - 0x10, 0xb, 0xd, - 0x10, 0xb, 0xc, - 0x10, 0xb, 0xb, - 0x10, 0xc, 0xb, - 0x10, 0xd, 0xb, - 0x10, 0xf, 0xb, - 0x10, 0x10, 0xb, - 0xf, 0x10, 0xb, - 0xd, 0x10, 0xb, - 0xc, 0x10, 0xb, - 0xb, 0x10, 0xb, - 0xb, 0x10, 0xc, - 0xb, 0x10, 0xd, - 0xb, 0x10, 0xf, - 0xb, 0x10, 0x10, - 0xb, 0xf, 0x10, - 0xb, 0xd, 0x10, - 0xb, 0xc, 0x10, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0 + /* red green blue */ + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x2a }, + { 0x0, 0x2a, 0x0 }, + { 0x0, 0x2a, 0x2a }, + { 0x2a, 0x0, 0x0 }, + { 0x2a, 0x0, 0x2a }, + { 0x2a, 0x2a, 0x0 }, + { 0x2a, 0x2a, 0x2a }, + { 0x0, 0x0, 0x15 }, + { 0x0, 0x0, 0x3f }, + { 0x0, 0x2a, 0x15 }, + { 0x0, 0x2a, 0x3f }, + { 0x2a, 0x0, 0x15 }, + { 0x2a, 0x0, 0x3f }, + { 0x2a, 0x2a, 0x15 }, + { 0x2a, 0x2a, 0x3f }, + { 0x0, 0x15, 0x0 }, + { 0x0, 0x15, 0x2a }, + { 0x0, 0x3f, 0x0 }, + { 0x0, 0x3f, 0x2a }, + { 0x2a, 0x15, 0x0 }, + { 0x2a, 0x15, 0x2a }, + { 0x2a, 0x3f, 0x0 }, + { 0x2a, 0x3f, 0x2a }, + { 0x0, 0x15, 0x15 }, + { 0x0, 0x15, 0x3f }, + { 0x0, 0x3f, 0x15 }, + { 0x0, 0x3f, 0x3f }, + { 0x2a, 0x15, 0x15 }, + { 0x2a, 0x15, 0x3f }, + { 0x2a, 0x3f, 0x15 }, + { 0x2a, 0x3f, 0x3f }, + { 0x15, 0x0, 0x0 }, + { 0x15, 0x0, 0x2a }, + { 0x15, 0x2a, 0x0 }, + { 0x15, 0x2a, 0x2a }, + { 0x3f, 0x0, 0x0 }, + { 0x3f, 0x0, 0x2a }, + { 0x3f, 0x2a, 0x0 }, + { 0x3f, 0x2a, 0x2a }, + { 0x15, 0x0, 0x15 }, + { 0x15, 0x0, 0x3f }, + { 0x15, 0x2a, 0x15 }, + { 0x15, 0x2a, 0x3f }, + { 0x3f, 0x0, 0x15 }, + { 0x3f, 0x0, 0x3f }, + { 0x3f, 0x2a, 0x15 }, + { 0x3f, 0x2a, 0x3f }, + { 0x15, 0x15, 0x0 }, + { 0x15, 0x15, 0x2a }, + { 0x15, 0x3f, 0x0 }, + { 0x15, 0x3f, 0x2a }, + { 0x3f, 0x15, 0x0 }, + { 0x3f, 0x15, 0x2a }, + { 0x3f, 0x3f, 0x0 }, + { 0x3f, 0x3f, 0x2a }, + { 0x15, 0x15, 0x15 }, + { 0x15, 0x15, 0x3f }, + { 0x15, 0x3f, 0x15 }, + { 0x15, 0x3f, 0x3f }, + { 0x3f, 0x15, 0x15 }, + { 0x3f, 0x15, 0x3f }, + { 0x3f, 0x3f, 0x15 }, + { 0x3f, 0x3f, 0x3f }, + { 0x39, 0xc, 0x5 }, + { 0x15, 0x2c, 0xf }, + { 0x26, 0x10, 0x3d }, + { 0x29, 0x29, 0x38 }, + { 0x4, 0x1a, 0xe }, + { 0x2, 0x1e, 0x3a }, + { 0x3c, 0x25, 0x33 }, + { 0x3c, 0xc, 0x2c }, + { 0x3f, 0x3, 0x2b }, + { 0x1c, 0x9, 0x13 }, + { 0x25, 0x2a, 0x35 }, + { 0x1e, 0xa, 0x38 }, + { 0x24, 0x8, 0x3 }, + { 0x3, 0xe, 0x36 }, + { 0xc, 0x6, 0x2a }, + { 0x26, 0x3, 0x32 }, + { 0x5, 0x2f, 0x33 }, + { 0x3c, 0x35, 0x2f }, + { 0x2d, 0x26, 0x3e }, + { 0xd, 0xa, 0x10 }, + { 0x25, 0x3c, 0x11 }, + { 0xd, 0x4, 0x2e }, + { 0x5, 0x19, 0x3e }, + { 0xc, 0x13, 0x34 }, + { 0x2b, 0x6, 0x24 }, + { 0x4, 0x3, 0xd }, + { 0x2f, 0x3c, 0xc }, + { 0x2a, 0x37, 0x1f }, + { 0xf, 0x12, 0x38 }, + { 0x38, 0xe, 0x2a }, + { 0x12, 0x2f, 0x19 }, + { 0x29, 0x2e, 0x31 }, + { 0x25, 0x13, 0x3e }, + { 0x33, 0x3e, 0x33 }, + { 0x1d, 0x2c, 0x25 }, + { 0x15, 0x15, 0x5 }, + { 0x32, 0x25, 0x39 }, + { 0x1a, 0x7, 0x1f }, + { 0x13, 0xe, 0x1d }, + { 0x36, 0x17, 0x34 }, + { 0xf, 0x15, 0x23 }, + { 0x2, 0x35, 0xd }, + { 0x15, 0x3f, 0xc }, + { 0x14, 0x2f, 0xf }, + { 0x19, 0x21, 0x3e }, + { 0x27, 0x11, 0x2f }, + { 0x38, 0x3f, 0x3c }, + { 0x36, 0x2d, 0x15 }, + { 0x16, 0x17, 0x2 }, + { 0x1, 0xa, 0x3d }, + { 0x1b, 0x11, 0x3f }, + { 0x21, 0x3c, 0xd }, + { 0x1a, 0x39, 0x3d }, + { 0x8, 0xe, 0xe }, + { 0x22, 0x21, 0x23 }, + { 0x1e, 0x30, 0x5 }, + { 0x1f, 0x22, 0x3d }, + { 0x1e, 0x2f, 0xa }, + { 0x0, 0x1c, 0xe }, + { 0x0, 0x1c, 0x15 }, + { 0x0, 0x1c, 0x1c }, + { 0x0, 0x15, 0x1c }, + { 0x0, 0xe, 0x1c }, + { 0x0, 0x7, 0x1c }, + { 0xe, 0xe, 0x1c }, + { 0x11, 0xe, 0x1c }, + { 0x15, 0xe, 0x1c }, + { 0x18, 0xe, 0x1c }, + { 0x1c, 0xe, 0x1c }, + { 0x1c, 0xe, 0x18 }, + { 0x1c, 0xe, 0x15 }, + { 0x1c, 0xe, 0x11 }, + { 0x1c, 0xe, 0xe }, + { 0x1c, 0x11, 0xe }, + { 0x1c, 0x15, 0xe }, + { 0x1c, 0x18, 0xe }, + { 0x1c, 0x1c, 0xe }, + { 0x18, 0x1c, 0xe }, + { 0x15, 0x1c, 0xe }, + { 0x11, 0x1c, 0xe }, + { 0xe, 0x1c, 0xe }, + { 0xe, 0x1c, 0x11 }, + { 0xe, 0x1c, 0x15 }, + { 0xe, 0x1c, 0x18 }, + { 0xe, 0x1c, 0x1c }, + { 0xe, 0x18, 0x1c }, + { 0xe, 0x15, 0x1c }, + { 0xe, 0x11, 0x1c }, + { 0x14, 0x14, 0x1c }, + { 0x16, 0x14, 0x1c }, + { 0x18, 0x14, 0x1c }, + { 0x1a, 0x14, 0x1c }, + { 0x1c, 0x14, 0x1c }, + { 0x1c, 0x14, 0x1a }, + { 0x1c, 0x14, 0x18 }, + { 0x1c, 0x14, 0x16 }, + { 0x1c, 0x14, 0x14 }, + { 0x1c, 0x16, 0x14 }, + { 0x1c, 0x18, 0x14 }, + { 0x1c, 0x1a, 0x14 }, + { 0x1c, 0x1c, 0x14 }, + { 0x1a, 0x1c, 0x14 }, + { 0x18, 0x1c, 0x14 }, + { 0x16, 0x1c, 0x14 }, + { 0x14, 0x1c, 0x14 }, + { 0x14, 0x1c, 0x16 }, + { 0x14, 0x1c, 0x18 }, + { 0x14, 0x1c, 0x1a }, + { 0x14, 0x1c, 0x1c }, + { 0x14, 0x1a, 0x1c }, + { 0x14, 0x18, 0x1c }, + { 0x14, 0x16, 0x1c }, + { 0x0, 0x0, 0x10 }, + { 0x4, 0x0, 0x10 }, + { 0x8, 0x0, 0x10 }, + { 0xc, 0x0, 0x10 }, + { 0x10, 0x0, 0x10 }, + { 0x10, 0x0, 0xc }, + { 0x10, 0x0, 0x8 }, + { 0x10, 0x0, 0x4 }, + { 0x10, 0x0, 0x0 }, + { 0x10, 0x4, 0x0 }, + { 0x10, 0x8, 0x0 }, + { 0x10, 0xc, 0x0 }, + { 0x10, 0x10, 0x0 }, + { 0xc, 0x10, 0x0 }, + { 0x8, 0x10, 0x0 }, + { 0x4, 0x10, 0x0 }, + { 0x0, 0x10, 0x0 }, + { 0x0, 0x10, 0x4 }, + { 0x0, 0x10, 0x8 }, + { 0x0, 0x10, 0xc }, + { 0x0, 0x10, 0x10 }, + { 0x0, 0xc, 0x10 }, + { 0x0, 0x8, 0x10 }, + { 0x0, 0x4, 0x10 }, + { 0x8, 0x8, 0x10 }, + { 0xa, 0x8, 0x10 }, + { 0xc, 0x8, 0x10 }, + { 0xe, 0x8, 0x10 }, + { 0x10, 0x8, 0x10 }, + { 0x10, 0x8, 0xe }, + { 0x10, 0x8, 0xc }, + { 0x10, 0x8, 0xa }, + { 0x10, 0x8, 0x8 }, + { 0x10, 0xa, 0x8 }, + { 0x10, 0xc, 0x8 }, + { 0x10, 0xe, 0x8 }, + { 0x10, 0x10, 0x8 }, + { 0xe, 0x10, 0x8 }, + { 0xc, 0x10, 0x8 }, + { 0xa, 0x10, 0x8 }, + { 0x8, 0x10, 0x8 }, + { 0x8, 0x10, 0xa }, + { 0x8, 0x10, 0xc }, + { 0x8, 0x10, 0xe }, + { 0x8, 0x10, 0x10 }, + { 0x8, 0xe, 0x10 }, + { 0x8, 0xc, 0x10 }, + { 0x8, 0xa, 0x10 }, + { 0xb, 0xb, 0x10 }, + { 0xc, 0xb, 0x10 }, + { 0xd, 0xb, 0x10 }, + { 0xf, 0xb, 0x10 }, + { 0x10, 0xb, 0x10 }, + { 0x10, 0xb, 0xf }, + { 0x10, 0xb, 0xd }, + { 0x10, 0xb, 0xc }, + { 0x10, 0xb, 0xb }, + { 0x10, 0xc, 0xb }, + { 0x10, 0xd, 0xb }, + { 0x10, 0xf, 0xb }, + { 0x10, 0x10, 0xb }, + { 0xf, 0x10, 0xb }, + { 0xd, 0x10, 0xb }, + { 0xc, 0x10, 0xb }, + { 0xb, 0x10, 0xb }, + { 0xb, 0x10, 0xc }, + { 0xb, 0x10, 0xd }, + { 0xb, 0x10, 0xf }, + { 0xb, 0x10, 0x10 }, + { 0xb, 0xf, 0x10 }, + { 0xb, 0xd, 0x10 }, + { 0xb, 0xc, 0x10 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 } }; unsigned char AC[21] = { @@ -721,7 +719,7 @@ } void -clearVideoMemory() +clearVideoMemory(void) { int i, j; for (i = 0; i < lines; i++) { diff -u --recursive --new-file v2.4.9/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.4.9/linux/arch/ppc/config.in Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/config.in Tue Aug 28 07:11:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.config.in 1.34 07/08/01 11:39:11 trini +# BK Id: SCCS/s.config.in 1.40 08/24/01 20:31:47 paulus # # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. @@ -26,6 +26,7 @@ mainmenu_option next_comment comment 'Platform support' define_bool CONFIG_PPC y +define_bool CONFIG_PPC32 y choice 'Processor Type' \ "6xx/7xx/74xx/8260 CONFIG_6xx \ 4xx CONFIG_4xx \ @@ -42,6 +43,11 @@ define_bool CONFIG_ALL_PPC y fi +if [ "$CONFIG_6xx" = "y" -o "$CONFIG_POWER3" = "y" -o \ + "$CONFIG_POWER4" = "y" ]; then + define_bool CONFIG_PPC_STD_MMU y +fi + if [ "$CONFIG_8260" = "y" ]; then define_bool CONFIG_SERIAL_CONSOLE y bool 'Support for EST8260' CONFIG_EST8260 @@ -93,7 +99,8 @@ bool 'Workarounds for PPC601 bugs' CONFIG_PPC601_SYNC_FIX fi -if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then +if [ "$CONFIG_POWER3" = "n" -a "$CONFIG_POWER4" = "n" -a \ + "$CONFIG_6xx" = "n" ]; then define_bool CONFIG_ALL_PPC n fi @@ -104,6 +111,11 @@ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then bool 'AltiVec Support' CONFIG_ALTIVEC + bool 'Thermal Management Support' CONFIG_TAU + if [ "$CONFIG_TAU" = "y" ]; then + bool ' Interrupt driven TAU driver (DANGEROUS)' CONFIG_TAU_INT + bool ' Average high and low temp' CONFIG_TAU_AVERAGE + fi fi if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/IVMS8_defconfig linux/arch/ppc/configs/IVMS8_defconfig --- v2.4.9/linux/arch/ppc/configs/IVMS8_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/IVMS8_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/SM850_defconfig linux/arch/ppc/configs/SM850_defconfig --- v2.4.9/linux/arch/ppc/configs/SM850_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/SM850_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/SPD823TS_defconfig linux/arch/ppc/configs/SPD823TS_defconfig --- v2.4.9/linux/arch/ppc/configs/SPD823TS_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/SPD823TS_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/TQM823L_defconfig linux/arch/ppc/configs/TQM823L_defconfig --- v2.4.9/linux/arch/ppc/configs/TQM823L_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/TQM823L_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/TQM850L_defconfig linux/arch/ppc/configs/TQM850L_defconfig --- v2.4.9/linux/arch/ppc/configs/TQM850L_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/TQM850L_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/TQM860L_defconfig linux/arch/ppc/configs/TQM860L_defconfig --- v2.4.9/linux/arch/ppc/configs/TQM860L_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/TQM860L_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/apus_defconfig linux/arch/ppc/configs/apus_defconfig --- v2.4.9/linux/arch/ppc/configs/apus_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/apus_defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,21 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y # CONFIG_ALL_PPC is not set CONFIG_APUS=y # CONFIG_GEMINI is not set # CONFIG_PPC601_SYNC_FIX is not set # CONFIG_SMP is not set # CONFIG_ALTIVEC is not set +# CONFIG_TAU is not set # # General setup @@ -746,8 +749,10 @@ CONFIG_SOUND=y CONFIG_DMASOUND_PAULA=m CONFIG_DMASOUND=m +# CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -756,6 +761,7 @@ # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set # CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/bseip_defconfig linux/arch/ppc/configs/bseip_defconfig --- v2.4.9/linux/arch/ppc/configs/bseip_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/bseip_defconfig Tue Aug 28 06:58:33 2001 @@ -19,6 +19,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig --- v2.4.9/linux/arch/ppc/configs/common_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/common_defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,23 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_GEMINI is not set CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set CONFIG_ALTIVEC=y +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +# CONFIG_TAU_AVERAGE is not set # # General setup @@ -228,6 +233,7 @@ CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_IDEDMA=y @@ -237,8 +243,8 @@ # CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD7409 is not set -# CONFIG_AMD7409_OVERRIDE is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -249,7 +255,8 @@ # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set # CONFIG_PDC202XX_BURST is not set -# CONFIG_BLK_DEV_OSB4 is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set @@ -769,8 +776,10 @@ CONFIG_SOUND=m CONFIG_DMASOUND_AWACS=m CONFIG_DMASOUND=m +# CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -779,6 +788,7 @@ # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set # CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/est8260_defconfig linux/arch/ppc/configs/est8260_defconfig --- v2.4.9/linux/arch/ppc/configs/est8260_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/est8260_defconfig Tue Aug 28 06:58:33 2001 @@ -19,16 +19,17 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set CONFIG_8260=y +CONFIG_PPC_STD_MMU=y CONFIG_SERIAL_CONSOLE=y CONFIG_EST8260=y CONFIG_PPC601_SYNC_FIX=y -# CONFIG_ALL_PPC is not set # CONFIG_SMP is not set # diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig --- v2.4.9/linux/arch/ppc/configs/gemini_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/gemini_defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,23 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y # CONFIG_ALL_PPC is not set # CONFIG_APUS is not set CONFIG_GEMINI=y # CONFIG_PPC601_SYNC_FIX is not set # CONFIG_SMP is not set CONFIG_ALTIVEC=y +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +# CONFIG_TAU_AVERAGE is not set # # General setup diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/ibmchrp_defconfig linux/arch/ppc/configs/ibmchrp_defconfig --- v2.4.9/linux/arch/ppc/configs/ibmchrp_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/ibmchrp_defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,21 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_GEMINI is not set # CONFIG_PPC601_SYNC_FIX is not set # CONFIG_SMP is not set # CONFIG_ALTIVEC is not set +# CONFIG_TAU is not set # # General setup diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/mbx_defconfig linux/arch/ppc/configs/mbx_defconfig --- v2.4.9/linux/arch/ppc/configs/mbx_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/mbx_defconfig Tue Aug 28 06:58:33 2001 @@ -19,6 +19,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig --- v2.4.9/linux/arch/ppc/configs/oak_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/oak_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set CONFIG_4xx=y # CONFIG_POWER3 is not set @@ -29,6 +30,7 @@ CONFIG_OAK=y # CONFIG_WALNUT is not set CONFIG_PPC601_SYNC_FIX=y +# CONFIG_ALL_PPC is not set # CONFIG_SMP is not set # CONFIG_MATH_EMULATION is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/power3_defconfig linux/arch/ppc/configs/power3_defconfig --- v2.4.9/linux/arch/ppc/configs/power3_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/power3_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set CONFIG_POWER3=y @@ -28,6 +29,7 @@ # CONFIG_8xx is not set CONFIG_PPC64BRIDGE=y CONFIG_ALL_PPC=y +CONFIG_PPC_STD_MMU=y CONFIG_SMP=y # CONFIG_IRQ_ALL_CPUS is not set @@ -640,8 +642,10 @@ # CONFIG_SOUND=y # CONFIG_DMASOUND_AWACS is not set +# CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -650,6 +654,7 @@ # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set # CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/rpxcllf_defconfig linux/arch/ppc/configs/rpxcllf_defconfig --- v2.4.9/linux/arch/ppc/configs/rpxcllf_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/rpxcllf_defconfig Tue Aug 28 06:58:33 2001 @@ -19,6 +19,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/rpxlite_defconfig linux/arch/ppc/configs/rpxlite_defconfig --- v2.4.9/linux/arch/ppc/configs/rpxlite_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/rpxlite_defconfig Tue Aug 28 06:58:33 2001 @@ -19,6 +19,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig --- v2.4.9/linux/arch/ppc/configs/walnut_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/walnut_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set CONFIG_4xx=y # CONFIG_POWER3 is not set @@ -29,6 +30,7 @@ # CONFIG_OAK is not set CONFIG_WALNUT=y CONFIG_PPC601_SYNC_FIX=y +# CONFIG_ALL_PPC is not set # CONFIG_SMP is not set # CONFIG_MATH_EMULATION is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/defconfig linux/arch/ppc/defconfig --- v2.4.9/linux/arch/ppc/defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,23 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_GEMINI is not set CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set CONFIG_ALTIVEC=y +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +# CONFIG_TAU_AVERAGE is not set # # General setup @@ -228,6 +233,7 @@ CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_IDEDMA=y @@ -237,8 +243,8 @@ # CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD7409 is not set -# CONFIG_AMD7409_OVERRIDE is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -249,7 +255,8 @@ # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set # CONFIG_PDC202XX_BURST is not set -# CONFIG_BLK_DEV_OSB4 is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set @@ -769,8 +776,10 @@ CONFIG_SOUND=m CONFIG_DMASOUND_AWACS=m CONFIG_DMASOUND=m +# CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -779,6 +788,7 @@ # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set # CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile --- v2.4.9/linux/arch/ppc/kernel/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.24 07/10/01 12:12:22 trini +# BK Id: SCCS/s.Makefile 1.32 08/24/01 20:07:37 paulus # # # Makefile for the linux kernel. @@ -29,12 +29,13 @@ O_TARGET := kernel.o -export-objs := ppc_ksyms.o prep_setup.o +export-objs := ppc_ksyms.o prep_setup.o time.o obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ process.o signal.o ptrace.o \ ppc_htab.o semaphore.o syscalls.o \ - align.o setup.o + align.o setup.o cputable.o +obj-$(CONFIG_6xx) += l2cr.o obj-$(CONFIG_MODULES) += ppc_ksyms.o obj-$(CONFIG_POWER4) += xics.o obj-$(CONFIG_PCI) += pci.o pci-dma.o @@ -43,6 +44,7 @@ obj-$(CONFIG_4xx) += ppc4xx_pic.o obj-$(CONFIG_OAK) += oak_setup.o obj-$(CONFIG_WALNUT) += walnut_setup.o +obj-$(CONFIG_TAU) += temp.o ifeq ($(CONFIG_WALNUT),y) obj-$(CONFIG_PCI) += galaxy_pci.o endif @@ -71,12 +73,17 @@ obj-$(CONFIG_GEMINI) += gemini_prom.o gemini_pci.o gemini_setup.o \ open_pic.o obj-$(CONFIG_8260) += m8260_setup.o ppc8260_pic.o +obj-$(CONFIG_BOOTX_TEXT) += btext.o +ifeq ($(CONFIG_SMP),y) +obj-$(CONFIG_ALL_PPC) += pmac_smp.o chrp_smp.o +endif include $(TOPDIR)/Rules.make entry.o: entry.S ppc_defs.h misc.o: misc.S ppc_defs.h +l2cr.o: l2cr.S ppc_defs.h head.o: head.S ppc_defs.h head_4xx.o: head_4xx.S ppc_defs.h head_8xx.o: head_8xx.S ppc_defs.h diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/apus_pci.c linux/arch/ppc/kernel/apus_pci.c --- v2.4.9/linux/arch/ppc/kernel/apus_pci.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/apus_pci.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.apus_pci.c 1.4 07/06/01 09:19:28 trini + * BK Id: SCCS/s.apus_pci.c 1.5 09/08/01 15:47:42 paulus */ /* * Copyright (C) Michel Dänzer @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c --- v2.4.9/linux/arch/ppc/kernel/apus_setup.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/apus_setup.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.apus_setup.c 1.14 07/06/01 09:19:28 trini + * BK Id: SCCS/s.apus_setup.c 1.20 09/08/01 15:47:42 paulus */ /* * linux/arch/ppc/kernel/apus_setup.c @@ -76,7 +76,6 @@ #include #include #include -#include #include "local_irq.h" @@ -611,32 +610,8 @@ /* * IDE stuff. */ -void ide_insw(ide_ioreg_t port, void *buf, int ns); -void ide_outsw(ide_ioreg_t port, void *buf, int ns); -void -apus_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - ide_insw(port, buf, ns); -} - -void -apus_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - ide_outsw(port, buf, ns); -} - -int -apus_ide_default_irq(ide_ioreg_t base) -{ - return 0; -} - -ide_ioreg_t -apus_ide_default_io_base(int index) -{ - return 0; -} +#if 0 /* no longer used -- paulus */ void apus_ide_fix_driveid(struct hd_driveid *id) { @@ -682,6 +657,7 @@ } } } +#endif /* 0 */ __init void apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, @@ -1039,6 +1015,15 @@ return total; } +static void __init +apus_map_io(void) +{ + /* Map PPC exception vectors. */ + io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL); + /* Map chip and ZorroII memory */ + io_block_mapping(zTwoBase, 0x00000000, 0x01000000, _PAGE_IO); +} + __init void apus_init_IRQ(void) { @@ -1061,8 +1046,8 @@ } __init -void apus_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { extern int parse_bootinfo(const struct bi_record *); extern char _end[]; @@ -1113,6 +1098,7 @@ ppc_md.calibrate_decr = apus_calibrate_decr; ppc_md.find_end_of_memory = apus_find_end_of_memory; + ppc_md.setup_io_mappings = apus_map_io; ppc_md.nvram_read_val = NULL; ppc_md.nvram_write_val = NULL; @@ -1130,14 +1116,7 @@ #endif #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = apus_ide_insw; - ppc_ide_md.outsw = apus_ide_outsw; - ppc_ide_md.default_irq = apus_ide_default_irq; - ppc_ide_md.default_io_base = apus_ide_default_io_base; - ppc_ide_md.fix_driveid = apus_ide_fix_driveid; ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; #endif } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/btext.c linux/arch/ppc/kernel/btext.c --- v2.4.9/linux/arch/ppc/kernel/btext.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/btext.c Sat Sep 8 12:38:41 2001 @@ -0,0 +1,868 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * Procedures for drawing on the screen early on in the boot process. + * + * Benjamin Herrenschmidt + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NO_SCROLL + +#ifndef NO_SCROLL +static void scrollscreen(void); +#endif + +static void draw_byte(unsigned char c, long locX, long locY); +static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb); +static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb); +static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb); + +static int g_loc_X; +static int g_loc_Y; +static int g_max_loc_X; +static int g_max_loc_Y; + +unsigned long disp_BAT[2] __initdata = {0, 0}; + +#define cmapsz (16*256) + +static unsigned char vga_font[cmapsz]; + +int boot_text_mapped = 1; + +boot_infos_t *disp_bi; +boot_infos_t fake_bi; + +extern char *klimit; + +/* + * Powermac can use btext_* after boot for xmon, + * chrp only uses it during early boot. + */ +#ifdef CONFIG_XMON +#define BTEXT __pmac +#define BTDATA __pmacdata +#else +#define BTEXT __init +#define BTDATA __initdata +#endif /* CONFIG_XMON */ + +/* + * This is called only when we are booted via BootX. + */ +void __init +btext_init(boot_infos_t *bi) +{ + unsigned long offset = reloc_offset(); + + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y) = 0; + RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8; + RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16; + RELOC(disp_bi) = PTRUNRELOC(bi); +} + +void __init +btext_welcome(boot_infos_t* bi) +{ + unsigned long offset = reloc_offset(); + unsigned long flags; + unsigned long pvr; + + btext_drawstring(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n")); + btext_drawstring(RELOC("\nlinked at : 0x")); + btext_drawhex(KERNELBASE); + btext_drawstring(RELOC("\nframe buffer at : 0x")); + btext_drawhex((unsigned long)bi->dispDeviceBase); + btext_drawstring(RELOC(" (phys), 0x")); + btext_drawhex((unsigned long)bi->logicalDisplayBase); + btext_drawstring(RELOC(" (log)")); + btext_drawstring(RELOC("\nklimit : 0x")); + btext_drawhex((unsigned long)RELOC(klimit)); + btext_drawstring(RELOC("\nMSR : 0x")); + __asm__ __volatile__ ("mfmsr %0" : "=r" (flags)); + btext_drawhex(flags); + __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr)); + pvr >>= 16; + if (pvr > 1) { + btext_drawstring(RELOC("\nHID0 : 0x")); + __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags)); + btext_drawhex(flags); + } + if (pvr == 8 || pvr == 12 || pvr == 0x800c) { + btext_drawstring(RELOC("\nICTC : 0x")); + __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags)); + btext_drawhex(flags); + } + btext_drawstring(RELOC("\n\n")); +} + +/* Calc BAT values for mapping the display and store them + * in disp_BAT. Those values are then used from head.S to map + * the display during identify_machine() and MMU_Init() + * + * The display is mapped to virtual address 0xD0000000, rather + * than 1:1, because some some CHRP machines put the frame buffer + * in the region starting at 0xC0000000 (KERNELBASE). + * This mapping is temporary and will disappear as soon as the + * setup done by MMU_Init() is applied. + * + * For now, we align the BAT and then map 8Mb on 601 and 16Mb + * on other PPCs. This may cause trouble if the framebuffer + * is really badly aligned, but I didn't encounter this case + * yet. + */ +void __init +btext_prepare_BAT(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long addr = (unsigned long)bi->dispDeviceBase; + unsigned long vaddr = KERNELBASE + 0x10000000; + unsigned long lowbits; + + if (!RELOC(disp_bi)) { + RELOC(boot_text_mapped) = 0; + return; + } + if (PVR_VER(mfspr(PVR)) != 1) { + /* 603, 604, G3, G4, ... */ + lowbits = addr & ~0xFF000000UL; + addr &= 0xFF000000UL; + RELOC(disp_BAT[0]) = vaddr | (BL_16M<<2) | 2; + RELOC(disp_BAT[1]) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW); + } else { + /* 601 */ + lowbits = addr & ~0xFF800000UL; + addr &= 0xFF800000UL; + RELOC(disp_BAT[0]) = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4; + RELOC(disp_BAT[1]) = addr | BL_8M | 0x40; + } + bi->logicalDisplayBase = (void *) (vaddr + lowbits); +} + +/* This function will enable the early boot text when doing OF booting. This + * way, xmon output should work too + */ +void __init +btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi; + + RELOC(disp_bi) = &fake_bi; + bi = PTRRELOC((&fake_bi)); + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y) = 0; + RELOC(g_max_loc_X) = width / 8; + RELOC(g_max_loc_Y) = height / 16; + bi->logicalDisplayBase = (unsigned char *)address; + bi->dispDeviceBase = (unsigned char *)address; + bi->dispDeviceRowBytes = pitch; + bi->dispDeviceDepth = depth; + bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; +} + +/* Here's a small text engine to use during early boot + * or for debugging purposes + * + * todo: + * + * - build some kind of vgacon with it to enable early printk + * - move to a separate file + * - add a few video driver hooks to keep in sync with display + * changes. + */ + +void __openfirmware +map_boot_text(void) +{ + unsigned long base, offset, size; + if (disp_bi == 0) + return; + base = ((unsigned long) disp_bi->dispDeviceBase) & 0xFFFFF000UL; + offset = ((unsigned long) disp_bi->dispDeviceBase) - base; + size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset + + disp_bi->dispDeviceRect[0]; + disp_bi->logicalDisplayBase = ioremap(base, size); + if (disp_bi->logicalDisplayBase == 0) + return; + disp_bi->logicalDisplayBase += offset; + boot_text_mapped = 1; +} + +/* Calc the base address of a given point (x,y) */ +static unsigned char * BTEXT +calc_base(boot_infos_t *bi, int x, int y) +{ + unsigned char *base; + + base = bi->logicalDisplayBase; + if (base == 0) + base = bi->dispDeviceBase; + base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); + base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; + return base; +} + +/* Adjust the display to a new resolution */ +void +btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch) +{ + if (disp_bi == 0) + return; + /* check it's the same frame buffer (within 64MB) */ + if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xfc000000) { + return; + } + + disp_bi->dispDeviceBase = (__u8 *) phys; + disp_bi->dispDeviceRect[0] = 0; + disp_bi->dispDeviceRect[1] = 0; + disp_bi->dispDeviceRect[2] = width; + disp_bi->dispDeviceRect[3] = height; + disp_bi->dispDeviceDepth = depth; + disp_bi->dispDeviceRowBytes = pitch; + if (boot_text_mapped) { + iounmap(disp_bi->logicalDisplayBase); + boot_text_mapped = 0; + } + map_boot_text(); + g_loc_X = 0; + g_loc_Y = 0; + g_max_loc_X = width / 8; + g_max_loc_Y = height / 16; +} + +void BTEXT btext_clearscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + { + unsigned long *ptr = base; + for(j=width; j; --j) + *(ptr++) = 0; + base += (bi->dispDeviceRowBytes >> 2); + } +} + +__inline__ void dcbst(const void* addr) +{ + __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr)); +} + +void BTEXT btext_flushscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + { + unsigned long *ptr = base; + for(j=width; j>0; j-=8) { + dcbst(ptr); + ptr += 8; + } + base += (bi->dispDeviceRowBytes >> 2); + } +} + +#ifndef NO_SCROLL +static BTEXT void +scrollscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long *src = (unsigned long *)calc_base(bi,0,16); + unsigned long *dst = (unsigned long *)calc_base(bi,0,0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + +#ifdef CONFIG_ADB_PMU + pmu_suspend(); /* PMU will not shut us down ! */ +#endif + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) + { + unsigned long *src_ptr = src; + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = *(src_ptr++); + src += (bi->dispDeviceRowBytes >> 2); + dst += (bi->dispDeviceRowBytes >> 2); + } + for (i=0; i<16; i++) + { + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = 0; + dst += (bi->dispDeviceRowBytes >> 2); + } +#ifdef CONFIG_ADB_PMU + pmu_resume(); /* PMU will not shut us down ! */ +#endif +} +#endif /* ndef NO_SCROLL */ + +void BTEXT btext_drawchar(char c) +{ + unsigned long offset = reloc_offset(); + int cline = 0, x; + + if (!RELOC(boot_text_mapped)) + return; + + switch (c) { + case '\b': + if (RELOC(g_loc_X) > 0) + --RELOC(g_loc_X); + break; + case '\t': + RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8; + break; + case '\r': + RELOC(g_loc_X) = 0; + break; + case '\n': + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y)++; + cline = 1; + break; + default: + draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y)); + } + if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) { + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y)++; + cline = 1; + } +#ifndef NO_SCROLL + while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { + scrollscreen(); + RELOC(g_loc_Y)--; + } +#else + /* wrap around from bottom to top of screen so we don't + waste time scrolling each line. -- paulus. */ + if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) + RELOC(g_loc_Y) = 0; + if (cline) { + for (x = 0; x < RELOC(g_max_loc_X); ++x) + draw_byte(' ', x, RELOC(g_loc_Y)); + } +#endif +} + +void BTEXT +btext_drawstring(const char *c) +{ + unsigned long offset = reloc_offset(); + + if (!RELOC(boot_text_mapped)) + return; + while (*c) + btext_drawchar(*c++); +} + +void BTEXT +btext_drawhex(unsigned long v) +{ + static char hex_table[] = "0123456789abcdef"; + unsigned long offset = reloc_offset(); + + if (!RELOC(boot_text_mapped)) + return; + btext_drawchar(RELOC(hex_table)[(v >> 28) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 24) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 20) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 16) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 12) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 8) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 4) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 0) & 0x0000000FUL]); + btext_drawchar(' '); +} + +static void BTEXT +draw_byte(unsigned char c, long locX, long locY) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned char *base = calc_base(bi, locX << 3, locY << 4); + unsigned char *font = &RELOC(vga_font)[((unsigned long)c) * 16]; + int rb = bi->dispDeviceRowBytes; + + switch(bi->dispDeviceDepth) { + case 32: + draw_byte_32(font, (unsigned long *)base, rb); + break; + case 16: + draw_byte_16(font, (unsigned long *)base, rb); + break; + case 8: + draw_byte_8(font, (unsigned long *)base, rb); + break; + } +} + +static unsigned long expand_bits_8[16] BTDATA = { + 0x00000000, + 0x000000ff, + 0x0000ff00, + 0x0000ffff, + 0x00ff0000, + 0x00ff00ff, + 0x00ffff00, + 0x00ffffff, + 0xff000000, + 0xff0000ff, + 0xff00ff00, + 0xff00ffff, + 0xffff0000, + 0xffff00ff, + 0xffffff00, + 0xffffffff +}; + +static unsigned long expand_bits_16[4] BTDATA = { + 0x00000000, + 0x0000ffff, + 0xffff0000, + 0xffffffff +}; + + +static void BTEXT +draw_byte_32(unsigned char *font, unsigned long *base, int rb) +{ + int l, bits; + int fg = 0xFFFFFFFFUL; + int bg = 0x00000000UL; + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (-(bits >> 7) & fg) ^ bg; + base[1] = (-((bits >> 6) & 1) & fg) ^ bg; + base[2] = (-((bits >> 5) & 1) & fg) ^ bg; + base[3] = (-((bits >> 4) & 1) & fg) ^ bg; + base[4] = (-((bits >> 3) & 1) & fg) ^ bg; + base[5] = (-((bits >> 2) & 1) & fg) ^ bg; + base[6] = (-((bits >> 1) & 1) & fg) ^ bg; + base[7] = (-(bits & 1) & fg) ^ bg; + base = (unsigned long *) ((char *)base + rb); + } +} + +static void BTEXT +draw_byte_16(unsigned char *font, unsigned long *base, int rb) +{ + int l, bits; + int fg = 0xFFFFFFFFUL; + int bg = 0x00000000UL; + unsigned long offset = reloc_offset(); + unsigned long *eb = RELOC(expand_bits_16); + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (eb[bits >> 6] & fg) ^ bg; + base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; + base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; + base[3] = (eb[bits & 3] & fg) ^ bg; + base = (unsigned long *) ((char *)base + rb); + } +} + +static void BTEXT +draw_byte_8(unsigned char *font, unsigned long *base, int rb) +{ + int l, bits; + int fg = 0x0F0F0F0FUL; + int bg = 0x00000000UL; + unsigned long offset = reloc_offset(); + unsigned long *eb = RELOC(expand_bits_8); + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (eb[bits >> 4] & fg) ^ bg; + base[1] = (eb[bits & 0xf] & fg) ^ bg; + base = (unsigned long *) ((char *)base + rb); + } +} + +static unsigned char vga_font[cmapsz] BTDATA = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, +0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, +0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, +0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, +0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, +0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, +0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, +0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, +0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, +0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, +0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, +0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, +0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, +0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, +0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, +0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, +0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, +0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, +0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, +0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, +0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, +0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, +0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, +0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, +0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, +0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, +0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, +0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, +0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, +0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, +0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, +0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, +0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, +0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, +0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, +0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, +0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, +0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, +0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, +0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, +0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, +0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, +0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, +0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, +0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, +0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, +0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, +0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, +0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, +0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, +0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, +0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, +0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, +0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, +0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, +0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, +0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, +0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, +0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, +0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, +0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, +0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, +0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, +0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, +}; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c --- v2.4.9/linux/arch/ppc/kernel/chrp_pci.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/chrp_pci.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrp_pci.c 1.20 08/08/01 16:35:43 paulus + * BK Id: SCCS/s.chrp_pci.c 1.22 09/08/01 15:47:42 paulus */ /* * CHRP pci routines. @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include "open_pic.h" diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.4.9/linux/arch/ppc/kernel/chrp_setup.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/chrp_setup.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrp_setup.c 1.22 07/18/01 22:56:39 paulus + * BK Id: SCCS/s.chrp_setup.c 1.36 09/08/01 15:47:42 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -51,8 +51,9 @@ #include #include #include -#include +#include #include +#include #include "local_irq.h" #include "i8259.h" @@ -68,7 +69,7 @@ void chrp_event_scan(void); void rtas_display_progress(char *, unsigned short); void rtas_indicator_progress(char *, unsigned short); -void bootx_text_progress(char *, unsigned short); +void btext_progress(char *, unsigned short); extern unsigned long pmac_find_end_of_memory(void); extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); @@ -79,14 +80,7 @@ extern void pckbd_leds(unsigned char leds); extern void pckbd_init_hw(void); extern unsigned char pckbd_sysrq_xlate[128]; -extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int mackbd_getkeycode(unsigned int scancode); -extern int mackbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char mackbd_unexpected_up(unsigned char keycode); -extern void mackbd_leds(unsigned char leds); -extern void mackbd_init_hw(void); -extern unsigned char mackbd_sysrq_xlate[128]; +extern void select_adb_keyboard(void); extern kdev_t boot_dev; @@ -94,9 +88,13 @@ extern unsigned long Hash_size, Hash_mask; extern int probingmem; extern unsigned long loops_per_jiffy; -extern int bootx_text_mapped; static int max_width; +#ifdef CONFIG_SMP +extern struct smp_ops_t chrp_smp_ops; +extern struct smp_ops_t xics_smp_ops; +#endif + static const char *gg2_memtypes[4] = { "FPM", "SDRAM", "EDO", "BEDO" }; @@ -248,9 +246,6 @@ chrp_find_bridges(); #ifndef CONFIG_PPC64BRIDGE - /* PCI bridge config space access area - - * appears to be not in devtree on longtrail. */ - ioremap(GG2_PCI_CONFIG_BASE, 0x80000); /* * Temporary fixes for PCI devices. * -- Geert @@ -259,7 +254,6 @@ #endif /* CONFIG_PPC64BRIDGE */ -#ifndef CONFIG_POWER4 /* Some IBM machines don't have the hydra -- Cort */ if (!OpenPIC_Addr) { struct device_node *root; @@ -276,7 +270,6 @@ OpenPIC_Addr = ioremap(opprop[n-1], 0x40000); } } -#endif /* * Fix the Super I/O configuration @@ -401,9 +394,6 @@ void __init chrp_init2(void) { -#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) - struct device_node *kbd; -#endif #ifdef CONFIG_NVRAM pmac_nvram_init(); #endif @@ -418,87 +408,35 @@ if (ppc_md.progress) ppc_md.progress(" Have fun! ", 0x7777); -#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) +#if defined(CONFIG_VT) && (defined(CONFIG_ADB_KEYBOARD) || defined(CONFIG_INPUT)) /* see if there is a keyboard in the device tree with a parent of type "adb" */ - for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) - if (kbd->parent && kbd->parent->type - && strcmp(kbd->parent->type, "adb") == 0) - break; - if (kbd) { - ppc_md.kbd_setkeycode = mackbd_setkeycode; - ppc_md.kbd_getkeycode = mackbd_getkeycode; - ppc_md.kbd_translate = mackbd_translate; - ppc_md.kbd_unexpected_up = mackbd_unexpected_up; - ppc_md.kbd_leds = mackbd_leds; - ppc_md.kbd_init_hw = mackbd_init_hw; -#ifdef CONFIG_MAGIC_SYSRQ - ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate; - SYSRQ_KEY = 0x69; -#endif /* CONFIG_MAGIC_SYSRQ */ + { + struct device_node *kbd; + + for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) { + if (kbd->parent && kbd->parent->type + && strcmp(kbd->parent->type, "adb") == 0) { + select_adb_keyboard(); + break; + } + } } -#endif /* CONFIG_VT && CONFIG_ADB_KEYBOARD */ +#endif /* CONFIG_VT && (CONFIG_ADB_KEYBOARD || CONFIG_INPUT) */ } #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) /* * IDE stuff. */ -unsigned int chrp_ide_irq = 0; -int chrp_ide_ports_known = 0; -ide_ioreg_t chrp_ide_regbase[MAX_HWIFS]; -ide_ioreg_t chrp_idedma_regbase; - -void __chrp -chrp_ide_probe(void) -{ - struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL); - - chrp_ide_ports_known = 1; - - if(pdev) { - chrp_ide_regbase[0]=pdev->resource[0].start; - chrp_ide_regbase[1]=pdev->resource[2].start; - chrp_idedma_regbase=pdev->resource[4].start; - chrp_ide_irq=pdev->irq; - } -} -void __chrp -chrp_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - ide_insw(port+_IO_BASE, buf, ns); -} - -void __chrp -chrp_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - ide_outsw(port+_IO_BASE, buf, ns); -} - -int __chrp -chrp_ide_default_irq(ide_ioreg_t base) -{ - if (chrp_ide_ports_known == 0) - chrp_ide_probe(); - return chrp_ide_irq; -} - -ide_ioreg_t __chrp -chrp_ide_default_io_base(int index) -{ - if (chrp_ide_ports_known == 0) - chrp_ide_probe(); - return chrp_ide_regbase[index]; -} - -int __chrp +static int __chrp chrp_ide_check_region(ide_ioreg_t from, unsigned int extent) { return check_region(from, extent); } -void __chrp +static void __chrp chrp_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) @@ -506,14 +444,14 @@ request_region(from, extent, name); } -void __chrp +static void __chrp chrp_ide_release_region(ide_ioreg_t from, unsigned int extent) { release_region(from, extent); } -void __chrp +static void __chrp chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) { ide_ioreg_t reg = data_port; @@ -523,20 +461,42 @@ hw->io_ports[i] = reg; reg += 1; } - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; +} +#endif + +/* + * One of the main thing these mappings are needed for is so that + * xmon can get to the serial port early on. We probably should + * handle the machines with the mpc106 as well as the python (F50) + * and the GG2 (longtrail). Actually we should look in the device + * tree and do the right thing. + */ +static void __init +chrp_map_io(void) +{ + char *name; + + /* + * The code below tends to get removed, please don't take it out. + * The F50 needs this mapping and it you take it out I'll track you + * down and slap your hands. If it causes problems please email me. + * -- Cort + */ + name = get_property(find_path_device("/"), "name", NULL); + if (name && strncmp(name, "IBM-70", 6) == 0 + && strstr(name, "-F50")) { + io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); + io_block_mapping(0x90000000, 0x90000000, 0x10000000, _PAGE_IO); + return; } else { - hw->io_ports[IDE_CONTROL_OFFSET] = 0; + io_block_mapping(0xf8000000, 0xf8000000, 0x04000000, _PAGE_IO); } - if (irq != NULL) - hw->irq = chrp_ide_irq; } -#endif - void __init - chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { #ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ @@ -576,6 +536,7 @@ ppc_md.calibrate_decr = chrp_calibrate_decr; ppc_md.find_end_of_memory = pmac_find_end_of_memory; + ppc_md.setup_io_mappings = chrp_map_io; #ifdef CONFIG_VT /* these are adjusted in chrp_init2 if we have an ADB keyboard */ @@ -608,22 +569,23 @@ } } #ifdef CONFIG_BOOTX_TEXT - if (ppc_md.progress == NULL && bootx_text_mapped) - ppc_md.progress = bootx_text_progress; + if (ppc_md.progress == NULL && boot_text_mapped) + ppc_md.progress = btext_progress; #endif +#ifdef CONFIG_SMP +#ifndef CONFIG_POWER4 + ppc_md.smp_ops = &chrp_smp_ops; +#else + ppc_md.smp_ops = &xics_smp_ops; +#endif /* CONFIG_POWER4 */ +#endif /* CONFIG_SMP */ + #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = chrp_ide_insw; - ppc_ide_md.outsw = chrp_ide_outsw; - ppc_ide_md.default_irq = chrp_ide_default_irq; - ppc_ide_md.default_io_base = chrp_ide_default_io_base; ppc_ide_md.ide_check_region = chrp_ide_check_region; ppc_ide_md.ide_request_region = chrp_ide_request_region; ppc_ide_md.ide_release_region = chrp_ide_release_region; - ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; #endif /* @@ -668,7 +630,7 @@ #ifdef CONFIG_BOOTX_TEXT void -bootx_text_progress(char *s, unsigned short hex) +btext_progress(char *s, unsigned short hex) { prom_print(s); prom_print("\n"); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/chrp_smp.c linux/arch/ppc/kernel/chrp_smp.c --- v2.4.9/linux/arch/ppc/kernel/chrp_smp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/chrp_smp.c Sat Sep 8 12:38:41 2001 @@ -0,0 +1,149 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * Smp support for CHRP machines. + * + * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great + * deal of code from the sparc and intel versions. + * + * Copyright (C) 1999 Cort Dougan + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "open_pic.h" + +extern unsigned long smp_chrp_cpu_nr; + +static int __init +smp_chrp_probe(void) +{ + if (smp_chrp_cpu_nr > 1) + openpic_request_IPIs(); + + return smp_chrp_cpu_nr; +} + +static void __init +smp_chrp_kick_cpu(int nr) +{ + *(unsigned long *)KERNELBASE = nr; + asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); +} + +static void __init +smp_chrp_setup_cpu(int cpu_nr) +{ + static atomic_t ready = ATOMIC_INIT(1); + static volatile int frozen = 0; + + if (cpu_nr == 0) { + /* wait for all the others */ + while (atomic_read(&ready) < smp_num_cpus) + barrier(); + atomic_set(&ready, 1); + /* freeze the timebase */ + call_rtas("freeze-time-base", 0, 1, NULL); + mb(); + frozen = 1; + /* XXX assumes this is not a 601 */ + set_tb(0, 0); + last_jiffy_stamp(0) = 0; + while (atomic_read(&ready) < smp_num_cpus) + barrier(); + /* thaw the timebase again */ + call_rtas("thaw-time-base", 0, 1, NULL); + mb(); + frozen = 0; + smp_tb_synchronized = 1; + } else { + atomic_inc(&ready); + while (!frozen) + barrier(); + set_tb(0, 0); + last_jiffy_stamp(0) = 0; + mb(); + atomic_inc(&ready); + while (frozen) + barrier(); + } + + if (OpenPIC_Addr) + do_openpic_setup_cpu(); +} + +#ifdef CONFIG_POWER4 +static void __chrp +smp_xics_message_pass(int target, int msg, unsigned long data, int wait) +{ + /* for now, only do reschedule messages + since we only have one IPI */ + if (msg != PPC_MSG_RESCHEDULE) + return; + for (i = 0; i < smp_num_cpus; ++i) { + if (target == MSG_ALL || target == i + || (target == MSG_ALL_BUT_SELF + && i != smp_processor_id())) + xics_cause_IPI(i); + } +} + +static int __chrp +smp_xics_probe(void) +{ + return smp_chrp_cpu_nr; +} + +static void __chrp +smp_xics_setup_cpu(int cpu_nr) +{ + if (cpu_nr > 0) + xics_setup_cpu(); +} +#endif /* CONFIG_POWER4 */ + +/* CHRP with openpic */ +struct smp_ops_t chrp_smp_ops __chrpdata = { + smp_openpic_message_pass, + smp_chrp_probe, + smp_chrp_kick_cpu, + smp_chrp_setup_cpu, +}; + +#ifdef CONFIG_POWER4 +/* CHRP with new XICS interrupt controller */ +struct smp_ops_t xics_smp_ops __chrpdata = { + smp_xics_message_pass, + smp_xics_probe, + smp_chrp_kick_cpu, + smp_xics_setup_cpu, +}; +#endif /* CONFIG_POWER4 */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c --- v2.4.9/linux/arch/ppc/kernel/chrp_time.c Mon May 21 17:04:46 2001 +++ linux/arch/ppc/kernel/chrp_time.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrp_time.c 1.7 05/17/01 18:14:21 cort + * BK Id: SCCS/s.chrp_time.c 1.10 09/08/01 15:47:42 paulus */ /* * linux/arch/i386/kernel/time.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include extern spinlock_t rtc_lock; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/cputable.c linux/arch/ppc/kernel/cputable.c --- v2.4.9/linux/arch/ppc/kernel/cputable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/cputable.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,283 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * arch/ppc/kernel/cputable.c + * + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +struct cpu_spec* cur_cpu_spec[NR_CPUS]; + +extern void __setup_cpu_601(int cpu_nr); +extern void __setup_cpu_603(int cpu_nr); +extern void __setup_cpu_604(int cpu_nr); +extern void __setup_cpu_750(int cpu_nr); +extern void __setup_cpu_7400(int cpu_nr); +extern void __setup_cpu_7450(int cpu_nr); +extern void __setup_cpu_power3(int cpu_nr); +extern void __setup_cpu_power4(int cpu_nr); +extern void __setup_cpu_8xx(int cpu_nr); +extern void __setup_cpu_generic(int cpu_nr); + +#define CLASSIC_PPC (!defined(CONFIG_8xx) && \ + !defined(CONFIG_4xx) && !defined(CONFIG_POWER3) && \ + !defined(CONFIG_POWER4) && !defined(CONFIG_PPC_ISERIES)) + +/* This table only contains "desktop" CPUs, it need to be filled with embedded + * ones as well... + */ +#define COMMON_PPC (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ + PPC_FEATURE_HAS_MMU) + +/* We only set the altivec features if the kernel was compiled with altivec + * support + */ +#ifdef CONFIG_ALTIVEC +#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC +#else +#define CPU_FTR_ALTIVEC_COMP 0 +#endif + +struct cpu_spec cpu_specs[] = { +#if CLASSIC_PPC + { /* 601 */ + 0xffff0000, 0x00010000, "601", + CPU_FTR_601 | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_601_INSTR | PPC_FEATURE_UNIFIED_CACHE, + 32, 32, + __setup_cpu_601 + }, + { /* 603 */ + 0xffff0000, 0x00030000, "603", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, + COMMON_PPC, + 32, 32, + __setup_cpu_603 + }, + { /* 603e */ + 0xffff0000, 0x00060000, "603e", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, + COMMON_PPC, + 32, 32, + __setup_cpu_603 + }, + { /* 603ev */ + 0xffff0000, 0x00070000, "603ev", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, + COMMON_PPC, + 32, 32, + __setup_cpu_603 + }, + { /* 604 */ + 0xffff0000, 0x00040000, "604", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | + CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_604 + }, + { /* 604e */ + 0xfffff000, 0x00090000, "604e", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | + CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_604 + }, + { /* 604r */ + 0xffff0000, 0x00090000, "604r", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | + CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_604 + }, + { /* 604ev */ + 0xffff0000, 0x000a0000, "604ev", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | + CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_604 + }, + { /* 750 (0x4202, don't support TAU ?) */ + 0xffffffff, 0x00084202, "750", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_750 + }, + { /* 750CX */ + 0xffffff00, 0x00082200, "750CX", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_750 + }, + { /* 740/750 (L2CR bit need fixup for 740) */ + 0xffff0000, 0x00080000, "740/750", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_750 + }, + { /* 7400 rev 1.1 ? (no TAU) */ + 0xffffffff, 0x000c1101, "7400 (1.1)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC, + 32, 32, + __setup_cpu_7400 + }, + { /* 7400 */ + 0xffff0000, 0x000c0000, "7400", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC, + 32, 32, + __setup_cpu_7400 + }, + { /* 7410 */ + 0xffff0000, 0x800c0000, "7410", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC, + 32, 32, + __setup_cpu_7400 + }, + { /* 7450 */ + 0xffff0000, 0x80000000, "7450", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450, + COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC, + 32, 32, + __setup_cpu_7450 + }, + { /* 82xx (8240, 8245, 8260 are all 603e cores) */ + 0xffff0000, 0x00810000, "82xx", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, + COMMON_PPC, + 32, 32, + __setup_cpu_603 + }, + { /* default match, we assume split I/D cache & TB (non-601)... */ + 0x00000000, 0x00000000, "(generic PPC)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_generic + }, +#endif /* CLASSIC_PPC */ +#ifdef CONFIG_PPC64BRIDGE + { /* Power3 */ + 0xffff0000, 0x00400000, "Power3 (630)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power3 + }, + { /* Power3+ */ + 0xffff0000, 0x00410000, "Power3 (630+)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power3 + }, + { /* I-star */ + 0xffff0000, 0x00360000, "I-star", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power3 + }, + { /* S-star */ + 0xffff0000, 0x00370000, "S-star", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power3 + }, +#endif /* CONFIG_PPC64BRIDGE */ +#ifdef CONFIG_POWER4 + { /* Power4 */ + 0xffff0000, 0x00350000, "Power4", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power4 + }, +#endif /* CONFIG_POWER4 */ +#ifdef CONFIG_8xx + { /* 8xx */ + 0xffff0000, 0x00500000, "8xx", + /* CPU_FTR_CAN_DOZE is possible, if the 8xx code is there.... */ + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 16, 16, + 0, __setup_cpu_8xx + }, +#endif /* CONFIG_8xx */ +#ifdef CONFIG_4xx + { /* 403GC */ + 0xffffff00, 0x00200200, "403GC", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 16, 16, + 0, /*__setup_cpu_403 */ + }, + { /* 403GCX */ + 0xffffff00, 0x00201400, "403GCX", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 16, 16, + 0, /*__setup_cpu_403 */ + }, + { /* 403G ?? */ + 0xffff0000, 0x00200000, "403G ??", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 16, 16, + 0, /*__setup_cpu_403 */ + }, + { /* 405GP */ + 0xffff0000, 0x40110000, "405GP", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + 32, 32, + 0, /*__setup_cpu_405 */ + }, + { /* STB 03xxx */ + 0xffff0000, 0x40130000, "STB03xxx", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + 32, 32, + 0, /*__setup_cpu_405 */ + }, +#endif /* CONFIG_4xx */ +#if !CLASSIC_PPC + { /* default match */ + 0x00000000, 0x00000000, "(generic PPC)", + 0, + PPC_FEATURE_32, + 32, 32, + 0, + } +#endif /* !CLASSIC_PPC */ +}; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S --- v2.4.9/linux/arch/ppc/kernel/entry.S Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/entry.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.entry.S 1.20 07/19/01 23:02:48 paulus + * BK Id: SCCS/s.entry.S 1.22 08/15/01 22:43:06 paulus */ /* * PowerPC version @@ -23,12 +23,14 @@ */ #include "ppc_asm.h" +#include +#include +#include +#include #include #include #include -#include -#include -#include +#include #undef SHOW_SYSCALLS #undef SHOW_SYSCALLS_TASK @@ -217,7 +219,9 @@ mfmsr r22 li r0,MSR_FP /* Disable floating-point */ #ifdef CONFIG_ALTIVEC - oris r0,r0,MSR_VEC@h +BEGIN_FTR_SECTION + oris r0,r0,MSR_VEC@h /* Disable altivec */ +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ andc r22,r22,r0 mtmsr r22 @@ -238,21 +242,6 @@ tophys(r0,r4) CLR_TOP32(r0) mtspr SPRG3,r0 /* Update current THREAD phys addr */ -#ifdef CONFIG_8xx - /* XXX it would be nice to find a SPRGx for this on 6xx,7xx too */ - lwz r9,PGDIR(r4) /* cache the page table root */ - tophys(r9,r9) /* convert to phys addr */ -#ifdef CONFIG_8xx_CPU6 - lis r6, cpu6_errata_word@h - ori r6, r6, cpu6_errata_word@l - li r5, 0x3980 - stw r5, 8(r6) - lwz r5, 8(r6) -#endif - mtspr M_TWB,r9 /* Update MMU base address */ - tlbia - sync -#endif /* CONFIG_8xx */ lwz r1,KSP(r4) /* Load new stack pointer */ /* save the old current 'last' for return value */ mr r3,r2 @@ -328,19 +317,16 @@ andi. r0,r0,MSR_PR beq+ 1f #ifdef CONFIG_ALTIVEC - mfpvr r8 /* check if we are on a G4 */ - srwi r8,r8,16 - cmpwi r8,PVR_7400@h - bne 2f +BEGIN_FTR_SECTION lwz r0,THREAD+THREAD_VRSAVE(r2) - mtspr SPRN_VRSAVE,r0 /* if so, restore VRSAVE reg */ -2: + mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */ +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ addi r0,r1,INT_FRAME_SIZE /* size of frame */ stw r0,THREAD+KSP(r2) /* save kernel stack pointer */ tophys(r8,r1) CLR_TOP32(r8) - mtspr SPRG2,r8 /* phys exception stack pointer */ + mtspr SPRG2,r8 /* phys exception stack pointer */ 1: lwz r3,_CTR(r1) lwz r0,_LINK(r1) @@ -348,15 +334,32 @@ mtlr r0 REST_4GPRS(3, r1) REST_2GPRS(7, r1) + + /* We have to "dummy" load from the context save area in case + * these instructions cause an MMU fault. If this happens + * after we load SRR0/SRR1, our return context is hosed. -- Dan + */ + lwz r0,GPR0(r1) + lwz r0,GPR2(r1) + lwz r0,GPR1(r1) + + /* We re-use r3,r4 here (the load above was to cause the MMU + * fault if necessary). Using r3,r4 removes the need to "dummy" + * load the CCR and NIP. Since we load them we may as well + * use them. + */ + lwz r3,_CCR(r1) + lwz r4,_NIP(r1) + lwz r0,_MSR(r1) FIX_SRR1(r0,r2) mtspr SRR1,r0 - lwz r2,_CCR(r1) - mtcrf 0xFF,r2 - lwz r2,_NIP(r1) - mtspr SRR0,r2 + mtcrf 0xFF,r3 + mtspr SRR0,r4 lwz r0,GPR0(r1) lwz r2,GPR2(r1) + lwz r3,GPR3(r1) + lwz r4,GPR4(r1) lwz r1,GPR1(r1) SYNC RFI diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c --- v2.4.9/linux/arch/ppc/kernel/feature.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/feature.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.feature.c 1.16 07/06/01 14:42:47 trini + * BK Id: SCCS/s.feature.c 1.21 09/08/01 15:47:42 paulus */ /* * arch/ppc/kernel/feature.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -38,11 +38,15 @@ #define FREG(c,r) (&(((c)->reg)[(r)>>2])) /* Keylargo reg. access. */ -#define KL_FCR(r) (keylargo_base + ((r) >> 2)) -#define KL_IN(r) (in_le32(KL_FCR(r))) -#define KL_OUT(r,v) (out_le32(KL_FCR(r), (v))) -#define KL_BIS(r,v) (KL_OUT((r), KL_IN(r) | (v))) -#define KL_BIC(r,v) (KL_OUT((r), KL_IN(r) & ~(v))) +#define KL_FCR(r) (keylargo_base + ((r) >> 2)) +#define KL_IN(r) (in_le32(KL_FCR(r))) +#define KL_OUT(r,v) (out_le32(KL_FCR(r), (v))) +#define KL_BIS(r,v) (KL_OUT((r), KL_IN(r) | (v))) +#define KL_BIC(r,v) (KL_OUT((r), KL_IN(r) & ~(v))) +#define KL_GPIO_IN(r) (in_8(((volatile u8 *)keylargo_base)+(r))) +#define KL_GPIO_OUT(r,v) (out_8(((volatile u8 *)keylargo_base)+(r), (v))) +#define KL_LOCK() spin_lock_irqsave(&keylargo->lock, flags) +#define KL_UNLOCK() spin_unlock_irqrestore(&keylargo->lock, flags) /* Uni-N reg. access. Note that Uni-N regs are big endian */ #define UN_REG(r) (uninorth_base + ((r) >> 2)) @@ -259,15 +263,29 @@ static int uninorth_rev; static int keylargo_rev; static u32 board_features; -static u8 airport_pwr_regs[5]; static int airport_pwr_state; static struct device_node* airport_dev; +static struct device_node* uninorth_fw; +/* Feature bits for Apple motherboards */ #define FTR_NEED_OPENPIC_TWEAK 0x00000001 #define FTR_CAN_NAP 0x00000002 #define FTR_HAS_FW_POWER 0x00000004 #define FTR_CAN_SLEEP 0x00000008 +/* This table currently lacks most oldworld machines, but + * they currently don't need it so... + * + * Todo: The whole feature_xxx mecanism need to be redone + * some way to be able to handle the new kind of features + * exposed by core99. At this point, the main "tables" will + * probably be in this table, which will have to be filled with + * all known machines + */ +/* Warning: Don't change ordering of entries as some machines + * adverstise beeing compatible with several models. In those + * case, the "highest" has to be first + */ static struct board_features_t { char* compatible; u32 features; @@ -283,17 +301,21 @@ { "PowerMac3,1", FTR_NEED_OPENPIC_TWEAK }, /* Sawtooth (G4) */ { "PowerMac3,2", 0 }, /* G4/Dual G4 */ { "PowerMac3,3", FTR_NEED_OPENPIC_TWEAK }, /* G4/Dual G4 */ - { "PowerMac5,1", 0 }, /* Cube */ + { "PowerMac3,4", 0 }, /* QuickSilver G4 */ + { "PowerMac3,5", 0 }, /* QuickSilver G4 */ + { "PowerMac5,1", FTR_CAN_NAP }, /* Cube */ { "AAPL,3400/2400", FTR_CAN_SLEEP }, /* 2400/3400 PowerBook */ { "AAPL,3500", FTR_CAN_SLEEP }, /* 3500 PowerBook (G3) */ { "AAPL,PowerBook1998", FTR_CAN_SLEEP }, /* Wallstreet PowerBook */ { "PowerBook1,1", FTR_CAN_SLEEP }, /* 101 (Lombard) PowerBook */ + { "PowerBook4,1", FTR_CAN_NAP|FTR_CAN_SLEEP| /* New polycarbonate iBook */ + 0/*FTR_HAS_FW_POWER*/ }, { "PowerBook2,1", FTR_CAN_SLEEP }, /* iBook */ - { "PowerBook4,1", FTR_CAN_NAP|FTR_CAN_SLEEP }, /* iBook Dual USB */ { "PowerBook2,2", FTR_CAN_SLEEP /*| FTR_CAN_NAP*/ }, /* iBook FireWire */ { "PowerBook3,1", FTR_CAN_SLEEP|FTR_CAN_NAP| /* PowerBook 2000 (Pismo) */ FTR_HAS_FW_POWER }, - { "PowerBook3,2", FTR_CAN_NAP|FTR_CAN_SLEEP }, /* PowerBook Titanium */ + { "PowerBook3,2", FTR_CAN_NAP|FTR_CAN_SLEEP| /* PowerBook Titanium */ + 0/*FTR_HAS_FW_POWER*/ }, { NULL, 0 } }; @@ -305,15 +327,25 @@ struct device_node *np; u32 *rev; int i; - + char* model; + if (_machine != _MACH_Pmac) return; - /* Figure out motherboard type & options */ - for(i=0;board_features_datas[i].compatible;i++) { - if (machine_is_compatible(board_features_datas[i].compatible)) { - board_features = board_features_datas[i].features; - break; + np = find_path_device("/"); + if (!np) { + printk(KERN_ERR "feature.c: Can't find device-tree root !\n"); + return; + } + model = (char*)get_property(np, "model", NULL); + if (model) { + printk("PowerMac model: %s\n", model); + /* Figure out motherboard type & options */ + for(i=0;board_features_datas[i].compatible;i++) { + if (!strcmp(board_features_datas[i].compatible, model)) { + board_features = board_features_datas[i].features; + break; + } } } @@ -382,8 +414,9 @@ printk("Uninorth at 0x%08x\n", np->addrs[0].address); } if (uninorth_base && keylargo_base) - printk("Uni-N revision: %d, KeyLargo revision: %d\n", - uninorth_rev, keylargo_rev); + printk("Uni-N revision: %d, KeyLargo revision: %d %s\n", + uninorth_rev, keylargo_rev, + (keylargo_rev & KL_PANGEA_REV) ? "(Pangea chipset)" : ""); if (uninorth_base) uninorth_init(); @@ -402,6 +435,25 @@ feature_clear(controllers[0].device, FEATURE_Sound_CLK_enable); } #endif + +#ifdef CONFIG_PMAC_PBOOK + /* On PowerBooks, we disable the serial ports by default, they + * will be re-enabled by the driver + */ +#ifndef CONFIG_XMON + if (controller_count && find_devices("via-pmu") != NULL) { + feature_set_modem_power(NULL, 0); + feature_clear(controllers[0].device, FEATURE_Serial_IO_A); + feature_clear(controllers[0].device, FEATURE_Serial_IO_B); + feature_clear(controllers[0].device, FEATURE_Serial_enable); + if (controller_count > 1) { + feature_clear(controllers[1].device, FEATURE_Serial_IO_A); + feature_clear(controllers[1].device, FEATURE_Serial_IO_B); + feature_clear(controllers[1].device, FEATURE_Serial_enable); + } + } +#endif +#endif } static struct feature_controller __init * @@ -588,12 +640,16 @@ /* TODO: Handle save/restore of PCI config space here */ - spin_lock_irqsave(&keylargo->lock, flags); + /* XXX We use the keylargo spinlock, but we never + * have uninorth without keylargo, so... + */ + KL_LOCK(); if (power) UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); else UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); - spin_unlock_irqrestore(&keylargo->lock, flags); + (void)UN_IN(UNI_N_CLOCK_CNTL); + KL_UNLOCK(); udelay(20); } @@ -605,17 +661,16 @@ if (!keylargo_base || !keylargo) return; - spin_lock_irqsave(&keylargo->lock, flags); - out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET), - KEYLARGO_GPIO_OUTPUT_ENABLE); - (void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET)); - spin_unlock_irqrestore(&keylargo->lock, flags); + KL_LOCK(); + KL_GPIO_OUT(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)KL_GPIO_IN(KL_GPIO_ETH_PHY_RESET); + KL_UNLOCK(); mdelay(10); - spin_lock_irqsave(&keylargo->lock, flags); - out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET), + KL_LOCK(); + KL_GPIO_OUT(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); - (void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET)); - spin_unlock_irqrestore(&keylargo->lock, flags); + (void)KL_GPIO_IN(KL_GPIO_ETH_PHY_RESET); + KL_UNLOCK(); mdelay(10); } @@ -642,17 +697,23 @@ else return; - spin_lock_irqsave(&keylargo->lock, flags); + KL_LOCK(); if (power) { /* Turn ON */ if (number == 0) { KL_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); + (void)KL_IN(KEYLARGO_FCR0); + KL_UNLOCK(); mdelay(1); + KL_LOCK(); KL_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); } else { KL_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); + KL_UNLOCK(); + (void)KL_IN(KEYLARGO_FCR0); mdelay(1); + KL_LOCK(); KL_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); } reg = KL_IN(KEYLARGO_FCR4); @@ -689,7 +750,7 @@ } udelay(1); } - spin_unlock_irqrestore(&keylargo->lock, flags); + KL_UNLOCK(); } void __pmac @@ -697,18 +758,25 @@ { unsigned long flags; - /* TODO: Handle save/restore of PCI config space here + /* TODO: should probably handle save/restore of PCI config space here */ + if (!uninorth_fw || (device && uninorth_fw != device)) + return; if (!uninorth_base) return; - spin_lock_irqsave(&keylargo->lock, flags); + + /* XXX We use the keylargo spinlock, but we never + * have uninorth without keylargo, so... + */ + KL_LOCK(); if (power) UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); else UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); + (void)UN_IN(UNI_N_CLOCK_CNTL); + KL_UNLOCK(); udelay(20); - spin_unlock_irqrestore(&keylargo->lock, flags); } /* Warning: will kill the PHY.. */ @@ -717,79 +785,159 @@ { unsigned long flags; u8 gpioValue = power ? 0 : 4; - + + if (!uninorth_fw || (device && uninorth_fw != device)) + return; if (!keylargo_base || !(board_features & FTR_HAS_FW_POWER)) return; - spin_lock_irqsave(&keylargo->lock, flags); - out_8((volatile u8 *)KL_FCR(KL_GPIO_FW_CABLE_POWER), gpioValue); - (void)in_8((volatile u8 *)KL_FCR(KL_GPIO_FW_CABLE_POWER)); - spin_unlock_irqrestore(&keylargo->lock, flags); + KL_LOCK(); + KL_GPIO_OUT(KL_GPIO_FW_CABLE_POWER, gpioValue); + (void)KL_GPIO_IN(KL_GPIO_FW_CABLE_POWER); + KL_UNLOCK(); +} + +void +feature_set_modem_power(struct device_node* device, int power) +{ + unsigned long flags; + + if (!device) { + device = find_devices("ch-a"); + while(device && !device_is_compatible(device, "cobalt")) + device = device->next; + if (!device) + return; + } + if (keylargo && (keylargo_rev & KL_PANGEA_REV)) { + KL_LOCK(); + if (power) { + /* Assert modem reset */ + KL_GPIO_OUT(KL_GPIO_MODEM_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)KL_GPIO_IN(KL_GPIO_MODEM_RESET); + udelay(10); + /* Power up modem */ + KL_GPIO_OUT(KL_GPIO_MODEM_POWER, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)KL_GPIO_IN(KL_GPIO_MODEM_POWER); + udelay(10); + /* Release modem reset */ + KL_GPIO_OUT(KL_GPIO_MODEM_RESET, + KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + (void)KL_GPIO_IN(KL_GPIO_MODEM_RESET); + } else { + /* Power down modem */ + KL_GPIO_OUT(KL_GPIO_MODEM_POWER, + KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + (void)KL_GPIO_IN(KL_GPIO_MODEM_POWER); + } + KL_UNLOCK(); + } else { + if (power) { + mdelay(300); + feature_set(device, FEATURE_Modem_power); + mdelay(5); + feature_clear(device, FEATURE_Modem_power); + mdelay(10); + feature_set(device, FEATURE_Modem_power); + } else { + feature_clear(device, FEATURE_Modem_power); + mdelay(10); + } + } } #ifdef CONFIG_SMP void __pmac feature_core99_kick_cpu(int cpu_nr) { -#if 1 /* New way */ const int reset_lines[] = { KL_GPIO_RESET_CPU0, KL_GPIO_RESET_CPU1, KL_GPIO_RESET_CPU2, KL_GPIO_RESET_CPU3 }; - volatile u8* reset_io; - + int reset_io; + unsigned long flags; + if (!keylargo_base || cpu_nr > 3) return; - reset_io = (volatile u8*)KL_FCR(reset_lines[cpu_nr]); - out_8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); - udelay(1); - out_8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); -#else - out_8((volatile u8 *)KL_FCR(KL_GPIO_EXTINT_CPU1), KL_GPIO_EXTINT_CPU1_ASSERT); + reset_io = reset_lines[cpu_nr]; + + KL_LOCK(); + KL_GPIO_OUT(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)KL_GPIO_IN(reset_io); udelay(1); - out_8((volatile u8 *)KL_FCR(KL_GPIO_EXTINT_CPU1), KL_GPIO_EXTINT_CPU1_RELEASE); -#endif + KL_GPIO_OUT(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + (void)KL_GPIO_IN(reset_io); + KL_UNLOCK(); } #endif /* CONFIG_SMP */ void __pmac feature_set_airport_power(struct device_node* device, int power) { + unsigned long flags; + if (!keylargo_base || !airport_dev || airport_dev != device) return; if (airport_pwr_state == power) - return; + return; if (power) { - /* Some if this is from Darwin code, some is from tracing of - * MacOS driver with Macsbug. Some real bit definitions would - * really help here... + /* This code is a reproduction of OF enable-cardslot + * and init-wireless methods, slightly hacked until + * I got it working. */ - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0), airport_pwr_regs[0]); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1), airport_pwr_regs[1]); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2), airport_pwr_regs[2]); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3), airport_pwr_regs[3]); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), airport_pwr_regs[4]); - udelay(20); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 5); - udelay(20); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 4); - mdelay(20); + KL_LOCK(); + KL_GPIO_OUT(KEYLARGO_GPIO_0+0xf, 5); + (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xf); + KL_UNLOCK(); + mdelay(10); + KL_LOCK(); + KL_GPIO_OUT(KEYLARGO_GPIO_0+0xf, 4); + (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xf); + KL_UNLOCK(); + + mdelay(10); + + KL_LOCK(); KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N); + (void)KL_IN(KEYLARGO_FCR2); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xb, 0); + (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xb); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28); + (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xa); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28); + (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xd); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_0+0xd, 0x28); + (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xd); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_0+0xe, 0x28); + (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xe); + KL_UNLOCK(); udelay(10); + KL_OUT(0x1c000, 0); + + mdelay(1); out_8((volatile u8*)KL_FCR(0x1a3e0), 0x41); + (void)in_8((volatile u8*)KL_FCR(0x1a3e0)); udelay(10); + KL_LOCK(); KL_BIS(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N); - udelay(10); + (void)KL_IN(KEYLARGO_FCR2); + KL_UNLOCK(); + mdelay(100); } else { - airport_pwr_regs[0] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0)); - airport_pwr_regs[1] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1)); - airport_pwr_regs[2] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2)); - airport_pwr_regs[3] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3)); - airport_pwr_regs[4] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4)); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0), 0); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1), 0); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2), 0); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3), 0); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 0); + KL_LOCK(); + KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N); + (void)KL_IN(KEYLARGO_FCR2); + KL_GPIO_OUT(KL_GPIO_AIRPORT_0, 0); + KL_GPIO_OUT(KL_GPIO_AIRPORT_1, 0); + KL_GPIO_OUT(KL_GPIO_AIRPORT_2, 0); + KL_GPIO_OUT(KL_GPIO_AIRPORT_3, 0); + KL_GPIO_OUT(KL_GPIO_AIRPORT_4, 0); + (void)KL_GPIO_IN(KL_GPIO_AIRPORT_4); + KL_UNLOCK(); } airport_pwr_state = power; } @@ -826,8 +974,11 @@ /* Enable FW before PCI probe. Will be disabled later on */ fw = find_devices("firewire"); - if (fw && device_is_compatible(fw, "pci106b,18")) + if (fw && (device_is_compatible(fw, "pci106b,18") || + device_is_compatible(fw, "pci106b,30"))) { + uninorth_fw = fw; feature_set_firewire_power(fw, 1); + } } /* Initialize the Core99 KeyLargo ASIC. @@ -864,7 +1015,7 @@ device_is_compatible(ctrler->device, "gatwick")) ctrler = &controllers[1]; - if (ctrler->bits == feature_bits_heathrow || + if (ctrler->bits == feature_bits_wallstreet || ctrler->bits == feature_bits_paddington) { heathrow_prepare_for_sleep(ctrler); return; @@ -884,7 +1035,7 @@ device_is_compatible(ctrler->device, "gatwick")) ctrler = &controllers[1]; - if (ctrler->bits == feature_bits_heathrow || + if (ctrler->bits == feature_bits_wallstreet || ctrler->bits == feature_bits_paddington) { heathrow_wakeup(ctrler); return; @@ -929,15 +1080,10 @@ { u32 temp; - /* For now, suspending the USB ref cause the machine to die on - * wakeup -- BenH - */ -#if 0 mdelay(1); KL_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); (void)KL_IN(KEYLARGO_FCR0); - mdelay(1500); -#endif + mdelay(100); KL_BIC(KEYLARGO_FCR0, KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | KL0_SCC_CELL_ENABLE | @@ -1014,7 +1160,7 @@ core99_prepare_for_sleep(struct feature_controller* ctrler) { int i; - u8* base8; + volatile u8* base8; /* * Save various bits of KeyLargo @@ -1026,15 +1172,19 @@ feature_set_airport_power(airport_dev, 0); /* We power off the FW cable. Should be done by the driver... */ + feature_set_firewire_power(NULL, 0); feature_set_firewire_cable_power(NULL, 0); + + /* We make sure int. modem is off (in case driver lost it) */ + feature_set_modem_power(NULL, 0); /* Save the state of the various GPIOs */ save_gpio_levels[0] = KL_IN(KEYLARGO_GPIO_LEVELS0); save_gpio_levels[1] = KL_IN(KEYLARGO_GPIO_LEVELS1); - base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_EXTINT_0); + base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_EXTINT_0; for (i=0; i> 28) & 0xf; + pvr = mfspr(PVR); + hid1 = (mfspr(HID1) >> 28) & 0xf; if (PVR_VER(pvr) == 8 || PVR_VER(pvr) == 12) hid1 = cpu_7xx[hid1]; @@ -241,11 +231,12 @@ { unsigned char reg, brev, fam, creg; unsigned long cache; - unsigned long pvr = _get_PVR(); + unsigned long pvr; reg = readb(GEMINI_L2CFG); brev = readb(GEMINI_BREV); fam = readb(GEMINI_FEAT); + pvr = mfspr(PVR); switch(PVR_VER(pvr)) { @@ -486,11 +477,60 @@ return total; } -void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +static void __init +gemini_map_io(void) +{ + io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); + io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); +} + +#ifdef CONFIG_SMP +static int +smp_gemini_probe(void) +{ + int i, nr; + + nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2; + if (nr == 0) + nr = 4; + + if (nr > 1) { + openpic_request_IPIs(); + for (i = 1; i < nr; ++i) + smp_hw_index[i] = i; + } + + return nr; +} + +static void +smp_gemini_kick_cpu(int nr) +{ + openpic_init_processor( 1< 0) + gemini_init_l2(); +} + +static struct smp_ops_t gemini_smp_ops = { + smp_openpic_message_pass, + smp_gemini_probe, + smp_gemini_kick_cpu, + smp_gemini_setup_cpu, +}; +#endif /* CONFIG_SMP */ + +void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { int i; - int chrp_get_irq( struct pt_regs * ); for(i = 0; i < GEMINI_LEDS; i++) gemini_led_off(i); @@ -525,6 +565,7 @@ ppc_md.calibrate_decr = gemini_calibrate_decr; ppc_md.find_end_of_memory = gemini_find_end_of_memory; + ppc_md.setup_io_mappings = gemini_map_io; /* no keyboard/mouse/video stuff yet.. */ ppc_md.kbd_setkeycode = NULL; @@ -537,4 +578,8 @@ ppc_md.ppc_kbd_sysrq_xlate = NULL; #endif ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup; + +#ifdef CONFIG_SMP + ppc_md.smp_ops = &gemini_smp_ops; +#endif /* CONFIG_SMP */ } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.4.9/linux/arch/ppc/kernel/head.S Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/head.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head.S 1.25 07/07/01 17:08:44 paulus + * BK Id: SCCS/s.head.S 1.29 08/19/01 22:43:23 paulus */ /* * PowerPC version @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_APUS #include @@ -153,7 +154,7 @@ #ifndef CONFIG_GEMINI /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains - * the physical address we are running at, returned by prom_init() + * the physical address we are running at, returned by early_init() */ bl mmu_off __after_mmu_off: @@ -761,12 +762,10 @@ addi r24,r1,STACK_FRAME_OVERHEAD stw r24,PT_REGS(r23) #ifdef CONFIG_ALTIVEC - mfpvr r24 /* check if we are on a G4 */ - srwi r24,r24,16 - cmpwi r24,PVR_7400@h - bne 2f - mfspr r22,SPRN_VRSAVE /* if so, save vrsave register value */ +BEGIN_FTR_SECTION + mfspr r22,SPRN_VRSAVE /* if G4, save vrsave register value */ stw r22,THREAD_VRSAVE(r23) +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ 2: addi r2,r23,-THREAD /* set r2 to current */ tovirt(r2,r2) @@ -1280,10 +1279,13 @@ SYNC MTMSRD(r0) isync -#else - bl enable_caches #endif + lis r3,-KERNELBASE@h + mr r4,r24 + bl identify_cpu + bl call_setup_cpu /* Call setup_cpu for this CPU */ + /* get current */ lis r2,current_set@h ori r2,r2,current_set@l @@ -1322,54 +1324,87 @@ /* * Enable caches and 604-specific features if necessary. */ -enable_caches: - mfspr r9,PVR - rlwinm r9,r9,16,16,31 - cmpi 0,r9,1 - beq 6f /* not needed for 601 */ +_GLOBAL(__setup_cpu_601) + blr +_GLOBAL(__setup_cpu_603) + b setup_common_caches +_GLOBAL(__setup_cpu_604) + mflr r4 + bl setup_common_caches + bl setup_604_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_750) + mflr r4 + bl setup_common_caches + bl setup_750_7400_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_7400) + mflr r4 + bl setup_common_caches + bl setup_750_7400_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_7450) + blr +_GLOBAL(__setup_cpu_power3) + blr +_GLOBAL(__setup_cpu_power4) + blr +_GLOBAL(__setup_cpu_generic) + blr + +/* Enable caches for 603's, 604, 750 & 7400 */ +setup_common_caches: mfspr r11,HID0 andi. r0,r11,HID0_DCE ori r11,r11,HID0_ICE|HID0_DCE ori r8,r11,HID0_ICFI - bne 3f /* don't invalidate the D-cache */ + bne 1f /* don't invalidate the D-cache */ ori r8,r8,HID0_DCI /* unless it wasn't enabled */ -3: - sync +1: sync mtspr HID0,r8 /* enable and invalidate caches */ sync mtspr HID0,r11 /* enable caches */ sync isync - cmpi 0,r9,4 /* check for 604 */ - cmpi 1,r9,9 /* or 604e */ - cmpi 2,r9,10 /* or mach5 / 604r */ - cmpi 3,r9,8 /* check for 750 (G3) */ - cmpi 4,r9,12 /* or 7400 (G4) */ - cror 2,2,6 - cror 2,2,10 - bne 4f - ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e|r], enable */ - bne 2,5f - ori r11,r11,HID0_BTCD /* superscalar exec & br history tbl */ - b 5f -4: - cror 14,14,18 - bne 3,6f - /* for G3/G4: - * enable Store Gathering (SGE), Address Brodcast (ABE), - * Branch History Table (BHTE), Branch Target ICache (BTIC) - */ + blr + +/* 604, 604e, 604ev, ... + * Enable superscalar execution & branch history table + */ +setup_604_hid0: + mfspr r11,HID0 + ori r11,r11,HID0_SIED|HID0_BHTE + ori r8,r11,HID0_BTCD + sync + mtspr HID0,r8 /* flush branch target address cache */ + sync /* on 604e/604r */ + mtspr HID0,r11 + sync + isync + blr + +/* 740/750/7400/7410 + * Enable Store Gathering (SGE), Address Brodcast (ABE), + * Branch History Table (BHTE), Branch Target ICache (BTIC) + * Dynamic Power Management (DPM), Speculative (SPD) + * Clear Instruction cache throttling (ICTC) + */ +setup_750_7400_hid0: + mfspr r11,HID0 ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ li r3,HID0_SPD andc r11,r11,r3 /* clear SPD: enable speculative */ li r3,0 mtspr ICTC,r3 /* Instruction Cache Throttling off */ -5: isync + isync mtspr HID0,r11 sync isync -6: blr + blr /* * Load stuff into the MMU. Intended to be called with @@ -1414,9 +1449,10 @@ * This is where the main kernel code starts. */ start_here: -#ifndef CONFIG_PPC64BRIDGE - bl enable_caches -#endif + /* Call setup_cpu for CPU 0 */ + li r3,0 /* data offset */ + li r24,0 /* cpu# */ + bl call_setup_cpu /* ptr to current */ lis r2,init_task_union@h @@ -1435,14 +1471,15 @@ li r0,0 stwu r0,-STACK_FRAME_OVERHEAD(r1) /* - * Decide what sort of machine this is and initialize the MMU. + * Do early bootinfo parsing, platform-specific initialization, + * and set up the MMU. */ mr r3,r31 mr r4,r30 mr r5,r29 mr r6,r28 mr r7,r27 - bl identify_machine + bl machine_init bl MMU_init #ifdef CONFIG_APUS @@ -1475,12 +1512,10 @@ /* Load up the kernel context */ 2: sync /* Force all PTE updates to finish */ + ISYNC_601 tlbia /* Clear all TLB entries */ sync /* wait for tlbia/tlbie to finish */ -#ifdef CONFIG_SMP - tlbsync /* ... on all CPUs */ - sync -#endif + TLBSYNC /* ... on all CPUs */ bl load_up_mmu /* Now turn on the MMU for real! */ @@ -1500,7 +1535,7 @@ mulli r3,r3,897 /* multiply context by skew factor */ rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */ addis r3,r3,0x6000 /* Set Ks, Ku bits */ - li r0,12 /* TASK_SIZE / SEGMENT_SIZE */ + li r0,NUM_USER_SEGMENTS mtctr r0 li r4,0 3: @@ -1512,7 +1547,8 @@ rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b - SYNC + SYNC_601 + isync blr /* diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S --- v2.4.9/linux/arch/ppc/kernel/head_8xx.S Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/head_8xx.S Wed Aug 29 20:49:36 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head_8xx.S 1.14 06/28/01 15:50:16 paulus + * BK Id: SCCS/s.head_8xx.S 1.21 08/28/01 16:27:27 trini */ /* * arch/ppc/kernel/except_8xx.S @@ -31,6 +31,7 @@ #include #include #include +#include .text .globl _stext @@ -87,70 +88,10 @@ mr r27,r7 li r24,0 /* cpu # */ - tlbia /* Invalidate all TLB entries */ - li r8, 0 - mtspr MI_CTR, r8 /* Set instruction control to zero */ - lis r8, MD_RESETVAL@h -#ifndef CONFIG_8xx_COPYBACK - oris r8, r8, MD_WTDEF@h -#endif - mtspr MD_CTR, r8 /* Set data TLB control */ - - /* Now map the lower 8 Meg into the TLBs. For this quick hack, - * we can load the instruction and data TLB registers with the - * same values. - */ - lis r8, KERNELBASE@h /* Create vaddr for TLB */ - ori r8, r8, MI_EVALID /* Mark it valid */ - mtspr MI_EPN, r8 - mtspr MD_EPN, r8 - li r8, MI_PS8MEG /* Set 8M byte page */ - ori r8, r8, MI_SVALID /* Make it valid */ - mtspr MI_TWC, r8 - mtspr MD_TWC, r8 - li r8, MI_BOOTINIT /* Create RPN for address 0 */ - mtspr MI_RPN, r8 /* Store TLB entry */ - mtspr MD_RPN, r8 - lis r8, MI_Kp@h /* Set the protection mode */ - mtspr MI_AP, r8 - mtspr MD_AP, r8 - - /* Map another 8 MByte at the IMMR to get the processor - * internal registers (among other things). + /* We have to turn on the MMU right away so we get cache modes + * set correctly. */ - mfspr r9, 638 /* Get current IMMR */ - andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */ - - mr r8, r9 /* Create vaddr for TLB */ - ori r8, r8, MD_EVALID /* Mark it valid */ - mtspr MD_EPN, r8 - li r8, MD_PS8MEG /* Set 8M byte page */ - ori r8, r8, MD_SVALID /* Make it valid */ - mtspr MD_TWC, r8 - mr r8, r9 /* Create paddr for TLB */ - ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */ - mtspr MD_RPN, r8 - - /* Since the cache is enabled according to the information we - * just loaded into the TLB, invalidate and enable the caches here. - * We should probably check/set other modes....later. - */ - lis r8, IDC_INVALL@h - mtspr IC_CST, r8 - mtspr DC_CST, r8 - lis r8, IDC_ENABLE@h - mtspr IC_CST, r8 -#ifdef CONFIG_8xx_COPYBACK - mtspr DC_CST, r8 -#else - /* For a debug option, I left this here to easily enable - * the write through cache mode - */ - lis r8, DC_SFWT@h - mtspr DC_CST, r8 - lis r8, IDC_ENABLE@h - mtspr DC_CST, r8 -#endif + bl initial_mmu /* We now have the lower 8 Meg mapped into TLB entries, and the caches * ready to work. @@ -513,6 +454,7 @@ #else li r21, 0x00f0 rlwimi r20, r21, 0, 24, 28 + #endif #ifdef CONFIG_8xx_CPU6 li r3, 0x3d80 @@ -721,131 +663,34 @@ giveup_fpu: blr -/* - * This code is jumped to from the startup code to copy - * the kernel image to physical address 0. - */ -relocate_kernel: - lis r9,0x426f /* if booted from BootX, don't */ - addi r9,r9,0x6f58 /* translate source addr */ - cmpw r31,r9 /* (we have to on chrp) */ - beq 7f - rlwinm r4,r4,0,8,31 /* translate source address */ - add r4,r4,r3 /* to region mapped with BATs */ -7: addis r9,r26,klimit@ha /* fetch klimit */ - lwz r25,klimit@l(r9) - addis r25,r25,-KERNELBASE@h - li r6,0 /* Destination offset */ - li r5,0x4000 /* # bytes of memory to copy */ - bl copy_and_flush /* copy the first 0x4000 bytes */ - addi r0,r3,4f@l /* jump to the address of 4f */ - mtctr r0 /* in copy and do the rest. */ - bctr /* jump to the copy */ -4: mr r5,r25 - bl copy_and_flush /* copy the rest */ - b turn_on_mmu - -/* - * Copy routine used to copy the kernel to start at physical address 0 - * and flush and invalidate the caches as needed. - * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset - * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. - */ -copy_and_flush: - addi r5,r5,-4 - addi r6,r6,-4 -4: li r0,CACHE_LINE_SIZE/4 - mtctr r0 -3: addi r6,r6,4 /* copy a cache line */ - lwzx r0,r6,r4 - stwx r0,r6,r3 - bdnz 3b - dcbst r6,r3 /* write it to memory */ - sync - icbi r6,r3 /* flush the icache line */ - cmplw 0,r6,r5 - blt 4b - isync - addi r5,r5,4 - addi r6,r6,4 +/* Maybe someday....... +*/ +_GLOBAL(__setup_cpu_8xx) blr -#ifdef CONFIG_SMP - .globl __secondary_start_psurge -__secondary_start_psurge: - li r24,1 /* cpu # */ - b __secondary_start - - .globl __secondary_hold -__secondary_hold: - /* tell the master we're here */ - lis r5,0x4@h - ori r5,r5,0x4@l - stw r3,0(r5) - dcbf 0,r5 -100: - lis r5,0 - dcbi 0,r5 - lwz r4,0(r5) - /* wait until we're told to start */ - cmp 0,r4,r3 - bne 100b - /* our cpu # was at addr 0 - go */ - lis r5,__secondary_start@h - ori r5,r5,__secondary_start@l - tophys(r5,r5) - mtlr r5 - mr r24,r3 /* cpu # */ - blr -#endif /* CONFIG_SMP */ - /* * This is where the main kernel code starts. */ start_here: -#ifdef CONFIG_SMP - /* if we're the second cpu stack and r2 are different - * and we want to not clear the bss -- Cort */ - lis r5,first_cpu_booted@h - ori r5,r5,first_cpu_booted@l - lwz r5,0(r5) - cmpi 0,r5,0 - beq 99f - - /* get current */ - lis r2,current_set@h - ori r2,r2,current_set@l - slwi r24,r24,2 /* cpu # to current_set[cpu#] */ - add r2,r2,r24 - lwz r2,0(r2) - b 10f -99: -#endif /* CONFIG_SMP */ + /* ptr to current */ lis r2,init_task_union@h ori r2,r2,init_task_union@l - /* Clear out the BSS */ - lis r11,_end@ha - addi r11,r11,_end@l - lis r8,__bss_start@ha - addi r8,r8,__bss_start@l - subf r11,r8,r11 - addi r11,r11,3 - rlwinm. r11,r11,30,2,31 - beq 2f - addi r8,r8,-4 - mtctr r11 - li r0,0 -3: stwu r0,4(r8) - bdnz 3b -2: -#ifdef CONFIG_SMP -10: -#endif /* CONFIG_SMP */ + + /* ptr to phys current thread */ + tophys(r4,r2) + addi r4,r4,THREAD /* init task's THREAD */ + mtspr SPRG3,r4 + li r3,0 + mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ + /* stack */ addi r1,r2,TASK_UNION_SIZE li r0,0 stwu r0,-STACK_FRAME_OVERHEAD(r1) + + bl early_init /* We have to do this with MMU on */ + /* * Decide what sort of machine this is and initialize the MMU. */ @@ -854,12 +699,11 @@ mr r5,r29 mr r6,r28 mr r7,r27 - bl identify_machine + bl machine_init bl MMU_init /* * Go back to running unmapped so we can load up new values - * for SDR1 (hash table pointer) and the segment registers * and change to using our exception vectors. * On the 8xx, all we have to do is invalidate the TLB to clear * the old 8M byte TLB mappings and load the page table base register. @@ -869,8 +713,8 @@ * easier......until someone changes init's static structures. */ lis r6, swapper_pg_dir@h - tophys(r6,r6) ori r6, r6, swapper_pg_dir@l + tophys(r6,r6) #ifdef CONFIG_8xx_CPU6 lis r4, cpu6_errata_word@h ori r4, r4, cpu6_errata_word@l @@ -891,65 +735,117 @@ SYNC /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ sync /* wait for tlbia/tlbie to finish */ -#ifdef CONFIG_SMP - tlbsync /* ... on all CPUs */ - sync -#endif -/* Set up for using our exception vectors */ - /* ptr to phys current thread */ - tophys(r4,r2) - addi r4,r4,THREAD /* init task's THREAD */ - mtspr SPRG3,r4 - li r3,0 - mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ + TLBSYNC /* ... on all CPUs */ + + /* set up the PTE pointers for the Abatron bdiGDB. + */ + tovirt(r6,r6) + lis r5, abatron_pteptrs@h + ori r5, r5, abatron_pteptrs@l + stw r5, 0xf0(r0) /* Must match your Abatron config file */ + tophys(r5,r5) + stw r6, 0(r5) + /* Now turn on the MMU for real! */ li r4,MSR_KERNEL lis r3,start_kernel@h ori r3,r3,start_kernel@l -#ifdef CONFIG_SMP - /* the second time through here we go to - * start_secondary(). -- Cort - */ - lis r5,first_cpu_booted@h - ori r5,r5,first_cpu_booted@l - tophys(r5,r5) - lwz r5,0(r5) - cmpi 0,r5,0 - beq 10f - lis r3,start_secondary@h - ori r3,r3,start_secondary@l -10: -#endif /* CONFIG_SMP */ mtspr SRR0,r3 mtspr SRR1,r4 rfi /* enable MMU and jump to start_kernel */ +/* Set up the initial MMU state so we can do the first level of + * kernel initialization. This maps the first 8 MBytes of memory 1:1 + * virtual to physical. Also, set the cache mode since that is defined + * by TLB entries and perform any additional mapping (like of the IMMR). + */ +initial_mmu: + tlbia /* Invalidate all TLB entries */ + li r8, 0 + mtspr MI_CTR, r8 /* Set instruction control to zero */ + lis r8, MD_RESETVAL@h +#ifndef CONFIG_8xx_COPYBACK + oris r8, r8, MD_WTDEF@h +#endif + mtspr MD_CTR, r8 /* Set data TLB control */ + + /* Now map the lower 8 Meg into the TLBs. For this quick hack, + * we can load the instruction and data TLB registers with the + * same values. + */ + lis r8, KERNELBASE@h /* Create vaddr for TLB */ + ori r8, r8, MI_EVALID /* Mark it valid */ + mtspr MI_EPN, r8 + mtspr MD_EPN, r8 + li r8, MI_PS8MEG /* Set 8M byte page */ + ori r8, r8, MI_SVALID /* Make it valid */ + mtspr MI_TWC, r8 + mtspr MD_TWC, r8 + li r8, MI_BOOTINIT /* Create RPN for address 0 */ + mtspr MI_RPN, r8 /* Store TLB entry */ + mtspr MD_RPN, r8 + lis r8, MI_Kp@h /* Set the protection mode */ + mtspr MI_AP, r8 + mtspr MD_AP, r8 + + /* Map another 8 MByte at the IMMR to get the processor + * internal registers (among other things). + */ + mfspr r9, 638 /* Get current IMMR */ + andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */ + + mr r8, r9 /* Create vaddr for TLB */ + ori r8, r8, MD_EVALID /* Mark it valid */ + mtspr MD_EPN, r8 + li r8, MD_PS8MEG /* Set 8M byte page */ + ori r8, r8, MD_SVALID /* Make it valid */ + mtspr MD_TWC, r8 + mr r8, r9 /* Create paddr for TLB */ + ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */ + mtspr MD_RPN, r8 + + /* Since the cache is enabled according to the information we + * just loaded into the TLB, invalidate and enable the caches here. + * We should probably check/set other modes....later. + */ + lis r8, IDC_INVALL@h + mtspr IC_CST, r8 + mtspr DC_CST, r8 + lis r8, IDC_ENABLE@h + mtspr IC_CST, r8 +#ifdef CONFIG_8xx_COPYBACK + mtspr DC_CST, r8 +#else + /* For a debug option, I left this here to easily enable + * the write through cache mode + */ + lis r8, DC_SFWT@h + mtspr DC_CST, r8 + lis r8, IDC_ENABLE@h + mtspr DC_CST, r8 +#endif + blr + + /* * Set up to use a given MMU context. + * r3 is context number, r4 is PGD pointer. * - * The MPC8xx has something that currently happens "automagically." - * Unshared user space address translations are subject to ASID (context) - * match. During each task switch, the ASID is incremented. We can - * guarantee (I hope :-) that no entries currently match this ASID - * because every task will cause at least a TLB entry to be loaded for - * the first instruction and data access, plus the kernel running will - * have displaced several more TLBs. The MMU contains 32 entries for - * each TLB, and there are 16 contexts, so we just need to make sure - * two pages get replaced for every context switch, which currently - * happens. There are other TLB management techniques that I will - * eventually implement, but this is the easiest for now. -- Dan - * - * On the MPC8xx, we place the physical address of the new task - * page directory loaded into the MMU base register, and set the - * ASID compare register with the new "context". + * We place the physical address of the new task page directory loaded + * into the MMU base register, and set the ASID compare register with + * the new "context." */ _GLOBAL(set_context) - /* fetch the pgd from the context_mm array */ - lis r5, context_mm@ha - slwi r6, r3, 2 - add r5, r5, r6 - lwz r5, context_mm@l(r5) /* get the mm */ - lwz r4, MM_PGD(r5) /* get the pgd from the mm */ + +#ifdef CONFIG_BDI_SWITCH + /* Context switch the PTE pointer for the Abatron BDI2000. + * The PGDIR is passed as second argument. + */ + lis r5, KERNELBASE@h + lwz r5, 0xf0(r5) + stw r4, 0x4(r5) +#endif + #ifdef CONFIG_8xx_CPU6 lis r6, cpu6_errata_word@h ori r6, r6, cpu6_errata_word@l @@ -967,7 +863,6 @@ tophys (r4, r4) mtspr M_TWB, r4 /* and pgd */ #endif - tlbia SYNC blr @@ -1012,6 +907,12 @@ .globl cmd_line cmd_line: .space 512 + +/* Room for two PTE table poiners, usually the kernel and current user + * pointer to their respective root page table (pgdir). + */ +abatron_pteptrs: + .space 8 #ifdef CONFIG_8xx_CPU6 .globl cpu6_errata_word diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c --- v2.4.9/linux/arch/ppc/kernel/idle.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/idle.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.idle.c 1.11 05/17/01 18:14:21 cort + * BK Id: SCCS/s.idle.c 1.14 08/15/01 22:43:06 paulus */ /* * Idle daemon for PowerPC. Idle daemon will handle any action @@ -31,12 +31,11 @@ #include #include #include +#include void zero_paged(void); void power_save(void); -void inline htab_reclaim(void); -unsigned long htab_reclaim_on = 0; unsigned long zero_paged_on = 0; unsigned long powersave_nap = 0; @@ -50,27 +49,30 @@ { int do_power_save = 0; - /* only sleep on the 603-family/750 processors */ - switch (_get_PVR() >> 16) { - case 3: /* 603 */ - case 6: /* 603e */ - case 7: /* 603ev */ - case 8: /* 750 */ - case 12: /* 7400 */ - case 0x800c: /* 7410 */ + if (cur_cpu_spec[smp_processor_id()]->cpu_features & CPU_FTR_CAN_DOZE) do_power_save = 1; - } /* endless loop with no priority at all */ current->nice = 20; current->counter = -100; - init_idle(); - for (;;) - { - /*if ( !current->need_resched && zero_paged_on ) - zero_paged();*/ - if (!current->need_resched && htab_reclaim_on) - htab_reclaim(); + init_idle(); + for (;;) { +#ifdef CONFIG_SMP + int oldval; + + if (!do_power_save) { + /* + * Deal with another CPU just having chosen a thread to + * run here: + */ + oldval = xchg(¤t->need_resched, -1); + + if (!oldval) { + while(current->need_resched == -1) + ; /* Do Nothing */ + } + } +#endif if (do_power_save && !current->need_resched) power_save(); @@ -92,68 +94,6 @@ return 0; } -/* - * Mark 'zombie' pte's in the hash table as invalid. - * This improves performance for the hash table reload code - * a bit since we don't consider unused pages as valid. - * -- Cort - */ -PTE *reclaim_ptr = 0; -void inline htab_reclaim(void) -{ -#ifndef CONFIG_8xx -#if 0 - PTE *ptr, *start; - static int dir = 1; -#endif - struct task_struct *p; - unsigned long valid = 0; - extern PTE *Hash, *Hash_end; - extern unsigned long Hash_size; - - /* if we don't have a htab */ - if ( Hash_size == 0 ) - return; -#if 0 - /* find a random place in the htab to start each time */ - start = &Hash[jiffies%(Hash_size/sizeof(PTE))]; - /* go a different direction each time */ - dir *= -1; - for ( ptr = start; - !current->need_resched && (ptr != Hash_end) && (ptr != Hash); - ptr += dir) - { -#else - if ( !reclaim_ptr ) reclaim_ptr = Hash; - while ( !current->need_resched ) - { - reclaim_ptr++; - if ( reclaim_ptr == Hash_end ) reclaim_ptr = Hash; -#endif - if (!reclaim_ptr->v) - continue; - valid = 0; - for_each_task(p) - { - if ( current->need_resched ) - goto out; - /* if this vsid/context is in use */ - if ( (reclaim_ptr->vsid >> 4) == p->mm->context ) - { - valid = 1; - break; - } - } - if ( valid ) - continue; - /* this pte isn't used */ - reclaim_ptr->v = 0; - } -out: - if ( current->need_resched ) printk("need_resched: %lx\n", current->need_resched); -#endif /* CONFIG_8xx */ -} - #if 0 /* * Returns a pre-zero'd page from the list otherwise returns @@ -287,7 +227,7 @@ atomic_inc((atomic_t *)&zero_cache_total); } } -#endif +#endif /* 0 */ void power_save(void) { diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/indirect_pci.c linux/arch/ppc/kernel/indirect_pci.c --- v2.4.9/linux/arch/ppc/kernel/indirect_pci.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/indirect_pci.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.indirect_pci.c 1.7 05/17/01 18:14:21 cort + * BK Id: SCCS/s.indirect_pci.c 1.10 09/08/01 15:47:42 paulus */ /* * Support for indirect PCI bridges. @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.4.9/linux/arch/ppc/kernel/irq.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/irq.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.irq.c 1.30 07/19/01 16:51:32 paulus + * BK Id: SCCS/s.irq.c 1.32 08/24/01 20:07:37 paulus */ /* * arch/ppc/kernel/irq.c @@ -93,6 +93,11 @@ static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES]; extern int mem_init_done; +#if defined(CONFIG_TAU_INT) +extern int tau_interrupts(unsigned long cpu); +extern int tau_initialized; +#endif + void *irq_kmalloc(size_t size, int pri) { unsigned int i; @@ -402,12 +407,14 @@ } len += sprintf(buf+len, "\n"); } -#ifdef CONFIG_TAU - len += sprintf(buf+len, "TAU: "); - for (j = 0; j < smp_num_cpus; j++) - len += sprintf(buf+len, "%10u ", - tau_interrupts(j)); - len += sprintf(buf+len, "\n"); +#ifdef CONFIG_TAU_INT + if (tau_initialized){ + len += sprintf(buf+len, "TAU: "); + for (j = 0; j < smp_num_cpus; j++) + len += sprintf(buf+len, "%10u ", + tau_interrupts(j)); + len += sprintf(buf+len, " PowerPC Thermal Assist (cpu temp)\n"); + } #endif #ifdef CONFIG_SMP /* should this be per processor send/receive? */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/l2cr.S linux/arch/ppc/kernel/l2cr.S --- v2.4.9/linux/arch/ppc/kernel/l2cr.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/l2cr.S Tue Aug 28 06:58:33 2001 @@ -0,0 +1,201 @@ +/* + L2CR functions + Copyright © 1997-1998 by PowerLogix R & D, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + Thur, Dec. 12, 1998. + - First public release, contributed by PowerLogix. + *********** + Sat, Aug. 7, 1999. + - Terry: Made sure code disabled interrupts before running. (Previously + it was assumed interrupts were already disabled). + - Terry: Updated for tentative G4 support. 4MB of memory is now flushed + instead of 2MB. (Prob. only 3 is necessary). + - Terry: Updated for workaround to HID0[DPM] processor bug + during global invalidates. + *********** + Thu, July 13, 2000. + - Terry: Added isync to correct for an errata. + + Author: Terry Greeniaus (tgree@phys.ualberta.ca) + Please e-mail updates to this file to me, thanks! +*/ +#include +#include +#include "ppc_asm.h" + +/* Usage: + + When setting the L2CR register, you must do a few special + things. If you are enabling the cache, you must perform a + global invalidate. If you are disabling the cache, you must + flush the cache contents first. This routine takes care of + doing these things. When first enabling the cache, make sure + you pass in the L2CR you want, as well as passing in the + global invalidate bit set. A global invalidate will only be + performed if the L2I bit is set in applyThis. When enabling + the cache, you should also set the L2E bit in applyThis. If + you want to modify the L2CR contents after the cache has been + enabled, the recommended procedure is to first call + __setL2CR(0) to disable the cache and then call it again with + the new values for L2CR. Examples: + + _setL2CR(0) - disables the cache + _setL2CR(0xB3A04000) - enables my G3 upgrade card: + - L2E set to turn on the cache + - L2SIZ set to 1MB + - L2CLK set to 1:1 + - L2RAM set to pipelined synchronous late-write + - L2I set to perform a global invalidation + - L2OH set to 0.5 nS + - L2DF set because this upgrade card + requires it + + A similar call should work for your card. You need to know + the correct setting for your card and then place them in the + fields I have outlined above. Other fields support optional + features, such as L2DO which caches only data, or L2TS which + causes cache pushes from the L1 cache to go to the L2 cache + instead of to main memory. +*/ +/* + * Summary: this procedure ignores the L2I bit in the value passed in, + * flushes the cache if it was already enabled, always invalidates the + * cache, then enables the cache if the L2E bit is set in the value + * passed in. + * -- paulus. + */ +_GLOBAL(_set_L2CR) + /* Make sure this is a 750 or 7400 chip */ +BEGIN_FTR_SECTION + li r3,-1 + blr +END_FTR_SECTION_IFCLR(CPU_FTR_L2CR) + + /* Turn off interrupts and data relocation. */ + mfmsr r7 /* Save MSR in r7 */ + rlwinm r4,r7,0,17,15 + rlwinm r4,r4,0,28,26 /* Turn off DR bit */ + sync + mtmsr r4 + isync + + /* Get the current enable bit of the L2CR into r4 */ + mfspr r4,L2CR + + /* Tweak some bits */ + rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ + rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ + rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ + + /* Check to see if we need to flush */ + rlwinm. r4,r4,0,0,0 + beq 2f + + /* Flush the cache. First, read the first 4MB of memory (physical) to + * put new data in the cache. (Actually we only need + * the size of the L2 cache plus the size of the L1 cache, but 4MB will + * cover everything just to be safe). + */ + + /**** Might be a good idea to set L2DO here - to prevent instructions + from getting into the cache. But since we invalidate + the next time we enable the cache it doesn't really matter. + ****/ + + lis r4,0x0002 + mtctr r4 + li r4,0 +1: + lwzx r0,r0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + + /* Now, flush the first 4MB of memory */ + lis r4,0x0002 + mtctr r4 + li r4,0 + sync +1: + dcbf r0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + +2: + /* Set up the L2CR configuration bits (and switch L2 off) */ + sync + mtspr L2CR,r3 + sync + + /* Before we perform the global invalidation, we must disable dynamic + * power management via HID0[DPM] to work around a processor bug where + * DPM can possibly interfere with the state machine in the processor + * that invalidates the L2 cache tags. + */ + mfspr r8,HID0 /* Save HID0 in r8 */ + rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ + sync + mtspr HID0,r4 /* Disable DPM */ + sync + + /* Perform a global invalidation */ + oris r3,r3,0x0020 + sync + mtspr L2CR,r3 + sync + isync /* For errata */ + + /* Wait for the invalidation to complete */ +3: mfspr r3,L2CR + rlwinm. r4,r3,0,31,31 + bne 3b + + rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */ + sync + mtspr L2CR,r3 + sync + + /* Restore HID0[DPM] to whatever it was before */ + sync + mtspr 1008,r8 + sync + + /* See if we need to enable the cache */ + cmplwi r5,0 + beq 4f + + /* Enable the cache */ + oris r3,r3,0x8000 + mtspr L2CR,r3 + sync + + /* Restore MSR (restores EE and DR bits to original state) */ +4: SYNC + mtmsr r7 + isync + blr + +_GLOBAL(_get_L2CR) + /* Return the L2CR contents */ + li r3,0 +BEGIN_FTR_SECTION + mfspr r3,L2CR +END_FTR_SECTION_IFSET(CPU_FTR_L2CR) + blr + +/* --- End of PowerLogix code --- + */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/m8260_setup.c linux/arch/ppc/kernel/m8260_setup.c --- v2.4.9/linux/arch/ppc/kernel/m8260_setup.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/m8260_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.m8260_setup.c 1.20 07/18/01 22:56:39 paulus + * BK Id: SCCS/s.m8260_setup.c 1.24 08/20/01 15:25:16 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -52,17 +52,6 @@ unsigned long m8260_get_rtc_time(void); void m8260_calibrate_decr(void); -#if 0 -extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int mackbd_getkeycode(unsigned int scancode); -extern int mackbd_pretranslate(unsigned char scancode, char raw_mode); -extern int mackbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char mackbd_unexpected_up(unsigned char keycode); -extern void mackbd_leds(unsigned char leds); -extern void mackbd_init_hw(void); -#endif - extern unsigned long loops_per_jiffy; unsigned char __res[sizeof(bd_t)]; @@ -72,10 +61,6 @@ extern unsigned long find_available_memory(void); extern void m8260_cpm_reset(void); -void __init adbdev_init(void) -{ -} - void __init m8260_setup_arch(void) { @@ -102,7 +87,7 @@ bd_t *binfo = (bd_t *)__res; int freq, divisor; - freq = (binfo->bi_busfreq * 1000000); + freq = binfo->bi_busfreq; divisor = 4; tb_ticks_per_jiffy = freq / HZ / divisor; tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000); @@ -111,7 +96,8 @@ /* The 8260 has an internal 1-second timer update register that * we should use for this purpose. */ -static uint rtc_time; +static uint rtc_time; + static int m8260_set_rtc_time(unsigned long time) { @@ -145,7 +131,7 @@ startaddr = simple_strtoul(&cmd[10], NULL, 0); } - m8260_gorom((uint)__pa(__res), startaddr); + m8260_gorom((unsigned int)__pa(__res), startaddr); } void @@ -171,9 +157,9 @@ len += sprintf(len+buffer,"core clock\t: %d MHz\n" "CPM clock\t: %d MHz\n" "bus clock\t: %d MHz\n", - bp->bi_intfreq /*/ 1000000*/, - bp->bi_cpmfreq /*/ 1000000*/, - bp->bi_busfreq /*/ 1000000*/); + bp->bi_intfreq / 1000000, + bp->bi_cpmfreq / 1000000, + bp->bi_busfreq / 1000000); return len; } @@ -219,9 +205,21 @@ return binfo->bi_memsize; } +/* Map the IMMR, plus anything else we can cover + * in that upper space according to the memory controller + * chip select mapping. Grab another bunch of space + * below that for stuff we can't cover in the upper. + */ +static void __init +m8260_map_io(void) +{ + io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); + io_block_mapping(0xe0000000, 0xe0000000, 0x10000000, _PAGE_IO); +} + void __init -m8260_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { if ( r3 ) @@ -261,6 +259,7 @@ ppc_md.calibrate_decr = m8260_calibrate_decr; ppc_md.find_end_of_memory = m8260_find_end_of_memory; + ppc_md.setup_io_mappings = m8260_map_io; ppc_md.kbd_setkeycode = NULL; ppc_md.kbd_getkeycode = NULL; @@ -273,51 +272,11 @@ #endif #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = m8xx_ide_insw; - ppc_ide_md.outsw = m8xx_ide_outsw; ppc_ide_md.default_irq = m8xx_ide_default_irq; ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; ppc_ide_md.ide_request_irq = m8xx_ide_request_irq; - - ppc_ide_md.io_base = _IO_BASE; #endif -} - -/* - * Copied from prom.c so I don't have include all of that crap. - * -- Dan - * - * prom_init() is called very early on, before the kernel text - * and data have been mapped to KERNELBASE. At this point the code - * is running at whatever address it has been loaded at, so - * references to extern and static variables must be relocated - * explicitly. The procedure reloc_offset() returns the address - * we're currently running at minus the address we were linked at. - * (Note that strings count as static variables.) - */ -extern unsigned long reloc_offset(void); -#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) - -__init -unsigned long -prom_init(uint r3, uint r4, uint r5, uint r6) -{ - unsigned long offset = reloc_offset(); - unsigned long phys; - extern char __bss_start, _end; - - /* First zero the BSS -- use memset, some arches don't have - * caches on yet */ - memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); - - /* Default */ - phys = offset + KERNELBASE; - - /* We are done. - */ - return phys; } /* Mainly for ksyms. diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c --- v2.4.9/linux/arch/ppc/kernel/m8xx_setup.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/m8xx_setup.c Sat Sep 8 12:39:33 2001 @@ -1,7 +1,6 @@ /* - * BK Id: SCCS/s.m8xx_setup.c 1.23 07/18/01 22:56:39 paulus - */ -/* + * BK Id: SCCS/s.m8xx_setup.c 1.29 08/30/01 09:01:04 trini + * * linux/arch/ppc/kernel/setup.c * * Copyright (C) 1995 Linus Torvalds @@ -172,8 +171,7 @@ machine_restart(NULL); } -/* A place holder for time base interrupts, if they are ever enabled. -*/ +/* A place holder for time base interrupts, if they are ever enabled. */ void timebase_interrupt(int irq, void * dev, struct pt_regs * regs) { printk ("timebase_interrupt()\n"); @@ -188,13 +186,11 @@ bd_t *binfo = (bd_t *)__res; int freq, fp, divisor; - /* Unlock the SCCR. - */ + /* Unlock the SCCR. */ ((volatile immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk = ~KAPWR_KEY; ((volatile immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk = KAPWR_KEY; - /* Force all 8xx processors to use divide by 16 processor clock. - */ + /* Force all 8xx processors to use divide by 16 processor clock. */ ((volatile immap_t *)IMAP_ADDR)->im_clkrst.car_sccr |= 0x02000000; /* Processor frequency is MHz. @@ -224,15 +220,17 @@ */ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = ~KAPWR_KEY; ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = ~KAPWR_KEY; - ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = ~KAPWR_KEY; + ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = ~KAPWR_KEY; ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY; ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY; - ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = KAPWR_KEY; + ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = KAPWR_KEY; - /* Disable the RTC one second and alarm interrupts. - */ + /* Disable the RTC one second and alarm interrupts. */ ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &= ~(RTCSC_SIE | RTCSC_ALE); + /* Enable the RTC */ + ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc |= + (RTCSC_RTF | RTCSC_RTE); /* Enabling the decrementer also enables the timebase interrupts * (or from the other point of view, to get decrementer interrupts @@ -260,15 +258,14 @@ return(0); } -unsigned long +static unsigned long m8xx_get_rtc_time(void) { - /* Get time from the RTC. - */ + /* Get time from the RTC. */ return((unsigned long)(((immap_t *)IMAP_ADDR)->im_sit.sit_rtc)); } -void +static void m8xx_restart(char *cmd) { __volatile__ unsigned char dummy; @@ -288,20 +285,21 @@ while(1); } -void +static void m8xx_power_off(void) { m8xx_restart(NULL); } -void +static void m8xx_halt(void) { m8xx_restart(NULL); } -int m8xx_setup_residual(char *buffer) +static int +m8xx_setup_residual(char *buffer) { int len = 0; bd_t *bp; @@ -322,7 +320,7 @@ * External interrupts can be either edge or level triggered, and * need to be initialized by the appropriate driver. */ -void __init +static void __init m8xx_init_IRQ(void) { int i; @@ -353,32 +351,12 @@ * IDE stuff. */ #ifdef CONFIG_BLK_DEV_MPC8xx_IDE -void ide_interrupt_handler (void *dev) +static void ide_interrupt_handler (void *dev) { } #endif -void -m8xx_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ -#ifdef CONFIG_BLK_DEV_MPC8xx_IDE - ide_insw(port, buf, ns); -#else - _insw_ns((unsigned short *)(port+_IO_BASE), buf, ns); -#endif -} - -void -m8xx_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ -#ifdef CONFIG_BLK_DEV_MPC8xx_IDE - ide_outsw(port, buf, ns); -#else - _outsw_ns((unsigned short *)(port+_IO_BASE), buf, ns); -#endif -} - -int +static int m8xx_ide_default_irq(ide_ioreg_t base) { #ifdef CONFIG_BLK_DEV_MPC8xx_IDE @@ -391,13 +369,13 @@ #endif } -ide_ioreg_t +static ide_ioreg_t m8xx_ide_default_io_base(int index) { return index; } -int +static int m8xx_ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, @@ -412,8 +390,9 @@ * * See include/linux/ide.h for definition of hw_regs_t (p, base) */ -void m8xx_ide_init_hwif_ports(hw_regs_t *hw, - ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) +static void +m8xx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) { int i; #ifdef CONFIG_BLK_DEV_MPC8xx_IDE @@ -479,7 +458,7 @@ # endif /* CONFIG_SPD823TS, CONFIG_IVMS8 */ for (i = 0; i < IDE_NR_PORTS; ++i) { - *p++ = base + ioport_dsc[data_port].reg_off[i]; + *p++ = base + ioport_dsc[data_port].reg_off[i] - _IO_BASE; } if (irq) { @@ -585,7 +564,8 @@ * functions in the image just to get prom_init, all we really need right * now is the initialization of the physical memory region. */ -unsigned long __init m8xx_find_end_of_memory(void) +static unsigned long __init +m8xx_find_end_of_memory(void) { bd_t *binfo; extern unsigned char __res[]; @@ -595,11 +575,47 @@ return binfo->bi_memsize; } -void __init -m8xx_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +/* + * Now map in some of the I/O space that is generically needed + * or shared with multiple devices. + * All of this fits into the same 4Mbyte region, so it only + * requires one page table page. (or at least it used to -- paulus) + */ +static void __init +m8xx_map_io(void) { + io_block_mapping(IMAP_ADDR, IMAP_ADDR, IMAP_SIZE, _PAGE_IO); +#ifdef CONFIG_MBX + io_block_mapping(NVRAM_ADDR, NVRAM_ADDR, NVRAM_SIZE, _PAGE_IO); + io_block_mapping(MBX_CSR_ADDR, MBX_CSR_ADDR, MBX_CSR_SIZE, _PAGE_IO); + io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO); + + /* Map some of the PCI/ISA I/O space to get the IDE interface. + */ + io_block_mapping(PCI_ISA_IO_ADDR, PCI_ISA_IO_ADDR, 0x4000, _PAGE_IO); + io_block_mapping(PCI_IDE_ADDR, PCI_IDE_ADDR, 0x4000, _PAGE_IO); +#endif +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) + io_block_mapping(RPX_CSR_ADDR, RPX_CSR_ADDR, RPX_CSR_SIZE, _PAGE_IO); +#if !defined(CONFIG_PCI) + io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO); +#endif +#endif +#ifdef CONFIG_HTDMSOUND + io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO); +#endif +#ifdef CONFIG_FADS + io_block_mapping(BCSR_ADDR, BCSR_ADDR, BCSR_SIZE, _PAGE_IO); +#endif +#ifdef CONFIG_PCI + io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO); +#endif +} +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ if ( r3 ) memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); @@ -617,8 +633,7 @@ #endif /* CONFIG_BLK_DEV_INITRD */ /* take care of cmd line */ if ( r6 ) - { - + { *(char *)(r7+KERNELBASE) = 0; strcpy(cmd_line, (char *)(r6+KERNELBASE)); } @@ -641,6 +656,7 @@ ppc_md.calibrate_decr = m8xx_calibrate_decr; ppc_md.find_end_of_memory = m8xx_find_end_of_memory; + ppc_md.setup_io_mappings = m8xx_map_io; ppc_md.kbd_setkeycode = NULL; ppc_md.kbd_getkeycode = NULL; @@ -653,13 +669,8 @@ #endif #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = m8xx_ide_insw; - ppc_ide_md.outsw = m8xx_ide_outsw; ppc_ide_md.default_irq = m8xx_ide_default_irq; ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; #endif } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.4.9/linux/arch/ppc/kernel/misc.S Sun Aug 12 13:27:58 2001 +++ linux/arch/ppc/kernel/misc.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.misc.S 1.21 07/07/01 17:00:08 paulus + * BK Id: SCCS/s.misc.S 1.28 08/24/01 20:07:37 paulus */ /* * This file contains miscellaneous low-level functions. @@ -22,6 +22,7 @@ #include #include #include +#include #include "ppc_asm.h" .text @@ -49,6 +50,97 @@ mtlr r0 blr +/* + * identify_cpu, + * called with r3 = data offset and r4 = CPU number + * doesn't change r3 + */ +_GLOBAL(identify_cpu) + addis r8,r3,cpu_specs@ha + addi r8,r8,cpu_specs@l + mfpvr r7 +1: + lwz r5,CPU_SPEC_PVR_MASK(r8) + and r5,r5,r7 + lwz r6,CPU_SPEC_PVR_VALUE(r8) + cmplw 0,r6,r5 + beq 1f + addi r8,r8,CPU_SPEC_ENTRY_SIZE + b 1b +1: + addis r6,r3,cur_cpu_spec@ha + addi r6,r6,cur_cpu_spec@l + slwi r4,r4,2 + sub r8,r8,r3 + stwx r8,r4,r6 + blr + +/* + * do_cpu_ftr_fixups - goes through the list of CPU feature fixups + * and writes nop's over sections of code that don't apply for this cpu. + * r3 = data offset (not changed) + */ +_GLOBAL(do_cpu_ftr_fixups) + /* Get CPU 0 features */ + addis r6,r3,cur_cpu_spec@ha + addi r6,r6,cur_cpu_spec@l + lwz r4,0(r6) + add r4,r4,r3 + lwz r4,CPU_SPEC_FEATURES(r4) + + /* Get the fixup table */ + addis r6,r3,__start___ftr_fixup@ha + addi r6,r6,__start___ftr_fixup@l + addis r7,r3,__stop___ftr_fixup@ha + addi r7,r7,__stop___ftr_fixup@l + + /* Do the fixup */ +1: cmplw 0,r6,r7 + bgelr + addi r6,r6,16 + lwz r8,-16(r6) /* mask */ + and r8,r8,r4 + lwz r9,-12(r6) /* value */ + cmplw 0,r8,r9 + beq 1b + lwz r8,-8(r6) /* section begin */ + lwz r9,-4(r6) /* section end */ + subf. r9,r8,r9 + beq 1b + /* write nops over the section of code */ + /* todo: if large section, add a branch at the start of it */ + srwi r9,r9,2 + mtctr r9 + add r8,r8,r3 + lis r0,0x60000000@h /* nop */ +3: stw r0,0(r8) + andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l + beq 2f + dcbst 0,r8 /* suboptimal, but simpler */ + sync + icbi 0,r8 +2: addi r8,r8,4 + bdnz 3b + sync /* additional sync needed on g4 */ + isync + b 1b + +/* + * call_setup_cpu - call the setup_cpu function for this cpu + * r3 = data offset, r24 = cpu number + */ +_GLOBAL(call_setup_cpu) + addis r5,r3,cur_cpu_spec@ha + addi r5,r5,cur_cpu_spec@l + slwi r4,r24,2 + lwzx r5,r4,r5 + add r5,r5,r3 + lwz r6,CPU_SPEC_SETUP(r5) + add r6,r6,r3 + mtctr r6 + mr r3,r24 + bctr + /* void __save_flags_ptr(unsigned long *flags) */ _GLOBAL(__save_flags_ptr) mfmsr r4 @@ -185,7 +277,7 @@ _GLOBAL(_nmask_and_or_msr) mfmsr r0 /* Get current msr */ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */ - or r0,r0,r4 /* Or on the bits in r4 (second parm) */ + or r0,r0,r4 /* Or on the bits in r4 (second parm) */ SYNC /* Some chip revs have problems here... */ mtmsr r0 /* Update machine state */ isync @@ -216,8 +308,7 @@ tlbia sync #ifdef CONFIG_SMP - tlbsync - sync + TLBSYNC li r0,0 stw r0,0(r9) /* clear hash_table_lock */ mtmsr r10 @@ -249,8 +340,7 @@ tlbie r3 sync #ifdef CONFIG_SMP - tlbsync - sync + TLBSYNC li r0,0 stw r0,0(r9) /* clear hash_table_lock */ mtmsr r10 @@ -314,26 +404,70 @@ sync /* additional sync needed on g4 */ isync blr +/* + * Write any modified data cache blocks out to memory. + * Does not invalidate the corresponding cache lines (especially for + * any corresponding instruction cache). + * + * clean_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(clean_dcache_range) + li r5,CACHE_LINE_SIZE-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,LG_CACHE_LINE_SIZE + beqlr + mtctr r4 + +1: dcbst 0,r3 + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + sync /* wait for dcbst's to get to ram */ + blr /* - * Like above, but only do the D-cache. + * Write any modified data cache blocks out to memory + * and invalidate the corresponding instruction cache blocks. * * flush_dcache_range(unsigned long start, unsigned long stop) */ _GLOBAL(flush_dcache_range) - li r5,CACHE_LINE_SIZE-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,LG_CACHE_LINE_SIZE - beqlr - mtctr r4 - -1: dcbst 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - sync /* wait for dcbst's to get to ram */ - blr + li r5,CACHE_LINE_SIZE-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,LG_CACHE_LINE_SIZE + beqlr + mtctr r4 + +1: dcbf 0,r3 + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + sync /* wait for dcbst's to get to ram */ + blr + +/* + * Like above, but invalidate the D-cache. This is used by the 8xx + * to invalidate the cache so the PPC core doesn't get stale data + * from the CPM (no cache snooping here :-). + * + * invalidate_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(invalidate_dcache_range) + li r5,CACHE_LINE_SIZE-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,LG_CACHE_LINE_SIZE + beqlr + mtctr r4 + +1: dcbi 0,r3 + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + sync /* wait for dcbi's to get to ram */ + blr /* * Flush a particular page from the data cache to RAM. @@ -481,94 +615,9 @@ blr /* - * Try to acquire a spinlock. - * Only does the stwcx. if the load returned 0 - the Programming - * Environments Manual suggests not doing unnecessary stcwx.'s - * since they may inhibit forward progress by other CPUs in getting - * a lock. - */ -_GLOBAL(__spin_trylock) - mr r4,r3 - eieio /* prevent reordering of stores */ - li r5,-1 - lwarx r3,0,r4 /* fetch old value, establish reservation */ - cmpwi 0,r3,0 /* is it 0? */ - bnelr- /* return failure if not */ - stwcx. r5,0,r4 /* try to update with new value */ - bne- 1f /* if we failed */ - eieio /* prevent reordering of stores */ - blr -1: li r3,1 /* return non-zero for failure */ - blr - -/* - * Atomic add/sub/inc/dec operations - * - * void atomic_add(int c, int *v) - * void atomic_sub(int c, int *v) - * void atomic_inc(int *v) - * void atomic_dec(int *v) - * int atomic_dec_and_test(int *v) - * int atomic_inc_return(int *v) - * int atomic_dec_return(int *v) * void atomic_clear_mask(atomic_t mask, atomic_t *addr) * void atomic_set_mask(atomic_t mask, atomic_t *addr); */ -#if 0 /* now inline - paulus */ -_GLOBAL(atomic_add) -10: lwarx r5,0,r4 /* Fetch old value & reserve */ - add r5,r5,r3 /* Perform 'add' operation */ - stwcx. r5,0,r4 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - blr -_GLOBAL(atomic_add_return) -10: lwarx r5,0,r4 /* Fetch old value & reserve */ - add r5,r5,r3 /* Perform 'add' operation */ - stwcx. r5,0,r4 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - mr r3,r5 - blr -_GLOBAL(atomic_sub) -10: lwarx r5,0,r4 /* Fetch old value & reserve */ - sub r5,r5,r3 /* Perform 'add' operation */ - stwcx. r5,0,r4 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - blr -_GLOBAL(atomic_inc) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - addi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - blr -_GLOBAL(atomic_inc_return) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - addi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - mr r3,r5 /* Return new value */ - blr -_GLOBAL(atomic_dec) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - subi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - blr -_GLOBAL(atomic_dec_return) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - subi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - mr r3,r5 /* Return new value */ - blr -_GLOBAL(atomic_dec_and_test) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - subi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - cntlzw r3,r5 - srwi r3,r3,5 - blr -#endif /* 0 */ _GLOBAL(atomic_clear_mask) 10: lwarx r5,0,r4 andc r5,r5,r3 @@ -768,281 +817,7 @@ _GLOBAL(_get_SP) mr r3,r1 /* Close enough */ blr - -#if 0 -/* isn't it just easier to use the mtspr/mfspr inline macros?? --Troy */ -_GLOBAL(_get_THRM1) - mfspr r3,THRM1 - blr - -_GLOBAL(_get_THRM2) - mfspr r3,THRM2 - blr - -_GLOBAL(_get_THRM3) - mfspr r3,THRM3 - blr - -_GLOBAL(_set_THRM1) - mtspr THRM1,r3 - blr - -_GLOBAL(_set_THRM2) - mtspr THRM2,r3 - blr - -_GLOBAL(_set_THRM3) - mtspr THRM3,r3 - blr -#endif - -_GLOBAL(_get_PVR) - mfspr r3,PVR - blr - -#ifdef CONFIG_8xx -_GLOBAL(_get_IMMR) - mfspr r3, 638 - blr -#endif -_GLOBAL(_get_HID0) - mfspr r3,HID0 - blr - -_GLOBAL(_set_HID0) - sync - mtspr HID0, r3 - SYNC /* Handle errata in some cases */ - blr - -_GLOBAL(_get_ICTC) - mfspr r3,ICTC - blr - -_GLOBAL(_set_ICTC) - mtspr ICTC,r3 - blr - -/* - L2CR functions - Copyright © 1997-1998 by PowerLogix R & D, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - Thur, Dec. 12, 1998. - - First public release, contributed by PowerLogix. - *********** - Sat, Aug. 7, 1999. - - Terry: Made sure code disabled interrupts before running. (Previously - it was assumed interrupts were already disabled). - - Terry: Updated for tentative G4 support. 4MB of memory is now flushed - instead of 2MB. (Prob. only 3 is necessary). - - Terry: Updated for workaround to HID0[DPM] processor bug - during global invalidates. - *********** - Thu, July 13, 2000. - - Terry: Added isync to correct for an errata. - - Author: Terry Greeniaus (tgree@phys.ualberta.ca) - Please e-mail updates to this file to me, thanks! -*/ -/* Usage: - - When setting the L2CR register, you must do a few special - things. If you are enabling the cache, you must perform a - global invalidate. If you are disabling the cache, you must - flush the cache contents first. This routine takes care of - doing these things. When first enabling the cache, make sure - you pass in the L2CR you want, as well as passing in the - global invalidate bit set. A global invalidate will only be - performed if the L2I bit is set in applyThis. When enabling - the cache, you should also set the L2E bit in applyThis. If - you want to modify the L2CR contents after the cache has been - enabled, the recommended procedure is to first call - __setL2CR(0) to disable the cache and then call it again with - the new values for L2CR. Examples: - - _setL2CR(0) - disables the cache - _setL2CR(0xB3A04000) - enables my G3 upgrade card: - - L2E set to turn on the cache - - L2SIZ set to 1MB - - L2CLK set to 1:1 - - L2RAM set to pipelined synchronous late-write - - L2I set to perform a global invalidation - - L2OH set to 0.5 nS - - L2DF set because this upgrade card - requires it - - A similar call should work for your card. You need to know - the correct setting for your card and then place them in the - fields I have outlined above. Other fields support optional - features, such as L2DO which caches only data, or L2TS which - causes cache pushes from the L1 cache to go to the L2 cache - instead of to main memory. -*/ -/* - * Summary: this procedure ignores the L2I bit in the value passed in, - * flushes the cache if it was already enabled, always invalidates the - * cache, then enables the cache if the L2E bit is set in the value - * passed in. - * -- paulus. - */ -_GLOBAL(_set_L2CR) - /* Make sure this is a 750 or 7400 chip */ - mfspr r4,PVR - rlwinm r4,r4,16,16,31 - cmpwi r4,0x0008 - cmpwi cr1,r4,0x000c - cror 2,2,4*cr1+2 - bne 99f - - /* Turn off interrupts and data relocation. */ - mfmsr r7 /* Save MSR in r7 */ - rlwinm r4,r7,0,17,15 - rlwinm r4,r4,0,28,26 /* Turn off DR bit */ - sync - mtmsr r4 - isync - - /* Get the current enable bit of the L2CR into r4 */ - mfspr r4,L2CR - - /* Tweak some bits */ - rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ - rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ - rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ - - /* Check to see if we need to flush */ - rlwinm. r4,r4,0,0,0 - beq 2f - - /* Flush the cache. First, read the first 4MB of memory (physical) to - * put new data in the cache. (Actually we only need - * the size of the L2 cache plus the size of the L1 cache, but 4MB will - * cover everything just to be safe). - */ - - /**** Might be a good idea to set L2DO here - to prevent instructions - from getting into the cache. But since we invalidate - the next time we enable the cache it doesn't really matter. - ****/ - - lis r4,0x0002 - mtctr r4 - li r4,0 -1: - lwzx r0,r0,r4 - addi r4,r4,32 /* Go to start of next cache line */ - bdnz 1b - - /* Now, flush the first 4MB of memory */ - lis r4,0x0002 - mtctr r4 - li r4,0 - sync -1: - dcbf r0,r4 - addi r4,r4,32 /* Go to start of next cache line */ - bdnz 1b - -2: - /* Set up the L2CR configuration bits (and switch L2 off) */ - sync - mtspr L2CR,r3 - sync - - /* Before we perform the global invalidation, we must disable dynamic - * power management via HID0[DPM] to work around a processor bug where - * DPM can possibly interfere with the state machine in the processor - * that invalidates the L2 cache tags. - */ - mfspr r8,HID0 /* Save HID0 in r8 */ - rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ - sync - mtspr HID0,r4 /* Disable DPM */ - sync - - /* Perform a global invalidation */ - oris r3,r3,0x0020 - sync - mtspr L2CR,r3 - sync - isync /* For errata */ - - /* Wait for the invalidation to complete */ -3: mfspr r3,L2CR - rlwinm. r4,r3,0,31,31 - bne 3b - - rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */ - sync - mtspr L2CR,r3 - sync - - /* Restore HID0[DPM] to whatever it was before */ - sync - mtspr 1008,r8 - sync - - /* See if we need to enable the cache */ - cmplwi r5,0 - beq 4f - - /* Enable the cache */ - oris r3,r3,0x8000 - mtspr L2CR,r3 - sync - - /* Restore MSR (restores EE and DR bits to original state) */ -4: SYNC - mtmsr r7 - isync - blr - -99: li r3,-1 - blr - -_GLOBAL(_get_L2CR) - /* Make sure this is a 750 chip */ - mfspr r3,PVR - srwi r3,r3,16 - cmpwi r3,0x0008 - cmpwi cr1,r3,0x000c - li r3,0 - cror 2,2,4*cr1+2 - bnelr - /* Return the L2CR contents */ - mfspr r3,L2CR - blr - -/* --- End of PowerLogix code --- - */ - -/* -_GLOBAL(_get_L2CR) - mfspr r3,L2CR - blr - -_GLOBAL(_set_L2CR) - mtspr L2CR,r3 - blr - -*/ - /* * These are used in the alignment trap handler when emulating * single-precision loads and stores. @@ -1099,7 +874,7 @@ mr r3,r4 /* load arg and call fn */ blrl li r0,__NR_exit /* exit after child exits */ - li r3,0 + li r3,0 sc /* @@ -1279,7 +1054,7 @@ .long sys_setfsuid .long sys_setfsgid .long sys_llseek /* 140 */ - .long sys_getdents + .long sys_getdents .long ppc_select .long sys_flock .long sys_msync diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c --- v2.4.9/linux/arch/ppc/kernel/mk_defs.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/mk_defs.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.mk_defs.c 1.8 06/28/01 15:50:16 paulus + * BK Id: SCCS/s.mk_defs.c 1.11 08/19/01 22:43:23 paulus */ /* * This program is used to generate definitions needed by @@ -26,6 +26,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n#define\t" #sym "\t%0" : : "i" (val)) @@ -118,5 +119,14 @@ DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); DEFINE(CLONE_VM, CLONE_VM); DEFINE(MM_PGD, offsetof(struct mm_struct, pgd)); + + /* About the CPU features table */ + DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); + DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); + DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); + DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); + DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); + + DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); return 0; } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/oak_setup.c linux/arch/ppc/kernel/oak_setup.c --- v2.4.9/linux/arch/ppc/kernel/oak_setup.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/oak_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.oak_setup.c 1.5 05/17/01 18:14:21 cort + * BK Id: SCCS/s.oak_setup.c 1.8 08/15/01 21:48:38 paulus */ /* * @@ -74,8 +74,8 @@ * */ void __init -oak_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { /* * If we were passed in a board information, copy it into the diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c --- v2.4.9/linux/arch/ppc/kernel/open_pic.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/open_pic.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.open_pic.c 1.20 05/17/01 18:14:21 cort + * BK Id: SCCS/s.open_pic.c 1.28 09/08/01 15:47:42 paulus */ /* * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling @@ -17,11 +17,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "local_irq.h" #include "open_pic.h" @@ -47,8 +49,6 @@ /* Global Operations */ static void openpic_disable_8259_pass_through(void); -static u_int openpic_irq(void); -static void openpic_eoi(void); static void openpic_set_priority(u_int pri); static void openpic_set_spurious(u_int vector); @@ -73,8 +73,8 @@ * These functions are not used but the code is kept here * for completeness and future reference. */ -#ifdef notused static void openpic_reset(void); +#ifdef notused static void openpic_enable_8259_pass_through(void); static u_int openpic_get_priority(void); static u_int openpic_get_spurious(void); @@ -412,13 +412,16 @@ #endif } -#ifdef notused static void openpic_reset(void) { openpic_setfield(&OpenPIC->Global.Global_Configuration0, OPENPIC_CONFIG_RESET); + while (openpic_readfield(&OpenPIC->Global.Global_Configuration0, + OPENPIC_CONFIG_RESET)) + mb(); } +#ifdef notused static void openpic_enable_8259_pass_through(void) { openpic_clearfield(&OpenPIC->Global.Global_Configuration0, @@ -435,7 +438,7 @@ /* * Find out the current interrupt */ -static u_int openpic_irq(void) +u_int openpic_irq(void) { u_int vec; DECL_THIS_CPU; @@ -446,7 +449,7 @@ return vec; } -static void openpic_eoi(void) +void openpic_eoi(void) { DECL_THIS_CPU; @@ -518,6 +521,8 @@ physmask(cpumask)); } +static spinlock_t openpic_setup_lock = SPIN_LOCK_UNLOCKED; + #ifdef CONFIG_SMP /* * Initialize an interprocessor interrupt (and disable it) @@ -583,7 +588,6 @@ * Get IPI's working and start taking interrupts. * -- Cort */ -static spinlock_t openpic_setup_lock __initdata = SPIN_LOCK_UNLOCKED; void __init do_openpic_setup_cpu(void) { @@ -802,11 +806,87 @@ #endif openpic_eoi(); } - if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset) { + if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset) irq = -1; - /* That's not SMP safe ... but who cares ? */ - ppc_spurious_interrupts++; - } return irq; } +#ifdef CONFIG_SMP +void +smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) +{ + /* make sure we're sending something that translates to an IPI */ + if (msg > 0x3) { + printk("SMP %d: smp_message_pass: unknown msg %d\n", + smp_processor_id(), msg); + return; + } + switch (target) { + case MSG_ALL: + openpic_cause_IPI(msg, 0xffffffff); + break; + case MSG_ALL_BUT_SELF: + openpic_cause_IPI(msg, + 0xffffffff & ~(1 << smp_processor_id())); + break; + default: + openpic_cause_IPI(msg, 1<Processor[i].Current_Task_Priority); + openpic_writefield(&OpenPIC->Processor[i].Current_Task_Priority, + OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf); + } + + for (i=0; iGlobal.IPI_Vector_Priority(i)); + for (i=0; iSource[i].Vector_Priority) + & ~OPENPIC_ACTIVITY; + save_irq_src_dest[i] = openpic_read(&OpenPIC->Source[i].Destination); + } + spin_unlock_irqrestore(&openpic_setup_lock, flags); +} + +void __pmac +openpic_sleep_restore_intrs(void) +{ + int i; + unsigned long flags; + + spin_lock_irqsave(&openpic_setup_lock, flags); + + openpic_reset(); + + for (i=0; iGlobal.IPI_Vector_Priority(i), save_ipi_vp[i]); + for (i=0; iSource[i].Vector_Priority, save_irq_src_vp[i]); + openpic_write(&OpenPIC->Source[i].Destination, save_irq_src_dest[i]); + } + openpic_set_spurious(OPENPIC_VEC_SPURIOUS+open_pic_irq_offset); + openpic_disable_8259_pass_through(); + for (i=0; iProcessor[i].Current_Task_Priority, save_cpu_task_pri[i]); + + spin_unlock_irqrestore(&openpic_setup_lock, flags); +} +#endif /* CONFIG_PMAC_PBOOK */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h --- v2.4.9/linux/arch/ppc/kernel/open_pic.h Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/open_pic.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.open_pic.h 1.8 05/17/01 18:14:21 cort + * BK Id: SCCS/s.open_pic.h 1.12 08/20/01 22:33:28 paulus */ /* * arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling @@ -19,6 +19,14 @@ #define OPENPIC_SIZE 0x40000 +/* + * Non-offset'ed vector numbers + */ + +#define OPENPIC_VEC_TIMER 64 /* and up */ +#define OPENPIC_VEC_IPI 72 /* and up */ +#define OPENPIC_VEC_SPURIOUS 127 + /* OpenPIC IRQ controller structure */ extern struct hw_interrupt_type open_pic; @@ -33,16 +41,28 @@ /* Exported functions */ extern void openpic_init(int, int, unsigned char *, int); +extern u_int openpic_irq(void); +extern void openpic_eoi(void); extern void openpic_request_IPIs(void); extern void do_openpic_setup_cpu(void); extern int openpic_get_irq(struct pt_regs *regs); extern void openpic_init_processor(u_int cpumask); extern void openpic_setup_ISU(int isu_num, unsigned long addr); extern void openpic_cause_IPI(u_int ipi, u_int cpumask); +extern void smp_openpic_message_pass(int target, int msg, unsigned long data, + int wait); extern inline int openpic_to_irq(int irq) { - return irq += NUM_8259_INTERRUPTS; + /* IRQ 0 usually means 'disabled'.. don't mess with it + * exceptions to this (sandpoint maybe?) + * shouldn't use openpic_to_irq + */ + if (irq != 0){ + return irq += NUM_8259_INTERRUPTS; + } else { + return 0; + } } /*extern int open_pic_irq_offset;*/ #endif /* _PPC_KERNEL_OPEN_PIC_H */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/open_pic_defs.h linux/arch/ppc/kernel/open_pic_defs.h --- v2.4.9/linux/arch/ppc/kernel/open_pic_defs.h Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/open_pic_defs.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.open_pic_defs.h 1.7 05/17/01 18:14:21 cort + * BK Id: SCCS/s.open_pic_defs.h 1.8 08/20/01 22:33:28 paulus */ /* * linux/openpic.h -- OpenPIC definitions @@ -44,14 +44,6 @@ #define OPENPIC_NUM_PRI 16 #define OPENPIC_NUM_VECTORS 256 - - /* - * Non-offset'ed vector numbers - */ - -#define OPENPIC_VEC_TIMER 64 /* and up */ -#define OPENPIC_VEC_IPI 72 /* and up */ -#define OPENPIC_VEC_SPURIOUS 127 /* diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_backlight.c linux/arch/ppc/kernel/pmac_backlight.c --- v2.4.9/linux/arch/ppc/kernel/pmac_backlight.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/pmac_backlight.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_backlight.c 1.5 05/17/01 18:14:21 cort + * BK Id: SCCS/s.pmac_backlight.c 1.8 09/08/01 15:47:42 paulus */ /* * Miscellaneous procedures for dealing with the PowerMac hardware. @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_nvram.c linux/arch/ppc/kernel/pmac_nvram.c --- v2.4.9/linux/arch/ppc/kernel/pmac_nvram.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/pmac_nvram.c Sat Sep 8 12:38:41 2001 @@ -1,17 +1,18 @@ /* - * BK Id: SCCS/s.pmac_nvram.c 1.10 08/08/01 16:23:35 paulus + * BK Id: SCCS/s.pmac_nvram.c 1.15 09/08/01 15:47:42 paulus */ /* * Miscellaneous procedures for dealing with the PowerMac hardware. */ #include +#include #include #include #include #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c --- v2.4.9/linux/arch/ppc/kernel/pmac_pci.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/pmac_pci.c Sat Sep 8 12:38:41 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_pci.c 1.22 08/08/01 16:35:43 paulus + * BK Id: SCCS/s.pmac_pci.c 1.27 09/08/01 15:47:42 paulus */ /* * Support for PCI bridges found on Power Macintoshes. @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include @@ -528,6 +528,7 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) { struct device_node* node; + int updatecfg = 0; node = pci_device_to_OF_node(dev); @@ -538,14 +539,40 @@ && dev->device == PCI_DEVICE_ID_APPLE_KL_USB && !node) return -EINVAL; - /* Firewire was disabled after PCI probe, the driver is claiming it, - * so we must re-enable it now, at least until the driver can do it - * itself. + /* Firewire & GMAC were disabled after PCI probe, the driver is + * claiming them, we must re-enable them now. */ if (node && !strcmp(node->name, "firewire") && - device_is_compatible(node, "pci106b,18")) { + (device_is_compatible(node, "pci106b,18") || + device_is_compatible(node, "pci106b,30"))) { feature_set_firewire_cable_power(node, 1); feature_set_firewire_power(node, 1); + updatecfg = 1; + } + if (node && !strcmp(node->name, "ethernet") && + device_is_compatible(node, "gmac")) { + feature_set_gmac_power(node, 1); + updatecfg = 1; + } + + if (updatecfg) { + u16 cmd; + + /* + * Make sure PCI is correctly configured + * + * We use old pci_bios versions of the function since, by + * default, gmac is not powered up, and so will be absent + * from the kernel initial PCI lookup. + * + * Should be replaced by 2.4 new PCI mecanisms and really + * regiser the device. + */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; + pci_write_config_word(dev, PCI_COMMAND, cmd); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); } return 0; @@ -580,7 +607,8 @@ nd = find_devices("firewire"); while (nd) { - if (nd->parent && device_is_compatible(nd, "pci106b,18") + if (nd->parent && (device_is_compatible(nd, "pci106b,18") || + device_is_compatible(nd, "pci106b,30")) && device_is_compatible(nd->parent, "uni-north")) { feature_set_firewire_power(nd, 0); feature_set_firewire_cable_power(nd, 0); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c --- v2.4.9/linux/arch/ppc/kernel/pmac_pic.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/pmac_pic.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_pic.c 1.14 05/17/01 18:14:21 cort + * BK Id: SCCS/s.pmac_pic.c 1.20 09/08/01 15:47:42 paulus */ #include #include @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -35,7 +35,6 @@ static int max_irqs; static int max_real_irqs; -static int pmac_has_openpic; spinlock_t pmac_pic_lock = SPIN_LOCK_UNLOCKED; @@ -291,17 +290,16 @@ * controller. If we find this second ohare, set it up and fix the * interrupt value in the device tree for the ethernet chip. */ -static void __init enable_second_ohare(void) +static int __init enable_second_ohare(void) { unsigned char bus, devfn; unsigned short cmd; unsigned long addr; - int second_irq; struct device_node *irqctrler = find_devices("pci106b,7"); struct device_node *ether; if (irqctrler == NULL || irqctrler->n_addrs <= 0) - return; + return -1; addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); max_irqs = 64; @@ -317,11 +315,6 @@ } } - second_irq = irqctrler->intrs[0].line; - printk(KERN_INFO "irq: secondary controller on irq %d\n", second_irq); - request_irq(second_irq, gatwick_action, SA_INTERRUPT, - "interrupt cascade", 0 ); - /* Fix interrupt for the modem/ethernet combo controller. The number in the device tree (27) is bogus (correct for the ethernet-only board but not the combo ethernet/modem board). @@ -333,6 +326,9 @@ printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", ether->intrs[0].line); } + + /* Return the interrupt number of the cascade */ + return irqctrler->intrs[0].line; } void __init @@ -341,8 +337,8 @@ int i; struct device_node *irqctrler; unsigned long addr; - int second_irq = -999; - + int irq_cascade = -1; + /* We first try to detect Apple's new Core99 chipset, since mac-io * is quite different on those machines and contains an IBM MPIC2. */ @@ -368,7 +364,6 @@ OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, irqctrler->addrs[0].size); openpic_init(1, 0, 0, nmi_irq); - pmac_has_openpic = 1; #ifdef CONFIG_XMON if (nmi_irq >= 0) request_irq(nmi_irq, xmon_irq, 0, @@ -418,6 +413,9 @@ for (i = 2; i < 4; ++i) pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) (addr + (4 - i) * 0x10); + irq_cascade = irqctrler->intrs[0].line; + if (device_is_compatible(irqctrler, "gatwick")) + pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); } } else { /* older powermacs have a GC (grand central) or ohare at @@ -430,23 +428,20 @@ ohare chip, on the combo ethernet/modem card */ if (machine_is_compatible("AAPL,3400/2400") || machine_is_compatible("AAPL,3500")) - enable_second_ohare(); + irq_cascade = enable_second_ohare(); /* disable all interrupts in all controllers */ for (i = 0; i * 32 < max_irqs; ++i) out_le32(&pmac_irq_hw[i]->enable, 0); /* get interrupt line of secondary interrupt controller */ - if (irqctrler) { - second_irq = irqctrler->intrs[0].line; + if (irq_cascade >= 0) { printk(KERN_INFO "irq: secondary controller on irq %d\n", - (int)second_irq); - if (device_is_compatible(irqctrler, "gatwick")) - pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); + (int)irq_cascade); for ( i = max_real_irqs ; i < max_irqs ; i++ ) irq_desc[i].handler = &gatwick_pic; - request_irq( second_irq, gatwick_action, SA_INTERRUPT, - "gatwick cascade", 0 ); + request_irq( irq_cascade, gatwick_action, SA_INTERRUPT, + "cascade", 0 ); } printk("System has %d possible interrupts\n", max_irqs); if (max_irqs != max_real_irqs) @@ -467,14 +462,15 @@ */ unsigned int sleep_save_mask[2]; -void -sleep_save_intrs(int viaint) +void __pmac +pmac_sleep_save_intrs(int viaint) { sleep_save_mask[0] = ppc_cached_irq_mask[0]; sleep_save_mask[1] = ppc_cached_irq_mask[1]; ppc_cached_irq_mask[0] = 0; ppc_cached_irq_mask[1] = 0; - set_bit(viaint, ppc_cached_irq_mask); + if (viaint > 0) + set_bit(viaint, ppc_cached_irq_mask); out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]); if (max_real_irqs > 32) out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]); @@ -484,8 +480,8 @@ (void)in_le32(&pmac_irq_hw[0]->enable); } -void -sleep_restore_intrs(void) +void __pmac +pmac_sleep_restore_intrs(void) { int i; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_pic.h linux/arch/ppc/kernel/pmac_pic.h --- v2.4.9/linux/arch/ppc/kernel/pmac_pic.h Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/pmac_pic.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_pic.h 1.5 05/17/01 18:14:21 cort + * BK Id: SCCS/s.pmac_pic.h 1.9 08/19/01 22:23:04 paulus */ #ifndef _PPC_KERNEL_PMAC_PIC_H #define _PPC_KERNEL_PMAC_PIC_H @@ -10,6 +10,5 @@ void pmac_pic_init(void); int pmac_get_irq(struct pt_regs *regs); -void pmac_post_irq(int); #endif /* _PPC_KERNEL_PMAC_PIC_H */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c --- v2.4.9/linux/arch/ppc/kernel/pmac_setup.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/pmac_setup.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_setup.c 1.24 07/06/01 14:49:51 trini + * BK Id: SCCS/s.pmac_setup.c 1.39 09/08/01 15:47:42 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -51,7 +51,7 @@ #include #include -#include +#include #include #include #include @@ -65,6 +65,8 @@ #include #include #include +#include +#include #include #include "local_irq.h" @@ -133,13 +135,16 @@ sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; #ifdef CONFIG_SMP +extern struct smp_ops_t psurge_smp_ops; +extern struct smp_ops_t core99_smp_ops; + volatile static long int core99_l2_cache; -void __pmac +void __init core99_init_l2(void) { int cpu = smp_processor_id(); - if ( (_get_PVR() >> 16) != 8 && (_get_PVR() >> 16) != 12 ) + if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)) return; if (cpu == 0){ @@ -277,6 +282,9 @@ { struct device_node *cpu; int *fp; + unsigned long pvr; + + pvr = PVR_VER(mfspr(PVR)); /* Set loops_per_jiffy to a half-way reasonable value, for use until calibrate_delay gets called. */ @@ -284,18 +292,12 @@ if (cpu != 0) { fp = (int *) get_property(cpu, "clock-frequency", NULL); if (fp != 0) { - switch (_get_PVR() >> 16) { - case 4: /* 604 */ - case 8: /* G3 */ - case 9: /* 604e */ - case 10: /* mach V (604ev5) */ - case 12: /* G4 */ - case 20: /* 620 */ + if (pvr == 4 || pvr >= 8) + /* 604, G3, G4 etc. */ loops_per_jiffy = *fp / HZ; - break; - default: /* 601, 603, etc. */ + else + /* 601, 603, etc. */ loops_per_jiffy = *fp / (2*HZ); - } } else loops_per_jiffy = 50000000 / HZ; } @@ -303,14 +305,13 @@ /* this area has the CPU identification register and some registers used by smp boards */ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); - __ioremap(0xffc00000, 0x400000, pgprot_val(PAGE_READONLY)); ohare_init(); /* Lookup PCI hosts */ pmac_find_bridges(); /* Checks "l2cr-value" property in the registry */ - if ( (_get_PVR() >> 16) == 8 || (_get_PVR() >> 16) == 12 ) { + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) { struct device_node *np = find_devices("cpus"); if (np == 0) np = find_type_devices("cpu"); @@ -342,9 +343,19 @@ #ifdef CONFIG_ADB_CUDA find_via_cuda(); +#else + if (find_devices("via-cuda")) { + printk("WARNING ! Your machine is Cuda based but your kernel\n"); + printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); + } #endif #ifdef CONFIG_ADB_PMU find_via_pmu(); +#else + if (find_devices("via-pmu")) { + printk("WARNING ! Your machine is PMU based but your kernel\n"); + printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); + } #endif #ifdef CONFIG_NVRAM pmac_nvram_init(); @@ -361,6 +372,14 @@ else #endif ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); + +#ifdef CONFIG_SMP + /* Check for Core99 */ + if (find_devices("uni-n")) + ppc_md.smp_ops = &core99_smp_ops; + else + ppc_md.smp_ops = &psurge_smp_ops; +#endif /* CONFIG_SMP */ } static void __init ohare_init(void) @@ -475,9 +494,11 @@ static int found_boot = 0; char *p; - /* Do nothing if the root has been set already. */ + /* Do nothing if the root has been mounted already. */ + if (init_task.fs->rootmnt != NULL) + return; if ((goodness <= current_root_goodness) && - (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))) + (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))) return; p = strstr(saved_command_line, "root="); if (p != NULL && (p == saved_command_line || p[-1] == ' ')) @@ -563,41 +584,7 @@ /* * IDE stuff. */ -void __pmac -pmac_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - _insw_ns((unsigned short *)(port+_IO_BASE), buf, ns); -} - -void __pmac -pmac_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - _outsw_ns((unsigned short *)(port+_IO_BASE), buf, ns); -} - -int __pmac -pmac_ide_default_irq(ide_ioreg_t base) -{ -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - extern int pmac_ide_get_irq(ide_ioreg_t base); - return pmac_ide_get_irq(base); -#else - return 0; -#endif -} - -ide_ioreg_t __pmac -pmac_ide_default_io_base(int index) -{ -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - extern ide_ioreg_t pmac_ide_get_base(int index); - return pmac_ide_get_base(index); -#else - return 0; -#endif -} - -int __pmac +static int __pmac pmac_ide_check_region(ide_ioreg_t from, unsigned int extent) { /* @@ -606,11 +593,11 @@ * register, it should be OK. */ if (from < ~_IO_BASE) - return 0; - return check_region(from, extent); + return check_region(from, extent); + return 0; } -void __pmac +static void __pmac pmac_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) @@ -619,7 +606,7 @@ request_region(from, extent, name); } -void __pmac +static void __pmac pmac_ide_release_region(ide_ioreg_t from, unsigned int extent) { @@ -627,21 +614,24 @@ release_region(from, extent); } -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) -/* This is declared in drivers/block/ide-pmac.c */ -void __pmac -pmac_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq); -#else /* - * This registers the standard ports for this architecture with the IDE - * driver. + * This is only used if we have a PCI IDE controller, not + * for the IDE controller in the ohare/paddington/heathrow/keylargo. */ -void __pmac -pmac_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) +static void __pmac +pmac_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) { + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; } #endif -#endif /* * Read in a property describing some pieces of memory. @@ -728,39 +718,8 @@ } void __init -pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +select_adb_keyboard(void) { - /* isa_io_base gets set in pmac_find_bridges */ - isa_mem_base = PMAC_ISA_MEM_BASE; - pci_dram_offset = PMAC_PCI_DRAM_OFFSET; - ISA_DMA_THRESHOLD = ~0L; - DMA_MODE_READ = 1; - DMA_MODE_WRITE = 2; - - ppc_md.setup_arch = pmac_setup_arch; - ppc_md.setup_residual = NULL; - ppc_md.get_cpuinfo = pmac_get_cpuinfo; - ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = pmac_pic_init; - ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ - ppc_md.init = pmac_init2; - - ppc_md.pcibios_fixup = pmac_pcibios_fixup; - ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; - ppc_md.pcibios_after_init = pmac_pcibios_after_init; - - ppc_md.restart = pmac_restart; - ppc_md.power_off = pmac_power_off; - ppc_md.halt = pmac_halt; - - ppc_md.time_init = pmac_time_init; - ppc_md.set_rtc_time = pmac_set_rtc_time; - ppc_md.get_rtc_time = pmac_get_rtc_time; - ppc_md.calibrate_decr = pmac_calibrate_decr; - - ppc_md.find_end_of_memory = pmac_find_end_of_memory; - #ifdef CONFIG_VT #ifdef CONFIG_INPUT ppc_md.kbd_init_hw = mac_hid_init_hw; @@ -768,6 +727,7 @@ ppc_md.kbd_unexpected_up = mac_hid_kbd_unexpected_up; ppc_md.kbd_setkeycode = 0; ppc_md.kbd_getkeycode = 0; + ppc_md.kbd_leds = 0; #ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAC_ADBKEYCODES if (!keyboard_sends_linux_keycodes) { @@ -793,21 +753,55 @@ #endif /* CONFIG_MAGIC_SYSRQ */ #endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */ #endif /* CONFIG_VT */ +} + +void __init +pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + /* isa_io_base gets set in pmac_find_bridges */ + isa_mem_base = PMAC_ISA_MEM_BASE; + pci_dram_offset = PMAC_PCI_DRAM_OFFSET; + ISA_DMA_THRESHOLD = ~0L; + DMA_MODE_READ = 1; + DMA_MODE_WRITE = 2; + + ppc_md.setup_arch = pmac_setup_arch; + ppc_md.setup_residual = NULL; + ppc_md.get_cpuinfo = pmac_get_cpuinfo; + ppc_md.irq_cannonicalize = NULL; + ppc_md.init_IRQ = pmac_pic_init; + ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ + ppc_md.init = pmac_init2; + + ppc_md.pcibios_fixup = pmac_pcibios_fixup; + ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; + ppc_md.pcibios_after_init = pmac_pcibios_after_init; + + ppc_md.restart = pmac_restart; + ppc_md.power_off = pmac_power_off; + ppc_md.halt = pmac_halt; + + ppc_md.time_init = pmac_time_init; + ppc_md.set_rtc_time = pmac_set_rtc_time; + ppc_md.get_rtc_time = pmac_get_rtc_time; + ppc_md.calibrate_decr = pmac_calibrate_decr; + + ppc_md.find_end_of_memory = pmac_find_end_of_memory; + + select_adb_keyboard(); #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - ppc_ide_md.insw = pmac_ide_insw; - ppc_ide_md.outsw = pmac_ide_outsw; - ppc_ide_md.default_irq = pmac_ide_default_irq; - ppc_ide_md.default_io_base = pmac_ide_default_io_base; ppc_ide_md.ide_check_region = pmac_ide_check_region; ppc_ide_md.ide_request_region = pmac_ide_request_region; ppc_ide_md.ide_release_region = pmac_ide_release_region; - ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; #endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ + #ifdef CONFIG_BOOTX_TEXT ppc_md.progress = pmac_progress; #endif /* CONFIG_BOOTX_TEXT */ + if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); } @@ -821,7 +815,7 @@ { if (disp_bi == 0) return; - prom_drawstring(s); - prom_drawchar('\n'); + btext_drawstring(s); + btext_drawchar('\n'); } #endif /* CONFIG_BOOTX_TEXT */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_smp.c linux/arch/ppc/kernel/pmac_smp.c --- v2.4.9/linux/arch/ppc/kernel/pmac_smp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/pmac_smp.c Sat Sep 8 12:38:42 2001 @@ -0,0 +1,489 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * SMP support for power macintosh. + * + * We support both the old "powersurge" SMP architecture + * and the current Core99 (G4 PowerMac) machines. + * + * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net) + * and Ben Herrenschmidt . + * + * Support for DayStar quad CPU cards + * Copyright (C) XLR8, Inc. 1994-2000 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "open_pic.h" + +/* + * Powersurge (old powermac SMP) support. + */ + +extern void __secondary_start_psurge(void); +extern void __secondary_start_psurge2(void); /* Temporary horrible hack */ +extern void __secondary_start_psurge3(void); /* Temporary horrible hack */ + +/* Addresses for powersurge registers */ +#define HAMMERHEAD_BASE 0xf8000000 +#define HHEAD_CONFIG 0x90 +#define HHEAD_SEC_INTR 0xc0 + +/* register for interrupting the primary processor on the powersurge */ +/* N.B. this is actually the ethernet ROM! */ +#define PSURGE_PRI_INTR 0xf3019000 + +/* register for storing the start address for the secondary processor */ +/* N.B. this is the PCI config space address register for the 1st bridge */ +#define PSURGE_START 0xf2800000 + +/* Daystar/XLR8 4-CPU card */ +#define PSURGE_QUAD_REG_ADDR 0xf8800000 + +#define PSURGE_QUAD_IRQ_SET 0 +#define PSURGE_QUAD_IRQ_CLR 1 +#define PSURGE_QUAD_IRQ_PRIMARY 2 +#define PSURGE_QUAD_CKSTOP_CTL 3 +#define PSURGE_QUAD_PRIMARY_ARB 4 +#define PSURGE_QUAD_BOARD_ID 6 +#define PSURGE_QUAD_WHICH_CPU 7 +#define PSURGE_QUAD_CKSTOP_RDBK 8 +#define PSURGE_QUAD_RESET_CTL 11 + +#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v))) +#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f) +#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) +#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) + +/* virtual addresses for the above */ +static volatile u8 *hhead_base; +static volatile u8 *quad_base; +static volatile u32 *psurge_pri_intr; +static volatile u8 *psurge_sec_intr; +static volatile u32 *psurge_start; + +/* what sort of powersurge board we have */ +static int psurge_type; + +/* values for psurge_type */ +#define PSURGE_DUAL 0 +#define PSURGE_QUAD_OKEE 1 +#define PSURGE_QUAD_COTTON 2 +#define PSURGE_QUAD_ICEGRASS 3 + +/* l2 cache stuff for dual G4 macs */ +extern void core99_init_l2(void); + +/* + * Set and clear IPIs for powersurge. + */ +static inline void psurge_set_ipi(int cpu) +{ + if (cpu == 0) + in_be32(psurge_pri_intr); + else if (psurge_type == PSURGE_DUAL) + out_8(psurge_sec_intr, 0); + else + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); +} + +static inline void psurge_clr_ipi(int cpu) +{ + if (cpu > 0) { + if (psurge_type == PSURGE_DUAL) + out_8(psurge_sec_intr, ~0); + else + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); + } +} + +/* + * On powersurge (old SMP powermac architecture) we don't have + * separate IPIs for separate messages like openpic does. Instead + * we have a bitmap for each processor, where a 1 bit means that + * the corresponding message is pending for that processor. + * Ideally each cpu's entry would be in a different cache line. + * -- paulus. + */ +static unsigned long psurge_smp_message[NR_CPUS]; + +void __pmac +psurge_smp_message_recv(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int msg; + + /* clear interrupt */ + psurge_clr_ipi(cpu); + + if (smp_num_cpus < 2) + return; + + /* make sure there is a message there */ + for (msg = 0; msg < 4; msg++) + if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) + smp_message_recv(msg, regs); +} + +void __pmac +psurge_primary_intr(int irq, void *d, struct pt_regs *regs) +{ + psurge_smp_message_recv(regs); +} + +static void __pmac +smp_psurge_message_pass(int target, int msg, unsigned long data, int wait) +{ + int i; + + if (smp_num_cpus < 2) + return; + + for (i = 0; i < smp_num_cpus; i++) { + if (target == MSG_ALL + || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) + || target == i) { + set_bit(msg, &psurge_smp_message[i]); + psurge_set_ipi(i); + } + } +} + +/* + * Determine a quad card presence. We read the board ID register, we + * force the data bus to change to something else, and we read it again. + * It it's stable, then the register probably exist (ugh !) + */ +static int __init psurge_quad_probe(void) +{ + int type; + unsigned int i; + + type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); + if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS + || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) + return PSURGE_DUAL; + + /* looks OK, try a slightly more rigorous test */ + /* bogus is not necessarily cacheline-aligned, + though I don't suppose that really matters. -- paulus */ + for (i = 0; i < 100; i++) { + volatile u32 bogus[8]; + bogus[(0+i)%8] = 0x00000000; + bogus[(1+i)%8] = 0x55555555; + bogus[(2+i)%8] = 0xFFFFFFFF; + bogus[(3+i)%8] = 0xAAAAAAAA; + bogus[(4+i)%8] = 0x33333333; + bogus[(5+i)%8] = 0xCCCCCCCC; + bogus[(6+i)%8] = 0xCCCCCCCC; + bogus[(7+i)%8] = 0x33333333; + wmb(); + asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); + mb(); + if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) + return PSURGE_DUAL; + } + return type; +} + +static void __init psurge_quad_init(void) +{ + int procbits; + + if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); + procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); + if (psurge_type == PSURGE_QUAD_ICEGRASS) + PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); + else + PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); + mdelay(33); + out_8(psurge_sec_intr, ~0); + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); + PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); + if (psurge_type != PSURGE_QUAD_ICEGRASS) + PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); + PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); + mdelay(33); + PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); + mdelay(33); + PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); + mdelay(33); +} + +static int __init smp_psurge_probe(void) +{ + int i, ncpus; + + /* We don't do SMP on the PPC601 -- paulus */ + if (PVR_VER(mfspr(PVR)) == 1) + return 1; + + /* + * The powersurge cpu board can be used in the generation + * of powermacs that have a socket for an upgradeable cpu card, + * including the 7500, 8500, 9500, 9600. + * The device tree doesn't tell you if you have 2 cpus because + * OF doesn't know anything about the 2nd processor. + * Instead we look for magic bits in magic registers, + * in the hammerhead memory controller in the case of the + * dual-cpu powersurge board. -- paulus. + */ + if (find_devices("hammerhead") == NULL) + return 1; + + hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); + quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); + psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; + + psurge_type = psurge_quad_probe(); + if (psurge_type != PSURGE_DUAL) { + psurge_quad_init(); + /* All released cards using this HW design have 4 CPUs */ + ncpus = 4; + } else { + iounmap((void *) quad_base); + if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { + /* not a dual-cpu card */ + iounmap((void *) hhead_base); + return 1; + } + ncpus = 2; + } + + psurge_start = ioremap(PSURGE_START, 4); + psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); + + /* this is not actually strictly necessary -- paulus. */ + for (i = 1; i < ncpus; ++i) + smp_hw_index[i] = i; + + if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); + + return ncpus; +} + +static void __init smp_psurge_kick_cpu(int nr) +{ + void (*start)(void) = __secondary_start_psurge; + unsigned long a; + + /* may need to flush here if secondary bats aren't setup */ + for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) + asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); + asm volatile("sync"); + + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); + + /* setup entry point of secondary processor */ + switch (nr) { + case 2: + start = __secondary_start_psurge2; + break; + case 3: + start = __secondary_start_psurge3; + break; + } + + out_be32(psurge_start, __pa(start)); + mb(); + + psurge_set_ipi(nr); + udelay(10); + psurge_clr_ipi(nr); + + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); +} + +/* + * With the dual-cpu powersurge board, the decrementers and timebases + * of both cpus are frozen after the secondary cpu is started up, + * until we give the secondary cpu another interrupt. This routine + * uses this to get the timebases synchronized. + * -- paulus. + */ +static void __init psurge_dual_sync_tb(int cpu_nr) +{ + static volatile int sec_tb_reset = 0; + int t; + + set_dec(tb_ticks_per_jiffy); + set_tb(0, 0); + last_jiffy_stamp(cpu_nr) = 0; + + if (cpu_nr > 0) { + mb(); + sec_tb_reset = 1; + return; + } + + /* wait for the secondary to have reset its TB before proceeding */ + for (t = 10000000; t > 0 && !sec_tb_reset; --t) + ; + + /* now interrupt the secondary, starting both TBs */ + psurge_set_ipi(1); + + smp_tb_synchronized = 1; +} + +static void __init +smp_psurge_setup_cpu(int cpu_nr) +{ + + if (cpu_nr == 0) { + if (smp_num_cpus < 2) + return; + /* reset the entry point so if we get another intr we won't + * try to startup again */ + out_be32(psurge_start, 0x100); + if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0)) + printk(KERN_ERR "Couldn't get primary IPI interrupt"); + } + + if (psurge_type == PSURGE_DUAL) + psurge_dual_sync_tb(cpu_nr); +} + +static int __init +smp_core99_probe(void) +{ + struct device_node *cpus; + int i, ncpus = 1; + + if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); + cpus = find_type_devices("cpu"); + if (cpus) + while ((cpus = cpus->next) != NULL) + ++ncpus; + printk("smp_core99_probe: found %d cpus\n", ncpus); + if (ncpus > 1) { + openpic_request_IPIs(); + for (i = 1; i < ncpus; ++i) + smp_hw_index[i] = i; + } + + return ncpus; +} + +static void __init +smp_core99_kick_cpu(int nr) +{ + unsigned long save_vector, new_vector; + unsigned long flags; +#if 1 /* New way... */ + volatile unsigned long *vector + = ((volatile unsigned long *)(KERNELBASE+0x100)); + if (nr < 1 || nr > 3) + return; +#else + volatile unsigned long *vector + = ((volatile unsigned long *)(KERNELBASE+0x500)); + if (nr != 1) + return; +#endif + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector that does + * b __secondary_start_psurge - KERNELBASE + */ + switch(nr) { + case 1: + new_vector = (unsigned long)__secondary_start_psurge; + break; + case 2: + new_vector = (unsigned long)__secondary_start_psurge2; + break; + case 3: + new_vector = (unsigned long)__secondary_start_psurge3; + break; + } + *vector = 0x48000002 + new_vector - KERNELBASE; + + /* flush data cache and inval instruction cache */ + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + /* Put some life in our friend */ + feature_core99_kick_cpu(nr); + + /* FIXME: We wait a bit for the CPU to take the exception, I should + * instead wait for the entry code to set something for me. Well, + * ideally, all that crap will be done in prom.c and the CPU left + * in a RAM-based wait loop like CHRP. + */ + mdelay(1); + + /* Restore our exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); +} + +static void __init +smp_core99_setup_cpu(int cpu_nr) +{ + /* Setup openpic */ + do_openpic_setup_cpu(); + + /* Setup L2 */ + if (cpu_nr != 0) + core99_init_l2(); + else + if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); +} + +/* PowerSurge-style Macs */ +struct smp_ops_t psurge_smp_ops __pmacdata = { + smp_psurge_message_pass, + smp_psurge_probe, + smp_psurge_kick_cpu, + smp_psurge_setup_cpu, +}; + +/* Core99 Macs (dual G4s) */ +struct smp_ops_t core99_smp_ops __pmacdata = { + smp_openpic_message_pass, + smp_core99_probe, + smp_core99_kick_cpu, + smp_core99_setup_cpu, +}; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c --- v2.4.9/linux/arch/ppc/kernel/pmac_time.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/pmac_time.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_time.c 1.11 07/06/01 15:46:39 trini + * BK Id: SCCS/s.pmac_time.c 1.16 09/08/01 15:47:42 paulus */ /* * Support for periodic interrupts (100 per second) and for getting @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include @@ -260,8 +260,13 @@ pmu_register_sleep_notifier(&time_sleep_notifier); #endif /* CONFIG_PMAC_PBOOK */ - if (via_calibrate_decr()) - return; + /* We assume MacRISC2 machines have correct device-tree + * calibration. That's better since the VIA itself seems + * to be slightly off. --BenH + */ + if (!machine_is_compatible("MacRISC2")) + if (via_calibrate_decr()) + return; /* * The cpu node should have a timebase-frequency property diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/ppc_asm.h linux/arch/ppc/kernel/ppc_asm.h --- v2.4.9/linux/arch/ppc/kernel/ppc_asm.h Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/ppc_asm.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc_asm.h 1.14 07/02/01 22:08:05 paulus + * BK Id: SCCS/s.ppc_asm.h 1.16 08/15/01 22:43:06 paulus */ /* * arch/ppc/kernel/ppc_asm.h @@ -70,20 +70,35 @@ #define REST_32VR(n,b,base) REST_16VR(n,b,base); REST_16VR(n+16,b,base) #ifdef CONFIG_PPC601_SYNC_FIX -#define SYNC \ - sync; \ - isync +#define SYNC \ +BEGIN_FTR_SECTION \ + sync; \ + isync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) +#define SYNC_601 \ +BEGIN_FTR_SECTION \ + sync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) +#define ISYNC_601 \ +BEGIN_FTR_SECTION \ + isync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) #else #define SYNC +#define SYNC_601 +#define ISYNC_601 #endif #ifndef CONFIG_SMP #define TLBSYNC #else /* CONFIG_SMP */ +/* tlbsync is not implemented on 601 */ #define TLBSYNC \ +BEGIN_FTR_SECTION \ tlbsync; \ - sync -#endif /* CONFIG_SMP */ + sync; \ +END_FTR_SECTION_IFCLR(CPU_FTR_601) +#endif /* * This instruction is not implemented on the PPC 603 or 601; however, on diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- v2.4.9/linux/arch/ppc/kernel/ppc_htab.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/ppc_htab.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc_htab.c 1.11 06/28/01 15:50:16 paulus + * BK Id: SCCS/s.ppc_htab.c 1.17 08/20/01 22:59:41 paulus */ /* * PowerPC hash table management proc entry. Will show information @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,8 @@ #include #include #include +#include +#include static ssize_t ppc_htab_read(struct file * file, char * buf, size_t count, loff_t *ppos); @@ -67,7 +70,7 @@ write: ppc_htab_write, }; -char *pmc1_lookup(unsigned long mmcr0) +static char *pmc1_lookup(unsigned long mmcr0) { switch ( mmcr0 & (0x7f<<7) ) { @@ -84,7 +87,7 @@ } } -char *pmc2_lookup(unsigned long mmcr0) +static char *pmc2_lookup(unsigned long mmcr0) { switch ( mmcr0 & 0x3f ) { @@ -121,11 +124,7 @@ if (count < 0) return -EINVAL; - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { asm volatile ("mfspr %0,952 \n\t" "mfspr %1,953 \n\t" "mfspr %2,954 \n\t" @@ -141,12 +140,9 @@ "PMC2\t\t: %08lx (%s)\n", pmc1, pmc1_lookup(mmcr0), pmc2, pmc2_lookup(mmcr0)); - break; - default: - break; } - +#ifdef CONFIG_PPC_STD_MMU /* if we don't have a htab */ if ( Hash_size == 0 ) { @@ -154,7 +150,6 @@ goto return_string; } -#if !defined(CONFIG_8xx) && !defined(CONFIG_4xx) for ( ptr = Hash ; ptr < Hash_end ; ptr++) { unsigned int ctx, mctx, vsid; @@ -211,7 +206,7 @@ "Evicts\t\t: %lu\n", htab_reloads, htab_preloads, htab_hash_searches, primary_pteg_full, htab_evicts); -#endif /* !8xx && !4xx */ +#endif /* CONFIG_PPC_STD_MMU */ return_string: n += sprintf( buffer + n, @@ -235,7 +230,7 @@ static ssize_t ppc_htab_write(struct file * file, const char * buffer, size_t count, loff_t *ppos) { -#ifndef CONFIG_8xx +#ifdef CONFIG_PPC_STD_MMU unsigned long tmp; if ( current->uid != 0 ) return -EACCES; @@ -246,37 +241,22 @@ /* turn off performance monitoring */ if ( !strncmp( buffer, "off", 3) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { asm volatile ("mtspr %0, %3 \n\t" "mtspr %1, %3 \n\t" "mtspr %2, %3 \n\t" :: "i" (MMCR0), "i" (PMC1), "i" (PMC2), "r" (0)); - break; - default: - break; } - } if ( !strncmp( buffer, "reset", 5) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* reset PMC1 and PMC2 */ asm volatile ( "mtspr 953, %0 \n\t" "mtspr 954, %0 \n\t" :: "r" (0)); - break; - default: - break; } htab_reloads = 0; htab_evicts = 0; @@ -286,11 +266,7 @@ if ( !strncmp( buffer, "user", 4) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm("mfspr %0,%1\n\t" : "=r" (tmp) : "i" (MMCR0)); tmp &= ~(0x60000000); @@ -301,19 +277,12 @@ "mtspr %5,%4 \n\t" /* reset the pmc2 */ :: "r" (tmp), "i" (MMCR0), "i" (0), "i" (PMC1), "r" (0), "i"(PMC2) ); - break; - default: - break; } } if ( !strncmp( buffer, "kernel", 6) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm("mfspr %0,%1\n\t" : "=r" (tmp) : "i" (MMCR0)); tmp &= ~(0x60000000); @@ -324,20 +293,13 @@ "mtspr %5,%4 \n\t" /* reset the pmc2 */ :: "r" (tmp), "i" (MMCR0), "i" (0), "i" (PMC1), "r" (0), "i"(PMC2) ); - break; - default: - break; } } /* PMC1 values */ if ( !strncmp( buffer, "dtlb", 4) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm("mfspr %0,%1\n\t" : "=r" (tmp) : "i" (MMCR0)); tmp &= ~(0x7f<<7); @@ -352,11 +314,7 @@ if ( !strncmp( buffer, "ic miss", 7) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm("mfspr %0,%1\n\t" : "=r" (tmp) : "i" (MMCR0)); tmp &= ~(0x7f<<7); @@ -372,11 +330,7 @@ /* PMC2 values */ if ( !strncmp( buffer, "load miss time", 14) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm volatile( "mfspr %0,%1\n\t" /* get current mccr0 */ @@ -392,11 +346,7 @@ if ( !strncmp( buffer, "itlb", 4) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm volatile( "mfspr %0,%1\n\t" /* get current mccr0 */ @@ -412,11 +362,7 @@ if ( !strncmp( buffer, "dc miss", 7) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm volatile( "mfspr %0,%1\n\t" /* get current mccr0 */ @@ -472,9 +418,9 @@ reset_SDR1(); #endif return count; -#else /* CONFIG_8xx */ +#else /* CONFIG_PPC_STD_MMU */ return 0; -#endif /* CONFIG_8xx */ +#endif /* CONFIG_PPC_STD_MMU */ } @@ -516,7 +462,7 @@ "0.5", "1.0", "(reserved2)", "(reserved3)" }; - if ( ((_get_PVR() >> 16) != 8) && ((_get_PVR() >> 16) != 12)) + if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)) return -EFAULT; if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) { @@ -526,7 +472,7 @@ vleft = table->maxlen / sizeof(int); left = *lenp; - + for (; left /*&& vleft--*/; first=0) { if (write) { while (left) { @@ -556,7 +502,6 @@ buffer += len; left -= len; _set_L2CR(val); - } else { p = buf; if (!first) diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.4.9/linux/arch/ppc/kernel/ppc_ksyms.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/ppc_ksyms.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc_ksyms.c 1.38 07/23/01 15:35:53 trini + * BK Id: SCCS/s.ppc_ksyms.c 1.51 08/24/01 17:05:47 paulus */ #include #include @@ -48,6 +48,8 @@ #include #endif /* CONFIG_SMP */ #include +#include +#include #ifdef CONFIG_8xx #include "../8xx_io/commproc.h" @@ -73,6 +75,8 @@ int abs(int); extern unsigned long ret_to_user_hook; +extern unsigned long mm_ptov (unsigned long paddr); + EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(do_signal); EXPORT_SYMBOL(syscall_trace); @@ -157,16 +161,10 @@ EXPORT_SYMBOL(ioremap); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); +EXPORT_SYMBOL(iopa); +EXPORT_SYMBOL(mm_ptov); -EXPORT_SYMBOL(ide_insw); -EXPORT_SYMBOL(ide_outsw); EXPORT_SYMBOL(ppc_ide_md); -#ifdef CONFIG_BLK_DEV_IDE_MODULE -EXPORT_SYMBOL(chrp_ide_irq); -EXPORT_SYMBOL(chrp_ide_ports_known); -EXPORT_SYMBOL(chrp_ide_regbase); -EXPORT_SYMBOL(chrp_ide_probe); -#endif #ifdef CONFIG_PCI EXPORT_SYMBOL_NOVERS(isa_io_base); @@ -183,10 +181,10 @@ /*EXPORT_SYMBOL(_disable_interrupts); EXPORT_SYMBOL(_enable_interrupts);*/ EXPORT_SYMBOL(flush_instruction_cache); -EXPORT_SYMBOL(_get_PVR); EXPORT_SYMBOL(giveup_fpu); EXPORT_SYMBOL(enable_kernel_fp); EXPORT_SYMBOL(flush_icache_range); +EXPORT_SYMBOL(flush_dcache_range); EXPORT_SYMBOL(xchg_u32); #ifdef CONFIG_ALTIVEC EXPORT_SYMBOL(last_task_used_altivec); @@ -200,6 +198,7 @@ EXPORT_SYMBOL(__global_sti); EXPORT_SYMBOL(__global_save_flags); EXPORT_SYMBOL(__global_restore_flags); +#ifdef SPINLOCK_DEBUG EXPORT_SYMBOL(_spin_lock); EXPORT_SYMBOL(_spin_unlock); EXPORT_SYMBOL(spin_trylock); @@ -207,6 +206,7 @@ EXPORT_SYMBOL(_read_unlock); EXPORT_SYMBOL(_write_lock); EXPORT_SYMBOL(_write_unlock); +#endif EXPORT_SYMBOL(smp_call_function); EXPORT_SYMBOL(smp_hw_index); EXPORT_SYMBOL(smp_num_cpus); @@ -226,17 +226,6 @@ EXPORT_SYMBOL(cuda_request); EXPORT_SYMBOL(cuda_poll); #endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_ADB_PMU -EXPORT_SYMBOL(pmu_request); -EXPORT_SYMBOL(pmu_poll); -EXPORT_SYMBOL(pmu_suspend); -EXPORT_SYMBOL(pmu_resume); -#endif /* CONFIG_ADB_PMU */ -#ifdef CONFIG_PMAC_PBOOK -EXPORT_SYMBOL(pmu_register_sleep_notifier); -EXPORT_SYMBOL(pmu_unregister_sleep_notifier); -EXPORT_SYMBOL(pmu_enable_irled); -#endif /* CONFIG_PMAC_PBOOK */ #ifdef CONFIG_PMAC_BACKLIGHT EXPORT_SYMBOL(get_backlight_level); EXPORT_SYMBOL(set_backlight_level); @@ -245,7 +234,6 @@ #endif /* CONFIG_PMAC_BACKLIGHT */ #if defined(CONFIG_ALL_PPC) EXPORT_SYMBOL(_machine); -EXPORT_SYMBOL_NOVERS(have_of); EXPORT_SYMBOL_NOVERS(sys_ctrler); EXPORT_SYMBOL(find_devices); EXPORT_SYMBOL(find_type_devices); @@ -273,10 +261,11 @@ EXPORT_SYMBOL(feature_set_usb_power); EXPORT_SYMBOL(feature_set_firewire_power); EXPORT_SYMBOL(feature_set_firewire_cable_power); +EXPORT_SYMBOL(feature_set_modem_power); EXPORT_SYMBOL(feature_set_airport_power); #endif /* defined(CONFIG_ALL_PPC) */ #if defined(CONFIG_BOOTX_TEXT) -EXPORT_SYMBOL(bootx_update_display); +EXPORT_SYMBOL(btext_update_display); #endif #if defined(CONFIG_SCSI) && defined(CONFIG_ALL_PPC) EXPORT_SYMBOL(note_scsi_host); @@ -303,7 +292,7 @@ EXPORT_SYMBOL(abs); -#ifdef CONFIG_VT +#ifdef CONFIG_VGA_CONSOLE EXPORT_SYMBOL(screen_info); #endif @@ -367,3 +356,4 @@ #endif extern long *ret_from_intercept; EXPORT_SYMBOL(ret_from_intercept); +EXPORT_SYMBOL(cur_cpu_spec); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/prep_nvram.c linux/arch/ppc/kernel/prep_nvram.c --- v2.4.9/linux/arch/ppc/kernel/prep_nvram.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/prep_nvram.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prep_nvram.c 1.9 05/17/01 18:14:22 cort + * BK Id: SCCS/s.prep_nvram.c 1.12 09/08/01 15:47:42 paulus */ /* * linux/arch/ppc/kernel/prep_nvram.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c --- v2.4.9/linux/arch/ppc/kernel/prep_pci.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/prep_pci.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prep_pci.c 1.22 08/05/01 16:18:54 trini + * BK Id: SCCS/s.prep_pci.c 1.26 09/08/01 15:47:42 paulus */ /* * PReP pci functions. @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -172,7 +172,7 @@ 0, /* Slot 7 - unused */ 0, /* Slot 8 - unused */ 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unxued */ + 0, /* Slot 10 - unused */ 0, /* Slot 11 - unused */ 0, /* Slot 12 - unused */ 0, /* Slot 13 - unused */ @@ -200,7 +200,7 @@ 0, /* Slot 7 - unused */ 0, /* Slot 8 - unused */ 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unxued */ + 0, /* Slot 10 - unused */ 0, /* Slot 11 - unused */ 0, /* Slot 12 - unused */ 0, /* Slot 13 - unused */ @@ -322,8 +322,8 @@ 3, /* Slot 12 - unused */ 0, /* Slot 13 - unused */ 2, /* Slot 14 - SCSI */ - 0, /* Slot 15 - graphics on 3600 */ - 9, /* Slot 16 - PMC */ + 0, /* Slot 15 - unused */ + 9, /* Slot 16 - PMC 1 */ 12, /* Slot 17 - pci */ 11, /* Slot 18 - pci */ 10, /* Slot 19 - pci */ @@ -511,6 +511,44 @@ 13 /* Line 4 */ }; +/* + * IBM RS/6000 43p/140 -- paulus + * XXX we should get all this from the residual data + */ +static char ibm43p_pci_IRQ_map[23] __prepdata = { + 0, /* Slot 0 - unused */ + 0, /* Slot 1 - unused */ + 0, /* Slot 2 - unused */ + 0, /* Slot 3 - unused */ + 0, /* Slot 4 - unused */ + 0, /* Slot 5 - unused */ + 0, /* Slot 6 - unused */ + 0, /* Slot 7 - unused */ + 0, /* Slot 8 - unused */ + 0, /* Slot 9 - unused */ + 0, /* Slot 10 - unused */ + 0, /* Slot 11 - FireCoral ISA bridge */ + 6, /* Slot 12 - Ethernet */ + 0, /* Slot 13 - openpic */ + 0, /* Slot 14 - unused */ + 0, /* Slot 15 - unused */ + 7, /* Slot 16 - NCR58C825a onboard scsi */ + 0, /* Slot 17 - unused */ + 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */ + 0, /* Slot 19 - unused */ + 0, /* Slot 20 - unused */ + 0, /* Slot 21 - unused */ + 1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ +}; + +static char ibm43p_pci_IRQ_routes[] __prepdata = { + 0, /* Line 0 - unused */ + 15, /* Line 1 */ + 15, /* Line 2 */ + 15, /* Line 3 */ + 15, /* Line 4 */ +}; + /* Motorola PowerPlus architecture PCI IRQ tables */ /* Interrupt line values for INTA-D on primary/secondary MPIC inputs */ @@ -767,7 +805,52 @@ {0x000, 0x00, 0x00, "", NULL, NULL, NULL, NULL, 0x00} }; -unsigned long __init prep_route_pci_interrupts(void) +void ibm_prep_init(void) +{ + u32 addr; +#ifdef CONFIG_PREP_RESIDUAL + PPC_DEVICE *mpic; +#endif + + if (inb(0x0852) == 0xd5) { + /* This is for the 43p-140 */ + early_read_config_dword(0, 0, PCI_DEVFN(13, 0), + PCI_BASE_ADDRESS_0, &addr); + if (addr != 0xffffffff + && !(addr & PCI_BASE_ADDRESS_SPACE_IO) + && (addr &= PCI_BASE_ADDRESS_MEM_MASK) != 0) { + addr += PREP_ISA_MEM_BASE; + OpenPIC_Addr = ioremap(addr, 0x40000); + ppc_md.get_irq = openpic_get_irq; + } + } + +#ifdef CONFIG_PREP_RESIDUAL + mpic = residual_find_device(-1, NULL, SystemPeripheral, + ProgrammableInterruptController, MPIC, 0); + if (mpic != NULL) { + printk("mpic = %p\n", mpic); + } +#endif +} + +void +ibm43p_pci_map_non0(struct pci_dev *dev) +{ + unsigned char intpin; + static unsigned char bridge_intrs[4] = { 3, 4, 5, 8 }; + + if (dev == NULL) + return; + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin); + if (intpin < 1 || intpin > 4) + return; + intpin = (PCI_SLOT(dev->devfn) + intpin - 1) & 3; + dev->irq = openpic_to_irq(bridge_intrs[intpin]); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); +} + +void __init prep_route_pci_interrupts(void) { unsigned char *ibc_pirq = (unsigned char *)0x80800860; unsigned char *ibc_pcicon = (unsigned char *)0x80800840; @@ -856,7 +939,13 @@ Motherboard_map_name = "IBM 6015"; Motherboard_map = ibm6015_pci_IRQ_map; Motherboard_routes = ibm6015_pci_IRQ_routes; - break; + break; + case 0xd5: + Motherboard_map_name = "IBM 43p/140"; + Motherboard_map = ibm43p_pci_IRQ_map; + Motherboard_routes = ibm43p_pci_IRQ_routes; + Motherboard_non0 = ibm43p_pci_map_non0; + break; default: Motherboard_map_name = "IBM 8xx (Carolina)"; Motherboard_map = ibm8xx_pci_IRQ_map; @@ -878,7 +967,7 @@ else { printk("No known machine pci routing!\n"); - return -1; + return; } /* Set up mapping from slots */ @@ -888,16 +977,15 @@ } /* Enable PCI interrupts */ *ibc_pcicon |= 0x20; - return 0; } void __init prep_pib_init(void) { -unsigned char reg; -unsigned short short_reg; + unsigned char reg; + unsigned short short_reg; -struct pci_dev *dev = NULL; + struct pci_dev *dev = NULL; if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) { /* @@ -910,43 +998,47 @@ * PPCBUG does not set the enable bits * for the IDE device. Force them on here. */ - pcibios_read_config_byte(dev->bus->number, - dev->devfn, 0x40, ®); + pci_read_config_byte(dev, 0x40, ®); reg |= 0x03; /* IDE: Chip Enable Bits */ - pcibios_write_config_byte(dev->bus->number, - dev->devfn, 0x40, reg); - - /* Force correct IDE function interrupt */ - dev->irq = 14; - pcibios_write_config_byte(dev->bus->number, - dev->devfn, + pci_write_config_byte(dev, 0x40, reg); + } + if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, + dev)) && (dev->devfn = 0x5a)) { + /* Force correct USB interrupt */ + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - - } else if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + } + if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, dev))) { - /* - * Clear the PCI Interrupt Routing Control Register. - */ + /* Clear PCI Interrupt Routing Control Register. */ short_reg = 0x0000; pci_write_config_word(dev, 0x44, short_reg); if (OpenPIC_Addr){ - /* - * Route both IDE interrupts to IRQ 14 - */ + /* Route IDE interrupts to IRQ 14 */ reg = 0xEE; - pci_write_config_byte(dev, 0x44, reg); + pci_write_config_byte(dev, 0x43, reg); } } } + if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev))){ if (OpenPIC_Addr){ - /* Disable LEGIRQ mode so PCI INTs are routed to - the 8259 */ - printk("Set winbond IDE to native mode\n"); - pci_write_config_dword(dev, 0x40, 0x10ff00a1); + /* + * Disable LEGIRQ mode so PCI INTS are routed + * directly to the 8259 and enable both channels + */ + pci_write_config_dword(dev, 0x40, 0x10ff0033); + + /* Force correct IDE interrupt */ + dev->irq = 14; + pci_write_config_byte(dev, + PCI_INTERRUPT_LINE, + dev->irq); }else{ /* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */ pci_write_config_dword(dev, 0x40, 0x10ff08a1); @@ -1106,6 +1198,19 @@ } } +static void __init +prep_init_resource(struct resource *res, unsigned long start, + unsigned long end, int flags) +{ + res->flags = flags; + res->start = start; + res->end = end; + res->name = "PCI host bridge"; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; +} + void __init prep_find_bridges(void) { @@ -1119,6 +1224,9 @@ hose->last_busno = 0xff; hose->pci_mem_offset = PREP_ISA_MEM_BASE; hose->io_base_virt = (void *)PREP_ISA_IO_BASE; + prep_init_resource(&hose->io_resource, 0, 0x0fffffff, IORESOURCE_IO); + prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff, + IORESOURCE_MEM); printk("PReP architecture\n"); { diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c --- v2.4.9/linux/arch/ppc/kernel/prep_setup.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/prep_setup.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prep_setup.c 1.26 08/05/01 16:18:54 trini + * BK Id: SCCS/s.prep_setup.c 1.36 09/08/01 15:47:42 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -7,6 +7,9 @@ * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) + * + * Support for PReP (Motorola MTX/MVME) + * by Troy Benjegerdes (hozer@drgw.net) */ /* @@ -38,7 +41,7 @@ #include #include -#include +#include #include #include #include @@ -78,6 +81,7 @@ extern unsigned char rs_nvram_read_val(int addr); extern void rs_nvram_write_val(int addr, unsigned char val); +extern void ibm_prep_init(void); extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); @@ -329,13 +333,20 @@ /*print_residual_device_info();*/ - raven_init(); + switch (_prep_type) { + case _PREP_Motorola: + raven_init(); + break; + case _PREP_IBM: + ibm_prep_init(); + break; + } #ifdef CONFIG_VGA_CONSOLE /* remap the VGA memory */ vgacon_remap_base = 0xf0000000; /*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/ - conswitchp = &vga_con; + conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; #endif @@ -662,23 +673,6 @@ } } -#if 0 -void __prep -prep_do_IRQ(struct pt_regs *regs, int cpu) -{ - int irq; - - if ( (irq = i8259_irq(0)) < 0 ) - { - printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n", - regs->nip); - ppc_spurious_interrupts++; - return; - } - ppc_irq_dispatch_handler( regs, irq ); -} -#endif - int __prep prep_get_irq(struct pt_regs *regs) { @@ -701,18 +695,6 @@ /* * IDE stuff. */ -void __prep -prep_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - _insw((unsigned short *)((port)+_IO_BASE), buf, ns); -} - -void __prep -prep_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - _outsw((unsigned short *)((port)+_IO_BASE), buf, ns); -} - int __prep prep_ide_default_irq(ide_ioreg_t base) { @@ -721,8 +703,9 @@ case 0x170: return 13; case 0x1e8: return 11; case 0x168: return 10; - default: - return 0; + case 0xfff0: return 14; /* MCP(N)750 ide0 */ + case 0xffe0: return 15; /* MCP(N)750 ide1 */ + default: return 0; } } @@ -780,6 +763,45 @@ } #endif +#ifdef CONFIG_SMP +/* PReP (MTX) support */ +static int +smp_prep_probe(void) +{ + extern int mot_multi; + + if (mot_multi) { + openpic_request_IPIs(); + smp_hw_index[1] = 1; + return 2; + } + + return 1; +} + +static void +smp_prep_kick_cpu(int nr) +{ + *(unsigned long *)KERNELBASE = nr; + asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); + printk("CPU1 reset, waiting\n"); +} + +static void +smp_prep_setup_cpu(int cpu_nr) +{ + if (OpenPIC_Addr) + do_openpic_setup_cpu(); +} + +static struct smp_ops_t prep_smp_ops = { + smp_openpic_message_pass, + smp_prep_probe, + smp_prep_kick_cpu, + smp_prep_setup_cpu, +}; +#endif /* CONFIG_SMP */ + /* * This finds the amount of physical ram and does necessary * setup for prep. This is pretty architecture specific so @@ -788,29 +810,39 @@ */ unsigned long __init prep_find_end_of_memory(void) { - unsigned long total; + unsigned long total = 0; + extern unsigned int boot_mem_size; + #ifdef CONFIG_PREP_RESIDUAL total = res->TotalMemory; -#else - total = 0; #endif - if (total == 0 ) - { + if (total == 0 && boot_mem_size != 0) + total = boot_mem_size; + + if (total == 0) { /* * I need a way to probe the amount of memory if the residual * data doesn't contain it. -- Cort */ - printk("Ramsize from residual data was 0 -- Probing for value\n"); total = 0x02000000; - printk("Ramsize default to be %ldM\n", total>>20); + printk(KERN_INFO "Ramsize from residual data was 0" + " -- defaulting to %ldM\n", total>>20); } return (total); } -unsigned long *MotSave_SmpIar; -unsigned char *MotSave_CpusState[2]; +/* + * Setup the bat mappings we're going to load that cover + * the io areas. RAM was mapped by mapin_ram(). + * -- Cort + */ +void __init prep_map_io(void) +{ + io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); + io_block_mapping(0xf0000000, 0xc0000000, 0x08000000, _PAGE_IO); +} void __init prep_init2(void) @@ -838,13 +870,6 @@ { memcpy((void *)res,(void *)(r3+KERNELBASE), sizeof(RESIDUAL)); - - /* These need to be saved for the Motorola Prep - * MVME4600 and Dual MTX boards. - */ - MotSave_SmpIar = &old_res->VitalProductData.SmpIar; - MotSave_CpusState[0] = &old_res->Cpus[0].CpuState; - MotSave_CpusState[1] = &old_res->Cpus[1].CpuState; } #endif @@ -912,19 +937,16 @@ } ppc_md.find_end_of_memory = prep_find_end_of_memory; + ppc_md.setup_io_mappings = prep_map_io; #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = prep_ide_insw; - ppc_ide_md.outsw = prep_ide_outsw; ppc_ide_md.default_irq = prep_ide_default_irq; ppc_ide_md.default_io_base = prep_ide_default_io_base; ppc_ide_md.ide_check_region = prep_ide_check_region; ppc_ide_md.ide_request_region = prep_ide_request_region; ppc_ide_md.ide_release_region = prep_ide_release_region; - ppc_ide_md.fix_driveid = NULL; ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports; -#endif - ppc_ide_md.io_base = _IO_BASE; +#endif #ifdef CONFIG_VT ppc_md.kbd_setkeycode = pckbd_setkeycode; @@ -938,4 +960,8 @@ SYSRQ_KEY = 0x54; #endif #endif + +#ifdef CONFIG_SMP + ppc_md.smp_ops = &prep_smp_ops; +#endif /* CONFIG_SMP */ } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c --- v2.4.9/linux/arch/ppc/kernel/prep_time.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/prep_time.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prep_time.c 1.7 05/17/01 18:14:22 cort + * BK Id: SCCS/s.prep_time.c 1.10 09/08/01 15:47:42 paulus */ /* * linux/arch/i386/kernel/time.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.4.9/linux/arch/ppc/kernel/process.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/process.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.process.c 1.23 07/19/01 23:02:48 paulus + * BK Id: SCCS/s.process.c 1.27 08/28/01 22:01:21 paulus */ /* * linux/arch/ppc/kernel/process.c @@ -59,8 +59,6 @@ }; /* only used to get secondary processor up */ struct task_struct *current_set[NR_CPUS] = {&init_task, }; -char *sysmap = NULL; -unsigned long sysmap_size = 0; #undef SHOW_TASK_SWITCHES #undef CHECK_STACK @@ -324,7 +322,6 @@ unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - unsigned long msr; struct pt_regs *childregs, *kregs; extern void ret_from_fork(void); unsigned long sp = (unsigned long)p + sizeof(union task_union); @@ -362,11 +359,12 @@ * copy fpu info - assume lazy fpu switch now always * -- Cort */ - if (regs->msr & MSR_FP) + if (regs->msr & MSR_FP) { giveup_fpu(current); + childregs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); + } memcpy(&p->thread.fpr, ¤t->thread.fpr, sizeof(p->thread.fpr)); p->thread.fpscr = current->thread.fpscr; - childregs->msr &= ~MSR_FP; #ifdef CONFIG_ALTIVEC /* diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.4.9/linux/arch/ppc/kernel/prom.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/prom.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prom.c 1.35 07/25/01 14:11:37 trini + * BK Id: SCCS/s.prom.c 1.42 09/08/01 15:47:42 paulus */ /* * Procedures for interfacing to the Open Firmware PROM on @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include #include @@ -33,6 +33,7 @@ #include #include #include +#include #include "open_pic.h" #ifdef CONFIG_FB @@ -99,6 +100,7 @@ #define FB_MAX 8 #endif char *prom_display_paths[FB_MAX] __initdata = { 0, }; +phandle prom_display_nodes[FB_MAX] __initdata; unsigned int prom_num_displays __initdata = 0; char *of_stdout_device __initdata = 0; ihandle prom_disp_node __initdata = 0; @@ -125,40 +127,6 @@ static struct device_node *allnodes; -#ifdef CONFIG_BOOTX_TEXT - -#define NO_SCROLL - -static void clearscreen(void); -static void flushscreen(void); - -#ifndef NO_SCROLL -static void scrollscreen(void); -#endif - -static void prepare_disp_BAT(void); - -static void draw_byte(unsigned char c, long locX, long locY); -static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb); -static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb); -static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb); - -static int g_loc_X; -static int g_loc_Y; -static int g_max_loc_X; -static int g_max_loc_Y; - -unsigned long disp_BAT[2] __initdata = {0, 0}; - -#define cmapsz (16*256) - -static unsigned char vga_font[cmapsz]; - -int bootx_text_mapped = 1; - -#endif /* CONFIG_BOOTX_TEXT */ - - static void *call_prom(const char *service, int nargs, int nret, ...); static void prom_exit(void); static unsigned long copy_device_tree(unsigned long, unsigned long); @@ -174,7 +142,6 @@ #ifdef CONFIG_BOOTX_TEXT static void setup_disp_fake_bi(ihandle dp); -static void prom_welcome(boot_infos_t* bi, unsigned long phys); #endif extern void enter_rtas(void *); @@ -182,10 +149,6 @@ extern char cmd_line[512]; /* XXX */ boot_infos_t *boot_infos; -#ifdef CONFIG_BOOTX_TEXT -boot_infos_t *disp_bi; -boot_infos_t fake_bi; -#endif unsigned long dev_tree_size; #define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long)) @@ -257,13 +220,7 @@ unsigned long offset = reloc_offset(); if (RELOC(prom_stdout) == 0) - { -#ifdef CONFIG_BOOTX_TEXT - if (RELOC(disp_bi) != 0) - prom_drawstring(msg); -#endif return; - } for (p = msg; *p != 0; p = q) { for (q = p; *q != 0 && *q != '\n'; ++q) @@ -399,26 +356,21 @@ bi->logicalDisplayBase = 0; #ifdef CONFIG_BOOTX_TEXT - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y) = 0; - RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8; - RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16; - RELOC(disp_bi) = PTRUNRELOC(bi); - - clearscreen(); + btext_init(bi); - /* Test if boot-info is compatible. Done only in config CONFIG_BOOTX_TEXT since - there is nothing much we can do with an incompatible version, except display - a message and eventually hang the processor... - - I'll try to keep enough of boot-info compatible in the future to always allow - display of this message; - */ - if (!BOOT_INFO_IS_COMPATIBLE(bi)) - prom_print(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n")); - - prom_welcome(bi, phys); - flushscreen(); + /* + * Test if boot-info is compatible. Done only in config + * CONFIG_BOOTX_TEXT since there is nothing much we can do + * with an incompatible version, except display a message + * and eventually hang the processor... + * + * I'll try to keep enough of boot-info compatible in the + * future to always allow display of this message; + */ + if (!BOOT_INFO_IS_COMPATIBLE(bi)) { + btext_drawstring(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n")); + btext_flushscreen(); + } #endif /* CONFIG_BOOTX_TEXT */ /* New BootX enters kernel with MMU off, i/os are not allowed @@ -461,10 +413,13 @@ } #ifdef CONFIG_BOOTX_TEXT - prepare_disp_BAT(); - prom_drawstring(RELOC("booting...\n")); - flushscreen(); - RELOC(bootx_text_mapped) = 1; + /* + * Note that after we call prepare_disp_BAT, we can't do + * prom_draw*, flushscreen or clearscreen until we turn the MMU + * on, since prepare_disp_BAT sets disp_bi->logicalDisplayBase + * to a virtual address. + */ + btext_prepare_BAT(); #endif } @@ -591,13 +546,11 @@ unsigned long __init prom_init(int r3, int r4, prom_entry pp) { - int chrp = 0; unsigned long mem; - ihandle prom_mmu, prom_op; + ihandle prom_mmu; unsigned long offset = reloc_offset(); int l; char *p, *d; - int prom_version = 0; unsigned long phys; /* Default */ @@ -622,31 +575,6 @@ RELOC(of_stdout_device) = PTRUNRELOC(p); mem += strlen(p) + 1; - /* Find the OF version */ - prom_op = call_prom(RELOC("finddevice"), 1, 1, RELOC("/openprom")); - prom_version = 0; - if (prom_op != (void*)-1) { - char model[64]; - int sz; - sz = (int)call_prom(RELOC("getprop"), 4, 1, prom_op, - RELOC("model"), model, 64); - if (sz > 0) { - char *c; - /* hack to skip the ibm chrp firmware # */ - if ( strncmp(model,RELOC("IBM"),3) ) { - for (c = model; *c; c++) - if (*c >= '0' && *c <= '9') { - prom_version = *c - '0'; - break; - } - } - else - chrp = 1; - } - } - if (prom_version >= 3) - prom_print(RELOC("OF Version 3 detected.\n")); - /* Get the boot device and translate it to a full OF pathname. */ p = (char *) mem; l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen), @@ -725,22 +653,14 @@ call_prom(RELOC("quiesce"), 0, 0); #ifdef CONFIG_BOOTX_TEXT - if (!chrp && RELOC(disp_bi)) { - RELOC(prom_stdout) = 0; /* stop OF output */ - clearscreen(); - prepare_disp_BAT(); - prom_welcome(PTRRELOC(RELOC(disp_bi)), phys); - prom_drawstring(RELOC("booting...\n")); - RELOC(bootx_text_mapped) = 1; - } else { - RELOC(bootx_text_mapped) = 0; - } + btext_prepare_BAT(); #endif prom_print(RELOC("returning ")); prom_print_hex(phys); prom_print(RELOC(" from prom_init\n")); RELOC(prom_stdout) = 0; + return phys; } @@ -767,82 +687,6 @@ rtas(&u, RELOC(rtas_data)); } -#ifdef CONFIG_BOOTX_TEXT -static void __init -prom_welcome(boot_infos_t* bi, unsigned long phys) -{ - unsigned long offset = reloc_offset(); - unsigned long flags; - unsigned long pvr; - - prom_drawstring(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n")); - prom_drawstring(RELOC("\nstarted at : 0x")); - prom_drawhex(phys); - prom_drawstring(RELOC("\nlinked at : 0x")); - prom_drawhex(KERNELBASE); - prom_drawstring(RELOC("\nframe buffer at : 0x")); - prom_drawhex((unsigned long)bi->dispDeviceBase); - prom_drawstring(RELOC(" (phys), 0x")); - prom_drawhex((unsigned long)bi->logicalDisplayBase); - prom_drawstring(RELOC(" (log)")); - prom_drawstring(RELOC("\nklimit : 0x")); - prom_drawhex((unsigned long)RELOC(klimit)); - prom_drawstring(RELOC("\nMSR : 0x")); - __asm__ __volatile__ ("mfmsr %0" : "=r" (flags)); - prom_drawhex(flags); - __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr)); - pvr >>= 16; - if (pvr > 1) { - prom_drawstring(RELOC("\nHID0 : 0x")); - __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags)); - prom_drawhex(flags); - } - if (pvr == 8 || pvr == 12 || pvr == 0x800c) { - prom_drawstring(RELOC("\nICTC : 0x")); - __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags)); - prom_drawhex(flags); - } - prom_drawstring(RELOC("\n\n")); -} - -/* Calc BAT values for mapping the display and store them - * in disp_BAT. Those values are then used from head.S to map - * the display during identify_machine() and MMU_Init() - * - * For now, the display is mapped in place (1:1). This should - * be changed if the display physical address overlaps - * KERNELBASE, which is fortunately not the case on any machine - * I know of. This mapping is temporary and will disappear as - * soon as the setup done by MMU_Init() is applied - * - * For now, we align the BAT and then map 8Mb on 601 and 16Mb - * on other PPCs. This may cause trouble if the framebuffer - * is really badly aligned, but I didn't encounter this case - * yet. - */ -static void __init -prepare_disp_BAT(void) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned long addr = (unsigned long)bi->dispDeviceBase; - - if ((_get_PVR() >> 16) != 1) { - /* 603, 604, G3, G4, ... */ - addr &= 0xFF000000UL; - RELOC(disp_BAT[0]) = addr | (BL_16M<<2) | 2; - RELOC(disp_BAT[1]) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW); - } else { - /* 601 */ - addr &= 0xFF800000UL; - RELOC(disp_BAT[0]) = addr | (_PAGE_NO_CACHE | PP_RWXX) | 4; - RELOC(disp_BAT[1]) = addr | BL_8M | 0x40; - } - bi->logicalDisplayBase = bi->dispDeviceBase; -} - -#endif - static int __init prom_set_color(ihandle ih, int i, int r, int g, int b) { @@ -920,17 +764,22 @@ i = RELOC(prom_num_displays)++; if (RELOC(of_stdout_device) != 0 && i > 0 && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) { - for (; i > 0; --i) + for (; i > 0; --i) { RELOC(prom_display_paths[i]) = RELOC(prom_display_paths[i-1]); + RELOC(prom_display_nodes[i]) + = RELOC(prom_display_nodes[i-1]); + } } RELOC(prom_display_paths[i]) = PTRUNRELOC(path); + RELOC(prom_display_nodes[i]) = node; if (i == 0) RELOC(prom_disp_node) = node; if (RELOC(prom_num_displays) >= FB_MAX) break; } +try_again: /* * Open the first display and set its colormap. */ @@ -941,6 +790,15 @@ ih = call_prom(RELOC("open"), 1, 1, path); if (ih == 0 || ih == (ihandle) -1) { prom_print(RELOC("... failed\n")); + for (i=1; i 0) + RELOC(prom_disp_node) = RELOC(prom_display_nodes[0]); + else + RELOC(prom_disp_node) = NULL; + goto try_again; } else { prom_print(RELOC("... ok\n")); /* @@ -977,7 +835,6 @@ { int width = 640, height = 480, depth = 8, pitch; unsigned address; - boot_infos_t* bi; unsigned long offset = reloc_offset(); struct pci_reg_property addrs[8]; int i, naddrs; @@ -1025,20 +882,8 @@ /* kludge for valkyrie */ if (strcmp(name, RELOC("valkyrie")) == 0) address += 0x1000; - - RELOC(disp_bi) = &fake_bi; - bi = PTRRELOC((&fake_bi)); - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y) = 0; - RELOC(g_max_loc_X) = width / 8; - RELOC(g_max_loc_Y) = height / 16; - bi->logicalDisplayBase = (unsigned char *)address; - bi->dispDeviceBase = (unsigned char *)address; - bi->dispDeviceRowBytes = pitch; - bi->dispDeviceDepth = depth; - bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; - bi->dispDeviceRect[2] = width; - bi->dispDeviceRect[3] = height; + + btext_setup_display(width, height, depth, pitch, address); } #endif @@ -1147,8 +992,7 @@ prev_propp = &pp->next; namep = (char *) (pp + 1); pp->name = PTRUNRELOC(namep); - /* Work around a GCC3 bug */ - memcpy(namep, RELOC("linux,phandle"), sizeof("linux,phandle")); + strcpy(namep, RELOC("linux,phandle")); mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1); pp->value = (unsigned char *) PTRUNRELOC(&np->node); pp->length = sizeof(np->node); @@ -1213,15 +1057,21 @@ * np->name has not been set yet. -- paulus */ int n = 0; - char *name; + char *name, *ic; + int iclen; for (np = allnodes; np != NULL; np = np->allnext) { - if ((name = get_property(np, "name", NULL)) == NULL - || strcmp(name, "interrupt-controller") != 0) - continue; - if (n == 0) - dflt_interrupt_controller = np; - ++n; + ic = get_property(np, "interrupt-controller", &iclen); + name = get_property(np, "name", NULL); + /* checking iclen makes sure we don't get a false + match on /chosen.interrupt_controller */ + if ((name != NULL + && strcmp(name, "interrupt-controller") == 0) + || (ic != NULL && iclen == 0)) { + if (n == 0) + dflt_interrupt_controller = np; + ++n; + } } num_interrupt_controllers = n; } @@ -1559,7 +1409,7 @@ } } -int __init +int prom_n_addr_cells(struct device_node* np) { int* ip; @@ -1574,7 +1424,7 @@ return 1; } -int __init +int prom_n_size_cells(struct device_node* np) { int* ip; @@ -1890,7 +1740,7 @@ /* * Returns all nodes linked together */ -struct device_node __openfirmware * +struct device_node * __openfirmware find_all_nodes(void) { struct device_node *head, **prevp, *np; @@ -1983,7 +1833,7 @@ /* * Find the device_node with a given phandle. */ -static struct device_node __init * +static struct device_node * __init find_phandle(phandle ph) { struct device_node *np; @@ -2111,6 +1961,12 @@ u.words[i+3] = va_arg(list, unsigned long); va_end(list); + /* Shouldn't we enable kernel FP here ? enter_rtas will play + * with MSR_FE0|MSR_FE1|MSR_FP so I assume rtas might use + * floating points. If that's the case, then we need to make + * sure any lazy FP context is backed up + * --BenH + */ spin_lock_irqsave(&rtas_lock, s); enter_rtas((void *)__pa(&u)); spin_unlock_irqrestore(&rtas_lock, s); @@ -2130,694 +1986,3 @@ for (;;) prom_exit(); } - -#ifdef CONFIG_BOOTX_TEXT - -/* Here's a small text engine to use during early boot or for debugging purposes - * - * todo: - * - * - build some kind of vgacon with it to enable early printk - * - move to a separate file - * - add a few video driver hooks to keep in sync with display - * changes. - */ - -void -map_bootx_text(void) -{ - unsigned long base, offset, size; - if (disp_bi == 0) - return; - base = ((unsigned long) disp_bi->dispDeviceBase) & 0xFFFFF000UL; - offset = ((unsigned long) disp_bi->dispDeviceBase) - base; - size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset - + disp_bi->dispDeviceRect[0]; - disp_bi->logicalDisplayBase = ioremap(base, size); - if (disp_bi->logicalDisplayBase == 0) - return; - disp_bi->logicalDisplayBase += offset; - bootx_text_mapped = 1; -} - -/* Calc the base address of a given point (x,y) */ -static unsigned char * __pmac -calc_base(boot_infos_t *bi, int x, int y) -{ - unsigned char *base; - - base = bi->logicalDisplayBase; - if (base == 0) - base = bi->dispDeviceBase; - base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); - base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; - return base; -} - -/* Adjust the display to a new resolution */ -void __openfirmware -bootx_update_display(unsigned long phys, int width, int height, - int depth, int pitch) -{ - if (disp_bi == 0) - return; - /* check it's the same frame buffer (within 64MB) */ - if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xfc000000) { - return; - } - - disp_bi->dispDeviceBase = (__u8 *) phys; - disp_bi->dispDeviceRect[0] = 0; - disp_bi->dispDeviceRect[1] = 0; - disp_bi->dispDeviceRect[2] = width; - disp_bi->dispDeviceRect[3] = height; - disp_bi->dispDeviceDepth = depth; - disp_bi->dispDeviceRowBytes = pitch; - if (bootx_text_mapped) { - iounmap(disp_bi->logicalDisplayBase); - bootx_text_mapped = 0; - } - map_bootx_text(); - g_loc_X = 0; - g_loc_Y = 0; - g_max_loc_X = width / 8; - g_max_loc_Y = height / 16; -} - -static void __pmac -clearscreen(void) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); - unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - int i,j; - - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) - { - unsigned long *ptr = base; - for(j=width; j; --j) - *(ptr++) = 0; - base += (bi->dispDeviceRowBytes >> 2); - } -} - -__inline__ void dcbst(const void* addr) -{ - __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr)); -} - -static void __pmac -flushscreen(void) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); - unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - int i,j; - - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) - { - unsigned long *ptr = base; - for(j=width; j>0; j-=8) { - dcbst(ptr); - ptr += 8; - } - base += (bi->dispDeviceRowBytes >> 2); - } -} - -#ifndef NO_SCROLL -static void __pmac -scrollscreen(void) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned long *src = (unsigned long *)calc_base(bi,0,16); - unsigned long *dst = (unsigned long *)calc_base(bi,0,0); - unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - int i,j; - -#ifdef CONFIG_ADB_PMU - pmu_suspend(); /* PMU will not shut us down ! */ -#endif - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) - { - unsigned long *src_ptr = src; - unsigned long *dst_ptr = dst; - for(j=width; j; --j) - *(dst_ptr++) = *(src_ptr++); - src += (bi->dispDeviceRowBytes >> 2); - dst += (bi->dispDeviceRowBytes >> 2); - } - for (i=0; i<16; i++) - { - unsigned long *dst_ptr = dst; - for(j=width; j; --j) - *(dst_ptr++) = 0; - dst += (bi->dispDeviceRowBytes >> 2); - } -#ifdef CONFIG_ADB_PMU - pmu_resume(); /* PMU will not shut us down ! */ -#endif -} -#endif /* ndef NO_SCROLL */ - -void __pmac -prom_drawchar(char c) -{ - unsigned long offset = reloc_offset(); - int cline = 0, x; - - if (!RELOC(bootx_text_mapped)) - return; - - switch (c) { - case '\b': - if (RELOC(g_loc_X) > 0) - --RELOC(g_loc_X); - break; - case '\t': - RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8; - break; - case '\r': - RELOC(g_loc_X) = 0; - break; - case '\n': - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y)++; - cline = 1; - break; - default: - draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y)); - } - if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) { - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y)++; - cline = 1; - } -#ifndef NO_SCROLL - while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { - scrollscreen(); - RELOC(g_loc_Y)--; - } -#else - /* wrap around from bottom to top of screen so we don't - waste time scrolling each line. -- paulus. */ - if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) - RELOC(g_loc_Y) = 0; - if (cline) { - for (x = 0; x < RELOC(g_max_loc_X); ++x) - draw_byte(' ', x, RELOC(g_loc_Y)); - } -#endif -} - -void __pmac -prom_drawstring(const char *c) -{ - unsigned long offset = reloc_offset(); - - if (!RELOC(bootx_text_mapped)) - return; - while (*c) - prom_drawchar(*c++); -} - -void __pmac -prom_drawhex(unsigned long v) -{ - static char hex_table[] = "0123456789abcdef"; - unsigned long offset = reloc_offset(); - - if (!RELOC(bootx_text_mapped)) - return; - prom_drawchar(RELOC(hex_table)[(v >> 28) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 24) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 20) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 16) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 12) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 8) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 4) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 0) & 0x0000000FUL]); -} - -static void __pmac -draw_byte(unsigned char c, long locX, long locY) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned char *base = calc_base(bi, locX << 3, locY << 4); - unsigned char *font = &RELOC(vga_font)[((unsigned long)c) * 16]; - int rb = bi->dispDeviceRowBytes; - - switch(bi->dispDeviceDepth) { - case 32: - draw_byte_32(font, (unsigned long *)base, rb); - break; - case 16: - draw_byte_16(font, (unsigned long *)base, rb); - break; - case 8: - draw_byte_8(font, (unsigned long *)base, rb); - break; - default: - break; - } -} - -static unsigned long expand_bits_8[16] __pmacdata = { - 0x00000000, - 0x000000ff, - 0x0000ff00, - 0x0000ffff, - 0x00ff0000, - 0x00ff00ff, - 0x00ffff00, - 0x00ffffff, - 0xff000000, - 0xff0000ff, - 0xff00ff00, - 0xff00ffff, - 0xffff0000, - 0xffff00ff, - 0xffffff00, - 0xffffffff -}; - -static unsigned long expand_bits_16[4] __pmacdata = { - 0x00000000, - 0x0000ffff, - 0xffff0000, - 0xffffffff -}; - -static void __pmac -draw_byte_32(unsigned char *font, unsigned long *base, int rb) -{ - int l, bits; - int fg = 0xFFFFFFFFUL; - int bg = 0x00000000UL; - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (-(bits >> 7) & fg) ^ bg; - base[1] = (-((bits >> 6) & 1) & fg) ^ bg; - base[2] = (-((bits >> 5) & 1) & fg) ^ bg; - base[3] = (-((bits >> 4) & 1) & fg) ^ bg; - base[4] = (-((bits >> 3) & 1) & fg) ^ bg; - base[5] = (-((bits >> 2) & 1) & fg) ^ bg; - base[6] = (-((bits >> 1) & 1) & fg) ^ bg; - base[7] = (-(bits & 1) & fg) ^ bg; - base = (unsigned long *) ((char *)base + rb); - } -} - -static void __pmac -draw_byte_16(unsigned char *font, unsigned long *base, int rb) -{ - int l, bits; - int fg = 0xFFFFFFFFUL; - int bg = 0x00000000UL; - unsigned long offset = reloc_offset(); - unsigned long *eb = RELOC(expand_bits_16); - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (eb[bits >> 6] & fg) ^ bg; - base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; - base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; - base[3] = (eb[bits & 3] & fg) ^ bg; - base = (unsigned long *) ((char *)base + rb); - } -} - -static void __pmac -draw_byte_8(unsigned char *font, unsigned long *base, int rb) -{ - int l, bits; - int fg = 0x0F0F0F0FUL; - int bg = 0x00000000UL; - unsigned long offset = reloc_offset(); - unsigned long *eb = RELOC(expand_bits_8); - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (eb[bits >> 4] & fg) ^ bg; - base[1] = (eb[bits & 0xf] & fg) ^ bg; - base = (unsigned long *) ((char *)base + rb); - } -} - -static unsigned char vga_font[cmapsz] __pmacdata = { -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, -0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, -0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, -0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, -0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, -0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, -0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, -0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, -0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, -0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, -0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, -0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, -0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, -0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, -0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, -0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, -0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, -0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, -0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, -0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, -0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, -0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, -0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, -0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, -0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, -0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, -0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, -0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, -0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, -0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, -0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, -0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, -0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, -0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, -0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, -0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, -0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, -0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, -0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, -0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, -0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, -0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, -0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, -0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, -0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, -0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, -0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, -0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, -0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, -0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, -0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, -0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, -0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, -0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, -0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, -0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, -0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, -0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, -0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, -0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, -0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, -0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, -0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, -0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, -0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, -0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, -0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, -0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, -0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, -0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, -0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, -0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, -0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, -0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, -}; - -#endif /* CONFIG_BOOTX_TEXT */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c --- v2.4.9/linux/arch/ppc/kernel/residual.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/residual.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.residual.c 1.7 05/17/01 18:14:22 cort + * BK Id: SCCS/s.residual.c 1.11 09/08/01 15:47:42 paulus */ /* * Code to deal with the PReP residual data. @@ -44,7 +44,7 @@ #include #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,}; RESIDUAL *res = (RESIDUAL *)&__res; -const char * PnP_BASE_TYPES[] __initdata = { +char * PnP_BASE_TYPES[] __initdata = { "Reserved", "MassStorageDevice", "NetworkInterfaceController", @@ -71,7 +71,7 @@ /* Device Sub Type Codes */ -const unsigned char * PnP_SUB_TYPES[] __initdata = { +unsigned char * PnP_SUB_TYPES[] __initdata = { "\001\000SCSIController", "\001\001IDEController", "\001\002FloppyController", @@ -128,7 +128,7 @@ /* Device Interface Type Codes */ -const unsigned char * PnP_INTERFACES[] __initdata = { +unsigned char * PnP_INTERFACES[] __initdata = { "\000\000\000General", "\001\000\000GeneralSCSI", "\001\001\000GeneralIDE", diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.4.9/linux/arch/ppc/kernel/setup.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/setup.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.setup.c 1.46 07/26/01 14:18:18 trini + * BK Id: SCCS/s.setup.c 1.57 09/08/01 15:47:42 paulus */ /* * Common prep/pmac/chrp boot and setup code. @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -28,6 +27,7 @@ #include #include #include +#include #ifdef CONFIG_8xx #include #include @@ -40,55 +40,18 @@ #include #endif #include +#include #include #include #include +#include - -extern void apus_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void chrp_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void gemini_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void m8xx_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void m8260_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void pmac_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void prep_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - +extern void platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); extern void bootx_init(unsigned long r4, unsigned long phys); extern unsigned long reloc_offset(void); +extern void identify_cpu(unsigned long offset, unsigned long cpu); +extern void do_cpu_ftr_fixups(unsigned long offset); #ifdef CONFIG_XMON extern void xmon_map_scc(void); @@ -98,6 +61,13 @@ char saved_command_line[256]; unsigned char aux_device_present; struct ide_machdep_calls ppc_ide_md; +char *sysmap; +unsigned long sysmap_size; + +/* Used with the BI_MEMSIZE bootinfo parameter to store the memory + size value reported by the boot loader. */ +unsigned int boot_mem_size; + int parse_bootinfo(void); unsigned long ISA_DMA_THRESHOLD; @@ -105,7 +75,13 @@ #ifdef CONFIG_ALL_PPC int _machine = 0; -int have_of = 0; + +extern void prep_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); +extern void pmac_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); +extern void chrp_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); #endif /* CONFIG_ALL_PPC */ #ifdef CONFIG_MAGIC_SYSRQ @@ -126,15 +102,7 @@ int icache_bsize; int ucache_bsize; -/* - * Perhaps we can put the pmac screen_info[] here - * on pmac as well so we don't need the ifdef's. - * Until we get multiple-console support in here - * that is. -- Cort - * Maybe tie it to serial consoles, since this is really what - * these processors use on existing boards. -- Dan - */ -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260) +#ifdef CONFIG_VGA_CONSOLE struct screen_info screen_info = { 0, 25, /* orig-x, orig-y */ 0, /* unused */ @@ -146,35 +114,7 @@ 1, /* orig-video-isVGA */ 16 /* orig-video-points */ }; - -/* - * I really need to add multiple-console support... -- Cort - */ -int __init pmac_display_supported(char *name) -{ - return 0; -} -void __init pmac_find_display(void) -{ -} - -#else /* CONFIG_4xx || CONFIG_8xx */ - -/* We need this to satisfy some external references until we can - * strip the kernel down. - */ -struct screen_info screen_info = { - 0, 25, /* orig-x, orig-y */ - 0, /* unused */ - 0, /* orig-video-page */ - 0, /* orig-video-mode */ - 80, /* orig-video-cols */ - 0,0,0, /* ega_ax, ega_bx, ega_cx */ - 25, /* orig-video-lines */ - 0, /* orig-video-isVGA */ - 16 /* orig-video-points */ -}; -#endif /* !CONFIG_4xx && !CONFIG_8xx */ +#endif /* CONFIG_VGA_CONSOLE */ void machine_restart(char *cmd) { @@ -190,35 +130,11 @@ { ppc_md.halt(); } - -unsigned long cpu_temp(void) -{ - unsigned char thres = 0; - -#if 0 - /* disable thrm2 */ - _set_THRM2( 0 ); - /* threshold 0 C, tid: exceeding threshold, tie: don't generate interrupt */ - _set_THRM1( THRM1_V ); - - /* we need 20us to do the compare - assume 300MHz processor clock */ - _set_THRM3(0); - _set_THRM3(THRM3_E | (300*30)<<18 ); - - udelay(100); - /* wait for the compare to complete */ - /*while ( !(_get_THRM1() & THRM1_TIV) ) ;*/ - if ( !(_get_THRM1() & THRM1_TIV) ) - printk("no tiv\n"); - if ( _get_THRM1() & THRM1_TIN ) - printk("crossed\n"); - /* turn everything off */ - _set_THRM3(0); - _set_THRM1(0); -#endif - - return thres; -} + +#ifdef CONFIG_TAU +extern u32 cpu_temp(unsigned long cpu); +extern u32 cpu_temp_both(unsigned long cpu); +#endif /* CONFIG_TAU */ int get_cpuinfo(char *buffer) { @@ -227,7 +143,7 @@ unsigned long i; unsigned int pvr; unsigned short maj, min; - + #ifdef CONFIG_SMP #define CPU_PRESENT(x) (cpu_callin_map[(x)]) #define GET_PVR ((long int)(cpu_data[i].pvr)) @@ -235,7 +151,7 @@ #else #define CPU_PRESENT(x) ((x)==0) #define smp_num_cpus 1 -#define GET_PVR ((long int)_get_PVR()) +#define GET_PVR (mfspr(PVR)) #define CD(x) (x) #endif @@ -249,90 +165,31 @@ len += sprintf(len+buffer,"cpu\t\t: "); pvr = GET_PVR; - - switch (PVR_VER(pvr)) - { - case 0x0001: - len += sprintf(len+buffer, "601\n"); - break; - case 0x0003: - len += sprintf(len+buffer, "603\n"); - break; - case 0x0004: - len += sprintf(len+buffer, "604\n"); - break; - case 0x0006: - len += sprintf(len+buffer, "603e\n"); - break; - case 0x0007: - len += sprintf(len+buffer, "603"); - if (((pvr >> 12) & 0xF) == 1) { - pvr ^= 0x00001000; /* revision fix-up */ - len += sprintf(len+buffer, "r\n"); - } else { - len += sprintf(len+buffer, "ev\n"); - } - break; - case 0x0008: /* 740/750(P) */ - case 0x1008: - len += sprintf(len+buffer, "750%s\n", - PVR_VER(pvr) == 0x1008 ? "P" : ""); - len += sprintf(len+buffer, "temperature \t: %lu C\n", - cpu_temp()); - break; - case 0x0009: /* 604e/604r */ - case 0x000A: - len += sprintf(len+buffer, "604"); - - if (PVR_VER(pvr) == 0x000A || - ((pvr >> 12) & 0xF) != 0) { - pvr &= ~0x00003000; /* revision fix-up */ - len += sprintf(len+buffer, "r\n"); - } else { - len += sprintf(len+buffer, "e\n"); - } - break; - case 0x000C: - len += sprintf(len+buffer, "7400 (G4"); + + if (cur_cpu_spec[i]->pvr_mask) + len += sprintf(len+buffer, "%s", cur_cpu_spec[i]->cpu_name); + else + len += sprintf(len+buffer, "unknown (%08x)", pvr); #ifdef CONFIG_ALTIVEC + if (cur_cpu_spec[i]->cpu_features & CPU_FTR_ALTIVEC) len += sprintf(len+buffer, ", altivec supported"); -#endif /* CONFIG_ALTIVEC */ - len += sprintf(len+buffer, ")\n"); - break; - case 0x0020: - len += sprintf(len+buffer, "403G"); - switch ((pvr >> 8) & 0xFF) { - case 0x02: - len += sprintf(len+buffer, "C\n"); - break; - case 0x14: - len += sprintf(len+buffer, "CX\n"); - break; - } - break; - case 0x0035: - len += sprintf(len+buffer, "POWER4\n"); - break; - case 0x0040: - len += sprintf(len+buffer, "POWER3 (630)\n"); - break; - case 0x0041: - len += sprintf(len+buffer, "POWER3 (630+)\n"); - break; - case 0x0050: - len += sprintf(len+buffer, "8xx\n"); - break; - case 0x0081: - len += sprintf(len+buffer, "82xx\n"); - break; - case 0x4011: - len += sprintf(len+buffer, "405GP\n"); - break; - default: - len += sprintf(len+buffer, "unknown (%08x)\n", pvr); - break; +#endif + len += sprintf(len+buffer, "\n"); +#ifdef CONFIG_TAU + if (cur_cpu_spec[i]->cpu_features & CPU_FTR_TAU) { +#ifdef CONFIG_TAU_AVERAGE /* more straightforward, but potentially misleading */ + len += sprintf(len+buffer, "temperature \t: %u C (uncalibrated)\n", + cpu_temp(i)); +#else + /* show the actual temp sensor range */ + u32 temp; + temp = cpu_temp_both(i); + len += sprintf(len+buffer, "temperature \t: %u-%u C (uncalibrated)\n", + temp & 0xff, temp >> 16); +#endif } - +#endif + /* * Assume here that all clock rates are the same in a * smp system. -- Cort @@ -394,7 +251,7 @@ } #ifdef CONFIG_SMP - if ( i ) + if ( i && smp_num_cpus > 1) len += sprintf(buffer+len, "\n"); len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n", bogosum/(500000/HZ), @@ -423,31 +280,6 @@ return len; } -#ifdef CONFIG_ALL_PPC -void __init -intuit_machine_type(void) -{ - char *model; - struct device_node *root; - - /* ask the OF info if we're a chrp or pmac */ - root = find_path_device("/"); - if (root != 0) { - /* assume pmac unless proven to be chrp -- Cort */ - _machine = _MACH_Pmac; - model = get_property(root, "device_type", NULL); - if (model && !strncmp("chrp", model, 4)) - _machine = _MACH_chrp; - else { - model = get_property(root, "model", NULL); - if (model && !strncmp(model, "IBM", 3)) - _machine = _MACH_chrp; - } - } -} -#endif /* CONFIG_ALL_PPC */ - -#if defined(CONFIG_6xx) || defined(CONFIG_PPC64BRIDGE) /* * We're called here very early in the boot. We determine the machine * type and call the appropriate low-level setup functions. @@ -472,6 +304,13 @@ * caches on yet */ memset_io(PTRRELOC(&__bss_start), 0, &_end - &__bss_start); + /* + * Identify the CPU type and fix up code sections + * that depend on which cpu we have. + */ + identify_cpu(offset, 0); + do_cpu_ftr_fixups(offset); + #if defined(CONFIG_ALL_PPC) /* If we came here from BootX, clear the screen, * set up some pointers and return. */ @@ -493,78 +332,105 @@ return phys; } -#endif /* CONFIG_6xx || CONFIG_PPC64BRIDGE */ + +#ifdef CONFIG_ALL_PPC +void __init +intuit_machine_type(void) +{ + char *model; + struct device_node *root; + + /* ask the OF info if we're a chrp or pmac */ + root = find_path_device("/"); + if (root != 0) { + /* assume pmac unless proven to be chrp -- Cort */ + _machine = _MACH_Pmac; + model = get_property(root, "device_type", NULL); + if (model && !strncmp("chrp", model, 4)) + _machine = _MACH_chrp; + else { + model = get_property(root, "model", NULL); + if (model && !strncmp(model, "IBM", 3)) + _machine = _MACH_chrp; + } + } +} /* - * Find out what kind of machine we're on and save any data we need - * from the early boot process (devtree is copied on pmac by prom_init() ) + * The ALL_PPC version of platform_init... */ -unsigned long __init -identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { -#ifdef CONFIG_CMDLINE - strcpy(cmd_line, CONFIG_CMDLINE); -#endif /* CONFIG_CMDLINE */ +#ifdef CONFIG_BOOTX_TEXT + extern boot_infos_t *disp_bi; - parse_bootinfo(); + if (disp_bi) { + btext_clearscreen(); + btext_welcome(disp_bi); + } +#endif - if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100); - -#ifdef CONFIG_ALL_PPC /* if we didn't get any bootinfo telling us what we are... */ - if ( _machine == 0 ) - { + if (_machine == 0) { /* prep boot loader tells us if we're prep or not */ if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) - { _machine = _MACH_prep; - } else - have_of = 1; } - if ( have_of ) - { - /* prom_init has already been called from __start */ - if (boot_infos) - relocate_nodes(); - /* we need to set _machine before calling finish_device_tree */ - if (_machine == 0) - intuit_machine_type(); - finish_device_tree(); - /* - * If we were booted via quik, r3 points to the physical - * address of the command-line parameters. - * If we were booted from an xcoff image (i.e. netbooted or - * booted from floppy), we get the command line from the - * bootargs property of the /chosen node. - * If an initial ramdisk is present, r3 and r4 - * are used for initrd_start and initrd_size, - * otherwise they contain 0xdeadbeef. - */ - if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) { - strncpy(cmd_line, (char *)r3 + KERNELBASE, + /* not much more to do here, if prep */ + if (_machine == _MACH_prep) { + prep_init(r3, r4, r5, r6, r7); + return; + } + + /* prom_init has already been called from __start */ + if (boot_infos) + relocate_nodes(); + + /* If we aren't PReP, we can find out if we're Pmac + * or CHRP with this. */ + if (_machine == 0) + intuit_machine_type(); + + /* finish_device_tree may need _machine defined. */ + finish_device_tree(); + + /* + * If we were booted via quik, r3 points to the physical + * address of the command-line parameters. + * If we were booted from an xcoff image (i.e. netbooted or + * booted from floppy), we get the command line from the + * bootargs property of the /chosen node. + * If an initial ramdisk is present, r3 and r4 + * are used for initrd_start and initrd_size, + * otherwise they contain 0xdeadbeef. + */ + if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) { + cmd_line[0] = 0; + strncpy(cmd_line, (char *)r3 + KERNELBASE, + sizeof(cmd_line)); + } else if (boot_infos != 0) { + /* booted by BootX - check for ramdisk */ + if (boot_infos->kernelParamsOffset != 0) + strncpy(cmd_line, (char *) boot_infos + + boot_infos->kernelParamsOffset, sizeof(cmd_line)); - } else if (boot_infos != 0) { - /* booted by BootX - check for ramdisk */ - if (boot_infos->kernelParamsOffset != 0) - strncpy(cmd_line, (char *) boot_infos - + boot_infos->kernelParamsOffset, - sizeof(cmd_line)); #ifdef CONFIG_BLK_DEV_INITRD - if (boot_infos->ramDisk) { - initrd_start = (unsigned long) boot_infos - + boot_infos->ramDisk; - initrd_end = initrd_start + boot_infos->ramDiskSize; - initrd_below_start_ok = 1; - } + if (boot_infos->ramDisk) { + initrd_start = (unsigned long) boot_infos + + boot_infos->ramDisk; + initrd_end = initrd_start + boot_infos->ramDiskSize; + initrd_below_start_ok = 1; + } #endif - } else { - struct device_node *chosen; - char *p; + } else { + struct device_node *chosen; + char *p; #ifdef CONFIG_BLK_DEV_INITRD - if (r3 && r4 && r4 != 0xdeadbeef) + if (r3 && r4 && r4 != 0xdeadbeef) { if (r3 < KERNELBASE) r3 += KERNELBASE; @@ -574,92 +440,32 @@ initrd_below_start_ok = 1; } #endif - chosen = find_devices("chosen"); - if (chosen != NULL) { - p = get_property(chosen, "bootargs", NULL); - if (p && *p) { - cmd_line[0] = 0; - strncpy(cmd_line, p, sizeof(cmd_line)); - } + chosen = find_devices("chosen"); + if (chosen != NULL) { + p = get_property(chosen, "bootargs", NULL); + if (p && *p) { + cmd_line[0] = 0; + strncpy(cmd_line, p, sizeof(cmd_line)); } } - cmd_line[sizeof(cmd_line) - 1] = 0; } -#endif /* CONFIG_ALL_PPC */ + cmd_line[sizeof(cmd_line) - 1] = 0; -#if defined(CONFIG_ALL_PPC) - switch (_machine) - { + switch (_machine) { case _MACH_Pmac: - pmac_init(r3, r4, r5, r6, r7); - break; - case _MACH_prep: - prep_init(r3, r4, r5, r6, r7); + pmac_init(r3, r4, r5, r6, r7); break; case _MACH_chrp: - chrp_init(r3, r4, r5, r6, r7); + chrp_init(r3, r4, r5, r6, r7); break; - default: - printk("Unknown machine type in identify_machine!\n"); - } -#elif defined(CONFIG_APUS) - apus_init(r3, r4, r5, r6, r7); -#elif defined(CONFIG_GEMINI) - gemini_init(r3, r4, r5, r6, r7); -#elif defined(CONFIG_4xx) - oak_init(r3, r4, r5, r6, r7); -#elif defined(CONFIG_8xx) - m8xx_init(r3, r4, r5, r6, r7); -#elif defined(CONFIG_8260) - m8260_init(r3, r4, r5, r6, r7); -#else -#error "No board type has been defined for identify_machine()!" -#endif - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260) - /* Check for nobats option (used in mapin_ram). */ - if (strstr(cmd_line, "nobats")) { - extern int __map_without_bats; - __map_without_bats = 1; - } -#endif /* !CONFIG_4xx && !CONFIG_8xx && !CONFIG_8260 */ - - /* Look for mem= option on command line */ - if (strstr(cmd_line, "mem=")) { - char *p, *q; - unsigned long maxmem = 0; - extern unsigned long __max_memory; - - for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { - q = p + 4; - if (p > cmd_line && p[-1] != ' ') - continue; - maxmem = simple_strtoul(q, &q, 0); - if (*q == 'k' || *q == 'K') { - maxmem <<= 10; - ++q; - } else if (*q == 'm' || *q == 'M') { - maxmem <<= 20; - ++q; - } - } - __max_memory = maxmem; } - - /* this is for modules since _machine can be a define -- Cort */ - ppc_md.ppc_machine = _machine; - - if ( ppc_md.progress ) ppc_md.progress("id mach(): done", 0x200); - - return 0; } +#endif /* CONFIG_ALL_PPC */ int parse_bootinfo(void) { struct bi_record *rec; extern char __bss_start[]; - extern char *sysmap; - extern unsigned long sysmap_size; rec = (struct bi_record *)_ALIGN((ulong)__bss_start+(1<<20)-1,(1<<20)); if ( rec->tag != BI_FIRST ) @@ -696,20 +502,43 @@ #ifdef CONFIG_ALL_PPC case BI_MACHTYPE: _machine = data[0]; - have_of = data[1]; break; #endif /* CONFIG_ALL_PPC */ + case BI_MEMSIZE: + boot_mem_size = data[0]; + break; } } return 0; } +/* + * Find out what kind of machine we're on and save any data we need + * from the early boot process (devtree is copied on pmac by prom_init()). + * This is called very early on the boot process, after a minimal + * MMU environment has been set up but before MMU_init is called. + */ +void __init +machine_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ +#ifdef CONFIG_CMDLINE + strcpy(cmd_line, CONFIG_CMDLINE); +#endif /* CONFIG_CMDLINE */ + + parse_bootinfo(); + + platform_init(r3, r4, r5, r6, r7); + + if (ppc_md.progress) + ppc_md.progress("id mach(): done", 0x200); +} + /* Checks "l2cr=xxxx" command-line option */ -int ppc_setup_l2cr(char *str) +int __init ppc_setup_l2cr(char *str) { - if ( ((_get_PVR() >> 16) == 8) || ((_get_PVR() >> 16) == 12) ) - { + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) { unsigned long val = simple_strtoul(str, NULL, 0); printk(KERN_INFO "l2cr set to %lx\n", val); _set_L2CR(0); /* force invalidate by disable cache */ @@ -761,18 +590,13 @@ * Systems with OF can look in the properties on the cpu node(s) * for a possibly more accurate value. */ - dcache_bsize = icache_bsize = 32; /* most common value */ - switch (_get_PVR() >> 16) { - case 1: /* 601, with unified cache */ - ucache_bsize = 32; - break; - /* XXX need definitions in here for 8xx etc. */ - case 0x40: - case 0x41: - case 0x35: /* 64-bit POWER3, POWER3+, POWER4 */ - dcache_bsize = icache_bsize = 128; - break; - } + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPLIT_ID_CACHE) { + dcache_bsize = cur_cpu_spec[0]->dcache_bsize; + icache_bsize = cur_cpu_spec[0]->icache_bsize; + ucache_bsize = 0; + } else + ucache_bsize = dcache_bsize = icache_bsize + = cur_cpu_spec[0]->dcache_bsize; /* reboot on panic */ panic_timeout = 180; @@ -813,6 +637,9 @@ paging_init(); sort_exception_table(); + + /* this is for modules since _machine can be a define -- Cort */ + ppc_md.ppc_machine = _machine; } /* Convert the shorts/longs in hd_driveid from little to big endian; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S --- v2.4.9/linux/arch/ppc/kernel/sleep.S Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/sleep.S Tue Aug 28 06:58:33 2001 @@ -1,10 +1,10 @@ /* - * BK Id: SCCS/s.sleep.S 1.10 06/28/01 15:50:17 paulus + * BK Id: SCCS/s.sleep.S 1.13 08/19/01 22:23:04 paulus */ /* * This file contains sleep low-level functions for PowerBook G3. * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org) - * and Paul Mackerras (paulus@cs.anu.edu.au). + * and Paul Mackerras (paulus@samba.org). * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -45,7 +45,13 @@ #define tovirt(rd,rs) addis rd,rs,KERNELBASE@h .text + .align 5 +/* This gets called by via-pmu.c late during the sleep process. + * The PMU was already send the sleep command and will shut us down + * soon. We need to save all that is needed and setup the wakeup + * vector that will be called by the ROM on wakeup + */ _GLOBAL(low_sleep_handler) mflr r0 stw r0,4(r1) @@ -53,13 +59,14 @@ stw r2,SL_R2(r1) stmw r12,SL_R12(r1) - /* Save MSR, SDR1, TB */ + /* Save MSR & SDR1 */ mfmsr r4 stw r4,SL_MSR(r1) mfsdr1 r4 stw r4,SL_SDR1(r1) -1: - mftbu r4 + + /* Get a stable timebase and save it */ +1: mftbu r4 stw r4,SL_TB(r1) mftb r5 stw r5,SL_TB+4(r1) @@ -114,10 +121,19 @@ /* Save HID0 */ mfspr r4,HID0 stw r4,SL_HID0(r1) - - /* Set up stuff at address 0 */ - lis r5,wake_up@ha - addi r5,r5,wake_up@l + + /* The ROM can wake us up via 2 different vectors: + * - On wallstreet & lombard, we must write a magic + * value 'Lars' at address 4 and a pointer to a + * memory location containing the PC to resume from + * at address 0. + * - On Core99, we must store the wakeup vector at + * address 0x80 and eventually it's parameters + * at address 0x84. I've have some trouble with those + * parameters however and I no longer use them. + */ + lis r5,grackle_wake_up@ha + addi r5,r5,grackle_wake_up@l tophys(r5,r5) stw r5,SL_PC(r1) lis r4,KERNELBASE@h @@ -127,22 +143,35 @@ addi r6,r6,MAGIC@l stw r5,0(r4) stw r6,4(r4) + /* Setup stuffs at 0x80-0x84 for Core99 */ + lis r3,core99_wake_up@ha + addi r3,r3,core99_wake_up@l + tophys(r3,r3) + stw r3,0x80(r4) + stw r5,0x84(r4) + /* Store a pointer to our backup storage into + * a kernel global + */ + lis r3,sleep_storage@ha + addi r3,r3,sleep_storage@l + stw r5,0(r3) + /* - * Flush the L1 data cache by reading the first 64kB of RAM + * Flush the L1 data cache by reading the first 128kB of RAM * and then flushing the same area with the dcbf instruction. * The L2 cache has already been disabled. */ - li r4,0x0800 /* 64kB / 32B */ + li r4,0x1000 /* 128kB / 32B */ mtctr r4 lis r4,KERNELBASE@h 1: lwz r0,0(r4) - addi r4,r4,0x0020 /* Go to start of next cache line */ + addi r4,r4,0x0020 /* Go to start of next cache line */ bdnz 1b sync - li r4,0x0800 /* 64k */ + li r4,0x1000 /* 128kB / 32B */ mtctr r4 lis r4,KERNELBASE@h 1: @@ -160,7 +189,13 @@ sync mtspr HID0,r2 sync - + +/* This loop puts us back to sleep in case we have a spurrious + * wakeup so that the host bridge properly stays asleep. The + * CPU will be turned off, either after a known time (about 1 + * second) on wallstreet & lombard, or as soon as the CPU enters + * SLEEP mode on core99 + */ mfmsr r2 oris r2,r2,MSR_POW@h 1: sync @@ -170,22 +205,66 @@ /* * Here is the resume code. + */ + + +/* + * Core99 machines resume here + * r4 has the physical address of SL_PC(sp) (unused) + */ +_GLOBAL(core99_wake_up) + /* Make sure HID0 no longer contains any sleep bit */ + mfspr r3,HID0 + rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */ + mtspr HID0,r3 + sync + isync + + /* Won't that cause problems on CPU that doesn't support it ? */ + lis r3, 0 + mtspr SPRN_MMCR0, r3 + + /* sanitize MSR */ + mfmsr r3 + ori r3,r3,MSR_EE|MSR_IP + xori r3,r3,MSR_EE|MSR_IP + sync + isync + mtmsr r3 + sync + isync + + /* Recover sleep storage */ + lis r3,sleep_storage@ha + addi r3,r3,sleep_storage@l + tophys(r3,r3) + lwz r1,0(r3) + + /* Pass thru to older resume code ... */ +/* + * Here is the resume code for older machines. * r1 has the physical address of SL_PC(sp). */ -wake_up: - /* Flash inval the instruction cache */ +grackle_wake_up: + /* Enable and then Flash inval the instruction & data cache */ mfspr r3,HID0 - ori r3,r3, HID0_ICFI - mtspr HID0,r3 + ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI + sync isync - /* Restore the HID0 register. This turns on the L1 caches. */ + mtspr HID0,r3 + xori r3,r3, HID0_ICFI|HID0_DCI + mtspr HID0,r3 + sync + + /* Restore the remaining bits of the HID0 register. */ subi r1,r1,SL_PC lwz r3,SL_HID0(r1) sync isync mtspr HID0,r3 sync + isync /* Restore the kernel's segment registers, the BATs, and SDR1. Then we can turn on the MMU. */ @@ -242,6 +321,13 @@ lwz r4,SL_IBAT3+4(r1) mtibatl 3,r4 + /* Flush all TLBs */ + lis r4,0x1000 +1: addic. r4,r4,-0x1000 + tlbie r4 + blt 1b + sync + /* restore the MSR and turn on the MMU */ lwz r3,SL_MSR(r1) bl turn_on_mmu @@ -250,6 +336,8 @@ tovirt(r1,r1) /* Restore TB */ + li r3,0 + mttbl r3 lwz r3,SL_TB(r1) lwz r4,SL_TB+4(r1) mttbu r3 @@ -269,4 +357,10 @@ mtsrr0 r4 mtsrr1 r3 sync + isync rfi + + .data + .globl sleep_storage +sleep_storage: + .long 0 diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.4.9/linux/arch/ppc/kernel/smp.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/smp.c Sat Sep 8 12:38:42 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.smp.c 1.25 05/23/01 00:38:42 cort + * BK Id: SCCS/s.smp.c 1.31 09/08/01 15:47:42 paulus */ /* * Smp support for ppc. @@ -9,11 +9,6 @@ * * Copyright (C) 1999 Cort Dougan * - * Support for PReP (Motorola MTX/MVME) and Macintosh G4 SMP - * by Troy Benjegerdes (hozer@drgw.net) - * - * Support for DayStar quad CPU cards - * Copyright (C) XLR8, Inc. 1994-2000 */ #include @@ -36,16 +31,15 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include "open_pic.h" + int smp_threads_ready; volatile int smp_commenced; int smp_num_cpus = 1; @@ -54,13 +48,14 @@ struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 }; atomic_t ipi_recv; atomic_t ipi_sent; -spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; +spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED; unsigned int prof_multiplier[NR_CPUS]; unsigned int prof_counter[NR_CPUS]; cycles_t cacheflush_time; static int max_cpus __initdata = NR_CPUS; unsigned long cpu_online_map; int smp_hw_index[NR_CPUS]; +static struct smp_ops_t *smp_ops; /* all cpu mappings are 1-1 -- Cort */ volatile unsigned long cpu_callin_map[NR_CPUS]; @@ -74,60 +69,6 @@ void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); -extern void __secondary_start_psurge(void); -extern void __secondary_start_psurge2(void); /* Temporary horrible hack */ -extern void __secondary_start_psurge3(void); /* Temporary horrible hack */ - -/* Addresses for powersurge registers */ -#define HAMMERHEAD_BASE 0xf8000000 -#define HHEAD_CONFIG 0x90 -#define HHEAD_SEC_INTR 0xc0 - -/* register for interrupting the primary processor on the powersurge */ -/* N.B. this is actually the ethernet ROM! */ -#define PSURGE_PRI_INTR 0xf3019000 - -/* register for storing the start address for the secondary processor */ -/* N.B. this is the PCI config space address register for the 1st bridge */ -#define PSURGE_START 0xf2800000 - -/* Daystar/XLR8 4-CPU card */ -#define PSURGE_QUAD_REG_ADDR 0xf8800000 - -#define PSURGE_QUAD_IRQ_SET 0 -#define PSURGE_QUAD_IRQ_CLR 1 -#define PSURGE_QUAD_IRQ_PRIMARY 2 -#define PSURGE_QUAD_CKSTOP_CTL 3 -#define PSURGE_QUAD_PRIMARY_ARB 4 -#define PSURGE_QUAD_BOARD_ID 6 -#define PSURGE_QUAD_WHICH_CPU 7 -#define PSURGE_QUAD_CKSTOP_RDBK 8 -#define PSURGE_QUAD_RESET_CTL 11 - -#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v))) -#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f) -#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) -#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) - -/* virtual addresses for the above */ -static volatile u8 *hhead_base; -static volatile u8 *quad_base; -static volatile u32 *psurge_pri_intr; -static volatile u8 *psurge_sec_intr; -static volatile u32 *psurge_start; - -/* what sort of powersurge board we have */ -static int psurge_type; - -/* values for psurge_type */ -#define PSURGE_DUAL 0 -#define PSURGE_QUAD_OKEE 1 -#define PSURGE_QUAD_COTTON 2 -#define PSURGE_QUAD_ICEGRASS 3 - -/* l2 cache stuff for dual G4 macs */ -extern void core99_init_l2(void); - /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. * * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up @@ -137,621 +78,12 @@ #define PPC_MSG_INVALIDATE_TLB 2 #define PPC_MSG_XMON_BREAK 3 -static inline void set_tb(unsigned int upper, unsigned int lower) -{ - mtspr(SPRN_TBWL, 0); - mtspr(SPRN_TBWU, upper); - mtspr(SPRN_TBWL, lower); -} - -/* - * Set and clear IPIs for powersurge. - */ -static inline void psurge_set_ipi(int cpu) -{ - if (cpu == 0) - in_be32(psurge_pri_intr); - else if (psurge_type == PSURGE_DUAL) - out_8(psurge_sec_intr, 0); - else - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); -} - -static inline void psurge_clr_ipi(int cpu) -{ - if (cpu > 0) { - if (psurge_type == PSURGE_DUAL) - out_8(psurge_sec_intr, ~0); - else - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); - } -} - -/* - * On powersurge (old SMP powermac architecture) we don't have - * separate IPIs for separate messages like openpic does. Instead - * we have a bitmap for each processor, where a 1 bit means that - * the corresponding message is pending for that processor. - * Ideally each cpu's entry would be in a different cache line. - * -- paulus. - */ -static unsigned long psurge_smp_message[NR_CPUS]; - -void psurge_smp_message_recv(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - int msg; - - /* clear interrupt */ - psurge_clr_ipi(cpu); - - if (smp_num_cpus < 2) - return; - - /* make sure there is a message there */ - for (msg = 0; msg < 4; msg++) - if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) - smp_message_recv(msg, regs); -} - -void -psurge_primary_intr(int irq, void *d, struct pt_regs *regs) -{ - psurge_smp_message_recv(regs); -} - -static void -smp_psurge_message_pass(int target, int msg, unsigned long data, int wait) -{ - int i; - - if (smp_num_cpus < 2) - return; - - for (i = 0; i < smp_num_cpus; i++) { - if (target == MSG_ALL - || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) - || target == i) { - set_bit(msg, &psurge_smp_message[i]); - psurge_set_ipi(i); - } - } -} - -/* - * Determine a quad card presence. We read the board ID register, we - * force the data bus to change to something else, and we read it again. - * It it's stable, then the register probably exist (ugh !) - */ -static int __init psurge_quad_probe(void) -{ - int type; - unsigned int i; - - type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); - if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS - || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) - return PSURGE_DUAL; - - /* looks OK, try a slightly more rigorous test */ - /* bogus is not necessarily cacheline-aligned, - though I don't suppose that really matters. -- paulus */ - for (i = 0; i < 100; i++) { - volatile u32 bogus[8]; - bogus[(0+i)%8] = 0x00000000; - bogus[(1+i)%8] = 0x55555555; - bogus[(2+i)%8] = 0xFFFFFFFF; - bogus[(3+i)%8] = 0xAAAAAAAA; - bogus[(4+i)%8] = 0x33333333; - bogus[(5+i)%8] = 0xCCCCCCCC; - bogus[(6+i)%8] = 0xCCCCCCCC; - bogus[(7+i)%8] = 0x33333333; - wmb(); - asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); - mb(); - if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) - return PSURGE_DUAL; - } - return type; -} - -static void __init psurge_quad_init(void) -{ - int procbits; - - if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); - procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); - if (psurge_type == PSURGE_QUAD_ICEGRASS) - PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); - else - PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); - mdelay(33); - out_8(psurge_sec_intr, ~0); - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); - PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); - if (psurge_type != PSURGE_QUAD_ICEGRASS) - PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); - PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); - mdelay(33); - PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); - mdelay(33); - PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); - mdelay(33); -} - -static int __init smp_psurge_probe(void) -{ - int i, ncpus; - - /* We don't do SMP on the PPC601 -- paulus */ - if ((_get_PVR() >> 16) == 1) - return 1; - - /* - * The powersurge cpu board can be used in the generation - * of powermacs that have a socket for an upgradeable cpu card, - * including the 7500, 8500, 9500, 9600. - * The device tree doesn't tell you if you have 2 cpus because - * OF doesn't know anything about the 2nd processor. - * Instead we look for magic bits in magic registers, - * in the hammerhead memory controller in the case of the - * dual-cpu powersurge board. -- paulus. - */ - if (find_devices("hammerhead") == NULL) - return 1; - - hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); - quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); - psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; - - psurge_type = psurge_quad_probe(); - if (psurge_type != PSURGE_DUAL) { - psurge_quad_init(); - /* All released cards using this HW design have 4 CPUs */ - ncpus = 4; - } else { - iounmap((void *) quad_base); - if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { - /* not a dual-cpu card */ - iounmap((void *) hhead_base); - return 1; - } - ncpus = 2; - } - - psurge_start = ioremap(PSURGE_START, 4); - psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); - - /* this is not actually strictly necessary -- paulus. */ - for (i = 1; i < ncpus; ++i) - smp_hw_index[i] = i; - - if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); - - return ncpus; -} - -static void __init smp_psurge_kick_cpu(int nr) -{ - void (*start)(void) = __secondary_start_psurge; - - if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); - - /* setup entry point of secondary processor */ - switch (nr) { - case 2: - start = __secondary_start_psurge2; - break; - case 3: - start = __secondary_start_psurge3; - break; - } - - out_be32(psurge_start, __pa(start)); - mb(); - - psurge_set_ipi(nr); - udelay(10); - psurge_clr_ipi(nr); - - if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); -} - -/* - * With the dual-cpu powersurge board, the decrementers and timebases - * of both cpus are frozen after the secondary cpu is started up, - * until we give the secondary cpu another interrupt. This routine - * uses this to get the timebases synchronized. - * -- paulus. - */ -static void __init psurge_dual_sync_tb(int cpu_nr) -{ - static volatile int sec_tb_reset = 0; - int t; - - set_dec(tb_ticks_per_jiffy); - set_tb(0, 0); - last_jiffy_stamp(cpu_nr) = 0; - - if (cpu_nr > 0) { - mb(); - sec_tb_reset = 1; - return; - } - - /* wait for the secondary to have reset its TB before proceeding */ - for (t = 10000000; t > 0 && !sec_tb_reset; --t) - ; - - /* now interrupt the secondary, starting both TBs */ - psurge_set_ipi(1); - - smp_tb_synchronized = 1; -} - -static void -smp_psurge_setup_cpu(int cpu_nr) -{ - - if (cpu_nr == 0) { - if (smp_num_cpus < 2) - return; - /* reset the entry point so if we get another intr we won't - * try to startup again */ - out_be32(psurge_start, 0x100); - if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0)) - printk(KERN_ERR "Couldn't get primary IPI interrupt"); - } - - if (psurge_type == PSURGE_DUAL) - psurge_dual_sync_tb(cpu_nr); -} - - -static void -smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) -{ - /* make sure we're sending something that translates to an IPI */ - if ( msg > 0x3 ){ - printk("SMP %d: smp_message_pass: unknown msg %d\n", - smp_processor_id(), msg); - return; - } - switch ( target ) - { - case MSG_ALL: - openpic_cause_IPI(msg, 0xffffffff); - break; - case MSG_ALL_BUT_SELF: - openpic_cause_IPI(msg, - 0xffffffff & ~(1 << smp_processor_id())); - break; - default: - openpic_cause_IPI(msg, 1<next) != NULL) - ++ncpus; - printk("smp_core99_probe: found %d cpus\n", ncpus); - if (ncpus > 1) { - openpic_request_IPIs(); - for (i = 1; i < ncpus; ++i) - smp_hw_index[i] = i; - } - - return ncpus; -} - -static void -smp_core99_kick_cpu(int nr) -{ - unsigned long save_vector, new_vector; - unsigned long flags; -#if 1 /* New way... */ - volatile unsigned long *vector - = ((volatile unsigned long *)(KERNELBASE+0x100)); - if (nr < 1 || nr > 3) - return; -#else - volatile unsigned long *vector - = ((volatile unsigned long *)(KERNELBASE+0x500)); - if (nr != 1) - return; -#endif - if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); - - local_irq_save(flags); - local_irq_disable(); - - /* Save reset vector */ - save_vector = *vector; - - /* Setup fake reset vector that does - * b __secondary_start_psurge - KERNELBASE - */ - switch(nr) { - case 1: - new_vector = (unsigned long)__secondary_start_psurge; - break; - case 2: - new_vector = (unsigned long)__secondary_start_psurge2; - break; - case 3: - new_vector = (unsigned long)__secondary_start_psurge3; - break; - } - *vector = 0x48000002 + new_vector - KERNELBASE; - - /* flush data cache and inval instruction cache */ - flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); - - /* Put some life in our friend */ - feature_core99_kick_cpu(nr); - - /* FIXME: We wait a bit for the CPU to take the exception, I should - * instead wait for the entry code to set something for me. Well, - * ideally, all that crap will be done in prom.c and the CPU left - * in a RAM-based wait loop like CHRP. - */ - mdelay(1); - - /* Restore our exception vector */ - *vector = save_vector; - flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); - - local_irq_restore(flags); - if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); -} - -static void -smp_core99_setup_cpu(int cpu_nr) -{ - /* Setup openpic */ - do_openpic_setup_cpu(); - - /* Setup L2 */ - if (cpu_nr != 0) - core99_init_l2(); - else - if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); -} - -static int -smp_chrp_probe(void) -{ - extern unsigned long smp_chrp_cpu_nr; - - if (smp_chrp_cpu_nr > 1) - openpic_request_IPIs(); - - return smp_chrp_cpu_nr; -} - -static void -smp_chrp_kick_cpu(int nr) -{ - *(unsigned long *)KERNELBASE = nr; - asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); -} - -static void -smp_chrp_setup_cpu(int cpu_nr) -{ - static atomic_t ready = ATOMIC_INIT(1); - static volatile int frozen = 0; - - if (cpu_nr == 0) { - /* wait for all the others */ - while (atomic_read(&ready) < smp_num_cpus) - barrier(); - atomic_set(&ready, 1); - /* freeze the timebase */ - call_rtas("freeze-time-base", 0, 1, NULL); - mb(); - frozen = 1; - /* XXX assumes this is not a 601 */ - set_tb(0, 0); - last_jiffy_stamp(0) = 0; - while (atomic_read(&ready) < smp_num_cpus) - barrier(); - /* thaw the timebase again */ - call_rtas("thaw-time-base", 0, 1, NULL); - mb(); - frozen = 0; - smp_tb_synchronized = 1; - } else { - atomic_inc(&ready); - while (!frozen) - barrier(); - set_tb(0, 0); - last_jiffy_stamp(0) = 0; - mb(); - atomic_inc(&ready); - while (frozen) - barrier(); - } - - if (OpenPIC_Addr) - do_openpic_setup_cpu(); -} - -#ifdef CONFIG_POWER4 -static void -smp_xics_message_pass(int target, int msg, unsigned long data, int wait) -{ - /* for now, only do reschedule messages - since we only have one IPI */ - if (msg != PPC_MSG_RESCHEDULE) - return; - for (i = 0; i < smp_num_cpus; ++i) { - if (target == MSG_ALL || target == i - || (target == MSG_ALL_BUT_SELF - && i != smp_processor_id())) - xics_cause_IPI(i); - } -} - -static int -smp_xics_probe(void) -{ - return smp_chrp_cpu_nr; -} - -static void -smp_xics_setup_cpu(int cpu_nr) -{ - if (cpu_nr > 0) - xics_setup_cpu(); -} -#endif /* CONFIG_POWER4 */ - -static int -smp_prep_probe(void) -{ - extern int mot_multi; - - if (mot_multi) { - openpic_request_IPIs(); - smp_hw_index[1] = 1; - return 2; - } - - return 1; -} - -static void -smp_prep_kick_cpu(int nr) -{ - extern unsigned long *MotSave_SmpIar; - extern unsigned char *MotSave_CpusState[2]; - - *MotSave_SmpIar = (unsigned long)__secondary_start_psurge - KERNELBASE; - *MotSave_CpusState[1] = CPU_GOOD; - printk("CPU1 reset, waiting\n"); -} - -static void -smp_prep_setup_cpu(int cpu_nr) -{ - if (OpenPIC_Addr) - do_openpic_setup_cpu(); -} - -#ifdef CONFIG_GEMINI -static int -smp_gemini_probe(void) -{ - int i, nr; - - nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2; - if (nr == 0) - nr = 4; - - if (nr > 1) { - openpic_request_IPIs(); - for (i = 1; i < nr; ++i) - smp_hw_index[i] = i; - } - - return nr; -} - -static void -smp_gemini_kick_cpu(int nr) -{ - openpic_init_processor( 1< 0) - gemini_init_l2(); -} -#endif /* CONFIG_GEMINI */ - - -static struct smp_ops_t { - void (*message_pass)(int target, int msg, unsigned long data, int wait); - int (*probe)(void); - void (*kick_cpu)(int nr); - void (*setup_cpu)(int nr); - -} *smp_ops; - #define smp_message_pass(t,m,d,w) \ do { if (smp_ops) \ atomic_inc(&ipi_sent); \ smp_ops->message_pass((t),(m),(d),(w)); \ } while(0) - -/* PowerSurge-style Macs */ -static struct smp_ops_t psurge_smp_ops = { - smp_psurge_message_pass, - smp_psurge_probe, - smp_psurge_kick_cpu, - smp_psurge_setup_cpu, -}; - -/* Core99 Macs (dual G4s) */ -static struct smp_ops_t core99_smp_ops = { - smp_openpic_message_pass, - smp_core99_probe, - smp_core99_kick_cpu, - smp_core99_setup_cpu, -}; - -/* CHRP with openpic */ -static struct smp_ops_t chrp_smp_ops = { - smp_openpic_message_pass, - smp_chrp_probe, - smp_chrp_kick_cpu, - smp_chrp_setup_cpu, -}; - -#ifdef CONFIG_POWER4 -/* CHRP with new XICS interrupt controller */ -static struct smp_ops_t xics_smp_ops = { - smp_xics_message_pass, - smp_xics_probe, - smp_chrp_kick_cpu, - smp_xics_setup_cpu, -}; -#endif /* CONFIG_POWER4 */ - -/* PReP (MTX) */ -static struct smp_ops_t prep_smp_ops = { - smp_openpic_message_pass, - smp_prep_probe, - smp_prep_kick_cpu, - smp_prep_setup_cpu, -}; - -#ifdef CONFIG_GEMINI -/* Gemini */ -static struct smp_ops_t gemini_smp_ops = { - smp_openpic_message_pass, - smp_gemini_probe, - smp_gemini_kick_cpu, - smp_gemini_setup_cpu, -}; -#endif /* CONFIG_GEMINI */ - /* * Common functions */ @@ -798,7 +130,7 @@ */ void smp_send_tlb_invalidate(int cpu) { - if ( (_get_PVR()>>16) == 8 ) + if ( PVR_VER(mfspr(PVR)) == 8 ) smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB, 0, 0); } @@ -947,7 +279,6 @@ extern struct task_struct *current_set[NR_CPUS]; int i, cpu_nr; struct task_struct *p; - unsigned long a; printk("Entering SMP Mode...\n"); smp_num_cpus = 1; @@ -973,35 +304,12 @@ */ cacheflush_time = 5 * 1024; - /* To be later replaced by some arch-specific routine */ - switch(_machine) { - case _MACH_Pmac: - /* Check for Core99 */ - if (find_devices("uni-n")) - smp_ops = &core99_smp_ops; - else - smp_ops = &psurge_smp_ops; - break; - case _MACH_chrp: -#ifndef CONFIG_POWER4 - smp_ops = &chrp_smp_ops; -#else - smp_ops = &xics_smp_ops; -#endif /* CONFIG_POWER4 */ - break; - case _MACH_prep: - smp_ops = &prep_smp_ops; - break; -#ifdef CONFIG_GEMINI - case _MACH_gemini: - smp_ops = &gemini_smp_ops; - break; -#endif /* CONFIG_GEMINI */ - default: + smp_ops = ppc_md.smp_ops; + if (smp_ops == NULL) { printk("SMP not supported on this machine.\n"); return; } - + /* Probe arch for CPUs */ cpu_nr = smp_ops->probe(); @@ -1044,10 +352,12 @@ p->has_cpu = 1; current_set[i] = p; - /* need to flush here since secondary bats aren't setup */ - for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) - asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); - asm volatile("sync"); + /* + * There was a cache flush loop here to flush the cache + * to memory for the first 8MB of RAM. The cache flush + * has been pushed into the kick_cpu function for those + * platforms that need it. + */ /* wake up cpus */ smp_ops->kick_cpu(i); @@ -1155,7 +465,6 @@ /* so time.c doesn't get confused */ set_dec(tb_ticks_per_jiffy); last_jiffy_stamp(cpu) = 0; - cpu_callin_map[cpu] = 1; } void __init smp_commence(void) @@ -1247,7 +556,7 @@ /* assume bogomips are same for everything */ c->loops_per_jiffy = loops_per_jiffy; - c->pvr = _get_PVR(); + c->pvr = mfspr(PVR); } static int __init maxcpus(char *str) diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/temp.c linux/arch/ppc/kernel/temp.c --- v2.4.9/linux/arch/ppc/kernel/temp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/temp.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,278 @@ +/* + * temp.c Thermal management for cpu's with Thermal Assist Units + * + * Written by Troy Benjegerdes + * + * TODO: + * dynamic power management to limit peak CPU temp (using ICTC) + * calibration??? + * + * Silly, crazy ideas: use cpu load (from scheduler) and ICTC to extend battery + * life in portables, and add a 'performance/watt' metric somewhere in /proc + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static struct tau_temp +{ + int interrupts; + unsigned char low; + unsigned char high; + unsigned char grew; +} tau[NR_CPUS]; + +struct timer_list tau_timer; + +#undef DEBUG + +/* TODO: put these in a /proc interface, with some sanity checks, and maybe + * dynamic adjustment to minimize # of interrupts */ +/* configurable values for step size and how much to expand the window when + * we get an interrupt. These are based on the limit that was out of range */ +#define step_size 2 /* step size when temp goes out of range */ +#define window_expand 1 /* expand the window by this much */ +/* configurable values for shrinking the window */ +#define shrink_timer 2*HZ /* period between shrinking the window */ +#define min_window 2 /* minimum window size, degrees C */ + +void set_thresholds(unsigned long cpu) +{ +#ifdef CONFIG_TAU_INT + /* + * setup THRM1, + * threshold, valid bit, enable interrupts, interrupt when below threshold + */ + mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TIE | THRM1_TID); + + /* setup THRM2, + * threshold, valid bit, enable interrupts, interrupt when above threshhold + */ + mtspr (SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | THRM1_TIE); +#else + /* same thing but don't enable interrupts */ + mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TID); + mtspr(SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V); +#endif +} + +void TAUupdate(int cpu) +{ + unsigned thrm; + +#ifdef DEBUG + printk("TAUupdate "); +#endif + + /* if both thresholds are crossed, the step_sizes cancel out + * and the window winds up getting expanded twice. */ + if((thrm = mfspr(SPRN_THRM1)) & THRM1_TIV){ /* is valid? */ + if(thrm & THRM1_TIN){ /* crossed low threshold */ + if (tau[cpu].low >= step_size){ + tau[cpu].low -= step_size; + tau[cpu].high -= (step_size - window_expand); + } + tau[cpu].grew = 1; +#ifdef DEBUG + printk("low threshold crossed "); +#endif + } + } + if((thrm = mfspr(SPRN_THRM2)) & THRM1_TIV){ /* is valid? */ + if(thrm & THRM1_TIN){ /* crossed high threshold */ + if (tau[cpu].high <= 127-step_size){ + tau[cpu].low += (step_size - window_expand); + tau[cpu].high += step_size; + } + tau[cpu].grew = 1; +#ifdef DEBUG + printk("high threshold crossed "); +#endif + } + } + +#ifdef DEBUG + printk("grew = %d\n", tau[cpu].grew); +#endif + +#ifndef CONFIG_TAU_INT /* tau_timeout will do this if not using interrupts */ + set_thresholds(cpu); +#endif + +} + +#ifdef CONFIG_TAU_INT +/* + * TAU interrupts - called when we have a thermal assist unit interrupt + * with interrupts disabled + */ + +void TAUException(struct pt_regs * regs) +{ + unsigned long cpu = smp_processor_id(); + + hardirq_enter(cpu); + tau[cpu].interrupts++; + + TAUupdate(cpu); + + hardirq_exit(cpu); + return; +} +#endif /* CONFIG_TAU_INT */ + +static void tau_timeout(void * info) +{ + unsigned long cpu = smp_processor_id(); + unsigned long flags; + int size; + int shrink; + + /* disabling interrupts *should* be okay */ + save_flags(flags); cli(); + +#ifndef CONFIG_TAU_INT + TAUupdate(cpu); +#endif + + size = tau[cpu].high - tau[cpu].low; + if (size > min_window && ! tau[cpu].grew) { + /* do an exponential shrink of half the amount currently over size */ + shrink = (2 + size - min_window) / 4; + if (shrink) { + tau[cpu].low += shrink; + tau[cpu].high -= shrink; + } else { /* size must have been min_window + 1 */ + tau[cpu].low += 1; +#if 1 /* debug */ + if ((tau[cpu].high - tau[cpu].low) != min_window){ + printk(KERN_ERR "temp.c: line %d, logic error\n", __LINE__); + } +#endif + } + } + + tau[cpu].grew = 0; + + set_thresholds(cpu); + + /* + * Do the enable every time, since otherwise a bunch of (relatively) + * complex sleep code needs to be added. One mtspr every time + * tau_timeout is called is probably not a big deal. + * + * Enable thermal sensor and set up sample interval timer + * need 20 us to do the compare.. until a nice 'cpu_speed' function + * call is implemented, just assume a 500 mhz clock. It doesn't really + * matter if we take too long for a compare since it's all interrupt + * driven anyway. + * + * use a extra long time.. (60 us @ 500 mhz) + */ + mtspr(SPRN_THRM3, THRM3_SITV(500*60) | THRM3_E); + + restore_flags(flags); +} + +static void tau_timeout_smp(unsigned long unused) +{ + + /* schedule ourselves to be run again */ + mod_timer(&tau_timer, jiffies + shrink_timer) ; +#ifdef CONFIG_SMP + smp_call_function(tau_timeout, NULL, 1, 0); +#endif + tau_timeout(NULL); +} + +/* + * setup the TAU + * + * Set things up to use THRM1 as a temperature lower bound, and THRM2 as an upper bound. + * Start off at zero + */ + +int tau_initialized = 0; + +void __init TAU_init_smp(void * info) +{ + unsigned long cpu = smp_processor_id(); + + /* set these to a reasonable value and let the timer shrink the + * window */ + tau[cpu].low = 5; + tau[cpu].high = 120; + + set_thresholds(cpu); +} + +int __init TAU_init(void) +{ + /* We assume in SMP that if one CPU has TAU support, they + * all have it --BenH + */ + if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_TAU)) { + printk("Thermal assist unit not available\n"); + tau_initialized = 0; + return 1; + } + + + /* first, set up the window shrinking timer */ + init_timer(&tau_timer); + tau_timer.function = tau_timeout_smp; + tau_timer.expires = jiffies + shrink_timer; + add_timer(&tau_timer); + +#ifdef CONFIG_SMP + smp_call_function(TAU_init_smp, NULL, 1, 0); +#endif + TAU_init_smp(NULL); + + printk("Thermal assist unit "); +#ifdef CONFIG_TAU_INT + printk("using interrupts, "); +#else + printk("using timers, "); +#endif + printk("shrink_timer: %d jiffies\n", shrink_timer); + tau_initialized = 1; + + return 0; +} + +__initcall(TAU_init); + +/* + * return current temp + */ + +u32 cpu_temp_both(unsigned long cpu) +{ + return ((tau[cpu].high << 16) | tau[cpu].low); +} + +int cpu_temp(unsigned long cpu) +{ + return ((tau[cpu].high + tau[cpu].low) / 2); +} + +int tau_interrupts(unsigned long cpu) +{ + return (tau[cpu].interrupts); +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c --- v2.4.9/linux/arch/ppc/kernel/time.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/time.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.time.c 1.18 06/06/01 22:33:09 paulus + * BK Id: SCCS/s.time.c 1.21 08/20/01 22:08:08 paulus */ /* * Common time routines among all ppc machines. @@ -72,11 +72,6 @@ unsigned long disarm_decr[NR_CPUS]; -#ifdef CONFIG_SMP -extern void smp_local_timer_interrupt(struct pt_regs *); -extern int smp_tb_synchronized; -#endif /* CONFIG_SMP */ - extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); /* keep track of when we need to update the rtc */ @@ -321,27 +316,30 @@ * makes things more complex. Repeatedly read the RTC until the * next second boundary to try to achieve some precision... */ - stamp = get_native_tbl(); - sec = ppc_md.get_rtc_time(); - elapsed = 0; - do { - old_stamp = stamp; - old_sec = sec; + if (ppc_md.get_rtc_time) { stamp = get_native_tbl(); - if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000; - elapsed += stamp - old_stamp; sec = ppc_md.get_rtc_time(); - } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy); - if (sec==old_sec) { - printk("Warning: real time clock seems stuck!\n"); + elapsed = 0; + do { + old_stamp = stamp; + old_sec = sec; + stamp = get_native_tbl(); + if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000; + elapsed += stamp - old_stamp; + sec = ppc_md.get_rtc_time(); + } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy); + if (sec==old_sec) { + printk("Warning: real time clock seems stuck!\n"); + } + write_lock_irqsave(&xtime_lock, flags); + xtime.tv_sec = sec; + last_jiffy_stamp(0) = tb_last_stamp = stamp; + xtime.tv_usec = 0; + /* No update now, we just read the time from the RTC ! */ + last_rtc_update = xtime.tv_sec; + write_unlock_irqrestore(&xtime_lock, flags); } - write_lock_irqsave(&xtime_lock, flags); - xtime.tv_sec = sec; - last_jiffy_stamp(0) = tb_last_stamp = stamp; - xtime.tv_usec = 0; - /* No update now, we just read the time from the RTC ! */ - last_rtc_update = xtime.tv_sec; - write_unlock_irqrestore(&xtime_lock, flags); + /* Not exact, but the timer interrupt takes care of this */ set_dec(tb_ticks_per_jiffy); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c --- v2.4.9/linux/arch/ppc/kernel/traps.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/traps.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.traps.c 1.16 07/31/01 10:53:34 trini + * BK Id: SCCS/s.traps.c 1.19 08/24/01 20:07:37 paulus */ /* * linux/arch/ppc/kernel/traps.c @@ -244,7 +244,7 @@ */ if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) { rd = (instword >> 21) & 0x1f; - regs->gpr[rd] = _get_PVR(); + regs->gpr[rd] = mfspr(PVR); retval = 0; } if (retval == 0) @@ -372,12 +372,14 @@ } #endif +#if !defined(CONFIG_TAU_INT) void TAUException(struct pt_regs *regs) { printk("TAU trap at PC: %lx, SR: %lx, vector=%lx\n", regs->nip, regs->msr, regs->trap); } +#endif /* CONFIG_INT_TAU */ void __init trap_init(void) { diff -u --recursive --new-file v2.4.9/linux/arch/ppc/lib/checksum.S linux/arch/ppc/lib/checksum.S --- v2.4.9/linux/arch/ppc/lib/checksum.S Mon May 21 17:04:47 2001 +++ linux/arch/ppc/lib/checksum.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.checksum.S 1.5 05/17/01 18:14:22 cort + * BK Id: SCCS/s.checksum.S 1.8 08/20/01 22:09:34 paulus */ /* * This file contains assembly-language implementations @@ -122,12 +122,30 @@ addc r0,r0,r6 srwi. r6,r5,2 /* # words to do */ beq 3f -1: mtctr r6 -82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */ -92: stwu r6,4(r4) /* be unnecessary to unroll this loop */ +1: srwi. r6,r5,4 /* # groups of 4 words to do */ + beq 10f + mtctr r6 +71: lwz r6,4(r3) +72: lwz r9,8(r3) +73: lwz r10,12(r3) +74: lwzu r11,16(r3) adde r0,r0,r6 +75: stw r6,4(r4) + adde r0,r0,r9 +76: stw r9,8(r4) + adde r0,r0,r10 +77: stw r10,12(r4) + adde r0,r0,r11 +78: stwu r11,16(r4) + bdnz 71b +10: rlwinm. r6,r5,30,30,31 /* # words left to do */ + beq 13f + mtctr r6 +82: lwzu r9,4(r3) +92: stwu r9,4(r4) + adde r0,r0,r9 bdnz 82b - andi. r5,r5,3 +13: andi. r5,r5,3 3: cmpi 0,r5,2 blt+ 4f 83: lhz r6,4(r3) @@ -148,12 +166,16 @@ /* These shouldn't go in the fixup section, since that would cause the ex_table addresses to get out of order. */ +src_error_4: + mfctr r6 /* update # bytes remaining from ctr */ + rlwimi r5,r6,4,0,27 + b 79f src_error_1: li r6,0 subi r5,r5,2 95: sth r6,4(r4) addi r4,r4,2 - srwi. r6,r5,2 +79: srwi. r6,r5,2 beq 3f mtctr r6 src_error_2: @@ -187,6 +209,14 @@ .section __ex_table,"a" .long 81b,src_error_1 .long 91b,dst_error + .long 71b,src_error_4 + .long 72b,src_error_4 + .long 73b,src_error_4 + .long 74b,src_error_4 + .long 75b,dst_error + .long 76b,dst_error + .long 77b,dst_error + .long 78b,dst_error .long 82b,src_error_2 .long 92b,dst_error .long 83b,src_error_3 diff -u --recursive --new-file v2.4.9/linux/arch/ppc/lib/locks.c linux/arch/ppc/lib/locks.c --- v2.4.9/linux/arch/ppc/lib/locks.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/lib/locks.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.locks.c 1.8 05/17/01 18:14:22 cort + * BK Id: SCCS/s.locks.c 1.11 08/19/01 22:27:32 paulus */ /* * Locks for smp ppc @@ -16,29 +16,53 @@ #include #include -#define DEBUG_LOCKS 1 +#ifdef SPINLOCK_DEBUG #undef INIT_STUCK #define INIT_STUCK 200000000 /*0xffffffff*/ +/* + * Try to acquire a spinlock. + * Only does the stwcx. if the load returned 0 - the Programming + * Environments Manual suggests not doing unnecessary stcwx.'s + * since they may inhibit forward progress by other CPUs in getting + * a lock. + */ +static unsigned long __spin_trylock(volatile unsigned long *lock) +{ + unsigned long ret; + + __asm__ __volatile__ ("\n\ +1: lwarx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + bne 2f\n\ + stwcx. %2,0,%1\n\ + bne- 1b\n\ + isync\n\ +2:" + : "=&r"(ret) + : "r"(lock), "r"(1) + : "cr0", "memory"); + + return ret; +} + void _spin_lock(spinlock_t *lock) { int cpu = smp_processor_id(); -#ifdef DEBUG_LOCKS unsigned int stuck = INIT_STUCK; -#endif /* DEBUG_LOCKS */ while (__spin_trylock(&lock->lock)) { -#ifdef DEBUG_LOCKS - if(!--stuck) { - printk("_spin_lock(%p) CPU#%d NIP %p" - " holder: cpu %ld pc %08lX\n", - lock, cpu, __builtin_return_address(0), - lock->owner_cpu,lock->owner_pc); - stuck = INIT_STUCK; - /* steal the lock */ - /*xchg_u32((void *)&lock->lock,0);*/ + while ((unsigned volatile long)lock->lock != 0) { + if (!--stuck) { + printk("_spin_lock(%p) CPU#%d NIP %p" + " holder: cpu %ld pc %08lX\n", + lock, cpu, __builtin_return_address(0), + lock->owner_cpu,lock->owner_pc); + stuck = INIT_STUCK; + /* steal the lock */ + /*xchg_u32((void *)&lock->lock,0);*/ + } } -#endif /* DEBUG_LOCKS */ } lock->owner_pc = (unsigned long)__builtin_return_address(0); lock->owner_cpu = cpu; @@ -53,11 +77,8 @@ return 1; } - - void _spin_unlock(spinlock_t *lp) { -#ifdef DEBUG_LOCKS if ( !lp->lock ) printk("_spin_unlock(%p): no lock cpu %d curr PC %p %s/%d\n", lp, smp_processor_id(), __builtin_return_address(0), @@ -66,13 +87,12 @@ printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n", lp, smp_processor_id(), (int)lp->owner_cpu, lp->owner_pc,lp->lock); -#endif /* DEBUG_LOCKS */ lp->owner_pc = lp->owner_cpu = 0; wmb(); lp->lock = 0; - wmb(); } + /* * Just like x86, implement read-write locks as a 32-bit counter * with the high bit (sign) being the "write" bit. @@ -80,14 +100,11 @@ */ void _read_lock(rwlock_t *rw) { -#ifdef DEBUG_LOCKS unsigned long stuck = INIT_STUCK; int cpu = smp_processor_id(); -#endif /* DEBUG_LOCKS */ again: /* get our read lock in there */ - wmb(); atomic_inc((atomic_t *) &(rw)->lock); if ( (signed long)((rw)->lock) < 0) /* someone has a write lock */ { @@ -96,13 +113,11 @@ /* wait for the write lock to go away */ while ((signed long)((rw)->lock) < 0) { -#ifdef DEBUG_LOCKS if(!--stuck) { printk("_read_lock(%p) CPU#%d\n", rw, cpu); stuck = INIT_STUCK; } -#endif /* DEBUG_LOCKS */ } /* try to get the read lock again */ goto again; @@ -112,38 +127,30 @@ void _read_unlock(rwlock_t *rw) { -#ifdef DEBUG_LOCKS if ( rw->lock == 0 ) printk("_read_unlock(): %s/%d (nip %08lX) lock %lx\n", current->comm,current->pid,current->thread.regs->nip, rw->lock); -#endif /* DEBUG_LOCKS */ wmb(); atomic_dec((atomic_t *) &(rw)->lock); - wmb(); } void _write_lock(rwlock_t *rw) { -#ifdef DEBUG_LOCKS unsigned long stuck = INIT_STUCK; int cpu = smp_processor_id(); -#endif /* DEBUG_LOCKS */ again: - wmb(); if ( test_and_set_bit(31,&(rw)->lock) ) /* someone has a write lock */ { while ( (rw)->lock & (1<<31) ) /* wait for write lock */ { -#ifdef DEBUG_LOCKS if(!--stuck) { printk("write_lock(%p) CPU#%d lock %lx)\n", rw, cpu,rw->lock); stuck = INIT_STUCK; } -#endif /* DEBUG_LOCKS */ barrier(); } goto again; @@ -155,14 +162,12 @@ clear_bit(31,&(rw)->lock); while ( (rw)->lock & ~(1<<31) ) { -#ifdef DEBUG_LOCKS if(!--stuck) { printk("write_lock(%p) 2 CPU#%d lock %lx)\n", rw, cpu,rw->lock); stuck = INIT_STUCK; } -#endif /* DEBUG_LOCKS */ barrier(); } goto again; @@ -172,79 +177,12 @@ void _write_unlock(rwlock_t *rw) { -#ifdef DEBUG_LOCKS if ( !(rw->lock & (1<<31)) ) printk("_write_lock(): %s/%d (nip %08lX) lock %lx\n", current->comm,current->pid,current->thread.regs->nip, rw->lock); -#endif /* DEBUG_LOCKS */ wmb(); clear_bit(31,&(rw)->lock); - wmb(); -} - -void __lock_kernel(struct task_struct *task) -{ -#ifdef DEBUG_LOCKS - unsigned long stuck = INIT_STUCK; - - if ( (signed long)(task->lock_depth) < 0 ) - { - printk("__lock_kernel(): %s/%d (nip %08lX) lock depth %x\n", - task->comm,task->pid,task->thread.regs->nip, - task->lock_depth); - } -#endif /* DEBUG_LOCKS */ - - if (atomic_inc_return((atomic_t *) &task->lock_depth) != 1) - return; - /* mine! */ - while (__spin_trylock(&klock_info.kernel_flag)) { -#ifdef DEBUG_LOCKS - if(!--stuck) { - printk("_lock_kernel() CPU#%d NIP %p\n", - smp_processor_id(), - __builtin_return_address(0)); - stuck = INIT_STUCK; - } -#endif /* DEBUG_LOCKS */ - } - - klock_info.akp = smp_processor_id(); - /* my kernel mode! mine!!! */ } -void __unlock_kernel(struct task_struct *task) -{ -#ifdef DEBUG_LOCKS - if ((task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD)) - { - printk("__unlock_kernel(): %s/%d (nip %08lX) " - "lock depth %x flags %lx\n", - task->comm,task->pid,task->thread.regs->nip, - task->lock_depth, klock_info.kernel_flag); - klock_info.akp = NO_PROC_ID; - klock_info.kernel_flag = 0; - return; - } -#endif /* DEBUG_LOCKS */ - if (atomic_dec_and_test((atomic_t *) &task->lock_depth)) - { - wmb(); - klock_info.akp = NO_PROC_ID; - wmb(); - klock_info.kernel_flag = KLOCK_CLEAR; - wmb(); - } -} - -void reacquire_kernel_lock(struct task_struct *task, int cpu,int depth) -{ - if (depth) - { - __cli(); - __lock_kernel(task); - task->lock_depth = depth; - __sti(); - } -} +#endif diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/4xx_mmu.c linux/arch/ppc/mm/4xx_mmu.c --- v2.4.9/linux/arch/ppc/mm/4xx_mmu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/4xx_mmu.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,98 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines for initializing the MMU + * on the 4xx series of chips. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#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 + +/* Used by the 4xx TLB replacement exception handler. + * Just needed it declared someplace (and initialized to zero). + */ +unsigned int tlb_4xx_index; + +/* + * MMU_init_hw does the chip-specific initialization of the MMU hardware. + */ +void __init MMU_init_hw(void) +{ + /* + * The Zone Protection Register (ZPR) defines how protection will + * be applied to every page which is a member of a given zone. At + * present, we utilize only two of the 4xx's zones. + * The zone index bits (of ZSEL) in the PTE are used for software + * indicators, except the LSB. For user access, zone 15 is used, + * for kernel access, zone 14 is used. We set all but zone 15 + * to zero, allowing only kernel access as indicated in the PTE. + * For zone 15, we set a 01 binary (a value of 10 will not work) + * to allow user access as indicated in the PTE. This also allows + * kernel access as indicated in the PTE. + */ + + mtspr(SPRN_ZPR, 0x00000001); + + flush_instruction_cache(); + + /* + * Set up the real-mode cache parameters for the exception vector + * handlers (which are run in real-mode). + */ + + mtspr(SPRN_DCWR, 0x00000000); /* All caching is write-back */ + + /* + * Cache instruction and data space where the exception + * vectors and the kernel live in real-mode. + */ + + mtspr(SPRN_DCCR, 0x80000000); /* 128 MB of data space at 0x0. */ + mtspr(SPRN_ICCR, 0x80000000); /* 128 MB of instr. space at 0x0. */ +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile --- v2.4.9/linux/arch/ppc/mm/Makefile Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/mm/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.6 06/28/01 15:50:17 paulus +# BK Id: SCCS/s.Makefile 1.8 08/16/01 17:25:47 paulus # # # Makefile for the linux ppc-specific parts of the memory manager. @@ -15,15 +15,13 @@ EXTRA_AFLAGS := -Wa,-mppc64bridge endif -O_TARGET := mm.o -obj-y := fault.o init.o mem_pieces.o extable.o +O_TARGET := mm.o +obj-y := fault.o init.o mem_pieces.o extable.o \ + mmu_context.o pgtable.o -ifneq ($(CONFIG_8xx),y) -ifneq ($(CONFIG_4xx),y) -obj-y += hashtable.o -endif -endif - -obj-$(CONFIG_4xx) += 4xx_tlb.o +obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o +obj-$(CONFIG_PPC_ISERIES) += iSeries_hashtable.o iSeries_mmu.o tlb.o +obj-$(CONFIG_4xx) += cachemap.o 4xx_mmu.o +obj-$(CONFIG_8xx) += cachemap.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/cachemap.c linux/arch/ppc/mm/cachemap.c --- v2.4.9/linux/arch/ppc/mm/cachemap.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/cachemap.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,163 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + * + * PowerPC version derived from arch/arm/mm/consistent.c + * Copyright (C) 2001 Dan Malek (dmalek@jlc.net) + * + * linux/arch/arm/mm/consistent.c + * + * Copyright (C) 2000 Russell King + * + * Consistent memory allocators. Used for DMA devices that want to + * share uncached memory with the processor core. The function return + * is the virtual address and 'dma_handle' is the physical address. + * Mostly stolen from the ARM port, with some changes for PowerPC. + * -- Dan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#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 + +void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) +{ + int order, rsize; + unsigned long page; + void *ret; + pte_t *pte; + + if (in_interrupt()) + BUG(); + + /* Only allocate page size areas. + */ + size = PAGE_ALIGN(size); + order = get_order(size); + + page = __get_free_pages(gfp, order); + if (!page) { + BUG(); + return NULL; + } + + /* + * we need to ensure that there are no cachelines in use, + * or worse dirty in this area. + */ + invalidate_dcache_range(page, page + size); + + ret = (void *)page; + *dma_handle = virt_to_bus(ret); + + /* Chase down all of the PTEs and mark them uncached. + */ + rsize = (int)size; + while (rsize > 0) { + if (get_pteptr(&init_mm, page, &pte)) { + pte_val(*pte) |= _PAGE_NO_CACHE | _PAGE_GUARDED; + flush_tlb_page(find_vma(&init_mm,page),page); + } + else { + BUG(); + return NULL; + } + page += PAGE_SIZE; + rsize -= PAGE_SIZE; + } + + return ret; +} + +/* + * free page(s) as defined by the above mapping. + * The caller has to tell us the size so we can free the proper number + * of pages. We can't vmalloc() a new space for these pages and simply + * call vfree() like some other architectures because we could end up + * with aliased cache lines (or at least a cache line with the wrong + * attributes). This can happen when the PowerPC speculative loads + * across page boundaries. + */ +void consistent_free(void *vaddr, size_t size) +{ + int order, rsize; + unsigned long addr; + pte_t *pte; + + if (in_interrupt()) + BUG(); + + size = PAGE_ALIGN(size); + order = get_order(size); + + /* Chase down all of the PTEs and mark them cached again. + */ + addr = (unsigned long)vaddr; + rsize = (int)size; + while (rsize > 0) { + if (get_pteptr(&init_mm, addr, &pte)) { + pte_val(*pte) &= ~(_PAGE_NO_CACHE | _PAGE_GUARDED); + flush_tlb_page(find_vma(&init_mm,addr),addr); + } + else { + BUG(); + return; + } + addr += PAGE_SIZE; + rsize -= PAGE_SIZE; + } + free_pages((unsigned long)vaddr, order); +} + +/* + * make an area consistent. + */ +void consistent_sync(void *vaddr, size_t size, int direction) +{ + unsigned long start = (unsigned long)vaddr; + unsigned long end = start + size; + + switch (direction) { + case PCI_DMA_NONE: + BUG(); + case PCI_DMA_FROMDEVICE: /* invalidate only */ + invalidate_dcache_range(start, end); + break; + case PCI_DMA_TODEVICE: /* writeback only */ + clean_dcache_range(start, end); + break; + case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */ + flush_dcache_range(start, end); + break; + } +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/hashtable.S linux/arch/ppc/mm/hashtable.S --- v2.4.9/linux/arch/ppc/mm/hashtable.S Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/mm/hashtable.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.hashtable.S 1.16 06/29/01 08:51:52 paulus + * BK Id: SCCS/s.hashtable.S 1.18 08/15/01 22:43:07 paulus */ /* * arch/ppc/kernel/hashtable.S @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_SMP .comm hash_table_lock,4 diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.4.9/linux/arch/ppc/mm/init.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/mm/init.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.init.c 1.30 07/06/01 09:19:29 trini + * BK Id: SCCS/s.init.c 1.34 08/20/01 22:12:43 paulus */ /* * PowerPC version @@ -21,20 +21,14 @@ */ #include -#include #include #include #include #include #include -#include -#include #include -#include #include -#include #include -#include #include #include #ifdef CONFIG_BLK_DEV_INITRD @@ -47,138 +41,49 @@ #include #include #include -#include -#ifdef CONFIG_8xx -#include -#include -#endif -#ifdef CONFIG_8260 -#include -#include -#endif #include -#include #include -#include -#include -#include +#include #include "mem_pieces.h" +#include "mmu_decl.h" -#if defined(CONFIG_4xx) -#include "4xx_tlb.h" -#endif - -#define MAX_LOW_MEM (512 << 20) +#define MAX_LOW_MEM (0xF0000000UL - KERNELBASE) -#define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10) - -mm_context_t next_mmu_context; -unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))]; -#ifdef FEW_CONTEXTS -atomic_t nr_free_contexts; -struct mm_struct *context_mm[LAST_CONTEXT+1]; -void steal_context(void); -#endif /* FEW_CONTEXTS */ - -int prom_trashed; -unsigned long *end_of_DRAM; +void *end_of_DRAM; unsigned long total_memory; unsigned long total_lowmem; -unsigned long ram_phys_base; + int mem_init_done; int init_bootmem_done; int boot_mapsize; unsigned long totalram_pages; unsigned long totalhigh_pages; -extern pgd_t swapper_pg_dir[]; -extern char _start[], _end[]; + +extern char _end[]; extern char etext[], _stext[]; extern char __init_begin, __init_end; extern char __prep_begin, __prep_end; extern char __chrp_begin, __chrp_end; extern char __pmac_begin, __pmac_end; extern char __openfirmware_begin, __openfirmware_end; -unsigned long ioremap_base; -unsigned long ioremap_bot; -unsigned long avail_start; -extern int num_memory; -extern struct mem_info memory[]; -extern boot_infos_t *boot_infos; -extern unsigned int rtas_data, rtas_size; -#ifndef CONFIG_SMP -struct pgtable_cache_struct quicklists; -#endif + #ifdef CONFIG_HIGHMEM pte_t *kmap_pte; pgprot_t kmap_prot; #endif void MMU_init(void); -void *early_get_page(void); -static void mapin_ram(void); -int map_page(unsigned long va, unsigned long pa, int flags); void set_phys_avail(unsigned long total_ram); -extern void die_if_kernel(char *,struct pt_regs *,long); -extern char _start[], _end[]; -extern char _stext[], etext[]; +/* XXX should be in current.h -- paulus */ extern struct task_struct *current_set[NR_CPUS]; char *klimit = _end; struct mem_pieces phys_avail; -PTE *Hash, *Hash_end; -unsigned long Hash_size, Hash_mask; -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -unsigned long _SDR1; -static void hash_init(void); - -union ubat { /* BAT register values to be loaded */ - BAT bat; -#ifdef CONFIG_PPC64BRIDGE - u64 word[2]; -#else - u32 word[2]; -#endif -} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ - -struct batrange { /* stores address ranges mapped by BATs */ - unsigned long start; - unsigned long limit; - unsigned long phys; -} bat_addrs[4]; - -/* - * Return PA for this VA if it is mapped by a BAT, or 0 - */ -static inline unsigned long v_mapped_by_bats(unsigned long va) -{ - int b; - for (b = 0; b < 4; ++b) - if (va >= bat_addrs[b].start && va < bat_addrs[b].limit) - return bat_addrs[b].phys + (va - bat_addrs[b].start); - return 0; -} - -/* - * Return VA for a given PA or 0 if not mapped - */ -static inline unsigned long p_mapped_by_bats(unsigned long pa) -{ - int b; - for (b = 0; b < 4; ++b) - if (pa >= bat_addrs[b].phys - && pa < (bat_addrs[b].limit-bat_addrs[b].start) - +bat_addrs[b].phys) - return bat_addrs[b].start+(pa-bat_addrs[b].phys); - return 0; -} - -#else /* CONFIG_4xx || CONFIG_8xx */ -#define v_mapped_by_bats(x) (0UL) -#define p_mapped_by_bats(x) (0UL) -#endif /* !CONFIG_4xx && !CONFIG_8xx */ +extern char *sysmap; +extern unsigned long sysmap_size; /* * this tells the system to map all of ram with the segregs @@ -298,421 +203,7 @@ val->mem_unit = PAGE_SIZE; } -void * -ioremap(unsigned long addr, unsigned long size) -{ - return __ioremap(addr, size, _PAGE_NO_CACHE); -} - -void * -__ioremap(unsigned long addr, unsigned long size, unsigned long flags) -{ - unsigned long p, v, i; - int err; - - /* - * Choose an address to map it to. - * Once the vmalloc system is running, we use it. - * Before then, we map addresses >= ioremap_base - * virt == phys; for addresses below this we use - * space going down from ioremap_base (ioremap_bot - * records where we're up to). - */ - p = addr & PAGE_MASK; - size = PAGE_ALIGN(addr + size) - p; - - /* - * If the address lies within the first 16 MB, assume it's in ISA - * memory space - */ - if ( p < 16*1024*1024 ) - p += _ISA_MEM_BASE; - - /* - * Don't allow anybody to remap normal RAM that we're using. - * mem_init() sets high_memory so only do the check after that. - */ - if ( mem_init_done && (p < virt_to_phys(high_memory)) ) - { - printk("__ioremap(): phys addr %0lx is RAM lr %p\n", p, - __builtin_return_address(0)); - return NULL; - } - - if (size == 0) - return NULL; - - /* - * Is it already mapped? Perhaps overlapped by a previous - * BAT mapping. If the whole area is mapped then we're done, - * otherwise remap it since we want to keep the virt addrs for - * each request contiguous. - * - * We make the assumption here that if the bottom and top - * of the range we want are mapped then it's mapped to the - * same virt address (and this is contiguous). - * -- Cort - */ - if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ ) - goto out; - - if (mem_init_done) { - struct vm_struct *area; - area = get_vm_area(size, VM_IOREMAP); - if (area == 0) - return NULL; - v = VMALLOC_VMADDR(area->addr); - } else { -#ifndef CONFIG_HIGHMEM - if (p >= ioremap_base) -#else - if (p >= ioremap_base && p < PKMAP_BASE) -#endif /* CONFIG_HIGHMEM */ - v = p; - else - v = (ioremap_bot -= size); - } - - if ((flags & _PAGE_PRESENT) == 0) - flags |= pgprot_val(PAGE_KERNEL); - if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU)) - flags |= _PAGE_GUARDED; - - /* - * Should check if it is a candidate for a BAT mapping - */ - - err = 0; - for (i = 0; i < size && err == 0; i += PAGE_SIZE) - err = map_page(v+i, p+i, flags); - if (err) { - if (mem_init_done) - vfree((void *)v); - return NULL; - } - -out: - return (void *) (v + (addr & ~PAGE_MASK)); -} - -void iounmap(void *addr) -{ - if (addr > high_memory && (unsigned long) addr < ioremap_bot) - vfree((void *) (PAGE_MASK & (unsigned long) addr)); -} - -unsigned long iopa(unsigned long addr) -{ - unsigned long pa; - pmd_t *pd; - pte_t *pg; - - /* Check the BATs */ - pa = v_mapped_by_bats(addr); - if (pa) - return pa; - - /* Do we have a page table? */ - if (init_mm.pgd == NULL) - return 0; - - /* Use upper 10 bits of addr to index the first level map */ - pd = (pmd_t *) (init_mm.pgd + (addr >> PGDIR_SHIFT)); - if (pmd_none(*pd)) - return 0; - - /* Use middle 10 bits of addr to index the second-level map */ - pg = pte_offset(pd, addr); - return (pte_val(*pg) & PAGE_MASK) | (addr & ~PAGE_MASK); -} - -int -map_page(unsigned long va, unsigned long pa, int flags) -{ - pmd_t *pd; - pte_t *pg; - int err = -ENOMEM; - - spin_lock(&init_mm.page_table_lock); - /* Use upper 10 bits of VA to index the first level map */ - pd = pmd_offset(pgd_offset_k(va), va); - /* Use middle 10 bits of VA to index the second-level map */ - pg = pte_alloc(&init_mm, pd, va); - if (pg != 0) { - err = 0; - set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags))); -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) - if (mem_init_done && Hash != 0) - flush_hash_page(0, va, pg); -#endif /* !4xx && !8xx */ - } - spin_unlock(&init_mm.page_table_lock); - return err; -} - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -/* - * TLB flushing: - * - * - flush_tlb_all() flushes all processes TLBs - * - flush_tlb_mm(mm) flushes the specified mm context TLB's - * - flush_tlb_page(vma, vmaddr) flushes one page - * - flush_tlb_range(mm, start, end) flushes a range of pages - * - * since the hardware hash table functions as an extension of the - * tlb as far as the linux tables are concerned, flush it too. - * -- Cort - */ - -/* - * Flush all tlb/hash table entries (except perhaps for those - * mapping RAM starting at PAGE_OFFSET, since they never change). - */ -void -local_flush_tlb_all(void) -{ - /* aargh!!! */ - /* just flush the kernel part of the address space, that's - all that the current callers of this require. -- paulus. */ - local_flush_tlb_range(&init_mm, TASK_SIZE, ~0UL); - -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif /* CONFIG_SMP */ -} - -/* - * Flush all the (user) entries for the address space described - * by mm. We can't rely on mm->mmap describing all the entries - * that might be in the hash table. - */ -void -local_flush_tlb_mm(struct mm_struct *mm) -{ - if (Hash == 0) { - _tlbia(); - return; - } - - if (mm->map_count) { - struct vm_area_struct *mp; - for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) - local_flush_tlb_range(mm, mp->vm_start, mp->vm_end); - } else - local_flush_tlb_range(mm, 0, TASK_SIZE); - -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif -} - -void -local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) -{ - struct mm_struct *mm; - pmd_t *pmd; - pte_t *pte; - - if (Hash == 0) { - _tlbie(vmaddr); - return; - } - mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; - pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); - if (!pmd_none(*pmd)) { - pte = pte_offset(pmd, vmaddr); - if (pte_val(*pte) & _PAGE_HASHPTE) - flush_hash_page(mm->context, vmaddr, pte); - } -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif -} - - -/* - * For each address in the range, find the pte for the address - * and check _PAGE_HASHPTE bit; if it is set, find and destroy - * the corresponding HPTE. - */ -void -local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) -{ - pmd_t *pmd; - pte_t *pte; - unsigned long pmd_end; - unsigned int ctx = mm->context; - - if (Hash == 0) { - _tlbia(); - return; - } - start &= PAGE_MASK; - if (start >= end) - return; - pmd = pmd_offset(pgd_offset(mm, start), start); - do { - pmd_end = (start + PGDIR_SIZE) & PGDIR_MASK; - if (!pmd_none(*pmd)) { - if (!pmd_end || pmd_end > end) - pmd_end = end; - pte = pte_offset(pmd, start); - do { - if ((pte_val(*pte) & _PAGE_HASHPTE) != 0) - flush_hash_page(ctx, start, pte); - start += PAGE_SIZE; - ++pte; - } while (start && start < pmd_end); - } else { - start = pmd_end; - } - ++pmd; - } while (start && start < end); - -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif -} - -/* - * Set up one of the I/D BAT (block address translation) register pairs. - * The parameters are not checked; in particular size must be a power - * of 2 between 128k and 256M. - */ -void __init setbat(int index, unsigned long virt, unsigned long phys, - unsigned int size, int flags) -{ - unsigned int bl; - int wimgxpp; - union ubat *bat = BATS[index]; - - bl = (size >> 17) - 1; - if ((_get_PVR() >> 16) != 1) { - /* 603, 604, etc. */ - /* Do DBAT first */ - wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE - | _PAGE_COHERENT | _PAGE_GUARDED); - wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX; - bat[1].word[0] = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */ - bat[1].word[1] = phys | wimgxpp; -#ifndef CONFIG_KGDB /* want user access for breakpoints */ - if (flags & _PAGE_USER) -#endif - bat[1].bat.batu.vp = 1; - if (flags & _PAGE_GUARDED) { - /* G bit must be zero in IBATs */ - bat[0].word[0] = bat[0].word[1] = 0; - } else { - /* make IBAT same as DBAT */ - bat[0] = bat[1]; - } - } else { - /* 601 cpu */ - if (bl > BL_8M) - bl = BL_8M; - wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE - | _PAGE_COHERENT); - wimgxpp |= (flags & _PAGE_RW)? - ((flags & _PAGE_USER)? PP_RWRW: PP_RWXX): PP_RXRX; - bat->word[0] = virt | wimgxpp | 4; /* Ks=0, Ku=1 */ - bat->word[1] = phys | bl | 0x40; /* V=1 */ - } - - bat_addrs[index].start = virt; - bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1; - bat_addrs[index].phys = phys; -} - -#define IO_PAGE (_PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_RW) -#ifdef CONFIG_SMP -#define RAM_PAGE (_PAGE_RW|_PAGE_COHERENT) -#else -#define RAM_PAGE (_PAGE_RW) -#endif -#endif /* CONFIG_8xx */ - -/* - * Map in all of physical memory starting at KERNELBASE. - */ -static void __init mapin_ram(void) -{ - unsigned long v, p, s, f; - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_POWER4) - if (!__map_without_bats) { - unsigned long tot, bl, done; - unsigned long max_size = (256<<20); - unsigned long align; - - /* Set up BAT2 and if necessary BAT3 to cover RAM. */ - - /* Make sure we don't map a block larger than the - smallest alignment of the physical address. */ - /* alignment of ram_phys_base */ - align = ~(ram_phys_base-1) & ram_phys_base; - /* set BAT block size to MIN(max_size, align) */ - if (align && align < max_size) - max_size = align; - - tot = total_lowmem; - for (bl = 128<<10; bl < max_size; bl <<= 1) { - if (bl * 2 > tot) - break; - } - - setbat(2, KERNELBASE, ram_phys_base, bl, RAM_PAGE); - done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1; - if ((done < tot) && !bat_addrs[3].limit) { - /* use BAT3 to cover a bit more */ - tot -= done; - for (bl = 128<<10; bl < max_size; bl <<= 1) - if (bl * 2 > tot) - break; - setbat(3, KERNELBASE+done, ram_phys_base+done, bl, - RAM_PAGE); - } - } -#endif /* !CONFIG_4xx && !CONFIG_8xx && !CONFIG_POWER4 */ - - v = KERNELBASE; - p = ram_phys_base; - for (s = 0; s < total_lowmem; s += PAGE_SIZE) { - /* On the MPC8xx, we want the page shared so we - * don't get ASID compares on kernel space. - */ - f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED; -#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) - /* Allows stub to set breakpoints everywhere */ - f |= _PAGE_RW | _PAGE_DIRTY; -#else - if ((char *) v < _stext || (char *) v >= etext) - f |= _PAGE_RW | _PAGE_DIRTY; -#ifndef CONFIG_8xx - else - /* On the powerpc (not 8xx), no user access - forces R/W kernel access */ - f |= _PAGE_USER; -#endif /* CONFIG_8xx */ -#endif /* CONFIG_KGDB */ - map_page(v, p, f); - v += PAGE_SIZE; - p += PAGE_SIZE; - } -} - -/* This is only called until mem_init is done. */ -void __init *early_get_page(void) -{ - void *p; - - if (init_bootmem_done) { - p = alloc_bootmem_pages(PAGE_SIZE); - } else { - p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE); - } - return p; -} - +/* Free up now-unused memory */ static void free_sec(unsigned long start, unsigned long end, const char *name) { unsigned long cnt = 0; @@ -725,7 +216,7 @@ start += PAGE_SIZE; } if (cnt) { - printk(" %ldk %s", PGTOKB(cnt), name); + printk(" %ldk %s", cnt << (PAGE_SHIFT - 10), name); totalram_pages += cnt; } } @@ -766,110 +257,54 @@ #endif /* - * Initialize the context management stuff. + * Check for command-line options that affect what MMU_init will do. */ -static void mmu_context_init(void) +void MMU_setup(void) { - context_map[0] = 1; /* init_mm uses context 0 */ - next_mmu_context = 1; -#ifdef FEW_CONTEXTS - atomic_set(&nr_free_contexts, LAST_CONTEXT); - context_mm[0] = &init_mm; -#endif /* FEW_CONTEXTS */ -} - -#ifdef FEW_CONTEXTS -/* - * Steal a context from a task that has one at the moment. - * This is only used on 8xx and 4xx and we presently assume that - * they don't do SMP. If they do then this will have to check - * whether the MM we steal is in use. - * We also assume that this is only used on systems that don't - * use an MMU hash table - this is true for 8xx and 4xx. - * This isn't an LRU system, it just frees up each context in - * turn (sort-of pseudo-random replacement :). This would be the - * place to implement an LRU scheme if anyone was motivated to do it. - * -- paulus - */ -void steal_context(void) -{ - struct mm_struct *mm; - - /* free up context `next_mmu_context' */ - /* if we shouldn't free context 0, don't... */ -#ifdef CONFIG_4xx - if (next_mmu_context == 0) - next_mmu_context = 1; -#endif /* CONFIG_4xx */ - mm = context_mm[next_mmu_context]; - flush_tlb_mm(mm); - destroy_context(mm); + /* Check for nobats option (used in mapin_ram). */ + if (strstr(cmd_line, "nobats")) { + __map_without_bats = 1; + } + + /* Look for mem= option on command line */ + if (strstr(cmd_line, "mem=")) { + char *p, *q; + unsigned long maxmem = 0; + + for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { + q = p + 4; + if (p > cmd_line && p[-1] != ' ') + continue; + maxmem = simple_strtoul(q, &q, 0); + if (*q == 'k' || *q == 'K') { + maxmem <<= 10; + ++q; + } else if (*q == 'm' || *q == 'M') { + maxmem <<= 20; + ++q; + } + } + __max_memory = maxmem; + } } -#endif /* FEW_CONTEXTS */ - -extern boot_infos_t *disp_bi; /* - * Do very early mm setup such as finding the size of memory - * and setting up the hash table. - * A lot of this is prep/pmac specific but a lot of it could - * still be merged. - * -- Cort + * MMU_init sets up the basic memory mappings for the kernel, + * including both RAM and possibly some I/O regions, + * and sets up the page tables and the MMU hardware ready to go. */ -#if defined(CONFIG_4xx) -void __init -MMU_init(void) +void __init MMU_init(void) { - /* - * The Zone Protection Register (ZPR) defines how protection will - * be applied to every page which is a member of a given zone. At - * present, we utilize only two of the 4xx's zones. - * The zone index bits (of ZSEL) in the PTE are used for software - * indicators, except the LSB. For user access, zone 15 is used, - * for kernel access, zone 14 is used. We set all but zone 15 - * to zero, allowing only kernel access as indicated in the PTE. - * For zone 15, we set a 10 binary (I guess a 01 would work too) - * to allow user access as indicated in the PTE. This also allows - * kernel access as indicated in the PTE. - */ + if (ppc_md.progress) + ppc_md.progress("MMU:enter", 0x111); - mtspr(SPRN_ZPR, 0x00000002); - - flush_instruction_cache(); + /* parse args from command line */ + MMU_setup(); /* - * Find the top of physical memory and map all of it in starting - * at KERNELBASE. + * Figure out how much memory we have, how much + * is lowmem, and how much is highmem. */ - - total_memory = total_lowmem = ppc_md.find_end_of_memory(); - end_of_DRAM = __va(total_lowmem); - set_phys_avail(total_lowmem); - mapin_ram(); - - /* - * Set up the real-mode cache parameters for the exception vector - * handlers (which are run in real-mode). - */ - - mtspr(SPRN_DCWR, 0x00000000); /* All caching is write-back */ - - /* - * Cache instruction and data space where the exception - * vectors and the kernel live in real-mode. - */ - - mtspr(SPRN_DCCR, 0x80000000); /* 128 MB of data space at 0x0. */ - mtspr(SPRN_ICCR, 0x80000000); /* 128 MB of instr. space at 0x0. */ - - mmu_context_init(); -} - -#else /* !CONFIG_4xx */ -void __init MMU_init(void) -{ - if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111); - total_memory = ppc_md.find_end_of_memory(); if (__max_memory && total_memory > __max_memory) @@ -884,114 +319,54 @@ end_of_DRAM = __va(total_lowmem); set_phys_avail(total_lowmem); -#if !defined(CONFIG_8xx) - if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300); - hash_init(); -#ifndef CONFIG_PPC64BRIDGE - _SDR1 = __pa(Hash) | (Hash_mask >> 10); -#endif - - ioremap_base = 0xf8000000; -#endif /* CONFIG_8xx */ + /* Initialize the MMU hardware */ + if (ppc_md.progress) + ppc_md.progress("MMU:hw init", 0x300); + MMU_init_hw(); - if ( ppc_md.progress ) ppc_md.progress("MMU:mapin", 0x301); /* Map in all of RAM starting at KERNELBASE */ + if (ppc_md.progress) + ppc_md.progress("MMU:mapin", 0x301); mapin_ram(); -#if defined(CONFIG_8xx) - /* Now map in some of the I/O space that is generically needed - * or shared with multiple devices. - * All of this fits into the same 4Mbyte region, so it only - * requires one page table page. - */ - ioremap(IMAP_ADDR, IMAP_SIZE); -#ifdef CONFIG_MBX - ioremap(NVRAM_ADDR, NVRAM_SIZE); - ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE); - ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE); - - /* Map some of the PCI/ISA I/O space to get the IDE interface. - */ - ioremap(PCI_ISA_IO_ADDR, 0x4000); - ioremap(PCI_IDE_ADDR, 0x4000); -#endif -#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) - ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE); -#if !defined(CONFIG_PCI) - ioremap(_IO_BASE,_IO_BASE_SIZE); -#endif -#endif -#ifdef CONFIG_HTDMSOUND - ioremap(HIOX_CSR_ADDR, HIOX_CSR_SIZE); -#endif -#ifdef CONFIG_FADS - ioremap(BCSR_ADDR, BCSR_SIZE); -#endif -#ifdef CONFIG_PCI - ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE); -#endif -#else /* !CONFIG_8xx */ - /* - * Setup the bat mappings we're going to load that cover - * the io areas. RAM was mapped by mapin_ram(). - * -- Cort - */ - if ( ppc_md.progress ) ppc_md.progress("MMU:setbat", 0x302); - switch (_machine) { - case _MACH_prep: - setbat(0, 0x80000000, 0x80000000, 0x10000000, IO_PAGE); - setbat(1, 0xf0000000, 0xc0000000, 0x08000000, IO_PAGE); - ioremap_base = 0xf0000000; - break; - case _MACH_chrp: - /* - * The code below tends to get removed, please don't take it out. - * The F50 needs this mapping and it you take it out I'll track you - * down and slap your hands. If it causes problems please email me. - * -- Cort - */ -#ifndef CONFIG_POWER3 - setbat(0, 0x80000000, 0x80000000, 0x10000000, IO_PAGE); - setbat(1, 0x90000000, 0x90000000, 0x10000000, IO_PAGE); -#endif - break; - case _MACH_Pmac: - ioremap_base = 0xfe000000; - break; - case _MACH_apus: - /* Map PPC exception vectors. */ - setbat(0, 0xfff00000, 0xfff00000, 0x00020000, RAM_PAGE); - /* Map chip and ZorroII memory */ - setbat(1, zTwoBase, 0x00000000, 0x01000000, IO_PAGE); - break; - case _MACH_gemini: - setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE); - setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE); - break; - case _MACH_8260: - /* Map the IMMR, plus anything else we can cover - * in that upper space according to the memory controller - * chip select mapping. Grab another bunch of space - * below that for stuff we can't cover in the upper. - */ - setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE); - setbat(1, 0xe0000000, 0xe0000000, 0x10000000, IO_PAGE); - ioremap_base = 0xe0000000; - break; - } +#ifdef CONFIG_HIGHMEM + ioremap_base = PKMAP_BASE; +#else + ioremap_base = 0xfe000000UL; /* for now, could be 0xfffff000 */ +#endif /* CONFIG_HIGHMEM */ ioremap_bot = ioremap_base; -#endif /* CONFIG_8xx */ - if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211); + /* Map in I/O resources */ + if (ppc_md.progress) + ppc_md.progress("MMU:setio", 0x302); + if (ppc_md.setup_io_mappings) + ppc_md.setup_io_mappings(); + + /* Initialize the context management stuff */ + mmu_context_init(); + + if (ppc_md.progress) + ppc_md.progress("MMU:exit", 0x211); + #ifdef CONFIG_BOOTX_TEXT /* Must be done last, or ppc_md.progress will die */ - if (_machine == _MACH_Pmac || _machine == _MACH_chrp) - map_bootx_text(); + if (have_of) + map_boot_text(); #endif +} - mmu_context_init(); +/* This is only called until mem_init is done. */ +void __init *early_get_page(void) +{ + void *p; + + if (init_bootmem_done) { + p = alloc_bootmem_pages(PAGE_SIZE); + } else { + p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE); + } + return p; } -#endif /* CONFIG_4xx */ /* * Initialize the bootmem system and give it all the memory we @@ -1068,8 +443,6 @@ void __init mem_init(void) { - extern char *sysmap; - extern unsigned long sysmap_size; unsigned long addr; int codepages = 0; int datapages = 0; @@ -1094,7 +467,7 @@ make sure the ramdisk pages aren't reserved. */ if (initrd_start) { for (addr = initrd_start; addr < initrd_end; addr += PAGE_SIZE) - clear_bit(PG_reserved, &virt_to_page(addr)->flags); + ClearPageReserved(virt_to_page(addr)); } #endif /* CONFIG_BLK_DEV_INITRD */ @@ -1106,7 +479,7 @@ addr += PAGE_SIZE) SetPageReserved(virt_to_page(addr)); #endif /* defined(CONFIG_ALL_PPC) */ - if ( sysmap_size ) + if ( sysmap ) for (addr = (unsigned long)sysmap; addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ; addr += PAGE_SIZE) @@ -1147,133 +520,12 @@ codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10), initpages<< (PAGE_SHIFT-10), (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); + if (sysmap) + printk("System.map loaded at 0x%08x for debugger, size: %ld bytes\n", + (unsigned int)sysmap, sysmap_size); mem_init_done = 1; } -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -/* - * Initialize the hash table and patch the instructions in hashtable.S. - */ -static void __init hash_init(void) -{ - int Hash_bits, mb, mb2; - unsigned int hmask, h; - - extern unsigned int hash_page_patch_A[]; - extern unsigned int hash_page_patch_B[], hash_page_patch_C[]; - extern unsigned int hash_page[]; - extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[]; - -#ifdef CONFIG_PPC64BRIDGE - /* The hash table has already been allocated and initialized - in prom.c */ - Hash_mask = (Hash_size >> 7) - 1; - hmask = Hash_mask >> 9; - Hash_bits = __ilog2(Hash_size) - 7; - mb = 25 - Hash_bits; - if (Hash_bits > 16) - Hash_bits = 16; - mb2 = 25 - Hash_bits; - -#else /* CONFIG_PPC64BRIDGE */ - - if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); - /* - * Allow 64k of hash table for every 16MB of memory, - * up to a maximum of 2MB. - */ - for (h = 64<<10; h < total_memory / 256 && h < (2<<20); h *= 2) - ; - Hash_size = h; - Hash_mask = (h >> 6) - 1; - hmask = Hash_mask >> 10; - Hash_bits = __ilog2(h) - 6; - mb = 26 - Hash_bits; - if (Hash_bits > 16) - Hash_bits = 16; - mb2 = 26 - Hash_bits; - - /* shrink the htab since we don't use it on 603's -- Cort */ - switch (_get_PVR()>>16) { - case 3: /* 603 */ - case 6: /* 603e */ - case 7: /* 603ev */ - case 0x0081: /* 82xx */ - Hash_size = 0; - Hash_mask = 0; - break; - default: - /* on 601/4 let things be */ - break; - } - - if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); - /* Find some memory for the hash table. */ - if ( Hash_size ) { - Hash = mem_pieces_find(Hash_size, Hash_size); - cacheable_memzero(Hash, Hash_size); - _SDR1 = __pa(Hash) | (Hash_mask >> 10); - } else - Hash = 0; -#endif /* CONFIG_PPC64BRIDGE */ - - printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", - total_memory >> 20, Hash_size >> 10, Hash); - if ( Hash_size ) - { - if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345); - Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); - - /* - * Patch up the instructions in hashtable.S:create_hpte - */ - hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff) - | ((unsigned int)(Hash) >> 16); - hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) - | (mb << 6); - hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) - | (mb2 << 6); - hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) - | hmask; - hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) - | hmask; - /* - * Ensure that the locations we've patched have been written - * out from the data cache and invalidated in the instruction - * cache, on those machines with split caches. - */ - flush_icache_range((unsigned long) &hash_page_patch_A[0], - (unsigned long) &hash_page_patch_C[1]); - /* - * Patch up the instructions in hashtable.S:flush_hash_page - */ - flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff) - | ((unsigned int)(Hash) >> 16); - flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) - | (mb << 6); - flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) - | (mb2 << 6); - flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) - | hmask; - flush_icache_range((unsigned long) &flush_hash_patch_A[0], - (unsigned long) &flush_hash_patch_B[1]); - } - else { - Hash_end = 0; - /* - * Put a blr (procedure return) instruction at the - * start of hash_page, since we can still get DSI - * exceptions on a 603. - */ - hash_page[0] = 0x4e800020; - flush_icache_range((unsigned long) &hash_page[0], - (unsigned long) &hash_page[1]); - } - - if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); -} -#endif /* !CONFIG_4xx && !CONFIG_8xx */ - /* * Set phys_avail to the amount of physical memory, * less the kernel text/data/bss. @@ -1314,12 +566,16 @@ /* remove the RTAS pages from the available memory */ if (rtas_data) mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1); + /* remove the sysmap pages from the available memory */ + if (sysmap) + mem_pieces_remove(&phys_avail, __pa(sysmap), sysmap_size, 1); #endif /* CONFIG_ALL_PPC */ -#ifdef CONFIG_PPC64BRIDGE - /* Remove the hash table from the available memory */ - if (Hash) - mem_pieces_remove(&phys_avail, __pa(Hash), Hash_size, 1); -#endif /* CONFIG_PPC64BRIDGE */ +} + +/* Mark some memory as reserved by removing it from phys_avail. */ +void __init reserve_phys_mem(unsigned long start, unsigned long size) +{ + mem_pieces_remove(&phys_avail, start, size, 1); } void flush_page_to_ram(struct page *page) @@ -1328,32 +584,6 @@ __flush_page_to_ram(vaddr); kunmap(page); } - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -/* - * This is called at the end of handling a user page fault, when the - * fault has been handled by updating a PTE in the linux page tables. - * We use it to preload an HPTE into the hash table corresponding to - * the updated linux PTE. - */ -void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, - pte_t pte) -{ - struct mm_struct *mm; - pmd_t *pmd; - pte_t *ptep; - static int nopreload; - - if (Hash == 0 || nopreload) - return; - mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm; - pmd = pmd_offset(pgd_offset(mm, address), address); - if (!pmd_none(*pmd)) { - ptep = pte_offset(pmd, address); - add_hash_page(mm->context, address, ptep); - } -} -#endif /* !4xx && !8xx */ /* * set_pte stores a linux PTE into the linux page table. diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/mmu_context.c linux/arch/ppc/mm/mmu_context.c --- v2.4.9/linux/arch/ppc/mm/mmu_context.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/mmu_context.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,89 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines for handling the MMU on those + * PowerPC implementations where the MMU substantially follows the + * architecture specification. This includes the 6xx, 7xx, 7xxx, + * 8260, and POWER3 implementations but excludes the 8xx and 4xx. + * Although the iSeries hardware does comply with the architecture + * specification, the need to work through the hypervisor makes + * things sufficiently different that it is handled elsewhere. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include + +#include + +mm_context_t next_mmu_context; +unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))]; +#ifdef FEW_CONTEXTS +atomic_t nr_free_contexts; +struct mm_struct *context_mm[LAST_CONTEXT+1]; +void steal_context(void); +#endif /* FEW_CONTEXTS */ + +/* + * Initialize the context management stuff. + */ +void __init mmu_context_init(void) +{ + /* + * Some processors have too few contexts to reserve one for + * init_mm, and require using context 0 for a normal task. + * Other processors reserve the use of context zero for the kernel. + * This code assumes FIRST_CONTEXT < 32. + */ + context_map[0] = (1 << FIRST_CONTEXT) - 1; + next_mmu_context = FIRST_CONTEXT; +#ifdef FEW_CONTEXTS + atomic_set(&nr_free_contexts, LAST_CONTEXT); +#endif /* FEW_CONTEXTS */ +} + +#ifdef FEW_CONTEXTS +/* + * Steal a context from a task that has one at the moment. + * This is only used on 8xx and 4xx and we presently assume that + * they don't do SMP. If they do then this will have to check + * whether the MM we steal is in use. + * We also assume that this is only used on systems that don't + * use an MMU hash table - this is true for 8xx and 4xx. + * This isn't an LRU system, it just frees up each context in + * turn (sort-of pseudo-random replacement :). This would be the + * place to implement an LRU scheme if anyone was motivated to do it. + * -- paulus + */ +void steal_context(void) +{ + struct mm_struct *mm; + + /* free up context `next_mmu_context' */ + /* if we shouldn't free context 0, don't... */ + if (next_mmu_context < FIRST_CONTEXT) + next_mmu_context = FIRST_CONTEXT; + mm = context_mm[next_mmu_context]; + flush_tlb_mm(mm); + destroy_context(mm); +} +#endif /* FEW_CONTEXTS */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/mmu_decl.h linux/arch/ppc/mm/mmu_decl.h --- v2.4.9/linux/arch/ppc/mm/mmu_decl.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/mmu_decl.h Tue Aug 28 06:58:33 2001 @@ -0,0 +1,73 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * Declarations of procedures and variables shared between files + * in arch/ppc/mm/. + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +extern void mapin_ram(void); +extern void bat_mapin_ram(void); +extern int map_page(unsigned long va, unsigned long pa, int flags); +extern void setbat(int index, unsigned long virt, unsigned long phys, + unsigned int size, int flags); +extern void reserve_phys_mem(unsigned long start, unsigned long size); + +extern int __map_without_bats; +extern void *end_of_DRAM; +extern unsigned long ioremap_base; +extern unsigned long ioremap_bot; +extern unsigned int rtas_data, rtas_size; + +extern unsigned long total_memory; +extern unsigned long total_lowmem; +extern unsigned long ram_phys_base; +extern int mem_init_done; + +extern PTE *Hash, *Hash_end; +extern unsigned long Hash_size, Hash_mask; + +/* ...and now those things that may be slightly different between processor + * architectures. -- Dan + */ +#if defined(CONFIG_8xx) +#define flush_HPTE(X, va, pg) _tlbie(va) +#define MMU_init_hw() do { } while(0) + +#elif defined(CONFIG_4xx) +#define flush_HPTE(X, va, pg) _tlbie(va) + +#else +/* anything except 4xx or 8xx */ +extern void MMU_init_hw(void); + +/* Be careful....this needs to be updated if we ever encounter 603 SMPs, + * which includes all new 82xx processors. We need tlbie/tlbsync here + * in that case (I think). -- Dan. + */ +static inline void flush_HPTE(unsigned context, unsigned long va, pte_t *pg) +{ + if ((Hash != 0) && + (cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE)) + flush_hash_page(0, va, pg); + else + _tlbie(va); +} +#endif diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/pgtable.c linux/arch/ppc/mm/pgtable.c --- v2.4.9/linux/arch/ppc/mm/pgtable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/pgtable.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,360 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines setting up the linux page tables. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mmu_decl.h" + +unsigned long ram_phys_base; + +unsigned long ioremap_base; +unsigned long ioremap_bot; +int io_bat_index; + +#ifndef CONFIG_SMP +struct pgtable_cache_struct quicklists; +#endif + +#if defined(CONFIG_6xx) || defined(CONFIG_POWER3) +#define HAVE_BATS 1 +#endif + +extern char etext[], _stext[]; + +#ifdef HAVE_BATS +extern unsigned long v_mapped_by_bats(unsigned long va); +extern unsigned long p_mapped_by_bats(unsigned long pa); +void setbat(int index, unsigned long virt, unsigned long phys, + unsigned int size, int flags); + +#else /* !HAVE_BATS */ +#define v_mapped_by_bats(x) (0UL) +#define p_mapped_by_bats(x) (0UL) +#endif /* HAVE_BATS */ + +#ifndef CONFIG_PPC_ISERIES +void * +ioremap(unsigned long addr, unsigned long size) +{ + return __ioremap(addr, size, _PAGE_NO_CACHE); +} + +void * +__ioremap(unsigned long addr, unsigned long size, unsigned long flags) +{ + unsigned long p, v, i; + int err; + + /* + * Choose an address to map it to. + * Once the vmalloc system is running, we use it. + * Before then, we use space going down from ioremap_base + * (ioremap_bot records where we're up to). + */ + p = addr & PAGE_MASK; + size = PAGE_ALIGN(addr + size) - p; + + /* + * If the address lies within the first 16 MB, assume it's in ISA + * memory space + */ + if (p < 16*1024*1024) + p += _ISA_MEM_BASE; + + /* + * Don't allow anybody to remap normal RAM that we're using. + * mem_init() sets high_memory so only do the check after that. + */ + if ( mem_init_done && (p < virt_to_phys(high_memory)) ) + { + printk("__ioremap(): phys addr %0lx is RAM lr %p\n", p, + __builtin_return_address(0)); + return NULL; + } + + if (size == 0) + return NULL; + + /* + * Is it already mapped? Perhaps overlapped by a previous + * BAT mapping. If the whole area is mapped then we're done, + * otherwise remap it since we want to keep the virt addrs for + * each request contiguous. + * + * We make the assumption here that if the bottom and top + * of the range we want are mapped then it's mapped to the + * same virt address (and this is contiguous). + * -- Cort + */ + if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ ) + goto out; + + if (mem_init_done) { + struct vm_struct *area; + area = get_vm_area(size, VM_IOREMAP); + if (area == 0) + return NULL; + v = VMALLOC_VMADDR(area->addr); + } else { + v = (ioremap_bot -= size); + } + + if ((flags & _PAGE_PRESENT) == 0) + flags |= _PAGE_KERNEL; + if (flags & _PAGE_NO_CACHE) + flags |= _PAGE_GUARDED; + + /* + * Should check if it is a candidate for a BAT mapping + */ + + err = 0; + for (i = 0; i < size && err == 0; i += PAGE_SIZE) + err = map_page(v+i, p+i, flags); + if (err) { + if (mem_init_done) + vfree((void *)v); + return NULL; + } + +out: + return (void *) (v + (addr & ~PAGE_MASK)); +} + +void iounmap(void *addr) +{ + /* + * If mapped by BATs then there is nothing to do. + * Calling vfree() generates a benign warning. + */ + if (v_mapped_by_bats((unsigned long)addr)) return; + + if (addr > high_memory && (unsigned long) addr < ioremap_bot) + vfree((void *) (PAGE_MASK & (unsigned long) addr)); +} +#endif /* CONFIG_PPC_ISERIES */ + +int +map_page(unsigned long va, unsigned long pa, int flags) +{ + pmd_t *pd; + pte_t *pg; + int err = -ENOMEM; + + spin_lock(&init_mm.page_table_lock); + /* Use upper 10 bits of VA to index the first level map */ + pd = pmd_offset(pgd_offset_k(va), va); + /* Use middle 10 bits of VA to index the second-level map */ + pg = pte_alloc(&init_mm, pd, va); + if (pg != 0) { + err = 0; + set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags))); + if (mem_init_done) + flush_HPTE(0, va, pg); + } + spin_unlock(&init_mm.page_table_lock); + return err; +} + +/* + * Map in all of physical memory starting at KERNELBASE. + */ +void __init mapin_ram(void) +{ + unsigned long v, p, s, f; + +#ifdef HAVE_BATS + if (!__map_without_bats) + bat_mapin_ram(); +#endif /* HAVE_BATS */ + + v = KERNELBASE; + p = ram_phys_base; + for (s = 0; s < total_lowmem; s += PAGE_SIZE) { + /* On the MPC8xx, we want the page shared so we + * don't get ASID compares on kernel space. + */ + f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED; +#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) + /* Allows stub to set breakpoints everywhere */ + f |= _PAGE_RW | _PAGE_DIRTY; +#else + if ((char *) v < _stext || (char *) v >= etext) + f |= _PAGE_RW | _PAGE_DIRTY; +#ifndef CONFIG_8xx + else + /* On the powerpc (not 8xx), no user access + forces R/W kernel access */ + f |= _PAGE_USER; +#endif /* CONFIG_8xx */ +#endif /* CONFIG_KGDB */ + map_page(v, p, f); + v += PAGE_SIZE; + p += PAGE_SIZE; + } +} + +/* is x a power of 2? */ +#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) + +/* + * Set up a mapping for a block of I/O. + * virt, phys, size must all be page-aligned. + * This should only be called before ioremap is called. + */ +void __init io_block_mapping(unsigned long virt, unsigned long phys, + unsigned int size, int flags) +{ + int i; + + if (virt > KERNELBASE && virt < ioremap_bot) + ioremap_bot = ioremap_base = virt; + +#ifdef HAVE_BATS + /* + * Use a BAT for this if possible... + */ + if (io_bat_index < 2 && is_power_of_2(size) + && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { + setbat(io_bat_index, virt, phys, size, flags); + ++io_bat_index; + return; + } +#endif /* HAVE_BATS */ + + /* No BATs available, put it in the page tables. */ + for (i = 0; i < size; i += PAGE_SIZE) + map_page(virt + i, phys + i, flags); +} + +/* Scan the real Linux page tables and return a PTE pointer for + * a virtual address in a context. + * Returns true (1) if PTE was found, zero otherwise. The pointer to + * the PTE pointer is unmodified if PTE is not found. + */ +int +get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int retval = 0; + + pgd = pgd_offset(mm, addr & PAGE_MASK); + if (pgd) { + pmd = pmd_offset(pgd, addr & PAGE_MASK); + if (pmd_present(*pmd)) { + pte = pte_offset(pmd, addr & PAGE_MASK); + if (pte) { + retval = 1; + *ptep = pte; + } + } + } + return(retval); +} + +/* Find physical address for this virtual address. Normally used by + * I/O functions, but anyone can call it. + */ +unsigned long iopa(unsigned long addr) +{ + unsigned long pa; + + /* I don't know why this won't work on PMacs or CHRP. It + * appears there is some bug, or there is some implicit + * mapping done not properly represented by BATs or in page + * tables.......I am actively working on resolving this, but + * can't hold up other stuff. -- Dan + */ + pte_t *pte; + struct mm_struct *mm; + + /* Check the BATs */ + pa = v_mapped_by_bats(addr); + if (pa) + return pa; + + /* Allow mapping of user addresses (within the thread) + * for DMA if necessary. + */ + if (addr < TASK_SIZE) + mm = current->mm; + else + mm = &init_mm; + + pa = 0; + if (get_pteptr(mm, addr, &pte)) + pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); + + return(pa); +} + +/* This is will find the virtual address for a physical one.... + * Swiped from APUS, could be dangerous :-). + * This is only a placeholder until I really find a way to make this + * work. -- Dan + */ +unsigned long +mm_ptov (unsigned long paddr) +{ + unsigned long ret; +#if 0 + if (paddr < 16*1024*1024) + ret = ZTWO_VADDR(paddr); + else { + int i; + + for (i = 0; i < kmap_chunk_count;){ + unsigned long phys = kmap_chunks[i++]; + unsigned long size = kmap_chunks[i++]; + unsigned long virt = kmap_chunks[i++]; + if (paddr >= phys + && paddr < (phys + size)){ + ret = virt + paddr - phys; + goto exit; + } + } + + ret = (unsigned long) __va(paddr); + } +exit: +#ifdef DEBUGPV + printk ("PTOV(%lx)=%lx\n", paddr, ret); +#endif +#else + ret = (unsigned long)paddr + KERNELBASE; +#endif + return ret; +} + diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/ppc_mmu.c linux/arch/ppc/mm/ppc_mmu.c --- v2.4.9/linux/arch/ppc/mm/ppc_mmu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/ppc_mmu.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,313 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines for handling the MMU on those + * PowerPC implementations where the MMU substantially follows the + * architecture specification. This includes the 6xx, 7xx, 7xxx, + * 8260, and POWER3 implementations but excludes the 8xx and 4xx. + * Although the iSeries hardware does comply with the architecture + * specification, the need to work through the hypervisor makes + * things sufficiently different that it is handled elsewhere. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "mmu_decl.h" +#include "mem_pieces.h" + +PTE *Hash, *Hash_end; +unsigned long Hash_size, Hash_mask; +unsigned long _SDR1; + +union ubat { /* BAT register values to be loaded */ + BAT bat; +#ifdef CONFIG_PPC64BRIDGE + u64 word[2]; +#else + u32 word[2]; +#endif +} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ + +struct batrange { /* stores address ranges mapped by BATs */ + unsigned long start; + unsigned long limit; + unsigned long phys; +} bat_addrs[4]; + +/* + * Return PA for this VA if it is mapped by a BAT, or 0 + */ +unsigned long v_mapped_by_bats(unsigned long va) +{ + int b; + for (b = 0; b < 4; ++b) + if (va >= bat_addrs[b].start && va < bat_addrs[b].limit) + return bat_addrs[b].phys + (va - bat_addrs[b].start); + return 0; +} + +/* + * Return VA for a given PA or 0 if not mapped + */ +unsigned long p_mapped_by_bats(unsigned long pa) +{ + int b; + for (b = 0; b < 4; ++b) + if (pa >= bat_addrs[b].phys + && pa < (bat_addrs[b].limit-bat_addrs[b].start) + +bat_addrs[b].phys) + return bat_addrs[b].start+(pa-bat_addrs[b].phys); + return 0; +} + +void __init bat_mapin_ram(void) +{ + unsigned long tot, bl, done; + unsigned long max_size = (256<<20); + unsigned long align; + + /* Set up BAT2 and if necessary BAT3 to cover RAM. */ + + /* Make sure we don't map a block larger than the + smallest alignment of the physical address. */ + /* alignment of ram_phys_base */ + align = ~(ram_phys_base-1) & ram_phys_base; + /* set BAT block size to MIN(max_size, align) */ + if (align && align < max_size) + max_size = align; + + tot = total_lowmem; + for (bl = 128<<10; bl < max_size; bl <<= 1) { + if (bl * 2 > tot) + break; + } + + setbat(2, KERNELBASE, ram_phys_base, bl, _PAGE_KERNEL); + done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1; + if ((done < tot) && !bat_addrs[3].limit) { + /* use BAT3 to cover a bit more */ + tot -= done; + for (bl = 128<<10; bl < max_size; bl <<= 1) + if (bl * 2 > tot) + break; + setbat(3, KERNELBASE+done, ram_phys_base+done, bl, + _PAGE_KERNEL); + } +} + +/* + * Set up one of the I/D BAT (block address translation) register pairs. + * The parameters are not checked; in particular size must be a power + * of 2 between 128k and 256M. + */ +void __init setbat(int index, unsigned long virt, unsigned long phys, + unsigned int size, int flags) +{ + unsigned int bl; + int wimgxpp; + union ubat *bat = BATS[index]; + +#ifdef CONFIG_SMP + if ((flags & _PAGE_NO_CACHE) == 0) + flags |= _PAGE_COHERENT; +#endif + bl = (size >> 17) - 1; + if (PVR_VER(mfspr(PVR)) != 1) { + /* 603, 604, etc. */ + /* Do DBAT first */ + wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE + | _PAGE_COHERENT | _PAGE_GUARDED); + wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX; + bat[1].word[0] = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */ + bat[1].word[1] = phys | wimgxpp; +#ifndef CONFIG_KGDB /* want user access for breakpoints */ + if (flags & _PAGE_USER) +#endif + bat[1].bat.batu.vp = 1; + if (flags & _PAGE_GUARDED) { + /* G bit must be zero in IBATs */ + bat[0].word[0] = bat[0].word[1] = 0; + } else { + /* make IBAT same as DBAT */ + bat[0] = bat[1]; + } + } else { + /* 601 cpu */ + if (bl > BL_8M) + bl = BL_8M; + wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE + | _PAGE_COHERENT); + wimgxpp |= (flags & _PAGE_RW)? + ((flags & _PAGE_USER)? PP_RWRW: PP_RWXX): PP_RXRX; + bat->word[0] = virt | wimgxpp | 4; /* Ks=0, Ku=1 */ + bat->word[1] = phys | bl | 0x40; /* V=1 */ + } + + bat_addrs[index].start = virt; + bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1; + bat_addrs[index].phys = phys; +} + +/* + * Initialize the hash table and patch the instructions in hashtable.S. + */ +void __init MMU_init_hw(void) +{ + int Hash_bits, mb, mb2; + unsigned int hmask; + + extern unsigned int hash_page_patch_A[]; + extern unsigned int hash_page_patch_B[], hash_page_patch_C[]; + extern unsigned int hash_page[]; + extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[]; + +#ifdef CONFIG_PPC64BRIDGE + /* The hash table has already been allocated and initialized + in prom.c */ + Hash_mask = (Hash_size >> 7) - 1; + hmask = Hash_mask >> 9; + Hash_bits = __ilog2(Hash_size) - 7; + mb = 25 - Hash_bits; + if (Hash_bits > 16) + Hash_bits = 16; + mb2 = 25 - Hash_bits; + + /* Remove the hash table from the available memory */ + if (Hash) + reserve_phys_mem(__pa(Hash), Hash_size); + +#else /* CONFIG_PPC64BRIDGE */ + unsigned int h; + + if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE) == 0) + return; + if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); + /* + * Allow 64k of hash table for every 16MB of memory, + * up to a maximum of 2MB. + */ + for (h = 64<<10; h < total_memory / 256 && h < (2<<20); h *= 2) + ; + Hash_size = h; + Hash_mask = (h >> 6) - 1; + hmask = Hash_mask >> 10; + Hash_bits = __ilog2(h) - 6; + mb = 26 - Hash_bits; + if (Hash_bits > 16) + Hash_bits = 16; + mb2 = 26 - Hash_bits; + + if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); + /* Find some memory for the hash table. */ + if ( Hash_size ) { + Hash = mem_pieces_find(Hash_size, Hash_size); + cacheable_memzero(Hash, Hash_size); + _SDR1 = __pa(Hash) | (Hash_mask >> 10); + } else + Hash = 0; +#endif /* CONFIG_PPC64BRIDGE */ + + printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", + total_memory >> 20, Hash_size >> 10, Hash); + if (Hash_size) { + if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345); + Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); + + /* + * Patch up the instructions in hashtable.S:create_hpte + */ + hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff) + | ((unsigned int)(Hash) >> 16); + hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) + | (mb << 6); + hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) + | (mb2 << 6); + hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) + | hmask; + hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) + | hmask; + /* + * Ensure that the locations we've patched have been written + * out from the data cache and invalidated in the instruction + * cache, on those machines with split caches. + */ + flush_icache_range((unsigned long) &hash_page_patch_A[0], + (unsigned long) &hash_page_patch_C[1]); + /* + * Patch up the instructions in hashtable.S:flush_hash_page + */ + flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff) + | ((unsigned int)(Hash) >> 16); + flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) + | (mb << 6); + flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) + | (mb2 << 6); + flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) + | hmask; + flush_icache_range((unsigned long) &flush_hash_patch_A[0], + (unsigned long) &flush_hash_patch_B[1]); + } + else { + Hash_end = 0; + /* + * Put a blr (procedure return) instruction at the + * start of hash_page, since we can still get DSI + * exceptions on a 603. + */ + hash_page[0] = 0x4e800020; + flush_icache_range((unsigned long) &hash_page[0], + (unsigned long) &hash_page[1]); + } + + if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); +} + +/* + * This is called at the end of handling a user page fault, when the + * fault has been handled by updating a PTE in the linux page tables. + * We use it to preload an HPTE into the hash table corresponding to + * the updated linux PTE. + */ +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, + pte_t pte) +{ + struct mm_struct *mm; + pmd_t *pmd; + pte_t *ptep; + static int nopreload; + + if (Hash == 0 || nopreload) + return; + mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm; + pmd = pmd_offset(pgd_offset(mm, address), address); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, address); + add_hash_page(mm->context, address, ptep); + } +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/tlb.c linux/arch/ppc/mm/tlb.c --- v2.4.9/linux/arch/ppc/mm/tlb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/tlb.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,162 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines for TLB flushing. + * On machines where the MMU uses a hash table to store virtual to + * physical translations, these routines flush entries from the the + * hash table also. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include + +#include "mmu_decl.h" + +/* + * TLB flushing: + * + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(mm, start, end) flushes a range of pages + * + * since the hardware hash table functions as an extension of the + * tlb as far as the linux tables are concerned, flush it too. + * -- Cort + */ + +/* + * Flush all tlb/hash table entries (except perhaps for those + * mapping RAM starting at PAGE_OFFSET, since they never change). + */ +void +local_flush_tlb_all(void) +{ + /* aargh!!! */ + /* + * Just flush the kernel part of the address space, that's + * all that the current callers of this require. + * Eventually I hope to persuade the powers that be that + * we can and should dispense with flush_tlb_all(). + * -- paulus. + */ + local_flush_tlb_range(&init_mm, TASK_SIZE, ~0UL); + +#ifdef CONFIG_SMP + smp_send_tlb_invalidate(0); +#endif /* CONFIG_SMP */ +} + +/* + * Flush all the (user) entries for the address space described + * by mm. We can't rely on mm->mmap describing all the entries + * that might be in the hash table. + */ +void +local_flush_tlb_mm(struct mm_struct *mm) +{ + if (Hash == 0) { + _tlbia(); + return; + } + + if (mm->map_count) { + struct vm_area_struct *mp; + for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) + local_flush_tlb_range(mm, mp->vm_start, mp->vm_end); + } else + local_flush_tlb_range(mm, 0, TASK_SIZE); + +#ifdef CONFIG_SMP + smp_send_tlb_invalidate(0); +#endif +} + +void +local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) +{ + struct mm_struct *mm; + pmd_t *pmd; + pte_t *pte; + + if (Hash == 0) { + _tlbie(vmaddr); + return; + } + mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; + pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); + if (!pmd_none(*pmd)) { + pte = pte_offset(pmd, vmaddr); + if (pte_val(*pte) & _PAGE_HASHPTE) + flush_hash_page(mm->context, vmaddr, pte); + } +#ifdef CONFIG_SMP + smp_send_tlb_invalidate(0); +#endif +} + + +/* + * For each address in the range, find the pte for the address + * and check _PAGE_HASHPTE bit; if it is set, find and destroy + * the corresponding HPTE. + */ +void +local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) +{ + pmd_t *pmd; + pte_t *pte; + unsigned long pmd_end; + unsigned int ctx = mm->context; + + if (Hash == 0) { + _tlbia(); + return; + } + start &= PAGE_MASK; + if (start >= end) + return; + pmd = pmd_offset(pgd_offset(mm, start), start); + do { + pmd_end = (start + PGDIR_SIZE) & PGDIR_MASK; + if (!pmd_none(*pmd)) { + if (!pmd_end || pmd_end > end) + pmd_end = end; + pte = pte_offset(pmd, start); + do { + if ((pte_val(*pte) & _PAGE_HASHPTE) != 0) + flush_hash_page(ctx, start, pte); + start += PAGE_SIZE; + ++pte; + } while (start && start < pmd_end); + } else { + start = pmd_end; + } + ++pmd; + } while (start && start < end); + +#ifdef CONFIG_SMP + smp_send_tlb_invalidate(0); +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds --- v2.4.9/linux/arch/ppc/vmlinux.lds Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/vmlinux.lds Tue Aug 28 06:58:33 2001 @@ -70,6 +70,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___ftr_fixup = .; + __ftr_fixup : { *(__ftr_fixup) } + __stop___ftr_fixup = .; + . = ALIGN(32); .data.cacheline_aligned : { *(.data.cacheline_aligned) } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c --- v2.4.9/linux/arch/ppc/xmon/start.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/xmon/start.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.start.c 1.12 05/21/01 21:39:13 paulus + * BK Id: SCCS/s.start.c 1.16 08/20/01 22:17:58 paulus */ /* * Copyright (C) 1996 Paul Mackerras. @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef CONFIG_SMP #include #endif @@ -25,8 +26,6 @@ static volatile unsigned char *sccc, *sccd; unsigned long TXRDY, RXRDY; extern void xmon_printf(const char *fmt, ...); -extern void prom_drawchar(char); -extern void prom_drawstring(const char *str); static int xmon_expect(const char *str, unsigned int timeout); static int console; @@ -56,6 +55,7 @@ void xmon_map_scc(void) { +#ifdef CONFIG_ALL_PPC volatile unsigned char *base; use_screen = 0; @@ -85,14 +85,34 @@ use_screen = 1; #endif } - prom_drawstring("xmon uses "); + if (!use_screen && (np = find_devices("escc")) != NULL) { + /* + * look for the device node for the serial port + * we're using and see if it says it has a modem + */ + char *name = xmon_use_sccb? "ch-b": "ch-a"; + char *slots; + int l; + + np = np->child; + while (np != NULL && strcmp(np->name, name) != 0) + np = np->sibling; + if (np != NULL) { + /* XXX should parse this properly */ + slots = get_property(np, "slot-names", &l); + if (slots != NULL && l >= 10 + && strcmp(slots+4, "Modem") == 0) + via_modem = 1; + } + } + btext_drawstring("xmon uses "); if (use_screen) - prom_drawstring("screen and keyboard\n"); + btext_drawstring("screen and keyboard\n"); else { if (via_modem) - prom_drawstring("modem on "); - prom_drawstring(xmon_use_sccb? "printer": "modem"); - prom_drawstring(" port\n"); + btext_drawstring("modem on "); + btext_drawstring(xmon_use_sccb? "printer": "modem"); + btext_drawstring(" port\n"); } #endif /* CONFIG_BOOTX_TEXT */ @@ -114,15 +134,6 @@ sccc = base + (addr & ~PAGE_MASK); sccd = sccc + 0x10; } - else if ( _machine & _MACH_gemini ) - { - /* should already be mapped by the kernel boot */ - sccc = (volatile unsigned char *) 0xffeffb0d; - sccd = (volatile unsigned char *) 0xffeffb08; - TXRDY = 0x20; - RXRDY = 1; - console = 1; - } else { /* should already be mapped by the kernel boot */ @@ -135,6 +146,14 @@ TXRDY = 0x20; RXRDY = 1; } +#elif defined(CONFIG_GEMINI) + /* should already be mapped by the kernel boot */ + sccc = (volatile unsigned char *) 0xffeffb0d; + sccd = (volatile unsigned char *) 0xffeffb08; + TXRDY = 0x20; + RXRDY = 1; + console = 1; +#endif /* platform */ } static int scc_initialized = 0; @@ -175,7 +194,7 @@ if (use_screen) { /* write it on the screen */ for (i = 0; i < nb; ++i) - prom_drawchar(*p++); + btext_drawchar(*p++); goto out; } #endif @@ -216,7 +235,7 @@ static unsigned char xmon_keytab[128] = "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */ - "yt123465=97-80o]" /* 0x10 - 0x1f */ + "yt123465=97-80]o" /* 0x10 - 0x1f */ "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */ "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ @@ -224,7 +243,7 @@ static unsigned char xmon_shift_keytab[128] = "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */ - "YT!@#$^%+(&=*)}O" /* 0x10 - 0x1f */ + "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */ "U{IP\rLJ\"K:|" /* 0x20 - 0x2f */ "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ @@ -243,15 +262,15 @@ do { if (--t < 0) { on = 1 - on; - prom_drawchar(on? 0xdb: 0x20); - prom_drawchar('\b'); + btext_drawchar(on? 0xdb: 0x20); + btext_drawchar('\b'); t = 200000; } do_poll_adb(); } while (xmon_adb_keycode == -1); k = xmon_adb_keycode; if (on) - prom_drawstring(" \b"); + btext_drawstring(" \b"); /* test for shift keys */ if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) { @@ -544,7 +563,9 @@ xmon_enter(void) { #ifdef CONFIG_ADB_PMU - pmu_suspend(); + if (_machine == _MACH_Pmac) { + pmu_suspend(); + } #endif } @@ -552,6 +573,8 @@ xmon_leave(void) { #ifdef CONFIG_ADB_PMU - pmu_resume(); + if (_machine == _MACH_Pmac) { + pmu_resume(); + } #endif } diff -u --recursive --new-file v2.4.9/linux/arch/sh/Makefile linux/arch/sh/Makefile --- v2.4.9/linux/arch/sh/Makefile Fri Dec 29 14:07:20 2000 +++ linux/arch/sh/Makefile Sat Sep 8 12:29:09 2001 @@ -75,6 +75,11 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +ifneq ($(CONFIG_SH_GENERIC)$(CONFIG_SH_STB1_HARP)$(CONFIG_SH_STB1_OVERDRIVE),) +SUBDIRS += arch/sh/stboards +CORE_FILES += arch/sh/stboards/stboards.o +endif + vmlinux: arch/sh/vmlinux.lds arch/sh/vmlinux.lds: arch/sh/vmlinux.lds.S FORCE @@ -93,6 +98,7 @@ archclean: @$(MAKEBOOT) clean $(MAKE) -C arch/$(ARCH)/kernel clean + $(MAKE) -C arch/$(ARCH)/stboards clean # $(MAKE) -C arch/$(ARCH)/tools clean archmrproper: diff -u --recursive --new-file v2.4.9/linux/arch/sh/config.in linux/arch/sh/config.in --- v2.4.9/linux/arch/sh/config.in Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/config.in Sat Sep 8 12:29:09 2001 @@ -42,6 +42,7 @@ CAT68701 CONFIG_SH_CAT68701 \ BigSur CONFIG_SH_BIGSUR \ SH2000 CONFIG_SH_SH2000 \ + ADX CONFIG_SH_ADX \ BareCPU CONFIG_SH_UNKNOWN" Generic # The SH7750 RTC module is disabled in the Dreamcast @@ -88,24 +89,40 @@ define_bool CONFIG_CPU_SH4 y fi bool 'Little Endian' CONFIG_CPU_LITTLE_ENDIAN +# Platform-specific memory start and size definitions if [ "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o "$CONFIG_SH_HP600" = "y" -o \ "$CONFIG_SH_BIGSUR" = "y" -o "$CONFIG_SH_7751_SOLUTION_ENGINE" = "y" -o \ "$CONFIG_SH_DREAMCAST" = "y" -o "$CONFIG_SH_SH2000" = "y" ]; then - define_hex CONFIG_MEMORY_START 0c000000 -else - if [ "$CONFIG_CPU_SUBTYPE_ST40STB1" = "y" ]; then - bool 'Memory on LMI' CONFIG_ST40_LMI_MEMORY - if [ "$CONFIG_ST40_LMI_MEMORY" = "y" ] ; then + define_hex CONFIG_MEMORY_START 0c000000 + define_hex CONFIG_MEMORY_SIZE 00400000 + define_bool CONFIG_MEMORY_SET y +fi +if [ "$CONFIG_CPU_SUBTYPE_ST40STB1" = "y" ]; then + bool 'Memory on LMI' CONFIG_ST40_LMI_MEMORY + if [ "$CONFIG_ST40_LMI_MEMORY" = "y" ] ; then define_hex CONFIG_MEMORY_START 08000000 - else - hex 'EMI physical memory start address' CONFIG_MEMORY_START 08000000 - fi - else - hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 - fi + define_hex CONFIG_MEMORY_SIZE 00400000 + define_bool CONFIG_MEMORY_SET y + fi +fi +if [ "$CONFIG_SH_ADX" = "y" ]; then + define_hex CONFIG_MEMORY_START 08000000 + define_hex CONFIG_MEMORY_SIZE 00400000 + define_bool CONFIG_MEMORY_SET y +fi +# If none of the above have set memory start/size, ask the user. +if [ "$CONFIG_MEMORY_SET" != "y" ]; then + hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 + hex 'Physical memory size' CONFIG_MEMORY_SIZE 00400000 fi endmenu +if [ "$CONFIG_SH_HP690" = "y" ]; then + define_bool CONFIG_DISCONTIGMEM y +else + define_bool CONFIG_DISCONTIGMEM n +fi + mainmenu_option next_comment comment 'General setup' @@ -120,10 +137,23 @@ bool 'Networking support' CONFIG_NET if [ "$CONFIG_SH_GENERIC" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o \ - "$CONFIG_SH_UNKNOWN" = "y" -o "$CONFIG_SH_CAT68701" = "y" ]; then + "$CONFIG_SH_UNKNOWN" = "y" -o "$CONFIG_SH_CAT68701" = "y" -o \ + "$CONFIG_SH_ADX" = "y" ]; then bool 'Compact Flash Enabler support' CONFIG_CF_ENABLER fi +if [ "$CONFIG_CF_ENABLER" = "y" ]; then + choice 'Compact Flash Connection Area' \ + "Area5 CONFIG_CF_AREA5 \ + Area6 CONFIG_CF_AREA6" Area6 + if [ "$CONFIG_CF_AREA5" = "y" ]; then + define_hex CONFIG_CF_BASE_ADDR b4000000 + fi + if [ "$CONFIG_CF_AREA6" = "y" ]; then + define_hex CONFIG_CF_BASE_ADDR b8000000 + fi +fi + bool 'Hitachi HD64461 companion chip support' CONFIG_HD64461 if [ "$CONFIG_HD64461" = "y" ]; then int 'HD64461 IRQ' CONFIG_HD64461_IRQ 36 @@ -136,6 +166,8 @@ int 'HD64465 IRQ' CONFIG_HD64465_IRQ 5 fi +bool 'DMA controller (DMAC) support' CONFIG_SH_DMA + bool 'PCI support' CONFIG_PCI if [ "$CONFIG_PCI" = "y" ]; then choice ' PCI access mode' \ @@ -148,6 +180,7 @@ if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then define_bool CONFIG_PCI_DIRECT y fi + define_bool CONFIG_SH_PCIDMA_NONCOHERENT n fi source drivers/pci/Config.in @@ -224,13 +257,22 @@ endmenu fi +mainmenu_option next_comment +comment 'Old CD-ROM drivers (not SCSI, not IDE)' + +bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI +if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then + source drivers/cdrom/Config.in +fi +endmenu + # # input before char - char/joystick depends on it. As does USB. # source drivers/input/Config.in if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then -source drivers/maple/Config.in + source drivers/maple/Config.in fi mainmenu_option next_comment @@ -259,7 +301,7 @@ "$CONFIG_SH_BIGSUR" = "y" -o \ "$CONFIG_SH_7751_SOLUTION_ENGINE" = "y" -o \ "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then - bool 'Heartbeat LED' CONFIG_HEARTBEAT + bool 'Heartbeat LED' CONFIG_HEARTBEAT fi if [ "$CONFIG_SH_DREAMCAST" = "y" -a "$CONFIG_MAPLE" != "n" ]; then @@ -322,7 +364,6 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ bool 'Use LinuxSH standard BIOS' CONFIG_SH_STANDARD_BIOS if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then - bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB bool 'Early printk support' CONFIG_SH_EARLY_PRINTK fi endmenu diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/Makefile linux/arch/sh/kernel/Makefile --- v2.4.9/linux/arch/sh/kernel/Makefile Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/Makefile Sat Sep 8 12:29:09 2001 @@ -21,13 +21,14 @@ obj-$(CONFIG_CF_ENABLER) += cf-enabler.o obj-$(CONFIG_CPU_SH4) += fpu.o obj-$(CONFIG_SH_RTC) += rtc.o +obj-$(CONFIG_SH_DMA) += dma.o obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o ifeq ($(CONFIG_PCI),y) ifeq ($(CONFIG_SH_DREAMCAST),y) -obj-y += pci-dc.o +obj-y += pci-dc.o pcibios.o else -obj-y += pci-dma.o +obj-y += pci-dma.o pcibios.o obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)+= pci_st40.o obj-$(CONFIG_CPU_SUBTYPE_SH7751)+= pci-sh7751.o obj-$(CONFIG_SH_BIGSUR)+= pci-bigsur.o @@ -41,8 +42,10 @@ obj-$(CONFIG_SH_SOLUTION_ENGINE)+= mach_se.o setup_se.o io_se.o led_se.o machine-specific-objs += mach_se.o setup_se.o io_se.o led_se.o -obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= mach_se.o setup_se.o io_se.o led_se.o pci-7751se.o -machine-specific-objs += mach_se.o setup_se.o io_se.o led_se.o pci-7751se.o +obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= mach_7751se.o setup_7751se.o \ + io_7751se.o led_7751se.o +machine-specific-objs += mach_7751se.o 7751setup_se.o \ + io_7751se.o led_7751se.o pci-7751se.o obj-$(CONFIG_SH_BIGSUR) += mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o machine-specific-objs += mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o @@ -64,11 +67,14 @@ obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) +=irq_intc2.o +obj-$(CONFIG_SH_ADX) += mach_adx.o setup_adx.o io_adx.o irq_maskreg.o +machine-specific-objs += mach_adx.o setup_adx.o io_adx.o irq_maskreg.o + # Doesn't compile well, so don't include in machine-specific-objs obj-$(CONFIG_HD64465) += setup_hd64465.o io_hd64465.o hd64465_gpio.o obj-$(CONFIG_SH_DMIDA) += mach_dmida.o obj-$(CONFIG_SH_EC3104) += setup_ec3104.o io_ec3104.o mach_ec3104.o -obj-$(CONFIG_SH_DREAMCAST) += mach_dc.o setup_dc.o io_dc.o +obj-$(CONFIG_SH_DREAMCAST) += mach_dc.o setup_dc.o io_dc.o rtc-aica.o ifeq ($(CONFIG_SH_GENERIC),y) obj-y += $(machine-specific-objs) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/cf-enabler.c linux/arch/sh/kernel/cf-enabler.c --- v2.4.9/linux/arch/sh/kernel/cf-enabler.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/cf-enabler.c Sat Sep 8 12:29:09 2001 @@ -1,9 +1,10 @@ -/* $Id: cf-enabler.c,v 1.2 2000/06/08 05:50:10 gniibe Exp $ +/* $Id: cf-enabler.c,v 1.8 2001/07/18 12:32:21 gniibe Exp $ * * linux/drivers/block/cf-enabler.c * * Copyright (C) 1999 Niibe Yutaka * Copyright (C) 2000 Toshiharu Nozawa + * Copyright (C) 2001 A&D Co., Ltd. * * Enable the CF configuration. */ @@ -14,7 +15,6 @@ #include #include -#define CF_CIS_BASE 0xb8000000 /* * You can connect Compact Flash directly to the bus of SuperH. * This is the enabler for that. @@ -29,15 +29,61 @@ * 0xB8001000 : Common Memory * 0xBA000000 : I/O */ +#if defined(CONFIG_IDE) && defined(__SH4__) +/* SH4 can't access PCMCIA interface through P2 area. + * we must remap it with appropreate attribute bit of the page set. + * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */ +#include +#include + +#if defined(CONFIG_CF_AREA6) +#define slot_no 0 +#else +#define slot_no 1 +#endif + +/* defined in mm/ioremap.c */ +extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags); + +/* use this pointer to access to directly connected compact flash io area*/ +void *cf_io_base; + +static int __init allocate_cf_area(void) +{ + pgprot_t prot; + unsigned long paddrbase, psize; + + /* open I/O area window */ + paddrbase = virt_to_phys((void*)CONFIG_CF_BASE_ADDR); + psize = PAGE_SIZE; + prot = PAGE_KERNEL_PCC(slot_no, _PAGE_PCC_IO16); + cf_io_base = p3_ioremap(paddrbase, psize, prot.pgprot); + if (!cf_io_base) { + printk("allocate_cf_area : can't open CF I/O window!\n"); + return -ENOMEM; + } +/* printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n", + paddrbase, psize, prot.pgprot, cf_io_base);*/ + + /* XXX : do we need attribute and common-memory area also? */ + + return 0; +} +#endif static int __init cf_init_default(void) { -#ifdef CONFIG_IDE - /* Enable the card, and set the level interrupt */ - ctrl_outw(0x0042, CF_CIS_BASE+0x0200); +/* You must have enabled the card, and set the level interrupt + * before reaching this point. Possibly in boot ROM or boot loader. + */ +#if defined(CONFIG_IDE) && defined(__SH4__) + allocate_cf_area(); #endif +#if defined(CONFIG_SH_UNKNOWN) + /* This should be done in each board's init_xxx_irq. */ make_imask_irq(14); disable_irq(14); +#endif return 0; } diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/dma.c linux/arch/sh/kernel/dma.c --- v2.4.9/linux/arch/sh/kernel/dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/dma.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,142 @@ +/* + * arch/sh/kernel/dma.c + * + * Copyright (C) 2000 Takashi YOSHII + * + * PC like DMA API for SuperH's DMAC. + */ + +#include +#include +#include +#include + +#include +#include + +static struct dma_info_t *dma_info[MAX_DMA_CHANNELS]; +static struct dma_info_t *autoinit_info[SH_MAX_DMA_CHANNELS] = {0}; +static spinlock_t dma_spin_lock; + +static unsigned int calc_chcr(struct dma_info_t *info) +{ + unsigned int chcr; + + chcr = ( info->mode & DMA_MODE_WRITE )? info->mode_write : info->mode_read; + if( info->mode & DMA_AUTOINIT ) + chcr |= CHCR_IE; + return chcr; +} + +static __inline__ int ts_shift(unsigned long chcr) +{ + return ((int[]){3,0,1,2,5,0,0,0})[(chcr>>4)&0x000007]; +} + +static void dma_tei(int irq, void *dev_id, struct pt_regs *regs) +{ + int chan = irq - DMTE_IRQ[0]; + struct dma_info_t *info = autoinit_info[chan]; + + if( info->mode & DMA_MODE_WRITE ) + ctrl_outl(info->mem_addr, SAR[info->chan]); + else + ctrl_outl(info->mem_addr, DAR[info->chan]); + + ctrl_outl(info->count>>ts_shift(calc_chcr(info)), DMATCR[info->chan]); + ctrl_outl(ctrl_inl(CHCR[info->chan])&~CHCR_TE, CHCR[info->chan]); +} + +static struct irqaction irq_tei = { dma_tei, SA_INTERRUPT, 0, "dma_tei", NULL, NULL}; + +void setup_dma(unsigned int dmanr, struct dma_info_t *info) +{ + make_ipr_irq(DMTE_IRQ[info->chan], DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); + setup_irq(DMTE_IRQ[info->chan], &irq_tei); + dma_info[dmanr] = info; +} + +unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +void enable_dma(unsigned int dmanr) +{ + struct dma_info_t *info = dma_info[dmanr]; + ctrl_outl(calc_chcr(info)|CHCR_DE, CHCR[info->chan]); +} + +void disable_dma(unsigned int dmanr) +{ + struct dma_info_t *info = dma_info[dmanr]; + ctrl_outl(calc_chcr(info)&~CHCR_DE, CHCR[info->chan]); +} + +void set_dma_mode(unsigned int dmanr, char mode) +{ + struct dma_info_t *info = dma_info[dmanr]; + + info->mode = mode; + set_dma_addr(dmanr, info->mem_addr); + set_dma_count(dmanr, info->count); + autoinit_info[info->chan] = info; +} + +void set_dma_addr(unsigned int dmanr, unsigned int a) +{ + struct dma_info_t *info = dma_info[dmanr]; + unsigned long sar, dar; + + info->mem_addr = a; + sar = (info->mode & DMA_MODE_WRITE)? info->mem_addr: info->dev_addr; + dar = (info->mode & DMA_MODE_WRITE)? info->dev_addr: info->mem_addr; + ctrl_outl(sar, SAR[info->chan]); + ctrl_outl(dar, DAR[info->chan]); +} + +void set_dma_count(unsigned int dmanr, unsigned int count) +{ + struct dma_info_t *info = dma_info[dmanr]; + info->count = count; + ctrl_outl(count>>ts_shift(calc_chcr(info)), DMATCR[info->chan]); +} + +int get_dma_residue(unsigned int dmanr) +{ + struct dma_info_t *info = dma_info[dmanr]; + return ctrl_inl(DMATCR[info->chan])< +#include +#include +#include +#include + +#include +#include + +#if 0 +/****************************************************************** + * Variables from io_se.c, related to PCMCIA (not PCI); we're not + * compiling them in, and have removed references from functions + * which follow. [Many checked for IO ports in the range bounded + * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset. + * As start/stop are uninitialized, only port 0x0 would match?] + * When used, remember to adjust names to avoid clash with io_se? + *****************************************************************/ +/* SH pcmcia io window base, start and end. */ +int sh_pcic_io_wbase = 0xb8400000; +int sh_pcic_io_start; +int sh_pcic_io_stop; +int sh_pcic_io_type; +int sh_pcic_io_dummy; +/*************************************************************/ +#endif + +/* + * The 7751 Solution Engine uses the built-in PCI controller (PCIC) + * of the 7751 processor, and has a SuperIO accessible via the PCI. + * The board also includes a PCMCIA controller on its memory bus, + * like the other Solution Engine boards. + */ + +#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR) +#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR) +#define PCI_IO_AREA SH7751_PCI_IO_BASE +#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE + +#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK)) + +#define maybebadio(name,port) \ + printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +static inline volatile __u16 * +port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); +#if 0 + else + return (volatile __u16 *) (PA_SUPERIO + (port << 1)); +#endif + maybebadio(name,port); + return (volatile __u16*)port; +} + +#if 0 +/* The 7751 Solution Engine seems to have everything hooked */ +/* up pretty normally (nothing on high-bytes only...) so this */ +/* shouldn't be needed */ +static inline int +shifted_port(unsigned long port) +{ + /* For IDE registers, value is not shifted */ + if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) + return 0; + else + return 1; +} +#endif + +/* In case someone configures the kernel w/o PCI support: in that */ +/* scenario, don't ever bother to check for PCI-window addresses */ + +/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */ +#if defined(CONFIG_PCI) +#define CHECK_SH7751_PCIIO(port) \ + ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE))) +#else +#define CHECK_SH_7751_PCIIO(port) (0) +#endif + +/* + * General outline: remap really low stuff [eventually] to SuperIO, + * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) + * is mapped through the PCI IO window. Stuff with high bits (PXSEG) + * should be way beyond the window, and is used w/o translation for + * compatibility. + */ +unsigned char sh7751se_inb(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned char *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned char *)PCI_IOMAP(port); + else + return (*port2adr(port))&0xff; +} + +unsigned char sh7751se_inb_p(unsigned long port) +{ + unsigned char v; + + if (PXSEG(port)) + v = *(volatile unsigned char *)port; + else if (CHECK_SH7751_PCIIO(port)) + v = *(volatile unsigned char *)PCI_IOMAP(port); + else + v = (*port2adr(port))&0xff; + delay(); + return v; +} + +unsigned short sh7751se_inw(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned short *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned short *)PCI_IOMAP(port); + else if (port >= 0x2000) + return *port2adr(port); + else + maybebadio(inw, port); + return 0; +} + +unsigned int sh7751se_inl(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned long *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned int *)PCI_IOMAP(port); + else if (port >= 0x2000) + return *port2adr(port); + else + maybebadio(inl, port); + return 0; +} + +void sh7751se_outb(unsigned char value, unsigned long port) +{ + + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned char*)PCI_IOMAP(port)) = value; + else + *(port2adr(port)) = value; +} + +void sh7751se_outb_p(unsigned char value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned char*)PCI_IOMAP(port)) = value; + else + *(port2adr(port)) = value; + delay(); +} + +void sh7751se_outw(unsigned short value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned short *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned short *)PCI_IOMAP(port)) = value; + else if (port >= 0x2000) + *port2adr(port) = value; + else + maybebadio(outw, port); +} + +void sh7751se_outl(unsigned int value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned long *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned long*)PCI_IOMAP(port)) = value; + else + maybebadio(outl, port); +} + +void sh7751se_insb(unsigned long port, void *addr, unsigned long count) +{ + unsigned char *p = addr; + while (count--) *p++ = sh7751se_inb(port); +} + +void sh7751se_insw(unsigned long port, void *addr, unsigned long count) +{ + unsigned short *p = addr; + while (count--) *p++ = sh7751se_inw(port); +} + +void sh7751se_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(insl, port); +} + +void sh7751se_outsb(unsigned long port, const void *addr, unsigned long count) +{ + unsigned char *p = (unsigned char*)addr; + while (count--) sh7751se_outb(*p++, port); +} + +void sh7751se_outsw(unsigned long port, const void *addr, unsigned long count) +{ + unsigned short *p = (unsigned short*)addr; + while (count--) sh7751se_outw(*p++, port); +} + +void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(outsw, port); +} + +/* For read/write calls, just copy generic (pass-thru); PCIMBR is */ +/* already set up. For a larger memory space, these would need to */ +/* reset PCIMBR as needed on a per-call basis... */ + +unsigned char sh7751se_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned short sh7751se_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned int sh7751se_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void sh7751se_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void sh7751se_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void sh7751se_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + + + +/* Map ISA bus address to the real address. Only for PCMCIA. */ + +/* ISA page descriptor. */ +static __u32 sh_isa_memmap[256]; + +static int +sh_isa_mmap(__u32 start, __u32 length, __u32 offset) +{ + int idx; + + if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000)) + return -1; + + idx = start >> 12; + sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff); +#if 0 + printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n", + start, length, offset, idx, sh_isa_memmap[idx]); +#endif + return 0; +} + +unsigned long +sh7751se_isa_port2addr(unsigned long offset) +{ + int idx; + + idx = (offset >> 12) & 0xff; + offset &= 0xfff; + return sh_isa_memmap[idx] + offset; +} diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/io_adx.c linux/arch/sh/kernel/io_adx.c --- v2.4.9/linux/arch/sh/kernel/io_adx.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/io_adx.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,192 @@ +/* + * linux/arch/sh/kernel/io_adx.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * I/O routine and setup routines for A&D ADX Board + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include +#include +#include + +#define PORT2ADDR(x) (adx_isa_port2addr(x)) + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +unsigned char adx_inb(unsigned long port) +{ + return *(volatile unsigned char*)PORT2ADDR(port); +} + +unsigned short adx_inw(unsigned long port) +{ + return *(volatile unsigned short*)PORT2ADDR(port); +} + +unsigned int adx_inl(unsigned long port) +{ + return *(volatile unsigned long*)PORT2ADDR(port); +} + +unsigned char adx_inb_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); + + delay(); + return v; +} + +unsigned short adx_inw_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); + + delay(); + return v; +} + +unsigned int adx_inl_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); + + delay(); + return v; +} + +void adx_insb(unsigned long port, void *buffer, unsigned long count) +{ + unsigned char *buf = buffer; + while(count--) *buf++ = inb(port); +} + +void adx_insw(unsigned long port, void *buffer, unsigned long count) +{ + unsigned short *buf = buffer; + while(count--) *buf++ = inw(port); +} + +void adx_insl(unsigned long port, void *buffer, unsigned long count) +{ + unsigned long *buf = buffer; + while(count--) *buf++ = inl(port); +} + +void adx_outb(unsigned char b, unsigned long port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; +} + +void adx_outw(unsigned short b, unsigned long port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; +} + +void adx_outl(unsigned int b, unsigned long port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; +} + +void adx_outb_p(unsigned char b, unsigned long port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; + delay(); +} + +void adx_outw_p(unsigned short b, unsigned long port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; + delay(); +} + +void adx_outl_p(unsigned int b, unsigned long port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; + delay(); +} + +void adx_outsb(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned char *buf = buffer; + while(count--) outb(*buf++, port); +} + +void adx_outsw(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned short *buf = buffer; + while(count--) outw(*buf++, port); +} + +void adx_outsl(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned long *buf = buffer; + while(count--) outl(*buf++, port); +} + +unsigned char adx_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned short adx_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned int adx_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void adx_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void adx_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void adx_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + +void *adx_ioremap(unsigned long offset, unsigned long size) +{ + return (void *)P2SEGADDR(offset); +} + +EXPORT_SYMBOL (adx_ioremap); + +void adx_iounmap(void *addr) +{ +} + +EXPORT_SYMBOL(adx_iounmap); + +#include +extern void *cf_io_base; + +unsigned long adx_isa_port2addr(unsigned long offset) +{ + /* CompactFlash (IDE) */ + if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) { + return (unsigned long)cf_io_base + offset; + } + + /* eth0 */ + if ((offset >= 0x300) && (offset <= 0x30f)) { + return 0xa5000000 + offset; /* COMM BOARD (AREA1) */ + } + + return offset + 0xb0000000; /* IOBUS (AREA 4)*/ +} diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c --- v2.4.9/linux/arch/sh/kernel/irq.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/irq.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.12 2000/03/06 14:07:50 gniibe Exp $ +/* $Id: irq.c,v 1.21 2001/07/17 02:26:53 gniibe Exp $ * * linux/arch/sh/kernel/irq.c * @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -399,7 +398,7 @@ spin_lock_irq(&desc->lock); if (!desc->action) - desc->handler->startup(i); + desc->handler->startup(i); spin_unlock_irq(&desc->lock); } @@ -452,7 +451,6 @@ } spin_unlock_irq(&desc->lock); } - spin_unlock_irq(&desc->lock); return val; } @@ -536,7 +534,7 @@ if (!shared) { desc->depth = 0; - desc->status &= ~IRQ_DISABLED; + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); desc->handler->startup(irq); } spin_unlock_irqrestore(&desc->lock,flags); diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/irq_imask.c linux/arch/sh/kernel/irq_imask.c --- v2.4.9/linux/arch/sh/kernel/irq_imask.c Sun Jan 28 18:56:00 2001 +++ linux/arch/sh/kernel/irq_imask.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: irq_imask.c,v 1.6 2000/03/06 14:11:32 gniibe Exp $ +/* $Id: irq_imask.c,v 1.13 2001/07/12 08:13:56 gniibe Exp $ * * linux/arch/sh/kernel/irq_imask.c * @@ -99,7 +99,8 @@ static void end_imask_irq(unsigned int irq) { - enable_imask_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_imask_irq(irq); } static void shutdown_imask_irq(unsigned int irq) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/irq_intc2.c linux/arch/sh/kernel/irq_intc2.c --- v2.4.9/linux/arch/sh/kernel/irq_intc2.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/irq_intc2.c Sat Sep 8 12:29:09 2001 @@ -92,7 +92,8 @@ static void end_intc2_irq(unsigned int irq) { - enable_intc2_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_intc2_irq(irq); } void make_intc2_irq(unsigned int irq, unsigned int addr, diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/irq_ipr.c linux/arch/sh/kernel/irq_ipr.c --- v2.4.9/linux/arch/sh/kernel/irq_ipr.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/irq_ipr.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: irq_ipr.c,v 1.6 2000/05/14 08:41:25 gniibe Exp $ +/* $Id: irq_ipr.c,v 1.20 2001/07/15 23:26:56 gniibe Exp $ * * linux/arch/sh/kernel/irq_ipr.c * @@ -102,7 +102,8 @@ static void end_ipr_irq(unsigned int irq) { - enable_ipr_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_ipr_irq(irq); } void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) @@ -176,7 +177,8 @@ static void end_pint_irq(unsigned int irq) { - enable_pint_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_pint_irq(irq); } void make_pint_irq(unsigned int irq) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/irq_maskreg.c linux/arch/sh/kernel/irq_maskreg.c --- v2.4.9/linux/arch/sh/kernel/irq_maskreg.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/irq_maskreg.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,107 @@ +/* + * linux/arch/sh/kernel/irq_maskreg.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * This file may be copied or modified under the terms of the GNU + * General Public License. See linux/COPYING for more information. + * + * Interrupt handling for Simple external interrupt mask register + * + * This is for the machine which have single 16 bit register + * for masking external IRQ individually. + * Each bit of the register is for masking each interrupt. + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* address of external interrupt mask register + * address must be set prior to use these (maybe in init_XXX_irq()) + * XXX : is it better to use .config than specifying it in code? */ +unsigned short *irq_mask_register = 0; + +/* forward declaration */ +static unsigned int startup_maskreg_irq(unsigned int irq); +static void shutdown_maskreg_irq(unsigned int irq); +static void enable_maskreg_irq(unsigned int irq); +static void disable_maskreg_irq(unsigned int irq); +static void mask_and_ack_maskreg(unsigned int); +static void end_maskreg_irq(unsigned int irq); + +/* hw_interrupt_type */ +static struct hw_interrupt_type maskreg_irq_type = { + " Mask Register", + startup_maskreg_irq, + shutdown_maskreg_irq, + enable_maskreg_irq, + disable_maskreg_irq, + mask_and_ack_maskreg, + end_maskreg_irq +}; + +/* actual implementatin */ +static unsigned int startup_maskreg_irq(unsigned int irq) +{ + enable_maskreg_irq(irq); + return 0; /* never anything pending */ +} + +static void shutdown_maskreg_irq(unsigned int irq) +{ + disable_maskreg_irq(irq); +} + +static void disable_maskreg_irq(unsigned int irq) +{ + if (irq_mask_register) { + unsigned long flags; + unsigned short val, mask = 0x01 << irq; + + /* Set "irq"th bit */ + save_and_cli(flags); + val = ctrl_inw((unsigned long)irq_mask_register); + val |= mask; + ctrl_outw(val, (unsigned long)irq_mask_register); + restore_flags(flags); + } +} + +static void enable_maskreg_irq(unsigned int irq) +{ + if (irq_mask_register) { + unsigned long flags; + unsigned short val, mask = ~(0x01 << irq); + + /* Clear "irq"th bit */ + save_and_cli(flags); + val = ctrl_inw((unsigned long)irq_mask_register); + val &= mask; + ctrl_outw(val, (unsigned long)irq_mask_register); + restore_flags(flags); + } +} + +static void mask_and_ack_maskreg(unsigned int irq) +{ + disable_maskreg_irq(irq); +} + +static void end_maskreg_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_maskreg_irq(irq); +} + +void make_maskreg_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &maskreg_irq_type; + disable_maskreg_irq(irq); +} diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/led_7751se.c linux/arch/sh/kernel/led_7751se.c --- v2.4.9/linux/arch/sh/kernel/led_7751se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/led_7751se.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,68 @@ +/* + * linux/arch/sh/kernel/led_se.c + * + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Solution Engine specific LED code. + */ + +#include +#include + +static void mach_led(int position, int value) +{ + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + + if (value) { + *p |= (1<<8); + } else { + *p &= ~(1<<8); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* Cycle the LED's in the clasic Knightrider/Sun pattern */ +void heartbeat_7751se(void) +{ + static unsigned int cnt = 0, period = 0; + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + static unsigned bit = 0, up = 1; + + cnt += 1; + if (cnt < period) { + return; + } + + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300< +#include static void mach_led(int position, int value) { - volatile unsigned short* p = (volatile unsigned short*)0xb0c00000; + volatile unsigned short* p = (volatile unsigned short*)PA_LED; if (value) { *p |= (1<<8); @@ -30,7 +31,7 @@ void heartbeat_se(void) { static unsigned int cnt = 0, period = 0; - volatile unsigned short* p = (volatile unsigned short*)0xb0c00000; + volatile unsigned short* p = (volatile unsigned short*)PA_LED; static unsigned bit = 0, up = 1; cnt += 1; diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/mach_7751se.c linux/arch/sh/kernel/mach_7751se.c --- v2.4.9/linux/arch/sh/kernel/mach_7751se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/mach_7751se.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,78 @@ +/* + * linux/arch/sh/kernel/mach_7751se.c + * + * Minor tweak of mach_se.c file to reference 7751se-specific items. + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the Hitachi 7751 SolutionEngine + */ + +#include +#include + +#include +#include +#include + +#include + +void heartbeat_7751se(void); +void setup_7751se(void); +void init_7751se_IRQ(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_7751se __initmv = { + mv_name: "7751 SolutionEngine", + + mv_nr_irqs: 72, + + mv_inb: sh7751se_inb, + mv_inw: sh7751se_inw, + mv_inl: sh7751se_inl, + mv_outb: sh7751se_outb, + mv_outw: sh7751se_outw, + mv_outl: sh7751se_outl, + + mv_inb_p: sh7751se_inb_p, + mv_inw_p: sh7751se_inw, + mv_inl_p: sh7751se_inl, + mv_outb_p: sh7751se_outb_p, + mv_outw_p: sh7751se_outw, + mv_outl_p: sh7751se_outl, + + mv_insb: sh7751se_insb, + mv_insw: sh7751se_insw, + mv_insl: sh7751se_insl, + mv_outsb: sh7751se_outsb, + mv_outsw: sh7751se_outsw, + mv_outsl: sh7751se_outsl, + + mv_readb: sh7751se_readb, + mv_readw: sh7751se_readw, + mv_readl: sh7751se_readl, + mv_writeb: sh7751se_writeb, + mv_writew: sh7751se_writew, + mv_writel: sh7751se_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: sh7751se_isa_port2addr, + + mv_init_arch: setup_7751se, + mv_init_irq: init_7751se_IRQ, +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_7751se, +#endif + + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, + + mv_hw_7751se: 1, +}; +ALIAS_MV(7751se) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/mach_adx.c linux/arch/sh/kernel/mach_adx.c --- v2.4.9/linux/arch/sh/kernel/mach_adx.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/mach_adx.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,73 @@ +/* + * linux/arch/sh/kernel/mach_adx.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * This file may be copied or modified under the terms of the GNU + * General Public License. See linux/COPYING for more information. + * + * Machine vector for the A&D ADX Board + */ + +#include +#include + +#include +#include +#include +#include + +extern void setup_adx(void); +extern void init_adx_IRQ(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_adx __initmv = { + mv_name: "A&D_ADX", + + mv_nr_irqs: 48, + + mv_inb: adx_inb, + mv_inw: adx_inw, + mv_inl: adx_inl, + mv_outb: adx_outb, + mv_outw: adx_outw, + mv_outl: adx_outl, + + mv_inb_p: adx_inb_p, + mv_inw_p: adx_inw, + mv_inl_p: adx_inl, + mv_outb_p: adx_outb_p, + mv_outw_p: adx_outw, + mv_outl_p: adx_outl, + + mv_insb: adx_insb, + mv_insw: adx_insw, + mv_insl: adx_insl, + mv_outsb: adx_outsb, + mv_outsw: adx_outsw, + mv_outsl: adx_outsl, + + mv_readb: adx_readb, + mv_readw: adx_readw, + mv_readl: adx_readl, + mv_writeb: adx_writeb, + mv_writew: adx_writew, + mv_writel: adx_writel, + + mv_ioremap: adx_ioremap, + mv_iounmap: adx_iounmap, + + mv_isa_port2addr: adx_isa_port2addr, + + mv_init_arch: setup_adx, + mv_init_irq: init_adx_IRQ, + + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, + + mv_hw_adx: 1, +}; +ALIAS_MV(adx) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/mach_dc.c linux/arch/sh/kernel/mach_dc.c --- v2.4.9/linux/arch/sh/kernel/mach_dc.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/mach_dc.c Sat Sep 8 12:29:09 2001 @@ -1,10 +1,11 @@ /* - * $Id: mach_dc.c,v 1.4 2001/05/24 05:09:16 mrbrown Exp $ + * $Id: mach_dc.c,v 1.5 2001/09/01 14:34:31 mrbrown Exp $ * SEGA Dreamcast machine vector */ #include #include +#include #include #include @@ -16,6 +17,10 @@ void __init setup_dreamcast(void); void __init dreamcast_pcibios_init(void); +/* Custom Dreamcast RTC routines */ +void aica_rtc_gettimeofday(struct timeval *tv); +int aica_rtc_settimeofday(const struct timeval *tv); + /* * The Machine Vector */ @@ -59,6 +64,9 @@ mv_init_arch: setup_dreamcast, mv_isa_port2addr: dreamcast_isa_port2addr, mv_irq_demux: systemasic_irq_demux, + + mv_rtc_gettimeofday: aica_rtc_gettimeofday, + mv_rtc_settimeofday: aica_rtc_settimeofday, mv_hw_dreamcast: 1, }; diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/mach_hp600.c linux/arch/sh/kernel/mach_hp600.c --- v2.4.9/linux/arch/sh/kernel/mach_hp600.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/mach_hp600.c Sat Sep 8 12:29:09 2001 @@ -15,8 +15,8 @@ #include #include -#include -#include +#include +#include #include /* @@ -26,7 +26,7 @@ struct sh_machine_vector mv_hp620 __initmv = { mv_name: "hp620", - mv_nr_irqs: 80, /* HD64461_IRQBASE+16, see hd64461.h */ + mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, mv_inb: hd64461_inb, mv_inw: hd64461_inw, @@ -71,7 +71,7 @@ struct sh_machine_vector mv_hp680 __initmv = { mv_name: "hp680", - mv_nr_irqs: 80, /* HD64461_IRQBASE+16, see hd64461.h */ + mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, mv_inb: hd64461_inb, mv_inw: hd64461_inw, @@ -116,7 +116,7 @@ struct sh_machine_vector mv_hp690 __initmv = { mv_name: "hp690", - mv_nr_irqs: 80, /* HD64461_IRQBASE+16, see hd64461.h */ + mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, mv_inb: hd64461_inb, mv_inw: hd64461_inw, diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/pci-7751se.c linux/arch/sh/kernel/pci-7751se.c --- v2.4.9/linux/arch/sh/kernel/pci-7751se.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/pci-7751se.c Sat Sep 8 12:29:09 2001 @@ -41,13 +41,13 @@ unsigned long bcr1, wcr1, wcr2, wcr3, mcr; unsigned short bcr2; - // - // Initialize the slave bus controller on the pcic. The values used - // here should not be hardcoded, but they should be taken from the bsc - // on the processor, to make this function as generic as possible. - // (i.e. Another sbc may usr different SDRAM timing settings -- in order - // for the pcic to work, its settings need to be exactly the same.) - // + /* + * Initialize the slave bus controller on the pcic. The values used + * here should not be hardcoded, but they should be taken from the bsc + * on the processor, to make this function as generic as possible. + * (i.e. Another sbc may usr different SDRAM timing settings -- in order + * for the pcic to work, its settings need to be exactly the same.) + */ bcr1 = (*(volatile unsigned long*)(SH7751_BCR1)); bcr2 = (*(volatile unsigned short*)(SH7751_BCR2)); wcr1 = (*(volatile unsigned long*)(SH7751_WCR1)); @@ -67,21 +67,47 @@ mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */ + + /* Enable all interrupts, so we know what to fix */ PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff); - PCIC_WRITE(SH7751_PCIAINTM, 0x0000980f); - PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* FB9000C7 */ - PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */ - PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O */ - PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM0 old val: 0xb0000000 */ - PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM1 */ - PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Sub system ID & Sub system vendor ID */ - PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* PCI MEM0 */ - PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* PCI MEM1 */ - PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM0 */ - PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM1 */ + PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f); + + /* Set up standard PCI config registers */ + PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */ + PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */ + PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */ + PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */ + PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */ + PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */ + PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */ + PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */ + PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */ + PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */ + /* Now turn it on... */ PCIC_WRITE(SH7751_PCICR, 0xa5000001); + /* + * Set PCIMBR and PCIIOBR here, assuming a single window + * (16M MEM, 256K IO) is enough. If a larger space is + * needed, the readx/writex and inx/outx functions will + * have to do more (e.g. setting registers for each call). + */ + + /* + * Set the MBR so PCI address is one-to-one with window, + * meaning all calls go straight through... use ifdef to + * catch erroneous assumption. + */ +#if PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE +#error One-to-one assumption for PCI memory mapping is wrong!?!?!? +#endif + PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM); + + /* Set IOBR for window containing area specified in pci.h */ + PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK)); + + /* All done, may as well say so... */ printk("SH7751 PCI: Finished initialization of the PCI controller\n"); return 1; diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/pci-dc.c linux/arch/sh/kernel/pci-dc.c --- v2.4.9/linux/arch/sh/kernel/pci-dc.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/pci-dc.c Sat Sep 8 12:29:09 2001 @@ -1,5 +1,5 @@ /* - $ $Id: pci-dc.c,v 1.2 2001/05/24 05:09:16 mrbrown Exp $ + $ $Id: pci-dc.c,v 1.5 2001/08/24 12:38:19 dwmw2 Exp $ * Dreamcast PCI: Supports SEGA Broadband Adaptor only. */ @@ -104,62 +104,6 @@ }; -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size) -{ -} - - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ -} - - -void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ -} - - -void pcibios_set_master(struct pci_dev *dev) -{ - /* No special bus mastering setup handling */ -} - - -int pcibios_enable_device(struct pci_dev *dev) -{ - - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { - r = dev->resource + idx; - if (!r->start && r->end) { - printk(KERN_ERR - "PCI: Device %s not available because" - " of resource collisions\n", - dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - printk("PCI: enabling device %s (%04x -> %04x)\n", - dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; - -} - - void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t * dma_handle) { @@ -172,7 +116,7 @@ gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); - printk("pci_alloc_consistent: %ld bytes at 0x%p\n", size, buf); + printk("pci_alloc_consistent: %ld bytes at 0x%lx\n", (long)size, buf); *dma_handle = (dma_addr_t)buf; @@ -184,6 +128,7 @@ void *vaddr, dma_addr_t dma_handle) { /* XXX */ + gapspci_dma_used = 0; } diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/pci-dma.c linux/arch/sh/kernel/pci-dma.c --- v2.4.9/linux/arch/sh/kernel/pci-dma.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/pci-dma.c Sat Sep 8 12:29:09 2001 @@ -29,7 +29,7 @@ *dma_handle = virt_to_bus(ret); } /* We must flush the cache before we pass it on to the device */ - flush_cache_all(); + dma_cache_wback_inv(ret, size); return P2SEGADDR(ret); } diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/pci-sh7751.c linux/arch/sh/kernel/pci-sh7751.c --- v2.4.9/linux/arch/sh/kernel/pci-sh7751.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/pci-sh7751.c Sat Sep 8 12:29:09 2001 @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -57,10 +56,10 @@ /* PCIPDR may only be accessed as 32 bit words, * so we must do byte alignment by hand */ - __save_and_cli(flags); + save_and_cli(flags); outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); word = inl(PCI_REG(SH7751_PCIPDR)); - __restore_flags(flags); + restore_flags(flags); switch (where & 0x3) { case 3: *value = (u8)(word >> 24); @@ -88,10 +87,10 @@ /* PCIPDR may only be accessed as 32 bit words, * so we must do word alignment by hand */ - __save_and_cli(flags); + save_and_cli(flags); outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); word = inl(PCI_REG(SH7751_PCIPDR)); - __restore_flags(flags); + restore_flags(flags); switch (where & 0x3) { case 3: // This should never happen... @@ -116,10 +115,10 @@ { unsigned long flags; - __save_and_cli(flags); + save_and_cli(flags); outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); *value = inl(PCI_REG(SH7751_PCIPDR)); - __restore_flags(flags); + restore_flags(flags); PCIDBG(4,"pci_conf1_read_config_dword@0x%08x=0x%x\n", CONFIG_CMD(dev,where),*value); return PCIBIOS_SUCCESSFUL; @@ -135,14 +134,14 @@ /* Since SH7751 only does 32bit access we'll have to do a * read,mask,write operation */ - __save_and_cli(flags); + save_and_cli(flags); outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); word = inl(PCI_REG(SH7751_PCIPDR)) ; word &= ~mask; word |= value << shift; outl(word, PCI_REG(SH7751_PCIPDR)); - __restore_flags(flags); + restore_flags(flags); PCIDBG(4,"pci_conf1_write_config_byte@0x%08x=0x%x\n", CONFIG_CMD(dev,where),word); return PCIBIOS_SUCCESSFUL; @@ -161,14 +160,14 @@ */ if (shift == 24) return PCIBIOS_BAD_REGISTER_NUMBER; - __save_and_cli(flags); + save_and_cli(flags); outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); word = inl(PCI_REG(SH7751_PCIPDR)) ; word &= ~mask; word |= value << shift; outl(value, PCI_REG(SH7751_PCIPDR)); - __restore_flags(flags); + restore_flags(flags); PCIDBG(4,"pci_conf1_write_config_word@0x%08x=0x%x\n", CONFIG_CMD(dev,where),word); return PCIBIOS_SUCCESSFUL; @@ -178,10 +177,10 @@ { unsigned long flags; - __save_and_cli(flags); + save_and_cli(flags); outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); outl(value, PCI_REG(SH7751_PCIPDR)); - __restore_flags(flags); + restore_flags(flags); PCIDBG(4,"pci_conf1_write_config_dword@0x%08x=0x%x\n", CONFIG_CMD(dev,where),value); return PCIBIOS_SUCCESSFUL; @@ -233,7 +232,7 @@ * BIOS32 and PCI BIOS handling. * * The BIOS version of the pci functions is not yet implemented but it is left - * in for completeness. Currently an error will be genereated at compile time. + * in for completeness. Currently an error will be generated at compile time. */ #ifdef CONFIG_PCI_BIOS @@ -417,54 +416,6 @@ return str; } -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - */ -void -pcibios_align_resource(void *data, struct resource *res, unsigned long size) -{ - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} - - /* * Allocate the bridge and device resources */ @@ -593,53 +544,6 @@ pcibios_assign_resources(); } -int pcibios_enable_device(struct pci_dev *dev) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", dev->name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -/* - * If we set up a device for bus mastering, we need to check and set - * the latency timer as it may not be properly set. - */ -unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", dev->name, lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} /***************************************************************************************/ /* @@ -665,10 +569,4 @@ PCIDBG(2,"Setting IRQ for slot %s to %d\n", dev->slot_name, irq); return irq; -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - PCIDBG(3,"PCI: Update IRQ for %s on irq %d\n", dev->name, irq); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/pci_st40.c linux/arch/sh/kernel/pci_st40.c --- v2.4.9/linux/arch/sh/kernel/pci_st40.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/pci_st40.c Sat Sep 8 12:29:09 2001 @@ -458,91 +458,6 @@ } -int pcibios_enable_device(struct pci_dev *dev) -{ - - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { - r = dev->resource + idx; - if (!r->start && r->end) { - printk(KERN_ERR - "PCI: Device %s not available because" - " of resource collisions\n", - dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - printk("PCI: enabling device %s (%04x -> %04x)\n", - dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; - -} - void __init pcibios_fixup_bus(struct pci_bus *bus) { -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size) -{ -} - -void __init pcibios_update_resource(struct pci_dev *dev, - struct resource *root, - struct resource *res, int resource) -{ - - unsigned long where, size; - u32 reg; - - printk("PCI: Assigning %3s %08lx to %s\n", - res->flags & IORESOURCE_IO ? "IO" : "MEM", - res->start, dev->name); - - where = PCI_BASE_ADDRESS_0 + resource * 4; - size = res->end - res->start; - - pci_read_config_dword(dev, where, ®); - reg = (reg & size) | (((u32) (res->start - root->start)) & ~size); - pci_write_config_dword(dev, where, reg); - -} - - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} - -/* - * If we set up a device for bus mastering, we need to check the latency - * timer as certain crappy BIOSes forget to set it properly. - */ -unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/pcibios.c linux/arch/sh/kernel/pcibios.c --- v2.4.9/linux/arch/sh/kernel/pcibios.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/pcibios.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,126 @@ +/* + * $Id: pcibios.c,v 1.1 2001/08/24 12:38:19 dwmw2 Exp $ + * + * arch/sh/kernel/pcibios.c + * + * This is GPL'd. + * + * Provided here are generic versions of: + * pcibios_update_resource() + * pcibios_align_resource() + * pcibios_enable_device() + * pcibios_set_master() + * pcibios_update_irq() + * + * These functions are collected here to reduce duplication of common + * code amongst the many platform-specific PCI support code files. + * + * Platform-specific files are expected to provide: + * pcibios_fixup_bus() + * pcibios_init() + * pcibios_setup() + * pcibios_fixup_pbus_ranges() + */ + +#include +#include +#include + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + u32 new, check; + int reg; + + new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + if (resource < 6) { + reg = PCI_BASE_ADDRESS_0 + 4*resource; + } else if (resource == PCI_ROM_RESOURCE) { + res->flags |= PCI_ROM_ADDRESS_ENABLE; + new |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else { + /* Somebody might have asked allocation of a non-standard resource */ + return; + } + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { + printk(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resource, + new, check); + } +} + +/* + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + */ +void pcibios_align_resource(void *data, struct resource *res, unsigned long size) +{ + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } + } +} + +int pcibios_enable_device(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for(idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", dev->name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +/* + * If we set up a device for bus mastering, we need to check and set + * the latency timer as it may not be properly set. + */ +unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", dev->name, lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c --- v2.4.9/linux/arch/sh/kernel/process.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/process.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.33 2000/03/25 00:06:15 gniibe Exp $ +/* $Id: process.c,v 1.34 2001/07/30 12:42:11 gniibe Exp $ * * linux/arch/sh/kernel/process.c * @@ -11,40 +11,13 @@ * This file handles the architecture-dependent parts of process handling.. */ -#define __KERNEL_SYSCALLS__ -#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 -#ifdef CONFIG_SH_STANDARD_BIOS -#include -#endif static int hlt_counter=0; @@ -71,11 +44,17 @@ current->counter = -100; while (1) { - while (!current->need_resched) { - if (hlt_counter) - continue; + if (hlt_counter) { + if (current->need_resched) + break; + } else { + __cli(); + while (!current->need_resched) { + __sti(); + asm volatile("sleep" : : : "memory"); + __cli(); + } __sti(); - asm volatile("sleep" : : : "memory"); } schedule(); check_pgt_cache(); @@ -84,16 +63,15 @@ void machine_restart(char * __unused) { -#ifdef CONFIG_SH_STANDARD_BIOS - sh_bios_shutdown(1); -#endif + /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ + asm volatile("ldc %0, sr\n\t" + "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); } void machine_halt(void) { -#ifdef CONFIG_SH_STANDARD_BIOS - sh_bios_shutdown(0); -#endif + while (1) + asm volatile("sleep" : : : "memory"); } void machine_power_off(void) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/ptrace.c linux/arch/sh/kernel/ptrace.c --- v2.4.9/linux/arch/sh/kernel/ptrace.c Wed Jul 25 17:10:19 2001 +++ linux/arch/sh/kernel/ptrace.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: ptrace.c,v 1.6 2000/06/08 23:44:50 gniibe Exp $ +/* $Id: ptrace.c,v 1.12 2001/07/23 00:00:56 gniibe Exp $ * * linux/arch/sh/kernel/ptrace.c * @@ -122,24 +122,29 @@ { ctrl_outl(nextpc1, UBC_BARA); ctrl_outb(asid, UBC_BASRA); -#if defined(CONFIG_CPU_SUBTYPE_SH7709) - ctrl_outl(0x0fff, UBC_BAMRA); -#else - ctrl_outb(BAMR_12, UBC_BAMRA); -#endif - ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA); + if(UBC_TYPE_SH7729){ + ctrl_outl(0x0fff, UBC_BAMRA); + ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA); + }else{ + ctrl_outb(BAMR_12, UBC_BAMRA); + ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA); + } if (nextpc2 != (unsigned long) -1) { ctrl_outl(nextpc2, UBC_BARB); ctrl_outb(asid, UBC_BASRB); -#if defined(CONFIG_CPU_SUBTYPE_SH7709) - ctrl_outl(0x0fff, UBC_BAMRA); -#else - ctrl_outb(BAMR_12, UBC_BAMRB); -#endif - ctrl_outw(BBR_INST | BBR_READ, UBC_BBRB); - } - ctrl_outw(BRCR_PCBA | BRCR_PCBB, UBC_BRCR); + if(UBC_TYPE_SH7729){ + ctrl_outl(0x0fff, UBC_BAMRB); + ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRB); + }else{ + ctrl_outb(BAMR_12, UBC_BAMRB); + ctrl_outw(BBR_INST | BBR_READ, UBC_BBRB); + } + } + if(UBC_TYPE_SH7729) + ctrl_outl(BRCR_PCBA | BRCR_PCBB | BRCR_PCTE, UBC_BRCR); + else + ctrl_outw(BRCR_PCBA | BRCR_PCBB, UBC_BRCR); } asmlinkage int sys_ptrace(long request, long pid, long addr, long data) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/rtc-aica.c linux/arch/sh/kernel/rtc-aica.c --- v2.4.9/linux/arch/sh/kernel/rtc-aica.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/rtc-aica.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,70 @@ +/* arch/sh/kernel/rtc-aica.c + * + * Dreamcast AICA RTC routines. + * + * Copyright (c) 2001 M. R. Brown + * + * Released under the terms of the GNU GPL v2.0. + * + */ + +#include + +#include + +/* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in + seconds to get the standard Unix Epoch when getting the time, and add 20 + years when setting the time. */ +#define TWENTY_YEARS ((20 * 365LU + 5) * 86400) + +/* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit + registers.*/ +#define AICA_RTC_SECS_H 0xa0710000 +#define AICA_RTC_SECS_L 0xa0710004 + +/** + * aica_rtc_gettimeofday - Get the time from the AICA RTC + * @tv: pointer to resulting timeval + * + * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch. + */ +void aica_rtc_gettimeofday(struct timeval *tv) { + unsigned long val1, val2; + + do { + val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + + val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + } while (val1 != val2); + + tv->tv_sec = val1 - TWENTY_YEARS; + + /* Can't get microseconds with just a seconds counter. */ + tv->tv_usec = 0; +} + +/** + * aica_rtc_settimeofday - Set the AICA RTC to the current time + * @tv: contains the timeval to set + * + * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter. + */ +int aica_rtc_settimeofday(const struct timeval *tv) { + unsigned long val1, val2; + unsigned long secs = tv->tv_sec + TWENTY_YEARS; + + do { + ctrl_outl((secs & 0xffff0000) >> 16, AICA_RTC_SECS_H); + ctrl_outl((secs & 0xffff), AICA_RTC_SECS_L); + + val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + + val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + } while (val1 != val2); + + return 0; +} diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c --- v2.4.9/linux/arch/sh/kernel/setup.c Tue Jul 3 17:08:18 2001 +++ linux/arch/sh/kernel/setup.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.20 2000/03/05 02:44:41 gniibe Exp $ +/* $Id: setup.c,v 1.31 2001/08/23 16:36:40 dwmw2 Exp $ * * linux/arch/sh/kernel/setup.c * @@ -38,7 +38,6 @@ #include #include #include -#include #include #ifdef CONFIG_SH_EARLY_PRINTK #include @@ -48,7 +47,12 @@ * Machine setup.. */ -struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 0, 0, }; +/* + * Initialize loops_per_jiffy as 10000000 (1000MIPS). + * This value will be used at the very early stage of serial setup. + * The bigger value means no problem. + */ +struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, }; struct screen_info screen_info; unsigned char aux_device_present = 0xaa; @@ -209,8 +213,7 @@ saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; - /* Default is 4Mbyte. */ - memory_end = (unsigned long)PAGE_OFFSET+0x00400000+__MEMORY_START; + memory_end = memory_start + __MEMORY_SIZE; for (;;) { /* @@ -268,7 +271,9 @@ void __init setup_arch(char **cmdline_p) { +#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN) extern struct sh_machine_vector mv_unknown; +#endif struct sh_machine_vector *mv = NULL; char mv_name[MV_NAME_SIZE] = ""; unsigned long mv_io_base = 0; @@ -356,6 +361,18 @@ #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) +#ifdef CONFIG_DISCONTIGMEM + NODE_DATA(0)->bdata = &discontig_node_bdata[0]; + NODE_DATA(1)->bdata = &discontig_node_bdata[1]; + + bootmap_size = init_bootmem_node(NODE_DATA(1), + PFN_UP(__MEMORY_START_2ND), + PFN_UP(__MEMORY_START_2ND), + PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND)); + free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND); + reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size); +#endif + /* * Find the highest page frame number we have available */ @@ -377,7 +394,7 @@ * is intact) must be done via bootmem_alloc(). */ bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, - __MEMORY_START>>PAGE_SHIFT, + __MEMORY_START>>PAGE_SHIFT, max_low_pfn); /* @@ -399,7 +416,8 @@ last_pfn = max_low_pfn; pages = last_pfn - curr_pfn; - free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); + free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn), + PFN_PHYS(pages)); } /* @@ -409,19 +427,19 @@ * case of us accidentally initializing the bootmem allocator with * an invalid RAM area. */ - reserve_bootmem(__MEMORY_START+PAGE_SIZE, (PFN_PHYS(start_pfn) + - bootmap_size + PAGE_SIZE-1) - __MEMORY_START); + reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE, + (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); /* * reserve physical page 0 - it's a special BIOS page on many boxes, * enabling clean reboots, SMP operation, laptop functions. */ - reserve_bootmem(__MEMORY_START, PAGE_SIZE); + reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE); #ifdef CONFIG_BLK_DEV_INITRD if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { - reserve_bootmem(INITRD_START+__MEMORY_START, INITRD_SIZE); + reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE); initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; initrd_end = initrd_start + INITRD_SIZE; diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup_7751se.c linux/arch/sh/kernel/setup_7751se.c --- v2.4.9/linux/arch/sh/kernel/setup_7751se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/setup_7751se.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,136 @@ +/* + * linux/arch/sh/kernel/setup_7751se.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + * Modified for 7751 Solution Engine by + * Ian da Silva and Jeremy Siegel, 2001. + */ + +#include +#include +#include + +#include +#include +#include +#include + +/* + * Configure the Super I/O chip + */ +#if 0 +/* Leftover code from regular Solution Engine, for reference. */ +/* The SH7751 Solution Engine has a different SuperIO. */ +static void __init smsc_config(int index, int data) +{ + outb_p(index, INDEX_PORT); + outb_p(data, DATA_PORT); +} + +static void __init init_smsc(void) +{ + outb_p(CONFIG_ENTER, CONFIG_PORT); + outb_p(CONFIG_ENTER, CONFIG_PORT); + + /* FDC */ + smsc_config(CURRENT_LDN_INDEX, LDN_FDC); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */ + + /* IDE1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_IDE1); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */ + + /* AUXIO (GPIO): to use IDE1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO); + smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */ + smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */ + + /* COM1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_COM1); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IO_BASE_HI_INDEX, 0x03); + smsc_config(IO_BASE_LO_INDEX, 0xf8); + smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */ + + /* COM2 */ + smsc_config(CURRENT_LDN_INDEX, LDN_COM2); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IO_BASE_HI_INDEX, 0x02); + smsc_config(IO_BASE_LO_INDEX, 0xf8); + smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */ + + /* RTC */ + smsc_config(CURRENT_LDN_INDEX, LDN_RTC); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */ + + /* XXX: PARPORT, KBD, and MOUSE will come here... */ + outb_p(CONFIG_EXIT, CONFIG_PORT); +} +#endif + +/* + * Initialize IRQ setting + */ +void __init init_7751se_IRQ(void) +{ + + /* Leave old Solution Engine code in for reference. */ +#if defined(CONFIG_SH_SOLUTION_ENGINE) + /* + * Super I/O (Just mimic PC): + * 1: keyboard + * 3: serial 0 + * 4: serial 1 + * 5: printer + * 6: floppy + * 8: rtc + * 12: mouse + * 14: ide0 + */ + make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); + make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); + make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); + make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6); + make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5); + make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4); + make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3); + make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1); + + make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ + + make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ + make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ + make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ + make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ + + /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ + /* NOTE: #2 and #13 are not used on PC */ + make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ + make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ + +#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE) + + make_ipr_irq(13, BCR_ILCRD, 3, 2); + + /* Add additional calls to make_ipr_irq() as drivers are added + * and tested. + */ +#endif + +} + + +/* + * Initialize the board + */ +void __init setup_7751se(void) +{ + /* Call init_smsc() replacement to set up SuperIO. */ + /* XXX: RTC setting comes here */ +} diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup_adx.c linux/arch/sh/kernel/setup_adx.c --- v2.4.9/linux/arch/sh/kernel/setup_adx.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/setup_adx.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,40 @@ +/* + * linux/arch/sh/kernel/setup_adx.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * I/O routine and setup routines for A&D ADX Board + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include +#include +#include +#include + +void setup_adx(void) +{ + /* nothing to do just yet */ +/* printk("setup_adx()\n");*/ +} + +void init_adx_IRQ(void) +{ + int i; + +/* printk("init_adx_IRQ()\n");*/ + /* setup irq_mask_register */ + irq_mask_register = (unsigned short *)0xa6000008; + + /* cover all external interrupt area by maskreg_irq_type + * (Actually, irq15 doesn't exist) + */ + for (i = 0; i < 16; i++) { + make_maskreg_irq(i); + disable_irq(i); + } +} diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup_bigsur.c linux/arch/sh/kernel/setup_bigsur.c --- v2.4.9/linux/arch/sh/kernel/setup_bigsur.c Tue Jul 3 17:08:19 2001 +++ linux/arch/sh/kernel/setup_bigsur.c Sat Sep 8 12:29:09 2001 @@ -181,10 +181,12 @@ static void end_bigsur_irq(unsigned int irq) { DPRINTK("end_bigsur_irq IRQ %d\n", irq); - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) - enable_bigsur_l1irq(irq); - else - enable_bigsur_l2irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) + enable_bigsur_l1irq(irq); + else + enable_bigsur_l2irq(irq); + } } static unsigned int startup_bigsur_irq(unsigned int irq) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup_cqreek.c linux/arch/sh/kernel/setup_cqreek.c --- v2.4.9/linux/arch/sh/kernel/setup_cqreek.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/setup_cqreek.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: setup_cqreek.c,v 1.6 2001/02/14 09:36:42 gniibe Exp $ +/* $Id: setup_cqreek.c,v 1.9 2001/07/30 12:43:28 gniibe Exp $ * * arch/sh/kernel/setup_cqreek.c * @@ -85,15 +85,16 @@ unsigned short stat_port = cqreek_irq_data[irq].stat_port; unsigned short bit = cqreek_irq_data[irq].bit; - inw(stat_port); disable_cqreek_irq(irq); /* Clear IRQ (it might be edge IRQ) */ + inw(stat_port); outw_p(bit, stat_port); } static void end_cqreek_irq(unsigned int irq) { - enable_cqreek_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_cqreek_irq(irq); } static unsigned int startup_cqreek_irq(unsigned int irq) @@ -156,16 +157,9 @@ */ void __init setup_cqreek(void) { - extern void disable_hlt(void); int i; /* udelay is not available at setup time yet... */ #define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0) - - /* - * XXX: I don't know the reason, but it becomes so fragile with - * "sleep", so we need to stop sleeping. - */ - disable_hlt(); if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */ outw_p(0, BRIDGE_IDE_INTR_LVL); diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup_dc.c linux/arch/sh/kernel/setup_dc.c --- v2.4.9/linux/arch/sh/kernel/setup_dc.c Tue Jul 3 17:08:19 2001 +++ linux/arch/sh/kernel/setup_dc.c Sat Sep 8 12:29:09 2001 @@ -8,8 +8,8 @@ * * Released under the terms of the GNU GPL v2.0. * - * This file originally bore the message: - * $Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp $ + * This file originally bore the message (with enclosed-$): + * Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp * SEGA Dreamcast support */ @@ -70,21 +70,29 @@ /* Disable the hardware event by masking its bit in its EMR */ static inline void disable_systemasic_irq(unsigned int irq) { + unsigned long flags; __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); __u32 mask; + + save_and_cli(flags); mask = inl(emr); mask &= ~(1 << EVENT_BIT(irq)); outl(mask, emr); + restore_flags(flags); } /* Enable the hardware event by setting its bit in its EMR */ static inline void enable_systemasic_irq(unsigned int irq) { + unsigned long flags; __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); __u32 mask; + + save_and_cli(flags); mask = inl(emr); mask |= (1 << EVENT_BIT(irq)); outl(mask, emr); + restore_flags(flags); } /* Acknowledge a hardware event by writing its bit back to its ESR */ @@ -98,7 +106,8 @@ /* After a IRQ has been ack'd and responded to, it needs to be renabled */ static void end_systemasic_irq(unsigned int irq) { - enable_systemasic_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_systemasic_irq(irq); } static unsigned int startup_systemasic_irq(unsigned int irq) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup_ec3104.c linux/arch/sh/kernel/setup_ec3104.c --- v2.4.9/linux/arch/sh/kernel/setup_ec3104.c Sun May 20 12:11:38 2001 +++ linux/arch/sh/kernel/setup_ec3104.c Sat Sep 8 12:29:09 2001 @@ -167,7 +167,8 @@ static void end_ec3104_irq(unsigned int irq) { - unmask_ec3104_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_ec3104_irq(irq); } static unsigned int startup_ec3104_irq(unsigned int irq) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup_hd64461.c linux/arch/sh/kernel/setup_hd64461.c --- v2.4.9/linux/arch/sh/kernel/setup_hd64461.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/setup_hd64461.c Sat Sep 8 12:29:09 2001 @@ -1,5 +1,5 @@ /* - * $Id: setup_hd64461.c,v 1.1 2000/06/10 21:45:18 yaegashi Exp $ + * $Id: setup_hd64461.c,v 1.9 2001/07/15 23:26:56 gniibe Exp $ * Copyright (C) 2000 YAEGASHI Takeshi * Hitachi HD64461 companion chip support */ @@ -57,7 +57,8 @@ static void end_hd64461_irq(unsigned int irq) { - enable_hd64461_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_hd64461_irq(irq); } diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/setup_hd64465.c linux/arch/sh/kernel/setup_hd64465.c --- v2.4.9/linux/arch/sh/kernel/setup_hd64465.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/setup_hd64465.c Sat Sep 8 12:29:09 2001 @@ -1,5 +1,5 @@ /* - * $Id: setup_hd64465.c,v 1.3 2001/02/07 17:52:53 stuart_menefy Exp $ + * $Id: setup_hd64465.c,v 1.4 2001/07/15 23:26:56 gniibe Exp $ * * Setup and IRQ handling code for the HD64465 companion chip. * by Greg Banks @@ -70,7 +70,8 @@ static void end_hd64465_irq(unsigned int irq) { - enable_hd64465_irq(irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_hd64465_irq(irq); } diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/sh_ksyms.c linux/arch/sh/kernel/sh_ksyms.c --- v2.4.9/linux/arch/sh/kernel/sh_ksyms.c Tue Jul 3 17:08:19 2001 +++ linux/arch/sh/kernel/sh_ksyms.c Sat Sep 8 12:29:09 2001 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include #include extern void dump_thread(struct pt_regs *, struct user *); diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/sys_sh.c linux/arch/sh/kernel/sys_sh.c --- v2.4.9/linux/arch/sh/kernel/sys_sh.c Mon Mar 19 12:35:10 2001 +++ linux/arch/sh/kernel/sys_sh.c Sat Sep 8 12:29:09 2001 @@ -43,6 +43,45 @@ return error; } +#if defined(__SH4__) +/* + * To avoid cache alias, we map the shard page with same color. + */ +#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1)) + +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct vm_area_struct *vma; + + if (flags & MAP_FIXED) { + /* We do not accept a shared mapping if it would violate + * cache aliasing constraints. + */ + if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1))) + return -EINVAL; + return addr; + } + + if (len > TASK_SIZE) + return -ENOMEM; + if (!addr) + addr = TASK_UNMAPPED_BASE; + + addr = COLOUR_ALIGN(addr); + + for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; + if (!vma || addr + len <= vma->vm_start) + return addr; + addr = vma->vm_end; + addr = COLOUR_ALIGN(addr); + } +} +#endif + static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, int fd, unsigned long pgoff) diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c --- v2.4.9/linux/arch/sh/kernel/time.c Tue Jul 3 17:08:19 2001 +++ linux/arch/sh/kernel/time.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.20 2000/02/28 12:42:51 gniibe Exp $ +/* $Id: time.c,v 1.30 2001/09/01 14:34:31 mrbrown Exp $ * * linux/arch/sh/kernel/time.c * @@ -183,10 +183,9 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { do_timer(regs); -#if 0 + if (!user_mode(regs)) sh_do_profile(regs->pc); -#endif #ifdef CONFIG_HEARTBEAT if (sh_mv.mv_heartbeat != NULL) @@ -360,17 +359,11 @@ #endif #endif - if (MACH_DREAMCAST) - xtime.tv_sec = xtime.tv_usec = 0; - else - rtc_gettimeofday(&xtime); + rtc_gettimeofday(&xtime); setup_irq(TIMER_IRQ, &irq0); - if (MACH_DREAMCAST) - timer_freq = 50*1000*1000/4; - else - timer_freq = get_timer_frequency(); + timer_freq = get_timer_frequency(); module_clock = timer_freq * 4; @@ -391,10 +384,9 @@ } #elif defined(__SH4__) { +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 unsigned long pvr; - frqcr = ctrl_inw(FRQCR); -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 /* This should probably be moved into the SH3 probing code, and then use the processor * structure to determine which CPU we are running on. */ @@ -435,6 +427,8 @@ } else #endif { + frqcr = ctrl_inw(FRQCR); + ifc = ifc_table[(frqcr>> 6) & 0x0007]; bfc = bfc_table[(frqcr>> 3) & 0x0007]; pfc = pfc_table[frqcr & 0x0007]; diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/traps.c linux/arch/sh/kernel/traps.c --- v2.4.9/linux/arch/sh/kernel/traps.c Mon Jan 29 16:19:41 2001 +++ linux/arch/sh/kernel/traps.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.5 2000/02/27 08:27:55 gniibe Exp $ +/* $Id: traps.c,v 1.14 2001/07/24 08:07:10 gniibe Exp $ * * linux/arch/sh/traps.c * @@ -314,10 +314,10 @@ /* shout about the first ten userspace fixups */ if (user_mode(regs) && handle_unaligned_notify_count>0) { - handle_unaligned_notify_count--; + handle_unaligned_notify_count--; - printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", - current->comm,current->pid,(u16*)regs->pc,instruction); + printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", + current->comm,current->pid,(u16*)regs->pc,instruction); } ret = -EFAULT; @@ -502,7 +502,7 @@ die_if_kernel("exception", ®s, ex); } -#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) +#if defined(CONFIG_SH_STANDARD_BIOS) void *gdb_vbr_vector; #endif @@ -514,7 +514,7 @@ exception_handling_table[12] = (void *)do_reserved_inst; exception_handling_table[13] = (void *)do_illegal_slot_inst; -#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) +#if defined(CONFIG_SH_STANDARD_BIOS) /* * Read the old value of the VBR register to initialise * the vector through which debug and BIOS traps are diff -u --recursive --new-file v2.4.9/linux/arch/sh/lib/Makefile linux/arch/sh/lib/Makefile --- v2.4.9/linux/arch/sh/lib/Makefile Fri Dec 29 14:07:20 2000 +++ linux/arch/sh/lib/Makefile Sat Sep 8 12:29:09 2001 @@ -4,7 +4,7 @@ L_TARGET = lib.a obj-y = delay.o memcpy.o memset.o memmove.o memchr.o old-checksum.o \ - checksum.o strcasecmp.o + checksum.o strcasecmp.o strlen.o USE_STANDARD_AS_RULE := true diff -u --recursive --new-file v2.4.9/linux/arch/sh/lib/checksum.S linux/arch/sh/lib/checksum.S --- v2.4.9/linux/arch/sh/lib/checksum.S Sun Jan 28 18:56:00 2001 +++ linux/arch/sh/lib/checksum.S Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: checksum.S,v 1.4 2000/05/14 08:41:26 gniibe Exp $ +/* $Id: checksum.S,v 1.10 2001/07/06 13:11:32 gniibe Exp $ * * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket @@ -54,13 +54,14 @@ tst #2, r0 ! Check alignment. bt 2f ! Jump if alignment is ok. ! - add #-2, r5 ! Alignment uses up two bytes. + add #-2, r5 ! Alignment uses up two bytes. cmp/pz r5 ! bt/s 1f ! Jump if we had at least two bytes. clrt bra 6f add #2, r5 ! r5 was < 2. Deal with it. 1: + mov r5, r1 ! Save new len for later use. mov.w @r4+, r0 extu.w r0, r0 addc r0, r6 @@ -90,7 +91,7 @@ addc r3, r6 addc r0, r6 addc r2, r6 - movt r0 + movt r0 dt r5 bf/s 3b cmp/eq #1, r0 @@ -185,48 +186,48 @@ mov.l r5,@-r15 mov.l r6,@-r15 - mov #3, r0 ! Check src and dest are equally aligned - mov r4, r1 - and r0, r1 - and r5, r0 - cmp/eq r1, r0 - bf 3f ! Different alignments, use slow version - tst #1,r0 ! Check dest word aligned - bf 3f ! If not, do it the slow way + mov #3,r0 ! Check src and dest are equally aligned + mov r4,r1 + and r0,r1 + and r5,r0 + cmp/eq r1,r0 + bf 3f ! Different alignments, use slow version + tst #1,r0 ! Check dest word aligned + bf 3f ! If not, do it the slow way mov #2,r0 - tst r0,r5 ! Check dest alignment. - bt 2f ! Jump if alignment is ok. - add #-2,r6 ! Alignment uses up two bytes. - cmp/pz r6 ! Jump if we had at least two bytes. + tst r0,r5 ! Check dest alignment. + bt 2f ! Jump if alignment is ok. + add #-2,r6 ! Alignment uses up two bytes. + cmp/pz r6 ! Jump if we had at least two bytes. bt/s 1f clrt bra 4f - add #2,r6 ! r6 was < 2. Deal with it. + add #2,r6 ! r6 was < 2. Deal with it. -3: ! Handle different src and dest alinments. +3: ! Handle different src and dest alignments. ! This is not common, so simple byte by byte copy will do. - mov r6, r2 + mov r6,r2 shlr r6 - tst r6, r6 + tst r6,r6 bt 4f clrt -5: -SRC( mov.b @r4+,r0 ) -DST( mov.b r0,@r5 ) - add #1, r5 -SRC( mov.b @r4+,r1 ) -DST( mov.b r1,@r5 ) - add #1,r5 - - extu.b r0,r0 + .align 2 +5: +SRC( mov.b @r4+,r1 ) +SRC( mov.b @r4+,r0 ) extu.b r1,r1 +DST( mov.b r1,@r5 ) +DST( mov.b r0,@(1,r5) ) + extu.b r0,r0 + add #2,r5 + #ifdef __LITTLE_ENDIAN__ - shll8 r1 -#else shll8 r0 +#else + shll8 r1 #endif - or r1,r0 + or r1,r0 addc r0,r7 movt r0 @@ -238,16 +239,16 @@ mov r2, r0 tst #1, r0 - bt 7f + bt 7f bra 5f clrt ! src and dest equally aligned, but to a two byte boundary. ! Handle first two bytes as a special case - .align 5 + .align 2 1: -SRC( mov.w @r4+,r0 ) -DST( mov.w r0,@r5 ) +SRC( mov.w @r4+,r0 ) +DST( mov.w r0,@r5 ) add #2,r5 extu.w r0,r0 addc r0,r7 @@ -260,42 +261,36 @@ tst r6,r6 bt/s 2f clrt + .align 2 1: -SRC( mov.l @r4+,r0 ) -SRC( mov.l @r4+,r1 ) +SRC( mov.l @r4+,r0 ) +SRC( mov.l @r4+,r1 ) addc r0,r7 -DST( mov.l r0,@r5 ) - add #4,r5 +DST( mov.l r0,@r5 ) +DST( mov.l r1,@(4,r5) ) addc r1,r7 -DST( mov.l r1,@r5 ) - add #4,r5 -SRC( mov.l @r4+,r0 ) -SRC( mov.l @r4+,r1 ) +SRC( mov.l @r4+,r0 ) +SRC( mov.l @r4+,r1 ) addc r0,r7 -DST( mov.l r0,@r5 ) - add #4,r5 +DST( mov.l r0,@(8,r5) ) +DST( mov.l r1,@(12,r5) ) addc r1,r7 -DST( mov.l r1,@r5 ) - add #4,r5 SRC( mov.l @r4+,r0 ) -SRC( mov.l @r4+,r1 ) +SRC( mov.l @r4+,r1 ) addc r0,r7 -DST( mov.l r0,@r5 ) - add #4,r5 +DST( mov.l r0,@(16,r5) ) +DST( mov.l r1,@(20,r5) ) addc r1,r7 -DST( mov.l r1,@r5 ) - add #4,r5 -SRC( mov.l @r4+,r0 ) -SRC( mov.l @r4+,r1 ) +SRC( mov.l @r4+,r0 ) +SRC( mov.l @r4+,r1 ) addc r0,r7 -DST( mov.l r0,@r5 ) - add #4,r5 +DST( mov.l r0,@(24,r5) ) +DST( mov.l r1,@(28,r5) ) addc r1,r7 -DST( mov.l r1,@r5 ) - add #4,r5 + add #32,r5 movt r0 dt r6 bf/s 1b diff -u --recursive --new-file v2.4.9/linux/arch/sh/lib/strlen.S linux/arch/sh/lib/strlen.S --- v2.4.9/linux/arch/sh/lib/strlen.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/lib/strlen.S Sat Sep 8 12:29:09 2001 @@ -0,0 +1,70 @@ +/* $Id: strlen.S,v 1.2 2001/06/29 14:07:15 gniibe Exp $ + * + * "strlen" implementation of SuperH + * + * Copyright (C) 1999 Kaz Kojima + * + */ + +/* size_t strlen (const char *s) */ + +#include +ENTRY(strlen) + mov r4,r0 + and #3,r0 + tst r0,r0 + bt/s 1f + mov #0,r2 + + add #-1,r0 + shll2 r0 + shll r0 + braf r0 + nop + + mov.b @r4+,r1 + tst r1,r1 + bt 8f + add #1,r2 + + mov.b @r4+,r1 + tst r1,r1 + bt 8f + add #1,r2 + + mov.b @r4+,r1 + tst r1,r1 + bt 8f + add #1,r2 + +1: + mov #0,r3 +2: + mov.l @r4+,r1 + cmp/str r3,r1 + bf/s 2b + add #4,r2 + + add #-4,r2 +#ifndef __LITTLE_ENDIAN__ + swap.b r1,r1 + swap.w r1,r1 + swap.b r1,r1 +#endif + extu.b r1,r0 + tst r0,r0 + bt/s 8f + shlr8 r1 + add #1,r2 + extu.b r1,r0 + tst r0,r0 + bt/s 8f + shlr8 r1 + add #1,r2 + extu.b r1,r0 + tst r0,r0 + bt 8f + add #1,r2 +8: + rts + mov r2,r0 diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/Makefile linux/arch/sh/mm/Makefile --- v2.4.9/linux/arch/sh/mm/Makefile Fri Dec 29 14:07:20 2000 +++ linux/arch/sh/mm/Makefile Sat Sep 8 12:29:09 2001 @@ -8,6 +8,11 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -obj-y := init.o fault.o extable.o cache.o # ioremap.o +obj-y := init.o fault.o extable.o clear_page.o copy_page.o + +obj-$(CONFIG_CPU_SH3) += cache-sh3.o +obj-$(CONFIG_CPU_SH4) += cache-sh4.o __clear_user_page-sh4.o __copy_user_page-sh4.o ioremap.o + +USE_STANDARD_AS_RULE := true include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/__clear_user_page-sh4.S linux/arch/sh/mm/__clear_user_page-sh4.S --- v2.4.9/linux/arch/sh/mm/__clear_user_page-sh4.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/mm/__clear_user_page-sh4.S Sat Sep 8 12:29:09 2001 @@ -0,0 +1,49 @@ +/* $Id$ + * + * __clear_user_page implementation of SuperH + * + * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima + * + */ + +/* + * __clear_user_page + * @to: P1 address (with same color) + * @orig_to: P1 address + * + * void __clear_user_page(void *to, void *orig_to) + */ + +/* + * r0 --- scratch + * r4 --- to + * r5 --- orig_to + * r6 --- to + 4096 + */ +#include +ENTRY(__clear_user_page) + mov r4,r6 + mov.w .L4096,r0 + add r0,r6 + mov #0,r0 + ! +1: ocbi @r5 + add #32,r5 + movca.l r0,@r4 + mov r4,r1 + add #32,r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + add #28,r4 + cmp/eq r6,r4 + bf/s 1b + ocbwb @r1 + ! + rts + nop +.L4096: .word 4096 diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/__copy_user_page-sh4.S linux/arch/sh/mm/__copy_user_page-sh4.S --- v2.4.9/linux/arch/sh/mm/__copy_user_page-sh4.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/mm/__copy_user_page-sh4.S Sat Sep 8 12:29:09 2001 @@ -0,0 +1,69 @@ +/* $Id: __copy_user_page-sh4.S,v 1.1 2001/07/23 09:02:17 gniibe Exp $ + * + * __copy_user_page implementation of SuperH + * + * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima + * + */ + +/* + * __copy_user_page + * @to: P1 address (with same color) + * @from: P1 address + * @orig_to: P1 address + * + * void __copy_user_page(void *to, void *from, void *orig_to) + */ + +/* + * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch + * r8 --- from + 4096 + * r9 --- orig_to + * r10 --- to + * r11 --- from + */ +#include +ENTRY(__copy_user_page) + mov.l r8,@-r15 + mov.l r9,@-r15 + mov.l r10,@-r15 + mov.l r11,@-r15 + mov r4,r10 + mov r5,r11 + mov r6,r9 + mov r5,r8 + mov.w .L4096,r0 + add r0,r8 + ! +1: ocbi @r9 + add #32,r9 + mov.l @r11+,r0 + mov.l @r11+,r1 + mov.l @r11+,r2 + mov.l @r11+,r3 + mov.l @r11+,r4 + mov.l @r11+,r5 + mov.l @r11+,r6 + mov.l @r11+,r7 + movca.l r0,@r10 + mov r10,r0 + add #32,r10 + mov.l r7,@-r10 + mov.l r6,@-r10 + mov.l r5,@-r10 + mov.l r4,@-r10 + mov.l r3,@-r10 + mov.l r2,@-r10 + mov.l r1,@-r10 + ocbwb @r0 + cmp/eq r11,r8 + bf/s 1b + add #28,r10 + ! + mov.l @r15+,r11 + mov.l @r15+,r10 + mov.l @r15+,r9 + mov.l @r15+,r8 + rts + nop +.L4096: .word 4096 diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/cache-sh3.c linux/arch/sh/mm/cache-sh3.c --- v2.4.9/linux/arch/sh/mm/cache-sh3.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/mm/cache-sh3.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,219 @@ +/* $Id: cache-sh3.c,v 1.5 2001/08/24 15:31:41 dwmw2 Exp $ + * + * linux/arch/sh/mm/cache-sh3.c + * + * Copyright (C) 1999, 2000 Niibe Yutaka + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CCR 0xffffffec /* Address of Cache Control Register */ +#define CCR_CACHE_VAL 0x00000005 /* 8k-byte cache, P1-wb, enable */ +#define CCR_CACHE_INIT 0x0000000d /* 8k-byte cache, CF, P1-wb, enable */ +#define CCR_CACHE_ENABLE 1 + +#define CACHE_OC_ADDRESS_ARRAY 0xf0000000 +#define CACHE_VALID 1 +#define CACHE_UPDATED 2 +#define CACHE_PHYSADDR_MASK 0x1ffffc00 + +/* 7709A/7729 has 16K cache (256-entry), while 7702 has only 2K(direct) + 7702 is not supported (yet) */ +struct _cache_system_info { + int way_shift; + int entry_mask; + int num_entries; +}; + +/* Data at BSS is cleared after setting this variable. + So, we Should not placed this variable at BSS section. + Initialize this, it is placed at data section. */ +static struct _cache_system_info cache_system_info = {0,}; + +#define CACHE_OC_WAY_SHIFT (cache_system_info.way_shift) +#define CACHE_OC_ENTRY_SHIFT 4 +#define CACHE_OC_ENTRY_MASK (cache_system_info.entry_mask) +#define CACHE_OC_NUM_ENTRIES (cache_system_info.num_entries) +#define CACHE_OC_NUM_WAYS 4 +#define CACHE_OC_ASSOC_BIT (1<<3) + + +/* + * Write back all the cache. + * + * For SH-4, we only need to flush (write back) Operand Cache, + * as Instruction Cache doesn't have "updated" data. + * + * Assumes that this is called in interrupt disabled context, and P2. + * Shuld be INLINE function. + */ +static inline void cache_wback_all(void) +{ + unsigned long addr, data, i, j; + + for (i=0; itype = CPU_SH7708; + } else { /* 7709A or 7729 */ + cache_system_info.way_shift = 12; + cache_system_info.entry_mask = 0xff0; + cache_system_info.num_entries = 256; + cpu_data->type = CPU_SH7729; + } +} + +void __init cache_init(void) +{ + unsigned long ccr; + + detect_cpu_and_cache_system(); + + jump_to_P2(); + ccr = ctrl_inl(CCR); + if (ccr & CCR_CACHE_ENABLE) + /* + * XXX: Should check RA here. + * If RA was 1, we only need to flush the half of the caches. + */ + cache_wback_all(); + + ctrl_outl(CCR_CACHE_INIT, CCR); + back_to_P1(); +} + +/* + * Write back the dirty D-caches, but not invalidate them. + * + * Is this really worth it, or should we just alias this routine + * to __flush_purge_region too? + * + * START: Virtual Address (U0, P1, or P3) + * SIZE: Size of the region. + */ + +void __flush_wback_region(void *start, int size) +{ + unsigned long v, j; + unsigned long begin, end; + unsigned long flags; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + for (j=0; j +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CCR 0xff00001c /* Address of Cache Control Register */ +#define CCR_CACHE_VAL 0x00000105 /* 8k+16k-byte cache,P1-wb,enable */ +#define CCR_CACHE_INIT 0x0000090d /* ICI,ICE(8k), OCI,P1-wb,OCE(16k) */ +#define CCR_CACHE_ENABLE 0x00000101 + +#define CACHE_IC_ADDRESS_ARRAY 0xf0000000 +#define CACHE_OC_ADDRESS_ARRAY 0xf4000000 +#define CACHE_VALID 1 +#define CACHE_UPDATED 2 + +#define CACHE_OC_WAY_SHIFT 13 +#define CACHE_IC_WAY_SHIFT 13 +#define CACHE_OC_ENTRY_SHIFT 5 +#define CACHE_IC_ENTRY_SHIFT 5 +#define CACHE_OC_ENTRY_MASK 0x3fe0 +#define CACHE_OC_ENTRY_PHYS_MASK 0x0fe0 +#define CACHE_IC_ENTRY_MASK 0x1fe0 +#define CACHE_IC_NUM_ENTRIES 256 +#define CACHE_OC_NUM_ENTRIES 512 + +static void __init +detect_cpu_and_cache_system(void) +{ +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 + cpu_data->type = CPU_ST40STB1; +#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) + cpu_data->type = CPU_SH7750; +#else +#error Unknown SH4 CPU type +#endif +} + +void __init cache_init(void) +{ + unsigned long ccr; + + detect_cpu_and_cache_system(); + + jump_to_P2(); + ccr = ctrl_inl(CCR); + if (ccr & CCR_CACHE_ENABLE) { + /* + * XXX: Should check RA here. + * If RA was 1, we only need to flush the half of the caches. + */ + unsigned long addr, data; + + for (addr = CACHE_OC_ADDRESS_ARRAY; + addr < (CACHE_OC_ADDRESS_ARRAY+ + (CACHE_OC_NUM_ENTRIES << CACHE_OC_ENTRY_SHIFT)); + addr += (1 << CACHE_OC_ENTRY_SHIFT)) { + data = ctrl_inl(addr); + if ((data & (CACHE_UPDATED|CACHE_VALID)) + == (CACHE_UPDATED|CACHE_VALID)) + ctrl_outl(data & ~CACHE_UPDATED, addr); + } + } + + ctrl_outl(CCR_CACHE_INIT, CCR); + back_to_P1(); +} + +/* + * SH-4 has virtually indexed and physically tagged cache. + */ + +static struct semaphore p3map_sem[4]; + +void __init p3_cache_init(void) +{ + /* In ioremap.c */ + extern int remap_area_pages(unsigned long address, + unsigned long phys_addr, + unsigned long size, unsigned long flags); + + if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE)) + panic("p3_cachie_init failed."); + sema_init (&p3map_sem[0], 1); + sema_init (&p3map_sem[1], 1); + sema_init (&p3map_sem[2], 1); + sema_init (&p3map_sem[3], 1); +} + +/* + * Write back the dirty D-caches, but not invalidate them. + * + * START: Virtual Address (U0, P1, or P3) + * SIZE: Size of the region. + */ +void __flush_wback_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + asm volatile("ocbwb %0" + : /* no output */ + : "m" (__m(v))); + } +} + +/* + * Write back the dirty D-caches and invalidate them. + * + * START: Virtual Address (U0, P1, or P3) + * SIZE: Size of the region. + */ +void __flush_purge_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + asm volatile("ocbp %0" + : /* no output */ + : "m" (__m(v))); + } +} + + +/* + * No write back please + */ +void __flush_invalidate_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + asm volatile("ocbi %0" + : /* no output */ + : "m" (__m(v))); + } +} + +/* + * Write back the range of D-cache, and purge the I-cache. + * + * Called from kernel/module.c:sys_init_module and routine for a.out format. + */ +void flush_icache_range(unsigned long start, unsigned long end) +{ + flush_cache_all(); +} + +/* + * Write back the D-cache and purge the I-cache for signal trampoline. + */ +void flush_cache_sigtramp(unsigned long addr) +{ + unsigned long v, index; + unsigned long flags; + + v = addr & ~(L1_CACHE_BYTES-1); + asm volatile("ocbwb %0" + : /* no output */ + : "m" (__m(v))); + + index = CACHE_IC_ADDRESS_ARRAY| (v&CACHE_IC_ENTRY_MASK); + save_and_cli(flags); + jump_to_P2(); + ctrl_outl(0, index); /* Clear out Valid-bit */ + back_to_P1(); + restore_flags(flags); +} + +/* + * Writeback&Invalidate the D-cache of the page + */ +static void __flush_dcache_page(unsigned long phys) +{ + unsigned long addr, data; + unsigned long flags; + + phys |= CACHE_VALID; + + save_and_cli(flags); + jump_to_P2(); + + /* Loop all the D-cache */ + for (addr = CACHE_OC_ADDRESS_ARRAY; + addr < (CACHE_OC_ADDRESS_ARRAY + +(CACHE_OC_NUM_ENTRIES<< CACHE_OC_ENTRY_SHIFT)); + addr += (1<flags)) + __flush_dcache_page(PHYSADDR(page_address(page))); +} + +void flush_cache_all(void) +{ + extern unsigned long empty_zero_page[1024]; + unsigned long flags; + unsigned long addr; + + save_and_cli(flags); + + /* Prefetch the data to write back D-cache */ + for (addr = (unsigned long)empty_zero_page; + addr < (unsigned long)empty_zero_page + 1024*16; + addr += L1_CACHE_BYTES) + asm volatile("pref @%0"::"r" (addr)); + + jump_to_P2(); + /* Flush D-cache/I-cache */ + ctrl_outl(CCR_CACHE_INIT, CCR); + back_to_P1(); + restore_flags(flags); +} + +void flush_cache_mm(struct mm_struct *mm) +{ + /* Is there any good way? */ + /* XXX: possibly call flush_cache_range for each vm area */ + flush_cache_all(); +} + +/* + * Write back and invalidate D-caches. + * + * START, END: Virtual Address (U0 address) + * + * NOTE: We need to flush the _physical_ page entry. + * Flushing the cache lines for U0 only isn't enough. + * We need to flush for P1 too, which may contain aliases. + */ +void flush_cache_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + /* + * We could call flush_cache_page for the pages of these range, + * but it's not efficient (scan the caches all the time...). + * + * We can't use A-bit magic, as there's the case we don't have + * valid entry on TLB. + */ + flush_cache_all(); +} + +/* + * Write back and invalidate I/D-caches for the page. + * + * ADDR: Virtual Address (U0 address) + */ +void flush_cache_page(struct vm_area_struct *vma, unsigned long address) +{ + pgd_t *dir; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + unsigned long phys, addr, data; + unsigned long flags; + + dir = pgd_offset(vma->vm_mm, address); + pmd = pmd_offset(dir, address); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + return; + pte = pte_offset(pmd, address); + entry = *pte; + if (pte_none(entry) || !pte_present(entry)) + return; + + phys = pte_val(entry)&PTE_PHYS_MASK; + + phys |= CACHE_VALID; + save_and_cli(flags); + jump_to_P2(); + + /* We only need to flush D-cache when we have alias */ + if ((address^phys) & CACHE_ALIAS) { + /* Loop 4K of the D-cache */ + for (addr = CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS); + addr < (CACHE_OC_ADDRESS_ARRAY + (address & CACHE_ALIAS) + +(CACHE_OC_NUM_ENTRIES/4<vm_flags & VM_EXEC) + /* Loop 4K of the I-cache */ + for (addr = CACHE_IC_ADDRESS_ARRAY|(address&0x1000); + addr < ((CACHE_IC_ADDRESS_ARRAY|(address&0x1000)) + +(CACHE_IC_NUM_ENTRIES/2<flags); + if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) + clear_page(to); + else { + pgprot_t pgprot = __pgprot(_PAGE_PRESENT | + _PAGE_RW | _PAGE_CACHABLE | + _PAGE_DIRTY | _PAGE_ACCESSED | + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD); + unsigned long phys_addr = PHYSADDR(to); + unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); + pgd_t *dir = pgd_offset_k(p3_addr); + pmd_t *pmd = pmd_offset(dir, p3_addr); + pte_t *pte = pte_offset(pmd, p3_addr); + pte_t entry; + unsigned long flags; + + entry = mk_pte_phys(phys_addr, pgprot); + down(&p3map_sem[(address & CACHE_ALIAS)>>12]); + set_pte(pte, entry); + save_and_cli(flags); + __flush_tlb_page(get_asid(), p3_addr); + restore_flags(flags); + update_mmu_cache(NULL, p3_addr, entry); + __clear_user_page((void *)p3_addr, to); + pte_clear(pte); + up(&p3map_sem[(address & CACHE_ALIAS)>>12]); + } +} + +/* + * copy_user_page + * @to: P1 address + * @from: P1 address + * @address: U0 address to be mapped + */ +void copy_user_page(void *to, void *from, unsigned long address) +{ + struct page *page = virt_to_page(to); + + __set_bit(PG_mapped, &page->flags); + if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) + copy_page(to, from); + else { + pgprot_t pgprot = __pgprot(_PAGE_PRESENT | + _PAGE_RW | _PAGE_CACHABLE | + _PAGE_DIRTY | _PAGE_ACCESSED | + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD); + unsigned long phys_addr = PHYSADDR(to); + unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); + pgd_t *dir = pgd_offset_k(p3_addr); + pmd_t *pmd = pmd_offset(dir, p3_addr); + pte_t *pte = pte_offset(pmd, p3_addr); + pte_t entry; + unsigned long flags; + + entry = mk_pte_phys(phys_addr, pgprot); + down(&p3map_sem[(address & CACHE_ALIAS)>>12]); + set_pte(pte, entry); + save_and_cli(flags); + __flush_tlb_page(get_asid(), p3_addr); + restore_flags(flags); + update_mmu_cache(NULL, p3_addr, entry); + __copy_user_page((void *)p3_addr, from, to); + pte_clear(pte); + up(&p3map_sem[(address & CACHE_ALIAS)>>12]); + } +} diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c --- v2.4.9/linux/arch/sh/mm/cache.c Tue Jul 3 17:08:19 2001 +++ linux/arch/sh/mm/cache.c Wed Dec 31 16:00:00 1969 @@ -1,524 +0,0 @@ -/* $Id: cache.c,v 1.10 2000/03/07 11:58:34 gniibe Exp $ - * - * linux/arch/sh/mm/cache.c - * - * Copyright (C) 1999, 2000 Niibe Yutaka - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__sh3__) -#define CCR 0xffffffec /* Address of Cache Control Register */ -#define CCR_CACHE_VAL 0x00000005 /* 8k-byte cache, P1-wb, enable */ -#define CCR_CACHE_INIT 0x0000000d /* 8k-byte cache, CF, P1-wb, enable */ -#define CCR_CACHE_ENABLE 1 - -#define CACHE_IC_ADDRESS_ARRAY 0xf0000000 /* SH-3 has unified cache system */ -#define CACHE_OC_ADDRESS_ARRAY 0xf0000000 -#define CACHE_VALID 1 -#define CACHE_UPDATED 2 - -/* 7709A/7729 has 16K cache (256-entry), while 7702 has only 2K(direct) - 7702 is not supported (yet) */ -struct _cache_system_info { - int way_shift; - int entry_mask; - int num_entries; -}; - -/* Data at BSS is cleared after setting this variable. - So, we Should not placed this variable at BSS section. - Initialize this, it is placed at data section. */ -static struct _cache_system_info cache_system_info = {0,}; - -#define CACHE_OC_WAY_SHIFT (cache_system_info.way_shift) -#define CACHE_IC_WAY_SHIFT (cache_system_info.way_shift) -#define CACHE_OC_ENTRY_SHIFT 4 -#define CACHE_OC_ENTRY_MASK (cache_system_info.entry_mask) -#define CACHE_IC_ENTRY_MASK (cache_system_info.entry_mask) -#define CACHE_OC_NUM_ENTRIES (cache_system_info.num_entries) -#define CACHE_OC_NUM_WAYS 4 -#define CACHE_IC_NUM_WAYS 4 -#elif defined(__SH4__) -#define CCR 0xff00001c /* Address of Cache Control Register */ -#define CCR_CACHE_VAL 0x00000105 /* 8k+16k-byte cache,P1-wb,enable */ -#define CCR_CACHE_INIT 0x0000090d /* ICI,ICE(8k), OCI,P1-wb,OCE(16k) */ -#define CCR_CACHE_ENABLE 0x00000101 - -#define CACHE_IC_ADDRESS_ARRAY 0xf0000000 -#define CACHE_OC_ADDRESS_ARRAY 0xf4000000 -#define CACHE_VALID 1 -#define CACHE_UPDATED 2 - -#define CACHE_OC_WAY_SHIFT 13 -#define CACHE_IC_WAY_SHIFT 13 -#define CACHE_OC_ENTRY_SHIFT 5 -#define CACHE_IC_ENTRY_SHIFT 5 -#define CACHE_OC_ENTRY_MASK 0x3fe0 -#define CACHE_OC_ENTRY_PHYS_MASK 0x0fe0 -#define CACHE_IC_ENTRY_MASK 0x1fe0 -#define CACHE_IC_NUM_ENTRIES 256 -#define CACHE_OC_NUM_ENTRIES 512 -#define CACHE_OC_NUM_WAYS 1 -#define CACHE_IC_NUM_WAYS 1 -#endif - - -/* - * Write back all the cache. - * - * For SH-4, we only need to flush (write back) Operand Cache, - * as Instruction Cache doesn't have "updated" data. - * - * Assumes that this is called in interrupt disabled context, and P2. - * Shuld be INLINE function. - */ -static inline void cache_wback_all(void) -{ - unsigned long addr, data, i, j; - - for (i=0; itype = CPU_SH7708; - } else { /* 7709A or 7729 */ - cache_system_info.way_shift = 12; - cache_system_info.entry_mask = 0xff0; - cache_system_info.num_entries = 256; - cpu_data->type = CPU_SH7729; - } -#elif defined(__SH4__) -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - cpu_data->type = CPU_ST40STB1; -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ - defined(CONFIG_CPU_SUBTYPE_SH7751) - cpu_data->type = CPU_SH7750; -#else -#error Unknown SH4 CPU type -#endif -#endif -} - -void __init cache_init(void) -{ - unsigned long ccr; - - detect_cpu_and_cache_system(); - - ccr = ctrl_inl(CCR); - jump_to_P2(); - if (ccr & CCR_CACHE_ENABLE) - /* - * XXX: Should check RA here. - * If RA was 1, we only need to flush the half of the caches. - */ - cache_wback_all(); - - ctrl_outl(CCR_CACHE_INIT, CCR); - back_to_P1(); -} - -#if defined(__SH4__) -/* - * SH-4 has virtually indexed and physically tagged cache. - */ - -/* - * Write back the dirty D-caches, but not invalidate them. - * - * START, END: Virtual Address - */ -static void dcache_wback_range(unsigned long start, unsigned long end) -{ - unsigned long v; - - start &= ~(L1_CACHE_BYTES-1); - for (v = start; v < end; v+=L1_CACHE_BYTES) { - asm volatile("ocbwb %0" - : /* no output */ - : "m" (__m(v))); - } -} - -/* - * Invalidate I-caches. - * - * START, END: Virtual Address - * - */ -static void icache_purge_range(unsigned long start, unsigned long end) -{ - unsigned long addr, data, v; - - start &= ~(L1_CACHE_BYTES-1); - - jump_to_P2(); - /* - * To handle the cache-line, we calculate the entry with virtual - * address: entry = vaddr & CACHE_IC_ENTRY_MASK. - * - * With A-bit "on", data written to is translated by MMU and - * compared the tag of cache and if it's not matched, nothing - * will be occurred. (We can avoid flushing other caches.) - * - * NOTE: We can use A-bit feature here, because we have valid - * entriy in TLB (at least in UTLB), as dcache_wback_range is - * called before this function is called. - */ - for (v = start; v < end; v+=L1_CACHE_BYTES) { - addr = CACHE_IC_ADDRESS_ARRAY | (v&CACHE_IC_ENTRY_MASK) - | 0x8 /* A-bit */; - data = (v&0xfffffc00); /* Valid=0 */ - ctrl_outl(data, addr); - } - back_to_P1(); -} - -/* - * Write back the range of D-cache, and purge the I-cache. - * - * Called from sh/kernel/signal.c, after accessing the memory - * through U0 area. START and END is the address of U0. - */ -void flush_icache_range(unsigned long start, unsigned long end) -{ - unsigned long flags; - - save_and_cli(flags); - dcache_wback_range(start, end); - icache_purge_range(start, end); - restore_flags(flags); -} - -/* - * Write back the D-cache and purge the I-cache for signal trampoline. - */ -void flush_cache_sigtramp(unsigned long addr) -{ - unsigned long v, index; - - v = addr & ~(L1_CACHE_BYTES-1); - asm volatile("ocbwb %0" - : /* no output */ - : "m" (__m(v))); - - index = CACHE_IC_ADDRESS_ARRAY| (v&CACHE_IC_ENTRY_MASK); - ctrl_outl(0, index); /* Clear out Valid-bit */ -} - -/* - * Invalidate the I-cache of the page (don't need to write back D-cache). - * - * Called from kernel/ptrace.c, mm/memory.c after flush_page_to_ram is called. - */ -void flush_icache_page(struct vm_area_struct *vma, struct page *pg) -{ - unsigned long phys, addr, data, i; - - /* Physical address of this page */ - phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START; - - jump_to_P2(); - /* Loop all the I-cache */ - for (i=0; ivm_mm, addr); - pmd = pmd_offset(dir, addr); - if (pmd_none(*pmd)) - return; - if (pmd_bad(*pmd)) - return; - pte = pte_offset(pmd, addr); - entry = *pte; - if (pte_none(entry) || !pte_present(entry)) - return; - phys = pte_val(entry)&PAGE_MASK; - pg = virt_to_page(__va(phys)); - flush_dcache_page(pg); -} - -/* - * Write-back & invalidate the cache. - * - * After accessing the memory from kernel space (P1-area), we need to - * write back the cache line. - * - * We search the D-cache to see if we have the entries corresponding to - * the page, and if found, write back them. - */ -void __flush_page_to_ram(void *kaddr) -{ - unsigned long phys, addr, data, i; - - /* Physical address of this page */ - phys = PHYSADDR(kaddr); - - jump_to_P2(); - /* Loop all the D-cache */ - for (i=0; i>CACHE_OC_ENTRY_SHIFT; - - jump_to_P2(); - /* Loop all the D-cache */ - for (i=0; i +ENTRY(clear_page) + mov r4,r5 + mov.w .Llimit,r0 + add r0,r5 + mov #0,r0 + ! +1: +#if defined(__sh3__) + mov.l r0,@r4 +#elif defined(__SH4__) + movca.l r0,@r4 + mov r4,r1 +#endif + add #32,r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 +#if defined(__SH4__) + ocbwb @r1 +#endif + cmp/eq r5,r4 + bf/s 1b + add #28,r4 + ! + rts + nop +.Llimit: .word (4096-28) diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/copy_page.S linux/arch/sh/mm/copy_page.S --- v2.4.9/linux/arch/sh/mm/copy_page.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/mm/copy_page.S Sat Sep 8 12:29:09 2001 @@ -0,0 +1,69 @@ +/* $Id: copy_page.S,v 1.2 2001/07/23 10:27:25 gniibe Exp $ + * + * copy_page implementation of SuperH + * + * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima + * + */ + +/* + * copy_page + * @to: P1 address + * @from: P1 address + * + * void copy_page(void *to, void *from) + */ + +/* + * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch + * r8 --- from + 4096 + * r9 --- not used + * r10 --- to + * r11 --- from + */ +#include +ENTRY(copy_page) + mov.l r8,@-r15 + mov.l r10,@-r15 + mov.l r11,@-r15 + mov r4,r10 + mov r5,r11 + mov r5,r8 + mov.w .L4096,r0 + add r0,r8 + ! +1: mov.l @r11+,r0 + mov.l @r11+,r1 + mov.l @r11+,r2 + mov.l @r11+,r3 + mov.l @r11+,r4 + mov.l @r11+,r5 + mov.l @r11+,r6 + mov.l @r11+,r7 +#if defined(__sh3__) + mov.l r0,@r10 +#elif defined(__SH4__) + movca.l r0,@r10 + mov r10,r0 +#endif + add #32,r10 + mov.l r7,@-r10 + mov.l r6,@-r10 + mov.l r5,@-r10 + mov.l r4,@-r10 + mov.l r3,@-r10 + mov.l r2,@-r10 + mov.l r1,@-r10 +#if defined(__SH4__) + ocbwb @r0 +#endif + cmp/eq r11,r8 + bf/s 1b + add #28,r10 + ! + mov.l @r15+,r11 + mov.l @r15+,r10 + mov.l @r15+,r8 + rts + nop +.L4096: .word 4096 diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/extable.c linux/arch/sh/mm/extable.c --- v2.4.9/linux/arch/sh/mm/extable.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/mm/extable.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: extable.c,v 1.1 1999/09/18 16:57:37 gniibe Exp $ +/* $Id: extable.c,v 1.2 2001/03/31 10:43:18 gniibe Exp $ * * linux/arch/sh/mm/extable.c * Taken from: diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/fault.c linux/arch/sh/mm/fault.c --- v2.4.9/linux/arch/sh/mm/fault.c Tue Jul 3 17:08:19 2001 +++ linux/arch/sh/mm/fault.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.13 2000/03/07 12:05:24 gniibe Exp $ +/* $Id: fault.c,v 1.48 2001/08/09 00:27:04 gniibe Exp $ * * linux/arch/sh/mm/fault.c * Copyright (C) 1999 Niibe Yutaka @@ -28,10 +28,6 @@ #include extern void die(const char *,struct pt_regs *,long); -static void __flush_tlb_page(unsigned long asid, unsigned long page); -#if defined(__SH4__) -static void __flush_tlb_phys(unsigned long phys); -#endif /* * Ugly, ugly, but the goto's result in better assembly.. @@ -242,8 +238,10 @@ pte_t *pte; pte_t entry; - if (address >= VMALLOC_START && address < VMALLOC_END) + if (address >= P3SEG && address < P4SEG) dir = pgd_offset_k(address); + else if (address >= TASK_SIZE) + return 1; else dir = pgd_offset(current->mm, address); @@ -257,7 +255,7 @@ } pte = pte_offset(pmd, address); entry = *pte; - if (pte_none(entry) || !pte_present(entry) + if (pte_none(entry) || pte_not_present(entry) || (writeaccess && !pte_write(entry))) return 1; @@ -283,27 +281,24 @@ unsigned long pteval; unsigned long vpn; #if defined(__SH4__) + struct page *page; unsigned long ptea; #endif - save_and_cli(flags); -#if defined(__SH4__) - if (pte_shared(pte)) { - struct page *pg; + /* Ptrace may call this routine. */ + if (vma && current->active_mm != vma->vm_mm) + return; - pteval = pte_val(pte); - pteval &= PAGE_MASK; /* Physicall page address */ - __flush_tlb_phys(pteval); - pg = virt_to_page(__va(pteval)); - flush_dcache_page(pg); +#if defined(__SH4__) + page = pte_page(pte); + if (VALID_PAGE(page) && !test_bit(PG_mapped, &page->flags)) { + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; + __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE); + __set_bit(PG_mapped, &page->flags); } #endif - /* Ptrace may call this routine. */ - if (vma && current->active_mm != vma->vm_mm) { - restore_flags(flags); - return; - } + save_and_cli(flags); /* Set PTEH register */ vpn = (address & MMU_VPN_MASK) | get_asid(); @@ -327,7 +322,7 @@ restore_flags(flags); } -static void __flush_tlb_page(unsigned long asid, unsigned long page) +void __flush_tlb_page(unsigned long asid, unsigned long page) { unsigned long addr, data; @@ -349,40 +344,6 @@ back_to_P1(); #endif } - -#if defined(__SH4__) -static void __flush_tlb_phys(unsigned long phys) -{ - unsigned long addr, data, pte; - - pte = phys | MMU_UTLB_VALID; - for (addr = MMU_UTLB_DATA_ARRAY; - addr < MMU_UTLB_DATA_ARRAY+(MMU_UTLB_ENTRIES< high) { - do { - if (pgd_quicklist) { - free_pgd_slow(get_pgd_fast()); - freed++; - } - if (pmd_quicklist) { - pmd_free_slow(pmd_alloc_one_fast(NULL, 0)); - freed++; - } - if (pte_quicklist) { - pte_free_slow(pte_alloc_one_fast(NULL, 0)); - freed++; - } - } while (pgtable_cache_size > low); - } - return freed; -} - void show_mem(void) { int i, total = 0, reserved = 0; @@ -91,7 +70,6 @@ printk("%d reserved pages\n",reserved); printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); - printk("%ld pages in page table cache\n",pgtable_cache_size); show_buffers(); } @@ -146,12 +124,18 @@ zones_size[ZONE_DMA] = max_dma - start_pfn; zones_size[ZONE_NORMAL] = low - max_dma; } - free_area_init_node(0, 0, 0, zones_size, __MEMORY_START, 0); + free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START, 0); +#ifdef CONFIG_DISCONTIGMEM + zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; + zones_size[ZONE_NORMAL] = 0; + free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND, 0); +#endif } } void __init mem_init(void) { + extern unsigned long empty_zero_page[1024]; int codesize, reservedpages, datasize, initsize; int tmp; @@ -160,10 +144,13 @@ /* clear the zero-page */ memset(empty_zero_page, 0, PAGE_SIZE); - flush_page_to_ram(virt_to_page(empty_zero_page)); + __flush_wback_region(empty_zero_page, PAGE_SIZE); /* this will put all low memory onto the freelists */ - totalram_pages += free_all_bootmem(); + totalram_pages += free_all_bootmem_node(NODE_DATA(0)); +#ifdef CONFIG_DISCONTIGMEM + totalram_pages += free_all_bootmem_node(NODE_DATA(1)); +#endif reservedpages = 0; for (tmp = 0; tmp < num_physpages; tmp++) /* @@ -182,6 +169,8 @@ reservedpages << (PAGE_SHIFT-10), datasize >> 10, initsize >> 10); + + p3_cache_init(); } void free_initmem(void) diff -u --recursive --new-file v2.4.9/linux/arch/sh/mm/ioremap.c linux/arch/sh/mm/ioremap.c --- v2.4.9/linux/arch/sh/mm/ioremap.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/mm/ioremap.c Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: ioremap.c,v 1.2 1999/11/25 14:00:28 gniibe Exp $ +/* $Id: ioremap.c,v 1.4 2001/06/30 09:18:39 gniibe Exp $ * * arch/sh/mm/ioremap.c * @@ -13,8 +13,8 @@ #include #include -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline void remap_area_pte(pte_t * pte, unsigned long address, + unsigned long size, unsigned long phys_addr, unsigned long flags) { unsigned long end; pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | @@ -36,11 +36,11 @@ address += PAGE_SIZE; phys_addr += PAGE_SIZE; pte++; - } while (address && address < end); + } while (address && (address < end)); } -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, + unsigned long size, unsigned long phys_addr, unsigned long flags) { unsigned long end; @@ -58,19 +58,19 @@ remap_area_pte(pte, address, end - address, address + phys_addr, flags); address = (address + PMD_SIZE) & PMD_MASK; pmd++; - } while (address && address < end); + } while (address && (address < end)); return 0; } -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) +int remap_area_pages(unsigned long address, unsigned long phys_addr, + unsigned long size, unsigned long flags) { int error; pgd_t * dir; unsigned long end = address + size; phys_addr -= address; - dir = pgd_offset(&init_mm, address); + dir = pgd_offset_k(address); flush_cache_all(); if (address >= end) BUG(); @@ -106,7 +106,7 @@ * have to convert them into an offset in a page-aligned mapping, but the * caller shouldn't need to know that small detail. */ -void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) { void * addr; struct vm_struct * area; @@ -150,7 +150,7 @@ return (void *) (offset + (char *)addr); } -void iounmap(void *addr) +void p3_iounmap(void *addr) { if (addr > high_memory) return vfree((void *) (PAGE_MASK & (unsigned long) addr)); diff -u --recursive --new-file v2.4.9/linux/arch/sh/vmlinux.lds.S linux/arch/sh/vmlinux.lds.S --- v2.4.9/linux/arch/sh/vmlinux.lds.S Tue Jul 3 17:08:19 2001 +++ linux/arch/sh/vmlinux.lds.S Sat Sep 8 12:29:09 2001 @@ -1,4 +1,4 @@ -/* $Id: vmlinux.lds.S,v 1.4 1999/12/23 11:37:45 gniibe Exp $ +/* $Id: vmlinux.lds.in,v 1.5 2001/07/27 11:45:55 gniibe Exp $ * ld script to make SuperH Linux kernel * Written by Niibe Yutaka */ @@ -74,7 +74,11 @@ . = ALIGN(4096); .data.page_aligned : { *(.data.idt) } +#ifdef CONFIG_CPU_SH3 + . = ALIGN(16); +#else . = ALIGN(32); +#endif .data.cacheline_aligned : { *(.data.cacheline_aligned) } . = ALIGN(4); diff -u --recursive --new-file v2.4.9/linux/arch/sparc/boot/btfixupprep.c linux/arch/sparc/boot/btfixupprep.c --- v2.4.9/linux/arch/sparc/boot/btfixupprep.c Sun Oct 4 10:22:42 1998 +++ linux/arch/sparc/boot/btfixupprep.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: btfixupprep.c,v 1.5 1998/09/16 12:24:55 jj Exp $ +/* $Id: btfixupprep.c,v 1.6 2001/08/22 15:27:47 davem Exp $ Simple utility to prepare vmlinux image for sparc. Resolves all BTFIXUP uses and settings and creates a special .s object to link to the image. @@ -88,6 +88,16 @@ return array + last - 1; } +void set_mode (char *buffer) +{ + for (mode = 0;; mode++) + if (buffer[mode] < '0' || buffer[mode] > '9') + break; + if (mode != 8 && mode != 16) + fatal(); +} + + int main(int argc,char **argv) { char *p, *q; @@ -106,14 +116,6 @@ goto main0; fatal(); main0: - if (fgets (buffer, 1024, stdin) == NULL || buffer[0] < '0' || buffer[0] > '9') - fatal(); - for (mode = 0;; mode++) - if (buffer[mode] < '0' || buffer[mode] > '9') - break; - if (mode != 8 && mode != 16) - fatal(); - rellen = strlen(relrec); while (fgets (buffer, 1024, stdin) != NULL) if (!strncmp (buffer, relrec, rellen)) @@ -132,6 +134,8 @@ int nbase; if (!strncmp (buffer, relrec, rellen)) goto main1; + if (mode == 0) + set_mode (buffer); p = strchr (buffer, '\n'); if (p) *p = 0; if (strlen (buffer) < 22+mode) diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.4.9/linux/arch/sparc64/defconfig Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/defconfig Fri Sep 7 11:01:20 2001 @@ -255,6 +255,7 @@ CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_IDEDMA=y @@ -264,8 +265,8 @@ # CONFIG_AEC62XX_TUNING is not set CONFIG_BLK_DEV_ALI15X3=y # CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD7409 is not set -# CONFIG_AMD7409_OVERRIDE is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -276,7 +277,8 @@ # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set # CONFIG_PDC202XX_BURST is not set -# CONFIG_BLK_DEV_OSB4 is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set @@ -709,7 +711,10 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m @@ -740,10 +745,10 @@ # # USB Network adaptors # -CONFIG_USB_PLUSB=m CONFIG_USB_PEGASUS=m CONFIG_USB_CATC=m -CONFIG_USB_NET1080=m +CONFIG_USB_KAWETH=m +CONFIG_USB_USBNET=m # # USB port drivers diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/dtlb_backend.S linux/arch/sparc64/kernel/dtlb_backend.S --- v2.4.9/linux/arch/sparc64/kernel/dtlb_backend.S Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/dtlb_backend.S Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: dtlb_backend.S,v 1.12 2001/08/13 20:41:54 kanoj Exp $ +/* $Id: dtlb_backend.S,v 1.13 2001/08/17 04:55:09 kanoj Exp $ * dtlb_backend.S: Back end to DTLB miss replacement strategy. * This is included directly into the trap table. * @@ -6,11 +6,27 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#define TAG_CONTEXT_BITS 0x3ff +#include + +#if PAGE_SHIFT == 13 +#define FILL_VALID_SZ_BITS1(r1) \ + sllx %g2, 62, r1 +#define FILL_VALID_SZ_BITS2(r1) +#define FILL_VALID_SZ_BITS_NOP nop +#else /* PAGE_SHIFT */ +#define FILL_VALID_SZ_BITS1(r1) \ + or %g0, 5, r1 +#define FILL_VALID_SZ_BITS2(r1) \ + sllx r1, 61, r1 +#define FILL_VALID_SZ_BITS_NOP +#endif /* PAGE_SHIFT */ + +#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P ) #define VPTE_SHIFT (PAGE_SHIFT - 3) -#define PMD_SHIFT (23 - PAGE_SHIFT + 3) -#define PGD_SHIFT (34 - PAGE_SHIFT + 3) -#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P) +#define TLB_PMD_SHIFT (PAGE_SHIFT - 3 + 3) +#define TLB_PGD_SHIFT (PAGE_SHIFT - 2 + PAGE_SHIFT - 3 + 3) +#define TLB_PMD_MASK (((1 << PMD_BITS) - 1) << 1) +#define TLB_PGD_MASK (((1 << (VA_BITS - PAGE_SHIFT - (PAGE_SHIFT - 3) - PMD_BITS)) - 1) << 2) /* Ways we can get here: * @@ -31,13 +47,13 @@ /* TLB1 ** ICACHE line 2: Quick VPTE miss */ ldxa [%g1] ASI_DMMU, %g5 ! Doing PGD caching? - srlx %g6, (PMD_SHIFT - 1), %g1 ! Position PMD offset + srlx %g6, (TLB_PMD_SHIFT - 1), %g1 ! Position PMD offset be,pn %xcc, sparc64_vpte_nucleus ! Is it from Nucleus? - and %g1, 0xffe, %g1 ! Mask PMD offset bits + and %g1, TLB_PMD_MASK, %g1 ! Mask PMD offset bits brnz,pt %g5, sparc64_vpte_continue ! Yep, go like smoke add %g1, %g1, %g1 ! Position PMD offset some more - srlx %g6, (PGD_SHIFT - 2), %g5 ! Position PGD offset - and %g5, 0xffc, %g5 ! Mask PGD offset + srlx %g6, (TLB_PGD_SHIFT - 2), %g5 ! Position PGD offset + and %g5, TLB_PGD_MASK, %g5 ! Mask PGD offset /* TLB1 ** ICACHE line 3: Quick VPTE miss */ lduwa [%g7 + %g5] ASI_PHYS_USE_EC, %g5! Load PGD @@ -48,7 +64,8 @@ lduwa [%g5 + %g1] ASI_PHYS_USE_EC, %g5! Load PMD sllx %g5, 11, %g5 ! Shift into place brz,pn %g5, vpte_noent ! Valid? - sllx %g2, 62, %g1 ! Put _PAGE_VALID into %g1 + FILL_VALID_SZ_BITS1(%g1) ! Put _PAGE_VALID into %g1 + FILL_VALID_SZ_BITS2(%g1) ! Put _PAGE_VALID into %g1 or %g5, VPTE_BITS, %g5 ! Prepare VPTE data /* TLB1 ** ICACHE line 4: Quick VPTE miss */ @@ -59,10 +76,15 @@ retry ! Load PTE once again nop nop - nop + FILL_VALID_SZ_BITS_NOP -#undef TAG_CONTEXT_BITS #undef VPTE_SHIFT -#undef PMD_SHIFT -#undef PGD_SHIFT +#undef TLB_PMD_SHIFT +#undef TLB_PGD_SHIFT #undef VPTE_BITS +#undef TLB_PMD_MASK +#undef TLB_PGD_MASK +#undef FILL_VALID_SZ_BITS1 +#undef FILL_VALID_SZ_BITS2 +#undef FILL_VALID_SZ_BITS_NOP + diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/dtlb_base.S linux/arch/sparc64/kernel/dtlb_base.S --- v2.4.9/linux/arch/sparc64/kernel/dtlb_base.S Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/dtlb_base.S Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: dtlb_base.S,v 1.10 2001/08/13 20:41:54 kanoj Exp $ +/* $Id: dtlb_base.S,v 1.12 2001/08/17 04:55:09 kanoj Exp $ * dtlb_base.S: Front end to DTLB miss replacement strategy. * This is included directly into the trap table. * @@ -6,11 +6,6 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#define TAG_CONTEXT_BITS 0x3ff -#define VPTE_SHIFT (PAGE_SHIFT - 3) -#define KERN_HIGHBITS ((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000) -#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) - /* %g1 TLB_SFSR (%g1 + %g1 == TLB_TAG_ACCESS) * %g2 (KERN_HIGHBITS | KERN_LOWBITS) * %g3 VPTE base (0xfffffffe00000000) Spitfire/Blackbird (44-bit VA space) @@ -48,26 +43,47 @@ * 4) User space accesses by nucleus at tl0 */ +#if PAGE_SHIFT == 13 +/* + * To compute vpte offset, we need to do ((addr >> 13) << 3), + * which can be optimized to (addr >> 10) if bits 10/11/12 can + * be guaranteed to be 0 ... mmu_context.h does guarantee this + * by only using 10 bits in the hwcontext value. + */ +#define CREATE_VPTE_OFFSET1(r1, r2) +#define CREATE_VPTE_OFFSET2(r1, r2) \ + srax r1, 10, r2 +#define CREATE_VPTE_NOP nop +#else +#define CREATE_VPTE_OFFSET1(r1, r2) \ + srax r1, PAGE_SHIFT, r2 +#define CREATE_VPTE_OFFSET2(r1, r2) \ + sllx r2, 3, r2 +#define CREATE_VPTE_NOP +#endif + /* DTLB ** ICACHE line 1: Quick user TLB misses */ ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus? from_tl1_trap: + CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset be,pn %xcc, 3f ! Yep, special processing - srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset + CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE 1: brlz,pt %g5, 9f ! Valid, load into TLB nop ! Delay-slot - ba,a,pt %xcc, 4f ! Invalid, branch out + ba,a,pt %xcc, longpath ! Invalid, branch out /* DTLB ** ICACHE line 2: Quick kernel TLB misses */ 3: brlz,pt %g4, 9f ! Kernel virtual map? xor %g2, %g4, %g5 ! Finish bit twiddles - ldxa [%g3 + %g6] ASI_N, %g5 ! Yep, load k-vpte - ba,pt %xcc, 1b ! Continue tlb reload + ba,pt %xcc, kvmap ! Yep, go check for obp/vmalloc nop + nop 9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB retry ! Trap return -4: rdpr %pstate, %g5 ! Move into alternate globals +longpath: + rdpr %pstate, %g5 ! Move into alternate globals /* DTLB ** ICACHE line 3: winfixups+real_faults */ wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate @@ -87,9 +103,8 @@ nop nop nop - nop + CREATE_VPTE_NOP -#undef TAG_CONTEXT_BITS -#undef VPTE_SHIFT -#undef KERN_HIGHBITS -#undef KERN_LOWBITS +#undef CREATE_VPTE_OFFSET1 +#undef CREATE_VPTE_OFFSET2 +#undef CREATE_VPTE_NOP diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.4.9/linux/arch/sparc64/kernel/entry.S Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/entry.S Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.129 2001/08/13 20:41:54 kanoj Exp $ +/* $Id: entry.S,v 1.134 2001/08/27 18:42:07 kanoj Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -21,7 +21,7 @@ #include #include -/* #define SYSCALL_TRACING */ +/* #define SYSCALL_TRACING 1 */ #define curptr g6 @@ -32,7 +32,25 @@ .globl sparc64_vpte_patchme1 .globl sparc64_vpte_patchme2 +/* + * On a second level vpte miss, check whether the original fault is to the OBP + * range (note that this is only possible for instruction miss, data misses to + * obp range do not use vpte). If so, go back directly to the faulting address. + * This is because we want to read the tpc, otherwise we have no way of knowing + * the 8k aligned faulting address if we are using >8k kernel pagesize. This also + * ensures no vpte range addresses are dropped into tlb while obp is executing + * (see inherit_locked_prom_mappings() rant). + */ sparc64_vpte_nucleus: + mov 0xf, %g5 + sllx %g5, 28, %g5 ! Load 0xf0000000 + cmp %g4, %g5 ! Is addr >= LOW_OBP_ADDRESS? + blu,pn %xcc, sparc64_vpte_patchme1 + mov 0x1, %g5 + sllx %g5, 32, %g5 ! Load 0x100000000 + cmp %g4, %g5 ! Is addr < HI_OBP_ADDRESS? + blu,pn %xcc, obp_iaddr_patch + nop sparc64_vpte_patchme1: sethi %hi(0), %g5 ! This has to be patched sparc64_vpte_patchme2: @@ -45,6 +63,74 @@ stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS done ! Slick trick + .globl obp_iaddr_patch + .globl obp_daddr_patch + +obp_iaddr_patch: + sethi %hi(0), %g5 ! This and following is patched + or %g5, %lo(0), %g5 ! g5 now holds obp pmd base physaddr + wrpr %g0, 1, %tl ! Behave as if we are at TL0 + rdpr %tpc, %g4 ! Find original faulting iaddr + srlx %g4, 13, %g4 ! Throw out context bits + sllx %g4, 13, %g4 ! g4 has vpn + ctx0 now + mov TLB_SFSR, %g1 ! Restore %g1 value + stxa %g4, [%g1 + %g1] ASI_IMMU ! Restore previous TAG_ACCESS + srlx %g4, 23, %g6 ! Find pmd number + and %g6, 0x7ff, %g6 ! Find pmd number + sllx %g6, 2, %g6 ! Find pmd offset + lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pmd, ie pagetable physaddr + brz,pn %g5, longpath ! Kill the PROM ? :-) + sllx %g5, 11, %g5 ! Shift into place + srlx %g4, 13, %g6 ! find pte number in pagetable + and %g6, 0x3ff, %g6 ! find pte number in pagetable + sllx %g6, 3, %g6 ! find pte offset in pagetable + ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pte + brgez,pn %g5, longpath ! Kill the PROM ? :-) + nop + stxa %g5, [%g0] ASI_ITLB_DATA_IN ! put into tlb + retry ! go back to original fault + +obp_daddr_patch: + sethi %hi(0), %g5 ! This and following is patched + or %g5, %lo(0), %g5 ! g5 now holds obp pmd base physaddr + srlx %g4, 23, %g6 ! Find pmd number + and %g6, 0x7ff, %g6 ! Find pmd number + sllx %g6, 2, %g6 ! Find pmd offset + lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pmd, ie pagetable physaddr + brz,pn %g5, longpath + sllx %g5, 11, %g5 ! Shift into place + srlx %g4, 13, %g6 ! find pte number in pagetable + and %g6, 0x3ff, %g6 ! find pte number in pagetable + sllx %g6, 3, %g6 ! find pte offset in pagetable + ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pte + brgez,pn %g5, longpath + nop + stxa %g5, [%g0] ASI_DTLB_DATA_IN ! put into tlb + retry + +/* + * On a first level data miss, check whether this is to the OBP range (note that + * such accesses can be made by prom, as well as by kernel using prom_getproperty + * on "address"), and if so, do not use vpte access ... rather, use information + * saved during inherit_prom_mappings() using 8k pagesize. + */ +kvmap: + mov 0xf, %g5 + sllx %g5, 28, %g5 ! Load 0xf0000000 + cmp %g4, %g5 ! Is addr >= LOW_OBP_ADDRESS? + blu,pn %xcc, vmalloc_addr + mov 0x1, %g5 + sllx %g5, 32, %g5 ! Load 0x100000000 + cmp %g4, %g5 ! Is addr < HI_OBP_ADDRESS? + blu,pn %xcc, obp_daddr_patch + nop +vmalloc_addr: ! vmalloc addr accessed + ldxa [%g3 + %g6] ASI_N, %g5 ! Yep, load k-vpte + brgez,pn %g5, longpath ! Valid, load into TLB + nop + stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB + retry + /* This is trivial with the new code... */ .globl do_fpdis do_fpdis: @@ -1413,9 +1499,8 @@ srl %i0, 0, %o0 ! IEU0 sll %g1, 2, %l4 ! IEU0 Group #ifdef SYSCALL_TRACING - add %sp, STACK_BIAS + REGWIN_SZ, %o1 call syscall_trace_entry - mov %g1, %o0 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 srl %i0, 0, %o0 #endif mov %i4, %o4 ! IEU1 @@ -1442,9 +1527,8 @@ mov %i0, %o0 ! IEU0 sll %g1, 2, %l4 ! IEU0 Group #ifdef SYSCALL_TRACING - add %sp, STACK_BIAS + REGWIN_SZ, %o1 call syscall_trace_entry - mov %g1, %o0 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 mov %i0, %o0 #endif mov %i1, %o1 ! IEU1 @@ -1464,8 +1548,10 @@ 3: stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ret_sys_call: #ifdef SYSCALL_TRACING + mov %o0, %o1 call syscall_trace_exit - add %sp, STACK_BIAS + REGWIN_SZ, %o1 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + mov %o1, %o0 #endif ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3 ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S --- v2.4.9/linux/arch/sparc64/kernel/head.S Thu Apr 12 12:10:25 2001 +++ linux/arch/sparc64/kernel/head.S Fri Sep 7 11:01:20 2001 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.77 2001/04/05 12:44:34 davem Exp $ +/* $Id: head.S,v 1.78 2001/08/30 03:22:00 kanoj Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -488,13 +488,6 @@ call __bzero sub %o1, %o0, %o1 - /* Now clear empty_zero_page */ - sethi %hi(8192), %o1 - or %o1, %lo(8192), %o1 - sethi %hi(KERNBASE), %g3 - call __bzero - or %g3, %lo(KERNBASE), %o0 - mov %l6, %o1 ! OpenPROM stack call prom_init mov %l7, %o0 ! OpenPROM cif handler @@ -647,12 +640,13 @@ ret restore +/* + * The following skips make sure the trap table in ttable.S is aligned + * on a 32K boundary as required by the v9 specs for TBA register. + */ sparc64_boot_end: .skip 0x2000 + _start - sparc64_boot_end bootup_user_stack_end: - - .globl empty_bad_page -empty_bad_page: .skip 0x2000 #ifdef CONFIG_SBUS diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.4.9/linux/arch/sparc64/kernel/ioctl32.c Sun Aug 12 13:27:59 2001 +++ linux/arch/sparc64/kernel/ioctl32.c Fri Sep 7 11:01:20 2001 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.121 2001/08/03 14:27:21 davem Exp $ +/* $Id: ioctl32.c,v 1.123 2001/09/02 03:52:07 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -3691,6 +3691,8 @@ COMPATIBLE_IOCTL(BLKFRASET) COMPATIBLE_IOCTL(BLKSECTSET) COMPATIBLE_IOCTL(BLKSSZGET) +COMPATIBLE_IOCTL(BLKBSZGET) +COMPATIBLE_IOCTL(BLKBSZSET) /* RAID */ COMPATIBLE_IOCTL(RAID_VERSION) @@ -3733,6 +3735,7 @@ COMPATIBLE_IOCTL(KDGKBSENT) COMPATIBLE_IOCTL(KDSKBSENT) COMPATIBLE_IOCTL(KDGKBDIACR) +COMPATIBLE_IOCTL(KDKBDREP) COMPATIBLE_IOCTL(KDSKBDIACR) COMPATIBLE_IOCTL(KDGKBLED) COMPATIBLE_IOCTL(KDSKBLED) diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/iommu_common.c linux/arch/sparc64/kernel/iommu_common.c --- v2.4.9/linux/arch/sparc64/kernel/iommu_common.c Mon Jun 19 17:59:38 2000 +++ linux/arch/sparc64/kernel/iommu_common.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: iommu_common.c,v 1.4 2000/06/04 21:50:23 anton Exp $ +/* $Id: iommu_common.c,v 1.5 2001/08/24 17:57:51 kanoj Exp $ * iommu_common.c: UltraSparc SBUS/PCI common iommu code. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -36,12 +36,12 @@ unsigned long start, end; start = sg[i].dvma_address; - start = start & PAGE_MASK; + start = start & IO_PAGE_MASK; end = sg[i].dvma_address + sg[i].dvma_length; - end = (end + (PAGE_SIZE - 1)) & PAGE_MASK; + end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK; - pgcount += ((end - start) >> PAGE_SHIFT); + pgcount += ((end - start) >> IO_PAGE_SHIFT); } if (pgcount != npages) { @@ -70,7 +70,7 @@ unsigned long paddr; /* SG and DMA_SG must begin at the same sub-page boundary. */ - if ((sgaddr & ~PAGE_MASK) != (daddr & ~PAGE_MASK)) { + if ((sgaddr & ~IO_PAGE_MASK) != (daddr & ~IO_PAGE_MASK)) { printk("verify_one_map: Wrong start offset " "sg[%08lx] dma[%08x]\n", sgaddr, daddr); @@ -80,10 +80,10 @@ /* Verify the IOPTE points to the right page. */ paddr = iopte_val(*iopte) & IOPTE_PAGE; - if ((paddr + PAGE_OFFSET) != (sgaddr & PAGE_MASK)) { + if ((paddr + PAGE_OFFSET) != (sgaddr & IO_PAGE_MASK)) { printk("verify_one_map: IOPTE[%08lx] maps the " "wrong page, should be [%08lx]\n", - iopte_val(*iopte), (sgaddr & PAGE_MASK) - PAGE_OFFSET); + iopte_val(*iopte), (sgaddr & IO_PAGE_MASK) - PAGE_OFFSET); nents = -1; goto out; } @@ -91,10 +91,10 @@ /* If this SG crosses a page, adjust to that next page * boundary and loop. */ - if ((sgaddr & PAGE_MASK) ^ ((sgaddr + sglen - 1) & PAGE_MASK)) { + if ((sgaddr & IO_PAGE_MASK) ^ ((sgaddr + sglen - 1) & IO_PAGE_MASK)) { unsigned long next_page, diff; - next_page = (sgaddr + PAGE_SIZE) & PAGE_MASK; + next_page = (sgaddr + IO_PAGE_SIZE) & IO_PAGE_MASK; diff = next_page - sgaddr; sgaddr += diff; daddr += diff; @@ -109,7 +109,7 @@ daddr += sglen; dlen -= sglen; - if (dlen > 0 && ((daddr & ~PAGE_MASK) == 0)) + if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0)) iopte++; sg++; @@ -175,7 +175,7 @@ int i; printk("verify_sglist: Crap, messed up mappings, dumping, iodma at %08x.\n", - (u32) (sg->dvma_address & PAGE_MASK)); + (u32) (sg->dvma_address & IO_PAGE_MASK)); for (i = 0; i < nents; i++) { printk("sg(%d): address(%p) length(%x) " "dma_address[%08x] dma_length[%08x]\n", @@ -189,13 +189,6 @@ } #endif -/* Two addresses are "virtually contiguous" if and only if: - * 1) They are equal, or... - * 2) They are both on a page boundry - */ -#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ - (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) - unsigned long prepare_sg(struct scatterlist *sg, int nents) { struct scatterlist *dma_sg = sg; @@ -204,7 +197,7 @@ prev = (unsigned long) sg->address; prev += (unsigned long) (dent_len = sg->length); - dent_addr = (u32) ((unsigned long)sg->address & (PAGE_SIZE - 1UL)); + dent_addr = (u32) ((unsigned long)sg->address & (IO_PAGE_SIZE - 1UL)); while (--nents) { unsigned long addr; @@ -217,9 +210,9 @@ dent_addr = ((dent_addr + dent_len + - (PAGE_SIZE - 1UL)) >> PAGE_SHIFT); - dent_addr <<= PAGE_SHIFT; - dent_addr += addr & (PAGE_SIZE - 1UL); + (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT); + dent_addr <<= IO_PAGE_SHIFT; + dent_addr += addr & (IO_PAGE_SIZE - 1UL); dent_len = 0; } dent_len += sg->length; @@ -230,5 +223,5 @@ return ((unsigned long) dent_addr + (unsigned long) dent_len + - (PAGE_SIZE - 1UL)) >> PAGE_SHIFT; + (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT; } diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/iommu_common.h linux/arch/sparc64/kernel/iommu_common.h --- v2.4.9/linux/arch/sparc64/kernel/iommu_common.h Mon Dec 20 22:05:52 1999 +++ linux/arch/sparc64/kernel/iommu_common.h Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: iommu_common.h,v 1.1 1999/12/17 12:31:54 jj Exp $ +/* $Id: iommu_common.h,v 1.3 2001/08/24 19:36:58 kanoj Exp $ * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -10,6 +10,22 @@ #include #include #include + +/* + * These give mapping size of each iommu pte/tlb. + */ +#define IO_PAGE_SHIFT 13 +#define IO_PAGE_SIZE (1UL << IO_PAGE_SHIFT) +#define IO_PAGE_MASK (~(IO_PAGE_SIZE-1)) +#define IO_PAGE_ALIGN(addr) (((addr)+IO_PAGE_SIZE-1)&IO_PAGE_MASK) + +#define IO_TSB_ENTRIES (128*1024) +#define IO_TSB_SIZE (IO_TSB_ENTRIES * 8) + +/* + * This is the hardwired shift in the iotlb tag/data parts. + */ +#define IOMMU_PAGE_SHIFT 13 /* You are _strongly_ advised to enable the following debugging code * any time you make changes to the sg code below, run it for a while diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/itlb_base.S linux/arch/sparc64/kernel/itlb_base.S --- v2.4.9/linux/arch/sparc64/kernel/itlb_base.S Sun Nov 12 20:37:16 2000 +++ linux/arch/sparc64/kernel/itlb_base.S Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: itlb_base.S,v 1.10 2000/11/10 08:28:45 davem Exp $ +/* $Id: itlb_base.S,v 1.11 2001/08/17 04:55:09 kanoj Exp $ * itlb_base.S: Front end to ITLB miss replacement strategy. * This is included directly into the trap table. * @@ -6,8 +6,25 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#define TAG_CONTEXT_BITS 0x3ff -#define VPTE_SHIFT (PAGE_SHIFT - 3) +#if PAGE_SHIFT == 13 +/* + * To compute vpte offset, we need to do ((addr >> 13) << 3), + * which can be optimized to (addr >> 10) if bits 10/11/12 can + * be guaranteed to be 0 ... mmu_context.h does guarantee this + * by only using 10 bits in the hwcontext value. + */ +#define CREATE_VPTE_OFFSET1(r1, r2) \ + srax r1, 10, r2 +#define CREATE_VPTE_OFFSET2(r1, r2) +#define CREATE_VPTE_NOP nop +#else /* PAGE_SHIFT */ +#define CREATE_VPTE_OFFSET1(r1, r2) \ + srax r1, PAGE_SHIFT, r2 +#define CREATE_VPTE_OFFSET2(r1, r2) \ + sllx r2, 3, r2 +#define CREATE_VPTE_NOP +#endif /* PAGE_SHIFT */ + /* Ways we can get here: * @@ -20,7 +37,8 @@ /* ITLB ** ICACHE line 1: Quick user TLB misses */ ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS - srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset + CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset + CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset ldxa [%g3 + %g6] ASI_P, %g5 ! Load VPTE 1: brgez,pn %g5, 3f ! Not valid, branch out nop ! Delay-slot @@ -58,7 +76,8 @@ nop nop nop - nop + CREATE_VPTE_NOP -#undef TAG_CONTEXT_BITS -#undef VPTE_SHIFT +#undef CREATE_VPTE_OFFSET1 +#undef CREATE_VPTE_OFFSET2 +#undef CREATE_VPTE_NOP diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c --- v2.4.9/linux/arch/sparc64/kernel/pci_iommu.c Thu May 24 15:00:58 2001 +++ linux/arch/sparc64/kernel/pci_iommu.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_iommu.c,v 1.14 2001/05/23 03:06:51 davem Exp $ +/* $Id: pci_iommu.c,v 1.15 2001/08/24 19:36:58 kanoj Exp $ * pci_iommu.c: UltraSparc PCI controller IOM/STC support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -121,7 +121,7 @@ while ((1UL << cnum) < npages) cnum++; - ent = (base << (32 - PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits)) + ent = (base << (32 - IO_PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits)) >> (32 + PBM_LOGCLUSTERS + cnum - iommu->page_table_sz_bits); /* If the global flush might not have caught this entry, @@ -184,7 +184,7 @@ void *ret; int npages; - size = PAGE_ALIGN(size); + size = IO_PAGE_ALIGN(size); order = get_order(size); if (order >= 10) return NULL; @@ -198,7 +198,7 @@ iommu = pcp->pbm->iommu; spin_lock_irqsave(&iommu->lock, flags); - iopte = alloc_consistent_cluster(iommu, size >> PAGE_SHIFT); + iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT); if (iopte == NULL) { spin_unlock_irqrestore(&iommu->lock, flags); free_pages(first_page, order); @@ -206,9 +206,9 @@ } *dma_addrp = (iommu->page_table_map_base + - ((iopte - iommu->page_table) << PAGE_SHIFT)); + ((iopte - iommu->page_table) << IO_PAGE_SHIFT)); ret = (void *) first_page; - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; @@ -218,17 +218,17 @@ IOPTE_WRITE | (first_page & IOPTE_PAGE)); iopte++; - first_page += PAGE_SIZE; + first_page += IO_PAGE_SIZE; } { int i; u32 daddr = *dma_addrp; - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; for (i = 0; i < npages; i++) { pci_iommu_write(iommu->iommu_flush, daddr); - daddr += PAGE_SIZE; + daddr += IO_PAGE_SIZE; } } @@ -245,11 +245,11 @@ iopte_t *iopte; unsigned long flags, order, npages, i, ctx; - npages = PAGE_ALIGN(size) >> PAGE_SHIFT; + npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; pcp = pdev->sysdata; iommu = pcp->pbm->iommu; iopte = iommu->page_table + - ((dvma - iommu->page_table_map_base) >> PAGE_SHIFT); + ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); spin_lock_irqsave(&iommu->lock, flags); @@ -286,7 +286,7 @@ pci_iommu_write(iommu->iommu_ctxflush, ctx); } else { for (i = 0; i < npages; i++) { - u32 daddr = dvma + (i << PAGE_SHIFT); + u32 daddr = dvma + (i << IO_PAGE_SHIFT); pci_iommu_write(iommu->iommu_flush, daddr); } @@ -321,8 +321,8 @@ BUG(); oaddr = (unsigned long)ptr; - npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; + npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK); + npages >>= IO_PAGE_SHIFT; spin_lock_irqsave(&iommu->lock, flags); @@ -330,9 +330,9 @@ if (base == NULL) goto bad; bus_addr = (iommu->page_table_map_base + - ((base - iommu->page_table) << PAGE_SHIFT)); - ret = bus_addr | (oaddr & ~PAGE_MASK); - base_paddr = __pa(oaddr & PAGE_MASK); + ((base - iommu->page_table) << IO_PAGE_SHIFT)); + ret = bus_addr | (oaddr & ~IO_PAGE_MASK); + base_paddr = __pa(oaddr & IO_PAGE_MASK); ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; @@ -343,7 +343,7 @@ if (direction != PCI_DMA_TODEVICE) iopte_protection |= IOPTE_WRITE; - for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE) + for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE) iopte_val(*base) = iopte_protection | base_paddr; spin_unlock_irqrestore(&iommu->lock, flags); @@ -372,15 +372,15 @@ iommu = pcp->pbm->iommu; strbuf = &pcp->pbm->stc; - npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK); - npages >>= PAGE_SHIFT; + npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); + npages >>= IO_PAGE_SHIFT; base = iommu->page_table + - ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU if (iopte_val(*base) == IOPTE_INVALID) printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n", bus_addr, sz, __builtin_return_address(0)); #endif - bus_addr &= PAGE_MASK; + bus_addr &= IO_PAGE_MASK; spin_lock_irqsave(&iommu->lock, flags); @@ -404,7 +404,7 @@ pci_iommu_write(flushreg, ctx); } while(((long)pci_iommu_read(matchreg)) < 0L); } else { - for (i = 0; i < npages; i++, vaddr += PAGE_SIZE) + for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, vaddr); } @@ -432,9 +432,9 @@ unsigned long pteval = ~0UL; u32 dma_npages; - dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) + + dma_npages = ((dma_sg->dvma_address & (IO_PAGE_SIZE - 1UL)) + dma_sg->dvma_length + - ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT; + ((u32)(IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT; do { unsigned long offset; signed int len; @@ -449,15 +449,15 @@ tmp = (unsigned long) __pa(sg->address); len = sg->length; - if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) { - pteval = tmp & PAGE_MASK; - offset = tmp & (PAGE_SIZE - 1UL); + if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { + pteval = tmp & IO_PAGE_MASK; + offset = tmp & (IO_PAGE_SIZE - 1UL); break; } - if (((tmp ^ (tmp + len - 1UL)) >> PAGE_SHIFT) != 0UL) { - pteval = (tmp + PAGE_SIZE) & PAGE_MASK; + if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) { + pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK; offset = 0UL; - len -= (PAGE_SIZE - (tmp & (PAGE_SIZE - 1UL))); + len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); break; } sg++; @@ -466,8 +466,8 @@ pteval = iopte_protection | (pteval & IOPTE_PAGE); while (len > 0) { *iopte++ = __iopte(pteval); - pteval += PAGE_SIZE; - len -= (PAGE_SIZE - offset); + pteval += IO_PAGE_SIZE; + len -= (IO_PAGE_SIZE - offset); offset = 0; dma_npages--; } @@ -479,14 +479,14 @@ * adjusting pteval along the way. Stop when we * detect a page crossing event. */ - while ((pteval << (64 - PAGE_SHIFT)) != 0UL && + while ((pteval << (64 - IO_PAGE_SHIFT)) != 0UL && pteval == __pa(sg->address) && ((pteval ^ - (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { + (__pa(sg->address) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { pteval += sg->length; sg++; } - if ((pteval << (64 - PAGE_SHIFT)) == 0UL) + if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) pteval = ~0UL; } while (dma_npages != 0); dma_sg++; @@ -534,7 +534,7 @@ base = alloc_streaming_cluster(iommu, npages); if (base == NULL) goto bad; - dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << PAGE_SHIFT); + dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << IO_PAGE_SHIFT); /* Step 3: Normalize DMA addresses. */ used = nelems; @@ -591,16 +591,16 @@ iommu = pcp->pbm->iommu; strbuf = &pcp->pbm->stc; - bus_addr = sglist->dvma_address & PAGE_MASK; + bus_addr = sglist->dvma_address & IO_PAGE_MASK; for (i = 1; i < nelems; i++) if (sglist[i].dvma_length == 0) break; i--; - npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT; + npages = (IO_PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> IO_PAGE_SHIFT; base = iommu->page_table + - ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU if (iopte_val(*base) == IOPTE_INVALID) @@ -629,7 +629,7 @@ pci_iommu_write(flushreg, ctx); } while(((long)pci_iommu_read(matchreg)) < 0L); } else { - for (i = 0; i < npages; i++, vaddr += PAGE_SIZE) + for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, vaddr); } @@ -667,9 +667,9 @@ spin_lock_irqsave(&iommu->lock, flags); - npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK); - npages >>= PAGE_SHIFT; - bus_addr &= PAGE_MASK; + npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); + npages >>= IO_PAGE_SHIFT; + bus_addr &= IO_PAGE_MASK; /* Step 1: Record the context, if any. */ ctx = 0; @@ -678,7 +678,7 @@ iopte_t *iopte; iopte = iommu->page_table + - ((bus_addr - iommu->page_table_map_base)>>PAGE_SHIFT); + ((bus_addr - iommu->page_table_map_base)>>IO_PAGE_SHIFT); ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; } @@ -696,7 +696,7 @@ } else { unsigned long i; - for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) + for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, bus_addr); } @@ -735,7 +735,7 @@ iopte_t *iopte; iopte = iommu->page_table + - ((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT); + ((sglist[0].dvma_address - iommu->page_table_map_base) >> IO_PAGE_SHIFT); ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; } @@ -754,14 +754,14 @@ unsigned long i, npages; u32 bus_addr; - bus_addr = sglist[0].dvma_address & PAGE_MASK; + bus_addr = sglist[0].dvma_address & IO_PAGE_MASK; for(i = 1; i < nelems; i++) if (!sglist[i].dvma_length) break; i--; - npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT; - for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) + npages = (IO_PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> IO_PAGE_SHIFT; + for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, bus_addr); } diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c --- v2.4.9/linux/arch/sparc64/kernel/pci_psycho.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/pci_psycho.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.27 2001/08/12 13:18:23 davem Exp $ +/* $Id: pci_psycho.c,v 1.28 2001/08/24 19:36:58 kanoj Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -18,6 +18,7 @@ #include #include "pci_impl.h" +#include "iommu_common.h" /* All PSYCHO registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter @@ -715,12 +716,12 @@ ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), - (tag & PSYCHO_IOMMU_TAG_VPAGE) << PAGE_SHIFT); + (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); printk("PSYCHO%d: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", p->index, i, ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), - (data & PSYCHO_IOMMU_DATA_PPAGE) << PAGE_SHIFT); + (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); } } __psycho_check_stc_error(p, afsr, afar, type); @@ -1322,7 +1323,7 @@ * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. */ - tsbbase = __get_free_pages(GFP_KERNEL, 7); + tsbbase = __get_free_pages(GFP_KERNEL, get_order(IO_TSB_SIZE)); if (!tsbbase) { prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n"); prom_halt(); @@ -1331,7 +1332,7 @@ iommu->page_table_sz_bits = 17; iommu->page_table_map_base = 0xc0000000; iommu->dma_addr_mask = 0xffffffff; - memset((char *)tsbbase, 0, PAGE_SIZE << 7); + memset((char *)tsbbase, 0, IO_TSB_SIZE); /* We start with no consistent mappings. */ iommu->lowest_consistent_map = diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c --- v2.4.9/linux/arch/sparc64/kernel/pci_sabre.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/pci_sabre.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.38 2001/08/12 13:18:23 davem Exp $ +/* $Id: pci_sabre.c,v 1.39 2001/08/24 19:36:58 kanoj Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -19,6 +19,7 @@ #include #include "pci_impl.h" +#include "iommu_common.h" /* All SABRE registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter @@ -759,13 +760,13 @@ p->index, i, tag, type_string, ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), - ((tag & SABRE_IOMMUTAG_VPN) << PAGE_SHIFT)); + ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); printk("SABRE%d: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", p->index, i, data, ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), - ((data & SABRE_IOMMUDATA_PPN) << PAGE_SHIFT)); + ((data & SABRE_IOMMUDATA_PPN) << IOMMU_PAGE_SHIFT)); } } spin_unlock_irqrestore(&iommu->lock, flags); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c --- v2.4.9/linux/arch/sparc64/kernel/pci_schizo.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/pci_schizo.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_schizo.c,v 1.20 2001/08/12 13:18:23 davem Exp $ +/* $Id: pci_schizo.c,v 1.21 2001/08/24 19:36:58 kanoj Exp $ * pci_schizo.c: SCHIZO specific PCI controller support. * * Copyright (C) 2001 David S. Miller (davem@redhat.com) @@ -16,6 +16,7 @@ #include #include "pci_impl.h" +#include "iommu_common.h" /* All SCHIZO registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter @@ -659,12 +660,12 @@ ((tag & SCHIZO_IOMMU_TAG_WRITE) ? 1 : 0), ((tag & SCHIZO_IOMMU_TAG_STREAM) ? 1 : 0), ((tag & SCHIZO_IOMMU_TAG_SIZE) ? 64 : 8), - (tag & SCHIZO_IOMMU_TAG_VPAGE) << PAGE_SHIFT); + (tag & SCHIZO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); printk("SCHIZO%d: PBM-%c IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", p->index, pbm_name, i, ((data & SCHIZO_IOMMU_DATA_VALID) ? 1 : 0), ((data & SCHIZO_IOMMU_DATA_CACHE) ? 1 : 0), - (data & SCHIZO_IOMMU_DATA_PPAGE) << PAGE_SHIFT); + (data & SCHIZO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); } } __schizo_check_stc_error_pbm(pbm, type); @@ -1639,7 +1640,7 @@ * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. */ - tsbbase = __get_free_pages(GFP_KERNEL, 7); + tsbbase = __get_free_pages(GFP_KERNEL, get_order(IO_TSB_SIZE)); if (!tsbbase) { prom_printf("SCHIZO_IOMMU: Error, gfp(tsb) failed.\n"); prom_halt(); @@ -1648,7 +1649,7 @@ iommu->page_table_sz_bits = 17; iommu->page_table_map_base = 0xc0000000; iommu->dma_addr_mask = 0xffffffff; - memset((char *)tsbbase, 0, PAGE_SIZE << 7); + memset((char *)tsbbase, 0, IO_TSB_SIZE); /* We start with no consistent mappings. */ iommu->lowest_consistent_map = diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c --- v2.4.9/linux/arch/sparc64/kernel/sbus.c Thu May 24 15:00:58 2001 +++ linux/arch/sparc64/kernel/sbus.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.14 2001/05/23 03:06:51 davem Exp $ +/* $Id: sbus.c,v 1.16 2001/08/24 19:36:58 kanoj Exp $ * sbus.c: UltraSparc SBUS controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -37,7 +37,7 @@ #define ONE_GIG (1UL * 1024UL * 1024UL * 1024UL) #define CLUSTER_SIZE (ONE_GIG / NCLUSTERS) #define CLUSTER_MASK (CLUSTER_SIZE - 1) -#define CLUSTER_NPAGES (CLUSTER_SIZE >> PAGE_SHIFT) +#define CLUSTER_NPAGES (CLUSTER_SIZE >> IO_PAGE_SHIFT) #define MAP_BASE ((u32)0xc0000000) struct sbus_iommu { @@ -99,7 +99,7 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) { while (npages--) - upa_writeq(base + (npages << PAGE_SHIFT), + upa_writeq(base + (npages << IO_PAGE_SHIFT), iommu->iommu_regs + IOMMU_FLUSH); upa_readq(iommu->sbus_control_reg); } @@ -120,7 +120,7 @@ { iommu->strbuf_flushflag = 0UL; while (npages--) - upa_writeq(base + (npages << PAGE_SHIFT), + upa_writeq(base + (npages << IO_PAGE_SHIFT), iommu->strbuf_regs + STRBUF_PFLUSH); /* Whoopee cushion! */ @@ -191,8 +191,8 @@ cnum = 0; while ((1UL << cnum) < npages) cnum++; - ent = (base & CLUSTER_MASK) >> (PAGE_SHIFT + cnum); - iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT); + ent = (base & CLUSTER_MASK) >> (IO_PAGE_SHIFT + cnum); + iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); iopte_val(*iopte) = 0UL; /* If the global flush might not have caught this entry, @@ -235,7 +235,7 @@ static void free_consistent_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) { - iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT); + iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); if ((iopte - iommu->page_table) == iommu->lowest_consistent_map) { iopte_t *walk = iopte + npages; @@ -266,7 +266,7 @@ if (size <= 0 || sdev == NULL || dvma_addr == NULL) return NULL; - size = PAGE_ALIGN(size); + size = IO_PAGE_ALIGN(size); order = get_order(size); if (order >= 10) return NULL; @@ -278,7 +278,7 @@ iommu = sdev->bus->iommu; spin_lock_irqsave(&iommu->lock, flags); - iopte = alloc_consistent_cluster(iommu, size >> PAGE_SHIFT); + iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT); if (iopte == NULL) { spin_unlock_irqrestore(&iommu->lock, flags); free_pages(first_page, order); @@ -286,15 +286,15 @@ } /* Ok, we're committed at this point. */ - *dvma_addr = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); + *dvma_addr = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); ret = (void *) first_page; - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; while (npages--) { *iopte++ = __iopte(IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | (__pa(first_page) & IOPTE_PAGE)); - first_page += PAGE_SIZE; + first_page += IO_PAGE_SIZE; } - iommu_flush(iommu, *dvma_addr, size >> PAGE_SHIFT); + iommu_flush(iommu, *dvma_addr, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); return ret; @@ -308,7 +308,7 @@ if (size <= 0 || sdev == NULL || cpu == NULL) return; - npages = PAGE_ALIGN(size) >> PAGE_SHIFT; + npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; iommu = sdev->bus->iommu; spin_lock_irq(&iommu->lock); @@ -333,25 +333,25 @@ BUG(); pbase = (unsigned long) ptr; - offset = (u32) (pbase & ~PAGE_MASK); - size = (PAGE_ALIGN(pbase + size) - (pbase & PAGE_MASK)); - pbase = (unsigned long) __pa(pbase & PAGE_MASK); + offset = (u32) (pbase & ~IO_PAGE_MASK); + size = (IO_PAGE_ALIGN(pbase + size) - (pbase & IO_PAGE_MASK)); + pbase = (unsigned long) __pa(pbase & IO_PAGE_MASK); spin_lock_irqsave(&iommu->lock, flags); - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; iopte = alloc_streaming_cluster(iommu, npages); if (iopte == NULL) goto bad; - dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); - npages = size >> PAGE_SHIFT; + dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); + npages = size >> IO_PAGE_SHIFT; iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; if (dir != SBUS_DMA_TODEVICE) iopte_bits |= IOPTE_WRITE; while (npages--) { *iopte++ = __iopte(iopte_bits | (pbase & IOPTE_PAGE)); - pbase += PAGE_SIZE; + pbase += IO_PAGE_SIZE; } - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; spin_unlock_irqrestore(&iommu->lock, flags); return (dma_base | offset); @@ -365,14 +365,14 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, int direction) { struct sbus_iommu *iommu = sdev->bus->iommu; - u32 dma_base = dma_addr & PAGE_MASK; + u32 dma_base = dma_addr & IO_PAGE_MASK; unsigned long flags; - size = (PAGE_ALIGN(dma_addr + size) - dma_base); + size = (IO_PAGE_ALIGN(dma_addr + size) - dma_base); spin_lock_irqsave(&iommu->lock, flags); - free_streaming_cluster(iommu, dma_base, size >> PAGE_SHIFT); - strbuf_flush(iommu, dma_base, size >> PAGE_SHIFT); + free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); + strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -385,9 +385,9 @@ unsigned long pteval = ~0UL; u32 dma_npages; - dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) + + dma_npages = ((dma_sg->dvma_address & (IO_PAGE_SIZE - 1UL)) + dma_sg->dvma_length + - ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT; + ((u32)(IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT; do { unsigned long offset; signed int len; @@ -402,15 +402,15 @@ tmp = (unsigned long) __pa(sg->address); len = sg->length; - if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) { - pteval = tmp & PAGE_MASK; - offset = tmp & (PAGE_SIZE - 1UL); + if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { + pteval = tmp & IO_PAGE_MASK; + offset = tmp & (IO_PAGE_SIZE - 1UL); break; } - if (((tmp ^ (tmp + len - 1UL)) >> PAGE_SHIFT) != 0UL) { - pteval = (tmp + PAGE_SIZE) & PAGE_MASK; + if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) { + pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK; offset = 0UL; - len -= (PAGE_SIZE - (tmp & (PAGE_SIZE - 1UL))); + len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); break; } sg++; @@ -419,8 +419,8 @@ pteval = ((pteval & IOPTE_PAGE) | iopte_bits); while (len > 0) { *iopte++ = __iopte(pteval); - pteval += PAGE_SIZE; - len -= (PAGE_SIZE - offset); + pteval += IO_PAGE_SIZE; + len -= (IO_PAGE_SIZE - offset); offset = 0; dma_npages--; } @@ -432,14 +432,14 @@ * adjusting pteval along the way. Stop when we * detect a page crossing event. */ - while ((pteval << (64 - PAGE_SHIFT)) != 0UL && + while ((pteval << (64 - IO_PAGE_SHIFT)) != 0UL && pteval == __pa(sg->address) && ((pteval ^ - (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { + (__pa(sg->address) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { pteval += sg->length; sg++; } - if ((pteval << (64 - PAGE_SHIFT)) == 0UL) + if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) pteval = ~0UL; } while (dma_npages != 0); dma_sg++; @@ -472,7 +472,7 @@ iopte = alloc_streaming_cluster(iommu, npages); if (iopte == NULL) goto bad; - dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); + dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); /* Normalize DVMA addresses. */ sgtmp = sg; @@ -516,18 +516,18 @@ return; } - dvma_base = sg[0].dvma_address & PAGE_MASK; + dvma_base = sg[0].dvma_address & IO_PAGE_MASK; for (i = 0; i < nents; i++) { if (sg[i].dvma_length == 0) break; } i--; - size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - dvma_base; + size = IO_PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - dvma_base; iommu = sdev->bus->iommu; spin_lock_irqsave(&iommu->lock, flags); - free_streaming_cluster(iommu, dvma_base, size >> PAGE_SHIFT); - strbuf_flush(iommu, dvma_base, size >> PAGE_SHIFT); + free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); + strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -536,10 +536,10 @@ struct sbus_iommu *iommu = sdev->bus->iommu; unsigned long flags; - size = (PAGE_ALIGN(base + size) - (base & PAGE_MASK)); + size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); spin_lock_irqsave(&iommu->lock, flags); - strbuf_flush(iommu, base & PAGE_MASK, size >> PAGE_SHIFT); + strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -550,16 +550,16 @@ u32 base; int i; - base = sg[0].dvma_address & PAGE_MASK; + base = sg[0].dvma_address & IO_PAGE_MASK; for (i = 0; i < nents; i++) { if (sg[i].dvma_length == 0) break; } i--; - size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - base; + size = IO_PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - base; spin_lock_irqsave(&iommu->lock, flags); - strbuf_flush(iommu, base, size >> PAGE_SHIFT); + strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -1123,14 +1123,14 @@ * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. */ - tsb_base = __get_free_pages(GFP_ATOMIC, 7); + tsb_base = __get_free_pages(GFP_ATOMIC, get_order(IO_TSB_SIZE)); if (tsb_base == 0UL) { prom_printf("sbus_iommu_init: Fatal error, cannot alloc TSB table.\n"); prom_halt(); } iommu->page_table = (iopte_t *) tsb_base; - memset(iommu->page_table, 0, (PAGE_SIZE << 7)); + memset(iommu->page_table, 0, IO_TSB_SIZE); upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.4.9/linux/arch/sparc64/kernel/smp.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/smp.c Tue Aug 28 07:09:44 2001 @@ -702,7 +702,7 @@ int cpu = smp_processor_id(); start &= PAGE_MASK; - end &= PAGE_MASK; + end = PAGE_ALIGN(end); if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { mm->cpu_vm_mask = (1UL << cpu); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.4.9/linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Fri Sep 7 11:01:20 2001 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.108 2001/06/05 03:39:50 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.111 2001/08/30 03:22:00 kanoj Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -163,7 +163,9 @@ /* Atomic counter implementation. */ EXPORT_SYMBOL(__atomic_add); EXPORT_SYMBOL(__atomic_sub); +#ifdef CONFIG_SMP EXPORT_SYMBOL(atomic_dec_and_lock); +#endif /* Atomic bit operations. */ EXPORT_SYMBOL(___test_and_set_bit); @@ -206,7 +208,6 @@ EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(isa_chain); EXPORT_SYMBOL(pci_memspace_mask); -EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(outsb); EXPORT_SYMBOL(outsw); EXPORT_SYMBOL(outsl); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S --- v2.4.9/linux/arch/sparc64/lib/blockops.S Thu Apr 12 12:10:25 2001 +++ linux/arch/sparc64/lib/blockops.S Fri Sep 7 11:01:20 2001 @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.31 2001/04/05 11:08:12 davem Exp $ +/* $Id: blockops.S,v 1.34 2001/09/03 01:34:18 kanoj Exp $ * blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com) diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.4.9/linux/arch/sparc64/mm/fault.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/mm/fault.c Fri Sep 7 11:01:20 2001 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.55 2001/08/09 20:18:43 davem Exp $ +/* $Id: fault.c,v 1.58 2001/09/01 00:11:16 kanoj Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -22,11 +22,58 @@ #include #include #include +#include +#include #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0])) extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; +/* + * To debug kernel during syscall entry. + */ +void syscall_trace_entry(struct pt_regs *regs) +{ + printk("scall entry: %s[%d]/cpu%d: %d\n", current->comm, current->pid, smp_processor_id(), (int) regs->u_regs[UREG_G1]); +} + +/* + * To debug kernel during syscall exit. + */ +void syscall_trace_exit(struct pt_regs *regs) +{ + printk("scall exit: %s[%d]/cpu%d: %d\n", current->comm, current->pid, smp_processor_id(), (int) regs->u_regs[UREG_G1]); +} + +/* + * To debug kernel to catch accesses to certain virtual/physical addresses. + * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. + * flags = VM_READ watches memread accesses, flags = VM_WRITE watches memwrite accesses. + * Caller passes in a 64bit aligned addr, with mask set to the bytes that need to be + * watched. This is only useful on a single cpu machine for now. After the watchpoint + * is detected, the process causing it will be killed, thus preventing an infinite loop. + */ +void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode) +{ + unsigned long lsubits = LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM; + + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (addr), "r" (mode ? VIRT_WATCHPOINT : PHYS_WATCHPOINT), + "i" (ASI_DMMU)); + lsubits |= ((unsigned long)mask << (mode ? 25 : 33)); + if (flags & VM_READ) + lsubits |= (mode ? LSU_CONTROL_VR : LSU_CONTROL_PR); + if (flags & VM_WRITE) + lsubits |= (mode ? LSU_CONTROL_VW : LSU_CONTROL_PW); + __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (lsubits), "i" (ASI_LSU_CONTROL) + : "memory"); +} + /* Nice, simple, prom library does all the sweating for us. ;) */ unsigned long __init prom_probe_memory (void) { @@ -170,7 +217,7 @@ unsigned long g2; unsigned char asi = ASI_P; - if (!insn) + if ((!insn) && (regs->tstate & TSTATE_PRIV)) goto cannot_handle; /* If user insn could be read (thus insn is zero), that diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.4.9/linux/arch/sparc64/mm/init.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/mm/init.c Fri Sep 7 11:01:20 2001 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.179 2001/08/08 07:52:00 davem Exp $ +/* $Id: init.c,v 1.189 2001/09/02 23:27:18 kanoj Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -55,6 +54,8 @@ extern unsigned int sparc_ramdisk_image; extern unsigned int sparc_ramdisk_size; +struct page *mem_map_zero; + int do_check_pgt_cache(int low, int high) { int freed = 0; @@ -130,28 +131,6 @@ } } -/* - * BAD_PAGE is the page that is used for page faults when linux - * is out-of-memory. Older versions of linux just did a - * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving an inode - * unused etc.. - * - * BAD_PAGETABLE is the accompanying page-table: it is initialized - * to point to BAD_PAGE entries. - * - * ZERO_PAGE is a special page that is used for zero-initialized - * data and COW. - */ -pte_t __bad_page(void) -{ - memset((void *) &empty_bad_page, 0, PAGE_SIZE); - return pte_mkdirty(mk_pte_phys((((unsigned long) &empty_bad_page) - - ((unsigned long)&empty_zero_page) - + phys_base), - PAGE_SHARED)); -} - void show_mem(void) { printk("Mem-info:\n"); @@ -202,10 +181,10 @@ struct linux_prom_translation *trans; unsigned long phys_page, tte_vaddr, tte_data; void (*remap_func)(unsigned long, unsigned long, int); - pgd_t *pgdp; - pmd_t *pmdp; + pmd_t *pmdp, *pmd; pte_t *ptep; int node, n, i, tsz; + extern unsigned int obp_iaddr_patch[2], obp_daddr_patch[2]; node = prom_finddevice("/virtual-memory"); n = prom_getproplen(node, "translations"); @@ -229,36 +208,39 @@ } n = n / sizeof(*trans); + /* + * The obp translations are saved based on 8k pagesize, since obp can use + * a mixture of pagesizes. Misses to the 0xf0000000 - 0x100000000, ie obp + * range, are handled in entry.S and do not use the vpte scheme (see rant + * in inherit_locked_prom_mappings()). + */ +#define OBP_PMD_SIZE 2048 +#define BASE_PAGE_SIZE 8192 + pmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, 0UL); + if (pmd == NULL) + early_pgtable_allocfail("pmd"); + memset(pmd, 0, OBP_PMD_SIZE); for (i = 0; i < n; i++) { unsigned long vaddr; if (trans[i].virt >= 0xf0000000 && trans[i].virt < 0x100000000) { for (vaddr = trans[i].virt; vaddr < trans[i].virt + trans[i].size; - vaddr += PAGE_SIZE) { + vaddr += BASE_PAGE_SIZE) { unsigned long val; - pgdp = pgd_offset(&init_mm, vaddr); - if (pgd_none(*pgdp)) { - pmdp = __alloc_bootmem(PMD_TABLE_SIZE, - PMD_TABLE_SIZE, - 0UL); - if (pmdp == NULL) - early_pgtable_allocfail("pmd"); - memset(pmdp, 0, PMD_TABLE_SIZE); - pgd_set(pgdp, pmdp); - } - pmdp = pmd_offset(pgdp, vaddr); + pmdp = pmd + ((vaddr >> 23) & 0x7ff); if (pmd_none(*pmdp)) { - ptep = __alloc_bootmem(PTE_TABLE_SIZE, - PTE_TABLE_SIZE, + ptep = __alloc_bootmem(BASE_PAGE_SIZE, + BASE_PAGE_SIZE, 0UL); if (ptep == NULL) early_pgtable_allocfail("pte"); - memset(ptep, 0, PTE_TABLE_SIZE); + memset(ptep, 0, BASE_PAGE_SIZE); pmd_set(pmdp, ptep); } - ptep = pte_offset(pmdp, vaddr); + ptep = (pte_t *)pmd_page(*pmdp) + + ((vaddr >> 13) & 0x3ff); val = trans[i].data; @@ -267,10 +249,17 @@ val &= ~0x0003fe0000000000UL; set_pte (ptep, __pte(val | _PAGE_MODIFIED)); - trans[i].data += PAGE_SIZE; + trans[i].data += BASE_PAGE_SIZE; } } } + phys_page = __pa(pmd); + obp_iaddr_patch[0] |= (phys_page >> 10); + obp_iaddr_patch[1] |= (phys_page & 0x3ff); + flushi((long)&obp_iaddr_patch[0]); + obp_daddr_patch[0] |= (phys_page >> 10); + obp_daddr_patch[1] |= (phys_page & 0x3ff); + flushi((long)&obp_daddr_patch[0]); /* Now fixup OBP's idea about where we really are mapped. */ prom_printf("Remapping the kernel... "); @@ -295,7 +284,7 @@ phys_page &= _PAGE_PADDR; phys_page += ((unsigned long)&prom_boot_page - - (unsigned long)&empty_zero_page); + (unsigned long)KERNBASE); if (tlb_type == spitfire) { /* Lock this into i/d tlb entry 59 */ @@ -336,7 +325,7 @@ BUG(); } - tte_vaddr = (unsigned long) &empty_zero_page; + tte_vaddr = (unsigned long) KERNBASE; /* Spitfire Errata #32 workaround */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" @@ -366,7 +355,7 @@ remap_func((tlb_type == spitfire ? (spitfire_get_dtlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR) : (cheetah_get_litlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR)), - (unsigned long) &empty_zero_page, + (unsigned long) KERNBASE, prom_get_mmu_ihandle()); /* Flush out that temporary mapping. */ @@ -389,7 +378,7 @@ unsigned long size = trans[i].size; if (vaddr < 0xf0000000UL) { - unsigned long avoid_start = (unsigned long) &empty_zero_page; + unsigned long avoid_start = (unsigned long) KERNBASE; unsigned long avoid_end = avoid_start + (4 * 1024 * 1024); if (vaddr < avoid_start) { @@ -1048,7 +1037,7 @@ * 4MB locked TLB translation. */ start_pfn = PAGE_ALIGN((unsigned long) &_end) - - ((unsigned long) &empty_zero_page); + ((unsigned long) KERNBASE); /* Adjust up to the physical address where the kernel begins. */ start_pfn += phys_base; @@ -1133,7 +1122,7 @@ unsigned long alias_base = phys_base + PAGE_OFFSET; unsigned long second_alias_page = 0; unsigned long pt, flags, end_pfn, pages_avail; - unsigned long shift = alias_base - ((unsigned long)&empty_zero_page); + unsigned long shift = alias_base - ((unsigned long)KERNBASE); unsigned long real_end; set_bit(0, mmu_context_bmap); @@ -1429,7 +1418,7 @@ addr = PAGE_OFFSET + phys_base; last = PAGE_ALIGN((unsigned long)&_end) - - ((unsigned long) &empty_zero_page); + ((unsigned long) KERNBASE); last += PAGE_OFFSET + phys_base; while (addr < last) { set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap); @@ -1441,7 +1430,20 @@ max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT); high_memory = __va(last_valid_pfn << PAGE_SHIFT); - num_physpages = free_all_bootmem(); + num_physpages = free_all_bootmem() - 1; + + /* + * Set up the zero page, mark it reserved, so that page count + * is not manipulated when freeing the page from user ptes. + */ + mem_map_zero = _alloc_pages(GFP_KERNEL, 0); + if (mem_map_zero == NULL) { + prom_printf("paging_init: Cannot alloc zero page.\n"); + prom_halt(); + } + SetPageReserved(mem_map_zero); + clear_page(page_address(mem_map_zero)); + codepages = (((unsigned long) &etext) - ((unsigned long)&_start)); codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; datapages = (((unsigned long) &edata) - ((unsigned long)&etext)); @@ -1455,7 +1457,7 @@ extern pgd_t empty_pg_dir[1024]; unsigned long addr = (unsigned long)empty_pg_dir; unsigned long alias_base = phys_base + PAGE_OFFSET - - (long)(&empty_zero_page); + (long)(KERNBASE); memset(empty_pg_dir, 0, sizeof(empty_pg_dir)); addr += alias_base; @@ -1477,16 +1479,20 @@ void free_initmem (void) { - unsigned long addr; + unsigned long addr, initend; - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + /* + * The init section is aligned to 8k in vmlinux.lds. Page align for >8k pagesizes. + */ + addr = PAGE_ALIGN((unsigned long)(&__init_begin)); + initend = (unsigned long)(&__init_end) & PAGE_MASK; + for (; addr < initend; addr += PAGE_SIZE) { unsigned long page; struct page *p; page = (addr + ((unsigned long) __va(phys_base)) - - ((unsigned long) &empty_zero_page)); + ((unsigned long) KERNBASE)); p = virt_to_page(page); ClearPageReserved(p); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/mm/modutil.c linux/arch/sparc64/mm/modutil.c --- v2.4.9/linux/arch/sparc64/mm/modutil.c Thu Apr 12 12:10:25 2001 +++ linux/arch/sparc64/mm/modutil.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: modutil.c,v 1.8 2001/04/04 00:49:39 davem Exp $ +/* $Id: modutil.c,v 1.9 2001/08/14 22:10:56 davem Exp $ * arch/sparc64/mm/modutil.c * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -10,7 +10,10 @@ #include #include -#include + +#define MODULES_VADDR 0x0000000001000000ULL /* Where to map modules */ +#define MODULES_LEN 0x000000007f000000ULL +#define MODULES_END 0x0000000080000000ULL static struct vm_struct * modvmlist = NULL; diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.4.9/linux/arch/sparc64/mm/ultra.S Sun Mar 25 18:14:21 2001 +++ linux/arch/sparc64/mm/ultra.S Fri Sep 7 11:01:20 2001 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.54 2001/03/22 07:26:04 davem Exp $ +/* $Id: ultra.S,v 1.56 2001/08/30 10:10:32 davem Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com) @@ -302,7 +302,7 @@ nop flush_dcpage_cheetah: - sethi %hi(8192), %o4 + sethi %hi(PAGE_SIZE), %o4 1: subcc %o4, (1 << 5), %o4 stxa %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE membar #Sync @@ -440,13 +440,13 @@ retry xcall_flush_tlb_range: - sethi %hi(8192 - 1), %g2 - or %g2, %lo(8192 - 1), %g2 + sethi %hi(PAGE_SIZE - 1), %g2 + or %g2, %lo(PAGE_SIZE - 1), %g2 andn %g1, %g2, %g1 andn %g7, %g2, %g7 sub %g7, %g1, %g3 add %g2, 1, %g2 - srlx %g3, 13, %g4 + srlx %g3, PAGE_SHIFT, %g4 cmp %g4, 96 bgu,pn %icc, xcall_flush_tlb_mm diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds --- v2.4.9/linux/arch/sparc64/vmlinux.lds Tue Jul 3 17:08:19 2001 +++ linux/arch/sparc64/vmlinux.lds Fri Sep 7 11:01:20 2001 @@ -5,7 +5,6 @@ SECTIONS { - empty_zero_page = 0x0000000000400000; swapper_pmd_dir = 0x0000000000402000; empty_pg_dir = 0x0000000000403000; . = 0x4000; diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/block/mfmhd.c linux/drivers/acorn/block/mfmhd.c --- v2.4.9/linux/drivers/acorn/block/mfmhd.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/acorn/block/mfmhd.c Sat Sep 8 12:02:32 2001 @@ -1450,10 +1450,7 @@ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB?) read ahread */ -#ifndef MODULE - mfm_gendisk.next = gendisk_head; - gendisk_head = &mfm_gendisk; -#endif + add_gendisk(&mfm_gendisk); Busy = 0; lastspecifieddrive = -1; @@ -1512,6 +1509,7 @@ outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */ free_irq(mfm_irq, NULL); unregister_blkdev(MAJOR_NR, "mfm"); + del_gendisk(&mfm_gendisk); if (ecs) ecard_release(ecs); if (mfm_addr) diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/Makefile linux/drivers/acpi/Makefile --- v2.4.9/linux/drivers/acpi/Makefile Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/Makefile Sat Sep 8 12:26:47 2001 @@ -38,9 +38,8 @@ obj-$(CONFIG_ACPI) += $(foreach dir,$(acpi-subdirs),$(dir)/$(dir).o) ifdef CONFIG_ACPI_KERNEL_CONFIG obj-$(CONFIG_ACPI) += acpiconf.o osconf.o -else - obj-$(CONFIG_ACPI) += driver.o endif +obj-$(CONFIG_ACPI) += driver.o ifeq ($(CONFIG_ACPI_BUSMGR),y) obj-y += ospm/ospm.o diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/include/platform/acgcc.h linux/drivers/acpi/include/platform/acgcc.h --- v2.4.9/linux/drivers/acpi/include/platform/acgcc.h Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/include/platform/acgcc.h Sat Sep 1 11:01:28 2001 @@ -39,7 +39,6 @@ #define BREAKPOINT3 #define disable() __cli() #define enable() __sti() -#define wbinvd() /*! [Begin] no source code translation */ @@ -101,7 +100,6 @@ #define disable() __cli() #define enable() __sti() #define halt() __asm__ __volatile__ ("sti; hlt":::"memory") -#define wbinvd() /*! [Begin] no source code translation * diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/ospm/busmgr/Makefile linux/drivers/acpi/ospm/busmgr/Makefile --- v2.4.9/linux/drivers/acpi/ospm/busmgr/Makefile Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/busmgr/Makefile Sun Sep 2 07:48:02 2001 @@ -1,3 +1,5 @@ +export-objs := bm_osl.o + O_TARGET := ospm_$(notdir $(CURDIR)).o obj-m := $(O_TARGET) EXTRA_CFLAGS += $(ACPI_CFLAGS) diff -u --recursive --new-file v2.4.9/linux/drivers/atm/Makefile linux/drivers/atm/Makefile --- v2.4.9/linux/drivers/atm/Makefile Mon Mar 26 15:36:30 2001 +++ linux/drivers/atm/Makefile Mon Aug 27 09:01:33 2001 @@ -25,6 +25,7 @@ obj-$(CONFIG_ATM_AMBASSADOR) += ambassador.o obj-$(CONFIG_ATM_TCP) += atmtcp.o obj-$(CONFIG_ATM_IA) += iphase.o suni.o +obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o ifeq ($(CONFIG_ATM_FORE200E_PCA),y) FORE200E_FW_OBJS += fore200e_pca_fw.o diff -u --recursive --new-file v2.4.9/linux/drivers/atm/firestream.h linux/drivers/atm/firestream.h --- v2.4.9/linux/drivers/atm/firestream.h Wed Apr 11 19:02:30 2001 +++ linux/drivers/atm/firestream.h Sat Sep 8 12:28:14 2001 @@ -345,18 +345,28 @@ #define CELLOSCONF_COST (0x1 << 0) /* Bits? */ - #define RAS0 0x1bc #define RAS0_DCD_XHLT (0x1 << 31) #define RAS0_VPSEL (0x1 << 16) #define RAS0_VCSEL (0x1 << 0) +#define RAS1 0x1c0 +#define RAS1_UTREG (0x1 << 5) + #define DMAMR 0x1cc #define DMAMR_TX_MODE_FULL (0x0 << 0) #define DMAMR_TX_MODE_PART (0x1 << 0) #define DMAMR_TX_MODE_NONE (0x2 << 0) /* And 3 */ + + + +#define RAS2 0x280 + +#define RAS2_NNI (0x1 << 0) +#define RAS2_USEL (0x1 << 1) +#define RAS2_UBS (0x1 << 2) diff -u --recursive --new-file v2.4.9/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c --- v2.4.9/linux/drivers/block/DAC960.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/block/DAC960.c Sat Sep 8 12:02:32 2001 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1937,13 +1938,7 @@ /* Install the Generic Disk Information structure at the end of the list. */ - if ((GenericDiskInfo = gendisk_head) != NULL) - { - while (GenericDiskInfo->next != NULL) - GenericDiskInfo = GenericDiskInfo->next; - GenericDiskInfo->next = &Controller->GenericDiskInfo; - } - else gendisk_head = &Controller->GenericDiskInfo; + add_gendisk(&Controller->GenericDiskInfo); /* Indicate the Block Device Registration completed successfully, */ @@ -1979,16 +1974,7 @@ /* Remove the Generic Disk Information structure from the list. */ - if (gendisk_head != &Controller->GenericDiskInfo) - { - GenericDiskInfo_T *GenericDiskInfo = gendisk_head; - while (GenericDiskInfo != NULL && - GenericDiskInfo->next != &Controller->GenericDiskInfo) - GenericDiskInfo = GenericDiskInfo->next; - if (GenericDiskInfo != NULL) - GenericDiskInfo->next = GenericDiskInfo->next->next; - } - else gendisk_head = Controller->GenericDiskInfo.next; + del_gendisk(&Controller->GenericDiskInfo); } @@ -5094,21 +5080,12 @@ .nr_sects, (long *) Argument); case BLKRAGET: - /* Get Read-Ahead. */ - if ((long *) Argument == NULL) return -EINVAL; - return put_user(read_ahead[MAJOR(Inode->i_rdev)], (long *) Argument); case BLKRASET: - /* Set Read-Ahead. */ - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (Argument > 256) return -EINVAL; - read_ahead[MAJOR(Inode->i_rdev)] = Argument; - return 0; case BLKFLSBUF: - /* Flush Buffers. */ - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - fsync_dev(Inode->i_rdev); - invalidate_buffers(Inode->i_rdev); - return 0; + case BLKBSZGET: + case BLKBSZSET: + return blk_ioctl (Inode->i_rdev, Request, Argument); + case BLKRRPART: /* Re-Read Partition Table. */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; diff -u --recursive --new-file v2.4.9/linux/drivers/block/acsi.c linux/drivers/block/acsi.c --- v2.4.9/linux/drivers/block/acsi.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/block/acsi.c Sat Sep 8 12:02:32 2001 @@ -1792,8 +1792,7 @@ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ - acsi_gendisk.next = gendisk_head; - gendisk_head = &acsi_gendisk; + add_gendisk(&acsi_gendisk); #ifdef CONFIG_ATARI_SLM err = slm_init(); @@ -1817,8 +1816,6 @@ void cleanup_module(void) { - struct gendisk ** gdp; - del_timer( &acsi_timer ); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); atari_stram_free( acsi_buffer ); @@ -1826,13 +1823,7 @@ if (devfs_unregister_blkdev( MAJOR_NR, "ad" ) != 0) printk( KERN_ERR "acsi: cleanup_module failed\n"); - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) - if (*gdp == &acsi_gendisk) - break; - if (!*gdp) - printk( KERN_ERR "acsi: entry in disk chain missing!\n" ); - else - *gdp = (*gdp)->next; + del_gendisk(&acsi_gendisk); } #endif diff -u --recursive --new-file v2.4.9/linux/drivers/block/blkpg.c linux/drivers/block/blkpg.c --- v2.4.9/linux/drivers/block/blkpg.c Sun May 20 11:34:05 2001 +++ linux/drivers/block/blkpg.c Sat Sep 8 12:02:32 2001 @@ -54,17 +54,6 @@ * Note that several drives may have the same major. */ -/* a linear search, superfluous when dev is a pointer */ -static struct gendisk *get_gendisk(kdev_t dev) { - struct gendisk *g; - int m = MAJOR(dev); - - for (g = gendisk_head; g; g = g->next) - if (g->major == m) - break; - return g; -} - /* * Add a partition. * @@ -273,6 +262,29 @@ case BLKELVSET: return blkelvset_ioctl(&blk_get_queue(dev)->elevator, (blkelv_ioctl_arg_t *) arg); + + case BLKBSZGET: + /* get the logical block size (cf. BLKSSZGET) */ + intval = BLOCK_SIZE; + if (blksize_size[MAJOR(dev)]) + intval = blksize_size[MAJOR(dev)][MINOR(dev)]; + return put_user (intval, (int *) arg); + + case BLKBSZSET: + /* set the logical block size */ + if (!capable (CAP_SYS_ADMIN)) + return -EACCES; + if (!dev || !arg) + return -EINVAL; + if (get_user (intval, (int *) arg)) + return -EFAULT; + if (intval > PAGE_SIZE || intval < 512 || + (intval & (intval - 1))) + return -EINVAL; + if (is_mounted (dev) || is_swap_partition (dev)) + return -EBUSY; + set_blocksize (dev, intval); + return 0; default: return -EINVAL; diff -u --recursive --new-file v2.4.9/linux/drivers/block/cciss.c linux/drivers/block/cciss.c --- v2.4.9/linux/drivers/block/cciss.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/block/cciss.c Sat Sep 8 12:02:32 2001 @@ -406,6 +406,8 @@ case BLKRRPART: return revalidate_logvol(inode->i_rdev, 1); case BLKFLSBUF: + case BLKBSZSET: + case BLKBSZGET: case BLKROSET: case BLKROGET: case BLKRASET: @@ -1963,8 +1965,7 @@ hba[i]->gendisk.nr_real = hba[i]->num_luns; /* Get on the disk list */ - hba[i]->gendisk.next = gendisk_head; - gendisk_head = &(hba[i]->gendisk); + add_gendisk(&(hba[i]->gendisk)); cciss_geninit(i); for(j=0; jdriver_data == NULL) { @@ -2005,19 +2005,8 @@ /* remove it from the disk list */ - if (gendisk_head == &(hba[i]->gendisk)) - { - gendisk_head = hba[i]->gendisk.next; - } else - { - for(g=gendisk_head; g ; g=g->next) - { - if(g->next == &(hba[i]->gendisk)) - { - g->next = hba[i]->gendisk.next; - } - } - } + del_gendisk(&(hba[i]->gendisk)); + pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), diff -u --recursive --new-file v2.4.9/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c --- v2.4.9/linux/drivers/block/cpqarray.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/block/cpqarray.c Sat Sep 8 12:02:32 2001 @@ -311,7 +311,6 @@ void cleanup_module(void) { int i; - struct gendisk *g; char buff[4]; for(i=0; icmd_pool_dhandle); kfree(hba[i]->cmd_pool_bits); - if (gendisk_head == &ida_gendisk[i]) { - gendisk_head = ida_gendisk[i].next; - } else { - for(g=gendisk_head; g; g=g->next) { - if (g->next == &ida_gendisk[i]) { - g->next = ida_gendisk[i].next; - break; - } - } - } + del_gendisk(&ida_gendisk[i]); } remove_proc_entry("cpqarray", proc_root_driver); kfree(ida); @@ -550,8 +540,7 @@ ida_gendisk[i].nr_real = 0; /* Get on the disk list */ - ida_gendisk[i].next = gendisk_head; - gendisk_head = &ida_gendisk[i]; + add_gendisk(&ida_gendisk[i]); init_timer(&hba[i]->timer); hba[i]->timer.expires = jiffies + IDA_TIMER; @@ -1266,6 +1255,8 @@ } case BLKFLSBUF: + case BLKBSZSET: + case BLKBSZGET: case BLKROSET: case BLKROGET: case BLKRASET: diff -u --recursive --new-file v2.4.9/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.4.9/linux/drivers/block/floppy.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/block/floppy.c Fri Sep 7 09:28:38 2001 @@ -124,6 +124,11 @@ * - s/suser/capable/ */ +/* + * 2001/08/26 -- Paul Gortmaker - fix insmod oops on machines with no + * floppy controller (lingering task on list after module is gone... boom.) + */ + #define FLOPPY_SANITY_CHECK #undef FLOPPY_SILENT_DCL_CLEAR @@ -4144,7 +4149,7 @@ return 0; } -static int have_no_fdc= -EIO; +static int have_no_fdc= -ENODEV; int __init floppy_init(void) @@ -4200,7 +4205,6 @@ del_timer(&fd_timeout); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); devfs_unregister_blkdev(MAJOR_NR,"fd"); - del_timer(&fd_timeout); return -EBUSY; } @@ -4259,9 +4263,7 @@ if (have_no_fdc) { DPRINT("no floppy controllers found\n"); - floppy_tq.routine = (void *)(void *) empty; - mark_bh(IMMEDIATE_BH); - schedule(); + run_task_queue(&tq_immediate); if (usage_count) floppy_release_irq_and_dma(); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); @@ -4472,6 +4474,7 @@ MODULE_PARM(FLOPPY_DMA,"i"); MODULE_AUTHOR("Alain L. Knaff"); MODULE_SUPPORTED_DEVICE("fd"); +MODULE_LICENSE("GPL"); #else diff -u --recursive --new-file v2.4.9/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v2.4.9/linux/drivers/block/genhd.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/block/genhd.c Sat Sep 8 12:02:32 2001 @@ -17,6 +17,75 @@ #include #include + +struct gendisk *gendisk_head; + +void +add_gendisk(struct gendisk *gp) +{ + gp->next = gendisk_head; + gendisk_head = gp; +} + +void +del_gendisk(struct gendisk *gp) +{ + struct gendisk **gpp; + + for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next)) + if (*gpp == gp) + break; + if (*gpp) + *gpp = (*gpp)->next; +} + +struct gendisk * +get_gendisk(kdev_t dev) +{ + struct gendisk *gp = NULL; + int maj = MAJOR(dev); + + for (gp = gendisk_head; gp; gp = gp->next) + if (gp->major == maj) + return gp; + return NULL; +} + +#ifdef CONFIG_PROC_FS +int +get_partition_list(char *page, char **start, off_t offset, int count) +{ + struct gendisk *gp; + char buf[64]; + int len, n; + + len = sprintf(page, "major minor #blocks name\n\n"); + for (gp = gendisk_head; gp; gp = gp->next) { + for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) { + if (gp->part[n].nr_sects == 0) + continue; + + len += snprintf(page + len, 63, + "%4d %4d %10d %s\n", + gp->major, n, gp->sizes[n], + disk_name(gp, n, buf)); + if (len < offset) + offset -= len, len = 0; + else if (len >= offset + count) + goto out; + } + } + +out: + *start = page + offset; + len -= offset; + if (len < 0) + len = 0; + return len > count ? count : len; +} +#endif + + extern int blk_dev_init(void); #ifdef CONFIG_BLK_DEV_DAC960 extern void DAC960_Initialize(void); diff -u --recursive --new-file v2.4.9/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.4.9/linux/drivers/block/ll_rw_blk.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/block/ll_rw_blk.c Sat Sep 8 12:00:46 2001 @@ -131,7 +131,7 @@ return max_sectors[MAJOR(dev)][MINOR(dev)]; } -inline request_queue_t *__blk_get_queue(kdev_t dev) +inline request_queue_t *blk_get_queue(kdev_t dev) { struct blk_dev_struct *bdev = blk_dev + MAJOR(dev); @@ -141,22 +141,6 @@ return &blk_dev[MAJOR(dev)].request_queue; } -/* - * NOTE: the device-specific queue() functions - * have to be atomic! - */ -request_queue_t *blk_get_queue(kdev_t dev) -{ - request_queue_t *ret; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock,flags); - ret = __blk_get_queue(dev); - spin_unlock_irqrestore(&io_request_lock,flags); - - return ret; -} - static int __blk_cleanup_queue(struct list_head *head) { struct request *rq; @@ -1272,7 +1256,6 @@ EXPORT_SYMBOL(end_that_request_last); EXPORT_SYMBOL(blk_init_queue); EXPORT_SYMBOL(blk_get_queue); -EXPORT_SYMBOL(__blk_get_queue); EXPORT_SYMBOL(blk_cleanup_queue); EXPORT_SYMBOL(blk_queue_headactive); EXPORT_SYMBOL(blk_queue_make_request); diff -u --recursive --new-file v2.4.9/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.4.9/linux/drivers/block/loop.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/block/loop.c Sat Sep 1 11:01:28 2001 @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -853,6 +854,10 @@ break; } err = put_user(loop_sizes[lo->lo_number] << 1, (long *) arg); + break; + case BLKBSZGET: + case BLKBSZSET: + err = blk_ioctl(inode->i_rdev, cmd, arg); break; default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; diff -u --recursive --new-file v2.4.9/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c --- v2.4.9/linux/drivers/block/paride/pd.c Sat Apr 28 11:27:53 2001 +++ linux/drivers/block/paride/pd.c Sat Sep 8 12:02:32 2001 @@ -455,8 +455,7 @@ pd_gendisk.major = major; pd_gendisk.major_name = name; - pd_gendisk.next = gendisk_head; - gendisk_head = &pd_gendisk; + add_gendisk(&pd_gendisk); for(i=0;inext)) - if (*gdp == &pd_gendisk) break; - if (*gdp) *gdp = (*gdp)->next; - - for (unit=0;unitmode) { @@ -393,33 +376,6 @@ //*************************************************************************** -static u8 ppc6_rd_reg(PPC *ppc, u8 reg) -{ - ppc6_send_cmd(ppc,(u8)(reg | ACCESS_REG | ACCESS_READ)); - - return(ppc6_rd_data_byte(ppc)); -} - -//*************************************************************************** - -static void ppc6_wr_reg(PPC *ppc, u8 reg, u8 data) -{ - ppc6_send_cmd(ppc,(u8)(reg | ACCESS_REG | ACCESS_WRITE)); - - ppc6_wr_data_byte(ppc, data); -} - -//*************************************************************************** - -static u8 ppc6_version(PPC *ppc) -{ - ppc6_send_cmd(ppc,(REG_VERSION | ACCESS_REG | ACCESS_READ)); - - return(ppc6_rd_data_byte(ppc) & 0x3F); -} - -//*************************************************************************** - static void ppc6_rd_data_blk(PPC *ppc, u8 *data, long count) { switch(ppc->mode) @@ -708,44 +664,6 @@ //*************************************************************************** -static u16 ppc6_rd_port16(PPC *ppc, u8 port) -{ - u16 data; - - ppc6_send_cmd(ppc, (CMD_PREFIX_SET | PREFIX_IO16)); - - ppc6_send_cmd(ppc, (u8)(port | ACCESS_PORT | ACCESS_READ)); - - data = ppc6_rd_data_byte(ppc); - - ppc6_send_cmd(ppc, (u8)(port | ACCESS_PORT | ACCESS_READ)); - - data += (u16)ppc6_rd_data_byte(ppc) << 8; - - ppc6_send_cmd(ppc, (CMD_PREFIX_RESET | PREFIX_IO16)); - - return(data); -} - -//*************************************************************************** - -static void ppc6_wr_port16(PPC *ppc, u8 port, u16 data) -{ - ppc6_send_cmd(ppc, (CMD_PREFIX_SET | PREFIX_IO16)); - - ppc6_send_cmd(ppc, (u8)(port | ACCESS_PORT | ACCESS_WRITE)); - - ppc6_wr_data_byte(ppc, (u8)data); - - ppc6_send_cmd(ppc, (u8)(port | ACCESS_PORT | ACCESS_WRITE)); - - ppc6_wr_data_byte(ppc, (u8)(data >> 8)); - - ppc6_send_cmd(ppc, (CMD_PREFIX_RESET | PREFIX_IO16)); -} - -//*************************************************************************** - static void ppc6_wr_port16_blk(PPC *ppc, u8 port, u8 *data, long length) { length = length << 1; @@ -762,148 +680,6 @@ ppc6_wr_data_blk(ppc, data, length); ppc6_send_cmd(ppc, (CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK)); -} - -//*************************************************************************** - -static u8 ppc6_rd_eeprom_reg(PPC *ppc) -{ - ppc6_send_cmd(ppc, (REG_EEPROM | ACCESS_REG | ACCESS_READ)); - - return(ppc6_rd_data_byte(ppc)); -} - -//*************************************************************************** - -static void ppc6_wr_eeprom_reg(PPC *ppc, u8 data) -{ - ppc6_send_cmd(ppc, (REG_EEPROM | ACCESS_REG | ACCESS_WRITE)); - - ppc6_wr_data_byte(ppc, data); -} - -//*************************************************************************** - -static void ppc6_eeprom_start(PPC *ppc) -{ - ppc6_wr_eeprom_reg(ppc, EEPROM_EN); -} - -//*************************************************************************** - -static void ppc6_eeprom_end(PPC *ppc) -{ - ppc6_wr_eeprom_reg(ppc, 0); -} - -//*************************************************************************** - -static void ppc6_set_cs(PPC *ppc) -{ - ppc6_wr_eeprom_reg(ppc, (u8)(ppc6_rd_eeprom_reg(ppc) | EEPROM_CS)); -} - -//*************************************************************************** - -static void ppc6_reset_cs(PPC *ppc) -{ - ppc6_wr_eeprom_reg(ppc, (u8)(ppc6_rd_eeprom_reg(ppc) & ~EEPROM_CS)); -} - -//*************************************************************************** - -static u8 ppc6_rd_eeprom_bit(PPC *ppc) -{ - ppc6_send_cmd(ppc, (REG_STATUS | ACCESS_REG | ACCESS_READ)); - - if (ppc6_rd_data_byte(ppc) & STATUS_EEPROM_DO) - return(1); - else - return(0); -} - -//*************************************************************************** - -static void ppc6_eeprom_ready_wait(PPC *ppc) -{ - ppc6_set_cs(ppc); - - while(ppc6_rd_eeprom_bit(ppc)); - - ppc6_reset_cs(ppc); -} - -//*************************************************************************** - -static void ppc6_wr_eeprom_bit(PPC *ppc, u8 bit) -{ - u8 eereg; - - eereg = ppc6_rd_eeprom_reg(ppc); - - eereg &= ~(EEPROM_SK | EEPROM_DI); - - if (bit & 1) - eereg |= EEPROM_DI; - - ppc6_wr_eeprom_reg(ppc, eereg); - - eereg |= EEPROM_SK; - - ppc6_wr_eeprom_reg(ppc, eereg); - - eereg &= ~EEPROM_SK; - - ppc6_wr_eeprom_reg(ppc, eereg); -} - -//*************************************************************************** - -static u16 ppc6_eeprom_read(PPC *ppc, u8 addr) -{ - int i; - u16 data; - - ppc6_set_cs(ppc); - - ppc6_wr_eeprom_bit(ppc, 1); // Start bit - - ppc6_wr_eeprom_bit(ppc, 1); // opcode 10 (read) - ppc6_wr_eeprom_bit(ppc, 0); - - for(i=0; i<6; i++) - ppc6_wr_eeprom_bit(ppc, (u8)((addr >> (5 - i)) & 1)); - - data = 0; - - for(i=0; i<16; i++) - { - ppc6_wr_eeprom_bit(ppc,0); - - data = (data << 1) | ppc6_rd_eeprom_bit(ppc); - } - - ppc6_reset_cs(ppc); - - return(data); -} - -//*************************************************************************** - -static u8 ppc6_irq_test(PPC *ppc) -{ - ppc6_send_cmd(ppc,(REG_STATUS | ACCESS_REG | ACCESS_READ)); - - return(ppc6_rd_data_byte(ppc) & STATUS_IRQA); -} - -//*************************************************************************** - -static u8 ppc6_rd_extout(PPC *ppc) -{ - ppc6_send_cmd(ppc,(REG_VERSION | ACCESS_REG | ACCESS_READ)); - - return((ppc6_rd_data_byte(ppc) & 0xC0) >> 6); } //*************************************************************************** diff -u --recursive --new-file v2.4.9/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c --- v2.4.9/linux/drivers/block/ps2esdi.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/block/ps2esdi.c Sat Sep 8 12:02:32 2001 @@ -184,8 +184,7 @@ read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ /* some minor housekeeping - setup the global gendisk structure */ - ps2esdi_gendisk.next = gendisk_head; - gendisk_head = &ps2esdi_gendisk; + add_gendisk(&ps2esdi_gendisk); ps2esdi_geninit(); return 0; } /* ps2esdi_init */ @@ -232,6 +231,7 @@ free_dma(dma_arb_level); free_irq(PS2ESDI_IRQ, NULL) devfs_unregister_blkdev(MAJOR_NR, "ed"); + del_gendisk(&ps2esdi_gendisk); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); } #endif /* MODULE */ @@ -1127,6 +1127,8 @@ case BLKRASET: case BLKRAGET: case BLKFLSBUF: + case BLKBSZGET: + case BLKBSZSET: case BLKPG: return blk_ioctl(inode->i_rdev, cmd, arg); } diff -u --recursive --new-file v2.4.9/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.4.9/linux/drivers/block/rd.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/block/rd.c Fri Sep 7 09:45:51 2001 @@ -100,7 +100,7 @@ static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */ static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */ static devfs_handle_t devfs_handle; -static struct inode *rd_inode[NUM_RAMDISKS]; /* Protected device inodes */ +static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */ /* * Parameters for the boot-loading of the RAM disk. These are set by @@ -259,7 +259,7 @@ /* special: we want to release the ramdisk memory, it's not like with the other blockdevices where this ioctl only flushes away the buffer cache. */ - if ((atomic_read(&inode->i_bdev->bd_openers) > 2)) + if ((atomic_read(rd_bdev[minor]->bd_openers) > 2)) return -EBUSY; destroy_buffers(inode->i_rdev); rd_blocksizes[minor] = 0; @@ -305,7 +305,6 @@ lock_kernel(); if (!--initrd_users) { blkdev_put(inode->i_bdev, BDEV_FILE); - iput(inode); free_initrd_mem(initrd_start, initrd_end); initrd_start = 0; } @@ -324,8 +323,10 @@ static int rd_open(struct inode * inode, struct file * filp) { + int unit = DEVICE_NR(inode->i_rdev); + #ifdef CONFIG_BLK_DEV_INITRD - if (DEVICE_NR(inode->i_rdev) == INITRD_MINOR) { + if (unit == INITRD_MINOR) { if (!initrd_start) return -ENODEV; initrd_users++; filp->f_op = &initrd_fops; @@ -333,16 +334,15 @@ } #endif - if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS) + if (unit >= NUM_RAMDISKS) return -ENXIO; /* * Immunize device against invalidate_buffers() and prune_icache(). */ - if (rd_inode[DEVICE_NR(inode->i_rdev)] == NULL) { - if (!inode->i_bdev) return -ENXIO; - if ((rd_inode[DEVICE_NR(inode->i_rdev)] = igrab(inode)) != NULL) - atomic_inc(&rd_inode[DEVICE_NR(inode->i_rdev)]->i_bdev->bd_openers); + if (rd_bdev[unit] == NULL) { + rd_bdev[unit] = bdget(kdev_t_to_nr(inode->i_rdev)); + atomic_inc(&rd_bdev[unit]->bd_openers); } MOD_INC_USE_COUNT; @@ -369,12 +369,11 @@ int i; for (i = 0 ; i < NUM_RAMDISKS; i++) { - if (rd_inode[i]) { - /* withdraw invalidate_buffers() and prune_icache() immunity */ - atomic_dec(&rd_inode[i]->i_bdev->bd_openers); - /* remove stale pointer to module address space */ - rd_inode[i]->i_bdev->bd_op = NULL; - iput(rd_inode[i]); + struct block_device *bdev = rd_bdev[i]; + rd_bdev[i] = NULL; + if (bdev) { + blkdev_put(bdev); + bdput(bdev); } destroy_buffers(MKDEV(MAJOR_NR, i)); } diff -u --recursive --new-file v2.4.9/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.4.9/linux/drivers/block/xd.c Thu May 24 15:14:08 2001 +++ linux/drivers/block/xd.c Sat Sep 8 12:02:32 2001 @@ -173,8 +173,7 @@ devfs_handle = devfs_mk_dir (NULL, xd_gendisk.major_name, NULL); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ - xd_gendisk.next = gendisk_head; - gendisk_head = &xd_gendisk; + add_gendisk(&xd_gendisk); xd_geninit(); return 0; @@ -1112,18 +1111,12 @@ static void xd_done (void) { - struct gendisk ** gdp; - blksize_size[MAJOR_NR] = NULL; blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_size[MAJOR_NR] = NULL; hardsect_size[MAJOR_NR] = NULL; read_ahead[MAJOR_NR] = 0; - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) - if (*gdp == &xd_gendisk) - break; - if (*gdp) - *gdp = (*gdp)->next; + del_gendisk(&xd_gendisk); release_region(xd_iobase,4); } diff -u --recursive --new-file v2.4.9/linux/drivers/bluetooth/Config.in linux/drivers/bluetooth/Config.in --- v2.4.9/linux/drivers/bluetooth/Config.in Tue Jul 3 17:08:19 2001 +++ linux/drivers/bluetooth/Config.in Fri Sep 7 09:28:38 2001 @@ -3,6 +3,6 @@ dep_tristate 'HCI USB driver' CONFIG_BLUEZ_HCIUSB $CONFIG_BLUEZ $CONFIG_USB dep_tristate 'HCI UART driver' CONFIG_BLUEZ_HCIUART $CONFIG_BLUEZ -dep_tristate 'HCI EMU (virtual device) driver' CONFIG_BLUEZ_HCIEMU $CONFIG_BLUEZ +dep_tristate 'HCI VHCI virtual HCI device driver' CONFIG_BLUEZ_HCIVHCI $CONFIG_BLUEZ endmenu diff -u --recursive --new-file v2.4.9/linux/drivers/bluetooth/Makefile linux/drivers/bluetooth/Makefile --- v2.4.9/linux/drivers/bluetooth/Makefile Tue Jul 3 17:08:19 2001 +++ linux/drivers/bluetooth/Makefile Fri Sep 7 09:28:38 2001 @@ -6,6 +6,6 @@ obj-$(CONFIG_BLUEZ_HCIUSB) += hci_usb.o obj-$(CONFIG_BLUEZ_HCIUART) += hci_uart.o -obj-$(CONFIG_BLUEZ_HCIEMU) += hci_emu.o +obj-$(CONFIG_BLUEZ_HCIVHCI) += hci_vhci.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/drivers/bluetooth/hci_emu.c linux/drivers/bluetooth/hci_emu.c --- v2.4.9/linux/drivers/bluetooth/hci_emu.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/bluetooth/hci_emu.c Wed Dec 31 16:00:00 1969 @@ -1,330 +0,0 @@ -/* - BlueZ - Bluetooth protocol stack for Linux - Copyright (C) 2000-2001 Qualcomm Incorporated - - Written 2000,2001 by Maxim Krasnyansky - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation; - - 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 OF THIRD PARTY RIGHTS. - IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY - CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, - COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS - SOFTWARE IS DISCLAIMED. -*/ - -/* - * BlueZ HCI virtual device driver. - * - * $Id: hci_emu.c,v 1.1 2001/06/01 08:12:10 davem Exp $ - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include - -/* HCI device part */ - -int hci_emu_open(struct hci_dev *hdev) -{ - hdev->flags |= HCI_RUNNING; - return 0; -} - -int hci_emu_flush(struct hci_dev *hdev) -{ - struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) hdev->driver_data; - bluez_skb_queue_purge(&hci_emu->readq); - return 0; -} - -int hci_emu_close(struct hci_dev *hdev) -{ - hdev->flags &= ~HCI_RUNNING; - hci_emu_flush(hdev); - return 0; -} - -int hci_emu_send_frame(struct sk_buff *skb) -{ - struct hci_dev* hdev = (struct hci_dev *) skb->dev; - struct hci_emu_struct *hci_emu; - - if (!hdev) { - ERR("Frame for uknown device (hdev=NULL)"); - return -ENODEV; - } - - if (!(hdev->flags & HCI_RUNNING)) - return -EBUSY; - - hci_emu = (struct hci_emu_struct *) hdev->driver_data; - - memcpy(skb_push(skb, 1), &skb->pkt_type, 1); - skb_queue_tail(&hci_emu->readq, skb); - - if (hci_emu->flags & HCI_EMU_FASYNC) - kill_fasync(&hci_emu->fasync, SIGIO, POLL_IN); - wake_up_interruptible(&hci_emu->read_wait); - - return 0; -} - -/* Character device part */ - -/* Poll */ -static unsigned int hci_emu_chr_poll(struct file *file, poll_table * wait) -{ - struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; - - poll_wait(file, &hci_emu->read_wait, wait); - - if (skb_queue_len(&hci_emu->readq)) - return POLLIN | POLLRDNORM; - - return POLLOUT | POLLWRNORM; -} - -/* Get packet from user space buffer(already verified) */ -static __inline__ ssize_t hci_emu_get_user(struct hci_emu_struct *hci_emu, const char *buf, size_t count) -{ - struct sk_buff *skb; - - if (count > HCI_EMU_MAX_FRAME) - return -EINVAL; - - if (!(skb = bluez_skb_alloc(count, GFP_KERNEL))) - return -ENOMEM; - - copy_from_user(skb_put(skb, count), buf, count); - - skb->dev = (void *) &hci_emu->hdev; - skb->pkt_type = *((__u8 *) skb->data); - skb_pull(skb, 1); - - hci_recv_frame(skb); - - return count; -} - -/* Write */ -static ssize_t hci_emu_chr_write(struct file * file, const char * buf, - size_t count, loff_t *pos) -{ - struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; - - if (verify_area(VERIFY_READ, buf, count)) - return -EFAULT; - - return hci_emu_get_user(hci_emu, buf, count); -} - -/* Put packet to user space buffer(already verified) */ -static __inline__ ssize_t hci_emu_put_user(struct hci_emu_struct *hci_emu, - struct sk_buff *skb, char *buf, int count) -{ - int len = count, total = 0; - char *ptr = buf; - - len = MIN(skb->len, len); - copy_to_user(ptr, skb->data, len); - total += len; - - hci_emu->hdev.stat.byte_tx += len; - switch (skb->pkt_type) { - case HCI_COMMAND_PKT: - hci_emu->hdev.stat.cmd_tx++; - break; - - case HCI_ACLDATA_PKT: - hci_emu->hdev.stat.acl_tx++; - break; - - case HCI_SCODATA_PKT: - hci_emu->hdev.stat.cmd_tx++; - break; - }; - - return total; -} - -/* Read */ -static ssize_t hci_emu_chr_read(struct file * file, char * buf, size_t count, loff_t *pos) -{ - struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; - DECLARE_WAITQUEUE(wait, current); - struct sk_buff *skb; - ssize_t ret = 0; - - add_wait_queue(&hci_emu->read_wait, &wait); - while (count) { - current->state = TASK_INTERRUPTIBLE; - - /* Read frames from device queue */ - if (!(skb = skb_dequeue(&hci_emu->readq))) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - /* Nothing to read, let's sleep */ - schedule(); - continue; - } - - if (!verify_area(VERIFY_WRITE, buf, count)) - ret = hci_emu_put_user(hci_emu, skb, buf, count); - else - ret = -EFAULT; - - bluez_skb_free(skb); - break; - } - - current->state = TASK_RUNNING; - remove_wait_queue(&hci_emu->read_wait, &wait); - - return ret; -} - -static int hci_emu_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} - -static int hci_emu_chr_fasync(int fd, struct file *file, int on) -{ - struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; - int ret; - - if ((ret = fasync_helper(fd, file, on, &hci_emu->fasync)) < 0) - return ret; - - if (on) - hci_emu->flags |= HCI_EMU_FASYNC; - else - hci_emu->flags &= ~HCI_EMU_FASYNC; - - return 0; -} - -static int hci_emu_chr_open(struct inode *inode, struct file * file) -{ - struct hci_emu_struct *hci_emu = NULL; - struct hci_dev *hdev; - - if (!(hci_emu = kmalloc(sizeof(struct hci_emu_struct), GFP_KERNEL))) - return -ENOMEM; - - memset(hci_emu, 0, sizeof(struct hci_emu_struct)); - - skb_queue_head_init(&hci_emu->readq); - init_waitqueue_head(&hci_emu->read_wait); - - /* Initialize and register HCI device */ - hdev = &hci_emu->hdev; - - hdev->type = HCI_EMU; - hdev->driver_data = hci_emu; - - hdev->open = hci_emu_open; - hdev->close = hci_emu_close; - hdev->flush = hci_emu_flush; - hdev->send = hci_emu_send_frame; - - if (hci_register_dev(hdev) < 0) { - kfree(hci_emu); - return -EBUSY; - } - - file->private_data = hci_emu; - return 0; -} - -static int hci_emu_chr_close(struct inode *inode, struct file *file) -{ - struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; - - if (hci_unregister_dev(&hci_emu->hdev) < 0) { - ERR("Can't unregister HCI device %s", hci_emu->hdev.name); - } - - kfree(hci_emu); - file->private_data = NULL; - - return 0; -} - -static struct file_operations hci_emu_fops = { - owner: THIS_MODULE, - llseek: no_llseek, - read: hci_emu_chr_read, - write: hci_emu_chr_write, - poll: hci_emu_chr_poll, - ioctl: hci_emu_chr_ioctl, - open: hci_emu_chr_open, - release:hci_emu_chr_close, - fasync: hci_emu_chr_fasync -}; - -static struct miscdevice hci_emu_miscdev= -{ - HCI_EMU_MINOR, - "hci_emu", - &hci_emu_fops -}; - -int __init hci_emu_init(void) -{ - INF("BlueZ HCI EMU driver ver %s Copyright (C) 2000,2001 Qualcomm Inc", - BLUEZ_VER); - INF("Written 2000,2001 by Maxim Krasnyansky "); - - if (misc_register(&hci_emu_miscdev)) { - ERR("Can't register misc device %d\n", HCI_EMU_MINOR); - return -EIO; - } - - return 0; -} - -void hci_emu_cleanup(void) -{ - misc_deregister(&hci_emu_miscdev); -} - -module_init(hci_emu_init); -module_exit(hci_emu_cleanup); diff -u --recursive --new-file v2.4.9/linux/drivers/bluetooth/hci_uart.c linux/drivers/bluetooth/hci_uart.c --- v2.4.9/linux/drivers/bluetooth/hci_uart.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/bluetooth/hci_uart.c Fri Sep 7 09:28:38 2001 @@ -25,8 +25,9 @@ /* * BlueZ HCI UART driver. * - * $Id: hci_uart.c,v 1.1 2001/06/01 08:12:10 davem Exp $ + * $Id: hci_uart.c,v 1.5 2001/07/05 18:42:44 maxk Exp $ */ +#define VERSION "1.0" #include #include @@ -84,7 +85,7 @@ DBG("hdev %p tty %p", hdev, tty); /* Drop TX queue */ - bluez_skb_queue_purge(&n_hci->txq); + skb_queue_purge(&n_hci->txq); /* Flush any pending characters in the driver and discipline. */ if (tty->ldisc.flush_buffer) @@ -139,7 +140,7 @@ if (len == skb->len) { /* Full frame was sent */ - bluez_skb_free(skb); + kfree_skb(skb); } else { /* Subtract sent part and requeue */ skb_pull(skb, len); @@ -334,7 +335,7 @@ hci_recv_frame(n_hci->rx_skb); } else if (len > room) { ERR("Data length is to large"); - bluez_skb_free(n_hci->rx_skb); + kfree_skb(n_hci->rx_skb); n_hci->hdev.stat.err_rx++; } else { n_hci->rx_state = WAIT_DATA; @@ -356,7 +357,7 @@ hci_sco_hdr *sh; register int len, type, dlen; - DBG("count %d state %d rx_count %d", count, n_hci->rx_state, n_hci->rx_count); + DBG("count %d state %ld rx_count %ld", count, n_hci->rx_state, n_hci->rx_count); n_hci->hdev.stat.byte_rx += count; @@ -441,7 +442,7 @@ ptr++; count--; /* Allocate packet */ - if (!(n_hci->rx_skb = bluez_skb_alloc(HCI_MAX_READ, GFP_ATOMIC))) { + if (!(n_hci->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { ERR("Can't allocate mem for new packet"); n_hci->rx_state = WAIT_PACKET_TYPE; @@ -536,7 +537,7 @@ int err; INF("BlueZ HCI UART driver ver %s Copyright (C) 2000,2001 Qualcomm Inc", - BLUEZ_VER); + VERSION); INF("Written 2000,2001 by Maxim Krasnyansky "); /* Register the tty discipline */ @@ -573,3 +574,7 @@ module_init(n_hci_init); module_exit(n_hci_cleanup); + +MODULE_AUTHOR("Maxim Krasnyansky "); +MODULE_DESCRIPTION("BlueZ HCI UART driver ver " VERSION); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/bluetooth/hci_usb.c linux/drivers/bluetooth/hci_usb.c --- v2.4.9/linux/drivers/bluetooth/hci_usb.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/bluetooth/hci_usb.c Fri Sep 7 09:28:38 2001 @@ -28,8 +28,9 @@ * Copyright (c) 2000 Greg Kroah-Hartman * Copyright (c) 2000 Mark Douglas Corner * - * $Id: hci_usb.c,v 1.1 2001/06/01 08:12:10 davem Exp $ + * $Id: hci_usb.c,v 1.5 2001/07/05 18:42:44 maxk Exp $ */ +#define VERSION "1.0" #include #include @@ -106,7 +107,7 @@ usb_free_urb(husb->write_urb); if (husb->intr_skb) - bluez_skb_free(husb->intr_skb); + kfree_skb(husb->intr_skb); } /* ------- Interface to HCI layer ------ */ @@ -139,8 +140,8 @@ DBG("%s", hdev->name); /* Drop TX queues */ - bluez_skb_queue_purge(&husb->tx_ctrl_q); - bluez_skb_queue_purge(&husb->tx_write_q); + skb_queue_purge(&husb->tx_ctrl_q); + skb_queue_purge(&husb->tx_write_q); return 0; } @@ -173,7 +174,7 @@ goto done; if (hci_usb_ctrl_msg(husb, skb)){ - bluez_skb_free(skb); + kfree_skb(skb); goto done; } @@ -271,7 +272,7 @@ DBG("%s ctrl status: %d", hdev->name, urb->status); clear_bit(HCI_TX_CTRL, &husb->tx_state); - bluez_skb_free(skb); + kfree_skb(skb); /* Wake up device */ hci_usb_ctrl_wakeup(husb); @@ -294,7 +295,7 @@ DBG("%s bulk write status: %d", hdev->name, urb->status); clear_bit(HCI_TX_WRITE, &husb->tx_state); - bluez_skb_free(skb); + kfree_skb(skb); /* Wake up device */ hci_usb_write_wakeup(husb); @@ -352,7 +353,7 @@ if (count > husb->intr_count) { ERR("%s bad frame len %d (expected %d)", husb->hdev.name, count, husb->intr_count); - bluez_skb_free(skb); + kfree_skb(skb); husb->intr_skb = NULL; husb->intr_count = 0; return; @@ -563,7 +564,7 @@ ep = bulk_in_ep; pipe = usb_rcvbulkpipe(udev, ep->bEndpointAddress); - size = HCI_USB_MAX_READ; + size = HCI_MAX_FRAME_SIZE; if (!(buf = kmalloc(size, GFP_KERNEL))) { ERR("Can't allocate: read buffer"); @@ -652,7 +653,7 @@ int err; INF("BlueZ HCI USB driver ver %s Copyright (C) 2000,2001 Qualcomm Inc", - BLUEZ_VER); + VERSION); INF("Written 2000,2001 by Maxim Krasnyansky "); if ((err = usb_register(&hci_usb_driver)) < 0) @@ -668,3 +669,7 @@ module_init(hci_usb_init); module_exit(hci_usb_cleanup); + +MODULE_AUTHOR("Maxim Krasnyansky "); +MODULE_DESCRIPTION("BlueZ HCI USB driver ver " VERSION); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/bluetooth/hci_vhci.c linux/drivers/bluetooth/hci_vhci.c --- v2.4.9/linux/drivers/bluetooth/hci_vhci.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/bluetooth/hci_vhci.c Fri Sep 7 09:28:38 2001 @@ -0,0 +1,340 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation; + + 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 OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ HCI virtual device driver. + * + * $Id: hci_vhci.c,v 1.3 2001/08/03 04:19:50 maxk Exp $ + */ +#define VERSION "1.0" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +/* HCI device part */ + +int hci_vhci_open(struct hci_dev *hdev) +{ + hdev->flags |= HCI_RUNNING; + return 0; +} + +int hci_vhci_flush(struct hci_dev *hdev) +{ + struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) hdev->driver_data; + skb_queue_purge(&hci_vhci->readq); + return 0; +} + +int hci_vhci_close(struct hci_dev *hdev) +{ + hdev->flags &= ~HCI_RUNNING; + hci_vhci_flush(hdev); + return 0; +} + +int hci_vhci_send_frame(struct sk_buff *skb) +{ + struct hci_dev* hdev = (struct hci_dev *) skb->dev; + struct hci_vhci_struct *hci_vhci; + + if (!hdev) { + ERR("Frame for uknown device (hdev=NULL)"); + return -ENODEV; + } + + if (!(hdev->flags & HCI_RUNNING)) + return -EBUSY; + + hci_vhci = (struct hci_vhci_struct *) hdev->driver_data; + + memcpy(skb_push(skb, 1), &skb->pkt_type, 1); + skb_queue_tail(&hci_vhci->readq, skb); + + if (hci_vhci->flags & VHCI_FASYNC) + kill_fasync(&hci_vhci->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&hci_vhci->read_wait); + + return 0; +} + +/* Character device part */ + +/* Poll */ +static unsigned int hci_vhci_chr_poll(struct file *file, poll_table * wait) +{ + struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; + + poll_wait(file, &hci_vhci->read_wait, wait); + + if (skb_queue_len(&hci_vhci->readq)) + return POLLIN | POLLRDNORM; + + return POLLOUT | POLLWRNORM; +} + +/* Get packet from user space buffer(already verified) */ +static inline ssize_t hci_vhci_get_user(struct hci_vhci_struct *hci_vhci, const char *buf, size_t count) +{ + struct sk_buff *skb; + + if (count > HCI_MAX_FRAME_SIZE) + return -EINVAL; + + if (!(skb = bluez_skb_alloc(count, GFP_KERNEL))) + return -ENOMEM; + + copy_from_user(skb_put(skb, count), buf, count); + + skb->dev = (void *) &hci_vhci->hdev; + skb->pkt_type = *((__u8 *) skb->data); + skb_pull(skb, 1); + + hci_recv_frame(skb); + + return count; +} + +/* Write */ +static ssize_t hci_vhci_chr_write(struct file * file, const char * buf, + size_t count, loff_t *pos) +{ + struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; + + if (verify_area(VERIFY_READ, buf, count)) + return -EFAULT; + + return hci_vhci_get_user(hci_vhci, buf, count); +} + +/* Put packet to user space buffer(already verified) */ +static inline ssize_t hci_vhci_put_user(struct hci_vhci_struct *hci_vhci, + struct sk_buff *skb, char *buf, int count) +{ + int len = count, total = 0; + char *ptr = buf; + + len = MIN(skb->len, len); + copy_to_user(ptr, skb->data, len); + total += len; + + hci_vhci->hdev.stat.byte_tx += len; + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hci_vhci->hdev.stat.cmd_tx++; + break; + + case HCI_ACLDATA_PKT: + hci_vhci->hdev.stat.acl_tx++; + break; + + case HCI_SCODATA_PKT: + hci_vhci->hdev.stat.cmd_tx++; + break; + }; + + return total; +} + +/* Read */ +static ssize_t hci_vhci_chr_read(struct file * file, char * buf, size_t count, loff_t *pos) +{ + struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; + DECLARE_WAITQUEUE(wait, current); + struct sk_buff *skb; + ssize_t ret = 0; + + add_wait_queue(&hci_vhci->read_wait, &wait); + while (count) { + current->state = TASK_INTERRUPTIBLE; + + /* Read frames from device queue */ + if (!(skb = skb_dequeue(&hci_vhci->readq))) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + /* Nothing to read, let's sleep */ + schedule(); + continue; + } + + if (!verify_area(VERIFY_WRITE, buf, count)) + ret = hci_vhci_put_user(hci_vhci, skb, buf, count); + else + ret = -EFAULT; + + kfree_skb(skb); + break; + } + + current->state = TASK_RUNNING; + remove_wait_queue(&hci_vhci->read_wait, &wait); + + return ret; +} + +static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + return -EINVAL; +} + +static int hci_vhci_chr_fasync(int fd, struct file *file, int on) +{ + struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; + int ret; + + if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0) + return ret; + + if (on) + hci_vhci->flags |= VHCI_FASYNC; + else + hci_vhci->flags &= ~VHCI_FASYNC; + + return 0; +} + +static int hci_vhci_chr_open(struct inode *inode, struct file * file) +{ + struct hci_vhci_struct *hci_vhci = NULL; + struct hci_dev *hdev; + + if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL))) + return -ENOMEM; + + memset(hci_vhci, 0, sizeof(struct hci_vhci_struct)); + + skb_queue_head_init(&hci_vhci->readq); + init_waitqueue_head(&hci_vhci->read_wait); + + /* Initialize and register HCI device */ + hdev = &hci_vhci->hdev; + + hdev->type = HCI_VHCI; + hdev->driver_data = hci_vhci; + + hdev->open = hci_vhci_open; + hdev->close = hci_vhci_close; + hdev->flush = hci_vhci_flush; + hdev->send = hci_vhci_send_frame; + + if (hci_register_dev(hdev) < 0) { + kfree(hci_vhci); + return -EBUSY; + } + + file->private_data = hci_vhci; + return 0; +} + +static int hci_vhci_chr_close(struct inode *inode, struct file *file) +{ + struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; + + if (hci_unregister_dev(&hci_vhci->hdev) < 0) { + ERR("Can't unregister HCI device %s", hci_vhci->hdev.name); + } + + kfree(hci_vhci); + file->private_data = NULL; + + return 0; +} + +static struct file_operations hci_vhci_fops = { + owner: THIS_MODULE, + llseek: hci_vhci_chr_lseek, + read: hci_vhci_chr_read, + write: hci_vhci_chr_write, + poll: hci_vhci_chr_poll, + ioctl: hci_vhci_chr_ioctl, + open: hci_vhci_chr_open, + release:hci_vhci_chr_close, + fasync: hci_vhci_chr_fasync +}; + +static struct miscdevice hci_vhci_miscdev= +{ + VHCI_MINOR, + "hci_vhci", + &hci_vhci_fops +}; + +int __init hci_vhci_init(void) +{ + INF("BlueZ VHCI driver ver %s Copyright (C) 2000,2001 Qualcomm Inc", + VERSION); + INF("Written 2000,2001 by Maxim Krasnyansky "); + + if (misc_register(&hci_vhci_miscdev)) { + ERR("Can't register misc device %d\n", VHCI_MINOR); + return -EIO; + } + + return 0; +} + +void hci_vhci_cleanup(void) +{ + misc_deregister(&hci_vhci_miscdev); +} + +module_init(hci_vhci_init); +module_exit(hci_vhci_cleanup); + +MODULE_AUTHOR("Maxim Krasnyansky "); +MODULE_DESCRIPTION("BlueZ VHCI driver ver " VERSION); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c --- v2.4.9/linux/drivers/cdrom/aztcd.c Thu Oct 26 23:35:47 2000 +++ linux/drivers/cdrom/aztcd.c Fri Sep 7 09:28:38 2001 @@ -185,19 +185,13 @@ #include #include -#ifndef AZT_KERNEL_PRIOR_2_1 #include -#endif #include #include -#ifdef AZT_KERNEL_PRIOR_2_1 -#include -#else #include static int aztcd_blocksizes[1] = {2048}; -#endif /*########################################################################### @@ -245,11 +239,6 @@ #define azt_port aztcd /*needed for the modutils*/ -#ifndef AZT_KERNEL_PRIOR_2_1 -#define memcpy_fromfs copy_from_user -#define memcpy_tofs copy_to_user -#endif - /*########################################################################## Type Definitions ########################################################################## @@ -298,9 +287,7 @@ static int azt_port = AZT_BASE_ADDR; -#ifndef AZT_KERNEL_PRIOR_2_1 MODULE_PARM(azt_port, "i"); -#endif static int azt_port_auto[16] = AZT_BASE_AUTO; @@ -364,11 +351,7 @@ static void azt_invalidate_buffers(void); int aztcd_open(struct inode *ip, struct file *fp); -#ifdef AZT_KERNEL_PRIOR_2_1 -static void aztcd_release(struct inode * inode, struct file * file); -#else static int aztcd_release(struct inode * inode, struct file * file); -#endif int aztcd_init(void); @@ -1111,7 +1094,7 @@ * Kernel IO-controls */ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) -{ int i, st; +{ int i; struct azt_Toc qInfo; struct cdrom_ti ti; struct cdrom_tochdr tocHdr; @@ -1175,9 +1158,8 @@ #ifdef AZT_DEBUG printk("aztcd ioctl MULTISESSION\n"); #endif - st = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct cdrom_multisession)); - if (st) return st; - memcpy_fromfs(&ms, (void*) arg, sizeof(struct cdrom_multisession)); + if(copy_from_user(&ms, (void*) arg, sizeof(struct cdrom_multisession))) + return -EFAULT; if (ms.addr_format == CDROM_MSF) { ms.addr.msf.minute = azt_bcd2bin(DiskInfo.lastSession.min); ms.addr.msf.second = azt_bcd2bin(DiskInfo.lastSession.sec); @@ -1188,7 +1170,8 @@ else return -EINVAL; ms.xa_flag = DiskInfo.xa; - memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession)); + if(copy_to_user((void*) arg, &ms, sizeof(struct cdrom_multisession))) + return -EFAULT; #ifdef AZT_DEBUG if (ms.addr_format == CDROM_MSF) printk("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n", @@ -1203,9 +1186,8 @@ return 0; } case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ - st = verify_area(VERIFY_READ, (void *) arg, sizeof ti); - if (st) return st; - memcpy_fromfs(&ti, (void *) arg, sizeof ti); + if(copy_from_user(&ti, (void *) arg, sizeof ti)) + return -EFAULT; if (ti.cdti_trk0 < DiskInfo.first || ti.cdti_trk0 > DiskInfo.last || ti.cdti_trk1 < ti.cdti_trk0) @@ -1234,9 +1216,8 @@ aztAudioStatus = CDROM_AUDIO_NO_STATUS; } */ - st = verify_area(VERIFY_READ, (void *) arg, sizeof msf); - if (st) return st; - memcpy_fromfs(&msf, (void *) arg, sizeof msf); + if(copy_from_user(&msf, (void *) arg, sizeof msf)) + return -EFAULT; /* convert to bcd */ azt_bin2bcd(&msf.cdmsf_min0); azt_bin2bcd(&msf.cdmsf_sec0); @@ -1264,16 +1245,14 @@ break; case CDROMREADTOCHDR: /* Read the table of contents header */ - st = verify_area(VERIFY_WRITE, (void *) arg, sizeof tocHdr); - if (st) return st; tocHdr.cdth_trk0 = DiskInfo.first; tocHdr.cdth_trk1 = DiskInfo.last; - memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr); + if(copy_to_user((void *) arg, &tocHdr, sizeof tocHdr)) + return -EFAULT; break; case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ - st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry); - if (st) return st; - memcpy_fromfs(&entry, (void *) arg, sizeof entry); + if(copy_from_user(&entry, (void *) arg, sizeof entry)) + return -EFAULT; if ((!aztTocUpToDate)||aztDiskChanged) aztUpdateToc(); if (entry.cdte_track == CDROM_LEADOUT) tocPtr = &Toc[DiskInfo.last + 1]; @@ -1295,19 +1274,13 @@ else { return -EINVAL; } - memcpy_tofs((void *) arg, &entry, sizeof entry); + if(copy_to_user((void *) arg, &entry, sizeof entry)) + return -EFAULT; break; case CDROMSUBCHNL: /* Get subchannel info */ - st = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl)); - if (st) { -#ifdef AZT_DEBUG - printk("aztcd: exiting aztcd_ioctl - Error 1 - Command:%x\n",cmd); -#endif - return st; - } - memcpy_fromfs(&subchnl, (void *) arg, sizeof (struct cdrom_subchnl)); - if (aztGetQChannelInfo(&qInfo) < 0) - if (st) { + if(copy_from_user(&subchnl, (void *) arg, sizeof (struct cdrom_subchnl))) + return -EFAULT; + if (aztGetQChannelInfo(&qInfo) < 0) { #ifdef AZT_DEBUG printk("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",cmd); #endif @@ -1331,15 +1304,15 @@ subchnl.cdsc_reladdr.msf.second = azt_bcd2bin(qInfo.trackTime.sec); subchnl.cdsc_reladdr.msf.frame = azt_bcd2bin(qInfo.trackTime.frame); } - memcpy_tofs((void *) arg, &subchnl, sizeof (struct cdrom_subchnl)); + if(copy_to_user((void *) arg, &subchnl, sizeof (struct cdrom_subchnl))) + return -EFAULT; break; case CDROMVOLCTRL: /* Volume control * With my Aztech CD268-01A volume control does not work, I can only turn the channels on (any value !=0) or off (value==0). Maybe it works better with your drive */ - st=verify_area(VERIFY_READ,(void *) arg, sizeof(volctrl)); - if (st) return (st); - memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl)); + if(copy_from_user(&volctrl,(char *) arg,sizeof(volctrl))) + return -EFAULT; azt_Play.start.min = 0x21; azt_Play.start.sec = 0x84; azt_Play.start.frame = volctrl.channel0; @@ -1377,9 +1350,9 @@ #if AZT_PRIVATE_IOCTLS case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes)*/ case CDROMREADRAW: /*read data in mode 2 (2336 Bytes)*/ - { st = verify_area(VERIFY_WRITE, (void *) arg, sizeof buf); - if (st) return st; - memcpy_fromfs(&msf, (void *) arg, sizeof msf); + { + if(copy_from_user(&msf, (void *) arg, sizeof msf)) + return -EFAULT; /* convert to bcd */ azt_bin2bcd(&msf.cdmsf_min0); azt_bin2bcd(&msf.cdmsf_sec0); @@ -1401,21 +1374,22 @@ { if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play)) return -1; DTEN_LOW; insb(DATA_PORT,buf,CD_FRAMESIZE_RAW); - memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE_RAW); + if(copy_to_user((void *) arg, &buf, CD_FRAMESIZE_RAW)) + return -EFAULT; } } else /*CDROMREADCOOKED*/ { if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1; DTEN_LOW; insb(DATA_PORT,buf,CD_FRAMESIZE); - memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE); + if(copy_to_user((void *) arg, &buf, CD_FRAMESIZE)) + return -EFAULT; } } break; case CDROMSEEK: /*seek msf address*/ - st = verify_area(VERIFY_READ, (void *) arg, sizeof msf); - if (st) return st; - memcpy_fromfs(&msf, (void *) arg, sizeof msf); + if(copy_from_user(&msf, (void *) arg, sizeof msf)) + return -EFAULT; /* convert to bcd */ azt_bin2bcd(&msf.cdmsf_min0); azt_bin2bcd(&msf.cdmsf_sec0); @@ -1586,11 +1560,7 @@ /* * On close, we flush all azt blocks from the buffer cache. */ -#ifdef AZT_KERNEL_PRIOR_2_1 -static void aztcd_release(struct inode * inode, struct file * file) -#else static int aztcd_release(struct inode * inode, struct file * file) -#endif { #ifdef AZT_DEBUG printk("aztcd: executing aztcd_release\n"); @@ -1604,11 +1574,7 @@ aztSendCmd(ACMD_EJECT); CLEAR_TIMER; } -#ifdef AZT_KERNEL_PRIOR_2_1 - return; -#else return 0; -#endif } @@ -1800,9 +1766,7 @@ return -EIO; } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); -#ifndef AZT_KERNEL_PRIOR_2_1 blksize_size[MAJOR_NR] = aztcd_blocksizes; -#endif read_ahead[MAJOR_NR] = 4; register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &azt_fops, 0); @@ -2284,3 +2248,6 @@ static int azt_bcd2bin(unsigned char bcd) { return (bcd >> 4) * 10 + (bcd & 0xF); } + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c --- v2.4.9/linux/drivers/cdrom/cdu31a.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/cdrom/cdu31a.c Fri Sep 7 09:28:38 2001 @@ -179,7 +179,7 @@ #define MAJOR_NR CDU31A_CDROM_MAJOR #include -#define CDU31A_READAHEAD 4 /* 128 sector, 64kB, 32 reads read-ahead */ +#define CDU31A_READAHEAD 4 /* 128 sector, 64kB, 32 reads read-ahead */ #define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10 #define DEBUG 0 @@ -192,25 +192,12 @@ ** Default is polled and no DMA. DMA is not recommended for double-speed ** drives. */ -static struct -{ - unsigned short base; /* I/O Base Address */ - short int_num; /* Interrupt Number (-1 means scan for it, - 0 means don't use) */ -} cdu31a_addresses[] __initdata = -{ -#if 0 /* No autoconfig any more. See Note at beginning - of this file. */ - { 0x340, 0 }, /* Standard configuration Sony Interface */ - { 0x1f88, 0 }, /* Fusion CD-16 */ - { 0x230, 0 }, /* SoundBlaster 16 card */ - { 0x360, 0 }, /* Secondary standard Sony Interface */ - { 0x320, 0 }, /* Secondary standard Sony Interface */ - { 0x330, 0 }, /* Secondary standard Sony Interface */ - { 0x634, 0 }, /* Sound FX SC400 */ - { 0x654, 0 }, /* Sound FX SC400 */ -#endif - { 0 } +static struct { + unsigned short base; /* I/O Base Address */ + short int_num; /* Interrupt Number (-1 means scan for it, + 0 means don't use) */ +} cdu31a_addresses[] __initdata = { + {0} }; static int handle_sony_cd_attention(void); @@ -220,17 +207,16 @@ /*static int scd_open(struct inode *inode, struct file *filp);*/ static int scd_open(struct cdrom_device_info *, int); static void do_sony_cd_cmd(unsigned char cmd, - unsigned char *params, - unsigned int num_params, - unsigned char *result_buffer, - unsigned int *result_size); -static void size_to_buf(unsigned int size, - unsigned char *buf); + unsigned char *params, + unsigned int num_params, + unsigned char *result_buffer, + unsigned int *result_size); +static void size_to_buf(unsigned int size, unsigned char *buf); /* Parameters for the read-ahead. */ -static unsigned int sony_next_block; /* Next 512 byte block offset */ -static unsigned int sony_blocks_left = 0; /* Number of 512 byte blocks left - in the current read command. */ +static unsigned int sony_next_block; /* Next 512 byte block offset */ +static unsigned int sony_blocks_left = 0; /* Number of 512 byte blocks left + in the current read command. */ /* The base I/O address of the Sony Interface. This is a variable (not a @@ -252,48 +238,48 @@ static volatile unsigned short sony_cd_fifost_reg; -static int sony_spun_up = 0; /* Has the drive been spun up? */ +static int sony_spun_up = 0; /* Has the drive been spun up? */ -static int sony_speed = 0; /* Last wanted speed */ +static int sony_speed = 0; /* Last wanted speed */ -static int sony_xa_mode = 0; /* Is an XA disk in the drive - and the drive a CDU31A? */ +static int sony_xa_mode = 0; /* Is an XA disk in the drive + and the drive a CDU31A? */ -static int sony_raw_data_mode = 1; /* 1 if data tracks, 0 if audio. - For raw data reads. */ +static int sony_raw_data_mode = 1; /* 1 if data tracks, 0 if audio. + For raw data reads. */ -static unsigned int sony_usage = 0; /* How many processes have the - drive open. */ +static unsigned int sony_usage = 0; /* How many processes have the + drive open. */ -static int sony_pas_init = 0; /* Initialize the Pro-Audio - Spectrum card? */ +static int sony_pas_init = 0; /* Initialize the Pro-Audio + Spectrum card? */ -static struct s_sony_session_toc single_toc; /* Holds the - table of - contents. */ +static struct s_sony_session_toc single_toc; /* Holds the + table of + contents. */ -static struct s_all_sessions_toc sony_toc; /* entries gathered from all - sessions */ +static struct s_all_sessions_toc sony_toc; /* entries gathered from all + sessions */ -static int sony_toc_read = 0; /* Has the TOC been read for - the drive? */ +static int sony_toc_read = 0; /* Has the TOC been read for + the drive? */ -static struct s_sony_subcode last_sony_subcode; /* Points to the last - subcode address read */ +static struct s_sony_subcode last_sony_subcode; /* Points to the last + subcode address read */ -static volatile int sony_inuse = 0; /* Is the drive in use? Only one operation - at a time allowed */ +static volatile int sony_inuse = 0; /* Is the drive in use? Only one operation + at a time allowed */ static DECLARE_WAIT_QUEUE_HEAD(sony_wait); /* Things waiting for the drive */ -static struct task_struct *has_cd_task = NULL; /* The task that is currently +static struct task_struct *has_cd_task = NULL; /* The task that is currently using the CDROM drive, or NULL if none. */ -static int is_double_speed = 0; /* does the drive support double speed ? */ -static int is_a_cdu31a = 1; /* Is the drive a CDU31A? */ +static int is_double_speed = 0; /* does the drive support double speed ? */ +static int is_a_cdu31a = 1; /* Is the drive a CDU31A? */ -static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */ +static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */ /* * The audio status uses the values from read subchannel data as specified @@ -319,7 +305,7 @@ interrupts. */ DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait); -static int curr_control_reg = 0; /* Current value of the control register */ +static int curr_control_reg = 0; /* Current value of the control register */ /* A disk changed variable. When a disk change is detected, it will all be set to TRUE. As the upper layers ask for disk_changed status @@ -348,25 +334,23 @@ * This routine returns 1 if the disk has been changed since the last * check or 0 if it hasn't. */ -static int -scd_disk_change(kdev_t full_dev) +static int scd_disk_change(kdev_t full_dev) { - int retval; + int retval; - retval = disk_changed; - disk_changed = 0; + retval = disk_changed; + disk_changed = 0; - return retval; + return retval; } /* * Uniform cdrom interface function * report back, if disc has changed from time of last request. */ -static int -scd_media_changed(struct cdrom_device_info *cdi, int disc_nr) +static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr) { - return scd_disk_change(cdi->dev); + return scd_disk_change(cdi->dev); } /* @@ -375,56 +359,51 @@ */ static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr) { - if (CDSL_CURRENT != slot_nr) { - /* we have no changer support */ - return -EINVAL; - } - if (scd_spinup() == 0) { - sony_spun_up = 1; - } - return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY; -} - -static inline void -enable_interrupts(void) -{ - curr_control_reg |= ( SONY_ATTN_INT_EN_BIT - | SONY_RES_RDY_INT_EN_BIT - | SONY_DATA_RDY_INT_EN_BIT); - outb(curr_control_reg, sony_cd_control_reg); -} - -static inline void -disable_interrupts(void) -{ - curr_control_reg &= ~( SONY_ATTN_INT_EN_BIT - | SONY_RES_RDY_INT_EN_BIT - | SONY_DATA_RDY_INT_EN_BIT); - outb(curr_control_reg, sony_cd_control_reg); + if (CDSL_CURRENT != slot_nr) { + /* we have no changer support */ + return -EINVAL; + } + if (scd_spinup() == 0) { + sony_spun_up = 1; + } + return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY; +} + +static inline void enable_interrupts(void) +{ + curr_control_reg |= (SONY_ATTN_INT_EN_BIT + | SONY_RES_RDY_INT_EN_BIT + | SONY_DATA_RDY_INT_EN_BIT); + outb(curr_control_reg, sony_cd_control_reg); +} + +static inline void disable_interrupts(void) +{ + curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT + | SONY_RES_RDY_INT_EN_BIT + | SONY_DATA_RDY_INT_EN_BIT); + outb(curr_control_reg, sony_cd_control_reg); } /* * Wait a little while (used for polling the drive). If in initialization, * setting a timeout doesn't work, so just loop for a while. */ -static inline void -sony_sleep(void) +static inline void sony_sleep(void) { - unsigned long flags; + unsigned long flags; - if (cdu31a_irq <= 0) - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(0); - } - else /* Interrupt driven */ - { - save_flags(flags); - cli(); - enable_interrupts(); - interruptible_sleep_on(&cdu31a_irq_wait); - restore_flags(flags); - } + if (cdu31a_irq <= 0) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(0); + } else { /* Interrupt driven */ + + save_flags(flags); + cli(); + enable_interrupts(); + interruptible_sleep_on(&cdu31a_irq_wait); + restore_flags(flags); + } } @@ -432,272 +411,276 @@ * The following are convenience routine to read various status and set * various conditions in the drive. */ -static inline int -is_attention(void) +static inline int is_attention(void) { - return((inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0); + return ((inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0); } -static inline int -is_busy(void) +static inline int is_busy(void) { - return((inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0); + return ((inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0); } -static inline int -is_data_ready(void) +static inline int is_data_ready(void) { - return((inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0); + return ((inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0); } -static inline int -is_data_requested(void) +static inline int is_data_requested(void) { - return((inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0); + return ((inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0); } -static inline int -is_result_ready(void) +static inline int is_result_ready(void) { - return((inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0); + return ((inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0); } -static inline int -is_param_write_rdy(void) +static inline int is_param_write_rdy(void) { - return((inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0); + return ((inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0); } -static inline int -is_result_reg_not_empty(void) +static inline int is_result_reg_not_empty(void) { - return((inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0); + return ((inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0); } -static inline void -reset_drive(void) +static inline void reset_drive(void) { - curr_control_reg = 0; - readahead_dataleft = 0; - sony_toc_read = 0; - outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg); + curr_control_reg = 0; + readahead_dataleft = 0; + sony_toc_read = 0; + outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg); } /* * Uniform cdrom interface function * reset drive and return when it is ready */ -static int scd_reset(struct cdrom_device_info * cdi) +static int scd_reset(struct cdrom_device_info *cdi) { - int retry_count; + int retry_count; - reset_drive(); + reset_drive(); - retry_count = jiffies + SONY_RESET_TIMEOUT; - while (time_before(jiffies, retry_count) && (!is_attention())) - { - sony_sleep(); - } + retry_count = jiffies + SONY_RESET_TIMEOUT; + while (time_before(jiffies, retry_count) && (!is_attention())) { + sony_sleep(); + } - return 0; + return 0; } -static inline void -clear_attention(void) +static inline void clear_attention(void) { - outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg); + outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg); } -static inline void -clear_result_ready(void) +static inline void clear_result_ready(void) { - outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg); + outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg); } -static inline void -clear_data_ready(void) +static inline void clear_data_ready(void) { - outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT, sony_cd_control_reg); + outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT, + sony_cd_control_reg); } -static inline void -clear_param_reg(void) +static inline void clear_param_reg(void) { - outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg); + outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg); } -static inline unsigned char -read_status_register(void) +static inline unsigned char read_status_register(void) { - return(inb(sony_cd_status_reg)); + return (inb(sony_cd_status_reg)); } -static inline unsigned char -read_result_register(void) +static inline unsigned char read_result_register(void) { - return(inb(sony_cd_result_reg)); + return (inb(sony_cd_result_reg)); } -static inline unsigned char -read_data_register(void) +static inline unsigned char read_data_register(void) { - return(inb(sony_cd_read_reg)); + return (inb(sony_cd_read_reg)); } -static inline void -write_param(unsigned char param) +static inline void write_param(unsigned char param) { - outb(param, sony_cd_param_reg); + outb(param, sony_cd_param_reg); } -static inline void -write_cmd(unsigned char cmd) +static inline void write_cmd(unsigned char cmd) { - outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT, sony_cd_control_reg); - outb(cmd, sony_cd_cmd_reg); + outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT, + sony_cd_control_reg); + outb(cmd, sony_cd_cmd_reg); } -static void -cdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void cdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned char val; + unsigned char val; + + if (abort_read_started) { + /* We might be waiting for an abort to finish. Don't + disable interrupts yet, though, because we handle + this one here. */ + /* Clear out the result registers. */ + while (is_result_reg_not_empty()) { + val = read_result_register(); + } + clear_data_ready(); + clear_result_ready(); - if (abort_read_started) - { - /* We might be waiting for an abort to finish. Don't - disable interrupts yet, though, because we handle - this one here. */ - /* Clear out the result registers. */ - while (is_result_reg_not_empty()) - { - val = read_result_register(); - } - clear_data_ready(); - clear_result_ready(); - - /* Clear out the data */ - while (is_data_requested()) - { - val = read_data_register(); - } - abort_read_started = 0; - - /* If something was waiting, wake it up now. */ - if (waitqueue_active(&cdu31a_irq_wait)) - { - disable_interrupts(); - wake_up(&cdu31a_irq_wait); - } - } - else if (waitqueue_active(&cdu31a_irq_wait)) - { - disable_interrupts(); - wake_up(&cdu31a_irq_wait); - } - else - { - disable_interrupts(); - printk("CDU31A: Got an interrupt but nothing was waiting\n"); - } + /* Clear out the data */ + while (is_data_requested()) { + val = read_data_register(); + } + abort_read_started = 0; + + /* If something was waiting, wake it up now. */ + if (waitqueue_active(&cdu31a_irq_wait)) { + disable_interrupts(); + wake_up(&cdu31a_irq_wait); + } + } else if (waitqueue_active(&cdu31a_irq_wait)) { + disable_interrupts(); + wake_up(&cdu31a_irq_wait); + } else { + disable_interrupts(); + printk + ("CDU31A: Got an interrupt but nothing was waiting\n"); + } } /* * give more verbose error messages */ -static unsigned char *translate_error( unsigned char err_code ) +static unsigned char *translate_error(unsigned char err_code) { - static unsigned char errbuf[80]; + static unsigned char errbuf[80]; - switch (err_code) { - case 0x10: return "illegal command "; - case 0x11: return "illegal parameter "; - - case 0x20: return "not loaded "; - case 0x21: return "no disc "; - case 0x22: return "not spinning "; - case 0x23: return "spinning "; - case 0x25: return "spindle servo "; - case 0x26: return "focus servo "; - case 0x29: return "eject mechanism "; - case 0x2a: return "audio playing "; - case 0x2c: return "emergency eject "; - - case 0x30: return "focus "; - case 0x31: return "frame sync "; - case 0x32: return "subcode address "; - case 0x33: return "block sync "; - case 0x34: return "header address "; - - case 0x40: return "illegal track read "; - case 0x41: return "mode 0 read "; - case 0x42: return "illegal mode read "; - case 0x43: return "illegal block size read "; - case 0x44: return "mode read "; - case 0x45: return "form read "; - case 0x46: return "leadout read "; - case 0x47: return "buffer overrun "; - - case 0x53: return "unrecoverable CIRC "; - case 0x57: return "unrecoverable LECC "; - - case 0x60: return "no TOC "; - case 0x61: return "invalid subcode data "; - case 0x63: return "focus on TOC read "; - case 0x64: return "frame sync on TOC read "; - case 0x65: return "TOC data "; - - case 0x70: return "hardware failure "; - case 0x91: return "leadin "; - case 0x92: return "leadout "; - case 0x93: return "data track "; - } - sprintf(errbuf, "unknown 0x%02x ", err_code); - return errbuf; + switch (err_code) { + case 0x10: + return "illegal command "; + case 0x11: + return "illegal parameter "; + + case 0x20: + return "not loaded "; + case 0x21: + return "no disc "; + case 0x22: + return "not spinning "; + case 0x23: + return "spinning "; + case 0x25: + return "spindle servo "; + case 0x26: + return "focus servo "; + case 0x29: + return "eject mechanism "; + case 0x2a: + return "audio playing "; + case 0x2c: + return "emergency eject "; + + case 0x30: + return "focus "; + case 0x31: + return "frame sync "; + case 0x32: + return "subcode address "; + case 0x33: + return "block sync "; + case 0x34: + return "header address "; + + case 0x40: + return "illegal track read "; + case 0x41: + return "mode 0 read "; + case 0x42: + return "illegal mode read "; + case 0x43: + return "illegal block size read "; + case 0x44: + return "mode read "; + case 0x45: + return "form read "; + case 0x46: + return "leadout read "; + case 0x47: + return "buffer overrun "; + + case 0x53: + return "unrecoverable CIRC "; + case 0x57: + return "unrecoverable LECC "; + + case 0x60: + return "no TOC "; + case 0x61: + return "invalid subcode data "; + case 0x63: + return "focus on TOC read "; + case 0x64: + return "frame sync on TOC read "; + case 0x65: + return "TOC data "; + + case 0x70: + return "hardware failure "; + case 0x91: + return "leadin "; + case 0x92: + return "leadout "; + case 0x93: + return "data track "; + } + sprintf(errbuf, "unknown 0x%02x ", err_code); + return errbuf; } /* * Set the drive parameters so the drive will auto-spin-up when a * disk is inserted. */ -static void -set_drive_params(int want_doublespeed) +static void set_drive_params(int want_doublespeed) { - unsigned char res_reg[12]; - unsigned int res_size; - unsigned char params[3]; - - - params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME; - params[1] = 0x00; /* Never spin down the drive. */ - do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, - params, - 2, - res_reg, - &res_size); - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk(" Unable to set spin-down time: 0x%2.2x\n", res_reg[1]); - } - - params[0] = SONY_SD_MECH_CONTROL; - params[1] = SONY_AUTO_SPIN_UP_BIT; /* Set auto spin up */ - - if (is_auto_eject) params[1] |= SONY_AUTO_EJECT_BIT; - - if (is_double_speed && want_doublespeed) - { - params[1] |= SONY_DOUBLE_SPEED_BIT; /* Set the drive to double speed if - possible */ - } - do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, - params, - 2, - res_reg, - &res_size); - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk(" Unable to set mechanical parameters: 0x%2.2x\n", res_reg[1]); - } + unsigned char res_reg[12]; + unsigned int res_size; + unsigned char params[3]; + + + params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME; + params[1] = 0x00; /* Never spin down the drive. */ + do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, + params, 2, res_reg, &res_size); + if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { + printk(" Unable to set spin-down time: 0x%2.2x\n", + res_reg[1]); + } + + params[0] = SONY_SD_MECH_CONTROL; + params[1] = SONY_AUTO_SPIN_UP_BIT; /* Set auto spin up */ + + if (is_auto_eject) + params[1] |= SONY_AUTO_EJECT_BIT; + + if (is_double_speed && want_doublespeed) { + params[1] |= SONY_DOUBLE_SPEED_BIT; /* Set the drive to double speed if + possible */ + } + do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, + params, 2, res_reg, &res_size); + if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { + printk(" Unable to set mechanical parameters: 0x%2.2x\n", + res_reg[1]); + } } /* @@ -706,13 +689,13 @@ */ static int scd_select_speed(struct cdrom_device_info *cdi, int speed) { - if (speed == 0) - sony_speed = 1; - else - sony_speed = speed - 1; + if (speed == 0) + sony_speed = 1; + else + sony_speed = speed - 1; - set_drive_params(sony_speed); - return 0; + set_drive_params(sony_speed); + return 0; } /* @@ -721,77 +704,69 @@ */ static int scd_lock_door(struct cdrom_device_info *cdi, int lock) { - if (lock == 0 && sony_usage == 1) - { - /* Unlock the door, only if nobody is using the drive */ - is_auto_eject = 1; - } else { - is_auto_eject = 0; - } - set_drive_params(sony_speed); - return 0; + if (lock == 0 && sony_usage == 1) { + /* Unlock the door, only if nobody is using the drive */ + is_auto_eject = 1; + } else { + is_auto_eject = 0; + } + set_drive_params(sony_speed); + return 0; } /* * This code will reset the drive and attempt to restore sane parameters. */ -static void -restart_on_error(void) +static void restart_on_error(void) { - unsigned char res_reg[12]; - unsigned int res_size; - unsigned int retry_count; - - - printk("cdu31a: Resetting drive on error\n"); - reset_drive(); - retry_count = jiffies + SONY_RESET_TIMEOUT; - while (time_before(jiffies, retry_count) && (!is_attention())) - { - sony_sleep(); - } - set_drive_params(sony_speed); - do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk("cdu31a: Unable to spin up drive: 0x%2.2x\n", res_reg[1]); - } + unsigned char res_reg[12]; + unsigned int res_size; + unsigned int retry_count; + + + printk("cdu31a: Resetting drive on error\n"); + reset_drive(); + retry_count = jiffies + SONY_RESET_TIMEOUT; + while (time_before(jiffies, retry_count) && (!is_attention())) { + sony_sleep(); + } + set_drive_params(sony_speed); + do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); + if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { + printk("cdu31a: Unable to spin up drive: 0x%2.2x\n", + res_reg[1]); + } - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(2*HZ); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(2 * HZ); - sony_get_toc(); + sony_get_toc(); } /* * This routine writes data to the parameter register. Since this should * happen fairly fast, it is polled with no OS waits between. */ -static int -write_params(unsigned char *params, - int num_params) +static int write_params(unsigned char *params, int num_params) { - unsigned int retry_count; + unsigned int retry_count; - retry_count = SONY_READY_RETRIES; - while ((retry_count > 0) && (!is_param_write_rdy())) - { - retry_count--; - } - if (!is_param_write_rdy()) - { - return -EIO; - } - - while (num_params > 0) - { - write_param(*params); - params++; - num_params--; - } + retry_count = SONY_READY_RETRIES; + while ((retry_count > 0) && (!is_param_write_rdy())) { + retry_count--; + } + if (!is_param_write_rdy()) { + return -EIO; + } + + while (num_params > 0) { + write_param(*params); + params++; + num_params--; + } - return 0; + return 0; } @@ -802,134 +777,125 @@ * the drive manual. */ static void -get_result(unsigned char *result_buffer, - unsigned int *result_size) +get_result(unsigned char *result_buffer, unsigned int *result_size) { - unsigned char a, b; - int i; - unsigned int retry_count; - - - while (handle_sony_cd_attention()) - ; - /* Wait for the result data to be ready */ - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (time_before(jiffies, retry_count) && (is_busy() || (!(is_result_ready())))) - { - sony_sleep(); - - while (handle_sony_cd_attention()) - ; - } - if (is_busy() || (!(is_result_ready()))) - { -#if DEBUG - printk("CDU31A timeout out %d\n", __LINE__); -#endif - result_buffer[0] = 0x20; - result_buffer[1] = SONY_TIMEOUT_OP_ERR; - *result_size = 2; - return; - } - - /* - * Get the first two bytes. This determines what else needs - * to be done. - */ - clear_result_ready(); - a = read_result_register(); - *result_buffer = a; - result_buffer++; - - /* Check for block error status result. */ - if ((a & 0xf0) == 0x50) - { - *result_size = 1; - return; - } - - b = read_result_register(); - *result_buffer = b; - result_buffer++; - *result_size = 2; - - /* - * 0x20 means an error occurred. Byte 2 will have the error code. - * Otherwise, the command succeeded, byte 2 will have the count of - * how many more status bytes are coming. - * - * The result register can be read 10 bytes at a time, a wait for - * result ready to be asserted must be done between every 10 bytes. - */ - if ((a & 0xf0) != 0x20) - { - if (b > 8) - { - for (i=0; i<8; i++) - { - *result_buffer = read_result_register(); - result_buffer++; - (*result_size)++; - } - b = b - 8; - - while (b > 10) - { - retry_count = SONY_READY_RETRIES; - while ((retry_count > 0) && (!is_result_ready())) - { - retry_count--; - } - if (!is_result_ready()) - { -#if DEBUG - printk("CDU31A timeout out %d\n", __LINE__); -#endif - result_buffer[0] = 0x20; - result_buffer[1] = SONY_TIMEOUT_OP_ERR; - *result_size = 2; - return; - } - - clear_result_ready(); - - for (i=0; i<10; i++) - { - *result_buffer = read_result_register(); - result_buffer++; - (*result_size)++; - } - b = b - 10; - } - - if (b > 0) - { - retry_count = SONY_READY_RETRIES; - while ((retry_count > 0) && (!is_result_ready())) - { - retry_count--; - } - if (!is_result_ready()) - { -#if DEBUG - printk("CDU31A timeout out %d\n", __LINE__); -#endif - result_buffer[0] = 0x20; - result_buffer[1] = SONY_TIMEOUT_OP_ERR; - *result_size = 2; - return; - } - } - } - - while (b > 0) - { - *result_buffer = read_result_register(); - result_buffer++; - (*result_size)++; - b--; - } - } + unsigned char a, b; + int i; + unsigned int retry_count; + + + while (handle_sony_cd_attention()); + /* Wait for the result data to be ready */ + retry_count = jiffies + SONY_JIFFIES_TIMEOUT; + while (time_before(jiffies, retry_count) + && (is_busy() || (!(is_result_ready())))) { + sony_sleep(); + + while (handle_sony_cd_attention()); + } + if (is_busy() || (!(is_result_ready()))) { +#if DEBUG + printk("CDU31A timeout out %d\n", __LINE__); +#endif + result_buffer[0] = 0x20; + result_buffer[1] = SONY_TIMEOUT_OP_ERR; + *result_size = 2; + return; + } + + /* + * Get the first two bytes. This determines what else needs + * to be done. + */ + clear_result_ready(); + a = read_result_register(); + *result_buffer = a; + result_buffer++; + + /* Check for block error status result. */ + if ((a & 0xf0) == 0x50) { + *result_size = 1; + return; + } + + b = read_result_register(); + *result_buffer = b; + result_buffer++; + *result_size = 2; + + /* + * 0x20 means an error occurred. Byte 2 will have the error code. + * Otherwise, the command succeeded, byte 2 will have the count of + * how many more status bytes are coming. + * + * The result register can be read 10 bytes at a time, a wait for + * result ready to be asserted must be done between every 10 bytes. + */ + if ((a & 0xf0) != 0x20) { + if (b > 8) { + for (i = 0; i < 8; i++) { + *result_buffer = read_result_register(); + result_buffer++; + (*result_size)++; + } + b = b - 8; + + while (b > 10) { + retry_count = SONY_READY_RETRIES; + while ((retry_count > 0) + && (!is_result_ready())) { + retry_count--; + } + if (!is_result_ready()) { +#if DEBUG + printk("CDU31A timeout out %d\n", + __LINE__); +#endif + result_buffer[0] = 0x20; + result_buffer[1] = + SONY_TIMEOUT_OP_ERR; + *result_size = 2; + return; + } + + clear_result_ready(); + + for (i = 0; i < 10; i++) { + *result_buffer = + read_result_register(); + result_buffer++; + (*result_size)++; + } + b = b - 10; + } + + if (b > 0) { + retry_count = SONY_READY_RETRIES; + while ((retry_count > 0) + && (!is_result_ready())) { + retry_count--; + } + if (!is_result_ready()) { +#if DEBUG + printk("CDU31A timeout out %d\n", + __LINE__); +#endif + result_buffer[0] = 0x20; + result_buffer[1] = + SONY_TIMEOUT_OP_ERR; + *result_size = 2; + return; + } + } + } + + while (b > 0) { + *result_buffer = read_result_register(); + result_buffer++; + (*result_size)++; + b--; + } + } } /* @@ -939,95 +905,81 @@ */ static void do_sony_cd_cmd(unsigned char cmd, - unsigned char *params, - unsigned int num_params, - unsigned char *result_buffer, - unsigned int *result_size) -{ - unsigned int retry_count; - int num_retries; - int recursive_call; - unsigned long flags; - - - save_flags(flags); - cli(); - if (current != has_cd_task) /* Allow recursive calls to this routine */ - { - while (sony_inuse) - { - interruptible_sleep_on(&sony_wait); - if (signal_pending(current)) - { - result_buffer[0] = 0x20; - result_buffer[1] = SONY_SIGNAL_OP_ERR; - *result_size = 2; - restore_flags(flags); - return; - } - } - sony_inuse = 1; - has_cd_task = current; - recursive_call = 0; - } - else - { - recursive_call = 1; - } + unsigned char *params, + unsigned int num_params, + unsigned char *result_buffer, unsigned int *result_size) +{ + unsigned int retry_count; + int num_retries; + int recursive_call; + unsigned long flags; + + + save_flags(flags); + cli(); + if (current != has_cd_task) { /* Allow recursive calls to this routine */ + while (sony_inuse) { + interruptible_sleep_on(&sony_wait); + if (signal_pending(current)) { + result_buffer[0] = 0x20; + result_buffer[1] = SONY_SIGNAL_OP_ERR; + *result_size = 2; + restore_flags(flags); + return; + } + } + sony_inuse = 1; + has_cd_task = current; + recursive_call = 0; + } else { + recursive_call = 1; + } - num_retries = 0; + num_retries = 0; retry_cd_operation: - while (handle_sony_cd_attention()) - ; + while (handle_sony_cd_attention()); + + sti(); - sti(); - - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (time_before(jiffies, retry_count) && (is_busy())) - { - sony_sleep(); - - while (handle_sony_cd_attention()) - ; - } - if (is_busy()) - { -#if DEBUG - printk("CDU31A timeout out %d\n", __LINE__); -#endif - result_buffer[0] = 0x20; - result_buffer[1] = SONY_TIMEOUT_OP_ERR; - *result_size = 2; - } - else - { - clear_result_ready(); - clear_param_reg(); - - write_params(params, num_params); - write_cmd(cmd); - - get_result(result_buffer, result_size); - } - - if ( ((result_buffer[0] & 0xf0) == 0x20) - && (num_retries < MAX_CDU31A_RETRIES)) - { - num_retries++; - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); /* Wait .1 seconds on retries */ - goto retry_cd_operation; - } - - if (!recursive_call) - { - has_cd_task = NULL; - sony_inuse = 0; - wake_up_interruptible(&sony_wait); - } + retry_count = jiffies + SONY_JIFFIES_TIMEOUT; + while (time_before(jiffies, retry_count) && (is_busy())) { + sony_sleep(); + + while (handle_sony_cd_attention()); + } + if (is_busy()) { +#if DEBUG + printk("CDU31A timeout out %d\n", __LINE__); +#endif + result_buffer[0] = 0x20; + result_buffer[1] = SONY_TIMEOUT_OP_ERR; + *result_size = 2; + } else { + clear_result_ready(); + clear_param_reg(); + + write_params(params, num_params); + write_cmd(cmd); + + get_result(result_buffer, result_size); + } + + if (((result_buffer[0] & 0xf0) == 0x20) + && (num_retries < MAX_CDU31A_RETRIES)) { + num_retries++; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ / 10); /* Wait .1 seconds on retries */ + goto retry_cd_operation; + } + + if (!recursive_call) { + has_cd_task = NULL; + sony_inuse = 0; + wake_up_interruptible(&sony_wait); + } - restore_flags(flags); + restore_flags(flags); } @@ -1040,120 +992,114 @@ * a 0), and returns a 0 if it happens too many times. This will help * prevent a lockup. */ -static int -handle_sony_cd_attention(void) +static int handle_sony_cd_attention(void) { - unsigned char atten_code; - static int num_consecutive_attentions = 0; - volatile int val; + unsigned char atten_code; + static int num_consecutive_attentions = 0; + volatile int val; #if 0*DEBUG - printk("Entering handle_sony_cd_attention\n"); + printk("Entering handle_sony_cd_attention\n"); #endif - if (is_attention()) - { - if (num_consecutive_attentions > CDU31A_MAX_CONSECUTIVE_ATTENTIONS) - { - printk("cdu31a: Too many consecutive attentions: %d\n", - num_consecutive_attentions); - num_consecutive_attentions = 0; -#if DEBUG - printk("Leaving handle_sony_cd_attention at %d\n", __LINE__); -#endif - return(0); - } - - clear_attention(); - atten_code = read_result_register(); - - switch (atten_code) - { - /* Someone changed the CD. Mark it as changed */ - case SONY_MECH_LOADED_ATTN: - disk_changed = 1; - sony_toc_read = 0; - sony_audio_status = CDROM_AUDIO_NO_STATUS; - sony_blocks_left = 0; - break; - - case SONY_SPIN_DOWN_COMPLETE_ATTN: - /* Mark the disk as spun down. */ - sony_spun_up = 0; - break; - - case SONY_AUDIO_PLAY_DONE_ATTN: - sony_audio_status = CDROM_AUDIO_COMPLETED; - read_subcode(); - break; - - case SONY_EJECT_PUSHED_ATTN: - if (is_auto_eject) - { - sony_audio_status = CDROM_AUDIO_INVALID; - } - break; - - case SONY_LEAD_IN_ERR_ATTN: - case SONY_LEAD_OUT_ERR_ATTN: - case SONY_DATA_TRACK_ERR_ATTN: - case SONY_AUDIO_PLAYBACK_ERR_ATTN: - sony_audio_status = CDROM_AUDIO_ERROR; - break; - } - - num_consecutive_attentions++; -#if DEBUG - printk("Leaving handle_sony_cd_attention at %d\n", __LINE__); -#endif - return(1); - } - else if (abort_read_started) - { - while (is_result_reg_not_empty()) - { - val = read_result_register(); - } - clear_data_ready(); - clear_result_ready(); - /* Clear out the data */ - while (is_data_requested()) - { - val = read_data_register(); - } - abort_read_started = 0; + if (is_attention()) { + if (num_consecutive_attentions > + CDU31A_MAX_CONSECUTIVE_ATTENTIONS) { + printk + ("cdu31a: Too many consecutive attentions: %d\n", + num_consecutive_attentions); + num_consecutive_attentions = 0; +#if DEBUG + printk("Leaving handle_sony_cd_attention at %d\n", + __LINE__); +#endif + return (0); + } + + clear_attention(); + atten_code = read_result_register(); + + switch (atten_code) { + /* Someone changed the CD. Mark it as changed */ + case SONY_MECH_LOADED_ATTN: + disk_changed = 1; + sony_toc_read = 0; + sony_audio_status = CDROM_AUDIO_NO_STATUS; + sony_blocks_left = 0; + break; + + case SONY_SPIN_DOWN_COMPLETE_ATTN: + /* Mark the disk as spun down. */ + sony_spun_up = 0; + break; + + case SONY_AUDIO_PLAY_DONE_ATTN: + sony_audio_status = CDROM_AUDIO_COMPLETED; + read_subcode(); + break; + + case SONY_EJECT_PUSHED_ATTN: + if (is_auto_eject) { + sony_audio_status = CDROM_AUDIO_INVALID; + } + break; + + case SONY_LEAD_IN_ERR_ATTN: + case SONY_LEAD_OUT_ERR_ATTN: + case SONY_DATA_TRACK_ERR_ATTN: + case SONY_AUDIO_PLAYBACK_ERR_ATTN: + sony_audio_status = CDROM_AUDIO_ERROR; + break; + } + + num_consecutive_attentions++; +#if DEBUG + printk("Leaving handle_sony_cd_attention at %d\n", + __LINE__); +#endif + return (1); + } else if (abort_read_started) { + while (is_result_reg_not_empty()) { + val = read_result_register(); + } + clear_data_ready(); + clear_result_ready(); + /* Clear out the data */ + while (is_data_requested()) { + val = read_data_register(); + } + abort_read_started = 0; #if DEBUG - printk("Leaving handle_sony_cd_attention at %d\n", __LINE__); + printk("Leaving handle_sony_cd_attention at %d\n", + __LINE__); #endif - return(1); - } + return (1); + } - num_consecutive_attentions = 0; + num_consecutive_attentions = 0; #if 0*DEBUG - printk("Leaving handle_sony_cd_attention at %d\n", __LINE__); + printk("Leaving handle_sony_cd_attention at %d\n", __LINE__); #endif - return(0); + return (0); } /* Convert from an integer 0-99 to BCD */ -static inline unsigned int -int_to_bcd(unsigned int val) +static inline unsigned int int_to_bcd(unsigned int val) { - int retval; + int retval; - retval = (val / 10) << 4; - retval = retval | val % 10; - return(retval); + retval = (val / 10) << 4; + retval = retval | val % 10; + return (retval); } /* Convert from BCD to an integer from 0-99 */ -static unsigned int -bcd_to_int(unsigned int bcd) +static unsigned int bcd_to_int(unsigned int bcd) { - return((((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f)); + return ((((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f)); } @@ -1161,32 +1107,30 @@ * Convert a logical sector value (like the OS would want to use for * a block device) to an MSF format. */ -static void -log_to_msf(unsigned int log, unsigned char *msf) +static void log_to_msf(unsigned int log, unsigned char *msf) { - log = log + LOG_START_OFFSET; - msf[0] = int_to_bcd(log / 4500); - log = log % 4500; - msf[1] = int_to_bcd(log / 75); - msf[2] = int_to_bcd(log % 75); + log = log + LOG_START_OFFSET; + msf[0] = int_to_bcd(log / 4500); + log = log % 4500; + msf[1] = int_to_bcd(log / 75); + msf[2] = int_to_bcd(log % 75); } /* * Convert an MSF format to a logical sector. */ -static unsigned int -msf_to_log(unsigned char *msf) +static unsigned int msf_to_log(unsigned char *msf) { - unsigned int log; + unsigned int log; - log = msf[2]; - log += msf[1] * 75; - log += msf[0] * 4500; - log = log - LOG_START_OFFSET; + log = msf[2]; + log += msf[1] * 75; + log += msf[0] * 4500; + log = log - LOG_START_OFFSET; - return log; + return log; } @@ -1194,14 +1138,12 @@ * Take in integer size value and put it into a buffer like * the drive would want to see a number-of-sector value. */ -static void -size_to_buf(unsigned int size, - unsigned char *buf) +static void size_to_buf(unsigned int size, unsigned char *buf) { - buf[0] = size / 65536; - size = size % 65536; - buf[1] = size / 256; - buf[2] = size % 256; + buf[0] = size / 65536; + size = size % 65536; + buf[1] = size / 256; + buf[2] = size % 256; } /* Starts a read operation. Returns 0 on success and 1 on failure. @@ -1211,430 +1153,380 @@ operation if the requested sector is not the next one from the drive. */ static int -start_request(unsigned int sector, - unsigned int nsect, - int read_nsect_only) -{ - unsigned char params[6]; - unsigned int read_size; - unsigned int retry_count; - - -#if DEBUG - printk("Entering start_request\n"); -#endif - log_to_msf(sector, params); - /* If requested, read exactly what was asked. */ - if (read_nsect_only) - { - read_size = nsect; - } - /* - * If the full read-ahead would go beyond the end of the media, trim - * it back to read just till the end of the media. - */ - else if ((sector + nsect) >= sony_toc.lead_out_start_lba) - { - read_size = sony_toc.lead_out_start_lba - sector; - } - /* Read the full readahead amount. */ - else - { - read_size = CDU31A_READAHEAD / 4; - } - size_to_buf(read_size, ¶ms[3]); - - /* - * Clear any outstanding attentions and wait for the drive to - * complete any pending operations. - */ - while (handle_sony_cd_attention()) - ; - - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (time_before(jiffies, retry_count) && (is_busy())) - { - sony_sleep(); - - while (handle_sony_cd_attention()) - ; - } - - if (is_busy()) - { - printk("CDU31A: Timeout while waiting to issue command\n"); -#if DEBUG - printk("Leaving start_request at %d\n", __LINE__); -#endif - return(1); - } - else - { - /* Issue the command */ - clear_result_ready(); - clear_param_reg(); - - write_params(params, 6); - write_cmd(SONY_READ_BLKERR_STAT_CMD); - - sony_blocks_left = read_size * 4; - sony_next_block = sector * 4; - readahead_dataleft = 0; - readahead_bad = 0; +start_request(unsigned int sector, unsigned int nsect, int read_nsect_only) +{ + unsigned char params[6]; + unsigned int read_size; + unsigned int retry_count; + + +#if DEBUG + printk("Entering start_request\n"); +#endif + log_to_msf(sector, params); + /* If requested, read exactly what was asked. */ + if (read_nsect_only) { + read_size = nsect; + } + /* + * If the full read-ahead would go beyond the end of the media, trim + * it back to read just till the end of the media. + */ + else if ((sector + nsect) >= sony_toc.lead_out_start_lba) { + read_size = sony_toc.lead_out_start_lba - sector; + } + /* Read the full readahead amount. */ + else { + read_size = CDU31A_READAHEAD / 4; + } + size_to_buf(read_size, ¶ms[3]); + + /* + * Clear any outstanding attentions and wait for the drive to + * complete any pending operations. + */ + while (handle_sony_cd_attention()); + + retry_count = jiffies + SONY_JIFFIES_TIMEOUT; + while (time_before(jiffies, retry_count) && (is_busy())) { + sony_sleep(); + + while (handle_sony_cd_attention()); + } + + if (is_busy()) { + printk("CDU31A: Timeout while waiting to issue command\n"); +#if DEBUG + printk("Leaving start_request at %d\n", __LINE__); +#endif + return (1); + } else { + /* Issue the command */ + clear_result_ready(); + clear_param_reg(); + + write_params(params, 6); + write_cmd(SONY_READ_BLKERR_STAT_CMD); + + sony_blocks_left = read_size * 4; + sony_next_block = sector * 4; + readahead_dataleft = 0; + readahead_bad = 0; #if DEBUG - printk("Leaving start_request at %d\n", __LINE__); + printk("Leaving start_request at %d\n", __LINE__); #endif - return(0); - } + return (0); + } #if DEBUG - printk("Leaving start_request at %d\n", __LINE__); + printk("Leaving start_request at %d\n", __LINE__); #endif } /* Abort a pending read operation. Clear all the drive status and readahead variables. */ -static void -abort_read(void) +static void abort_read(void) { - unsigned char result_reg[2]; - int result_size; - volatile int val; - - - do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size); - if ((result_reg[0] & 0xf0) == 0x20) - { - printk("CDU31A: Error aborting read, %s error\n", - translate_error( - result_reg[1])); - } - - while (is_result_reg_not_empty()) - { - val = read_result_register(); - } - clear_data_ready(); - clear_result_ready(); - /* Clear out the data */ - while (is_data_requested()) - { - val = read_data_register(); - } - - sony_blocks_left = 0; - readahead_dataleft = 0; - readahead_bad = 0; + unsigned char result_reg[2]; + int result_size; + volatile int val; + + + do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size); + if ((result_reg[0] & 0xf0) == 0x20) { + printk("CDU31A: Error aborting read, %s error\n", + translate_error(result_reg[1])); + } + + while (is_result_reg_not_empty()) { + val = read_result_register(); + } + clear_data_ready(); + clear_result_ready(); + /* Clear out the data */ + while (is_data_requested()) { + val = read_data_register(); + } + + sony_blocks_left = 0; + readahead_dataleft = 0; + readahead_bad = 0; } /* Called when the timer times out. This will abort the pending read operation. */ -static void -handle_abort_timeout(unsigned long data) +static void handle_abort_timeout(unsigned long data) { - unsigned long flags; + unsigned long flags; #if DEBUG - printk("Entering handle_abort_timeout\n"); + printk("Entering handle_abort_timeout\n"); #endif - save_flags(flags); - cli(); - /* If it is in use, ignore it. */ - if (!sony_inuse) - { - /* We can't use abort_read(), because it will sleep - or schedule in the timer interrupt. Just start - the operation, finish it on the next access to - the drive. */ - clear_result_ready(); - clear_param_reg(); - write_cmd(SONY_ABORT_CMD); - - sony_blocks_left = 0; - readahead_dataleft = 0; - readahead_bad = 0; - abort_read_started = 1; - } - restore_flags(flags); + save_flags(flags); + cli(); + /* If it is in use, ignore it. */ + if (!sony_inuse) { + /* We can't use abort_read(), because it will sleep + or schedule in the timer interrupt. Just start + the operation, finish it on the next access to + the drive. */ + clear_result_ready(); + clear_param_reg(); + write_cmd(SONY_ABORT_CMD); + + sony_blocks_left = 0; + readahead_dataleft = 0; + readahead_bad = 0; + abort_read_started = 1; + } + restore_flags(flags); #if DEBUG - printk("Leaving handle_abort_timeout\n"); + printk("Leaving handle_abort_timeout\n"); #endif } /* Actually get data and status from the drive. */ static void -input_data(char *buffer, - unsigned int bytesleft, - unsigned int nblocks, - unsigned int offset, - unsigned int skip) -{ - int i; - volatile unsigned char val; +input_data(char *buffer, + unsigned int bytesleft, + unsigned int nblocks, unsigned int offset, unsigned int skip) +{ + int i; + volatile unsigned char val; #if DEBUG - printk("Entering input_data\n"); -#endif - /* If an XA disk on a CDU31A, skip the first 12 bytes of data from - the disk. The real data is after that. */ - if (sony_xa_mode) - { - for(i=0; i readahead_dataleft) - { - /* The readahead will not fill the requested buffer, but - get the data out of the readahead into the buffer. */ - memcpy(buffer, - readahead_buffer + (2048 - readahead_dataleft), - readahead_dataleft); - readahead_dataleft = 0; - bytesleft -= readahead_dataleft; - offset += readahead_dataleft; - } - else - { - /* The readahead will fill the whole buffer, get the data - and return. */ - memcpy(buffer, - readahead_buffer + (2048 - readahead_dataleft), - bytesleft); - readahead_dataleft -= bytesleft; - bytesleft = 0; - sony_blocks_left -= nblocks; - sony_next_block += nblocks; - - /* If the data in the readahead is bad, return an error so the - driver will abort the buffer. */ - if (readahead_bad) - { - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - } - - if (readahead_dataleft == 0) - { - readahead_bad = 0; - } - - /* Final transfer is done for read command, get final result. */ - if (sony_blocks_left == 0) - { - get_result(res_reg, res_size); - } -#if DEBUG - printk("Leaving read_data_block at %d\n", __LINE__); -#endif - return; - } - } - - /* Wait for the drive to tell us we have something */ - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (time_before(jiffies, retry_count) && !(is_data_ready())) - { - while (handle_sony_cd_attention()) - ; - - sony_sleep(); - } - if (!(is_data_ready())) - { - if (is_result_ready()) - { - get_result(res_reg, res_size); - if ((res_reg[0] & 0xf0) != 0x20) - { - printk("CDU31A: Got result that should have been error: %d\n", - res_reg[0]); - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - } - abort_read(); - } - else - { -#if DEBUG - printk("CDU31A timeout out %d\n", __LINE__); -#endif - res_reg[0] = 0x20; - res_reg[1] = SONY_TIMEOUT_OP_ERR; - *res_size = 2; - abort_read(); - } - } - else - { - input_data(buffer, bytesleft, nblocks, offset, skip); - - /* Wait for the status from the drive. */ - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (time_before(jiffies, retry_count) && !(is_result_ready())) - { - while (handle_sony_cd_attention()) - ; - - sony_sleep(); - } - - if (!is_result_ready()) - { -#if DEBUG - printk("CDU31A timeout out %d\n", __LINE__); -#endif - res_reg[0] = 0x20; - res_reg[1] = SONY_TIMEOUT_OP_ERR; - *res_size = 2; - abort_read(); - } - else - { - get_result(res_reg, res_size); - - /* If we got a buffer status, handle that. */ - if ((res_reg[0] & 0xf0) == 0x50) - { - - if ( (res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT) - || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT) - || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT)) - { - /* The data was successful, but if data was read from - the readahead and it was bad, set the whole - buffer as bad. */ - if (readahead_bad) - { - readahead_bad = 0; - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - } - } - else - { - printk("CDU31A: Data block error: 0x%x\n", res_reg[0]); - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - - /* Data is in the readahead buffer but an error was returned. - Make sure future requests don't use the data. */ - if (bytesleft != 2048) - { - readahead_bad = 1; - } - } - - /* Final transfer is done for read command, get final result. */ - if (sony_blocks_left == 0) - { - get_result(res_reg, res_size); - } - } - else if ((res_reg[0] & 0xf0) != 0x20) - { - /* The drive gave me bad status, I don't know what to do. - Reset the driver and return an error. */ - printk("CDU31A: Invalid block status: 0x%x\n", res_reg[0]); - restart_on_error(); - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - } - } - } +read_data_block(char *buffer, + unsigned int block, + unsigned int nblocks, + unsigned char res_reg[], int *res_size) +{ + unsigned int retry_count; + unsigned int bytesleft; + unsigned int offset; + unsigned int skip; + + +#if DEBUG + printk("Entering read_data_block\n"); +#endif + + res_reg[0] = 0; + res_reg[1] = 0; + *res_size = 0; + bytesleft = nblocks * 512; + offset = 0; + + /* If the data in the read-ahead does not match the block offset, + then fix things up. */ + if (((block % 4) * 512) != ((2048 - readahead_dataleft) % 2048)) { + sony_next_block += block % 4; + sony_blocks_left -= block % 4; + skip = (block % 4) * 512; + } else { + skip = 0; + } + + /* We have readahead data in the buffer, get that first before we + decide if a read is necessary. */ + if (readahead_dataleft != 0) { + if (bytesleft > readahead_dataleft) { + /* The readahead will not fill the requested buffer, but + get the data out of the readahead into the buffer. */ + memcpy(buffer, + readahead_buffer + (2048 - + readahead_dataleft), + readahead_dataleft); + readahead_dataleft = 0; + bytesleft -= readahead_dataleft; + offset += readahead_dataleft; + } else { + /* The readahead will fill the whole buffer, get the data + and return. */ + memcpy(buffer, + readahead_buffer + (2048 - + readahead_dataleft), + bytesleft); + readahead_dataleft -= bytesleft; + bytesleft = 0; + sony_blocks_left -= nblocks; + sony_next_block += nblocks; + + /* If the data in the readahead is bad, return an error so the + driver will abort the buffer. */ + if (readahead_bad) { + res_reg[0] = 0x20; + res_reg[1] = SONY_BAD_DATA_ERR; + *res_size = 2; + } + + if (readahead_dataleft == 0) { + readahead_bad = 0; + } + + /* Final transfer is done for read command, get final result. */ + if (sony_blocks_left == 0) { + get_result(res_reg, res_size); + } +#if DEBUG + printk("Leaving read_data_block at %d\n", + __LINE__); +#endif + return; + } + } + + /* Wait for the drive to tell us we have something */ + retry_count = jiffies + SONY_JIFFIES_TIMEOUT; + while (time_before(jiffies, retry_count) && !(is_data_ready())) { + while (handle_sony_cd_attention()); + + sony_sleep(); + } + if (!(is_data_ready())) { + if (is_result_ready()) { + get_result(res_reg, res_size); + if ((res_reg[0] & 0xf0) != 0x20) { + printk + ("CDU31A: Got result that should have been error: %d\n", + res_reg[0]); + res_reg[0] = 0x20; + res_reg[1] = SONY_BAD_DATA_ERR; + *res_size = 2; + } + abort_read(); + } else { +#if DEBUG + printk("CDU31A timeout out %d\n", __LINE__); +#endif + res_reg[0] = 0x20; + res_reg[1] = SONY_TIMEOUT_OP_ERR; + *res_size = 2; + abort_read(); + } + } else { + input_data(buffer, bytesleft, nblocks, offset, skip); + + /* Wait for the status from the drive. */ + retry_count = jiffies + SONY_JIFFIES_TIMEOUT; + while (time_before(jiffies, retry_count) + && !(is_result_ready())) { + while (handle_sony_cd_attention()); + + sony_sleep(); + } + + if (!is_result_ready()) { +#if DEBUG + printk("CDU31A timeout out %d\n", __LINE__); +#endif + res_reg[0] = 0x20; + res_reg[1] = SONY_TIMEOUT_OP_ERR; + *res_size = 2; + abort_read(); + } else { + get_result(res_reg, res_size); + + /* If we got a buffer status, handle that. */ + if ((res_reg[0] & 0xf0) == 0x50) { + + if ((res_reg[0] == + SONY_NO_CIRC_ERR_BLK_STAT) + || (res_reg[0] == + SONY_NO_LECC_ERR_BLK_STAT) + || (res_reg[0] == + SONY_RECOV_LECC_ERR_BLK_STAT)) { + /* The data was successful, but if data was read from + the readahead and it was bad, set the whole + buffer as bad. */ + if (readahead_bad) { + readahead_bad = 0; + res_reg[0] = 0x20; + res_reg[1] = + SONY_BAD_DATA_ERR; + *res_size = 2; + } + } else { + printk + ("CDU31A: Data block error: 0x%x\n", + res_reg[0]); + res_reg[0] = 0x20; + res_reg[1] = SONY_BAD_DATA_ERR; + *res_size = 2; + + /* Data is in the readahead buffer but an error was returned. + Make sure future requests don't use the data. */ + if (bytesleft != 2048) { + readahead_bad = 1; + } + } + + /* Final transfer is done for read command, get final result. */ + if (sony_blocks_left == 0) { + get_result(res_reg, res_size); + } + } else if ((res_reg[0] & 0xf0) != 0x20) { + /* The drive gave me bad status, I don't know what to do. + Reset the driver and return an error. */ + printk + ("CDU31A: Invalid block status: 0x%x\n", + res_reg[0]); + restart_on_error(); + res_reg[0] = 0x20; + res_reg[1] = SONY_BAD_DATA_ERR; + *res_size = 2; + } + } + } #if DEBUG - printk("Leaving read_data_block at %d\n", __LINE__); + printk("Leaving read_data_block at %d\n", __LINE__); #endif } @@ -1646,230 +1538,215 @@ * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most * data access on a CD is done sequentially, this saves a lot of operations. */ -static void -do_cdu31a_request(request_queue_t * q) +static void do_cdu31a_request(request_queue_t * q) { - int block; - int nblock; - unsigned char res_reg[12]; - unsigned int res_size; - int num_retries; - unsigned long flags; - - -#if DEBUG - printk("Entering do_cdu31a_request\n"); -#endif - - /* - * Make sure no one else is using the driver; wait for them - * to finish if it is so. - */ - save_flags(flags); - cli(); - while (sony_inuse) - { - interruptible_sleep_on(&sony_wait); - if (signal_pending(current)) - { - restore_flags(flags); - if (!QUEUE_EMPTY && CURRENT->rq_status != RQ_INACTIVE) - { - end_request(0); - } - restore_flags(flags); -#if DEBUG - printk("Leaving do_cdu31a_request at %d\n", __LINE__); -#endif - return; - } - } - sony_inuse = 1; - has_cd_task = current; - - /* Get drive status before doing anything. */ - while (handle_sony_cd_attention()) - ; - - /* Make sure we have a valid TOC. */ - sony_get_toc(); - - spin_unlock_irq(&io_request_lock); - - /* Make sure the timer is cancelled. */ - del_timer(&cdu31a_abort_timer); - - while (1) - { -cdu31a_request_startover: - /* - * The beginning here is stolen from the hard disk driver. I hope - * it's right. - */ - if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE) - { - goto end_do_cdu31a_request; - } - - if (!sony_spun_up) - { - scd_spinup(); - } - - /* I don't use INIT_REQUEST because it calls return, which would - return without unlocking the device. It shouldn't matter, - but just to be safe... */ - if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) - { - panic(DEVICE_NAME ": request list destroyed"); - } - if (CURRENT->bh) - { - if (!buffer_locked(CURRENT->bh)) - { - panic(DEVICE_NAME ": block not locked"); - } - } - - block = CURRENT->sector; - nblock = CURRENT->nr_sectors; - - if (!sony_toc_read) - { - printk("CDU31A: TOC not read\n"); - end_request(0); - goto cdu31a_request_startover; - } - - switch(CURRENT->cmd) - { - case READ: - /* - * If the block address is invalid or the request goes beyond the end of - * the media, return an error. - */ + int block; + int nblock; + unsigned char res_reg[12]; + unsigned int res_size; + int num_retries; + unsigned long flags; + + +#if DEBUG + printk("Entering do_cdu31a_request\n"); +#endif + + /* + * Make sure no one else is using the driver; wait for them + * to finish if it is so. + */ + save_flags(flags); + cli(); + while (sony_inuse) { + interruptible_sleep_on(&sony_wait); + if (signal_pending(current)) { + restore_flags(flags); + if (!QUEUE_EMPTY + && CURRENT->rq_status != RQ_INACTIVE) { + end_request(0); + } + restore_flags(flags); +#if DEBUG + printk("Leaving do_cdu31a_request at %d\n", + __LINE__); +#endif + return; + } + } + sony_inuse = 1; + has_cd_task = current; + + /* Get drive status before doing anything. */ + while (handle_sony_cd_attention()); + + /* Make sure we have a valid TOC. */ + sony_get_toc(); + + spin_unlock_irq(&io_request_lock); + + /* Make sure the timer is cancelled. */ + del_timer(&cdu31a_abort_timer); + + while (1) { + cdu31a_request_startover: + /* + * The beginning here is stolen from the hard disk driver. I hope + * it's right. + */ + if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE) { + goto end_do_cdu31a_request; + } + + if (!sony_spun_up) { + scd_spinup(); + } + + /* I don't use INIT_REQUEST because it calls return, which would + return without unlocking the device. It shouldn't matter, + but just to be safe... */ + if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) { + panic(DEVICE_NAME ": request list destroyed"); + } + if (CURRENT->bh) { + if (!buffer_locked(CURRENT->bh)) { + panic(DEVICE_NAME ": block not locked"); + } + } + + block = CURRENT->sector; + nblock = CURRENT->nr_sectors; + + if (!sony_toc_read) { + printk("CDU31A: TOC not read\n"); + end_request(0); + goto cdu31a_request_startover; + } + + switch (CURRENT->cmd) { + case READ: + /* + * If the block address is invalid or the request goes beyond the end of + * the media, return an error. + */ #if 0 - if ((block / 4) < sony_toc.start_track_lba) - { - printk("CDU31A: Request before beginning of media\n"); - end_request(0); - goto cdu31a_request_startover; - } -#endif - if ((block / 4) >= sony_toc.lead_out_start_lba) - { - printk("CDU31A: Request past end of media\n"); - end_request(0); - goto cdu31a_request_startover; - } - if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) - { - printk("CDU31A: Request past end of media\n"); - end_request(0); - goto cdu31a_request_startover; - } - - num_retries = 0; - -try_read_again: - while (handle_sony_cd_attention()) - ; - - if (!sony_toc_read) - { - printk("CDU31A: TOC not read\n"); - end_request(0); - goto cdu31a_request_startover; - } - - /* If no data is left to be read from the drive, start the - next request. */ - if (sony_blocks_left == 0) - { - if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) - { - end_request(0); - goto cdu31a_request_startover; - } - } - /* If the requested block is not the next one waiting in - the driver, abort the current operation and start a - new one. */ - else if (block != sony_next_block) - { -#if DEBUG - printk("CDU31A Warning: Read for block %d, expected %d\n", - block, - sony_next_block); -#endif - abort_read(); - if (!sony_toc_read) - { - printk("CDU31A: TOC not read\n"); - end_request(0); - goto cdu31a_request_startover; - } - if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) - { - printk("CDU31a: start request failed\n"); - end_request(0); - goto cdu31a_request_startover; - } - } - - read_data_block(CURRENT->buffer, block, nblock, res_reg, &res_size); - if (res_reg[0] == 0x20) - { - if (num_retries > MAX_CDU31A_RETRIES) - { - end_request(0); - goto cdu31a_request_startover; - } - - num_retries++; - if (res_reg[1] == SONY_NOT_SPIN_ERR) - { - do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); - } - else - { - printk("CDU31A: %s error for block %d, nblock %d\n", translate_error(res_reg[1]), block, nblock); - } - goto try_read_again; - } - else - { - end_request(1); - } - break; - - case WRITE: - end_request(0); - break; - - default: - panic("CDU31A: Unknown cmd"); - } - } + if ((block / 4) < sony_toc.start_track_lba) { + printk + ("CDU31A: Request before beginning of media\n"); + end_request(0); + goto cdu31a_request_startover; + } +#endif + if ((block / 4) >= sony_toc.lead_out_start_lba) { + printk + ("CDU31A: Request past end of media\n"); + end_request(0); + goto cdu31a_request_startover; + } + if (((block + nblock) / 4) >= + sony_toc.lead_out_start_lba) { + printk + ("CDU31A: Request past end of media\n"); + end_request(0); + goto cdu31a_request_startover; + } + + num_retries = 0; + + try_read_again: + while (handle_sony_cd_attention()); + + if (!sony_toc_read) { + printk("CDU31A: TOC not read\n"); + end_request(0); + goto cdu31a_request_startover; + } + + /* If no data is left to be read from the drive, start the + next request. */ + if (sony_blocks_left == 0) { + if (start_request + (block / 4, CDU31A_READAHEAD / 4, 0)) { + end_request(0); + goto cdu31a_request_startover; + } + } + /* If the requested block is not the next one waiting in + the driver, abort the current operation and start a + new one. */ + else if (block != sony_next_block) { +#if DEBUG + printk + ("CDU31A Warning: Read for block %d, expected %d\n", + block, sony_next_block); +#endif + abort_read(); + if (!sony_toc_read) { + printk("CDU31A: TOC not read\n"); + end_request(0); + goto cdu31a_request_startover; + } + if (start_request + (block / 4, CDU31A_READAHEAD / 4, 0)) { + printk + ("CDU31a: start request failed\n"); + end_request(0); + goto cdu31a_request_startover; + } + } + + read_data_block(CURRENT->buffer, block, nblock, + res_reg, &res_size); + if (res_reg[0] == 0x20) { + if (num_retries > MAX_CDU31A_RETRIES) { + end_request(0); + goto cdu31a_request_startover; + } + + num_retries++; + if (res_reg[1] == SONY_NOT_SPIN_ERR) { + do_sony_cd_cmd(SONY_SPIN_UP_CMD, + NULL, 0, res_reg, + &res_size); + } else { + printk + ("CDU31A: %s error for block %d, nblock %d\n", + translate_error(res_reg[1]), + block, nblock); + } + goto try_read_again; + } else { + end_request(1); + } + break; + + case WRITE: + end_request(0); + break; + + default: + panic("CDU31A: Unknown cmd"); + } + } -end_do_cdu31a_request: - spin_lock_irq(&io_request_lock); + end_do_cdu31a_request: + spin_lock_irq(&io_request_lock); #if 0 - /* After finished, cancel any pending operations. */ - abort_read(); + /* After finished, cancel any pending operations. */ + abort_read(); #else - /* Start a timer to time out after a while to disable - the read. */ - cdu31a_abort_timer.expires = jiffies + 2*HZ; /* Wait 2 seconds */ - add_timer(&cdu31a_abort_timer); + /* Start a timer to time out after a while to disable + the read. */ + cdu31a_abort_timer.expires = jiffies + 2 * HZ; /* Wait 2 seconds */ + add_timer(&cdu31a_abort_timer); #endif - has_cd_task = NULL; - sony_inuse = 0; - wake_up_interruptible(&sony_wait); - restore_flags(flags); + has_cd_task = NULL; + sony_inuse = 0; + wake_up_interruptible(&sony_wait); + restore_flags(flags); #if DEBUG - printk("Leaving do_cdu31a_request at %d\n", __LINE__); + printk("Leaving do_cdu31a_request at %d\n", __LINE__); #endif } @@ -1878,356 +1755,473 @@ * Read the table of contents from the drive and set up TOC if * successful. */ -static void -sony_get_toc(void) +static void sony_get_toc(void) { - unsigned char res_reg[2]; - unsigned int res_size; - unsigned char parms[1]; - int session; - int num_spin_ups; - int totaltracks = 0; - int mint = 99; - int maxt = 0; - -#if DEBUG - printk("Entering sony_get_toc\n"); -#endif - - num_spin_ups = 0; - if (!sony_toc_read) - { -respinup_on_gettoc: - /* Ignore the result, since it might error if spinning already. */ - do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); - - do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size); - - /* The drive sometimes returns error 0. I don't know why, but ignore - it. It seems to mean the drive has already done the operation. */ - if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) - { - /* If the drive is already playing, it's ok. */ - if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) || (res_reg[1] == 0)) - { - goto gettoc_drive_spinning; - } - - /* If the drive says it is not spun up (even though we just did it!) - then retry the operation at least a few times. */ - if ( (res_reg[1] == SONY_NOT_SPIN_ERR) - && (num_spin_ups < MAX_CDU31A_RETRIES)) - { - num_spin_ups++; - goto respinup_on_gettoc; - } - - printk("cdu31a: Error reading TOC: %x %s\n", - res_reg[0], translate_error(res_reg[1])); - return; - } - -gettoc_drive_spinning: - - /* The idea here is we keep asking for sessions until the command - fails. Then we know what the last valid session on the disk is. - No need to check session 0, since session 0 is the same as session - 1; the command returns different information if you give it 0. - */ -#if DEBUG - memset(&sony_toc, 0x0e, sizeof(sony_toc)); - memset(&single_toc, 0x0f, sizeof(single_toc)); -#endif - session = 1; - while (1) - { + unsigned char res_reg[2]; + unsigned int res_size; + unsigned char parms[1]; + int session; + int num_spin_ups; + int totaltracks = 0; + int mint = 99; + int maxt = 0; + +#if DEBUG + printk("Entering sony_get_toc\n"); +#endif + + num_spin_ups = 0; + if (!sony_toc_read) { + respinup_on_gettoc: + /* Ignore the result, since it might error if spinning already. */ + do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, + &res_size); + + do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, + &res_size); + + /* The drive sometimes returns error 0. I don't know why, but ignore + it. It seems to mean the drive has already done the operation. */ + if ((res_size < 2) + || ((res_reg[0] != 0) && (res_reg[1] != 0))) { + /* If the drive is already playing, it's ok. */ + if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) + || (res_reg[1] == 0)) { + goto gettoc_drive_spinning; + } + + /* If the drive says it is not spun up (even though we just did it!) + then retry the operation at least a few times. */ + if ((res_reg[1] == SONY_NOT_SPIN_ERR) + && (num_spin_ups < MAX_CDU31A_RETRIES)) { + num_spin_ups++; + goto respinup_on_gettoc; + } + + printk("cdu31a: Error reading TOC: %x %s\n", + res_reg[0], translate_error(res_reg[1])); + return; + } + + gettoc_drive_spinning: + + /* The idea here is we keep asking for sessions until the command + fails. Then we know what the last valid session on the disk is. + No need to check session 0, since session 0 is the same as session + 1; the command returns different information if you give it 0. + */ +#if DEBUG + memset(&sony_toc, 0x0e, sizeof(sony_toc)); + memset(&single_toc, 0x0f, sizeof(single_toc)); +#endif + session = 1; + while (1) { /* This seems to slow things down enough to make it work. This * appears to be a problem in do_sony_cd_cmd. This printk seems * to address the symptoms... -Erik */ #if 1 - printk("cdu31a: Trying session %d\n", session); + printk("cdu31a: Trying session %d\n", session); #endif - parms[0] = session; - do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD, - parms, - 1, - res_reg, - &res_size); - -#if DEBUG - printk("%2.2x %2.2x\n", res_reg[0], res_reg[1]); -#endif - - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - /* An error reading the TOC, this must be past the last session. */ - if (session == 1) - printk("Yikes! Couldn't read any sessions!"); - break; - } -#if DEBUG - printk("Reading session %d\n", session); -#endif - - parms[0] = session; - do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD, - parms, - 1, - (unsigned char *) &single_toc, - &res_size); - if ((res_size < 2) || ((single_toc.exec_status[0] & 0xf0) == 0x20)) - { - printk("cdu31a: Error reading session %d: %x %s\n", - session, - single_toc.exec_status[0], - translate_error(single_toc.exec_status[1])); - /* An error reading the TOC. Return without sony_toc_read - set. */ - return; - } -#if DEBUG - printk("add0 %01x, con0 %01x, poi0 %02x, 1st trk %d, dsktyp %x, dum0 %x\n", - single_toc.address0, single_toc.control0, single_toc.point0, - bcd_to_int(single_toc.first_track_num), single_toc.disk_type, single_toc.dummy0); - printk("add1 %01x, con1 %01x, poi1 %02x, lst trk %d, dummy1 %x, dum2 %x\n", - single_toc.address1, single_toc.control1, single_toc.point1, - bcd_to_int(single_toc.last_track_num), single_toc.dummy1, single_toc.dummy2); - printk("add2 %01x, con2 %01x, poi2 %02x leadout start min %d, sec %d, frame %d\n", - single_toc.address2, single_toc.control2, single_toc.point2, - bcd_to_int(single_toc.lead_out_start_msf[0]), - bcd_to_int(single_toc.lead_out_start_msf[1]), - bcd_to_int(single_toc.lead_out_start_msf[2])); - if (res_size > 18 && single_toc.pointb0 > 0xaf) - printk("addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n" - "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n", - single_toc.addressb0, single_toc.controlb0, single_toc.pointb0, - bcd_to_int(single_toc.next_poss_prog_area_msf[0]), - bcd_to_int(single_toc.next_poss_prog_area_msf[1]), - bcd_to_int(single_toc.next_poss_prog_area_msf[2]), - single_toc.num_mode_5_pointers, - bcd_to_int(single_toc.max_start_outer_leadout_msf[0]), - bcd_to_int(single_toc.max_start_outer_leadout_msf[1]), - bcd_to_int(single_toc.max_start_outer_leadout_msf[2])); - if (res_size > 27 && single_toc.pointb1 > 0xaf) - printk("addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n", - single_toc.addressb1, single_toc.controlb1, single_toc.pointb1, - single_toc.dummyb0_1[0], - single_toc.dummyb0_1[1], - single_toc.dummyb0_1[2], - single_toc.dummyb0_1[3], - single_toc.num_skip_interval_pointers, - single_toc.num_skip_track_assignments, - single_toc.dummyb0_2); - if (res_size > 36 && single_toc.pointb2 > 0xaf) - printk("addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n", - single_toc.addressb2, single_toc.controlb2, single_toc.pointb2, - single_toc.tracksb2[0], - single_toc.tracksb2[1], - single_toc.tracksb2[2], - single_toc.tracksb2[3], - single_toc.tracksb2[4], - single_toc.tracksb2[5], - single_toc.tracksb2[6]); - if (res_size > 45 && single_toc.pointb3 > 0xaf) - printk("addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n", - single_toc.addressb3, single_toc.controlb3, single_toc.pointb3, - single_toc.tracksb3[0], - single_toc.tracksb3[1], - single_toc.tracksb3[2], - single_toc.tracksb3[3], - single_toc.tracksb3[4], - single_toc.tracksb3[5], - single_toc.tracksb3[6]); - if (res_size > 54 && single_toc.pointb4 > 0xaf) - printk("addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n", - single_toc.addressb4, single_toc.controlb4, single_toc.pointb4, - single_toc.tracksb4[0], - single_toc.tracksb4[1], - single_toc.tracksb4[2], - single_toc.tracksb4[3], - single_toc.tracksb4[4], - single_toc.tracksb4[5], - single_toc.tracksb4[6]); - if (res_size > 63 && single_toc.pointc0 > 0xaf) - printk("addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n", - single_toc.addressc0, single_toc.controlc0, single_toc.pointc0, - single_toc.dummyc0[0], - single_toc.dummyc0[1], - single_toc.dummyc0[2], - single_toc.dummyc0[3], - single_toc.dummyc0[4], - single_toc.dummyc0[5], - single_toc.dummyc0[6]); + parms[0] = session; + do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD, + parms, 1, res_reg, &res_size); + +#if DEBUG + printk("%2.2x %2.2x\n", res_reg[0], res_reg[1]); +#endif + + if ((res_size < 2) + || ((res_reg[0] & 0xf0) == 0x20)) { + /* An error reading the TOC, this must be past the last session. */ + if (session == 1) + printk + ("Yikes! Couldn't read any sessions!"); + break; + } +#if DEBUG + printk("Reading session %d\n", session); +#endif + + parms[0] = session; + do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD, + parms, + 1, + (unsigned char *) &single_toc, + &res_size); + if ((res_size < 2) + || ((single_toc.exec_status[0] & 0xf0) == + 0x20)) { + printk + ("cdu31a: Error reading session %d: %x %s\n", + session, single_toc.exec_status[0], + translate_error(single_toc. + exec_status[1])); + /* An error reading the TOC. Return without sony_toc_read + set. */ + return; + } +#if DEBUG + printk + ("add0 %01x, con0 %01x, poi0 %02x, 1st trk %d, dsktyp %x, dum0 %x\n", + single_toc.address0, single_toc.control0, + single_toc.point0, + bcd_to_int(single_toc.first_track_num), + single_toc.disk_type, single_toc.dummy0); + printk + ("add1 %01x, con1 %01x, poi1 %02x, lst trk %d, dummy1 %x, dum2 %x\n", + single_toc.address1, single_toc.control1, + single_toc.point1, + bcd_to_int(single_toc.last_track_num), + single_toc.dummy1, single_toc.dummy2); + printk + ("add2 %01x, con2 %01x, poi2 %02x leadout start min %d, sec %d, frame %d\n", + single_toc.address2, single_toc.control2, + single_toc.point2, + bcd_to_int(single_toc.lead_out_start_msf[0]), + bcd_to_int(single_toc.lead_out_start_msf[1]), + bcd_to_int(single_toc.lead_out_start_msf[2])); + if (res_size > 18 && single_toc.pointb0 > 0xaf) + printk + ("addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n" + "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n", + single_toc.addressb0, + single_toc.controlb0, + single_toc.pointb0, + bcd_to_int(single_toc. + next_poss_prog_area_msf + [0]), + bcd_to_int(single_toc. + next_poss_prog_area_msf + [1]), + bcd_to_int(single_toc. + next_poss_prog_area_msf + [2]), + single_toc.num_mode_5_pointers, + bcd_to_int(single_toc. + max_start_outer_leadout_msf + [0]), + bcd_to_int(single_toc. + max_start_outer_leadout_msf + [1]), + bcd_to_int(single_toc. + max_start_outer_leadout_msf + [2])); + if (res_size > 27 && single_toc.pointb1 > 0xaf) + printk + ("addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n", + single_toc.addressb1, + single_toc.controlb1, + single_toc.pointb1, + single_toc.dummyb0_1[0], + single_toc.dummyb0_1[1], + single_toc.dummyb0_1[2], + single_toc.dummyb0_1[3], + single_toc.num_skip_interval_pointers, + single_toc.num_skip_track_assignments, + single_toc.dummyb0_2); + if (res_size > 36 && single_toc.pointb2 > 0xaf) + printk + ("addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n", + single_toc.addressb2, + single_toc.controlb2, + single_toc.pointb2, + single_toc.tracksb2[0], + single_toc.tracksb2[1], + single_toc.tracksb2[2], + single_toc.tracksb2[3], + single_toc.tracksb2[4], + single_toc.tracksb2[5], + single_toc.tracksb2[6]); + if (res_size > 45 && single_toc.pointb3 > 0xaf) + printk + ("addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n", + single_toc.addressb3, + single_toc.controlb3, + single_toc.pointb3, + single_toc.tracksb3[0], + single_toc.tracksb3[1], + single_toc.tracksb3[2], + single_toc.tracksb3[3], + single_toc.tracksb3[4], + single_toc.tracksb3[5], + single_toc.tracksb3[6]); + if (res_size > 54 && single_toc.pointb4 > 0xaf) + printk + ("addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n", + single_toc.addressb4, + single_toc.controlb4, + single_toc.pointb4, + single_toc.tracksb4[0], + single_toc.tracksb4[1], + single_toc.tracksb4[2], + single_toc.tracksb4[3], + single_toc.tracksb4[4], + single_toc.tracksb4[5], + single_toc.tracksb4[6]); + if (res_size > 63 && single_toc.pointc0 > 0xaf) + printk + ("addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n", + single_toc.addressc0, + single_toc.controlc0, + single_toc.pointc0, + single_toc.dummyc0[0], + single_toc.dummyc0[1], + single_toc.dummyc0[2], + single_toc.dummyc0[3], + single_toc.dummyc0[4], + single_toc.dummyc0[5], + single_toc.dummyc0[6]); #endif #undef DEBUG #define DEBUG 0 - sony_toc.lead_out_start_msf[0] = bcd_to_int(single_toc.lead_out_start_msf[0]); - sony_toc.lead_out_start_msf[1] = bcd_to_int(single_toc.lead_out_start_msf[1]); - sony_toc.lead_out_start_msf[2] = bcd_to_int(single_toc.lead_out_start_msf[2]); - sony_toc.lead_out_start_lba = single_toc.lead_out_start_lba = - msf_to_log(sony_toc.lead_out_start_msf); - - /* For points that do not exist, move the data over them - to the right location. */ - if (single_toc.pointb0 != 0xb0) - { - memmove(((char *) &single_toc) + 27, - ((char *) &single_toc) + 18, - res_size - 18); - res_size += 9; - } - else if (res_size > 18) { - sony_toc.lead_out_start_msf[0] = bcd_to_int(single_toc.max_start_outer_leadout_msf[0]); - sony_toc.lead_out_start_msf[1] = bcd_to_int(single_toc.max_start_outer_leadout_msf[1]); - sony_toc.lead_out_start_msf[2] = bcd_to_int(single_toc.max_start_outer_leadout_msf[2]); - sony_toc.lead_out_start_lba = msf_to_log(sony_toc.lead_out_start_msf); - } - if (single_toc.pointb1 != 0xb1) - { - memmove(((char *) &single_toc) + 36, - ((char *) &single_toc) + 27, - res_size - 27); - res_size += 9; - } - if (single_toc.pointb2 != 0xb2) - { - memmove(((char *) &single_toc) + 45, - ((char *) &single_toc) + 36, - res_size - 36); - res_size += 9; - } - if (single_toc.pointb3 != 0xb3) - { - memmove(((char *) &single_toc) + 54, - ((char *) &single_toc) + 45, - res_size - 45); - res_size += 9; - } - if (single_toc.pointb4 != 0xb4) - { - memmove(((char *) &single_toc) + 63, - ((char *) &single_toc) + 54, - res_size - 54); - res_size += 9; - } - if (single_toc.pointc0 != 0xc0) - { - memmove(((char *) &single_toc) + 72, - ((char *) &single_toc) + 63, - res_size - 63); - res_size += 9; - } - -#if DEBUG - printk("start track lba %u, leadout start lba %u\n", - single_toc.start_track_lba, single_toc.lead_out_start_lba); - { int i; - for (i = 0; i < 1 + bcd_to_int(single_toc.last_track_num) - - bcd_to_int(single_toc.first_track_num); i++) { - printk("trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n", - i, single_toc.tracks[i].address, single_toc.tracks[i].control, - bcd_to_int(single_toc.tracks[i].track), - bcd_to_int(single_toc.tracks[i].track_start_msf[0]), - bcd_to_int(single_toc.tracks[i].track_start_msf[1]), - bcd_to_int(single_toc.tracks[i].track_start_msf[2])); - if (mint > bcd_to_int(single_toc.tracks[i].track)) - mint = bcd_to_int(single_toc.tracks[i].track); - if (maxt < bcd_to_int(single_toc.tracks[i].track)) - maxt = bcd_to_int(single_toc.tracks[i].track); - } - printk("min track number %d, max track number %d\n", mint, maxt); - } -#endif - - /* prepare a special table of contents for a CD-I disc. They don't have one. */ - if (single_toc.disk_type == 0x10 && - single_toc.first_track_num == 2 && - single_toc.last_track_num == 2 /* CD-I */) - { - sony_toc.tracks[totaltracks].address = 1; - sony_toc.tracks[totaltracks].control = 4; /* force data tracks */ - sony_toc.tracks[totaltracks].track = 1; - sony_toc.tracks[totaltracks].track_start_msf[0] = 0; - sony_toc.tracks[totaltracks].track_start_msf[1] = 2; - sony_toc.tracks[totaltracks].track_start_msf[2] = 0; - mint = maxt = 1; - totaltracks++; - } else - /* gather track entries from this session */ - { int i; - for (i = 0; i < 1 + bcd_to_int(single_toc.last_track_num) - - bcd_to_int(single_toc.first_track_num); i++, totaltracks++) { - sony_toc.tracks[totaltracks].address = single_toc.tracks[i].address; - sony_toc.tracks[totaltracks].control = single_toc.tracks[i].control; - sony_toc.tracks[totaltracks].track = bcd_to_int(single_toc.tracks[i].track); - sony_toc.tracks[totaltracks].track_start_msf[0] = - bcd_to_int(single_toc.tracks[i].track_start_msf[0]); - sony_toc.tracks[totaltracks].track_start_msf[1] = - bcd_to_int(single_toc.tracks[i].track_start_msf[1]); - sony_toc.tracks[totaltracks].track_start_msf[2] = - bcd_to_int(single_toc.tracks[i].track_start_msf[2]); - if (i == 0) - single_toc.start_track_lba = msf_to_log(sony_toc.tracks[totaltracks].track_start_msf); - if (mint > sony_toc.tracks[totaltracks].track) - mint = sony_toc.tracks[totaltracks].track; - if (maxt < sony_toc.tracks[totaltracks].track) - maxt = sony_toc.tracks[totaltracks].track; - } - } - sony_toc.first_track_num = mint; - sony_toc.last_track_num = maxt; - /* Disk type of last session wins. For example: - CD-Extra has disk type 0 for the first session, so - a dumb HiFi CD player thinks it is a plain audio CD. - We are interested in the disk type of the last session, - which is 0x20 (XA) for CD-Extra, so we can access the - data track ... */ - sony_toc.disk_type = single_toc.disk_type; - sony_toc.sessions = session; - - /* don't believe everything :-) */ - if (session == 1) - single_toc.start_track_lba = 0; - sony_toc.start_track_lba = single_toc.start_track_lba; - - if (session > 1 && single_toc.pointb0 == 0xb0 && - sony_toc.lead_out_start_lba == single_toc.lead_out_start_lba) - { - break; - } - - /* Let's not get carried away... */ - if (session > 40) - { - printk("cdu31a: too many sessions: %d\n", session); - break; - } - session++; - } - sony_toc.track_entries = totaltracks; - /* add one entry for the LAST track with track number CDROM_LEADOUT */ - sony_toc.tracks[totaltracks].address = single_toc.address2; - sony_toc.tracks[totaltracks].control = single_toc.control2; - sony_toc.tracks[totaltracks].track = CDROM_LEADOUT; - sony_toc.tracks[totaltracks].track_start_msf[0] = - sony_toc.lead_out_start_msf[0]; - sony_toc.tracks[totaltracks].track_start_msf[1] = - sony_toc.lead_out_start_msf[1]; - sony_toc.tracks[totaltracks].track_start_msf[2] = - sony_toc.lead_out_start_msf[2]; + sony_toc.lead_out_start_msf[0] = + bcd_to_int(single_toc.lead_out_start_msf[0]); + sony_toc.lead_out_start_msf[1] = + bcd_to_int(single_toc.lead_out_start_msf[1]); + sony_toc.lead_out_start_msf[2] = + bcd_to_int(single_toc.lead_out_start_msf[2]); + sony_toc.lead_out_start_lba = + single_toc.lead_out_start_lba = + msf_to_log(sony_toc.lead_out_start_msf); + + /* For points that do not exist, move the data over them + to the right location. */ + if (single_toc.pointb0 != 0xb0) { + memmove(((char *) &single_toc) + 27, + ((char *) &single_toc) + 18, + res_size - 18); + res_size += 9; + } else if (res_size > 18) { + sony_toc.lead_out_start_msf[0] = + bcd_to_int(single_toc. + max_start_outer_leadout_msf + [0]); + sony_toc.lead_out_start_msf[1] = + bcd_to_int(single_toc. + max_start_outer_leadout_msf + [1]); + sony_toc.lead_out_start_msf[2] = + bcd_to_int(single_toc. + max_start_outer_leadout_msf + [2]); + sony_toc.lead_out_start_lba = + msf_to_log(sony_toc. + lead_out_start_msf); + } + if (single_toc.pointb1 != 0xb1) { + memmove(((char *) &single_toc) + 36, + ((char *) &single_toc) + 27, + res_size - 27); + res_size += 9; + } + if (single_toc.pointb2 != 0xb2) { + memmove(((char *) &single_toc) + 45, + ((char *) &single_toc) + 36, + res_size - 36); + res_size += 9; + } + if (single_toc.pointb3 != 0xb3) { + memmove(((char *) &single_toc) + 54, + ((char *) &single_toc) + 45, + res_size - 45); + res_size += 9; + } + if (single_toc.pointb4 != 0xb4) { + memmove(((char *) &single_toc) + 63, + ((char *) &single_toc) + 54, + res_size - 54); + res_size += 9; + } + if (single_toc.pointc0 != 0xc0) { + memmove(((char *) &single_toc) + 72, + ((char *) &single_toc) + 63, + res_size - 63); + res_size += 9; + } +#if DEBUG + printk + ("start track lba %u, leadout start lba %u\n", + single_toc.start_track_lba, + single_toc.lead_out_start_lba); + { + int i; + for (i = 0; + i < + 1 + + bcd_to_int(single_toc.last_track_num) + - + bcd_to_int(single_toc. + first_track_num); i++) { + printk + ("trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n", + i, + single_toc.tracks[i].address, + single_toc.tracks[i].control, + bcd_to_int(single_toc. + tracks[i].track), + bcd_to_int(single_toc. + tracks[i]. + track_start_msf + [0]), + bcd_to_int(single_toc. + tracks[i]. + track_start_msf + [1]), + bcd_to_int(single_toc. + tracks[i]. + track_start_msf + [2])); + if (mint > + bcd_to_int(single_toc. + tracks[i].track)) + mint = + bcd_to_int(single_toc. + tracks[i]. + track); + if (maxt < + bcd_to_int(single_toc. + tracks[i].track)) + maxt = + bcd_to_int(single_toc. + tracks[i]. + track); + } + printk + ("min track number %d, max track number %d\n", + mint, maxt); + } +#endif + + /* prepare a special table of contents for a CD-I disc. They don't have one. */ + if (single_toc.disk_type == 0x10 && + single_toc.first_track_num == 2 && + single_toc.last_track_num == 2 /* CD-I */ ) { + sony_toc.tracks[totaltracks].address = 1; + sony_toc.tracks[totaltracks].control = 4; /* force data tracks */ + sony_toc.tracks[totaltracks].track = 1; + sony_toc.tracks[totaltracks]. + track_start_msf[0] = 0; + sony_toc.tracks[totaltracks]. + track_start_msf[1] = 2; + sony_toc.tracks[totaltracks]. + track_start_msf[2] = 0; + mint = maxt = 1; + totaltracks++; + } else + /* gather track entries from this session */ + { + int i; + for (i = 0; + i < + 1 + + bcd_to_int(single_toc.last_track_num) + - + bcd_to_int(single_toc. + first_track_num); + i++, totaltracks++) { + sony_toc.tracks[totaltracks]. + address = + single_toc.tracks[i].address; + sony_toc.tracks[totaltracks]. + control = + single_toc.tracks[i].control; + sony_toc.tracks[totaltracks]. + track = + bcd_to_int(single_toc. + tracks[i].track); + sony_toc.tracks[totaltracks]. + track_start_msf[0] = + bcd_to_int(single_toc. + tracks[i]. + track_start_msf[0]); + sony_toc.tracks[totaltracks]. + track_start_msf[1] = + bcd_to_int(single_toc. + tracks[i]. + track_start_msf[1]); + sony_toc.tracks[totaltracks]. + track_start_msf[2] = + bcd_to_int(single_toc. + tracks[i]. + track_start_msf[2]); + if (i == 0) + single_toc. + start_track_lba = + msf_to_log(sony_toc. + tracks + [totaltracks]. + track_start_msf); + if (mint > + sony_toc.tracks[totaltracks]. + track) + mint = + sony_toc. + tracks[totaltracks]. + track; + if (maxt < + sony_toc.tracks[totaltracks]. + track) + maxt = + sony_toc. + tracks[totaltracks]. + track; + } + } + sony_toc.first_track_num = mint; + sony_toc.last_track_num = maxt; + /* Disk type of last session wins. For example: + CD-Extra has disk type 0 for the first session, so + a dumb HiFi CD player thinks it is a plain audio CD. + We are interested in the disk type of the last session, + which is 0x20 (XA) for CD-Extra, so we can access the + data track ... */ + sony_toc.disk_type = single_toc.disk_type; + sony_toc.sessions = session; + + /* don't believe everything :-) */ + if (session == 1) + single_toc.start_track_lba = 0; + sony_toc.start_track_lba = + single_toc.start_track_lba; + + if (session > 1 && single_toc.pointb0 == 0xb0 && + sony_toc.lead_out_start_lba == + single_toc.lead_out_start_lba) { + break; + } + + /* Let's not get carried away... */ + if (session > 40) { + printk("cdu31a: too many sessions: %d\n", + session); + break; + } + session++; + } + sony_toc.track_entries = totaltracks; + /* add one entry for the LAST track with track number CDROM_LEADOUT */ + sony_toc.tracks[totaltracks].address = single_toc.address2; + sony_toc.tracks[totaltracks].control = single_toc.control2; + sony_toc.tracks[totaltracks].track = CDROM_LEADOUT; + sony_toc.tracks[totaltracks].track_start_msf[0] = + sony_toc.lead_out_start_msf[0]; + sony_toc.tracks[totaltracks].track_start_msf[1] = + sony_toc.lead_out_start_msf[1]; + sony_toc.tracks[totaltracks].track_start_msf[2] = + sony_toc.lead_out_start_msf[2]; - sony_toc_read = 1; + sony_toc_read = 1; #undef DEBUG #if DEBUG - printk("Disk session %d, start track: %d, stop track: %d\n", - session, - single_toc.start_track_lba, - single_toc.lead_out_start_lba); + printk + ("Disk session %d, start track: %d, stop track: %d\n", + session, single_toc.start_track_lba, + single_toc.lead_out_start_lba); #endif - } + } #if DEBUG - printk("Leaving sony_get_toc\n"); + printk("Leaving sony_get_toc\n"); #endif } @@ -2236,74 +2230,76 @@ * Uniform cdrom interface function * return multisession offset and sector information */ -static int scd_get_last_session(struct cdrom_device_info *cdi, - struct cdrom_multisession *ms_info) +static int scd_get_last_session(struct cdrom_device_info *cdi, + struct cdrom_multisession *ms_info) { - if (ms_info == NULL) - return 1; + if (ms_info == NULL) + return 1; - if (!sony_toc_read) - sony_get_toc(); + if (!sony_toc_read) + sony_get_toc(); - ms_info->addr_format = CDROM_LBA; - ms_info->addr.lba = sony_toc.start_track_lba; - ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE || - sony_toc.disk_type == 0x10 /* CDI */; + ms_info->addr_format = CDROM_LBA; + ms_info->addr.lba = sony_toc.start_track_lba; + ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE || + sony_toc.disk_type == 0x10 /* CDI */ ; - return 0; + return 0; } /* * Search for a specific track in the table of contents. */ -static int -find_track(int track) +static int find_track(int track) { - int i; + int i; - for (i = 0; i <= sony_toc.track_entries; i++) - { - if (sony_toc.tracks[i].track == track) - { - return i; - } - } + for (i = 0; i <= sony_toc.track_entries; i++) { + if (sony_toc.tracks[i].track == track) { + return i; + } + } - return -1; + return -1; } /* * Read the subcode and put it in last_sony_subcode for future use. */ -static int -read_subcode(void) +static int read_subcode(void) { - unsigned int res_size; + unsigned int res_size; - do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD, - NULL, - 0, - (unsigned char *) &last_sony_subcode, - &res_size); - if ((res_size < 2) || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) - { - printk("Sony CDROM error %s (read_subcode)\n", - translate_error(last_sony_subcode.exec_status[1])); - return -EIO; - } - - last_sony_subcode.track_num = bcd_to_int(last_sony_subcode.track_num); - last_sony_subcode.index_num = bcd_to_int(last_sony_subcode.index_num); - last_sony_subcode.abs_msf[0] = bcd_to_int(last_sony_subcode.abs_msf[0]); - last_sony_subcode.abs_msf[1] = bcd_to_int(last_sony_subcode.abs_msf[1]); - last_sony_subcode.abs_msf[2] = bcd_to_int(last_sony_subcode.abs_msf[2]); - - last_sony_subcode.rel_msf[0] = bcd_to_int(last_sony_subcode.rel_msf[0]); - last_sony_subcode.rel_msf[1] = bcd_to_int(last_sony_subcode.rel_msf[1]); - last_sony_subcode.rel_msf[2] = bcd_to_int(last_sony_subcode.rel_msf[2]); - return 0; + do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD, + NULL, + 0, (unsigned char *) &last_sony_subcode, &res_size); + if ((res_size < 2) + || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) { + printk("Sony CDROM error %s (read_subcode)\n", + translate_error(last_sony_subcode.exec_status[1])); + return -EIO; + } + + last_sony_subcode.track_num = + bcd_to_int(last_sony_subcode.track_num); + last_sony_subcode.index_num = + bcd_to_int(last_sony_subcode.index_num); + last_sony_subcode.abs_msf[0] = + bcd_to_int(last_sony_subcode.abs_msf[0]); + last_sony_subcode.abs_msf[1] = + bcd_to_int(last_sony_subcode.abs_msf[1]); + last_sony_subcode.abs_msf[2] = + bcd_to_int(last_sony_subcode.abs_msf[2]); + + last_sony_subcode.rel_msf[0] = + bcd_to_int(last_sony_subcode.rel_msf[0]); + last_sony_subcode.rel_msf[1] = + bcd_to_int(last_sony_subcode.rel_msf[1]); + last_sony_subcode.rel_msf[2] = + bcd_to_int(last_sony_subcode.rel_msf[2]); + return 0; } /* @@ -2313,37 +2309,33 @@ static int scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) { - unsigned char resbuffer[2 + 14]; - unsigned char *mcnp = mcn->medium_catalog_number; - unsigned char *resp = resbuffer + 3; - unsigned int res_size; - - memset(mcn->medium_catalog_number, 0, 14); - do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD, - NULL, - 0, - resbuffer, - &res_size); - if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20)) - ; - else { - /* packed bcd to single ASCII digits */ - *mcnp++ = (*resp >> 4) + '0'; - *mcnp++ = (*resp++ & 0x0f) + '0'; - *mcnp++ = (*resp >> 4) + '0'; - *mcnp++ = (*resp++ & 0x0f) + '0'; - *mcnp++ = (*resp >> 4) + '0'; - *mcnp++ = (*resp++ & 0x0f) + '0'; - *mcnp++ = (*resp >> 4) + '0'; - *mcnp++ = (*resp++ & 0x0f) + '0'; - *mcnp++ = (*resp >> 4) + '0'; - *mcnp++ = (*resp++ & 0x0f) + '0'; - *mcnp++ = (*resp >> 4) + '0'; - *mcnp++ = (*resp++ & 0x0f) + '0'; - *mcnp++ = (*resp >> 4) + '0'; - } - *mcnp = '\0'; - return 0; + unsigned char resbuffer[2 + 14]; + unsigned char *mcnp = mcn->medium_catalog_number; + unsigned char *resp = resbuffer + 3; + unsigned int res_size; + + memset(mcn->medium_catalog_number, 0, 14); + do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD, + NULL, 0, resbuffer, &res_size); + if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20)); + else { + /* packed bcd to single ASCII digits */ + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + } + *mcnp = '\0'; + return 0; } @@ -2354,67 +2346,67 @@ * already been stored, just use that. The ioctl call wants things in decimal * (not BCD), so all the conversions are done. */ -static int -sony_get_subchnl_info(struct cdrom_subchnl *schi) +static int sony_get_subchnl_info(struct cdrom_subchnl *schi) { - /* Get attention stuff */ - while (handle_sony_cd_attention()) - ; - - sony_get_toc(); - if (!sony_toc_read) - { - return -EIO; - } - - switch (sony_audio_status) - { - case CDROM_AUDIO_NO_STATUS: - case CDROM_AUDIO_PLAY: - if (read_subcode() < 0) - { - return -EIO; - } - break; - - case CDROM_AUDIO_PAUSED: - case CDROM_AUDIO_COMPLETED: - break; + /* Get attention stuff */ + while (handle_sony_cd_attention()); + + sony_get_toc(); + if (!sony_toc_read) { + return -EIO; + } + + switch (sony_audio_status) { + case CDROM_AUDIO_NO_STATUS: + case CDROM_AUDIO_PLAY: + if (read_subcode() < 0) { + return -EIO; + } + break; + + case CDROM_AUDIO_PAUSED: + case CDROM_AUDIO_COMPLETED: + break; #if 0 - case CDROM_AUDIO_NO_STATUS: - schi->cdsc_audiostatus = sony_audio_status; - return 0; - break; -#endif - case CDROM_AUDIO_INVALID: - case CDROM_AUDIO_ERROR: - default: - return -EIO; - } - - schi->cdsc_audiostatus = sony_audio_status; - schi->cdsc_adr = last_sony_subcode.address; - schi->cdsc_ctrl = last_sony_subcode.control; - schi->cdsc_trk = last_sony_subcode.track_num; - schi->cdsc_ind = last_sony_subcode.index_num; - if (schi->cdsc_format == CDROM_MSF) - { - schi->cdsc_absaddr.msf.minute = last_sony_subcode.abs_msf[0]; - schi->cdsc_absaddr.msf.second = last_sony_subcode.abs_msf[1]; - schi->cdsc_absaddr.msf.frame = last_sony_subcode.abs_msf[2]; - - schi->cdsc_reladdr.msf.minute = last_sony_subcode.rel_msf[0]; - schi->cdsc_reladdr.msf.second = last_sony_subcode.rel_msf[1]; - schi->cdsc_reladdr.msf.frame = last_sony_subcode.rel_msf[2]; - } - else if (schi->cdsc_format == CDROM_LBA) - { - schi->cdsc_absaddr.lba = msf_to_log(last_sony_subcode.abs_msf); - schi->cdsc_reladdr.lba = msf_to_log(last_sony_subcode.rel_msf); - } - - return 0; + case CDROM_AUDIO_NO_STATUS: + schi->cdsc_audiostatus = sony_audio_status; + return 0; + break; +#endif + case CDROM_AUDIO_INVALID: + case CDROM_AUDIO_ERROR: + default: + return -EIO; + } + + schi->cdsc_audiostatus = sony_audio_status; + schi->cdsc_adr = last_sony_subcode.address; + schi->cdsc_ctrl = last_sony_subcode.control; + schi->cdsc_trk = last_sony_subcode.track_num; + schi->cdsc_ind = last_sony_subcode.index_num; + if (schi->cdsc_format == CDROM_MSF) { + schi->cdsc_absaddr.msf.minute = + last_sony_subcode.abs_msf[0]; + schi->cdsc_absaddr.msf.second = + last_sony_subcode.abs_msf[1]; + schi->cdsc_absaddr.msf.frame = + last_sony_subcode.abs_msf[2]; + + schi->cdsc_reladdr.msf.minute = + last_sony_subcode.rel_msf[0]; + schi->cdsc_reladdr.msf.second = + last_sony_subcode.rel_msf[1]; + schi->cdsc_reladdr.msf.frame = + last_sony_subcode.rel_msf[2]; + } else if (schi->cdsc_format == CDROM_LBA) { + schi->cdsc_absaddr.lba = + msf_to_log(last_sony_subcode.abs_msf); + schi->cdsc_reladdr.lba = + msf_to_log(last_sony_subcode.rel_msf); + } + + return 0; } /* Get audio data from the drive. This is fairly complex because I @@ -2422,782 +2414,756 @@ then I just look for data. I need to get the status immediately so the switch from audio to data tracks will happen quickly. */ static void -read_audio_data(char *buffer, - unsigned char res_reg[], - int *res_size) -{ - unsigned int retry_count; - int result_read; - - - res_reg[0] = 0; - res_reg[1] = 0; - *res_size = 0; - result_read = 0; - - /* Wait for the drive to tell us we have something */ - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; -continue_read_audio_wait: - while (time_before(jiffies, retry_count) && !(is_data_ready()) - && !(is_result_ready() || result_read)) - { - while (handle_sony_cd_attention()) - ; - - sony_sleep(); - } - if (!(is_data_ready())) - { - if (is_result_ready() && !result_read) - { - get_result(res_reg, res_size); - - /* Read block status and continue waiting for data. */ - if ((res_reg[0] & 0xf0) == 0x50) - { - result_read = 1; - goto continue_read_audio_wait; - } - /* Invalid data from the drive. Shut down the operation. */ - else if ((res_reg[0] & 0xf0) != 0x20) - { - printk("CDU31A: Got result that should have been error: %d\n", - res_reg[0]); - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - } - abort_read(); - } - else - { -#if DEBUG - printk("CDU31A timeout out %d\n", __LINE__); -#endif - res_reg[0] = 0x20; - res_reg[1] = SONY_TIMEOUT_OP_ERR; - *res_size = 2; - abort_read(); - } - } - else - { - clear_data_ready(); - - /* If data block, then get 2340 bytes offset by 12. */ - if (sony_raw_data_mode) - { - insb(sony_cd_read_reg, buffer + CD_XA_HEAD, CD_FRAMESIZE_RAW1); - } - else - { - /* Audio gets the whole 2352 bytes. */ - insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW); - } - - /* If I haven't already gotten the result, get it now. */ - if (!result_read) - { - /* Wait for the drive to tell us we have something */ - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (time_before(jiffies, retry_count) && !(is_result_ready())) - { - while (handle_sony_cd_attention()) - ; - - sony_sleep(); - } - - if (!is_result_ready()) - { -#if DEBUG - printk("CDU31A timeout out %d\n", __LINE__); -#endif - res_reg[0] = 0x20; - res_reg[1] = SONY_TIMEOUT_OP_ERR; - *res_size = 2; - abort_read(); - return; - } - else - { - get_result(res_reg, res_size); - } - } - - if ((res_reg[0] & 0xf0) == 0x50) - { - if ( (res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT) - || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT) - || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT) - || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) - { - /* Ok, nothing to do. */ - } - else - { - printk("CDU31A: Data block error: 0x%x\n", res_reg[0]); - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - } - } - else if ((res_reg[0] & 0xf0) != 0x20) - { - /* The drive gave me bad status, I don't know what to do. - Reset the driver and return an error. */ - printk("CDU31A: Invalid block status: 0x%x\n", res_reg[0]); - restart_on_error(); - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - } - } +read_audio_data(char *buffer, unsigned char res_reg[], int *res_size) +{ + unsigned int retry_count; + int result_read; + + + res_reg[0] = 0; + res_reg[1] = 0; + *res_size = 0; + result_read = 0; + + /* Wait for the drive to tell us we have something */ + retry_count = jiffies + SONY_JIFFIES_TIMEOUT; + continue_read_audio_wait: + while (time_before(jiffies, retry_count) && !(is_data_ready()) + && !(is_result_ready() || result_read)) { + while (handle_sony_cd_attention()); + + sony_sleep(); + } + if (!(is_data_ready())) { + if (is_result_ready() && !result_read) { + get_result(res_reg, res_size); + + /* Read block status and continue waiting for data. */ + if ((res_reg[0] & 0xf0) == 0x50) { + result_read = 1; + goto continue_read_audio_wait; + } + /* Invalid data from the drive. Shut down the operation. */ + else if ((res_reg[0] & 0xf0) != 0x20) { + printk + ("CDU31A: Got result that should have been error: %d\n", + res_reg[0]); + res_reg[0] = 0x20; + res_reg[1] = SONY_BAD_DATA_ERR; + *res_size = 2; + } + abort_read(); + } else { +#if DEBUG + printk("CDU31A timeout out %d\n", __LINE__); +#endif + res_reg[0] = 0x20; + res_reg[1] = SONY_TIMEOUT_OP_ERR; + *res_size = 2; + abort_read(); + } + } else { + clear_data_ready(); + + /* If data block, then get 2340 bytes offset by 12. */ + if (sony_raw_data_mode) { + insb(sony_cd_read_reg, buffer + CD_XA_HEAD, + CD_FRAMESIZE_RAW1); + } else { + /* Audio gets the whole 2352 bytes. */ + insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW); + } + + /* If I haven't already gotten the result, get it now. */ + if (!result_read) { + /* Wait for the drive to tell us we have something */ + retry_count = jiffies + SONY_JIFFIES_TIMEOUT; + while (time_before(jiffies, retry_count) + && !(is_result_ready())) { + while (handle_sony_cd_attention()); + + sony_sleep(); + } + + if (!is_result_ready()) { +#if DEBUG + printk("CDU31A timeout out %d\n", + __LINE__); +#endif + res_reg[0] = 0x20; + res_reg[1] = SONY_TIMEOUT_OP_ERR; + *res_size = 2; + abort_read(); + return; + } else { + get_result(res_reg, res_size); + } + } + + if ((res_reg[0] & 0xf0) == 0x50) { + if ((res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT) + || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT) + || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT) + || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) { + /* Ok, nothing to do. */ + } else { + printk("CDU31A: Data block error: 0x%x\n", + res_reg[0]); + res_reg[0] = 0x20; + res_reg[1] = SONY_BAD_DATA_ERR; + *res_size = 2; + } + } else if ((res_reg[0] & 0xf0) != 0x20) { + /* The drive gave me bad status, I don't know what to do. + Reset the driver and return an error. */ + printk("CDU31A: Invalid block status: 0x%x\n", + res_reg[0]); + restart_on_error(); + res_reg[0] = 0x20; + res_reg[1] = SONY_BAD_DATA_ERR; + *res_size = 2; + } + } } /* Perform a raw data read. This will automatically detect the track type and read the proper data (audio or data). */ -static int -read_audio(struct cdrom_read_audio *ra) +static int read_audio(struct cdrom_read_audio *ra) { - int retval; - unsigned char params[2]; - unsigned char res_reg[12]; - unsigned int res_size; - unsigned int cframe; - unsigned long flags; - - /* - * Make sure no one else is using the driver; wait for them - * to finish if it is so. - */ - save_flags(flags); - cli(); - while (sony_inuse) - { - interruptible_sleep_on(&sony_wait); - if (signal_pending(current)) - { - restore_flags(flags); - return -EAGAIN; - } - } - sony_inuse = 1; - has_cd_task = current; - restore_flags(flags); - - if (!sony_spun_up) - { - scd_spinup(); - } - - /* Set the drive to do raw operations. */ - params[0] = SONY_SD_DECODE_PARAM; - params[1] = 0x06 | sony_raw_data_mode; - do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, - params, - 2, - res_reg, - &res_size); - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk("CDU31A: Unable to set decode params: 0x%2.2x\n", res_reg[1]); - return -EIO; - } - - /* From here down, we have to goto exit_read_audio instead of returning - because the drive parameters have to be set back to data before - return. */ - - retval = 0; - /* start_request clears out any readahead data, so it should be safe. */ - if (start_request(ra->addr.lba, ra->nframes, 1)) - { - retval = -EIO; - goto exit_read_audio; - } - - /* For every requested frame. */ - cframe = 0; - while (cframe < ra->nframes) - { - read_audio_data(readahead_buffer, res_reg, &res_size); - if ((res_reg[0] & 0xf0) == 0x20) - { - if (res_reg[1] == SONY_BAD_DATA_ERR) - { - printk("CDU31A: Data error on audio sector %d\n", - ra->addr.lba + cframe); - } - else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) - { - /* Illegal track type, change track types and start over. */ - sony_raw_data_mode = (sony_raw_data_mode) ? 0 : 1; - - /* Set the drive mode. */ - params[0] = SONY_SD_DECODE_PARAM; - params[1] = 0x06 | sony_raw_data_mode; - do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, - params, - 2, - res_reg, - &res_size); - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk("CDU31A: Unable to set decode params: 0x%2.2x\n", res_reg[1]); - retval = -EIO; - goto exit_read_audio; - } - - /* Restart the request on the current frame. */ - if (start_request(ra->addr.lba + cframe, ra->nframes - cframe, 1)) - { - retval = -EIO; - goto exit_read_audio; - } - - /* Don't go back to the top because don't want to get into - and infinite loop. A lot of code gets duplicated, but - that's no big deal, I don't guess. */ - read_audio_data(readahead_buffer, res_reg, &res_size); - if ((res_reg[0] & 0xf0) == 0x20) - { - if (res_reg[1] == SONY_BAD_DATA_ERR) - { - printk("CDU31A: Data error on audio sector %d\n", - ra->addr.lba + cframe); - } - else - { - printk("CDU31A: Error reading audio data on sector %d: %s\n", - ra->addr.lba + cframe, - translate_error(res_reg[1])); - retval = -EIO; - goto exit_read_audio; - } - } - else - { - copy_to_user((char *) (ra->buf + (CD_FRAMESIZE_RAW * cframe)), - (char *) readahead_buffer, - CD_FRAMESIZE_RAW); - } - } - else - { - printk("CDU31A: Error reading audio data on sector %d: %s\n", - ra->addr.lba + cframe, - translate_error(res_reg[1])); - retval = -EIO; - goto exit_read_audio; - } - } - else - { - copy_to_user((char *) (ra->buf + (CD_FRAMESIZE_RAW * cframe)), - (char *) readahead_buffer, - CD_FRAMESIZE_RAW); - } - - cframe++; - } - - get_result(res_reg, &res_size); - if ((res_reg[0] & 0xf0) == 0x20) - { - printk("CDU31A: Error return from audio read: %s\n", - translate_error(res_reg[1])); - retval = -EIO; - goto exit_read_audio; - } - -exit_read_audio: - - /* Set the drive mode back to the proper one for the disk. */ - params[0] = SONY_SD_DECODE_PARAM; - if (!sony_xa_mode) - { - params[1] = 0x0f; - } - else - { - params[1] = 0x07; - } - do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, - params, - 2, - res_reg, - &res_size); - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk("CDU31A: Unable to reset decode params: 0x%2.2x\n", res_reg[1]); - return -EIO; - } - - has_cd_task = NULL; - sony_inuse = 0; - wake_up_interruptible(&sony_wait); + int retval; + unsigned char params[2]; + unsigned char res_reg[12]; + unsigned int res_size; + unsigned int cframe; + unsigned long flags; + + /* + * Make sure no one else is using the driver; wait for them + * to finish if it is so. + */ + save_flags(flags); + cli(); + while (sony_inuse) { + interruptible_sleep_on(&sony_wait); + if (signal_pending(current)) { + restore_flags(flags); + return -EAGAIN; + } + } + sony_inuse = 1; + has_cd_task = current; + restore_flags(flags); + + if (!sony_spun_up) { + scd_spinup(); + } + + /* Set the drive to do raw operations. */ + params[0] = SONY_SD_DECODE_PARAM; + params[1] = 0x06 | sony_raw_data_mode; + do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, + params, 2, res_reg, &res_size); + if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { + printk("CDU31A: Unable to set decode params: 0x%2.2x\n", + res_reg[1]); + return -EIO; + } + + /* From here down, we have to goto exit_read_audio instead of returning + because the drive parameters have to be set back to data before + return. */ + + retval = 0; + /* start_request clears out any readahead data, so it should be safe. */ + if (start_request(ra->addr.lba, ra->nframes, 1)) { + retval = -EIO; + goto exit_read_audio; + } + + /* For every requested frame. */ + cframe = 0; + while (cframe < ra->nframes) { + read_audio_data(readahead_buffer, res_reg, &res_size); + if ((res_reg[0] & 0xf0) == 0x20) { + if (res_reg[1] == SONY_BAD_DATA_ERR) { + printk + ("CDU31A: Data error on audio sector %d\n", + ra->addr.lba + cframe); + } else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) { + /* Illegal track type, change track types and start over. */ + sony_raw_data_mode = + (sony_raw_data_mode) ? 0 : 1; + + /* Set the drive mode. */ + params[0] = SONY_SD_DECODE_PARAM; + params[1] = 0x06 | sony_raw_data_mode; + do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, + params, + 2, res_reg, &res_size); + if ((res_size < 2) + || ((res_reg[0] & 0xf0) == 0x20)) { + printk + ("CDU31A: Unable to set decode params: 0x%2.2x\n", + res_reg[1]); + retval = -EIO; + goto exit_read_audio; + } + + /* Restart the request on the current frame. */ + if (start_request + (ra->addr.lba + cframe, + ra->nframes - cframe, 1)) { + retval = -EIO; + goto exit_read_audio; + } + + /* Don't go back to the top because don't want to get into + and infinite loop. A lot of code gets duplicated, but + that's no big deal, I don't guess. */ + read_audio_data(readahead_buffer, res_reg, + &res_size); + if ((res_reg[0] & 0xf0) == 0x20) { + if (res_reg[1] == + SONY_BAD_DATA_ERR) { + printk + ("CDU31A: Data error on audio sector %d\n", + ra->addr.lba + + cframe); + } else { + printk + ("CDU31A: Error reading audio data on sector %d: %s\n", + ra->addr.lba + cframe, + translate_error + (res_reg[1])); + retval = -EIO; + goto exit_read_audio; + } + } else { + copy_to_user((char *) (ra->buf + + (CD_FRAMESIZE_RAW + * cframe)), + (char *) + readahead_buffer, + CD_FRAMESIZE_RAW); + } + } else { + printk + ("CDU31A: Error reading audio data on sector %d: %s\n", + ra->addr.lba + cframe, + translate_error(res_reg[1])); + retval = -EIO; + goto exit_read_audio; + } + } else { + copy_to_user((char *) (ra->buf + + (CD_FRAMESIZE_RAW * + cframe)), + (char *) readahead_buffer, + CD_FRAMESIZE_RAW); + } + + cframe++; + } + + get_result(res_reg, &res_size); + if ((res_reg[0] & 0xf0) == 0x20) { + printk("CDU31A: Error return from audio read: %s\n", + translate_error(res_reg[1])); + retval = -EIO; + goto exit_read_audio; + } + + exit_read_audio: + + /* Set the drive mode back to the proper one for the disk. */ + params[0] = SONY_SD_DECODE_PARAM; + if (!sony_xa_mode) { + params[1] = 0x0f; + } else { + params[1] = 0x07; + } + do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, + params, 2, res_reg, &res_size); + if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { + printk("CDU31A: Unable to reset decode params: 0x%2.2x\n", + res_reg[1]); + return -EIO; + } + + has_cd_task = NULL; + sony_inuse = 0; + wake_up_interruptible(&sony_wait); - return(retval); + return (retval); } static int do_sony_cd_cmd_chk(const char *name, - unsigned char cmd, - unsigned char *params, - unsigned int num_params, - unsigned char *result_buffer, - unsigned int *result_size) -{ - do_sony_cd_cmd(cmd, params, num_params, result_buffer, result_size); - if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) - { - printk("Sony CDROM error %s (CDROM%s)\n", translate_error(result_buffer[1]), name); - return -EIO; - } - return 0; + unsigned char cmd, + unsigned char *params, + unsigned int num_params, + unsigned char *result_buffer, unsigned int *result_size) +{ + do_sony_cd_cmd(cmd, params, num_params, result_buffer, + result_size); + if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) { + printk("Sony CDROM error %s (CDROM%s)\n", + translate_error(result_buffer[1]), name); + return -EIO; + } + return 0; } - + /* * Uniform cdrom interface function * open the tray */ static int scd_tray_move(struct cdrom_device_info *cdi, int position) { - if (position == 1 /* open tray */) - { - unsigned char res_reg[12]; - unsigned int res_size; - - do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size); - do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size); - - sony_audio_status = CDROM_AUDIO_INVALID; - return do_sony_cd_cmd_chk("EJECT",SONY_EJECT_CMD, NULL, 0, res_reg, &res_size); - } else { - if (0 == scd_spinup()) - sony_spun_up = 1; - return 0; - } + if (position == 1 /* open tray */ ) { + unsigned char res_reg[12]; + unsigned int res_size; + + do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, + &res_size); + do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, + &res_size); + + sony_audio_status = CDROM_AUDIO_INVALID; + return do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0, + res_reg, &res_size); + } else { + if (0 == scd_spinup()) + sony_spun_up = 1; + return 0; + } } /* * The big ugly ioctl handler. */ static int scd_audio_ioctl(struct cdrom_device_info *cdi, - unsigned int cmd, - void * arg) + unsigned int cmd, void *arg) { - unsigned char res_reg[12]; - unsigned int res_size; - unsigned char params[7]; - int i; - - - switch (cmd) - { - case CDROMSTART: /* Spin up the drive */ - return do_sony_cd_cmd_chk("START",SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); - break; - - case CDROMSTOP: /* Spin down the drive */ - do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size); - - /* - * Spin the drive down, ignoring the error if the disk was - * already not spinning. - */ - sony_audio_status = CDROM_AUDIO_NO_STATUS; - return do_sony_cd_cmd_chk("STOP",SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size); - - case CDROMPAUSE: /* Pause the drive */ - if(do_sony_cd_cmd_chk("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size)) - return -EIO; - /* Get the current position and save it for resuming */ - if (read_subcode() < 0) - { - return -EIO; - } - cur_pos_msf[0] = last_sony_subcode.abs_msf[0]; - cur_pos_msf[1] = last_sony_subcode.abs_msf[1]; - cur_pos_msf[2] = last_sony_subcode.abs_msf[2]; - sony_audio_status = CDROM_AUDIO_PAUSED; - return 0; - break; - - case CDROMRESUME: /* Start the drive after being paused */ - if (sony_audio_status != CDROM_AUDIO_PAUSED) - { - return -EINVAL; - } - - do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); - - /* Start the drive at the saved position. */ - params[1] = int_to_bcd(cur_pos_msf[0]); - params[2] = int_to_bcd(cur_pos_msf[1]); - params[3] = int_to_bcd(cur_pos_msf[2]); - params[4] = int_to_bcd(final_pos_msf[0]); - params[5] = int_to_bcd(final_pos_msf[1]); - params[6] = int_to_bcd(final_pos_msf[2]); - params[0] = 0x03; - if(do_sony_cd_cmd_chk("RESUME",SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size)<0) - return -EIO; - sony_audio_status = CDROM_AUDIO_PLAY; - return 0; - - case CDROMPLAYMSF: /* Play starting at the given MSF address. */ - do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); - - /* The parameters are given in int, must be converted */ - for (i=1; i<7; i++) - { - params[i] = int_to_bcd(((unsigned char *)arg)[i-1]); - } - params[0] = 0x03; - if(do_sony_cd_cmd_chk("PLAYMSF",SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size)<0) - return -EIO; - - /* Save the final position for pauses and resumes */ - final_pos_msf[0] = bcd_to_int(params[4]); - final_pos_msf[1] = bcd_to_int(params[5]); - final_pos_msf[2] = bcd_to_int(params[6]); - sony_audio_status = CDROM_AUDIO_PLAY; - return 0; - - case CDROMREADTOCHDR: /* Read the table of contents header */ - { - struct cdrom_tochdr *hdr; - - sony_get_toc(); - if (!sony_toc_read) - { - return -EIO; - } - - hdr = (struct cdrom_tochdr *) arg; - hdr->cdth_trk0 = sony_toc.first_track_num; - hdr->cdth_trk1 = sony_toc.last_track_num; - } - return 0; - - case CDROMREADTOCENTRY: /* Read a given table of contents entry */ - { - struct cdrom_tocentry *entry; - int track_idx; - unsigned char *msf_val = NULL; - - sony_get_toc(); - if (!sony_toc_read) - { - return -EIO; - } - - entry = (struct cdrom_tocentry *) arg; - - track_idx = find_track(entry->cdte_track); - if (track_idx < 0) - { - return -EINVAL; - } - - entry->cdte_adr = sony_toc.tracks[track_idx].address; - entry->cdte_ctrl = sony_toc.tracks[track_idx].control; - msf_val = sony_toc.tracks[track_idx].track_start_msf; - - /* Logical buffer address or MSF format requested? */ - if (entry->cdte_format == CDROM_LBA) - { - entry->cdte_addr.lba = msf_to_log(msf_val); - } - else if (entry->cdte_format == CDROM_MSF) - { - entry->cdte_addr.msf.minute = *msf_val; - entry->cdte_addr.msf.second = *(msf_val+1); - entry->cdte_addr.msf.frame = *(msf_val+2); - } - } - return 0; - break; - - case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ - { - struct cdrom_ti *ti = (struct cdrom_ti *) arg; - int track_idx; - - sony_get_toc(); - if (!sony_toc_read) - { - return -EIO; - } - - if ( (ti->cdti_trk0 < sony_toc.first_track_num) - || (ti->cdti_trk0 > sony_toc.last_track_num) - || (ti->cdti_trk1 < ti->cdti_trk0)) - { - return -EINVAL; - } - - track_idx = find_track(ti->cdti_trk0); - if (track_idx < 0) - { - return -EINVAL; - } - params[1] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[0]); - params[2] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[1]); - params[3] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[2]); - - /* - * If we want to stop after the last track, use the lead-out - * MSF to do that. - */ - if (ti->cdti_trk1 >= sony_toc.last_track_num) - { - track_idx = find_track(CDROM_LEADOUT); - } - else - { - track_idx = find_track(ti->cdti_trk1+1); - } - if (track_idx < 0) - { - return -EINVAL; - } - params[4] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[0]); - params[5] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[1]); - params[6] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[2]); - params[0] = 0x03; - - do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); - - do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size); - - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk("Params: %x %x %x %x %x %x %x\n", params[0], params[1], - params[2], params[3], params[4], params[5], params[6]); - printk("Sony CDROM error %s (CDROMPLAYTRKIND)\n", translate_error(res_reg[1])); - return -EIO; - } - - /* Save the final position for pauses and resumes */ - final_pos_msf[0] = bcd_to_int(params[4]); - final_pos_msf[1] = bcd_to_int(params[5]); - final_pos_msf[2] = bcd_to_int(params[6]); - sony_audio_status = CDROM_AUDIO_PLAY; - return 0; - } - - case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */ - { - struct cdrom_volctrl *volctrl = (struct cdrom_volctrl *) arg; - - params[0] = SONY_SD_AUDIO_VOLUME; - params[1] = volctrl->channel0; - params[2] = volctrl->channel1; - return do_sony_cd_cmd_chk("VOLCTRL",SONY_SET_DRIVE_PARAM_CMD, params, 3, res_reg, &res_size); - } - case CDROMSUBCHNL: /* Get subchannel info */ - return sony_get_subchnl_info((struct cdrom_subchnl *)arg); - - default: - return -EINVAL; - } + unsigned char res_reg[12]; + unsigned int res_size; + unsigned char params[7]; + int i; + + + switch (cmd) { + case CDROMSTART: /* Spin up the drive */ + return do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL, + 0, res_reg, &res_size); + break; + + case CDROMSTOP: /* Spin down the drive */ + do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, + &res_size); + + /* + * Spin the drive down, ignoring the error if the disk was + * already not spinning. + */ + sony_audio_status = CDROM_AUDIO_NO_STATUS; + return do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL, + 0, res_reg, &res_size); + + case CDROMPAUSE: /* Pause the drive */ + if (do_sony_cd_cmd_chk + ("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, + &res_size)) + return -EIO; + /* Get the current position and save it for resuming */ + if (read_subcode() < 0) { + return -EIO; + } + cur_pos_msf[0] = last_sony_subcode.abs_msf[0]; + cur_pos_msf[1] = last_sony_subcode.abs_msf[1]; + cur_pos_msf[2] = last_sony_subcode.abs_msf[2]; + sony_audio_status = CDROM_AUDIO_PAUSED; + return 0; + break; + + case CDROMRESUME: /* Start the drive after being paused */ + if (sony_audio_status != CDROM_AUDIO_PAUSED) { + return -EINVAL; + } + + do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, + &res_size); + + /* Start the drive at the saved position. */ + params[1] = int_to_bcd(cur_pos_msf[0]); + params[2] = int_to_bcd(cur_pos_msf[1]); + params[3] = int_to_bcd(cur_pos_msf[2]); + params[4] = int_to_bcd(final_pos_msf[0]); + params[5] = int_to_bcd(final_pos_msf[1]); + params[6] = int_to_bcd(final_pos_msf[2]); + params[0] = 0x03; + if (do_sony_cd_cmd_chk + ("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, + &res_size) < 0) + return -EIO; + sony_audio_status = CDROM_AUDIO_PLAY; + return 0; + + case CDROMPLAYMSF: /* Play starting at the given MSF address. */ + do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, + &res_size); + + /* The parameters are given in int, must be converted */ + for (i = 1; i < 7; i++) { + params[i] = + int_to_bcd(((unsigned char *) arg)[i - 1]); + } + params[0] = 0x03; + if (do_sony_cd_cmd_chk + ("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7, + res_reg, &res_size) < 0) + return -EIO; + + /* Save the final position for pauses and resumes */ + final_pos_msf[0] = bcd_to_int(params[4]); + final_pos_msf[1] = bcd_to_int(params[5]); + final_pos_msf[2] = bcd_to_int(params[6]); + sony_audio_status = CDROM_AUDIO_PLAY; + return 0; + + case CDROMREADTOCHDR: /* Read the table of contents header */ + { + struct cdrom_tochdr *hdr; + + sony_get_toc(); + if (!sony_toc_read) { + return -EIO; + } + + hdr = (struct cdrom_tochdr *) arg; + hdr->cdth_trk0 = sony_toc.first_track_num; + hdr->cdth_trk1 = sony_toc.last_track_num; + } + return 0; + + case CDROMREADTOCENTRY: /* Read a given table of contents entry */ + { + struct cdrom_tocentry *entry; + int track_idx; + unsigned char *msf_val = NULL; + + sony_get_toc(); + if (!sony_toc_read) { + return -EIO; + } + + entry = (struct cdrom_tocentry *) arg; + + track_idx = find_track(entry->cdte_track); + if (track_idx < 0) { + return -EINVAL; + } + + entry->cdte_adr = + sony_toc.tracks[track_idx].address; + entry->cdte_ctrl = + sony_toc.tracks[track_idx].control; + msf_val = + sony_toc.tracks[track_idx].track_start_msf; + + /* Logical buffer address or MSF format requested? */ + if (entry->cdte_format == CDROM_LBA) { + entry->cdte_addr.lba = msf_to_log(msf_val); + } else if (entry->cdte_format == CDROM_MSF) { + entry->cdte_addr.msf.minute = *msf_val; + entry->cdte_addr.msf.second = + *(msf_val + 1); + entry->cdte_addr.msf.frame = + *(msf_val + 2); + } + } + return 0; + break; + + case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ + { + struct cdrom_ti *ti = (struct cdrom_ti *) arg; + int track_idx; + + sony_get_toc(); + if (!sony_toc_read) { + return -EIO; + } + + if ((ti->cdti_trk0 < sony_toc.first_track_num) + || (ti->cdti_trk0 > sony_toc.last_track_num) + || (ti->cdti_trk1 < ti->cdti_trk0)) { + return -EINVAL; + } + + track_idx = find_track(ti->cdti_trk0); + if (track_idx < 0) { + return -EINVAL; + } + params[1] = + int_to_bcd(sony_toc.tracks[track_idx]. + track_start_msf[0]); + params[2] = + int_to_bcd(sony_toc.tracks[track_idx]. + track_start_msf[1]); + params[3] = + int_to_bcd(sony_toc.tracks[track_idx]. + track_start_msf[2]); + + /* + * If we want to stop after the last track, use the lead-out + * MSF to do that. + */ + if (ti->cdti_trk1 >= sony_toc.last_track_num) { + track_idx = find_track(CDROM_LEADOUT); + } else { + track_idx = find_track(ti->cdti_trk1 + 1); + } + if (track_idx < 0) { + return -EINVAL; + } + params[4] = + int_to_bcd(sony_toc.tracks[track_idx]. + track_start_msf[0]); + params[5] = + int_to_bcd(sony_toc.tracks[track_idx]. + track_start_msf[1]); + params[6] = + int_to_bcd(sony_toc.tracks[track_idx]. + track_start_msf[2]); + params[0] = 0x03; + + do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, + &res_size); + + do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, + res_reg, &res_size); + + if ((res_size < 2) + || ((res_reg[0] & 0xf0) == 0x20)) { + printk("Params: %x %x %x %x %x %x %x\n", + params[0], params[1], params[2], + params[3], params[4], params[5], + params[6]); + printk + ("Sony CDROM error %s (CDROMPLAYTRKIND)\n", + translate_error(res_reg[1])); + return -EIO; + } + + /* Save the final position for pauses and resumes */ + final_pos_msf[0] = bcd_to_int(params[4]); + final_pos_msf[1] = bcd_to_int(params[5]); + final_pos_msf[2] = bcd_to_int(params[6]); + sony_audio_status = CDROM_AUDIO_PLAY; + return 0; + } + + case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */ + { + struct cdrom_volctrl *volctrl = + (struct cdrom_volctrl *) arg; + + params[0] = SONY_SD_AUDIO_VOLUME; + params[1] = volctrl->channel0; + params[2] = volctrl->channel1; + return do_sony_cd_cmd_chk("VOLCTRL", + SONY_SET_DRIVE_PARAM_CMD, + params, 3, res_reg, + &res_size); + } + case CDROMSUBCHNL: /* Get subchannel info */ + return sony_get_subchnl_info((struct cdrom_subchnl *) arg); + + default: + return -EINVAL; + } } static int scd_dev_ioctl(struct cdrom_device_info *cdi, - unsigned int cmd, - unsigned long arg) + unsigned int cmd, unsigned long arg) { - int i; + int i; - switch (cmd) - { - case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte - raw data tracks. */ - { - struct cdrom_read_audio ra; - - - sony_get_toc(); - if (!sony_toc_read) - { - return -EIO; - } - - if(copy_from_user(&ra, (char *) arg, sizeof(ra))) - return -EFAULT; - - if (ra.nframes == 0) - { - return 0; - } - - i=verify_area(VERIFY_WRITE, ra.buf, CD_FRAMESIZE_RAW * ra.nframes); - if(i<0) - return i; - - if (ra.addr_format == CDROM_LBA) - { - if ( (ra.addr.lba >= sony_toc.lead_out_start_lba) - || (ra.addr.lba + ra.nframes >= sony_toc.lead_out_start_lba)) - { - return -EINVAL; - } - } - else if (ra.addr_format == CDROM_MSF) - { - if ( (ra.addr.msf.minute >= 75) - || (ra.addr.msf.second >= 60) - || (ra.addr.msf.frame >= 75)) - { - return -EINVAL; - } - - ra.addr.lba = ( (ra.addr.msf.minute * 4500) - + (ra.addr.msf.second * 75) - + ra.addr.msf.frame); - if ( (ra.addr.lba >= sony_toc.lead_out_start_lba) - || (ra.addr.lba + ra.nframes >= sony_toc.lead_out_start_lba)) - { - return -EINVAL; - } - - /* I know, this can go negative on an unsigned. However, - the first thing done to the data is to add this value, - so this should compensate and allow direct msf access. */ - ra.addr.lba -= LOG_START_OFFSET; - } - else - { - return -EINVAL; - } - - return(read_audio(&ra)); - } - return 0; - break; - - default: - return -EINVAL; - } + switch (cmd) { + case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte + raw data tracks. */ + { + struct cdrom_read_audio ra; + + + sony_get_toc(); + if (!sony_toc_read) { + return -EIO; + } + + if (copy_from_user(&ra, (char *) arg, sizeof(ra))) + return -EFAULT; + + if (ra.nframes == 0) { + return 0; + } + + i = verify_area(VERIFY_WRITE, ra.buf, + CD_FRAMESIZE_RAW * ra.nframes); + if (i < 0) + return i; + + if (ra.addr_format == CDROM_LBA) { + if ((ra.addr.lba >= + sony_toc.lead_out_start_lba) + || (ra.addr.lba + ra.nframes >= + sony_toc.lead_out_start_lba)) { + return -EINVAL; + } + } else if (ra.addr_format == CDROM_MSF) { + if ((ra.addr.msf.minute >= 75) + || (ra.addr.msf.second >= 60) + || (ra.addr.msf.frame >= 75)) { + return -EINVAL; + } + + ra.addr.lba = ((ra.addr.msf.minute * 4500) + + (ra.addr.msf.second * 75) + + ra.addr.msf.frame); + if ((ra.addr.lba >= + sony_toc.lead_out_start_lba) + || (ra.addr.lba + ra.nframes >= + sony_toc.lead_out_start_lba)) { + return -EINVAL; + } + + /* I know, this can go negative on an unsigned. However, + the first thing done to the data is to add this value, + so this should compensate and allow direct msf access. */ + ra.addr.lba -= LOG_START_OFFSET; + } else { + return -EINVAL; + } + + return (read_audio(&ra)); + } + return 0; + break; + + default: + return -EINVAL; + } } static int scd_spinup(void) { - unsigned char res_reg[12]; - unsigned int res_size; - int num_spin_ups; - - num_spin_ups = 0; - -respinup_on_open: - do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); - - /* The drive sometimes returns error 0. I don't know why, but ignore - it. It seems to mean the drive has already done the operation. */ - if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) - { - printk("Sony CDROM %s error (scd_open, spin up)\n", translate_error(res_reg[1])); - return 1; - } - - do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size); - - /* The drive sometimes returns error 0. I don't know why, but ignore - it. It seems to mean the drive has already done the operation. */ - if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) - { - /* If the drive is already playing, it's ok. */ - if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) || (res_reg[1] == 0)) - { - return 0; - } - - /* If the drive says it is not spun up (even though we just did it!) - then retry the operation at least a few times. */ - if ( (res_reg[1] == SONY_NOT_SPIN_ERR) - && (num_spin_ups < MAX_CDU31A_RETRIES)) - { - num_spin_ups++; - goto respinup_on_open; - } - - printk("Sony CDROM error %s (scd_open, read toc)\n", translate_error(res_reg[1])); - do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size); - return 1; - } - return 0; + unsigned char res_reg[12]; + unsigned int res_size; + int num_spin_ups; + + num_spin_ups = 0; + + respinup_on_open: + do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); + + /* The drive sometimes returns error 0. I don't know why, but ignore + it. It seems to mean the drive has already done the operation. */ + if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) { + printk("Sony CDROM %s error (scd_open, spin up)\n", + translate_error(res_reg[1])); + return 1; + } + + do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size); + + /* The drive sometimes returns error 0. I don't know why, but ignore + it. It seems to mean the drive has already done the operation. */ + if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) { + /* If the drive is already playing, it's ok. */ + if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) + || (res_reg[1] == 0)) { + return 0; + } + + /* If the drive says it is not spun up (even though we just did it!) + then retry the operation at least a few times. */ + if ((res_reg[1] == SONY_NOT_SPIN_ERR) + && (num_spin_ups < MAX_CDU31A_RETRIES)) { + num_spin_ups++; + goto respinup_on_open; + } + + printk("Sony CDROM error %s (scd_open, read toc)\n", + translate_error(res_reg[1])); + do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, + &res_size); + return 1; + } + return 0; } /* * Open the drive for operations. Spin the drive up and read the table of * contents if these have not already been done. */ -static int -scd_open(struct cdrom_device_info *cdi, int openmode) +static int scd_open(struct cdrom_device_info *cdi, int openmode) { - unsigned char res_reg[12]; - unsigned int res_size; - unsigned char params[2]; - - MOD_INC_USE_COUNT; - if (sony_usage == 0) - { - if (scd_spinup() != 0) { - MOD_DEC_USE_COUNT; - return -EIO; - } - sony_get_toc(); - if (!sony_toc_read) - { - do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size); - MOD_DEC_USE_COUNT; - return -EIO; - } - - /* For XA on the CDU31A only, we have to do special reads. - The CDU33A handles XA automagically. */ - /* if ( (sony_toc.disk_type == SONY_XA_DISK_TYPE) */ - if ( (sony_toc.disk_type != 0x00) - && (!is_double_speed)) - { - params[0] = SONY_SD_DECODE_PARAM; - params[1] = 0x07; - do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, - params, - 2, - res_reg, - &res_size); - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk("CDU31A: Unable to set XA params: 0x%2.2x\n", res_reg[1]); - } - sony_xa_mode = 1; - } - /* A non-XA disk. Set the parms back if necessary. */ - else if (sony_xa_mode) - { - params[0] = SONY_SD_DECODE_PARAM; - params[1] = 0x0f; - do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, - params, - 2, - res_reg, - &res_size); - if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) - { - printk("CDU31A: Unable to reset XA params: 0x%2.2x\n", res_reg[1]); - } - sony_xa_mode = 0; - } + unsigned char res_reg[12]; + unsigned int res_size; + unsigned char params[2]; + + MOD_INC_USE_COUNT; + if (sony_usage == 0) { + if (scd_spinup() != 0) { + MOD_DEC_USE_COUNT; + return -EIO; + } + sony_get_toc(); + if (!sony_toc_read) { + do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, + res_reg, &res_size); + MOD_DEC_USE_COUNT; + return -EIO; + } + + /* For XA on the CDU31A only, we have to do special reads. + The CDU33A handles XA automagically. */ + /* if ( (sony_toc.disk_type == SONY_XA_DISK_TYPE) */ + if ((sony_toc.disk_type != 0x00) + && (!is_double_speed)) { + params[0] = SONY_SD_DECODE_PARAM; + params[1] = 0x07; + do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, + params, 2, res_reg, &res_size); + if ((res_size < 2) + || ((res_reg[0] & 0xf0) == 0x20)) { + printk + ("CDU31A: Unable to set XA params: 0x%2.2x\n", + res_reg[1]); + } + sony_xa_mode = 1; + } + /* A non-XA disk. Set the parms back if necessary. */ + else if (sony_xa_mode) { + params[0] = SONY_SD_DECODE_PARAM; + params[1] = 0x0f; + do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, + params, 2, res_reg, &res_size); + if ((res_size < 2) + || ((res_reg[0] & 0xf0) == 0x20)) { + printk + ("CDU31A: Unable to reset XA params: 0x%2.2x\n", + res_reg[1]); + } + sony_xa_mode = 0; + } - sony_spun_up = 1; - } + sony_spun_up = 1; + } - sony_usage++; + sony_usage++; - return 0; + return 0; } @@ -3205,114 +3171,109 @@ * Close the drive. Spin it down if no task is using it. The spin * down will fail if playing audio, so audio play is OK. */ -static void -scd_release(struct cdrom_device_info *cdi) +static void scd_release(struct cdrom_device_info *cdi) { - if (sony_usage == 1) - { - unsigned char res_reg[12]; - unsigned int res_size; - - do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size); - - sony_spun_up = 0; - } - sony_usage--; - MOD_DEC_USE_COUNT; + if (sony_usage == 1) { + unsigned char res_reg[12]; + unsigned int res_size; + + do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, + &res_size); + + sony_spun_up = 0; + } + sony_usage--; + MOD_DEC_USE_COUNT; } static struct cdrom_device_ops scd_dops = { - open: scd_open, - release: scd_release, - drive_status: scd_drive_status, - media_changed: scd_media_changed, - tray_move: scd_tray_move, - lock_door: scd_lock_door, - select_speed: scd_select_speed, - get_last_session: scd_get_last_session, - get_mcn: scd_get_mcn, - reset: scd_reset, - audio_ioctl: scd_audio_ioctl, - dev_ioctl: scd_dev_ioctl, - capability: CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | - CDC_SELECT_SPEED | CDC_MULTI_SESSION | - CDC_MULTI_SESSION | CDC_MCN | - CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | - CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, - n_minors: 1, + open:scd_open, + release:scd_release, + drive_status:scd_drive_status, + media_changed:scd_media_changed, + tray_move:scd_tray_move, + lock_door:scd_lock_door, + select_speed:scd_select_speed, + get_last_session:scd_get_last_session, + get_mcn:scd_get_mcn, + reset:scd_reset, + audio_ioctl:scd_audio_ioctl, + dev_ioctl:scd_dev_ioctl, + capability:CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | + CDC_SELECT_SPEED | CDC_MULTI_SESSION | + CDC_MULTI_SESSION | CDC_MCN | + CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | + CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, + n_minors:1, }; static struct cdrom_device_info scd_info = { - ops: &scd_dops, - speed: 2, - capacity: 1, - name: "cdu31a" + ops:&scd_dops, + speed:2, + capacity:1, + name:"cdu31a" }; /* The different types of disc loading mechanisms supported */ -static const char *load_mech[] __initdata = { "caddy", "tray", "pop-up", "unknown" }; +static char *load_mech[] __initdata = + { "caddy", "tray", "pop-up", "unknown" }; -static void __init +static void __init get_drive_configuration(unsigned short base_io, - unsigned char res_reg[], - unsigned int *res_size) + unsigned char res_reg[], unsigned int *res_size) { - int retry_count; + int retry_count; - /* Set the base address */ - cdu31a_port = base_io; + /* Set the base address */ + cdu31a_port = base_io; - /* Set up all the register locations */ - sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET; - sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET; - sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET; - sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET; - sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET; - sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET; - sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET; - sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET; - - /* - * Check to see if anything exists at the status register location. - * I don't know if this is a good way to check, but it seems to work - * ok for me. - */ - if (read_status_register() != 0xff) - { - /* - * Reset the drive and wait for attention from it (to say it's reset). - * If you don't wait, the next operation will probably fail. - */ - reset_drive(); - retry_count = jiffies + SONY_RESET_TIMEOUT; - while (time_before(jiffies, retry_count) && (!is_attention())) - { - sony_sleep(); - } + /* Set up all the register locations */ + sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET; + sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET; + sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET; + sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET; + sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET; + sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET; + sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET; + sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET; + + /* + * Check to see if anything exists at the status register location. + * I don't know if this is a good way to check, but it seems to work + * ok for me. + */ + if (read_status_register() != 0xff) { + /* + * Reset the drive and wait for attention from it (to say it's reset). + * If you don't wait, the next operation will probably fail. + */ + reset_drive(); + retry_count = jiffies + SONY_RESET_TIMEOUT; + while (time_before(jiffies, retry_count) + && (!is_attention())) { + sony_sleep(); + } #if 0 - /* If attention is never seen probably not a CDU31a present */ - if (!is_attention()) - { - res_reg[0] = 0x20; - return; - } -#endif - - /* - * Get the drive configuration. - */ - do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD, - NULL, - 0, - (unsigned char *) res_reg, - res_size); - return; - } + /* If attention is never seen probably not a CDU31a present */ + if (!is_attention()) { + res_reg[0] = 0x20; + return; + } +#endif + + /* + * Get the drive configuration. + */ + do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD, + NULL, + 0, (unsigned char *) res_reg, res_size); + return; + } - /* Return an error */ - res_reg[0] = 0x20; + /* Return an error */ + res_reg[0] = 0x20; } #ifndef MODULE @@ -3321,33 +3282,28 @@ */ -static int __init cdu31a_setup(char *strings) +static int __init cdu31a_setup(char *strings) { - int ints[4]; - - (void)get_options(strings, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) - { - cdu31a_port = ints[1]; - } - if (ints[0] > 1) - { - cdu31a_irq = ints[2]; - } - if ((strings != NULL) && (*strings != '\0')) - { - if (strcmp(strings, "PAS") == 0) - { - sony_pas_init = 1; - } - else - { - printk("CDU31A: Unknown interface type: %s\n", strings); - } - } - - return 1; + int ints[4]; + + (void) get_options(strings, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) { + cdu31a_port = ints[1]; + } + if (ints[0] > 1) { + cdu31a_irq = ints[2]; + } + if ((strings != NULL) && (*strings != '\0')) { + if (strcmp(strings, "PAS") == 0) { + sony_pas_init = 1; + } else { + printk("CDU31A: Unknown interface type: %s\n", + strings); + } + } + + return 1; } __setup("cdu31a=", cdu31a_setup); @@ -3359,223 +3315,204 @@ /* * Initialize the driver. */ -int __init -cdu31a_init(void) +int __init cdu31a_init(void) { - struct s_sony_drive_config drive_config; - unsigned int res_size; - char msg[255]; - char buf[40]; - int i; - int drive_found; - int tmp_irq; - - - /* - * According to Alex Freed (freed@europa.orion.adobe.com), this is - * required for the Fusion CD-16 package. If the sound driver is - * loaded, it should work fine, but just in case... - * - * The following turn on the CD-ROM interface for a Fusion CD-16. - */ - if (sony_pas_init) - { - outb(0xbc, 0x9a01); - outb(0xe2, 0x9a01); - } - - drive_found = 0; - - /* Setting the base I/O address to 0xffff will disable it. */ - if (cdu31a_port == 0xffff) - { - } - else if (cdu31a_port != 0) - { - tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ - cdu31a_irq = 0; - - get_drive_configuration(cdu31a_port, - drive_config.exec_status, - &res_size); - if ((res_size > 2) && ((drive_config.exec_status[0] & 0xf0) == 0x00)) - { - drive_found = 1; - } - - cdu31a_irq = tmp_irq; - } - else - { - cdu31a_irq = 0; - i = 0; - while ( (cdu31a_addresses[i].base != 0) - && (!drive_found)) - { - if (check_region(cdu31a_addresses[i].base, 4)) { - i++; - continue; - } - get_drive_configuration(cdu31a_addresses[i].base, - drive_config.exec_status, - &res_size); - if ((res_size > 2) && ((drive_config.exec_status[0] & 0xf0) == 0x00)) - { - drive_found = 1; - cdu31a_irq = cdu31a_addresses[i].int_num; - } - else - { - i++; - } - } - } - - if (drive_found) - { - int deficiency=0; - - request_region(cdu31a_port, 4,"cdu31a"); - - if (devfs_register_blkdev(MAJOR_NR,"cdu31a",&cdrom_fops)) - { - printk("Unable to get major %d for CDU-31a\n", MAJOR_NR); - goto errout2; - } - - if (SONY_HWC_DOUBLE_SPEED(drive_config)) - { - is_double_speed = 1; - } - - tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ - cdu31a_irq = 0; - - set_drive_params(sony_speed); - - cdu31a_irq = tmp_irq; - - if (cdu31a_irq > 0) - { - if (request_irq(cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT, "cdu31a", NULL)) - { - printk("Unable to grab IRQ%d for the CDU31A driver\n", cdu31a_irq); - cdu31a_irq = 0; - } - } - - sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n", - drive_config.vendor_id, - drive_config.product_id, - drive_config.product_rev_level); - sprintf(buf, " Capabilities: %s", - load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]); - strcat(msg, buf); - if (SONY_HWC_AUDIO_PLAYBACK(drive_config)) - { - strcat(msg, ", audio"); - } else - deficiency |= CDC_PLAY_AUDIO; - if (SONY_HWC_EJECT(drive_config)) - { - strcat(msg, ", eject"); - } else - deficiency |= CDC_OPEN_TRAY; - if (SONY_HWC_LED_SUPPORT(drive_config)) - { - strcat(msg, ", LED"); - } - if (SONY_HWC_ELECTRIC_VOLUME(drive_config)) - { - strcat(msg, ", elec. Vol"); - } - if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config)) - { - strcat(msg, ", sep. Vol"); - } - if (is_double_speed) - { - strcat(msg, ", double speed"); - } else - deficiency |= CDC_SELECT_SPEED; - if (cdu31a_irq > 0) - { - sprintf(buf, ", irq %d", cdu31a_irq); - strcat(msg, buf); - } - strcat(msg, "\n"); - - is_a_cdu31a = strcmp("CD-ROM CDU31A", drive_config.product_id) == 0; - - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); - read_ahead[MAJOR_NR] = CDU31A_READAHEAD; - cdu31a_block_size = 1024; /* 1kB default block size */ - /* use 'mount -o block=2048' */ - blksize_size[MAJOR_NR] = &cdu31a_block_size; - - init_timer(&cdu31a_abort_timer); - cdu31a_abort_timer.function = handle_abort_timeout; - - scd_info.dev = MKDEV(MAJOR_NR,0); - scd_info.mask = deficiency; - strncpy(scd_info.name, "cdu31a", sizeof(scd_info.name)); - - if (register_cdrom(&scd_info)) - { - goto errout0; - } - } - - - disk_changed = 1; - - if (drive_found) - { - return(0); - } - else - { - goto errout3; - } -errout0: - printk("Unable to register CDU-31a with Uniform cdrom driver\n"); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - if (devfs_unregister_blkdev(MAJOR_NR, "cdu31a")) - { - printk("Can't unregister block device for cdu31a\n"); - } -errout2: - release_region(cdu31a_port,4); -errout3: - return -EIO; -} - - -void __exit -cdu31a_exit(void) -{ - if (unregister_cdrom(&scd_info)) - { - printk("Can't unregister cdu31a from Uniform cdrom driver\n"); - return; - } - if ((devfs_unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) - { - printk("Can't unregister cdu31a\n"); - return; - } - - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - - if (cdu31a_irq > 0) - free_irq(cdu31a_irq, NULL); - - release_region(cdu31a_port,4); - printk(KERN_INFO "cdu31a module released.\n"); -} + struct s_sony_drive_config drive_config; + unsigned int res_size; + char msg[255]; + char buf[40]; + int i; + int drive_found; + int tmp_irq; + + + /* + * According to Alex Freed (freed@europa.orion.adobe.com), this is + * required for the Fusion CD-16 package. If the sound driver is + * loaded, it should work fine, but just in case... + * + * The following turn on the CD-ROM interface for a Fusion CD-16. + */ + if (sony_pas_init) { + outb(0xbc, 0x9a01); + outb(0xe2, 0x9a01); + } + + drive_found = 0; + + /* Setting the base I/O address to 0xffff will disable it. */ + if (cdu31a_port == 0xffff) { + } else if (cdu31a_port != 0) { + tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ + cdu31a_irq = 0; + + get_drive_configuration(cdu31a_port, + drive_config.exec_status, + &res_size); + if ((res_size > 2) + && ((drive_config.exec_status[0] & 0xf0) == 0x00)) { + drive_found = 1; + } + + cdu31a_irq = tmp_irq; + } else { + cdu31a_irq = 0; + i = 0; + while ((cdu31a_addresses[i].base != 0) + && (!drive_found)) { + if (check_region(cdu31a_addresses[i].base, 4)) { + i++; + continue; + } + get_drive_configuration(cdu31a_addresses[i].base, + drive_config.exec_status, + &res_size); + if ((res_size > 2) + && ((drive_config.exec_status[0] & 0xf0) == + 0x00)) { + drive_found = 1; + cdu31a_irq = cdu31a_addresses[i].int_num; + } else { + i++; + } + } + } + + if (drive_found) { + int deficiency = 0; + + request_region(cdu31a_port, 4, "cdu31a"); + + if (devfs_register_blkdev(MAJOR_NR, "cdu31a", &cdrom_fops)) { + printk("Unable to get major %d for CDU-31a\n", + MAJOR_NR); + goto errout2; + } + + if (SONY_HWC_DOUBLE_SPEED(drive_config)) { + is_double_speed = 1; + } + + tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ + cdu31a_irq = 0; + + set_drive_params(sony_speed); + + cdu31a_irq = tmp_irq; + + if (cdu31a_irq > 0) { + if (request_irq + (cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT, + "cdu31a", NULL)) { + printk + ("Unable to grab IRQ%d for the CDU31A driver\n", + cdu31a_irq); + cdu31a_irq = 0; + } + } + + sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n", + drive_config.vendor_id, + drive_config.product_id, + drive_config.product_rev_level); + sprintf(buf, " Capabilities: %s", + load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]); + strcat(msg, buf); + if (SONY_HWC_AUDIO_PLAYBACK(drive_config)) { + strcat(msg, ", audio"); + } else + deficiency |= CDC_PLAY_AUDIO; + if (SONY_HWC_EJECT(drive_config)) { + strcat(msg, ", eject"); + } else + deficiency |= CDC_OPEN_TRAY; + if (SONY_HWC_LED_SUPPORT(drive_config)) { + strcat(msg, ", LED"); + } + if (SONY_HWC_ELECTRIC_VOLUME(drive_config)) { + strcat(msg, ", elec. Vol"); + } + if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config)) { + strcat(msg, ", sep. Vol"); + } + if (is_double_speed) { + strcat(msg, ", double speed"); + } else + deficiency |= CDC_SELECT_SPEED; + if (cdu31a_irq > 0) { + sprintf(buf, ", irq %d", cdu31a_irq); + strcat(msg, buf); + } + strcat(msg, "\n"); + + is_a_cdu31a = + strcmp("CD-ROM CDU31A", drive_config.product_id) == 0; + + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), + DEVICE_REQUEST); + read_ahead[MAJOR_NR] = CDU31A_READAHEAD; + cdu31a_block_size = 1024; /* 1kB default block size */ + /* use 'mount -o block=2048' */ + blksize_size[MAJOR_NR] = &cdu31a_block_size; + + init_timer(&cdu31a_abort_timer); + cdu31a_abort_timer.function = handle_abort_timeout; + + scd_info.dev = MKDEV(MAJOR_NR, 0); + scd_info.mask = deficiency; + strncpy(scd_info.name, "cdu31a", sizeof(scd_info.name)); + + if (register_cdrom(&scd_info)) { + goto errout0; + } + } + + + disk_changed = 1; + + if (drive_found) { + return (0); + } else { + goto errout3; + } + errout0: + printk("Unable to register CDU-31a with Uniform cdrom driver\n"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + if (devfs_unregister_blkdev(MAJOR_NR, "cdu31a")) { + printk("Can't unregister block device for cdu31a\n"); + } + errout2: + release_region(cdu31a_port, 4); + errout3: + return -EIO; +} + + +void __exit cdu31a_exit(void) +{ + if (unregister_cdrom(&scd_info)) { + printk + ("Can't unregister cdu31a from Uniform cdrom driver\n"); + return; + } + if ((devfs_unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) { + printk("Can't unregister cdu31a\n"); + return; + } + + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + + if (cdu31a_irq > 0) + free_irq(cdu31a_irq, NULL); + + release_region(cdu31a_port, 4); + printk(KERN_INFO "cdu31a module released.\n"); +} #ifdef MODULE module_init(cdu31a_init); #endif module_exit(cdu31a_exit); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c --- v2.4.9/linux/drivers/cdrom/cm206.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/cdrom/cm206.c Fri Sep 7 09:28:38 2001 @@ -178,7 +178,7 @@ * David van Leeuwen, david@tm.tno.nl. */ #define REVISION "$Revision: 1.5 $" -#include +#include #include /* These include what we really need */ #include @@ -211,16 +211,19 @@ address and interrupt request. It can be overridden by the boot parameter `auto'. */ -static int auto_probe=1; /* Yes, why not? */ +static int auto_probe = 1; /* Yes, why not? */ static int cm206_base = CM206_BASE; -static int cm206_irq = CM206_IRQ; -static int cm206[2] = {0,0}; /* for compatible `insmod' parameter passing */ +static int cm206_irq = CM206_IRQ; +#ifdef MODULE +static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */ +#endif MODULE_PARM(cm206_base, "i"); /* base */ MODULE_PARM(cm206_irq, "i"); /* irq */ MODULE_PARM(cm206, "1-2i"); /* base,irq or irq,base */ MODULE_PARM(auto_probe, "i"); /* auto probe base and irq */ +MODULE_LICENSE("GPL"); #define POLLOOP 100 /* milliseconds */ #define READ_AHEAD 1 /* defines private buffer, waste! */ @@ -233,7 +236,7 @@ #define LINUX_BLOCK_SIZE 512 /* WHERE is this defined? */ #define RAW_SECTOR_SIZE 2352 /* ok, is also defined in cdrom.h */ #define ISO_SECTOR_SIZE 2048 -#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE) /* 4 */ +#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE) /* 4 */ #define CD_SYNC_HEAD 16 /* CD_SYNC + CD_HEAD */ #ifdef STATISTICS /* keep track of errors in counters */ @@ -254,88 +257,91 @@ typedef unsigned char uch; /* 8-bits */ typedef unsigned short ush; /* 16-bits */ -struct toc_struct{ /* private copy of Table of Contents */ - uch track, fsm[3], q0; +struct toc_struct { /* private copy of Table of Contents */ + uch track, fsm[3], q0; }; static int cm206_blocksizes[1] = { 2048 }; struct cm206_struct { - volatile ush intr_ds; /* data status read on last interrupt */ - volatile ush intr_ls; /* uart line status read on last interrupt*/ - volatile uch ur[UR_SIZE]; /* uart receive buffer fifo */ - volatile uch ur_w, ur_r; /* write/read buffer index */ - volatile uch dsb, cc; /* drive status byte and condition (error) code */ - int command; /* command to be written to the uart */ - int openfiles; - ush sector[READ_AHEAD*RAW_SECTOR_SIZE/2]; /* buffered cd-sector */ - int sector_first, sector_last; /* range of these sectors */ - wait_queue_head_t uart; /* wait queues for interrupt */ - wait_queue_head_t data; - struct timer_list timer; /* time-out */ - char timed_out; - signed char max_sectors; /* number of sectors that fit in adapter mem */ - char wait_back; /* we're waiting for a background-read */ - char background; /* is a read going on in the background? */ - int adapter_first; /* if so, that's the starting sector */ - int adapter_last; - char fifo_overflowed; - uch disc_status[7]; /* result of get_disc_status command */ + volatile ush intr_ds; /* data status read on last interrupt */ + volatile ush intr_ls; /* uart line status read on last interrupt */ + volatile uch ur[UR_SIZE]; /* uart receive buffer fifo */ + volatile uch ur_w, ur_r; /* write/read buffer index */ + volatile uch dsb, cc; /* drive status byte and condition (error) code */ + int command; /* command to be written to the uart */ + int openfiles; + ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2]; /* buffered cd-sector */ + int sector_first, sector_last; /* range of these sectors */ + wait_queue_head_t uart; /* wait queues for interrupt */ + wait_queue_head_t data; + struct timer_list timer; /* time-out */ + char timed_out; + signed char max_sectors; /* number of sectors that fit in adapter mem */ + char wait_back; /* we're waiting for a background-read */ + char background; /* is a read going on in the background? */ + int adapter_first; /* if so, that's the starting sector */ + int adapter_last; + char fifo_overflowed; + uch disc_status[7]; /* result of get_disc_status command */ #ifdef STATISTICS - int stats[NR_STATS]; - int last_stat[NR_STATS]; /* `time' at which stat was stat */ - int stat_counter; -#endif - struct toc_struct toc[101]; /* The whole table of contents + lead-out */ - uch q[10]; /* Last read q-channel info */ - uch audio_status[5]; /* last read position on pause */ - uch media_changed; /* record if media changed */ + int stats[NR_STATS]; + int last_stat[NR_STATS]; /* `time' at which stat was stat */ + int stat_counter; +#endif + struct toc_struct toc[101]; /* The whole table of contents + lead-out */ + uch q[10]; /* Last read q-channel info */ + uch audio_status[5]; /* last read position on pause */ + uch media_changed; /* record if media changed */ }; #define DISC_STATUS cd->disc_status[0] #define FIRST_TRACK cd->disc_status[1] #define LAST_TRACK cd->disc_status[2] -#define PAUSED cd->audio_status[0] /* misuse this memory byte! */ +#define PAUSED cd->audio_status[0] /* misuse this memory byte! */ #define PLAY_TO cd->toc[0] /* toc[0] records end-time in play */ -static struct cm206_struct * cd; /* the main memory structure */ +static struct cm206_struct *cd; /* the main memory structure */ /* First, we define some polling functions. These are actually only being used in the initialization. */ void send_command_polled(int command) { - int loop=POLLOOP; - while (!(inw(r_line_status) & ls_transmitter_buffer_empty) && loop>0) { - mdelay(1); /* one millisec delay */ - --loop; - } - outw(command, r_uart_transmit); + int loop = POLLOOP; + while (!(inw(r_line_status) & ls_transmitter_buffer_empty) + && loop > 0) { + mdelay(1); /* one millisec delay */ + --loop; + } + outw(command, r_uart_transmit); } uch receive_echo_polled(void) { - int loop=POLLOOP; - while (!(inw(r_line_status) & ls_receive_buffer_full) && loop>0) { - mdelay(1); - --loop; - } - return ((uch) inw(r_uart_receive)); + int loop = POLLOOP; + while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) { + mdelay(1); + --loop; + } + return ((uch) inw(r_uart_receive)); } uch send_receive_polled(int command) { - send_command_polled(command); - return receive_echo_polled(); + send_command_polled(command); + return receive_echo_polled(); } -inline void clear_ur(void) { - if (cd->ur_r != cd->ur_w) { - debug(("Deleting bytes from fifo:")); - for(;cd->ur_r != cd->ur_w; cd->ur_r++, cd->ur_r %= UR_SIZE) - debug((" 0x%x", cd->ur[cd->ur_r])); - debug(("\n")); - } +inline void clear_ur(void) +{ + if (cd->ur_r != cd->ur_w) { + debug(("Deleting bytes from fifo:")); + for (; cd->ur_r != cd->ur_w; + cd->ur_r++, cd->ur_r %= UR_SIZE) + debug((" 0x%x", cd->ur[cd->ur_r])); + debug(("\n")); + } } /* The interrupt handler. When the cm260 generates an interrupt, very @@ -351,252 +357,269 @@ as there seems so reason for this to happen. */ -static void cm206_interrupt(int sig, void *dev_id, struct pt_regs * regs) +static void cm206_interrupt(int sig, void *dev_id, struct pt_regs *regs) /* you rang? */ { - volatile ush fool; - cd->intr_ds = inw(r_data_status); /* resets data_ready, data_error, - crc_error, sync_error, toc_ready - interrupts */ - cd->intr_ls = inw(r_line_status); /* resets overrun bit */ - debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls, cd->background)); - if (cd->intr_ls & ls_attention) stats(attention); - /* receive buffer full? */ - if (cd->intr_ls & ls_receive_buffer_full) { - cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */ - cd->intr_ls = inw(r_line_status); /* resets rbf interrupt */ - debug(("receiving #%d: 0x%x\n", cd->ur_w, cd->ur[cd->ur_w])); - cd->ur_w++; cd->ur_w %= UR_SIZE; - if (cd->ur_w == cd->ur_r) debug(("cd->ur overflow!\n")); - if (waitqueue_active(&cd->uart) && cd->background < 2) { - del_timer(&cd->timer); - wake_up_interruptible(&cd->uart); - } - } - /* data ready in fifo? */ - else if (cd->intr_ds & ds_data_ready) { - if (cd->background) ++cd->adapter_last; - if (waitqueue_active(&cd->data) && (cd->wait_back || !cd->background)) { - del_timer(&cd->timer); - wake_up_interruptible(&cd->data); - } - stats(data_ready); - } - /* ready to issue a write command? */ - else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) { - outw(dc_normal | (inw(r_data_status) & 0x7f), r_data_control); - outw(cd->command, r_uart_transmit); - cd->command=0; - if (!cd->background) wake_up_interruptible(&cd->uart); - } - /* now treat errors (at least, identify them for debugging) */ - else if (cd->intr_ds & ds_fifo_overflow) { - debug(("Fifo overflow at sectors 0x%x\n", cd->sector_first)); - fool = inw(r_fifo_output_buffer); /* de-assert the interrupt */ - cd->fifo_overflowed=1; /* signal one word less should be read */ - stats(fifo_overflow); - } - else if (cd->intr_ds & ds_data_error) { - debug(("Data error at sector 0x%x\n", cd->sector_first)); - stats(data_error); - } - else if (cd->intr_ds & ds_crc_error) { - debug(("CRC error at sector 0x%x\n", cd->sector_first)); - stats(crc_error); - } - else if (cd->intr_ds & ds_sync_error) { - debug(("Sync at sector 0x%x\n", cd->sector_first)); - stats(sync_error); - } - else if (cd->intr_ds & ds_toc_ready) { - /* do something appropriate */ - } - /* couldn't see why this interrupt, maybe due to init */ - else { - outw(dc_normal | READ_AHEAD, r_data_control); - stats(lost_intr); - } - if (cd->background && (cd->adapter_last-cd->adapter_first == cd->max_sectors - || cd->fifo_overflowed)) - mark_bh(CM206_BH); /* issue a stop read command */ - stats(interrupt); + volatile ush fool; + cd->intr_ds = inw(r_data_status); /* resets data_ready, data_error, + crc_error, sync_error, toc_ready + interrupts */ + cd->intr_ls = inw(r_line_status); /* resets overrun bit */ + debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls, + cd->background)); + if (cd->intr_ls & ls_attention) + stats(attention); + /* receive buffer full? */ + if (cd->intr_ls & ls_receive_buffer_full) { + cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */ + cd->intr_ls = inw(r_line_status); /* resets rbf interrupt */ + debug(("receiving #%d: 0x%x\n", cd->ur_w, + cd->ur[cd->ur_w])); + cd->ur_w++; + cd->ur_w %= UR_SIZE; + if (cd->ur_w == cd->ur_r) + debug(("cd->ur overflow!\n")); + if (waitqueue_active(&cd->uart) && cd->background < 2) { + del_timer(&cd->timer); + wake_up_interruptible(&cd->uart); + } + } + /* data ready in fifo? */ + else if (cd->intr_ds & ds_data_ready) { + if (cd->background) + ++cd->adapter_last; + if (waitqueue_active(&cd->data) + && (cd->wait_back || !cd->background)) { + del_timer(&cd->timer); + wake_up_interruptible(&cd->data); + } + stats(data_ready); + } + /* ready to issue a write command? */ + else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) { + outw(dc_normal | (inw(r_data_status) & 0x7f), + r_data_control); + outw(cd->command, r_uart_transmit); + cd->command = 0; + if (!cd->background) + wake_up_interruptible(&cd->uart); + } + /* now treat errors (at least, identify them for debugging) */ + else if (cd->intr_ds & ds_fifo_overflow) { + debug(("Fifo overflow at sectors 0x%x\n", + cd->sector_first)); + fool = inw(r_fifo_output_buffer); /* de-assert the interrupt */ + cd->fifo_overflowed = 1; /* signal one word less should be read */ + stats(fifo_overflow); + } else if (cd->intr_ds & ds_data_error) { + debug(("Data error at sector 0x%x\n", cd->sector_first)); + stats(data_error); + } else if (cd->intr_ds & ds_crc_error) { + debug(("CRC error at sector 0x%x\n", cd->sector_first)); + stats(crc_error); + } else if (cd->intr_ds & ds_sync_error) { + debug(("Sync at sector 0x%x\n", cd->sector_first)); + stats(sync_error); + } else if (cd->intr_ds & ds_toc_ready) { + /* do something appropriate */ + } + /* couldn't see why this interrupt, maybe due to init */ + else { + outw(dc_normal | READ_AHEAD, r_data_control); + stats(lost_intr); + } + if (cd->background + && (cd->adapter_last - cd->adapter_first == cd->max_sectors + || cd->fifo_overflowed)) + mark_bh(CM206_BH); /* issue a stop read command */ + stats(interrupt); } /* we have put the address of the wait queue in who */ void cm206_timeout(unsigned long who) { - cd->timed_out = 1; - debug(("Timing out\n")); - wake_up_interruptible((wait_queue_head_t *)who); + cd->timed_out = 1; + debug(("Timing out\n")); + wake_up_interruptible((wait_queue_head_t *) who); } /* This function returns 1 if a timeout occurred, 0 if an interrupt happened */ -int sleep_or_timeout(wait_queue_head_t *wait, int timeout) +int sleep_or_timeout(wait_queue_head_t * wait, int timeout) { - cd->timed_out=0; - cd->timer.data=(unsigned long) wait; - cd->timer.expires = jiffies + timeout; - add_timer(&cd->timer); - debug(("going to sleep\n")); - interruptible_sleep_on(wait); - del_timer(&cd->timer); - if (cd->timed_out) { - cd->timed_out = 0; - return 1; - } - else return 0; + cd->timed_out = 0; + cd->timer.data = (unsigned long) wait; + cd->timer.expires = jiffies + timeout; + add_timer(&cd->timer); + debug(("going to sleep\n")); + interruptible_sleep_on(wait); + del_timer(&cd->timer); + if (cd->timed_out) { + cd->timed_out = 0; + return 1; + } else + return 0; } -void cm206_delay(int nr_jiffies) +void cm206_delay(int nr_jiffies) { - DECLARE_WAIT_QUEUE_HEAD(wait); - sleep_or_timeout(&wait, nr_jiffies); + DECLARE_WAIT_QUEUE_HEAD(wait); + sleep_or_timeout(&wait, nr_jiffies); } void send_command(int command) { - debug(("Sending 0x%x\n", command)); - if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) { - cd->command = command; - cli(); /* don't interrupt before sleep */ - outw(dc_mask_sync_error | dc_no_stop_on_error | - (inw(r_data_status) & 0x7f), r_data_control); - /* interrupt routine sends command */ - if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) { - debug(("Time out on write-buffer\n")); - stats(write_timeout); - outw(command, r_uart_transmit); - } - debug(("Write commmand delayed\n")); - } - else outw(command, r_uart_transmit); + debug(("Sending 0x%x\n", command)); + if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) { + cd->command = command; + cli(); /* don't interrupt before sleep */ + outw(dc_mask_sync_error | dc_no_stop_on_error | + (inw(r_data_status) & 0x7f), r_data_control); + /* interrupt routine sends command */ + if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) { + debug(("Time out on write-buffer\n")); + stats(write_timeout); + outw(command, r_uart_transmit); + } + debug(("Write commmand delayed\n")); + } else + outw(command, r_uart_transmit); } uch receive_byte(int timeout) { - uch ret; - cli(); - debug(("cli\n")); - ret = cd->ur[cd->ur_r]; - if (cd->ur_r != cd->ur_w) { - sti(); - debug(("returning #%d: 0x%x\n", cd->ur_r, cd->ur[cd->ur_r])); - cd->ur_r++; cd->ur_r %= UR_SIZE; - return ret; - } - else if (sleep_or_timeout(&cd->uart, timeout)) { /* does sti() */ - debug(("Time out on receive-buffer\n")); + uch ret; + cli(); + debug(("cli\n")); + ret = cd->ur[cd->ur_r]; + if (cd->ur_r != cd->ur_w) { + sti(); + debug(("returning #%d: 0x%x\n", cd->ur_r, + cd->ur[cd->ur_r])); + cd->ur_r++; + cd->ur_r %= UR_SIZE; + return ret; + } else if (sleep_or_timeout(&cd->uart, timeout)) { /* does sti() */ + debug(("Time out on receive-buffer\n")); #ifdef STATISTICS - if (timeout==UART_TIMEOUT) stats(receive_timeout) /* no `;'! */ - else stats(dsb_timeout); + if (timeout == UART_TIMEOUT) + stats(receive_timeout) /* no `;'! */ + else + stats(dsb_timeout); #endif - return 0xda; - } - ret = cd->ur[cd->ur_r]; - debug(("slept; returning #%d: 0x%x\n", cd->ur_r, cd->ur[cd->ur_r])); - cd->ur_r++; cd->ur_r %= UR_SIZE; - return ret; + return 0xda; + } + ret = cd->ur[cd->ur_r]; + debug(("slept; returning #%d: 0x%x\n", cd->ur_r, + cd->ur[cd->ur_r])); + cd->ur_r++; + cd->ur_r %= UR_SIZE; + return ret; } inline uch receive_echo(void) { - return receive_byte(UART_TIMEOUT); + return receive_byte(UART_TIMEOUT); } inline uch send_receive(int command) { - send_command(command); - return receive_echo(); + send_command(command); + return receive_echo(); } inline uch wait_dsb(void) { - return receive_byte(DSB_TIMEOUT); + return receive_byte(DSB_TIMEOUT); } int type_0_command(int command, int expect_dsb) { - int e; - clear_ur(); - if (command != (e=send_receive(command))) { - debug(("command 0x%x echoed as 0x%x\n", command, e)); - stats(echo); - return -1; - } - if (expect_dsb) { - cd->dsb = wait_dsb(); /* wait for command to finish */ - } - return 0; -} - -int type_1_command(int command, int bytes, uch * status) /* returns info */ -{ - int i; - if (type_0_command(command,0)) return -1; - for(i=0; idsb = wait_dsb(); /* wait for command to finish */ + } + return 0; +} + +int type_1_command(int command, int bytes, uch * status) +{ /* returns info */ + int i; + if (type_0_command(command, 0)) + return -1; + for (i = 0; i < bytes; i++) + status[i] = send_receive(c_gimme); + return 0; +} /* This function resets the adapter card. We'd better not do this too * often, because it tends to generate `lost interrupts.' */ void reset_cm260(void) { - outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control); - udelay(10); /* 3.3 mu sec minimum */ - outw(dc_normal | READ_AHEAD, r_data_control); + outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control); + udelay(10); /* 3.3 mu sec minimum */ + outw(dc_normal | READ_AHEAD, r_data_control); } /* fsm: frame-sec-min from linear address; one of many */ -void fsm(int lba, uch * fsm) +void fsm(int lba, uch * fsm) { - fsm[0] = lba % 75; - lba /= 75; lba += 2; - fsm[1] = lba % 60; fsm[2] = lba / 60; + fsm[0] = lba % 75; + lba /= 75; + lba += 2; + fsm[1] = lba % 60; + fsm[2] = lba / 60; } -inline int fsm2lba(uch * fsm) +inline int fsm2lba(uch * fsm) { - return fsm[0] + 75*(fsm[1]-2 + 60*fsm[2]); + return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]); } inline int f_s_m2lba(uch f, uch s, uch m) { - return f + 75*(s-2 + 60*m); + return f + 75 * (s - 2 + 60 * m); } -int start_read(int start) +int start_read(int start) { - uch read_sector[4] = {c_read_data, }; - int i, e; + uch read_sector[4] = { c_read_data, }; + int i, e; - fsm(start, &read_sector[1]); - clear_ur(); - for (i=0; i<4; i++) - if (read_sector[i] != (e=send_receive(read_sector[i]))) { - debug(("read_sector: %x echoes %x\n", read_sector[i], e)); - stats(echo); - if (e==0xff) { /* this seems to happen often */ - e = receive_echo(); - debug(("Second try %x\n", e)); - if (e!=read_sector[i]) return -1; - } - } - return 0; + fsm(start, &read_sector[1]); + clear_ur(); + for (i = 0; i < 4; i++) + if (read_sector[i] != (e = send_receive(read_sector[i]))) { + debug(("read_sector: %x echoes %x\n", + read_sector[i], e)); + stats(echo); + if (e == 0xff) { /* this seems to happen often */ + e = receive_echo(); + debug(("Second try %x\n", e)); + if (e != read_sector[i]) + return -1; + } + } + return 0; } int stop_read(void) { - int e; - type_0_command(c_stop,0); - if((e=receive_echo()) != 0xff) { - debug(("c_stop didn't send 0xff, but 0x%x\n", e)); - stats(stop_0xff); - return -1; - } - return 0; -} + int e; + type_0_command(c_stop, 0); + if ((e = receive_echo()) != 0xff) { + debug(("c_stop didn't send 0xff, but 0x%x\n", e)); + stats(stop_0xff); + return -1; + } + return 0; +} /* This function starts to read sectors in adapter memory, the interrupt routine should stop the read. In fact, the bottom_half @@ -605,12 +628,14 @@ int read_background(int start, int reading) { - if (cd->background) return -1; /* can't do twice */ - outw(dc_normal | BACK_AHEAD, r_data_control); - if (!reading && start_read(start)) return -2; - cd->adapter_first = cd->adapter_last = start; - cd->background = 1; /* flag a read is going on */ - return 0; + if (cd->background) + return -1; /* can't do twice */ + outw(dc_normal | BACK_AHEAD, r_data_control); + if (!reading && start_read(start)) + return -2; + cd->adapter_first = cd->adapter_last = start; + cd->background = 1; /* flag a read is going on */ + return 0; } #ifdef USE_INSW @@ -618,12 +643,12 @@ #else /* this routine implements insw(,,). There was a time i had the impression that there would be any difference in error-behaviour. */ -void transport_data(int port, ush * dest, int count) +void transport_data(int port, ush * dest, int count) { - int i; - ush * d; - for (i=0, d=dest; ibackground) { - cd->background=0; - cd->adapter_last = -1; /* invalidate adapter memory */ - stop_read(); - } - cd->fifo_overflowed=0; - reset_cm260(); /* empty fifo etc. */ - if (start_read(start)) return -1; - do { - if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) { - debug(("Read timed out sector 0x%x\n", start)); - stats(read_timeout); - stop_read(); - return -3; - } - tries++; - } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES); - if (tries>1) debug(("Took me some tries\n")) - else if (tries == MAX_TRIES) - debug(("MAX_TRIES tries for read sector\n")); - transport_data(r_fifo_output_buffer, cd->sector, - READ_AHEAD*RAW_SECTOR_SIZE/2); - if (read_background(start+READ_AHEAD,1)) stats(read_background); - cd->sector_first = start; cd->sector_last = start+READ_AHEAD; - stats(read_restarted); - return 0; + int tries = 0; + if (cd->background) { + cd->background = 0; + cd->adapter_last = -1; /* invalidate adapter memory */ + stop_read(); + } + cd->fifo_overflowed = 0; + reset_cm260(); /* empty fifo etc. */ + if (start_read(start)) + return -1; + do { + if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) { + debug(("Read timed out sector 0x%x\n", start)); + stats(read_timeout); + stop_read(); + return -3; + } + tries++; + } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES); + if (tries > 1) + debug(("Took me some tries\n")) + else + if (tries == MAX_TRIES) + debug(("MAX_TRIES tries for read sector\n")); + transport_data(r_fifo_output_buffer, cd->sector, + READ_AHEAD * RAW_SECTOR_SIZE / 2); + if (read_background(start + READ_AHEAD, 1)) + stats(read_background); + cd->sector_first = start; + cd->sector_last = start + READ_AHEAD; + stats(read_restarted); + return 0; } /* The function of bottom-half is to send a stop command to the drive @@ -672,43 +702,46 @@ void cm206_bh(void) { - debug(("bh: %d\n", cd->background)); - switch (cd->background) { - case 1: - stats(bh); - if (!(cd->intr_ls & ls_transmitter_buffer_empty)) { - cd->command = c_stop; - outw(dc_mask_sync_error | dc_no_stop_on_error | - (inw(r_data_status) & 0x7f), r_data_control); - cd->background=2; - break; /* we'd better not time-out here! */ - } - else outw(c_stop, r_uart_transmit); - /* fall into case 2: */ - case 2: - /* the write has been satisfied by interrupt routine */ - cd->background=3; - break; - case 3: - if (cd->ur_r != cd->ur_w) { - if (cd->ur[cd->ur_r] != c_stop) { - debug(("cm206_bh: c_stop echoed 0x%x\n", cd->ur[cd->ur_r])); - stats(echo); - } - cd->ur_r++; cd->ur_r %= UR_SIZE; - } - cd->background++; - break; - case 4: - if (cd->ur_r != cd->ur_w) { - if (cd->ur[cd->ur_r] != 0xff) { - debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r])); - stats(stop_0xff); - } - cd->ur_r++; cd->ur_r %= UR_SIZE; - } - cd->background=0; - } + debug(("bh: %d\n", cd->background)); + switch (cd->background) { + case 1: + stats(bh); + if (!(cd->intr_ls & ls_transmitter_buffer_empty)) { + cd->command = c_stop; + outw(dc_mask_sync_error | dc_no_stop_on_error | + (inw(r_data_status) & 0x7f), r_data_control); + cd->background = 2; + break; /* we'd better not time-out here! */ + } else + outw(c_stop, r_uart_transmit); + /* fall into case 2: */ + case 2: + /* the write has been satisfied by interrupt routine */ + cd->background = 3; + break; + case 3: + if (cd->ur_r != cd->ur_w) { + if (cd->ur[cd->ur_r] != c_stop) { + debug(("cm206_bh: c_stop echoed 0x%x\n", + cd->ur[cd->ur_r])); + stats(echo); + } + cd->ur_r++; + cd->ur_r %= UR_SIZE; + } + cd->background++; + break; + case 4: + if (cd->ur_r != cd->ur_w) { + if (cd->ur[cd->ur_r] != 0xff) { + debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r])); + stats(stop_0xff); + } + cd->ur_r++; + cd->ur_r %= UR_SIZE; + } + cd->background = 0; + } } /* This command clears the dsb_possible_media_change flag, so we must @@ -716,66 +749,67 @@ */ void get_drive_status(void) { - uch status[2]; - type_1_command(c_drive_status, 2, status); /* this might be done faster */ - cd->dsb=status[0]; - cd->cc=status[1]; - cd->media_changed |= - !!(cd->dsb & (dsb_possible_media_change | - dsb_drive_not_ready | dsb_tray_not_closed)); + uch status[2]; + type_1_command(c_drive_status, 2, status); /* this might be done faster */ + cd->dsb = status[0]; + cd->cc = status[1]; + cd->media_changed |= + !!(cd->dsb & (dsb_possible_media_change | + dsb_drive_not_ready | dsb_tray_not_closed)); } void get_disc_status(void) { - if (type_1_command(c_disc_status, 7, cd->disc_status)) { - debug(("get_disc_status: error\n")); - } + if (type_1_command(c_disc_status, 7, cd->disc_status)) { + debug(("get_disc_status: error\n")); + } } /* The new open. The real opening strategy is defined in cdrom.c. */ -static int cm206_open(struct cdrom_device_info * cdi, int purpose) +static int cm206_open(struct cdrom_device_info *cdi, int purpose) { - MOD_INC_USE_COUNT; - if (!cd->openfiles) { /* reset only first time */ - cd->background=0; - reset_cm260(); - cd->adapter_last = -1; /* invalidate adapter memory */ - cd->sector_last = -1; - } - ++cd->openfiles; - stats(open); - return 0; -} - -static void cm206_release(struct cdrom_device_info * cdi) -{ - if (cd->openfiles==1) { - if (cd->background) { - cd->background=0; - stop_read(); - } - cd->sector_last = -1; /* Make our internal buffer invalid */ - FIRST_TRACK = 0; /* No valid disc status */ - } - --cd->openfiles; - MOD_DEC_USE_COUNT; + MOD_INC_USE_COUNT; + if (!cd->openfiles) { /* reset only first time */ + cd->background = 0; + reset_cm260(); + cd->adapter_last = -1; /* invalidate adapter memory */ + cd->sector_last = -1; + } + ++cd->openfiles; + stats(open); + return 0; +} + +static void cm206_release(struct cdrom_device_info *cdi) +{ + if (cd->openfiles == 1) { + if (cd->background) { + cd->background = 0; + stop_read(); + } + cd->sector_last = -1; /* Make our internal buffer invalid */ + FIRST_TRACK = 0; /* No valid disc status */ + } + --cd->openfiles; + MOD_DEC_USE_COUNT; } /* Empty buffer empties $sectors$ sectors of the adapter card buffer, * and then reads a sector in kernel memory. */ -void empty_buffer(int sectors) +void empty_buffer(int sectors) { - while (sectors>=0) { - transport_data(r_fifo_output_buffer, cd->sector + cd->fifo_overflowed, - RAW_SECTOR_SIZE/2 - cd->fifo_overflowed); - --sectors; - ++cd->adapter_first; /* update the current adapter sector */ - cd->fifo_overflowed=0; /* reset overflow bit */ - stats(sector_transferred); - } - cd->sector_first=cd->adapter_first-1; - cd->sector_last=cd->adapter_first; /* update the buffer sector */ + while (sectors >= 0) { + transport_data(r_fifo_output_buffer, + cd->sector + cd->fifo_overflowed, + RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed); + --sectors; + ++cd->adapter_first; /* update the current adapter sector */ + cd->fifo_overflowed = 0; /* reset overflow bit */ + stats(sector_transferred); + } + cd->sector_first = cd->adapter_first - 1; + cd->sector_last = cd->adapter_first; /* update the buffer sector */ } /* try_adapter. This function determines if the requested sector is @@ -783,29 +817,27 @@ success */ int try_adapter(int sector) { - if (cd->adapter_first <= sector && sector < cd->adapter_last) { - /* sector is in adapter memory */ - empty_buffer(sector - cd->adapter_first); - return 0; - } - else if (cd->background==1 && cd->adapter_first <= sector - && sector < cd->adapter_first+cd->max_sectors) { - /* a read is going on, we can wait for it */ - cd->wait_back=1; - while (sector >= cd->adapter_last) { - if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) { - debug(("Timed out during background wait: %d %d %d %d\n", sector, - cd->adapter_last, cd->adapter_first, cd->background)); - stats(back_read_timeout); - cd->wait_back=0; - return -1; - } - } - cd->wait_back=0; - empty_buffer(sector - cd->adapter_first); - return 0; - } - else return -2; + if (cd->adapter_first <= sector && sector < cd->adapter_last) { + /* sector is in adapter memory */ + empty_buffer(sector - cd->adapter_first); + return 0; + } else if (cd->background == 1 && cd->adapter_first <= sector + && sector < cd->adapter_first + cd->max_sectors) { + /* a read is going on, we can wait for it */ + cd->wait_back = 1; + while (sector >= cd->adapter_last) { + if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) { + debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background)); + stats(back_read_timeout); + cd->wait_back = 0; + return -1; + } + } + cd->wait_back = 0; + empty_buffer(sector - cd->adapter_first); + return 0; + } else + return -2; } /* This is not a very smart implementation. We could optimize for @@ -813,45 +845,50 @@ bring down the processor load. */ static void do_cm206_request(request_queue_t * q) { - long int i, cd_sec_no; - int quarter, error; - uch * source, * dest; - - while(1) { /* repeat until all requests have been satisfied */ - INIT_REQUEST; - if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE) - return; - if (CURRENT->cmd != READ) { - debug(("Non-read command %d on cdrom\n", CURRENT->cmd)); - end_request(0); - continue; - } - spin_unlock_irq(&io_request_lock); - error=0; - for (i=0; inr_sectors; i++) { - int e1, e2; - cd_sec_no = (CURRENT->sector+i)/BLOCKS_ISO; /* 4 times 512 bytes */ - quarter = (CURRENT->sector+i) % BLOCKS_ISO; - dest = CURRENT->buffer + i*LINUX_BLOCK_SIZE; - /* is already in buffer memory? */ - if (cd->sector_first <= cd_sec_no && cd_sec_no < cd->sector_last) { - source = ((uch *) cd->sector) + 16 + quarter*LINUX_BLOCK_SIZE - + (cd_sec_no-cd->sector_first)*RAW_SECTOR_SIZE; - memcpy(dest, source, LINUX_BLOCK_SIZE); - } - else if (!(e1=try_adapter(cd_sec_no)) || - !(e2=read_sector(cd_sec_no))) { - source = ((uch *) cd->sector)+16+quarter*LINUX_BLOCK_SIZE; - memcpy(dest, source, LINUX_BLOCK_SIZE); - } - else { - error=1; - debug(("cm206_request: %d %d\n", e1, e2)); - } - } - spin_lock_irq(&io_request_lock); - end_request(!error); - } + long int i, cd_sec_no; + int quarter, error; + uch *source, *dest; + + while (1) { /* repeat until all requests have been satisfied */ + INIT_REQUEST; + if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE) + return; + if (CURRENT->cmd != READ) { + debug(("Non-read command %d on cdrom\n", + CURRENT->cmd)); + end_request(0); + continue; + } + spin_unlock_irq(&io_request_lock); + error = 0; + for (i = 0; i < CURRENT->nr_sectors; i++) { + int e1, e2; + cd_sec_no = (CURRENT->sector + i) / BLOCKS_ISO; /* 4 times 512 bytes */ + quarter = (CURRENT->sector + i) % BLOCKS_ISO; + dest = CURRENT->buffer + i * LINUX_BLOCK_SIZE; + /* is already in buffer memory? */ + if (cd->sector_first <= cd_sec_no + && cd_sec_no < cd->sector_last) { + source = + ((uch *) cd->sector) + 16 + + quarter * LINUX_BLOCK_SIZE + + (cd_sec_no - + cd->sector_first) * RAW_SECTOR_SIZE; + memcpy(dest, source, LINUX_BLOCK_SIZE); + } else if (!(e1 = try_adapter(cd_sec_no)) || + !(e2 = read_sector(cd_sec_no))) { + source = + ((uch *) cd->sector) + 16 + + quarter * LINUX_BLOCK_SIZE; + memcpy(dest, source, LINUX_BLOCK_SIZE); + } else { + error = 1; + debug(("cm206_request: %d %d\n", e1, e2)); + } + } + spin_lock_irq(&io_request_lock); + end_request(!error); + } } /* Audio support. I've tried very hard, but the cm206 drive doesn't @@ -870,24 +907,27 @@ /* seek seeks to address lba. It does wait to arrive there. */ void seek(int lba) { - int i; - uch seek_command[4]={c_seek, }; - - fsm(lba, &seek_command[1]); - for (i=0; i<4; i++) type_0_command(seek_command[i], 0); - cd->dsb = wait_dsb(); + int i; + uch seek_command[4] = { c_seek, }; + + fsm(lba, &seek_command[1]); + for (i = 0; i < 4; i++) + type_0_command(seek_command[i], 0); + cd->dsb = wait_dsb(); } -uch bcdbin(unsigned char bcd) /* stolen from mcd.c! */ -{ - return (bcd >> 4)*10 + (bcd & 0xf); -} +uch bcdbin(unsigned char bcd) +{ /* stolen from mcd.c! */ + return (bcd >> 4) * 10 + (bcd & 0xf); +} -inline uch normalize_track(uch track) +inline uch normalize_track(uch track) { - if (track<1) return 1; - if (track>LAST_TRACK) return LAST_TRACK+1; - return track; + if (track < 1) + return 1; + if (track > LAST_TRACK) + return LAST_TRACK + 1; + return track; } /* This function does a binary search for track start. It records all @@ -896,150 +936,175 @@ */ int get_toc_lba(uch track) { - int max=74*60*75-150, min=fsm2lba(cd->toc[1].fsm); - int i, lba, l, old_lba=0; - uch * q = cd->q; - uch ct; /* current track */ - int binary=0; - const int skip = 3*60*75; /* 3 minutes */ - - for (i=track; i>0; i--) if (cd->toc[i].track) { - min = fsm2lba(cd->toc[i].fsm); - break; - } - lba = min + skip; - do { - seek(lba); - type_1_command(c_read_current_q, 10, q); - ct = normalize_track(q[1]); - if (!cd->toc[ct].track) { - l = q[9]-bcdbin(q[5]) + 75*(q[8]-bcdbin(q[4])-2 + - 60*(q[7]-bcdbin(q[3]))); - cd->toc[ct].track=q[1]; /* lead out still 0xaa */ - fsm(l, cd->toc[ct].fsm); - cd->toc[ct].q0 = q[0]; /* contains adr and ctrl info */ - if (ct==track) return l; - } - old_lba=lba; - if (binary) { - if (ct < track) min = lba; else max = lba; - lba = (min+max)/2; - } else { - if(ct < track) lba += skip; - else { - binary=1; - max = lba; min = lba - skip; - lba = (min+max)/2; - } - } - } while (lba!=old_lba); - return lba; + int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm); + int i, lba, l, old_lba = 0; + uch *q = cd->q; + uch ct; /* current track */ + int binary = 0; + const int skip = 3 * 60 * 75; /* 3 minutes */ + + for (i = track; i > 0; i--) + if (cd->toc[i].track) { + min = fsm2lba(cd->toc[i].fsm); + break; + } + lba = min + skip; + do { + seek(lba); + type_1_command(c_read_current_q, 10, q); + ct = normalize_track(q[1]); + if (!cd->toc[ct].track) { + l = q[9] - bcdbin(q[5]) + 75 * (q[8] - + bcdbin(q[4]) - 2 + + 60 * (q[7] - + bcdbin(q + [3]))); + cd->toc[ct].track = q[1]; /* lead out still 0xaa */ + fsm(l, cd->toc[ct].fsm); + cd->toc[ct].q0 = q[0]; /* contains adr and ctrl info */ + if (ct == track) + return l; + } + old_lba = lba; + if (binary) { + if (ct < track) + min = lba; + else + max = lba; + lba = (min + max) / 2; + } else { + if (ct < track) + lba += skip; + else { + binary = 1; + max = lba; + min = lba - skip; + lba = (min + max) / 2; + } + } + } while (lba != old_lba); + return lba; +} + +void update_toc_entry(uch track) +{ + track = normalize_track(track); + if (!cd->toc[track].track) + get_toc_lba(track); } -void update_toc_entry(uch track) +/* return 0 upon success */ +int read_toc_header(struct cdrom_tochdr *hp) { - track = normalize_track(track); - if (!cd->toc[track].track) get_toc_lba(track); + if (!FIRST_TRACK) + get_disc_status(); + if (hp) { + int i; + hp->cdth_trk0 = FIRST_TRACK; + hp->cdth_trk1 = LAST_TRACK; + /* fill in first track position */ + for (i = 0; i < 3; i++) + cd->toc[1].fsm[i] = cd->disc_status[3 + i]; + update_toc_entry(LAST_TRACK + 1); /* find most entries */ + return 0; + } + return -1; } -/* return 0 upon success */ -int read_toc_header(struct cdrom_tochdr * hp) +void play_from_to_msf(struct cdrom_msf *msfp) { - if (!FIRST_TRACK) get_disc_status(); - if (hp) { - int i; - hp->cdth_trk0 = FIRST_TRACK; - hp->cdth_trk1 = LAST_TRACK; - /* fill in first track position */ - for (i=0; i<3; i++) cd->toc[1].fsm[i] = cd->disc_status[3+i]; - update_toc_entry(LAST_TRACK+1); /* find most entries */ - return 0; - } - return -1; -} - -void play_from_to_msf(struct cdrom_msf* msfp) -{ - uch play_command[] = {c_play, - msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0, - msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2, 2}; - int i; - for (i=0; i<9; i++) type_0_command(play_command[i], 0); - for (i=0; i<3; i++) - PLAY_TO.fsm[i] = play_command[i+4]; - PLAY_TO.track = 0; /* say no track end */ - cd->dsb = wait_dsb(); -} + uch play_command[] = { c_play, + msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0, + msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2, + 2 + }; + int i; + for (i = 0; i < 9; i++) + type_0_command(play_command[i], 0); + for (i = 0; i < 3; i++) + PLAY_TO.fsm[i] = play_command[i + 4]; + PLAY_TO.track = 0; /* say no track end */ + cd->dsb = wait_dsb(); +} void play_from_to_track(int from, int to) { - uch play_command[8] = {c_play, }; - int i; + uch play_command[8] = { c_play, }; + int i; - if (from==0) { /* continue paused play */ - for (i=0; i<3; i++) { - play_command[i+1] = cd->audio_status[i+2]; - play_command[i+4] = PLAY_TO.fsm[i]; - } - } else { - update_toc_entry(from); update_toc_entry(to+1); - for (i=0; i<3; i++) { - play_command[i+1] = cd->toc[from].fsm[i]; - PLAY_TO.fsm[i] = play_command[i+4] = cd->toc[to+1].fsm[i]; - } - PLAY_TO.track = to; - } - for (i=0; i<7; i++) type_0_command(play_command[i],0); - for (i=0; i<2; i++) type_0_command(0x2, 0); /* volume */ - cd->dsb = wait_dsb(); -} - -int get_current_q(struct cdrom_subchnl * qp) -{ - int i; - uch * q = cd->q; - if (type_1_command(c_read_current_q, 10, q)) return 0; + if (from == 0) { /* continue paused play */ + for (i = 0; i < 3; i++) { + play_command[i + 1] = cd->audio_status[i + 2]; + play_command[i + 4] = PLAY_TO.fsm[i]; + } + } else { + update_toc_entry(from); + update_toc_entry(to + 1); + for (i = 0; i < 3; i++) { + play_command[i + 1] = cd->toc[from].fsm[i]; + PLAY_TO.fsm[i] = play_command[i + 4] = + cd->toc[to + 1].fsm[i]; + } + PLAY_TO.track = to; + } + for (i = 0; i < 7; i++) + type_0_command(play_command[i], 0); + for (i = 0; i < 2; i++) + type_0_command(0x2, 0); /* volume */ + cd->dsb = wait_dsb(); +} + +int get_current_q(struct cdrom_subchnl *qp) +{ + int i; + uch *q = cd->q; + if (type_1_command(c_read_current_q, 10, q)) + return 0; /* q[0] = bcdbin(q[0]); Don't think so! */ - for (i=2; i<6; i++) q[i]=bcdbin(q[i]); - qp->cdsc_adr = q[0] & 0xf; qp->cdsc_ctrl = q[0] >> 4; /* from mcd.c */ - qp->cdsc_trk = q[1]; qp->cdsc_ind = q[2]; - if (qp->cdsc_format == CDROM_MSF) { - qp->cdsc_reladdr.msf.minute = q[3]; - qp->cdsc_reladdr.msf.second = q[4]; - qp->cdsc_reladdr.msf.frame = q[5]; - qp->cdsc_absaddr.msf.minute = q[7]; - qp->cdsc_absaddr.msf.second = q[8]; - qp->cdsc_absaddr.msf.frame = q[9]; - } else { - qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]); - qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]); - } - get_drive_status(); - if (cd->dsb & dsb_play_in_progress) - qp->cdsc_audiostatus = CDROM_AUDIO_PLAY ; - else if (PAUSED) - qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED; - else qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS; - return 0; + for (i = 2; i < 6; i++) + q[i] = bcdbin(q[i]); + qp->cdsc_adr = q[0] & 0xf; + qp->cdsc_ctrl = q[0] >> 4; /* from mcd.c */ + qp->cdsc_trk = q[1]; + qp->cdsc_ind = q[2]; + if (qp->cdsc_format == CDROM_MSF) { + qp->cdsc_reladdr.msf.minute = q[3]; + qp->cdsc_reladdr.msf.second = q[4]; + qp->cdsc_reladdr.msf.frame = q[5]; + qp->cdsc_absaddr.msf.minute = q[7]; + qp->cdsc_absaddr.msf.second = q[8]; + qp->cdsc_absaddr.msf.frame = q[9]; + } else { + qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]); + qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]); + } + get_drive_status(); + if (cd->dsb & dsb_play_in_progress) + qp->cdsc_audiostatus = CDROM_AUDIO_PLAY; + else if (PAUSED) + qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED; + else + qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS; + return 0; } void invalidate_toc(void) { - memset(cd->toc, 0, sizeof(cd->toc)); - memset(cd->disc_status, 0, sizeof(cd->disc_status)); + memset(cd->toc, 0, sizeof(cd->toc)); + memset(cd->disc_status, 0, sizeof(cd->disc_status)); } /* cdrom.c guarantees that cdte_format == CDROM_MSF */ -void get_toc_entry(struct cdrom_tocentry * ep) +void get_toc_entry(struct cdrom_tocentry *ep) { - uch track = normalize_track(ep->cdte_track); - update_toc_entry(track); - ep->cdte_addr.msf.frame = cd->toc[track].fsm[0]; - ep->cdte_addr.msf.second = cd->toc[track].fsm[1]; - ep->cdte_addr.msf.minute = cd->toc[track].fsm[2]; - ep->cdte_adr = cd->toc[track].q0 & 0xf; - ep->cdte_ctrl = cd->toc[track].q0 >> 4; - ep->cdte_datamode=0; + uch track = normalize_track(ep->cdte_track); + update_toc_entry(track); + ep->cdte_addr.msf.frame = cd->toc[track].fsm[0]; + ep->cdte_addr.msf.second = cd->toc[track].fsm[1]; + ep->cdte_addr.msf.minute = cd->toc[track].fsm[2]; + ep->cdte_adr = cd->toc[track].q0 & 0xf; + ep->cdte_ctrl = cd->toc[track].q0 >> 4; + ep->cdte_datamode = 0; } /* Audio ioctl. Ioctl commands connected to audio are in such an @@ -1047,244 +1112,262 @@ * upon success. Memory checking has been done by cdrom_ioctl(), the * calling function, as well as LBA/MSF sanitization. */ -int cm206_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, - void * arg) +int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, + void *arg) { - switch (cmd) { - case CDROMREADTOCHDR: - return read_toc_header((struct cdrom_tochdr *) arg); - case CDROMREADTOCENTRY: - get_toc_entry((struct cdrom_tocentry *) arg); - return 0; - case CDROMPLAYMSF: - play_from_to_msf((struct cdrom_msf *) arg); - return 0; - case CDROMPLAYTRKIND: /* admittedly, not particularly beautiful */ - play_from_to_track(((struct cdrom_ti *)arg)->cdti_trk0, - ((struct cdrom_ti *)arg)->cdti_trk1); - return 0; - case CDROMSTOP: - PAUSED=0; - if (cd->dsb & dsb_play_in_progress) return type_0_command(c_stop, 1); - else return 0; - case CDROMPAUSE: - get_drive_status(); - if (cd->dsb & dsb_play_in_progress) { - type_0_command(c_stop, 1); - type_1_command(c_audio_status, 5, cd->audio_status); - PAUSED=1; /* say we're paused */ - } - return 0; - case CDROMRESUME: - if (PAUSED) play_from_to_track(0,0); - PAUSED=0; - return 0; - case CDROMSTART: - case CDROMVOLCTRL: - return 0; - case CDROMSUBCHNL: - return get_current_q((struct cdrom_subchnl *)arg); - default: - return -EINVAL; - } + switch (cmd) { + case CDROMREADTOCHDR: + return read_toc_header((struct cdrom_tochdr *) arg); + case CDROMREADTOCENTRY: + get_toc_entry((struct cdrom_tocentry *) arg); + return 0; + case CDROMPLAYMSF: + play_from_to_msf((struct cdrom_msf *) arg); + return 0; + case CDROMPLAYTRKIND: /* admittedly, not particularly beautiful */ + play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0, + ((struct cdrom_ti *) arg)->cdti_trk1); + return 0; + case CDROMSTOP: + PAUSED = 0; + if (cd->dsb & dsb_play_in_progress) + return type_0_command(c_stop, 1); + else + return 0; + case CDROMPAUSE: + get_drive_status(); + if (cd->dsb & dsb_play_in_progress) { + type_0_command(c_stop, 1); + type_1_command(c_audio_status, 5, + cd->audio_status); + PAUSED = 1; /* say we're paused */ + } + return 0; + case CDROMRESUME: + if (PAUSED) + play_from_to_track(0, 0); + PAUSED = 0; + return 0; + case CDROMSTART: + case CDROMVOLCTRL: + return 0; + case CDROMSUBCHNL: + return get_current_q((struct cdrom_subchnl *) arg); + default: + return -EINVAL; + } } /* Ioctl. These ioctls are specific to the cm206 driver. I have made some driver statistics accessible through ioctl calls. */ -static int cm206_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, +static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg) { - switch (cmd) { + switch (cmd) { #ifdef STATISTICS - case CM206CTL_GET_STAT: - if (arg >= NR_STATS) return -EINVAL; - else return cd->stats[arg]; - case CM206CTL_GET_LAST_STAT: - if (arg >= NR_STATS) return -EINVAL; - else return cd->last_stat[arg]; -#endif - default: - debug(("Unknown ioctl call 0x%x\n", cmd)); - return -EINVAL; - } -} - -int cm206_media_changed(struct cdrom_device_info * cdi, int disc_nr) -{ - if (cd != NULL) { - int r; - get_drive_status(); /* ensure cd->media_changed OK */ - r = cd->media_changed; - cd->media_changed = 0; /* clear bit */ - return r; - } - else return -EIO; + case CM206CTL_GET_STAT: + if (arg >= NR_STATS) + return -EINVAL; + else + return cd->stats[arg]; + case CM206CTL_GET_LAST_STAT: + if (arg >= NR_STATS) + return -EINVAL; + else + return cd->last_stat[arg]; +#endif + default: + debug(("Unknown ioctl call 0x%x\n", cmd)); + return -EINVAL; + } +} + +int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr) +{ + if (cd != NULL) { + int r; + get_drive_status(); /* ensure cd->media_changed OK */ + r = cd->media_changed; + cd->media_changed = 0; /* clear bit */ + return r; + } else + return -EIO; } /* The new generic cdrom support. Routines should be concise, most of the logic should be in cdrom.c */ /* returns number of times device is in use */ -int cm206_open_files(struct cdrom_device_info * cdi) +int cm206_open_files(struct cdrom_device_info *cdi) { - if (cd) return cd->openfiles; - return -1; + if (cd) + return cd->openfiles; + return -1; } /* controls tray movement */ -int cm206_tray_move(struct cdrom_device_info * cdi, int position) +int cm206_tray_move(struct cdrom_device_info *cdi, int position) { - if (position) { /* 1: eject */ - type_0_command(c_open_tray,1); - invalidate_toc(); - } - else type_0_command(c_close_tray, 1); /* 0: close */ - return 0; + if (position) { /* 1: eject */ + type_0_command(c_open_tray, 1); + invalidate_toc(); + } else + type_0_command(c_close_tray, 1); /* 0: close */ + return 0; } /* gives current state of the drive */ -int cm206_drive_status(struct cdrom_device_info * cdi, int slot_nr) +int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr) { - get_drive_status(); - if (cd->dsb & dsb_tray_not_closed) return CDS_TRAY_OPEN; - if (!(cd->dsb & dsb_disc_present)) return CDS_NO_DISC; - if (cd->dsb & dsb_drive_not_ready) return CDS_DRIVE_NOT_READY; - return CDS_DISC_OK; + get_drive_status(); + if (cd->dsb & dsb_tray_not_closed) + return CDS_TRAY_OPEN; + if (!(cd->dsb & dsb_disc_present)) + return CDS_NO_DISC; + if (cd->dsb & dsb_drive_not_ready) + return CDS_DRIVE_NOT_READY; + return CDS_DISC_OK; } - + /* locks or unlocks door lock==1: lock; return 0 upon success */ -int cm206_lock_door(struct cdrom_device_info * cdi, int lock) +int cm206_lock_door(struct cdrom_device_info *cdi, int lock) { - uch command = (lock) ? c_lock_tray : c_unlock_tray; - type_0_command(command, 1); /* wait and get dsb */ - /* the logic calculates the success, 0 means successful */ - return lock ^ ((cd->dsb & dsb_tray_locked) != 0); + uch command = (lock) ? c_lock_tray : c_unlock_tray; + type_0_command(command, 1); /* wait and get dsb */ + /* the logic calculates the success, 0 means successful */ + return lock ^ ((cd->dsb & dsb_tray_locked) != 0); } - + /* Although a session start should be in LBA format, we return it in MSF format because it is slightly easier, and the new generic ioctl will take care of the necessary conversion. */ -int cm206_get_last_session(struct cdrom_device_info * cdi, - struct cdrom_multisession * mssp) +int cm206_get_last_session(struct cdrom_device_info *cdi, + struct cdrom_multisession *mssp) { - if (!FIRST_TRACK) get_disc_status(); - if (mssp != NULL) { - if (DISC_STATUS & cds_multi_session) { /* multi-session */ - mssp->addr.msf.frame = cd->disc_status[3]; - mssp->addr.msf.second = cd->disc_status[4]; - mssp->addr.msf.minute = cd->disc_status[5]; - mssp->addr_format = CDROM_MSF; - mssp->xa_flag = 1; - } else { - mssp->xa_flag = 0; - } - return 1; - } - return 0; -} - -int cm206_get_upc(struct cdrom_device_info * cdi, struct cdrom_mcn * mcn) -{ - uch upc[10]; - char * ret = mcn->medium_catalog_number; - int i; - - if (type_1_command(c_read_upc, 10, upc)) return -EIO; - for (i=0; i<13; i++) { - int w=i/2+1, r=i%2; - if (r) ret[i] = 0x30 | (upc[w] & 0x0f); - else ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f); - } - ret[13] = '\0'; - return 0; -} - -int cm206_reset(struct cdrom_device_info * cdi) -{ - stop_read(); - reset_cm260(); - outw(dc_normal | dc_break | READ_AHEAD, r_data_control); - mdelay(1); /* 750 musec minimum */ - outw(dc_normal | READ_AHEAD, r_data_control); - cd->sector_last = -1; /* flag no data buffered */ - cd->adapter_last = -1; - invalidate_toc(); - return 0; -} - -int cm206_select_speed(struct cdrom_device_info * cdi, int speed) -{ - int r; - switch (speed) { - case 0: - r = type_0_command(c_auto_mode, 1); - break; - case 1: - r = type_0_command(c_force_1x, 1); - break; - case 2: - r = type_0_command(c_force_2x, 1); - break; - default: - return -1; - } - if (r<0) return r; - else return 1; + if (!FIRST_TRACK) + get_disc_status(); + if (mssp != NULL) { + if (DISC_STATUS & cds_multi_session) { /* multi-session */ + mssp->addr.msf.frame = cd->disc_status[3]; + mssp->addr.msf.second = cd->disc_status[4]; + mssp->addr.msf.minute = cd->disc_status[5]; + mssp->addr_format = CDROM_MSF; + mssp->xa_flag = 1; + } else { + mssp->xa_flag = 0; + } + return 1; + } + return 0; +} + +int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) +{ + uch upc[10]; + char *ret = mcn->medium_catalog_number; + int i; + + if (type_1_command(c_read_upc, 10, upc)) + return -EIO; + for (i = 0; i < 13; i++) { + int w = i / 2 + 1, r = i % 2; + if (r) + ret[i] = 0x30 | (upc[w] & 0x0f); + else + ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f); + } + ret[13] = '\0'; + return 0; +} + +int cm206_reset(struct cdrom_device_info *cdi) +{ + stop_read(); + reset_cm260(); + outw(dc_normal | dc_break | READ_AHEAD, r_data_control); + mdelay(1); /* 750 musec minimum */ + outw(dc_normal | READ_AHEAD, r_data_control); + cd->sector_last = -1; /* flag no data buffered */ + cd->adapter_last = -1; + invalidate_toc(); + return 0; +} + +int cm206_select_speed(struct cdrom_device_info *cdi, int speed) +{ + int r; + switch (speed) { + case 0: + r = type_0_command(c_auto_mode, 1); + break; + case 1: + r = type_0_command(c_force_1x, 1); + break; + case 2: + r = type_0_command(c_force_2x, 1); + break; + default: + return -1; + } + if (r < 0) + return r; + else + return 1; } static struct cdrom_device_ops cm206_dops = { - open: cm206_open, - release: cm206_release, - drive_status: cm206_drive_status, - media_changed: cm206_media_changed, - tray_move: cm206_tray_move, - lock_door: cm206_lock_door, - select_speed: cm206_select_speed, - get_last_session: cm206_get_last_session, - get_mcn: cm206_get_upc, - reset: cm206_reset, - audio_ioctl: cm206_audio_ioctl, - dev_ioctl: cm206_ioctl, - capability: CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | - CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | - CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | - CDC_IOCTLS | CDC_DRIVE_STATUS, - n_minors: 1, + open:cm206_open, + release:cm206_release, + drive_status:cm206_drive_status, + media_changed:cm206_media_changed, + tray_move:cm206_tray_move, + lock_door:cm206_lock_door, + select_speed:cm206_select_speed, + get_last_session:cm206_get_last_session, + get_mcn:cm206_get_upc, + reset:cm206_reset, + audio_ioctl:cm206_audio_ioctl, + dev_ioctl:cm206_ioctl, + capability:CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | + CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | + CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | + CDC_IOCTLS | CDC_DRIVE_STATUS, + n_minors:1, }; static struct cdrom_device_info cm206_info = { - ops: &cm206_dops, - speed: 2, - capacity: 1, - name: "cm206", + ops:&cm206_dops, + speed:2, + capacity:1, + name:"cm206", }; /* This routine gets called during initialization if things go wrong, * can be used in cleanup_module as well. */ static void cleanup(int level) { - switch (level) { - case 4: - if (unregister_cdrom(&cm206_info)) { - printk("Can't unregister cdrom cm206\n"); - return; - } - if (devfs_unregister_blkdev(MAJOR_NR, "cm206")) { - printk("Can't unregister major cm206\n"); - return; - } - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - case 3: - free_irq(cm206_irq, NULL); - case 2: - case 1: - kfree(cd); - release_region(cm206_base, 16); - default:; - } + switch (level) { + case 4: + if (unregister_cdrom(&cm206_info)) { + printk("Can't unregister cdrom cm206\n"); + return; + } + if (devfs_unregister_blkdev(MAJOR_NR, "cm206")) { + printk("Can't unregister major cm206\n"); + return; + } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + case 3: + free_irq(cm206_irq, NULL); + case 2: + case 1: + kfree(cd); + release_region(cm206_base, 16); + default:; + } } /* This function probes for the adapter card. It returns the base @@ -1299,117 +1382,129 @@ */ int __init probe_base_port(int base) { - int b=0x300, e=0x370; /* this is the range of start addresses */ - volatile int fool, i; + int b = 0x300, e = 0x370; /* this is the range of start addresses */ + volatile int fool, i; - if (base) b=e=base; - for (base=b; base<=e; base += 0x10) { - if (check_region(base, 0x10)) continue; - for (i=0; i<3; i++) - fool = inw(base+2); /* empty possibly uart_receive_buffer */ - if((inw(base+6) & 0xffef) != 0x0001 || /* line_status */ - (inw(base) & 0xad00) != 0) /* data status */ - continue; - return(base); - } - return 0; + if (base) + b = e = base; + for (base = b; base <= e; base += 0x10) { + if (check_region(base, 0x10)) + continue; + for (i = 0; i < 3; i++) + fool = inw(base + 2); /* empty possibly uart_receive_buffer */ + if ((inw(base + 6) & 0xffef) != 0x0001 || /* line_status */ + (inw(base) & 0xad00) != 0) /* data status */ + continue; + return (base); + } + return 0; } #if !defined(MODULE) || defined(AUTO_PROBE_MODULE) /* Probe for irq# nr. If nr==0, probe for all possible irq's. */ -int __init probe_irq(int nr){ - int irqs, irq; - outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */ - sti(); - irqs = probe_irq_on(); - reset_cm260(); /* causes interrupt */ - udelay(100); /* wait for it */ - irq = probe_irq_off(irqs); - outw(dc_normal | READ_AHEAD, r_data_control); /* services interrupt */ - if (nr && irq!=nr && irq>0) return 0; /* wrong interrupt happened */ - else return irq; +int __init probe_irq(int nr) +{ + int irqs, irq; + outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */ + sti(); + irqs = probe_irq_on(); + reset_cm260(); /* causes interrupt */ + udelay(100); /* wait for it */ + irq = probe_irq_off(irqs); + outw(dc_normal | READ_AHEAD, r_data_control); /* services interrupt */ + if (nr && irq != nr && irq > 0) + return 0; /* wrong interrupt happened */ + else + return irq; } #endif int __init cm206_init(void) { - uch e=0; - long int size=sizeof(struct cm206_struct); + uch e = 0; + long int size = sizeof(struct cm206_struct); - printk(KERN_INFO "cm206 cdrom driver " REVISION); - cm206_base = probe_base_port(auto_probe ? 0 : cm206_base); - if (!cm206_base) { - printk(" can't find adapter!\n"); - return -EIO; - } - printk(" adapter at 0x%x", cm206_base); - request_region(cm206_base, 16, "cm206"); - cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL); - if (!cd) return -EIO; - /* Now we have found the adaptor card, try to reset it. As we have - * found out earlier, this process generates an interrupt as well, - * so we might just exploit that fact for irq probing! */ + printk(KERN_INFO "cm206 cdrom driver " REVISION); + cm206_base = probe_base_port(auto_probe ? 0 : cm206_base); + if (!cm206_base) { + printk(" can't find adapter!\n"); + return -EIO; + } + printk(" adapter at 0x%x", cm206_base); + request_region(cm206_base, 16, "cm206"); + cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL); + if (!cd) + return -EIO; + /* Now we have found the adaptor card, try to reset it. As we have + * found out earlier, this process generates an interrupt as well, + * so we might just exploit that fact for irq probing! */ #if !defined(MODULE) || defined(AUTO_PROBE_MODULE) - cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq); - if (cm206_irq<=0) { - printk("can't find IRQ!\n"); - cleanup(1); - return -EIO; - } - else printk(" IRQ %d found\n", cm206_irq); + cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq); + if (cm206_irq <= 0) { + printk("can't find IRQ!\n"); + cleanup(1); + return -EIO; + } else + printk(" IRQ %d found\n", cm206_irq); #else - cli(); - reset_cm260(); - /* Now, the problem here is that reset_cm260 can generate an - interrupt. It seems that this can cause a kernel oops some time - later. So we wait a while and `service' this interrupt. */ - mdelay(1); - outw(dc_normal | READ_AHEAD, r_data_control); - sti(); - printk(" using IRQ %d\n", cm206_irq); + cli(); + reset_cm260(); + /* Now, the problem here is that reset_cm260 can generate an + interrupt. It seems that this can cause a kernel oops some time + later. So we wait a while and `service' this interrupt. */ + mdelay(1); + outw(dc_normal | READ_AHEAD, r_data_control); + sti(); + printk(" using IRQ %d\n", cm206_irq); #endif - if (send_receive_polled(c_drive_configuration) != c_drive_configuration) - { - printk(KERN_INFO " drive not there\n"); - cleanup(1); - return -EIO; - } - e = send_receive_polled(c_gimme); - printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code); - if (e & dcf_transfer_rate) printk(" double"); - else printk(" single"); - printk(" speed drive"); - if (e & dcf_motorized_tray) printk(", motorized tray"); - if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) { - printk("\nUnable to reserve IRQ---aborted\n"); - cleanup(2); - return -EIO; - } - printk(".\n"); - if (devfs_register_blkdev(MAJOR_NR, "cm206", &cdrom_fops) != 0) { - printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR); - cleanup(3); - return -EIO; - } - cm206_info.dev = MKDEV(MAJOR_NR,0); - if (register_cdrom(&cm206_info) != 0) { - printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR); - cleanup(3); - return -EIO; - } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); - blksize_size[MAJOR_NR] = cm206_blocksizes; - read_ahead[MAJOR_NR] = 16; /* reads ahead what? */ - init_bh(CM206_BH, cm206_bh); - - memset(cd, 0, sizeof(*cd)); /* give'm some reasonable value */ - cd->sector_last = -1; /* flag no data buffered */ - cd->adapter_last = -1; - cd->timer.function = cm206_timeout; - cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97; - printk(KERN_INFO "%d kB adapter memory available, " - " %ld bytes kernel memory used.\n", cd->max_sectors*2, size); - return 0; + if (send_receive_polled(c_drive_configuration) != + c_drive_configuration) { + printk(KERN_INFO " drive not there\n"); + cleanup(1); + return -EIO; + } + e = send_receive_polled(c_gimme); + printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code); + if (e & dcf_transfer_rate) + printk(" double"); + else + printk(" single"); + printk(" speed drive"); + if (e & dcf_motorized_tray) + printk(", motorized tray"); + if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) { + printk("\nUnable to reserve IRQ---aborted\n"); + cleanup(2); + return -EIO; + } + printk(".\n"); + if (devfs_register_blkdev(MAJOR_NR, "cm206", &cdrom_fops) != 0) { + printk(KERN_INFO "Cannot register for major %d!\n", + MAJOR_NR); + cleanup(3); + return -EIO; + } + cm206_info.dev = MKDEV(MAJOR_NR, 0); + if (register_cdrom(&cm206_info) != 0) { + printk(KERN_INFO "Cannot register for cdrom %d!\n", + MAJOR_NR); + cleanup(3); + return -EIO; + } + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + blksize_size[MAJOR_NR] = cm206_blocksizes; + read_ahead[MAJOR_NR] = 16; /* reads ahead what? */ + init_bh(CM206_BH, cm206_bh); + + memset(cd, 0, sizeof(*cd)); /* give'm some reasonable value */ + cd->sector_last = -1; /* flag no data buffered */ + cd->adapter_last = -1; + cd->timer.function = cm206_timeout; + cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97; + printk(KERN_INFO "%d kB adapter memory available, " + " %ld bytes kernel memory used.\n", cd->max_sectors * 2, + size); + return 0; } #ifdef MODULE @@ -1417,65 +1512,67 @@ static void __init parse_options(void) { - int i; - for (i=0; i<2; i++) { - if (0x300 <= cm206[i] && i<= 0x370 && cm206[i] % 0x10 == 0) { - cm206_base = cm206[i]; - auto_probe=0; - } - else if (3 <= cm206[i] && cm206[i] <= 15) { - cm206_irq = cm206[i]; - auto_probe=0; - } - } + int i; + for (i = 0; i < 2; i++) { + if (0x300 <= cm206[i] && i <= 0x370 + && cm206[i] % 0x10 == 0) { + cm206_base = cm206[i]; + auto_probe = 0; + } else if (3 <= cm206[i] && cm206[i] <= 15) { + cm206_irq = cm206[i]; + auto_probe = 0; + } + } } int __cm206_init(void) { parse_options(); #if !defined(AUTO_PROBE_MODULE) - auto_probe=0; + auto_probe = 0; #endif return cm206_init(); } void __exit cm206_exit(void) { - cleanup(4); - printk(KERN_INFO "cm206 removed\n"); + cleanup(4); + printk(KERN_INFO "cm206 removed\n"); } module_init(__cm206_init); module_exit(cm206_exit); - -#else /* !MODULE */ + +#else /* !MODULE */ /* This setup function accepts either `auto' or numbers in the range * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */ static int __init cm206_setup(char *s) { - int i, p[4]; - - (void)get_options(s, ARRAY_SIZE(p), p); - - if (!strcmp(s, "auto")) auto_probe=1; - for(i=1; i<=p[0]; i++) { - if (0x300 <= p[i] && i<= 0x370 && p[i] % 0x10 == 0) { - cm206_base = p[i]; - auto_probe = 0; - } - else if (3 <= p[i] && p[i] <= 15) { - cm206_irq = p[i]; - auto_probe = 0; - } - } - return 1; + int i, p[4]; + + (void) get_options(s, ARRAY_SIZE(p), p); + + if (!strcmp(s, "auto")) + auto_probe = 1; + for (i = 1; i <= p[0]; i++) { + if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) { + cm206_base = p[i]; + auto_probe = 0; + } else if (3 <= p[i] && p[i] <= 15) { + cm206_irq = p[i]; + auto_probe = 0; + } + } + return 1; } __setup("cm206=", cm206_setup); -#endif /* !MODULE */ +#endif /* !MODULE */ + + /* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -m486 -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o cm206.o cm206.c" diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c --- v2.4.9/linux/drivers/cdrom/gscd.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/cdrom/gscd.c Fri Sep 7 09:28:38 2001 @@ -41,8 +41,8 @@ */ -/* These settings are for various debug-level. Leave they untouched ... */ -#define NO_GSCD_DEBUG +/* These settings are for various debug-level. Leave they untouched ... */ +#define NO_GSCD_DEBUG #define NO_IOCTL_DEBUG #define NO_MODULE_DEBUG #define NO_FUTURE_WORK @@ -71,81 +71,82 @@ #define MAJOR_NR GOLDSTAR_CDROM_MAJOR #include -#define gscd_port gscd /* for compatible parameter passing with "insmod" */ +#define gscd_port gscd /* for compatible parameter passing with "insmod" */ #include "gscd.h" -static int gscd_blocksizes[1] = {512}; +static int gscd_blocksizes[1] = { 512 }; -static int gscdPresent = 0; +static int gscdPresent = 0; -static unsigned char gscd_buf[2048]; /* buffer for block size conversion */ -static int gscd_bn = -1; -static short gscd_port = GSCD_BASE_ADDR; +static unsigned char gscd_buf[2048]; /* buffer for block size conversion */ +static int gscd_bn = -1; +static short gscd_port = GSCD_BASE_ADDR; MODULE_PARM(gscd, "h"); /* Kommt spaeter vielleicht noch mal dran ... * static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq); - */ + */ -static void gscd_transfer (void); -static void gscd_read_cmd (void); -static void gscd_hsg2msf (long hsg, struct msf *msf); -static void gscd_bin2bcd (unsigned char *p); +static void gscd_transfer(void); +static void gscd_read_cmd(void); +static void gscd_hsg2msf(long hsg, struct msf *msf); +static void gscd_bin2bcd(unsigned char *p); /* Schnittstellen zum Kern/FS */ -static void do_gscd_request (request_queue_t *); -static void __do_gscd_request (unsigned long dummy); -static int gscd_ioctl (struct inode *, struct file *, unsigned int, unsigned long); -static int gscd_open (struct inode *, struct file *); -static int gscd_release (struct inode *, struct file *); -static int check_gscd_med_chg (kdev_t); +static void do_gscd_request(request_queue_t *); +static void __do_gscd_request(unsigned long dummy); +static int gscd_ioctl(struct inode *, struct file *, unsigned int, + unsigned long); +static int gscd_open(struct inode *, struct file *); +static int gscd_release(struct inode *, struct file *); +static int check_gscd_med_chg(kdev_t); /* GoldStar Funktionen */ -static void cc_Reset (void); -static int wait_drv_ready (void); -static int find_drives (void); -static void cmd_out (int, char *, char *, int); -static void cmd_status (void); -static void cc_Ident (char *); -static void cc_SetSpeed (void); -static void init_cd_drive (int); - -static int get_status (void); -static void clear_Audio (void); -static void cc_invalidate (void); +static void cc_Reset(void); +static int wait_drv_ready(void); +static int find_drives(void); +static void cmd_out(int, char *, char *, int); +static void cmd_status(void); +static void cc_Ident(char *); +static void cc_SetSpeed(void); +static void init_cd_drive(int); + +static int get_status(void); +static void clear_Audio(void); +static void cc_invalidate(void); /* some things for the next version */ #ifdef FUTURE_WORK -static void update_state (void); -static long gscd_msf2hsg (struct msf *mp); -static int gscd_bcd2bin (unsigned char bcd); +static void update_state(void); +static long gscd_msf2hsg(struct msf *mp); +static int gscd_bcd2bin(unsigned char bcd); #endif /* common GoldStar Initialization */ -static int my_gscd_init (void); +static int my_gscd_init(void); /* lo-level cmd-Funktionen */ -static void cmd_info_in ( char *, int ); -static void cmd_end ( void ); -static void cmd_read_b ( char *, int, int ); -static void cmd_read_w ( char *, int, int ); -static int cmd_unit_alive ( void ); -static void cmd_write_cmd ( char * ); +static void cmd_info_in(char *, int); +static void cmd_end(void); +static void cmd_read_b(char *, int, int); +static void cmd_read_w(char *, int, int); +static int cmd_unit_alive(void); +static void cmd_write_cmd(char *); /* GoldStar Variablen */ -static int curr_drv_state; -static int drv_states[] = {0,0,0,0,0,0,0,0}; -static int drv_mode; -static int disk_state; -static int speed; -static int ndrives; +static int curr_drv_state; +static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static int drv_mode; +static int disk_state; +static int speed; +static int ndrives; static unsigned char drv_num_read; static unsigned char f_dsk_valid; @@ -155,93 +156,91 @@ static char f_AudioPlay; static char f_AudioPause; -static int AudioStart_m; -static int AudioStart_f; -static int AudioEnd_m; -static int AudioEnd_f; - +static int AudioStart_m; +static int AudioStart_f; +static int AudioEnd_m; +static int AudioEnd_f; + static struct timer_list gscd_timer; static struct block_device_operations gscd_fops = { - open: gscd_open, - release: gscd_release, - ioctl: gscd_ioctl, - check_media_change: check_gscd_med_chg, + open:gscd_open, + release:gscd_release, + ioctl:gscd_ioctl, + check_media_change:check_gscd_med_chg, }; /* * Checking if the media has been changed * (not yet implemented) */ -static int check_gscd_med_chg (kdev_t full_dev) +static int check_gscd_med_chg(kdev_t full_dev) { - int target; + int target; - target = MINOR(full_dev); + target = MINOR(full_dev); - if (target > 0) - { - printk("GSCD: GoldStar CD-ROM request error: invalid device.\n"); - return 0; - } + if (target > 0) { + printk + ("GSCD: GoldStar CD-ROM request error: invalid device.\n"); + return 0; + } +#ifdef GSCD_DEBUG + printk("gscd: check_med_change\n"); +#endif - #ifdef GSCD_DEBUG - printk ("gscd: check_med_change\n"); - #endif - - return 0; + return 0; } #ifndef MODULE /* Using new interface for kernel-parameters */ - -static int __init gscd_setup (char *str) + +static int __init gscd_setup(char *str) { - int ints[2]; - (void)get_options(str, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) - { - gscd_port = ints[1]; - } - return 1; + int ints[2]; + (void) get_options(str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) { + gscd_port = ints[1]; + } + return 1; } __setup("gscd=", gscd_setup); #endif -static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) +static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, + unsigned long arg) { -unsigned char to_do[10]; -unsigned char dummy; + unsigned char to_do[10]; + unsigned char dummy; + - - switch (cmd) - { - case CDROMSTART: /* Spin up the drive */ + switch (cmd) { + case CDROMSTART: /* Spin up the drive */ /* Don't think we can do this. Even if we could, - * I think the drive times out and stops after a while + * I think the drive times out and stops after a while * anyway. For now, ignore it. */ - return 0; + return 0; - case CDROMRESUME: /* keine Ahnung was das ist */ - return 0; + case CDROMRESUME: /* keine Ahnung was das ist */ + return 0; - case CDROMEJECT: - cmd_status (); - to_do[0] = CMD_TRAY_CTL; - cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0); + case CDROMEJECT: + cmd_status(); + to_do[0] = CMD_TRAY_CTL; + cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); - return 0; + return 0; - default: - return -EINVAL; - } + default: + return -EINVAL; + } } @@ -251,17 +250,16 @@ * When Linux gets variable block sizes this will probably go away. */ -static void gscd_transfer (void) +static void gscd_transfer(void) { -long offs; + long offs; - while (CURRENT -> nr_sectors > 0 && gscd_bn == CURRENT -> sector / 4) - { - offs = (CURRENT -> sector & 3) * 512; - memcpy(CURRENT -> buffer, gscd_buf + offs, 512); - CURRENT -> nr_sectors--; - CURRENT -> sector++; - CURRENT -> buffer += 512; + while (CURRENT->nr_sectors > 0 && gscd_bn == CURRENT->sector / 4) { + offs = (CURRENT->sector & 3) * 512; + memcpy(CURRENT->buffer, gscd_buf + offs, 512); + CURRENT->nr_sectors--; + CURRENT->sector++; + CURRENT->buffer += 512; } } @@ -270,17 +268,17 @@ * I/O request routine called from Linux kernel. */ -static void do_gscd_request (request_queue_t * q) +static void do_gscd_request(request_queue_t * q) { - __do_gscd_request(0); + __do_gscd_request(0); } -static void __do_gscd_request (unsigned long dummy) +static void __do_gscd_request(unsigned long dummy) { -unsigned int block,dev; -unsigned int nsect; + unsigned int block, dev; + unsigned int nsect; -repeat: + repeat: if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE) goto out; INIT_REQUEST; @@ -288,18 +286,16 @@ block = CURRENT->sector; nsect = CURRENT->nr_sectors; - if (QUEUE_EMPTY || CURRENT -> sector == -1) + if (QUEUE_EMPTY || CURRENT->sector == -1) goto out; - if (CURRENT -> cmd != READ) - { - printk("GSCD: bad cmd %d\n", CURRENT -> cmd); + if (CURRENT->cmd != READ) { + printk("GSCD: bad cmd %d\n", CURRENT->cmd); end_request(0); goto repeat; } - if (MINOR(CURRENT -> rq_dev) != 0) - { + if (MINOR(CURRENT->rq_dev) != 0) { printk("GSCD: this version supports only one device\n"); end_request(0); goto repeat; @@ -309,18 +305,16 @@ /* if we satisfied the request from the buffer, we're done. */ - if (CURRENT -> nr_sectors == 0) - { + if (CURRENT->nr_sectors == 0) { end_request(1); goto repeat; } - #ifdef GSCD_DEBUG - printk ("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect ); + printk("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect); #endif - gscd_read_cmd (); -out: + gscd_read_cmd(); + out: return; } @@ -331,47 +325,42 @@ * read-data command. */ -static void -gscd_read_cmd (void) +static void gscd_read_cmd(void) { -long block; -struct gscd_Play_msf gscdcmd; -char cmd[] = { CMD_READ, 0x80, 0,0,0, 0,1 }; /* cmd mode M-S-F secth sectl */ + long block; + struct gscd_Play_msf gscdcmd; + char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 }; /* cmd mode M-S-F secth sectl */ - cmd_status (); - if ( disk_state & (ST_NO_DISK | ST_DOOR_OPEN) ) - { - printk ( "GSCD: no disk or door open\n" ); - end_request (0); - } - else - { - if ( disk_state & ST_INVALID ) - { - printk ( "GSCD: disk invalid\n" ); - end_request (0); - } - else - { - gscd_bn = -1; /* purge our buffer */ - block = CURRENT -> sector / 4; - gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */ - - cmd[2] = gscdcmd.start.min; - cmd[3] = gscdcmd.start.sec; - cmd[4] = gscdcmd.start.frame; + cmd_status(); + if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) { + printk("GSCD: no disk or door open\n"); + end_request(0); + } else { + if (disk_state & ST_INVALID) { + printk("GSCD: disk invalid\n"); + end_request(0); + } else { + gscd_bn = -1; /* purge our buffer */ + block = CURRENT->sector / 4; + gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */ + + cmd[2] = gscdcmd.start.min; + cmd[3] = gscdcmd.start.sec; + cmd[4] = gscdcmd.start.frame; #ifdef GSCD_DEBUG - printk ("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], cmd[4] ); -#endif - cmd_out ( TYPE_DATA, (char *)&cmd, (char *)&gscd_buf[0], 1 ); - - gscd_bn = CURRENT -> sector / 4; - gscd_transfer(); - end_request(1); - } + printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], + cmd[4]); +#endif + cmd_out(TYPE_DATA, (char *) &cmd, + (char *) &gscd_buf[0], 1); + + gscd_bn = CURRENT->sector / 4; + gscd_transfer(); + end_request(1); + } } SET_TIMER(__do_gscd_request, 1); } @@ -381,28 +370,27 @@ * Open the device special file. Check that a disk is in. */ -static int gscd_open (struct inode *ip, struct file *fp) +static int gscd_open(struct inode *ip, struct file *fp) { -int st; + int st; #ifdef GSCD_DEBUG -printk ( "GSCD: open\n" ); + printk("GSCD: open\n"); #endif if (gscdPresent == 0) - return -ENXIO; /* no hardware */ + return -ENXIO; /* no hardware */ MOD_INC_USE_COUNT; - get_status (); - st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN); - if ( st ) - { - printk ( "GSCD: no disk or door open\n" ); - MOD_DEC_USE_COUNT; - return -ENXIO; - } - + get_status(); + st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN); + if (st) { + printk("GSCD: no disk or door open\n"); + MOD_DEC_USE_COUNT; + return -ENXIO; + } + /* if (updateToc() < 0) return -EIO; */ @@ -415,11 +403,11 @@ * On close, we flush all gscd blocks from the buffer cache. */ -static int gscd_release (struct inode * inode, struct file * file) +static int gscd_release(struct inode *inode, struct file *file) { #ifdef GSCD_DEBUG -printk ( "GSCD: release\n" ); + printk("GSCD: release\n"); #endif gscd_bn = -1; @@ -429,692 +417,642 @@ } -int get_status (void) +int get_status(void) { -int status; + int status; + + cmd_status(); + status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01); - cmd_status (); - status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01); - - if ( status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01) ) - { - cc_invalidate (); - return 1; - } - else - { - return 0; - } + if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) { + cc_invalidate(); + return 1; + } else { + return 0; + } } -void cc_invalidate (void) -{ - drv_num_read = 0xFF; - f_dsk_valid = 0xFF; - current_drive = 0xFF; - f_drv_ok = 0xFF; - - clear_Audio (); - -} - -void clear_Audio (void) -{ - - f_AudioPlay = 0; - f_AudioPause = 0; - AudioStart_m = 0; - AudioStart_f = 0; - AudioEnd_m = 0; - AudioEnd_f = 0; - +void cc_invalidate(void) +{ + drv_num_read = 0xFF; + f_dsk_valid = 0xFF; + current_drive = 0xFF; + f_drv_ok = 0xFF; + + clear_Audio(); + +} + +void clear_Audio(void) +{ + + f_AudioPlay = 0; + f_AudioPause = 0; + AudioStart_m = 0; + AudioStart_f = 0; + AudioEnd_m = 0; + AudioEnd_f = 0; + } /* * waiting ? */ -int wait_drv_ready (void) +int wait_drv_ready(void) { -int found, read; + int found, read; + + do { + found = inb(GSCDPORT(0)); + found &= 0x0f; + read = inb(GSCDPORT(0)); + read &= 0x0f; + } while (read != found); - do - { - found = inb ( GSCDPORT(0) ); - found &= 0x0f; - read = inb ( GSCDPORT(0) ); - read &= 0x0f; - } while ( read != found ); - #ifdef GSCD_DEBUG -printk ( "Wait for: %d\n", read ); -#endif - - return read; + printk("Wait for: %d\n", read); +#endif + + return read; } -void cc_Ident (char * respons) +void cc_Ident(char *respons) { -char to_do [] = {CMD_IDENT, 0, 0}; + char to_do[] = { CMD_IDENT, 0, 0 }; - cmd_out (TYPE_INFO, (char *)&to_do, (char *)respons, (int)0x1E ); + cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E); } -void cc_SetSpeed (void) +void cc_SetSpeed(void) { -char to_do [] = {CMD_SETSPEED, 0, 0}; -char dummy; + char to_do[] = { CMD_SETSPEED, 0, 0 }; + char dummy; - if ( speed > 0 ) - { - to_do[1] = speed & 0x0F; - cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0); - } + if (speed > 0) { + to_do[1] = speed & 0x0F; + cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); + } } -void cc_Reset (void) +void cc_Reset(void) { -char to_do [] = {CMD_RESET, 0}; -char dummy; + char to_do[] = { CMD_RESET, 0 }; + char dummy; - cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0); + cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); } -void cmd_status (void) +void cmd_status(void) { -char to_do [] = {CMD_STATUS, 0}; -char dummy; + char to_do[] = { CMD_STATUS, 0 }; + char dummy; - cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0); + cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); #ifdef GSCD_DEBUG -printk ("GSCD: Status: %d\n", disk_state ); + printk("GSCD: Status: %d\n", disk_state); #endif } -void cmd_out ( int cmd_type, char * cmd, char * respo_buf, int respo_count ) +void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count) { -int result; + int result; + + + result = wait_drv_ready(); + if (result != drv_mode) { + unsigned long test_loops = 0xFFFF; + int i, dummy; + outb(curr_drv_state, GSCDPORT(0)); - result = wait_drv_ready (); - if ( result != drv_mode ) - { - unsigned long test_loops = 0xFFFF; - int i,dummy; - - outb ( curr_drv_state, GSCDPORT(0)); - - /* LOCLOOP_170 */ - do - { - result = wait_drv_ready (); - test_loops--; - } while ( (result != drv_mode) && (test_loops > 0) ); - - if ( result != drv_mode ) - { - disk_state = ST_x08 | ST_x04 | ST_INVALID; - return; - } - - /* ...and waiting */ - for ( i=1,dummy=1 ; i<0xFFFF ; i++ ) - { - dummy *= i; - } - } - - /* LOC_172 */ - /* check the unit */ - /* and wake it up */ - if ( cmd_unit_alive () != 0x08 ) - { - /* LOC_174 */ - /* game over for this unit */ - disk_state = ST_x08 | ST_x04 | ST_INVALID; - return; - } - - /* LOC_176 */ - #ifdef GSCD_DEBUG - printk ("LOC_176 "); - #endif - if ( drv_mode == 0x09 ) - { - /* magic... */ - printk ("GSCD: magic ...\n"); - outb ( result, GSCDPORT(2)); - } - - /* write the command to the drive */ - cmd_write_cmd (cmd); - - /* LOC_178 */ - for (;;) - { - result = wait_drv_ready (); - if ( result != drv_mode ) - { - /* LOC_179 */ - if ( result == 0x04 ) /* Mode 4 */ - { - /* LOC_205 */ - #ifdef GSCD_DEBUG - printk ("LOC_205 "); - #endif - disk_state = inb ( GSCDPORT (2)); - - do - { - result = wait_drv_ready (); - } while ( result != drv_mode ); - return; - - } - else - { - if ( result == 0x06 ) /* Mode 6 */ - { - /* LOC_181 */ - #ifdef GSCD_DEBUG - printk ("LOC_181 "); - #endif - - if (cmd_type == TYPE_DATA) - { - /* read data */ - /* LOC_184 */ - if ( drv_mode == 9 ) - { - /* read the data to the buffer (word) */ - - /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */ - cmd_read_w ( respo_buf, respo_count, CD_FRAMESIZE/2 ); - return; - } - else - { - /* read the data to the buffer (byte) */ - - /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */ - cmd_read_b ( respo_buf, respo_count, CD_FRAMESIZE ); - return; - } - } - else - { - /* read the info to the buffer */ - cmd_info_in ( respo_buf, respo_count ); - return; - } - - return; - } - } - - } - else - { - disk_state = ST_x08 | ST_x04 | ST_INVALID; - return; - } - } /* for (;;) */ + /* LOCLOOP_170 */ + do { + result = wait_drv_ready(); + test_loops--; + } while ((result != drv_mode) && (test_loops > 0)); + if (result != drv_mode) { + disk_state = ST_x08 | ST_x04 | ST_INVALID; + return; + } + + /* ...and waiting */ + for (i = 1, dummy = 1; i < 0xFFFF; i++) { + dummy *= i; + } + } + /* LOC_172 */ + /* check the unit */ + /* and wake it up */ + if (cmd_unit_alive() != 0x08) { + /* LOC_174 */ + /* game over for this unit */ + disk_state = ST_x08 | ST_x04 | ST_INVALID; + return; + } + + /* LOC_176 */ #ifdef GSCD_DEBUG -printk ("\n"); -#endif + printk("LOC_176 "); +#endif + if (drv_mode == 0x09) { + /* magic... */ + printk("GSCD: magic ...\n"); + outb(result, GSCDPORT(2)); + } + + /* write the command to the drive */ + cmd_write_cmd(cmd); + + /* LOC_178 */ + for (;;) { + result = wait_drv_ready(); + if (result != drv_mode) { + /* LOC_179 */ + if (result == 0x04) { /* Mode 4 */ + /* LOC_205 */ +#ifdef GSCD_DEBUG + printk("LOC_205 "); +#endif + disk_state = inb(GSCDPORT(2)); + + do { + result = wait_drv_ready(); + } while (result != drv_mode); + return; + + } else { + if (result == 0x06) { /* Mode 6 */ + /* LOC_181 */ +#ifdef GSCD_DEBUG + printk("LOC_181 "); +#endif + + if (cmd_type == TYPE_DATA) { + /* read data */ + /* LOC_184 */ + if (drv_mode == 9) { + /* read the data to the buffer (word) */ + + /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */ + cmd_read_w + (respo_buf, + respo_count, + CD_FRAMESIZE / + 2); + return; + } else { + /* read the data to the buffer (byte) */ + + /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */ + cmd_read_b + (respo_buf, + respo_count, + CD_FRAMESIZE); + return; + } + } else { + /* read the info to the buffer */ + cmd_info_in(respo_buf, + respo_count); + return; + } + + return; + } + } + + } else { + disk_state = ST_x08 | ST_x04 | ST_INVALID; + return; + } + } /* for (;;) */ + + +#ifdef GSCD_DEBUG + printk("\n"); +#endif +} + + +static void cmd_write_cmd(char *pstr) +{ + int i, j; + + /* LOC_177 */ +#ifdef GSCD_DEBUG + printk("LOC_177 "); +#endif + + /* calculate the number of parameter */ + j = *pstr & 0x0F; + + /* shift it out */ + for (i = 0; i < j; i++) { + outb(*pstr, GSCDPORT(2)); + pstr++; + } } -static void cmd_write_cmd ( char *pstr ) +static int cmd_unit_alive(void) { -int i,j; + int result; + unsigned long max_test_loops; + + + /* LOC_172 */ +#ifdef GSCD_DEBUG + printk("LOC_172 "); +#endif + + outb(curr_drv_state, GSCDPORT(0)); + max_test_loops = 0xFFFF; - /* LOC_177 */ - #ifdef GSCD_DEBUG - printk ("LOC_177 "); - #endif - - /* calculate the number of parameter */ - j = *pstr & 0x0F; - - /* shift it out */ - for ( i=0 ; i 0) ); - - return result; -} - - -static void cmd_info_in ( char *pb, int count ) -{ -int result; -char read; - - - /* read info */ - /* LOC_182 */ - #ifdef GSCD_DEBUG - printk ("LOC_182 "); - #endif - - do - { - read = inb (GSCDPORT(2)); - if ( count > 0 ) - { - *pb = read; - pb++; - count--; - } - - /* LOC_183 */ - do - { - result = wait_drv_ready (); - } while ( result == 0x0E ); - } while ( result == 6 ); - - cmd_end (); - return; -} - - -static void cmd_read_b ( char *pb, int count, int size ) -{ -int result; -int i; - - - /* LOC_188 */ - /* LOC_189 */ - #ifdef GSCD_DEBUG - printk ("LOC_189 "); - #endif - - do - { - do - { - result = wait_drv_ready (); - } while ( result != 6 || result == 0x0E ); - - if ( result != 6 ) - { - cmd_end (); - return; - } - - #ifdef GSCD_DEBUG - printk ("LOC_191 "); - #endif - - for ( i=0 ; i< size ; i++ ) - { - *pb = inb (GSCDPORT(2)); - pb++; - } - count--; - } while ( count > 0 ); - - cmd_end (); - return; -} - - -static void cmd_end (void) -{ -int result; - - - /* LOC_204 */ - #ifdef GSCD_DEBUG - printk ("LOC_204 "); - #endif - - do - { - result = wait_drv_ready (); - if ( result == drv_mode ) - { - return; - } - } while ( result != 4 ); - - /* LOC_205 */ - #ifdef GSCD_DEBUG - printk ("LOC_205 "); - #endif - - disk_state = inb ( GSCDPORT (2)); - - do - { - result = wait_drv_ready (); - } while ( result != drv_mode ); - return; - -} - - -static void cmd_read_w ( char *pb, int count, int size ) -{ -int result; -int i; - - - #ifdef GSCD_DEBUG - printk ("LOC_185 "); - #endif - - do - { - /* LOC_185 */ - do - { - result = wait_drv_ready (); - } while ( result != 6 || result == 0x0E ); - - if ( result != 6 ) - { - cmd_end (); - return; - } - - for ( i=0 ; i 0 ); - - cmd_end (); - return; -} - -int __init find_drives (void) -{ -int *pdrv; -int drvnum; -int subdrv; -int i; - - speed = 0; - pdrv = (int *)&drv_states; - curr_drv_state = 0xFE; - subdrv = 0; - drvnum = 0; - - for ( i=0 ; i<8 ; i++ ) - { - subdrv++; - cmd_status (); - disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01; - if ( disk_state != (ST_x08 | ST_x04 | ST_INVALID) ) - { - /* LOC_240 */ - *pdrv = curr_drv_state; - init_cd_drive (drvnum); - pdrv++; - drvnum++; - } - else - { - if ( subdrv < 2 ) - { - continue; - } - else - { - subdrv = 0; - } - } + do { + result = wait_drv_ready(); + max_test_loops--; + } while ((result != 0x08) && (max_test_loops > 0)); + + return result; +} -/* curr_drv_state<<1; <-- das geht irgendwie nicht */ + +static void cmd_info_in(char *pb, int count) +{ + int result; + char read; + + + /* read info */ + /* LOC_182 */ +#ifdef GSCD_DEBUG + printk("LOC_182 "); +#endif + + do { + read = inb(GSCDPORT(2)); + if (count > 0) { + *pb = read; + pb++; + count--; + } + + /* LOC_183 */ + do { + result = wait_drv_ready(); + } while (result == 0x0E); + } while (result == 6); + + cmd_end(); + return; +} + + +static void cmd_read_b(char *pb, int count, int size) +{ + int result; + int i; + + + /* LOC_188 */ + /* LOC_189 */ +#ifdef GSCD_DEBUG + printk("LOC_189 "); +#endif + + do { + do { + result = wait_drv_ready(); + } while (result != 6 || result == 0x0E); + + if (result != 6) { + cmd_end(); + return; + } +#ifdef GSCD_DEBUG + printk("LOC_191 "); +#endif + + for (i = 0; i < size; i++) { + *pb = inb(GSCDPORT(2)); + pb++; + } + count--; + } while (count > 0); + + cmd_end(); + return; +} + + +static void cmd_end(void) +{ + int result; + + + /* LOC_204 */ +#ifdef GSCD_DEBUG + printk("LOC_204 "); +#endif + + do { + result = wait_drv_ready(); + if (result == drv_mode) { + return; + } + } while (result != 4); + + /* LOC_205 */ +#ifdef GSCD_DEBUG + printk("LOC_205 "); +#endif + + disk_state = inb(GSCDPORT(2)); + + do { + result = wait_drv_ready(); + } while (result != drv_mode); + return; + +} + + +static void cmd_read_w(char *pb, int count, int size) +{ + int result; + int i; + + +#ifdef GSCD_DEBUG + printk("LOC_185 "); +#endif + + do { + /* LOC_185 */ + do { + result = wait_drv_ready(); + } while (result != 6 || result == 0x0E); + + if (result != 6) { + cmd_end(); + return; + } + + for (i = 0; i < size; i++) { + /* na, hier muss ich noch mal drueber nachdenken */ + *pb = inw(GSCDPORT(2)); + pb++; + } + count--; + } while (count > 0); + + cmd_end(); + return; +} + +int __init find_drives(void) +{ + int *pdrv; + int drvnum; + int subdrv; + int i; + + speed = 0; + pdrv = (int *) &drv_states; + curr_drv_state = 0xFE; + subdrv = 0; + drvnum = 0; + + for (i = 0; i < 8; i++) { + subdrv++; + cmd_status(); + disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01; + if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) { + /* LOC_240 */ + *pdrv = curr_drv_state; + init_cd_drive(drvnum); + pdrv++; + drvnum++; + } else { + if (subdrv < 2) { + continue; + } else { + subdrv = 0; + } + } + +/* curr_drv_state<<1; <-- das geht irgendwie nicht */ /* muss heissen: curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */ - curr_drv_state *= 2; - curr_drv_state |= 1; + curr_drv_state *= 2; + curr_drv_state |= 1; #ifdef GSCD_DEBUG - printk ("DriveState: %d\n", curr_drv_state ); + printk("DriveState: %d\n", curr_drv_state); #endif - } + } - ndrives = drvnum; - return drvnum; -} + ndrives = drvnum; + return drvnum; +} -void __init init_cd_drive ( int num ) +void __init init_cd_drive(int num) { -char resp [50]; -int i; + char resp[50]; + int i; - printk ("GSCD: init unit %d\n", num ); - cc_Ident ((char *)&resp); + printk("GSCD: init unit %d\n", num); + cc_Ident((char *) &resp); - printk ("GSCD: identification: "); - for ( i=0 ; i<0x1E; i++ ) - { - printk ( "%c", resp[i] ); - } - printk ("\n"); - - cc_SetSpeed (); + printk("GSCD: identification: "); + for (i = 0; i < 0x1E; i++) { + printk("%c", resp[i]); + } + printk("\n"); -} + cc_SetSpeed(); + +} #ifdef FUTURE_WORK /* return_done */ -static void update_state ( void ) +static void update_state(void) { -unsigned int AX; + unsigned int AX; + + + if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) { + if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) { + AX = ST_INVALID; + } + + if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) + == 0) { + invalidate(); + f_drv_ok = 0; + } + + AX |= 0x8000; + } + + if (disk_state & ST_PLAYING) { + AX |= 0x200; + } + AX |= 0x100; + /* pkt_esbx = AX; */ - if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 ) - { - if ( disk_state == (ST_x08 | ST_x04 | ST_INVALID)) - { - AX = ST_INVALID; - } - - if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 ) - { - invalidate (); - f_drv_ok = 0; - } - - AX |= 0x8000; - } - - if ( disk_state & ST_PLAYING ) - { - AX |= 0x200; - } - - AX |= 0x100; - /* pkt_esbx = AX; */ + disk_state = 0; - disk_state = 0; - } #endif /* Init for the Module-Version */ int init_gscd(void) { -long err; + long err; - /* call the GoldStar-init */ - err = my_gscd_init ( ); + /* call the GoldStar-init */ + err = my_gscd_init(); - if ( err < 0 ) - { - return err; - } - else - { - printk (KERN_INFO "Happy GoldStar !\n" ); - return 0; - } + if (err < 0) { + return err; + } else { + printk(KERN_INFO "Happy GoldStar !\n"); + return 0; + } } void __exit exit_gscd(void) { - CLEAR_TIMER; + CLEAR_TIMER; - devfs_unregister(devfs_find_handle(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, - 0)); - if ((devfs_unregister_blkdev(MAJOR_NR, "gscd" ) == -EINVAL)) - { - printk("What's that: can't unregister GoldStar-module\n" ); - return; - } - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - release_region (gscd_port,4); - printk(KERN_INFO "GoldStar-module released.\n" ); + devfs_unregister(devfs_find_handle + (NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0)); + if ((devfs_unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) { + printk("What's that: can't unregister GoldStar-module\n"); + return; + } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + release_region(gscd_port, 4); + printk(KERN_INFO "GoldStar-module released.\n"); } #ifdef MODULE module_init(init_gscd); -#endif +#endif module_exit(exit_gscd); /* Test for presence of drive and initialize it. Called only at boot time. */ -int __init gscd_init (void) +int __init gscd_init(void) { - return my_gscd_init (); + return my_gscd_init(); } /* This is the common initialisation for the GoldStar drive. */ /* It is called at boot time AND for module init. */ -int __init my_gscd_init (void) +int __init my_gscd_init(void) { -int i; -int result; + int i; + int result; - printk (KERN_INFO "GSCD: version %s\n", GSCD_VERSION); - printk (KERN_INFO "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", gscd_port); - - if (check_region(gscd_port, 4)) - { - printk("GSCD: Init failed, I/O port (%X) already in use.\n", gscd_port); - return -EIO; + printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION); + printk(KERN_INFO + "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", + gscd_port); + + if (check_region(gscd_port, 4)) { + printk + ("GSCD: Init failed, I/O port (%X) already in use.\n", + gscd_port); + return -EIO; } - + /* check for card */ - result = wait_drv_ready (); - if ( result == 0x09 ) - { - printk ("GSCD: DMA kann ich noch nicht!\n" ); - return -EIO; - } - - if ( result == 0x0b ) - { - drv_mode = result; - i = find_drives (); - if ( i == 0 ) - { - printk ( "GSCD: GoldStar CD-ROM Drive is not found.\n" ); - return -EIO; - } - } - - if ( (result != 0x0b) && (result != 0x09) ) - { - printk ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n" ); - return -EIO; - } - - /* reset all drives */ - i = 0; - while ( drv_states[i] != 0 ) - { - curr_drv_state = drv_states[i]; - printk (KERN_INFO "GSCD: Reset unit %d ... ",i ); - cc_Reset (); - printk ( "done\n" ); - i++; - } - - if (devfs_register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) - { - printk("GSCD: Unable to get major %d for GoldStar CD-ROM\n", - MAJOR_NR); + result = wait_drv_ready(); + if (result == 0x09) { + printk("GSCD: DMA kann ich noch nicht!\n"); return -EIO; } - devfs_register (NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, - S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL); + + if (result == 0x0b) { + drv_mode = result; + i = find_drives(); + if (i == 0) { + printk + ("GSCD: GoldStar CD-ROM Drive is not found.\n"); + return -EIO; + } + } + + if ((result != 0x0b) && (result != 0x09)) { + printk + ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n"); + return -EIO; + } + + /* reset all drives */ + i = 0; + while (drv_states[i] != 0) { + curr_drv_state = drv_states[i]; + printk(KERN_INFO "GSCD: Reset unit %d ... ", i); + cc_Reset(); + printk("done\n"); + i++; + } + + if (devfs_register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) { + printk + ("GSCD: Unable to get major %d for GoldStar CD-ROM\n", + MAJOR_NR); + return -EIO; + } + devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, + S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); blksize_size[MAJOR_NR] = gscd_blocksizes; read_ahead[MAJOR_NR] = 4; - - disk_state = 0; - gscdPresent = 1; + + disk_state = 0; + gscdPresent = 1; request_region(gscd_port, 4, "gscd"); - register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &gscd_fops, 0); + register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &gscd_fops, 0); - printk (KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n" ); + printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n"); return 0; } -static void gscd_hsg2msf (long hsg, struct msf *msf) +static void gscd_hsg2msf(long hsg, struct msf *msf) { hsg += CD_MSF_OFFSET; - msf -> min = hsg / (CD_FRAMES*CD_SECS); - hsg %= CD_FRAMES*CD_SECS; - msf -> sec = hsg / CD_FRAMES; - msf -> frame = hsg % CD_FRAMES; + msf->min = hsg / (CD_FRAMES * CD_SECS); + hsg %= CD_FRAMES * CD_SECS; + msf->sec = hsg / CD_FRAMES; + msf->frame = hsg % CD_FRAMES; - gscd_bin2bcd(&msf -> min); /* convert to BCD */ - gscd_bin2bcd(&msf -> sec); - gscd_bin2bcd(&msf -> frame); + gscd_bin2bcd(&msf->min); /* convert to BCD */ + gscd_bin2bcd(&msf->sec); + gscd_bin2bcd(&msf->frame); } - -static void gscd_bin2bcd (unsigned char *p) + +static void gscd_bin2bcd(unsigned char *p) { -int u, t; + int u, t; u = *p % 10; t = *p / 10; @@ -1123,18 +1061,19 @@ #ifdef FUTURE_WORK -static long gscd_msf2hsg (struct msf *mp) +static long gscd_msf2hsg(struct msf *mp) { - return gscd_bcd2bin(mp -> frame) - + gscd_bcd2bin(mp -> sec) * CD_FRAMES - + gscd_bcd2bin(mp -> min) * CD_FRAMES * CD_SECS - - CD_MSF_OFFSET; + return gscd_bcd2bin(mp->frame) + + gscd_bcd2bin(mp->sec) * CD_FRAMES + + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET; } -static int gscd_bcd2bin (unsigned char bcd) +static int gscd_bcd2bin(unsigned char bcd) { return (bcd >> 4) * 10 + (bcd & 0xF); } #endif - +MODULE_AUTHOR("Oliver Raupach "); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/isp16.c linux/drivers/cdrom/isp16.c --- v2.4.9/linux/drivers/cdrom/isp16.c Mon Dec 13 14:08:40 1999 +++ linux/drivers/cdrom/isp16.c Fri Sep 7 09:28:38 2001 @@ -44,9 +44,7 @@ #define ISP16_VERSION_MAJOR 0 #define ISP16_VERSION_MINOR 6 -#ifdef MODULE #include -#endif /* MODULE */ #include #include @@ -59,8 +57,9 @@ static short isp16_detect(void); static short isp16_c928__detect(void); static short isp16_c929__detect(void); -static short isp16_cdi_config(int base, u_char drive_type, int irq, int dma); -static short isp16_type; /* dependent on type of interface card */ +static short isp16_cdi_config(int base, u_char drive_type, int irq, + int dma); +static short isp16_type; /* dependent on type of interface card */ static u_char isp16_ctrl; static u_short isp16_enable_port; @@ -69,11 +68,12 @@ static int isp16_cdrom_dma = ISP16_CDROM_DMA; static char *isp16_cdrom_type = ISP16_CDROM_TYPE; -#ifdef MODULE MODULE_PARM(isp16_cdrom_base, "i"); MODULE_PARM(isp16_cdrom_irq, "i"); MODULE_PARM(isp16_cdrom_dma, "i"); MODULE_PARM(isp16_cdrom_type, "s"); + +#ifdef MODULE void isp16_exit(void); #endif @@ -82,243 +82,279 @@ #ifndef MODULE -static int +static int __init isp16_setup(char *str) { - int ints[4]; - - (void)get_options(str, ARRAY_SIZE(ints), ints); - if ( ints[0] > 0 ) - isp16_cdrom_base = ints[1]; - if ( ints[0] > 1 ) - isp16_cdrom_irq = ints[2]; - if ( ints[0] > 2 ) - isp16_cdrom_dma = ints[3]; - if ( str ) - isp16_cdrom_type = str; + int ints[4]; - return 1; + (void) get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] > 0) + isp16_cdrom_base = ints[1]; + if (ints[0] > 1) + isp16_cdrom_irq = ints[2]; + if (ints[0] > 2) + isp16_cdrom_dma = ints[3]; + if (str) + isp16_cdrom_type = str; + + return 1; } __setup("isp16=", isp16_setup); -#endif /* MODULE */ +#endif /* MODULE */ /* * ISP16 initialisation. * */ -int __init -isp16_init(void) +int __init isp16_init(void) { - u_char expected_drive; - - printk(KERN_INFO "ISP16: configuration cdrom interface, version %d.%d.\n", ISP16_VERSION_MAJOR, - ISP16_VERSION_MINOR); + u_char expected_drive; - if ( !strcmp(isp16_cdrom_type, "noisp16") ) { - printk("ISP16: no cdrom interface configured.\n"); - return(0); - } - - if (check_region(ISP16_IO_BASE, ISP16_IO_SIZE)) { - printk("ISP16: i/o ports already in use.\n"); - return(-EIO); - } - - if ( (isp16_type=isp16_detect()) < 0 ) { - printk("ISP16: no cdrom interface found.\n"); - return(-EIO); - } - - printk(KERN_INFO "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n", - (isp16_type==2) ? 9 : 8); - - if ( !strcmp(isp16_cdrom_type, "Sanyo") ) - expected_drive = (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0); - else if ( !strcmp(isp16_cdrom_type, "Sony") ) - expected_drive = ISP16_SONY; - else if ( !strcmp(isp16_cdrom_type, "Panasonic") ) - expected_drive = (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0); - else if ( !strcmp(isp16_cdrom_type, "Mitsumi") ) - expected_drive = ISP16_MITSUMI; - else { - printk("ISP16: %s not supported by cdrom interface.\n", isp16_cdrom_type); - return(-EIO); - } - - if ( isp16_cdi_config(isp16_cdrom_base, expected_drive, - isp16_cdrom_irq, isp16_cdrom_dma ) < 0) { - printk("ISP16: cdrom interface has not been properly configured.\n"); - return(-EIO); - } - printk(KERN_INFO "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d," - " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq, isp16_cdrom_dma, - isp16_cdrom_type); - return(0); + printk(KERN_INFO + "ISP16: configuration cdrom interface, version %d.%d.\n", + ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR); + + if (!strcmp(isp16_cdrom_type, "noisp16")) { + printk("ISP16: no cdrom interface configured.\n"); + return (0); + } + + if (check_region(ISP16_IO_BASE, ISP16_IO_SIZE)) { + printk("ISP16: i/o ports already in use.\n"); + return (-EIO); + } + + if ((isp16_type = isp16_detect()) < 0) { + printk("ISP16: no cdrom interface found.\n"); + return (-EIO); + } + + printk(KERN_INFO + "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n", + (isp16_type == 2) ? 9 : 8); + + if (!strcmp(isp16_cdrom_type, "Sanyo")) + expected_drive = + (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0); + else if (!strcmp(isp16_cdrom_type, "Sony")) + expected_drive = ISP16_SONY; + else if (!strcmp(isp16_cdrom_type, "Panasonic")) + expected_drive = + (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0); + else if (!strcmp(isp16_cdrom_type, "Mitsumi")) + expected_drive = ISP16_MITSUMI; + else { + printk("ISP16: %s not supported by cdrom interface.\n", + isp16_cdrom_type); + return (-EIO); + } + + if (isp16_cdi_config(isp16_cdrom_base, expected_drive, + isp16_cdrom_irq, isp16_cdrom_dma) < 0) { + printk + ("ISP16: cdrom interface has not been properly configured.\n"); + return (-EIO); + } + printk(KERN_INFO + "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d," + " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq, + isp16_cdrom_dma, isp16_cdrom_type); + return (0); } -static short __init -isp16_detect(void) +static short __init isp16_detect(void) { - if ( isp16_c929__detect() >= 0 ) - return(2); - else - return(isp16_c928__detect()); + if (isp16_c929__detect() >= 0) + return (2); + else + return (isp16_c928__detect()); } -static short __init -isp16_c928__detect(void) +static short __init isp16_c928__detect(void) { - u_char ctrl; - u_char enable_cdrom; - u_char io; - short i = -1; - - isp16_ctrl = ISP16_C928__CTRL; - isp16_enable_port = ISP16_C928__ENABLE_PORT; - - /* read' and write' are a special read and write, respectively */ - - /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */ - ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC; - ISP16_OUT( ISP16_CTRL_PORT, ctrl ); - - /* read' 3,4 and 5-bit from the cdrom enable port */ - enable_cdrom = ISP16_IN( ISP16_C928__ENABLE_PORT ) & 0x38; - - if ( !(enable_cdrom & 0x20) ) { /* 5-bit not set */ - /* read' last 2 bits of ISP16_IO_SET_PORT */ - io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03; - if ( ((io&0x01)<<1) == (io&0x02) ) { /* bits are the same */ - if ( io == 0 ) { /* ...the same and 0 */ - i = 0; - enable_cdrom |= 0x20; - } - else { /* ...the same and 1 */ /* my card, first time 'round */ - i = 1; - enable_cdrom |= 0x28; - } - ISP16_OUT( ISP16_C928__ENABLE_PORT, enable_cdrom ); - } - else { /* bits are not the same */ - ISP16_OUT( ISP16_CTRL_PORT, ctrl ); - return(i); /* -> not detected: possibly incorrect conclusion */ - } - } - else if ( enable_cdrom == 0x20 ) - i = 0; - else if ( enable_cdrom == 0x28 ) /* my card, already initialised */ - i = 1; + u_char ctrl; + u_char enable_cdrom; + u_char io; + short i = -1; + + isp16_ctrl = ISP16_C928__CTRL; + isp16_enable_port = ISP16_C928__ENABLE_PORT; + + /* read' and write' are a special read and write, respectively */ + + /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */ + ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC; + ISP16_OUT(ISP16_CTRL_PORT, ctrl); + + /* read' 3,4 and 5-bit from the cdrom enable port */ + enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38; + + if (!(enable_cdrom & 0x20)) { /* 5-bit not set */ + /* read' last 2 bits of ISP16_IO_SET_PORT */ + io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03; + if (((io & 0x01) << 1) == (io & 0x02)) { /* bits are the same */ + if (io == 0) { /* ...the same and 0 */ + i = 0; + enable_cdrom |= 0x20; + } else { /* ...the same and 1 *//* my card, first time 'round */ + i = 1; + enable_cdrom |= 0x28; + } + ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom); + } else { /* bits are not the same */ + ISP16_OUT(ISP16_CTRL_PORT, ctrl); + return (i); /* -> not detected: possibly incorrect conclusion */ + } + } else if (enable_cdrom == 0x20) + i = 0; + else if (enable_cdrom == 0x28) /* my card, already initialised */ + i = 1; - ISP16_OUT( ISP16_CTRL_PORT, ctrl ); + ISP16_OUT(ISP16_CTRL_PORT, ctrl); - return(i); + return (i); } -static short __init -isp16_c929__detect(void) +static short __init isp16_c929__detect(void) { - u_char ctrl; - u_char tmp; + u_char ctrl; + u_char tmp; - isp16_ctrl = ISP16_C929__CTRL; - isp16_enable_port = ISP16_C929__ENABLE_PORT; + isp16_ctrl = ISP16_C929__CTRL; + isp16_enable_port = ISP16_C929__ENABLE_PORT; - /* read' and write' are a special read and write, respectively */ + /* read' and write' are a special read and write, respectively */ - /* read' ISP16_CTRL_PORT and save */ - ctrl = ISP16_IN( ISP16_CTRL_PORT ); + /* read' ISP16_CTRL_PORT and save */ + ctrl = ISP16_IN(ISP16_CTRL_PORT); - /* write' zero to the ctrl port and get response */ - ISP16_OUT( ISP16_CTRL_PORT, 0 ); - tmp = ISP16_IN( ISP16_CTRL_PORT ); + /* write' zero to the ctrl port and get response */ + ISP16_OUT(ISP16_CTRL_PORT, 0); + tmp = ISP16_IN(ISP16_CTRL_PORT); - if ( tmp != 2 ) /* isp16 with 82C929 not detected */ - return(-1); + if (tmp != 2) /* isp16 with 82C929 not detected */ + return (-1); - /* restore ctrl port value */ - ISP16_OUT( ISP16_CTRL_PORT, ctrl ); - - return(2); + /* restore ctrl port value */ + ISP16_OUT(ISP16_CTRL_PORT, ctrl); + + return (2); } -static short __init +static short __init isp16_cdi_config(int base, u_char drive_type, int irq, int dma) { - u_char base_code; - u_char irq_code; - u_char dma_code; - u_char i; - - if ( (drive_type == ISP16_MITSUMI) && (dma != 0) ) - printk("ISP16: Mitsumi cdrom drive has no dma support.\n"); - - switch (base) { - case 0x340: base_code = ISP16_BASE_340; break; - case 0x330: base_code = ISP16_BASE_330; break; - case 0x360: base_code = ISP16_BASE_360; break; - case 0x320: base_code = ISP16_BASE_320; break; - default: - printk("ISP16: base address 0x%03X not supported by cdrom interface.\n", - base); - return(-1); - } - switch (irq) { - case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */ - case 5: irq_code = ISP16_IRQ_5; - printk("ISP16: irq 5 shouldn't be used by cdrom interface," - " due to possible conflicts with the sound card.\n"); - break; - case 7: irq_code = ISP16_IRQ_7; - printk("ISP16: irq 7 shouldn't be used by cdrom interface," - " due to possible conflicts with the sound card.\n"); - break; - case 3: irq_code = ISP16_IRQ_3; break; - case 9: irq_code = ISP16_IRQ_9; break; - case 10: irq_code = ISP16_IRQ_10; break; - case 11: irq_code = ISP16_IRQ_11; break; - default: - printk("ISP16: irq %d not supported by cdrom interface.\n", irq ); - return(-1); - } - switch (dma) { - case 0: dma_code = ISP16_DMA_X; break; /* disable dma */ - case 1: printk("ISP16: dma 1 cannot be used by cdrom interface," - " due to conflict with the sound card.\n"); - return(-1); break; - case 3: dma_code = ISP16_DMA_3; break; - case 5: dma_code = ISP16_DMA_5; break; - case 6: dma_code = ISP16_DMA_6; break; - case 7: dma_code = ISP16_DMA_7; break; - default: - printk("ISP16: dma %d not supported by cdrom interface.\n", dma); - return(-1); - } - - if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 && - drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 && - drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI && - drive_type != ISP16_DRIVE_X ) { - printk("ISP16: drive type (code 0x%02X) not supported by cdrom" - " interface.\n", drive_type ); - return(-1); - } - - /* set type of interface */ - i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */ - ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type ); - - /* enable cdrom on interface with 82C929 chip */ - if ( isp16_type > 1 ) - ISP16_OUT( isp16_enable_port, ISP16_ENABLE_CDROM ); - - /* set base address, irq and dma */ - i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */ - ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code ); + u_char base_code; + u_char irq_code; + u_char dma_code; + u_char i; + + if ((drive_type == ISP16_MITSUMI) && (dma != 0)) + printk("ISP16: Mitsumi cdrom drive has no dma support.\n"); + + switch (base) { + case 0x340: + base_code = ISP16_BASE_340; + break; + case 0x330: + base_code = ISP16_BASE_330; + break; + case 0x360: + base_code = ISP16_BASE_360; + break; + case 0x320: + base_code = ISP16_BASE_320; + break; + default: + printk + ("ISP16: base address 0x%03X not supported by cdrom interface.\n", + base); + return (-1); + } + switch (irq) { + case 0: + irq_code = ISP16_IRQ_X; + break; /* disable irq */ + case 5: + irq_code = ISP16_IRQ_5; + printk("ISP16: irq 5 shouldn't be used by cdrom interface," + " due to possible conflicts with the sound card.\n"); + break; + case 7: + irq_code = ISP16_IRQ_7; + printk("ISP16: irq 7 shouldn't be used by cdrom interface," + " due to possible conflicts with the sound card.\n"); + break; + case 3: + irq_code = ISP16_IRQ_3; + break; + case 9: + irq_code = ISP16_IRQ_9; + break; + case 10: + irq_code = ISP16_IRQ_10; + break; + case 11: + irq_code = ISP16_IRQ_11; + break; + default: + printk("ISP16: irq %d not supported by cdrom interface.\n", + irq); + return (-1); + } + switch (dma) { + case 0: + dma_code = ISP16_DMA_X; + break; /* disable dma */ + case 1: + printk("ISP16: dma 1 cannot be used by cdrom interface," + " due to conflict with the sound card.\n"); + return (-1); + break; + case 3: + dma_code = ISP16_DMA_3; + break; + case 5: + dma_code = ISP16_DMA_5; + break; + case 6: + dma_code = ISP16_DMA_6; + break; + case 7: + dma_code = ISP16_DMA_7; + break; + default: + printk("ISP16: dma %d not supported by cdrom interface.\n", + dma); + return (-1); + } + + if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 && + drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 && + drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI && + drive_type != ISP16_DRIVE_X) { + printk + ("ISP16: drive type (code 0x%02X) not supported by cdrom" + " interface.\n", drive_type); + return (-1); + } + + /* set type of interface */ + i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */ + ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type); + + /* enable cdrom on interface with 82C929 chip */ + if (isp16_type > 1) + ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM); + + /* set base address, irq and dma */ + i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */ + ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code); - return(0); + return (0); } void __exit isp16_exit(void) @@ -332,4 +368,5 @@ #endif module_exit(isp16_exit); - +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c --- v2.4.9/linux/drivers/cdrom/mcd.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/cdrom/mcd.c Fri Sep 7 09:28:38 2001 @@ -102,14 +102,14 @@ #define MAJOR_NR MITSUMI_CDROM_MAJOR #include -#define mcd_port mcd /* for compatible parameter passing with "insmod" */ +#define mcd_port mcd /* for compatible parameter passing with "insmod" */ #include "mcd.h" static int mcd_blocksizes[1]; /* I added A flag to drop to 1x speed if too many errors 0 = 1X ; 1 = 2X */ -static int mcdDouble; +static int mcdDouble; /* How many sectors to hold at 1x speed counter */ static int mcd1xhold; @@ -118,19 +118,19 @@ static int mcdPresent; #if 0 -#define TEST1 /* */ -#define TEST2 /* do_mcd_req */ -#define TEST3 */ /* MCD_S_state */ -#define TEST4 /* QUICK_LOOP-counter */ -#define TEST5 */ /* port(1) state */ +#define TEST1 /* */ +#define TEST2 /* do_mcd_req */ +#define TEST3 */ /* MCD_S_state */ +#define TEST4 /* QUICK_LOOP-counter */ +#define TEST5 */ /* port(1) state */ #endif #if 1 -#define QUICK_LOOP_DELAY udelay(45) /* use udelay */ +#define QUICK_LOOP_DELAY udelay(45) /* use udelay */ #define QUICK_LOOP_COUNT 20 #else #define QUICK_LOOP_DELAY -#define QUICK_LOOP_COUNT 140 /* better wait constant time */ +#define QUICK_LOOP_COUNT 140 /* better wait constant time */ #endif /* #define DOUBLE_QUICK_ONLY */ @@ -141,32 +141,32 @@ #define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA) #define MCD_BUF_SIZ 16 static volatile int mcd_transfer_is_active; -static char mcd_buf[2048*MCD_BUF_SIZ]; /* buffer for block size conversion */ +static char mcd_buf[2048 * MCD_BUF_SIZ]; /* buffer for block size conversion */ static volatile int mcd_buf_bn[MCD_BUF_SIZ], mcd_next_bn; static volatile int mcd_buf_in, mcd_buf_out = -1; static volatile int mcd_error; static int mcd_open_count; enum mcd_state_e { - MCD_S_IDLE, /* 0 */ - MCD_S_START, /* 1 */ - MCD_S_MODE, /* 2 */ - MCD_S_READ, /* 3 */ - MCD_S_DATA, /* 4 */ - MCD_S_STOP, /* 5 */ - MCD_S_STOPPING /* 6 */ + MCD_S_IDLE, /* 0 */ + MCD_S_START, /* 1 */ + MCD_S_MODE, /* 2 */ + MCD_S_READ, /* 3 */ + MCD_S_DATA, /* 4 */ + MCD_S_STOP, /* 5 */ + MCD_S_STOPPING /* 6 */ }; static volatile enum mcd_state_e mcd_state = MCD_S_IDLE; static int mcd_mode = -1; -static int MCMD_DATA_READ= MCMD_PLAY_READ; +static int MCMD_DATA_READ = MCMD_PLAY_READ; #define READ_TIMEOUT 3000 #define WORK_AROUND_MITSUMI_BUG_92 #define WORK_AROUND_MITSUMI_BUG_93 #ifdef WORK_AROUND_MITSUMI_BUG_93 int mitsumi_bug_93_wait; -#endif /* WORK_AROUND_MITSUMI_BUG_93 */ +#endif /* WORK_AROUND_MITSUMI_BUG_93 */ -static short mcd_port = CONFIG_MCD_BASE; /* used as "mcd" by "insmod" */ -static int mcd_irq = CONFIG_MCD_IRQ; /* must directly follow mcd_port */ +static short mcd_port = CONFIG_MCD_BASE; /* used as "mcd" by "insmod" */ +static int mcd_irq = CONFIG_MCD_IRQ; /* must directly follow mcd_port */ MODULE_PARM(mcd, "1-2i"); static int McdTimeout, McdTries; @@ -195,75 +195,76 @@ static int GetDiskInfo(void); static int GetToc(void); static int getValue(unsigned char *result); -static int mcd_open(struct cdrom_device_info * cdi, int purpose); -static void mcd_release(struct cdrom_device_info * cdi); -static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr); -static int mcd_tray_move(struct cdrom_device_info * cdi, int position); -int mcd_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, - void * arg); -int mcd_drive_status(struct cdrom_device_info * cdi, int slot_nr); +static int mcd_open(struct cdrom_device_info *cdi, int purpose); +static void mcd_release(struct cdrom_device_info *cdi); +static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr); +static int mcd_tray_move(struct cdrom_device_info *cdi, int position); +int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, + void *arg); +int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr); static struct timer_list mcd_timer; static struct cdrom_device_ops mcd_dops = { - open: mcd_open, - release: mcd_release, - drive_status: mcd_drive_status, - media_changed: mcd_media_changed, - tray_move: mcd_tray_move, - audio_ioctl: mcd_audio_ioctl, - capability: CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | - CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, + open:mcd_open, + release:mcd_release, + drive_status:mcd_drive_status, + media_changed:mcd_media_changed, + tray_move:mcd_tray_move, + audio_ioctl:mcd_audio_ioctl, + capability:CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | + CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, }; static struct cdrom_device_info mcd_info = { - ops: &mcd_dops, - speed: 2, - capacity: 1, - name: "mcd", + ops:&mcd_dops, + speed:2, + capacity:1, + name:"mcd", }; #ifndef MODULE static int __init mcd_setup(char *str) { - int ints[9]; - - (void)get_options(str, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) - mcd_port = ints[1]; - if (ints[0] > 1) - mcd_irq = ints[2]; + int ints[9]; + + (void) get_options(str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) + mcd_port = ints[1]; + if (ints[0] > 1) + mcd_irq = ints[2]; #ifdef WORK_AROUND_MITSUMI_BUG_93 - if (ints[0] > 2) - mitsumi_bug_93_wait = ints[3]; -#endif /* WORK_AROUND_MITSUMI_BUG_93 */ + if (ints[0] > 2) + mitsumi_bug_93_wait = ints[3]; +#endif /* WORK_AROUND_MITSUMI_BUG_93 */ - return 1; + return 1; } __setup("mcd=", mcd_setup); -#endif /* MODULE */ +#endif /* MODULE */ -static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr) +static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr) { - int retval; + int retval; -#if 1 /* the below is not reliable */ - return 0; -#endif +#if 1 /* the below is not reliable */ + return 0; +#endif - if (cdi->dev) { - printk("mcd: Mitsumi CD-ROM request error: invalid device.\n"); - return 0; - } + if (cdi->dev) { + printk + ("mcd: Mitsumi CD-ROM request error: invalid device.\n"); + return 0; + } - retval = mcdDiskChanged; - mcdDiskChanged = 0; + retval = mcdDiskChanged; + mcdDiskChanged = 0; - return retval; + return retval; } @@ -272,18 +273,16 @@ * because it calls 'getMcdStatus' which sleeps. */ -static int -statusCmd(void) +static int statusCmd(void) { int st = -1, retry; - for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) - { - outb(MCMD_GET_STATUS, MCDPORT(0)); /* send get-status cmd */ + for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { + outb(MCMD_GET_STATUS, MCDPORT(0)); /* send get-status cmd */ st = getMcdStatus(MCD_STATUS_DELAY); - if (st != -1) - break; + if (st != -1) + break; } return st; @@ -294,13 +293,11 @@ * Send a 'Play' command and get the status. Use only from the top half. */ -static int -mcdPlay(struct mcd_Play_msf *arg) +static int mcdPlay(struct mcd_Play_msf *arg) { int retry, st = -1; - for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) - { + for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { sendMcdCmd(MCMD_PLAY_READ, arg); st = getMcdStatus(2 * MCD_STATUS_DELAY); if (st != -1) @@ -311,45 +308,40 @@ } -static int -mcd_tray_move(struct cdrom_device_info * cdi, int position) +static int mcd_tray_move(struct cdrom_device_info *cdi, int position) { int i; if (position) { - /* Eject */ - /* all drives can at least stop! */ + /* Eject */ + /* all drives can at least stop! */ if (audioStatus == CDROM_AUDIO_PLAY) { - outb(MCMD_STOP, MCDPORT(0)); - i = getMcdStatus(MCD_STATUS_DELAY); + outb(MCMD_STOP, MCDPORT(0)); + i = getMcdStatus(MCD_STATUS_DELAY); } - audioStatus = CDROM_AUDIO_NO_STATUS; + audioStatus = CDROM_AUDIO_NO_STATUS; - outb(MCMD_EJECT, MCDPORT(0)); - /* - * the status (i) shows failure on all but the FX drives. - * But nothing we can do about that in software! - * So just read the status and forget it. - Jon. - */ - i = getMcdStatus(MCD_STATUS_DELAY); - return 0; - } - else + outb(MCMD_EJECT, MCDPORT(0)); + /* + * the status (i) shows failure on all but the FX drives. + * But nothing we can do about that in software! + * So just read the status and forget it. - Jon. + */ + i = getMcdStatus(MCD_STATUS_DELAY); + return 0; + } else return -EINVAL; } -long -msf2hsg(struct msf *mp) +long msf2hsg(struct msf *mp) { - return bcd2bin(mp -> frame) - + bcd2bin(mp -> sec) * 75 - + bcd2bin(mp -> min) * 4500 - - 150; + return bcd2bin(mp->frame) + + bcd2bin(mp->sec) * 75 + bcd2bin(mp->min) * 4500 - 150; } -int mcd_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, - void * arg) +int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, + void *arg) { int i, st; struct mcd_Toc qInfo; @@ -365,24 +357,22 @@ if (st < 0) return -EIO; - if (!tocUpToDate) - { + if (!tocUpToDate) { i = updateToc(); - if (i < 0) + if (i < 0) return i; /* error reading TOC */ } - switch (cmd) - { - case CDROMSTART: /* Spin up the drive */ + switch (cmd) { + case CDROMSTART: /* Spin up the drive */ /* Don't think we can do this. Even if we could, - * I think the drive times out and stops after a while + * I think the drive times out and stops after a while * anyway. For now, ignore it. */ return 0; - case CDROMSTOP: /* Spin down the drive */ + case CDROMSTOP: /* Spin down the drive */ outb(MCMD_STOP, MCDPORT(0)); i = getMcdStatus(MCD_STATUS_DELAY); @@ -391,15 +381,14 @@ audioStatus = CDROM_AUDIO_NO_STATUS; return 0; - case CDROMPAUSE: /* Pause the drive */ + case CDROMPAUSE: /* Pause the drive */ if (audioStatus != CDROM_AUDIO_PLAY) return -EINVAL; outb(MCMD_STOP, MCDPORT(0)); i = getMcdStatus(MCD_STATUS_DELAY); - if (GetQChannelInfo(&qInfo) < 0) - { + if (GetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */ audioStatus = CDROM_AUDIO_NO_STATUS; @@ -411,15 +400,14 @@ audioStatus = CDROM_AUDIO_PAUSED; return 0; - case CDROMRESUME: /* Play it again, Sam */ + case CDROMRESUME: /* Play it again, Sam */ if (audioStatus != CDROM_AUDIO_PAUSED) return -EINVAL; /* restart the drive at the saved position. */ i = mcdPlay(&mcd_Play); - if (i < 0) - { + if (i < 0) { audioStatus = CDROM_AUDIO_ERROR; return -EIO; } @@ -427,14 +415,13 @@ audioStatus = CDROM_AUDIO_PLAY; return 0; - case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ + case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ - ti=(struct cdrom_ti *) arg; + ti = (struct cdrom_ti *) arg; if (ti->cdti_trk0 < DiskInfo.first - || ti->cdti_trk0 > DiskInfo.last - || ti->cdti_trk1 < ti->cdti_trk0) - { + || ti->cdti_trk0 > DiskInfo.last + || ti->cdti_trk1 < ti->cdti_trk0) { return -EINVAL; } @@ -445,14 +432,14 @@ mcd_Play.end = Toc[ti->cdti_trk1 + 1].diskTime; #ifdef MCD_DEBUG -printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n", - mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame, - mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame); + printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n", + mcd_Play.start.min, mcd_Play.start.sec, + mcd_Play.start.frame, mcd_Play.end.min, + mcd_Play.end.sec, mcd_Play.end.frame); #endif i = mcdPlay(&mcd_Play); - if (i < 0) - { + if (i < 0) { audioStatus = CDROM_AUDIO_ERROR; return -EIO; } @@ -460,15 +447,15 @@ audioStatus = CDROM_AUDIO_PLAY; return 0; - case CDROMPLAYMSF: /* Play starting at the given MSF address. */ + case CDROMPLAYMSF: /* Play starting at the given MSF address. */ if (audioStatus == CDROM_AUDIO_PLAY) { - outb(MCMD_STOP, MCDPORT(0)); - i = getMcdStatus(MCD_STATUS_DELAY); - audioStatus = CDROM_AUDIO_NO_STATUS; + outb(MCMD_STOP, MCDPORT(0)); + i = getMcdStatus(MCD_STATUS_DELAY); + audioStatus = CDROM_AUDIO_NO_STATUS; } - msf=(struct cdrom_msf *) arg; + msf = (struct cdrom_msf *) arg; /* convert to bcd */ @@ -487,14 +474,14 @@ mcd_Play.end.frame = msf->cdmsf_frame1; #ifdef MCD_DEBUG -printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n", -mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame, -mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame); + printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n", + mcd_Play.start.min, mcd_Play.start.sec, + mcd_Play.start.frame, mcd_Play.end.min, + mcd_Play.end.sec, mcd_Play.end.frame); #endif i = mcdPlay(&mcd_Play); - if (i < 0) - { + if (i < 0) { audioStatus = CDROM_AUDIO_ERROR; return -EIO; } @@ -502,35 +489,37 @@ audioStatus = CDROM_AUDIO_PLAY; return 0; - case CDROMREADTOCHDR: /* Read the table of contents header */ - tocHdr=(struct cdrom_tochdr *) arg; + case CDROMREADTOCHDR: /* Read the table of contents header */ + tocHdr = (struct cdrom_tochdr *) arg; tocHdr->cdth_trk0 = DiskInfo.first; tocHdr->cdth_trk1 = DiskInfo.last; return 0; - case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ - entry=(struct cdrom_tocentry *) arg; + case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ + entry = (struct cdrom_tocentry *) arg; if (entry->cdte_track == CDROM_LEADOUT) tocPtr = &Toc[DiskInfo.last - DiskInfo.first + 1]; else if (entry->cdte_track > DiskInfo.last - || entry->cdte_track < DiskInfo.first) + || entry->cdte_track < DiskInfo.first) return -EINVAL; else tocPtr = &Toc[entry->cdte_track]; - entry->cdte_adr = tocPtr -> ctrl_addr; - entry->cdte_ctrl = tocPtr -> ctrl_addr >> 4; + entry->cdte_adr = tocPtr->ctrl_addr; + entry->cdte_ctrl = tocPtr->ctrl_addr >> 4; if (entry->cdte_format == CDROM_LBA) - entry->cdte_addr.lba = msf2hsg(&tocPtr -> diskTime); + entry->cdte_addr.lba = msf2hsg(&tocPtr->diskTime); - else if (entry->cdte_format == CDROM_MSF) - { - entry->cdte_addr.msf.minute = bcd2bin(tocPtr -> diskTime.min); - entry->cdte_addr.msf.second = bcd2bin(tocPtr -> diskTime.sec); - entry->cdte_addr.msf.frame = bcd2bin(tocPtr -> diskTime.frame); + else if (entry->cdte_format == CDROM_MSF) { + entry->cdte_addr.msf.minute = + bcd2bin(tocPtr->diskTime.min); + entry->cdte_addr.msf.second = + bcd2bin(tocPtr->diskTime.sec); + entry->cdte_addr.msf.frame = + bcd2bin(tocPtr->diskTime.frame); } else @@ -538,9 +527,9 @@ return 0; - case CDROMSUBCHNL: /* Get subchannel info */ + case CDROMSUBCHNL: /* Get subchannel info */ - subchnl=(struct cdrom_subchnl *) arg; + subchnl = (struct cdrom_subchnl *) arg; if (GetQChannelInfo(&qInfo) < 0) return -EIO; @@ -549,16 +538,22 @@ subchnl->cdsc_ctrl = qInfo.ctrl_addr >> 4; subchnl->cdsc_trk = bcd2bin(qInfo.track); subchnl->cdsc_ind = bcd2bin(qInfo.pointIndex); - subchnl->cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min); - subchnl->cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec); - subchnl->cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame); - subchnl->cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min); - subchnl->cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec); - subchnl->cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame); - return(0); + subchnl->cdsc_absaddr.msf.minute = + bcd2bin(qInfo.diskTime.min); + subchnl->cdsc_absaddr.msf.second = + bcd2bin(qInfo.diskTime.sec); + subchnl->cdsc_absaddr.msf.frame = + bcd2bin(qInfo.diskTime.frame); + subchnl->cdsc_reladdr.msf.minute = + bcd2bin(qInfo.trackTime.min); + subchnl->cdsc_reladdr.msf.second = + bcd2bin(qInfo.trackTime.sec); + subchnl->cdsc_reladdr.msf.frame = + bcd2bin(qInfo.trackTime.frame); + return (0); - case CDROMVOLCTRL: /* Volume control */ - volctrl=(struct cdrom_volctrl *) arg; + case CDROMVOLCTRL: /* Volume control */ + volctrl = (struct cdrom_volctrl *) arg; outb(MCMD_SET_VOLUME, MCDPORT(0)); outb(volctrl->channel0, MCDPORT(0)); outb(255, MCDPORT(0)); @@ -590,37 +585,38 @@ * When Linux gets variable block sizes this will probably go away. */ -static void -mcd_transfer(void) +static void mcd_transfer(void) { - if (CURRENT_VALID) { - while (CURRENT -> nr_sectors) { - int bn = CURRENT -> sector / 4; - int i; - for (i = 0; i < MCD_BUF_SIZ && mcd_buf_bn[i] != bn; ++i) - ; - if (i < MCD_BUF_SIZ) { - int offs = (i * 4 + (CURRENT -> sector & 3)) * 512; - int nr_sectors = 4 - (CURRENT -> sector & 3); - if (mcd_buf_out != i) { - mcd_buf_out = i; - if (mcd_buf_bn[i] != bn) { - mcd_buf_out = -1; - continue; - } - } - if (nr_sectors > CURRENT -> nr_sectors) - nr_sectors = CURRENT -> nr_sectors; - memcpy(CURRENT -> buffer, mcd_buf + offs, nr_sectors * 512); - CURRENT -> nr_sectors -= nr_sectors; - CURRENT -> sector += nr_sectors; - CURRENT -> buffer += nr_sectors * 512; - } else { - mcd_buf_out = -1; - break; - } - } - } + if (CURRENT_VALID) { + while (CURRENT->nr_sectors) { + int bn = CURRENT->sector / 4; + int i; + for (i = 0; i < MCD_BUF_SIZ && mcd_buf_bn[i] != bn; + ++i); + if (i < MCD_BUF_SIZ) { + int offs = + (i * 4 + (CURRENT->sector & 3)) * 512; + int nr_sectors = 4 - (CURRENT->sector & 3); + if (mcd_buf_out != i) { + mcd_buf_out = i; + if (mcd_buf_bn[i] != bn) { + mcd_buf_out = -1; + continue; + } + } + if (nr_sectors > CURRENT->nr_sectors) + nr_sectors = CURRENT->nr_sectors; + memcpy(CURRENT->buffer, mcd_buf + offs, + nr_sectors * 512); + CURRENT->nr_sectors -= nr_sectors; + CURRENT->sector += nr_sectors; + CURRENT->buffer += nr_sectors * 512; + } else { + mcd_buf_out = -1; + break; + } + } + } } @@ -629,500 +625,512 @@ * Just take the interrupt and clear out the status reg. */ -static void -mcd_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static void mcd_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int st; st = inb(MCDPORT(1)) & 0xFF; #ifdef TEST1 - printk("", st); + printk("", st); #endif - if (!(st & MFL_STATUS)) - { + if (!(st & MFL_STATUS)) { st = inb(MCDPORT(0)) & 0xFF; #ifdef TEST1 printk("", st); #endif if ((st & 0xFF) != 0xFF) - mcd_error = st ? st & 0xFF : -1; + mcd_error = st ? st & 0xFF : -1; } } -static void -do_mcd_request(request_queue_t * q) +static void do_mcd_request(request_queue_t * q) { #ifdef TEST2 - printk(" do_mcd_request(%ld+%ld)\n", CURRENT -> sector, CURRENT -> nr_sectors); + printk(" do_mcd_request(%ld+%ld)\n", CURRENT->sector, + CURRENT->nr_sectors); #endif - mcd_transfer_is_active = 1; - while (CURRENT_VALID) { - if (CURRENT->bh) { - if (!buffer_locked(CURRENT->bh)) - panic(DEVICE_NAME ": block not locked"); - } - mcd_transfer(); - if (CURRENT -> nr_sectors == 0) { - end_request(1); - } else { - mcd_buf_out = -1; /* Want to read a block not in buffer */ - if (mcd_state == MCD_S_IDLE) { - if (!tocUpToDate) { - if (updateToc() < 0) { - while (CURRENT_VALID) - end_request(0); - break; - } + mcd_transfer_is_active = 1; + while (CURRENT_VALID) { + if (CURRENT->bh) { + if (!buffer_locked(CURRENT->bh)) + panic(DEVICE_NAME ": block not locked"); + } + mcd_transfer(); + if (CURRENT->nr_sectors == 0) { + end_request(1); + } else { + mcd_buf_out = -1; /* Want to read a block not in buffer */ + if (mcd_state == MCD_S_IDLE) { + if (!tocUpToDate) { + if (updateToc() < 0) { + while (CURRENT_VALID) + end_request(0); + break; + } + } + mcd_state = MCD_S_START; + McdTries = 5; + SET_TIMER(mcd_poll, 1); + } + break; + } } - mcd_state = MCD_S_START; - McdTries = 5; - SET_TIMER(mcd_poll, 1); - } - break; - } - } - mcd_transfer_is_active = 0; + mcd_transfer_is_active = 0; #ifdef TEST2 - printk(" do_mcd_request ends\n"); + printk(" do_mcd_request ends\n"); #endif } -static void -mcd_poll(unsigned long dummy) +static void mcd_poll(unsigned long dummy) { - int st; - - - if (mcd_error) - { - if (mcd_error & 0xA5) - { - printk("mcd: I/O error 0x%02x", mcd_error); - if (mcd_error & 0x80) - printk(" (Door open)"); - if (mcd_error & 0x20) - printk(" (Disk changed)"); - if (mcd_error & 0x04) - { - printk(" (Read error)"); /* Bitch about the problem. */ - - /* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */ - /* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */ - /* But I find that rather HANDY!!! */ - /* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */ - /* AJK [06/17/95] */ - - /* Slap the CD down to single speed! */ - if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_2X_READ) - { - MCMD_DATA_READ = MCMD_PLAY_READ; /* Uhhh, Ummmm, muhuh-huh! */ - mcd1xhold = SINGLE_HOLD_SECTORS; /* Hey Beavis! */ - printk(" Speed now 1x"); /* Pull my finger! */ + int st; + + + if (mcd_error) { + if (mcd_error & 0xA5) { + printk("mcd: I/O error 0x%02x", mcd_error); + if (mcd_error & 0x80) + printk(" (Door open)"); + if (mcd_error & 0x20) + printk(" (Disk changed)"); + if (mcd_error & 0x04) { + printk(" (Read error)"); /* Bitch about the problem. */ + + /* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */ + /* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */ + /* But I find that rather HANDY!!! */ + /* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */ + /* AJK [06/17/95] */ + + /* Slap the CD down to single speed! */ + if (mcdDouble == 1 + && McdTries == MCD_RETRY_ATTEMPTS + && MCMD_DATA_READ == MCMD_2X_READ) { + MCMD_DATA_READ = MCMD_PLAY_READ; /* Uhhh, Ummmm, muhuh-huh! */ + mcd1xhold = SINGLE_HOLD_SECTORS; /* Hey Beavis! */ + printk(" Speed now 1x"); /* Pull my finger! */ + } + } + printk("\n"); + mcd_invalidate_buffers(); +#ifdef WARN_IF_READ_FAILURE + if (McdTries == MCD_RETRY_ATTEMPTS) + printk("mcd: read of block %d failed\n", + mcd_next_bn); +#endif + if (!McdTries--) { + /* Nuts! This cd is ready for recycling! */ + /* When WAS the last time YOU cleaned it CORRECTLY?! */ + printk + ("mcd: read of block %d failed, giving up\n", + mcd_next_bn); + if (mcd_transfer_is_active) { + McdTries = 0; + goto ret; + } + if (CURRENT_VALID) + end_request(0); + McdTries = MCD_RETRY_ATTEMPTS; + } } + mcd_error = 0; + mcd_state = MCD_S_STOP; } - printk("\n"); - mcd_invalidate_buffers(); -#ifdef WARN_IF_READ_FAILURE - if (McdTries == MCD_RETRY_ATTEMPTS) - printk("mcd: read of block %d failed\n", mcd_next_bn); -#endif - if (!McdTries--) - { - /* Nuts! This cd is ready for recycling! */ - /* When WAS the last time YOU cleaned it CORRECTLY?! */ - printk("mcd: read of block %d failed, giving up\n", mcd_next_bn); - if (mcd_transfer_is_active) - { - McdTries = 0; - goto ret; - } - if (CURRENT_VALID) - end_request(0); - McdTries = MCD_RETRY_ATTEMPTS; - } - } - mcd_error = 0; - mcd_state = MCD_S_STOP; - } /* Switch back to Double speed if enough GOOD sectors were read! */ - + /* Are we a double speed with a crappy CD?! */ - if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_PLAY_READ) - { - /* We ARE a double speed and we ARE bitching! */ - if (mcd1xhold == 0) /* Okay, Like are we STILL at single speed? */ - { /* We need to switch back to double speed now... */ - MCMD_DATA_READ = MCMD_2X_READ; /* Uhhh... BACK You GO! */ - printk("mcd: Switching back to 2X speed!\n"); /* Tell 'em! */ - } - else mcd1xhold--; /* No?! Count down the good reads some more... */ - /* and try, try again! */ - } + if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS + && MCMD_DATA_READ == MCMD_PLAY_READ) { + /* We ARE a double speed and we ARE bitching! */ + if (mcd1xhold == 0) { /* Okay, Like are we STILL at single speed? *//* We need to switch back to double speed now... */ + MCMD_DATA_READ = MCMD_2X_READ; /* Uhhh... BACK You GO! */ + printk("mcd: Switching back to 2X speed!\n"); /* Tell 'em! */ + } else + mcd1xhold--; /* No?! Count down the good reads some more... */ + /* and try, try again! */ + } - immediately: - switch (mcd_state) { + immediately: + switch (mcd_state) { - case MCD_S_IDLE: + case MCD_S_IDLE: #ifdef TEST3 - printk("MCD_S_IDLE\n"); + printk("MCD_S_IDLE\n"); #endif - goto out; + goto out; - case MCD_S_START: + case MCD_S_START: #ifdef TEST3 - printk("MCD_S_START\n"); + printk("MCD_S_START\n"); #endif - outb(MCMD_GET_STATUS, MCDPORT(0)); - mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE; - McdTimeout = 3000; - break; + outb(MCMD_GET_STATUS, MCDPORT(0)); + mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE; + McdTimeout = 3000; + break; - case MCD_S_MODE: + case MCD_S_MODE: #ifdef TEST3 - printk("MCD_S_MODE\n"); + printk("MCD_S_MODE\n"); #endif - if ((st = mcdStatus()) != -1) { + if ((st = mcdStatus()) != -1) { - if (st & MST_DSK_CHG) { - mcdDiskChanged = 1; - tocUpToDate = 0; - mcd_invalidate_buffers(); - } + if (st & MST_DSK_CHG) { + mcdDiskChanged = 1; + tocUpToDate = 0; + mcd_invalidate_buffers(); + } - set_mode_immediately: + set_mode_immediately: - if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) { - mcdDiskChanged = 1; - tocUpToDate = 0; - if (mcd_transfer_is_active) { - mcd_state = MCD_S_START; - goto immediately; - } - printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n"); - mcd_state = MCD_S_IDLE; - while (CURRENT_VALID) - end_request(0); - goto out; - } + if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) { + mcdDiskChanged = 1; + tocUpToDate = 0; + if (mcd_transfer_is_active) { + mcd_state = MCD_S_START; + goto immediately; + } + printk((st & MST_DOOR_OPEN) ? + "mcd: door open\n" : + "mcd: disk removed\n"); + mcd_state = MCD_S_IDLE; + while (CURRENT_VALID) + end_request(0); + goto out; + } - outb(MCMD_SET_MODE, MCDPORT(0)); - outb(1, MCDPORT(0)); - mcd_mode = 1; - mcd_state = MCD_S_READ; - McdTimeout = 3000; + outb(MCMD_SET_MODE, MCDPORT(0)); + outb(1, MCDPORT(0)); + mcd_mode = 1; + mcd_state = MCD_S_READ; + McdTimeout = 3000; - } - break; + } + break; - case MCD_S_READ: + case MCD_S_READ: #ifdef TEST3 - printk("MCD_S_READ\n"); + printk("MCD_S_READ\n"); #endif - if ((st = mcdStatus()) != -1) { + if ((st = mcdStatus()) != -1) { - if (st & MST_DSK_CHG) { - mcdDiskChanged = 1; - tocUpToDate = 0; - mcd_invalidate_buffers(); - } + if (st & MST_DSK_CHG) { + mcdDiskChanged = 1; + tocUpToDate = 0; + mcd_invalidate_buffers(); + } - read_immediately: + read_immediately: - if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) { - mcdDiskChanged = 1; - tocUpToDate = 0; - if (mcd_transfer_is_active) { - mcd_state = MCD_S_START; - goto immediately; - } - printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n"); - mcd_state = MCD_S_IDLE; - while (CURRENT_VALID) - end_request(0); - goto out; - } - - if (CURRENT_VALID) { - struct mcd_Play_msf msf; - mcd_next_bn = CURRENT -> sector / 4; - hsg2msf(mcd_next_bn, &msf.start); - msf.end.min = ~0; - msf.end.sec = ~0; - msf.end.frame = ~0; - sendMcdCmd(MCMD_DATA_READ, &msf); - mcd_state = MCD_S_DATA; - McdTimeout = READ_TIMEOUT; - } else { - mcd_state = MCD_S_STOP; - goto immediately; - } + if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) { + mcdDiskChanged = 1; + tocUpToDate = 0; + if (mcd_transfer_is_active) { + mcd_state = MCD_S_START; + goto immediately; + } + printk((st & MST_DOOR_OPEN) ? + "mcd: door open\n" : + "mcd: disk removed\n"); + mcd_state = MCD_S_IDLE; + while (CURRENT_VALID) + end_request(0); + goto out; + } - } - break; + if (CURRENT_VALID) { + struct mcd_Play_msf msf; + mcd_next_bn = CURRENT->sector / 4; + hsg2msf(mcd_next_bn, &msf.start); + msf.end.min = ~0; + msf.end.sec = ~0; + msf.end.frame = ~0; + sendMcdCmd(MCMD_DATA_READ, &msf); + mcd_state = MCD_S_DATA; + McdTimeout = READ_TIMEOUT; + } else { + mcd_state = MCD_S_STOP; + goto immediately; + } + + } + break; - case MCD_S_DATA: + case MCD_S_DATA: #ifdef TEST3 - printk("MCD_S_DATA\n"); + printk("MCD_S_DATA\n"); #endif - st = inb(MCDPORT(1)) & (MFL_STATUSorDATA); - data_immediately: + st = inb(MCDPORT(1)) & (MFL_STATUSorDATA); + data_immediately: #ifdef TEST5 - printk("Status %02x\n",st); + printk("Status %02x\n", st); #endif - switch (st) { + switch (st) { - case MFL_DATA: + case MFL_DATA: #ifdef WARN_IF_READ_FAILURE - if (McdTries == 5) - printk("mcd: read of block %d failed\n", mcd_next_bn); -#endif - if (!McdTries--) { - printk("mcd: read of block %d failed, giving up\n", mcd_next_bn); - if (mcd_transfer_is_active) { - McdTries = 0; - break; - } - if (CURRENT_VALID) - end_request(0); - McdTries = 5; - } - mcd_state = MCD_S_START; - McdTimeout = READ_TIMEOUT; - goto immediately; - - case MFL_STATUSorDATA: - break; - - default: - McdTries = 5; - if (!CURRENT_VALID && mcd_buf_in == mcd_buf_out) { - mcd_state = MCD_S_STOP; - goto immediately; - } - mcd_buf_bn[mcd_buf_in] = -1; - READ_DATA(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in, 2048); - mcd_buf_bn[mcd_buf_in] = mcd_next_bn++; - if (mcd_buf_out == -1) - mcd_buf_out = mcd_buf_in; - mcd_buf_in = mcd_buf_in + 1 == MCD_BUF_SIZ ? 0 : mcd_buf_in + 1; - if (!mcd_transfer_is_active) { - while (CURRENT_VALID) { - mcd_transfer(); - if (CURRENT -> nr_sectors == 0) - end_request(1); - else - break; - } - } - - if (CURRENT_VALID - && (CURRENT -> sector / 4 < mcd_next_bn || - CURRENT -> sector / 4 > mcd_next_bn + 16)) { - mcd_state = MCD_S_STOP; - goto immediately; - } - McdTimeout = READ_TIMEOUT; + if (McdTries == 5) + printk("mcd: read of block %d failed\n", + mcd_next_bn); +#endif + if (!McdTries--) { + printk + ("mcd: read of block %d failed, giving up\n", + mcd_next_bn); + if (mcd_transfer_is_active) { + McdTries = 0; + break; + } + if (CURRENT_VALID) + end_request(0); + McdTries = 5; + } + mcd_state = MCD_S_START; + McdTimeout = READ_TIMEOUT; + goto immediately; + + case MFL_STATUSorDATA: + break; + + default: + McdTries = 5; + if (!CURRENT_VALID && mcd_buf_in == mcd_buf_out) { + mcd_state = MCD_S_STOP; + goto immediately; + } + mcd_buf_bn[mcd_buf_in] = -1; + READ_DATA(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in, + 2048); + mcd_buf_bn[mcd_buf_in] = mcd_next_bn++; + if (mcd_buf_out == -1) + mcd_buf_out = mcd_buf_in; + mcd_buf_in = + mcd_buf_in + 1 == + MCD_BUF_SIZ ? 0 : mcd_buf_in + 1; + if (!mcd_transfer_is_active) { + while (CURRENT_VALID) { + mcd_transfer(); + if (CURRENT->nr_sectors == 0) + end_request(1); + else + break; + } + } + + if (CURRENT_VALID + && (CURRENT->sector / 4 < mcd_next_bn || + CURRENT->sector / 4 > mcd_next_bn + 16)) { + mcd_state = MCD_S_STOP; + goto immediately; + } + McdTimeout = READ_TIMEOUT; #ifdef DOUBLE_QUICK_ONLY - if (MCMD_DATA_READ != MCMD_PLAY_READ) + if (MCMD_DATA_READ != MCMD_PLAY_READ) #endif - { - int count= QUICK_LOOP_COUNT; - while (count--) { - QUICK_LOOP_DELAY; - if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) { + { + int count = QUICK_LOOP_COUNT; + while (count--) { + QUICK_LOOP_DELAY; + if ((st = + (inb(MCDPORT(1))) & + (MFL_STATUSorDATA)) != + (MFL_STATUSorDATA)) { # ifdef TEST4 /* printk("Quickloop success at %d\n",QUICK_LOOP_COUNT-count); */ - printk(" %d ",QUICK_LOOP_COUNT-count); + printk(" %d ", + QUICK_LOOP_COUNT - + count); # endif - goto data_immediately; - } - } + goto data_immediately; + } + } # ifdef TEST4 /* printk("Quickloop ended at %d\n",QUICK_LOOP_COUNT); */ - printk("ended "); + printk("ended "); # endif - } - break; - } - break; + } + break; + } + break; - case MCD_S_STOP: + case MCD_S_STOP: #ifdef TEST3 - printk("MCD_S_STOP\n"); + printk("MCD_S_STOP\n"); #endif #ifdef WORK_AROUND_MITSUMI_BUG_93 - if (!mitsumi_bug_93_wait) - goto do_not_work_around_mitsumi_bug_93_1; + if (!mitsumi_bug_93_wait) + goto do_not_work_around_mitsumi_bug_93_1; - McdTimeout = mitsumi_bug_93_wait; - mcd_state = 9+3+1; - break; + McdTimeout = mitsumi_bug_93_wait; + mcd_state = 9 + 3 + 1; + break; - case 9+3+1: - if (McdTimeout) - break; + case 9 + 3 + 1: + if (McdTimeout) + break; - do_not_work_around_mitsumi_bug_93_1: -#endif /* WORK_AROUND_MITSUMI_BUG_93 */ + do_not_work_around_mitsumi_bug_93_1: +#endif /* WORK_AROUND_MITSUMI_BUG_93 */ - outb(MCMD_STOP, MCDPORT(0)); + outb(MCMD_STOP, MCDPORT(0)); #ifdef WORK_AROUND_MITSUMI_BUG_92 - if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) { - int i = 4096; - do { - inb(MCDPORT(0)); - } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i); - outb(MCMD_STOP, MCDPORT(0)); - if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) { - i = 4096; - do { - inb(MCDPORT(0)); - } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i); - outb(MCMD_STOP, MCDPORT(0)); - } - } -#endif /* WORK_AROUND_MITSUMI_BUG_92 */ - - mcd_state = MCD_S_STOPPING; - McdTimeout = 1000; - break; + if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) { + int i = 4096; + do { + inb(MCDPORT(0)); + } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == + MFL_STATUS && --i); + outb(MCMD_STOP, MCDPORT(0)); + if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == + MFL_STATUS) { + i = 4096; + do { + inb(MCDPORT(0)); + } while ((inb(MCDPORT(1)) & + MFL_STATUSorDATA) == MFL_STATUS + && --i); + outb(MCMD_STOP, MCDPORT(0)); + } + } +#endif /* WORK_AROUND_MITSUMI_BUG_92 */ - case MCD_S_STOPPING: + mcd_state = MCD_S_STOPPING; + McdTimeout = 1000; + break; + + case MCD_S_STOPPING: #ifdef TEST3 - printk("MCD_S_STOPPING\n"); + printk("MCD_S_STOPPING\n"); #endif - if ((st = mcdStatus()) == -1 && McdTimeout) - break; - - if ((st != -1) && (st & MST_DSK_CHG)) { - mcdDiskChanged = 1; - tocUpToDate = 0; - mcd_invalidate_buffers(); - } + if ((st = mcdStatus()) == -1 && McdTimeout) + break; + if ((st != -1) && (st & MST_DSK_CHG)) { + mcdDiskChanged = 1; + tocUpToDate = 0; + mcd_invalidate_buffers(); + } #ifdef WORK_AROUND_MITSUMI_BUG_93 - if (!mitsumi_bug_93_wait) - goto do_not_work_around_mitsumi_bug_93_2; + if (!mitsumi_bug_93_wait) + goto do_not_work_around_mitsumi_bug_93_2; - McdTimeout = mitsumi_bug_93_wait; - mcd_state = 9+3+2; - break; + McdTimeout = mitsumi_bug_93_wait; + mcd_state = 9 + 3 + 2; + break; - case 9+3+2: - if (McdTimeout) - break; + case 9 + 3 + 2: + if (McdTimeout) + break; - st = -1; + st = -1; - do_not_work_around_mitsumi_bug_93_2: -#endif /* WORK_AROUND_MITSUMI_BUG_93 */ + do_not_work_around_mitsumi_bug_93_2: +#endif /* WORK_AROUND_MITSUMI_BUG_93 */ #ifdef TEST3 - printk("CURRENT_VALID %d mcd_mode %d\n", - CURRENT_VALID, mcd_mode); + printk("CURRENT_VALID %d mcd_mode %d\n", + CURRENT_VALID, mcd_mode); #endif - if (CURRENT_VALID) { - if (st != -1) { - if (mcd_mode == 1) - goto read_immediately; - else - goto set_mode_immediately; - } else { - mcd_state = MCD_S_START; - McdTimeout = 1; - } - } else { - mcd_state = MCD_S_IDLE; - goto out; - } - break; - - default: - printk("mcd: invalid state %d\n", mcd_state); - goto out; - } - - ret: - if (!McdTimeout--) { - printk("mcd: timeout in state %d\n", mcd_state); - mcd_state = MCD_S_STOP; - } - - SET_TIMER(mcd_poll, 1); -out: - return; + if (CURRENT_VALID) { + if (st != -1) { + if (mcd_mode == 1) + goto read_immediately; + else + goto set_mode_immediately; + } else { + mcd_state = MCD_S_START; + McdTimeout = 1; + } + } else { + mcd_state = MCD_S_IDLE; + goto out; + } + break; + + default: + printk("mcd: invalid state %d\n", mcd_state); + goto out; + } + + ret: + if (!McdTimeout--) { + printk("mcd: timeout in state %d\n", mcd_state); + mcd_state = MCD_S_STOP; + } + + SET_TIMER(mcd_poll, 1); + out: + return; } -static void -mcd_invalidate_buffers(void) -{ - int i; - for (i = 0; i < MCD_BUF_SIZ; ++i) - mcd_buf_bn[i] = -1; - mcd_buf_out = -1; +static void mcd_invalidate_buffers(void) +{ + int i; + for (i = 0; i < MCD_BUF_SIZ; ++i) + mcd_buf_bn[i] = -1; + mcd_buf_out = -1; } /* * Open the device special file. Check that a disk is in. */ -static int mcd_open(struct cdrom_device_info * cdi, int purpose) +static int mcd_open(struct cdrom_device_info *cdi, int purpose) { - int st, count=0; + int st, count = 0; if (mcdPresent == 0) - return -ENXIO; /* no hardware */ + return -ENXIO; /* no hardware */ - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; - if (mcd_open_count || mcd_state != MCD_S_IDLE) + if (mcd_open_count || mcd_state != MCD_S_IDLE) goto bump_count; - mcd_invalidate_buffers(); - do { - st = statusCmd(); /* check drive status */ - if (st == -1) - goto err_out; /* drive doesn't respond */ - if ((st & MST_READY) == 0) { /* no disk? wait a sec... */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ); - } - } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS); + mcd_invalidate_buffers(); + do { + st = statusCmd(); /* check drive status */ + if (st == -1) + goto err_out; /* drive doesn't respond */ + if ((st & MST_READY) == 0) { /* no disk? wait a sec... */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ); + } + } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS); - if (updateToc() < 0) - goto err_out; + if (updateToc() < 0) + goto err_out; -bump_count: + bump_count: ++mcd_open_count; return 0; -err_out: - MOD_DEC_USE_COUNT; + err_out: + MOD_DEC_USE_COUNT; return -EIO; } @@ -1130,11 +1138,12 @@ /* * On close, we flush all mcd blocks from the buffer cache. */ -static void mcd_release(struct cdrom_device_info * cdi) -{ MOD_DEC_USE_COUNT; - if (!--mcd_open_count) { - mcd_invalidate_buffers(); - } +static void mcd_release(struct cdrom_device_info *cdi) +{ + MOD_DEC_USE_COUNT; + if (!--mcd_open_count) { + mcd_invalidate_buffers(); + } } @@ -1143,23 +1152,25 @@ * and is used in mcd_exit as well. */ static void cleanup(int level) { - switch (level) { - case 3: - if (unregister_cdrom(&mcd_info)) { - printk(KERN_WARNING "Can't unregister cdrom mcd\n"); - return; - } - free_irq(mcd_irq, NULL); - case 2: - release_region(mcd_port,4); - case 1: - if (devfs_unregister_blkdev(MAJOR_NR, "mcd")) { - printk(KERN_WARNING "Can't unregister major mcd\n"); - return; - } - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - default:; - } + switch (level) { + case 3: + if (unregister_cdrom(&mcd_info)) { + printk(KERN_WARNING + "Can't unregister cdrom mcd\n"); + return; + } + free_irq(mcd_irq, NULL); + case 2: + release_region(mcd_port, 4); + case 1: + if (devfs_unregister_blkdev(MAJOR_NR, "mcd")) { + printk(KERN_WARNING + "Can't unregister major mcd\n"); + return; + } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + default:; + } } @@ -1175,21 +1186,20 @@ char msg[80]; if (mcd_port <= 0 || mcd_irq <= 0) { - printk("skip mcd_init\n"); - return -EIO; + printk("skip mcd_init\n"); + return -EIO; } - if (devfs_register_blkdev(MAJOR_NR, "mcd", &cdrom_fops) != 0) - { + if (devfs_register_blkdev(MAJOR_NR, "mcd", &cdrom_fops) != 0) { printk("Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR); - return -EIO; + return -EIO; } - if (check_region(mcd_port, 4)) { - cleanup(1); - printk("Init failed, I/O port (%X) already in use\n", - mcd_port); - return -EIO; + if (check_region(mcd_port, 4)) { + cleanup(1); + printk("Init failed, I/O port (%X) already in use\n", + mcd_port); + return -EIO; } blksize_size[MAJOR_NR] = mcd_blocksizes; @@ -1198,106 +1208,105 @@ /* check for card */ - outb(0, MCDPORT(1)); /* send reset */ + outb(0, MCDPORT(1)); /* send reset */ for (count = 0; count < 2000000; count++) - (void) inb(MCDPORT(1)); /* delay a bit */ + (void) inb(MCDPORT(1)); /* delay a bit */ - outb(0x40, MCDPORT(0)); /* send get-stat cmd */ + outb(0x40, MCDPORT(0)); /* send get-stat cmd */ for (count = 0; count < 2000000; count++) if (!(inb(MCDPORT(1)) & MFL_STATUS)) break; if (count >= 2000000) { printk("Init failed. No mcd device at 0x%x irq %d\n", - mcd_port, mcd_irq); + mcd_port, mcd_irq); cleanup(1); - return -EIO; + return -EIO; } - count = inb(MCDPORT(0)); /* pick up the status */ - - outb(MCMD_GET_VERSION,MCDPORT(0)); - for(count=0;count<3;count++) - if(getValue(result+count)) { + count = inb(MCDPORT(0)); /* pick up the status */ + + outb(MCMD_GET_VERSION, MCDPORT(0)); + for (count = 0; count < 3; count++) + if (getValue(result + count)) { printk("mitsumi get version failed at 0x%x\n", mcd_port); - cleanup(1); - return -EIO; - } + cleanup(1); + return -EIO; + } if (result[0] == result[1] && result[1] == result[2]) { cleanup(1); - return -EIO; + return -EIO; } - mcdVersion=result[2]; + mcdVersion = result[2]; - if (mcdVersion >=4) - outb(4,MCDPORT(2)); /* magic happens */ + if (mcdVersion >= 4) + outb(4, MCDPORT(2)); /* magic happens */ /* don't get the IRQ until we know for sure the drive is there */ - if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL)) - { - printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq); + if (request_irq + (mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL)) { + printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", + mcd_irq); cleanup(1); - return -EIO; + return -EIO; } - if (result[1] == 'D') - { + if (result[1] == 'D') { MCMD_DATA_READ = MCMD_2X_READ; /* Added flag to drop to 1x speed if too many errors */ mcdDouble = 1; - } else + } else mcd_info.speed = 1; sprintf(msg, " mcd: Mitsumi %s Speed CD-ROM at port=0x%x," - " irq=%d\n", mcd_info.speed == 1 ? "Single" : "Double", mcd_port, mcd_irq); + " irq=%d\n", mcd_info.speed == 1 ? "Single" : "Double", + mcd_port, mcd_irq); request_region(mcd_port, 4, "mcd"); outb(MCMD_CONFIG_DRIVE, MCDPORT(0)); - outb(0x02,MCDPORT(0)); - outb(0x00,MCDPORT(0)); + outb(0x02, MCDPORT(0)); + outb(0x00, MCDPORT(0)); getValue(result); outb(MCMD_CONFIG_DRIVE, MCDPORT(0)); - outb(0x10,MCDPORT(0)); - outb(0x04,MCDPORT(0)); + outb(0x10, MCDPORT(0)); + outb(0x04, MCDPORT(0)); getValue(result); mcd_invalidate_buffers(); mcdPresent = 1; - mcd_info.dev = MKDEV(MAJOR_NR,0); + mcd_info.dev = MKDEV(MAJOR_NR, 0); - if (register_cdrom(&mcd_info) != 0) { - printk("Cannot register Mitsumi CD-ROM!\n"); - cleanup(3); - return -EIO; - } - printk(msg); + if (register_cdrom(&mcd_info) != 0) { + printk("Cannot register Mitsumi CD-ROM!\n"); + cleanup(3); + return -EIO; + } + printk(msg); return 0; } -static void -hsg2msf(long hsg, struct msf *msf) +static void hsg2msf(long hsg, struct msf *msf) { hsg += 150; - msf -> min = hsg / 4500; + msf->min = hsg / 4500; hsg %= 4500; - msf -> sec = hsg / 75; - msf -> frame = hsg % 75; + msf->sec = hsg / 75; + msf->frame = hsg % 75; - bin2bcd(&msf -> min); /* convert to BCD */ - bin2bcd(&msf -> sec); - bin2bcd(&msf -> frame); + bin2bcd(&msf->min); /* convert to BCD */ + bin2bcd(&msf->sec); + bin2bcd(&msf->frame); } -static void -bin2bcd(unsigned char *p) +static void bin2bcd(unsigned char *p) { int u, t; @@ -1306,8 +1315,7 @@ *p = u | (t << 4); } -static int -bcd2bin(unsigned char bcd) +static int bcd2bin(unsigned char bcd) { return (bcd >> 4) * 10 + (bcd & 0xF); } @@ -1318,19 +1326,16 @@ * if it is ready. */ -static int -mcdStatus(void) +static int mcdStatus(void) { int i; int st; st = inb(MCDPORT(1)) & MFL_STATUS; - if (!st) - { + if (!st) { i = inb(MCDPORT(0)) & 0xFF; return i; - } - else + } else return -1; } @@ -1339,16 +1344,15 @@ * Send a play or read command to the drive */ -static void -sendMcdCmd(int cmd, struct mcd_Play_msf *params) +static void sendMcdCmd(int cmd, struct mcd_Play_msf *params) { outb(cmd, MCDPORT(0)); - outb(params -> start.min, MCDPORT(0)); - outb(params -> start.sec, MCDPORT(0)); - outb(params -> start.frame, MCDPORT(0)); - outb(params -> end.min, MCDPORT(0)); - outb(params -> end.sec, MCDPORT(0)); - outb(params -> end.frame, MCDPORT(0)); + outb(params->start.min, MCDPORT(0)); + outb(params->start.sec, MCDPORT(0)); + outb(params->start.frame, MCDPORT(0)); + outb(params->end.min, MCDPORT(0)); + outb(params->end.sec, MCDPORT(0)); + outb(params->end.frame, MCDPORT(0)); } @@ -1357,18 +1361,15 @@ * (see the next routine) */ -static void -mcdStatTimer(unsigned long dummy) +static void mcdStatTimer(unsigned long dummy) { - if (!(inb(MCDPORT(1)) & MFL_STATUS)) - { + if (!(inb(MCDPORT(1)) & MFL_STATUS)) { wake_up(&mcd_waitq); return; } McdTimeout--; - if (McdTimeout <= 0) - { + if (McdTimeout <= 0) { wake_up(&mcd_waitq); return; } @@ -1383,8 +1384,7 @@ * excessive rescheduling. */ -static int -getMcdStatus(int timeout) +static int getMcdStatus(int timeout) { int st; @@ -1402,8 +1402,7 @@ /* XXX might be an error? look at q-channel? */ audioStatus = CDROM_AUDIO_COMPLETED; - if (st & MST_DSK_CHG) - { + if (st & MST_DSK_CHG) { mcdDiskChanged = 1; tocUpToDate = 0; audioStatus = CDROM_AUDIO_NO_STATUS; @@ -1415,18 +1414,22 @@ /* gives current state of the drive This function is quite unreliable, and should probably be rewritten by someone, eventually... */ -int mcd_drive_status(struct cdrom_device_info * cdi, int slot_nr) +int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) { - int st; + int st; - st = statusCmd(); /* check drive status */ - if (st == -1) - return -EIO; /* drive doesn't respond */ - if ((st & MST_READY)) return CDS_DISC_OK; - if ((st & MST_DOOR_OPEN)) return CDS_TRAY_OPEN; - if ((st & MST_DSK_CHG)) return CDS_NO_DISC; - if ((st & MST_BUSY)) return CDS_DRIVE_NOT_READY; - return -EIO; + st = statusCmd(); /* check drive status */ + if (st == -1) + return -EIO; /* drive doesn't respond */ + if ((st & MST_READY)) + return CDS_DISC_OK; + if ((st & MST_DOOR_OPEN)) + return CDS_TRAY_OPEN; + if ((st & MST_DSK_CHG)) + return CDS_NO_DISC; + if ((st & MST_BUSY)) + return CDS_DRIVE_NOT_READY; + return -EIO; } @@ -1434,18 +1437,16 @@ * Read a value from the drive. */ -static int -getValue(unsigned char *result) +static int getValue(unsigned char *result) { - int count; + int count; int s; for (count = 0; count < 2000; count++) if (!(inb(MCDPORT(1)) & MFL_STATUS)) break; - if (count >= 2000) - { + if (count >= 2000) { printk("mcd: getValue timeout\n"); return -1; } @@ -1461,14 +1462,12 @@ * table of contents. */ -int -GetQChannelInfo(struct mcd_Toc *qp) +int GetQChannelInfo(struct mcd_Toc *qp) { unsigned char notUsed; int retry; - for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) - { + for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { outb(MCMD_GET_Q_CHANNEL, MCDPORT(0)); if (getMcdStatus(MCD_STATUS_DELAY) != -1) break; @@ -1477,16 +1476,26 @@ if (retry >= MCD_RETRY_ATTEMPTS) return -1; - if (getValue(&qp -> ctrl_addr) < 0) return -1; - if (getValue(&qp -> track) < 0) return -1; - if (getValue(&qp -> pointIndex) < 0) return -1; - if (getValue(&qp -> trackTime.min) < 0) return -1; - if (getValue(&qp -> trackTime.sec) < 0) return -1; - if (getValue(&qp -> trackTime.frame) < 0) return -1; - if (getValue(¬Used) < 0) return -1; - if (getValue(&qp -> diskTime.min) < 0) return -1; - if (getValue(&qp -> diskTime.sec) < 0) return -1; - if (getValue(&qp -> diskTime.frame) < 0) return -1; + if (getValue(&qp->ctrl_addr) < 0) + return -1; + if (getValue(&qp->track) < 0) + return -1; + if (getValue(&qp->pointIndex) < 0) + return -1; + if (getValue(&qp->trackTime.min) < 0) + return -1; + if (getValue(&qp->trackTime.sec) < 0) + return -1; + if (getValue(&qp->trackTime.frame) < 0) + return -1; + if (getValue(¬Used) < 0) + return -1; + if (getValue(&qp->diskTime.min) < 0) + return -1; + if (getValue(&qp->diskTime.sec) < 0) + return -1; + if (getValue(&qp->diskTime.frame) < 0) + return -1; return 0; } @@ -1496,8 +1505,7 @@ * Read the table of contents (TOC) and TOC header if necessary */ -static int -updateToc() +static int updateToc() { if (tocUpToDate) return 0; @@ -1517,13 +1525,11 @@ * Read the table of contents header */ -static int -GetDiskInfo() +static int GetDiskInfo() { int retry; - for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) - { + for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { outb(MCMD_GET_DISK_INFO, MCDPORT(0)); if (getMcdStatus(MCD_STATUS_DELAY) != -1) break; @@ -1532,30 +1538,35 @@ if (retry >= MCD_RETRY_ATTEMPTS) return -1; - if (getValue(&DiskInfo.first) < 0) return -1; - if (getValue(&DiskInfo.last) < 0) return -1; + if (getValue(&DiskInfo.first) < 0) + return -1; + if (getValue(&DiskInfo.last) < 0) + return -1; DiskInfo.first = bcd2bin(DiskInfo.first); DiskInfo.last = bcd2bin(DiskInfo.last); #ifdef MCD_DEBUG -printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n", - DiskInfo.first, - DiskInfo.last, - DiskInfo.diskLength.min, - DiskInfo.diskLength.sec, - DiskInfo.diskLength.frame, - DiskInfo.firstTrack.min, - DiskInfo.firstTrack.sec, - DiskInfo.firstTrack.frame); -#endif - - if (getValue(&DiskInfo.diskLength.min) < 0) return -1; - if (getValue(&DiskInfo.diskLength.sec) < 0) return -1; - if (getValue(&DiskInfo.diskLength.frame) < 0) return -1; - if (getValue(&DiskInfo.firstTrack.min) < 0) return -1; - if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1; - if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1; + printk + ("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n", + DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min, + DiskInfo.diskLength.sec, DiskInfo.diskLength.frame, + DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec, + DiskInfo.firstTrack.frame); +#endif + + if (getValue(&DiskInfo.diskLength.min) < 0) + return -1; + if (getValue(&DiskInfo.diskLength.sec) < 0) + return -1; + if (getValue(&DiskInfo.diskLength.frame) < 0) + return -1; + if (getValue(&DiskInfo.firstTrack.min) < 0) + return -1; + if (getValue(&DiskInfo.firstTrack.sec) < 0) + return -1; + if (getValue(&DiskInfo.firstTrack.frame) < 0) + return -1; return 0; } @@ -1565,8 +1576,7 @@ * Read the table of contents (TOC) */ -static int -GetToc() +static int GetToc() { int i, px; int limit; @@ -1578,8 +1588,7 @@ i = DiskInfo.last + 3; - for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) - { + for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { outb(MCMD_STOP, MCDPORT(0)); if (getMcdStatus(MCD_STATUS_DELAY) != -1) break; @@ -1588,10 +1597,9 @@ if (retry >= MCD_RETRY_ATTEMPTS) return -1; - for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) - { + for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { outb(MCMD_SET_MODE, MCDPORT(0)); - outb(0x05, MCDPORT(0)); /* mode: toc */ + outb(0x05, MCDPORT(0)); /* mode: toc */ mcd_mode = 0x05; if (getMcdStatus(MCD_STATUS_DELAY) != -1) break; @@ -1600,15 +1608,13 @@ if (retry >= MCD_RETRY_ATTEMPTS) return -1; - for (limit = 300; limit > 0; limit--) - { + for (limit = 300; limit > 0; limit--) { if (GetQChannelInfo(&qInfo) < 0) break; px = bcd2bin(qInfo.pointIndex); if (px > 0 && px < MAX_TRACKS && qInfo.track == 0) - if (Toc[px].pointIndex == 0) - { + if (Toc[px].pointIndex == 0) { Toc[px] = qInfo; i--; } @@ -1619,26 +1625,29 @@ Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength; - for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) - { - outb(MCMD_SET_MODE, MCDPORT(0)); - outb(0x01, MCDPORT(0)); + for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { + outb(MCMD_SET_MODE, MCDPORT(0)); + outb(0x01, MCDPORT(0)); mcd_mode = 1; - if (getMcdStatus(MCD_STATUS_DELAY) != -1) - break; + if (getMcdStatus(MCD_STATUS_DELAY) != -1) + break; } #ifdef MCD_DEBUG -for (i = 1; i <= DiskInfo.last; i++) -printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n", -i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, -Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame, -Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame); -for (i = 100; i < 103; i++) -printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n", -i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, -Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame, -Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame); + for (i = 1; i <= DiskInfo.last; i++) + printk + ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n", + i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, + Toc[i].trackTime.min, Toc[i].trackTime.sec, + Toc[i].trackTime.frame, Toc[i].diskTime.min, + Toc[i].diskTime.sec, Toc[i].diskTime.frame); + for (i = 100; i < 103; i++) + printk + ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n", + i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, + Toc[i].trackTime.min, Toc[i].trackTime.sec, + Toc[i].trackTime.frame, Toc[i].diskTime.min, + Toc[i].diskTime.sec, Toc[i].diskTime.frame); #endif return limit > 0 ? 0 : -1; @@ -1647,13 +1656,14 @@ void __exit mcd_exit(void) { - cleanup(3); - del_timer_sync(&mcd_timer); + cleanup(3); + del_timer_sync(&mcd_timer); } #ifdef MODULE module_init(mcd_init); -#endif +#endif module_exit(mcd_exit); - +MODULE_AUTHOR("Martin Harriss"); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c --- v2.4.9/linux/drivers/cdrom/mcdx.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/cdrom/mcdx.c Fri Sep 7 09:28:38 2001 @@ -53,7 +53,7 @@ #if RCS static const char *mcdx_c_version - = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $"; + = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $"; #endif #include @@ -120,10 +120,10 @@ enum datamodes { MODE0, MODE1, MODE2 }; enum resetmodes { SOFT, HARD }; -const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */ -const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */ -const int DOOR = 0x04; /* door locking capability */ -const int MULTI = 0x08; /* multi session capability */ +const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */ +const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */ +const int DOOR = 0x04; /* door locking capability */ +const int MULTI = 0x08; /* multi session capability */ const unsigned char READ1X = 0xc0; const unsigned char READ2X = 0xc1; @@ -159,53 +159,53 @@ struct s_drive_stuff { /* waitqueues */ - wait_queue_head_t busyq; - wait_queue_head_t lockq; - wait_queue_head_t sleepq; - - /* flags */ - volatile int introk; /* status of last irq operation */ - volatile int busy; /* drive performs an operation */ - volatile int lock; /* exclusive usage */ + wait_queue_head_t busyq; + wait_queue_head_t lockq; + wait_queue_head_t sleepq; + + /* flags */ + volatile int introk; /* status of last irq operation */ + volatile int busy; /* drive performs an operation */ + volatile int lock; /* exclusive usage */ /* cd infos */ struct s_diskinfo di; struct s_multi multi; - struct s_subqcode* toc; /* first entry of the toc array */ + struct s_subqcode *toc; /* first entry of the toc array */ struct s_subqcode start; - struct s_subqcode stop; - int xa; /* 1 if xa disk */ - int audio; /* 1 if audio disk */ + struct s_subqcode stop; + int xa; /* 1 if xa disk */ + int audio; /* 1 if audio disk */ int audiostatus; /* `buffer' control */ - volatile int valid; /* pending, ..., values are valid */ - volatile int pending; /* next sector to be read */ - volatile int low_border; /* first sector not to be skipped direct */ - volatile int high_border; /* first sector `out of area' */ + volatile int valid; /* pending, ..., values are valid */ + volatile int pending; /* next sector to be read */ + volatile int low_border; /* first sector not to be skipped direct */ + volatile int high_border; /* first sector `out of area' */ #ifdef AK2 - volatile int int_err; -#endif /* AK2 */ + volatile int int_err; +#endif /* AK2 */ /* adds and odds */ - void* wreg_data; /* w data */ - void* wreg_reset; /* w hardware reset */ - void* wreg_hcon; /* w hardware conf */ - void* wreg_chn; /* w channel */ - void* rreg_data; /* r data */ - void* rreg_status; /* r status */ - - int irq; /* irq used by this drive */ - int minor; /* minor number of this drive */ - int present; /* drive present and its capabilities */ - unsigned char readcmd; /* read cmd depends on single/double speed */ - unsigned char playcmd; /* play should always be single speed */ - unsigned int xxx; /* set if changed, reset while open */ - unsigned int yyy; /* set if changed, reset by media_changed */ - int users; /* keeps track of open/close */ - int lastsector; /* last block accessible */ - int status; /* last operation's error / status */ - int readerrs; /* # of blocks read w/o error */ + void *wreg_data; /* w data */ + void *wreg_reset; /* w hardware reset */ + void *wreg_hcon; /* w hardware conf */ + void *wreg_chn; /* w channel */ + void *rreg_data; /* r data */ + void *rreg_status; /* r status */ + + int irq; /* irq used by this drive */ + int minor; /* minor number of this drive */ + int present; /* drive present and its capabilities */ + unsigned char readcmd; /* read cmd depends on single/double speed */ + unsigned char playcmd; /* play should always be single speed */ + unsigned int xxx; /* set if changed, reset while open */ + unsigned int yyy; /* set if changed, reset by media_changed */ + int users; /* keeps track of open/close */ + int lastsector; /* last block accessible */ + int status; /* last operation's error / status */ + int readerrs; /* # of blocks read w/o error */ }; @@ -225,299 +225,333 @@ structure mcdx_dops. */ /* ??? exported by the mcdx_sigaction struct */ -static void mcdx_intr(int, void *, struct pt_regs*); +static void mcdx_intr(int, void *, struct pt_regs *); /* exported by file_ops */ -static int mcdx_open(struct cdrom_device_info * cdi, int purpose); -static void mcdx_close(struct cdrom_device_info * cdi); -static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr); -static int mcdx_tray_move(struct cdrom_device_info * cdi, int position); -static int mcdx_lockdoor(struct cdrom_device_info * cdi, int lock); -static int mcdx_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, - void * arg); +static int mcdx_open(struct cdrom_device_info *cdi, int purpose); +static void mcdx_close(struct cdrom_device_info *cdi); +static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr); +static int mcdx_tray_move(struct cdrom_device_info *cdi, int position); +static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock); +static int mcdx_audio_ioctl(struct cdrom_device_info *cdi, + unsigned int cmd, void *arg); /* misc internal support functions */ -static void log2msf(unsigned int, struct cdrom_msf0*); -static unsigned int msf2log(const struct cdrom_msf0*); +static void log2msf(unsigned int, struct cdrom_msf0 *); +static unsigned int msf2log(const struct cdrom_msf0 *); static unsigned int uint2bcd(unsigned int); static unsigned int bcd2uint(unsigned char); -static char *port(int*); -static int irq(int*); -static void mcdx_delay(struct s_drive_stuff*, long jifs); -static int mcdx_transfer(struct s_drive_stuff*, char* buf, int sector, int nr_sectors); -static int mcdx_xfer(struct s_drive_stuff*, char* buf, int sector, int nr_sectors); - -static int mcdx_config(struct s_drive_stuff*, int); -static int mcdx_requestversion(struct s_drive_stuff*, struct s_version*, int); -static int mcdx_stop(struct s_drive_stuff*, int); -static int mcdx_hold(struct s_drive_stuff*, int); -static int mcdx_reset(struct s_drive_stuff*, enum resetmodes, int); -static int mcdx_setdrivemode(struct s_drive_stuff*, enum drivemodes, int); -static int mcdx_setdatamode(struct s_drive_stuff*, enum datamodes, int); -static int mcdx_requestsubqcode(struct s_drive_stuff*, struct s_subqcode*, int); -static int mcdx_requestmultidiskinfo(struct s_drive_stuff*, struct s_multi*, int); -static int mcdx_requesttocdata(struct s_drive_stuff*, struct s_diskinfo*, int); -static int mcdx_getstatus(struct s_drive_stuff*, int); -static int mcdx_getval(struct s_drive_stuff*, int to, int delay, char*); -static int mcdx_talk(struct s_drive_stuff*, - const unsigned char* cmd, size_t, - void *buffer, size_t size, - unsigned int timeout, int); -static int mcdx_readtoc(struct s_drive_stuff*); -static int mcdx_playtrk(struct s_drive_stuff*, const struct cdrom_ti*); -static int mcdx_playmsf(struct s_drive_stuff*, const struct cdrom_msf*); -static int mcdx_setattentuator(struct s_drive_stuff*, struct cdrom_volctrl*, int); +static char *port(int *); +static int irq(int *); +static void mcdx_delay(struct s_drive_stuff *, long jifs); +static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector, + int nr_sectors); +static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector, + int nr_sectors); + +static int mcdx_config(struct s_drive_stuff *, int); +static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *, + int); +static int mcdx_stop(struct s_drive_stuff *, int); +static int mcdx_hold(struct s_drive_stuff *, int); +static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int); +static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int); +static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int); +static int mcdx_requestsubqcode(struct s_drive_stuff *, + struct s_subqcode *, int); +static int mcdx_requestmultidiskinfo(struct s_drive_stuff *, + struct s_multi *, int); +static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *, + int); +static int mcdx_getstatus(struct s_drive_stuff *, int); +static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *); +static int mcdx_talk(struct s_drive_stuff *, + const unsigned char *cmd, size_t, + void *buffer, size_t size, unsigned int timeout, int); +static int mcdx_readtoc(struct s_drive_stuff *); +static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *); +static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *); +static int mcdx_setattentuator(struct s_drive_stuff *, + struct cdrom_volctrl *, int); /* static variables ************************************************/ static int mcdx_blocksizes[MCDX_NDRIVES]; static int mcdx_drive_map[][2] = MCDX_DRIVEMAP; -static struct s_drive_stuff* mcdx_stuffp[MCDX_NDRIVES]; -static struct s_drive_stuff* mcdx_irq_map[16] = - {0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0}; +static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES]; +static struct s_drive_stuff *mcdx_irq_map[16] = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; MODULE_PARM(mcdx, "1-4i"); static struct cdrom_device_ops mcdx_dops = { - open: mcdx_open, - release: mcdx_close, - media_changed: mcdx_media_changed, - tray_move: mcdx_tray_move, - lock_door: mcdx_lockdoor, - audio_ioctl: mcdx_audio_ioctl, - capability: CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED | - CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, + open:mcdx_open, + release:mcdx_close, + media_changed:mcdx_media_changed, + tray_move:mcdx_tray_move, + lock_door:mcdx_lockdoor, + audio_ioctl:mcdx_audio_ioctl, + capability:CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED | + CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, }; static struct cdrom_device_info mcdx_info = { - ops: &mcdx_dops, - speed: 2, - capacity: 1, - name: "mcdx", + ops:&mcdx_dops, + speed:2, + capacity:1, + name:"mcdx", }; /* KERNEL INTERFACE FUNCTIONS **************************************/ -static int mcdx_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, - void * arg) +static int mcdx_audio_ioctl(struct cdrom_device_info *cdi, + unsigned int cmd, void *arg) { struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)]; - if (!stuffp->present) return -ENXIO; + if (!stuffp->present) + return -ENXIO; - if (stuffp->xxx) - { - if(-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) - { + if (stuffp->xxx) { + if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { stuffp->lastsector = -1; - } - else - { + } else { stuffp->lastsector = (CD_FRAMESIZE / 512) - * msf2log(&stuffp->di.msf_leadout) - 1; + * msf2log(&stuffp->di.msf_leadout) - 1; } - if (stuffp->toc) - { + if (stuffp->toc) { kfree(stuffp->toc); stuffp->toc = NULL; - if (-1 == mcdx_readtoc(stuffp)) return -1; + if (-1 == mcdx_readtoc(stuffp)) + return -1; } - stuffp->xxx=0; + stuffp->xxx = 0; } switch (cmd) { - case CDROMSTART: { - xtrace(IOCTL, "ioctl() START\n"); - /* Spin up the drive. Don't think we can do this. - * For now, ignore it. - */ + case CDROMSTART:{ + xtrace(IOCTL, "ioctl() START\n"); + /* Spin up the drive. Don't think we can do this. + * For now, ignore it. + */ return 0; } - case CDROMSTOP: { + case CDROMSTOP:{ xtrace(IOCTL, "ioctl() STOP\n"); - stuffp->audiostatus = CDROM_AUDIO_INVALID; + stuffp->audiostatus = CDROM_AUDIO_INVALID; if (-1 == mcdx_stop(stuffp, 1)) return -EIO; return 0; } - case CDROMPLAYTRKIND: { - struct cdrom_ti *ti=(struct cdrom_ti *) arg; + case CDROMPLAYTRKIND:{ + struct cdrom_ti *ti = (struct cdrom_ti *) arg; xtrace(IOCTL, "ioctl() PLAYTRKIND\n"); if ((ti->cdti_trk0 < stuffp->di.n_first) - || (ti->cdti_trk0 > stuffp->di.n_last) - || (ti->cdti_trk1 < stuffp->di.n_first)) - return -EINVAL; + || (ti->cdti_trk0 > stuffp->di.n_last) + || (ti->cdti_trk1 < stuffp->di.n_first)) + return -EINVAL; if (ti->cdti_trk1 > stuffp->di.n_last) - ti->cdti_trk1 = stuffp->di.n_last; - xtrace(PLAYTRK, "ioctl() track %d to %d\n", ti->cdti_trk0, ti->cdti_trk1); - return mcdx_playtrk(stuffp, ti); - } + ti->cdti_trk1 = stuffp->di.n_last; + xtrace(PLAYTRK, "ioctl() track %d to %d\n", + ti->cdti_trk0, ti->cdti_trk1); + return mcdx_playtrk(stuffp, ti); + } - case CDROMPLAYMSF: { - struct cdrom_msf *msf=(struct cdrom_msf *) arg; + case CDROMPLAYMSF:{ + struct cdrom_msf *msf = (struct cdrom_msf *) arg; - xtrace(IOCTL, "ioctl() PLAYMSF\n"); + xtrace(IOCTL, "ioctl() PLAYMSF\n"); - if ((stuffp->audiostatus == CDROM_AUDIO_PLAY) - && (-1 == mcdx_hold(stuffp, 1))) return -EIO; + if ((stuffp->audiostatus == CDROM_AUDIO_PLAY) + && (-1 == mcdx_hold(stuffp, 1))) + return -EIO; - msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0); - msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0); - msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0); + msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0); + msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0); + msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0); - msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1); - msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1); - msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1); + msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1); + msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1); + msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1); - stuffp->stop.dt.minute = msf->cdmsf_min1; - stuffp->stop.dt.second = msf->cdmsf_sec1; - stuffp->stop.dt.frame = msf->cdmsf_frame1; + stuffp->stop.dt.minute = msf->cdmsf_min1; + stuffp->stop.dt.second = msf->cdmsf_sec1; + stuffp->stop.dt.frame = msf->cdmsf_frame1; - return mcdx_playmsf(stuffp, msf); - } + return mcdx_playmsf(stuffp, msf); + } - case CDROMRESUME: { - xtrace(IOCTL, "ioctl() RESUME\n"); - return mcdx_playtrk(stuffp, NULL); - } + case CDROMRESUME:{ + xtrace(IOCTL, "ioctl() RESUME\n"); + return mcdx_playtrk(stuffp, NULL); + } - case CDROMREADTOCENTRY: { - struct cdrom_tocentry *entry=(struct cdrom_tocentry *) arg; + case CDROMREADTOCENTRY:{ + struct cdrom_tocentry *entry = + (struct cdrom_tocentry *) arg; struct s_subqcode *tp = NULL; xtrace(IOCTL, "ioctl() READTOCENTRY\n"); - if (-1 == mcdx_readtoc(stuffp)) return -1; + if (-1 == mcdx_readtoc(stuffp)) + return -1; if (entry->cdte_track == CDROM_LEADOUT) - tp = &stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1]; + tp = &stuffp->toc[stuffp->di.n_last - + stuffp->di.n_first + 1]; else if (entry->cdte_track > stuffp->di.n_last - || entry->cdte_track < stuffp->di.n_first) return -EINVAL; - else tp = &stuffp->toc[entry->cdte_track - stuffp->di.n_first]; + || entry->cdte_track < stuffp->di.n_first) + return -EINVAL; + else + tp = &stuffp->toc[entry->cdte_track - + stuffp->di.n_first]; - if (NULL == tp) + if (NULL == tp) return -EIO; entry->cdte_adr = tp->control; entry->cdte_ctrl = tp->control >> 4; - /* Always return stuff in MSF, and let the Uniform cdrom driver - worry about what the user actually wants */ - entry->cdte_addr.msf.minute = bcd2uint(tp->dt.minute); - entry->cdte_addr.msf.second = bcd2uint(tp->dt.second); - entry->cdte_addr.msf.frame = bcd2uint(tp->dt.frame); + /* Always return stuff in MSF, and let the Uniform cdrom driver + worry about what the user actually wants */ + entry->cdte_addr.msf.minute = + bcd2uint(tp->dt.minute); + entry->cdte_addr.msf.second = + bcd2uint(tp->dt.second); + entry->cdte_addr.msf.frame = + bcd2uint(tp->dt.frame); return 0; } - case CDROMSUBCHNL: { - struct cdrom_subchnl *sub= (struct cdrom_subchnl *)arg; + case CDROMSUBCHNL:{ + struct cdrom_subchnl *sub = + (struct cdrom_subchnl *) arg; struct s_subqcode q; xtrace(IOCTL, "ioctl() SUBCHNL\n"); - if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) + if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) return -EIO; - xtrace(SUBCHNL, "audiostatus: %x\n", stuffp->audiostatus); + xtrace(SUBCHNL, "audiostatus: %x\n", + stuffp->audiostatus); sub->cdsc_audiostatus = stuffp->audiostatus; sub->cdsc_adr = q.control; sub->cdsc_ctrl = q.control >> 4; sub->cdsc_trk = bcd2uint(q.tno); sub->cdsc_ind = bcd2uint(q.index); - xtrace(SUBCHNL, "trk %d, ind %d\n", - sub->cdsc_trk, sub->cdsc_ind); - /* Always return stuff in MSF, and let the Uniform cdrom driver - worry about what the user actually wants */ - sub->cdsc_absaddr.msf.minute = bcd2uint(q.dt.minute); - sub->cdsc_absaddr.msf.second = bcd2uint(q.dt.second); + xtrace(SUBCHNL, "trk %d, ind %d\n", + sub->cdsc_trk, sub->cdsc_ind); + /* Always return stuff in MSF, and let the Uniform cdrom driver + worry about what the user actually wants */ + sub->cdsc_absaddr.msf.minute = + bcd2uint(q.dt.minute); + sub->cdsc_absaddr.msf.second = + bcd2uint(q.dt.second); sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame); - sub->cdsc_reladdr.msf.minute = bcd2uint(q.tt.minute); - sub->cdsc_reladdr.msf.second = bcd2uint(q.tt.second); + sub->cdsc_reladdr.msf.minute = + bcd2uint(q.tt.minute); + sub->cdsc_reladdr.msf.second = + bcd2uint(q.tt.second); sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame); xtrace(SUBCHNL, - "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n", - sub->cdsc_absaddr.msf.minute, sub->cdsc_absaddr.msf.second, - sub->cdsc_absaddr.msf.frame, sub->cdsc_reladdr.msf.minute, - sub->cdsc_reladdr.msf.second, sub->cdsc_reladdr.msf.frame); + "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n", + sub->cdsc_absaddr.msf.minute, + sub->cdsc_absaddr.msf.second, + sub->cdsc_absaddr.msf.frame, + sub->cdsc_reladdr.msf.minute, + sub->cdsc_reladdr.msf.second, + sub->cdsc_reladdr.msf.frame); return 0; } - case CDROMREADTOCHDR: { - struct cdrom_tochdr *toc=(struct cdrom_tochdr *) arg; + case CDROMREADTOCHDR:{ + struct cdrom_tochdr *toc = + (struct cdrom_tochdr *) arg; xtrace(IOCTL, "ioctl() READTOCHDR\n"); toc->cdth_trk0 = stuffp->di.n_first; toc->cdth_trk1 = stuffp->di.n_last; - xtrace(TOCHDR, "ioctl() track0 = %d, track1 = %d\n", - stuffp->di.n_first, stuffp->di.n_last); + xtrace(TOCHDR, + "ioctl() track0 = %d, track1 = %d\n", + stuffp->di.n_first, stuffp->di.n_last); return 0; } - case CDROMPAUSE: { + case CDROMPAUSE:{ xtrace(IOCTL, "ioctl() PAUSE\n"); - if (stuffp->audiostatus != CDROM_AUDIO_PLAY) return -EINVAL; - if (-1 == mcdx_stop(stuffp, 1)) return -EIO; - stuffp->audiostatus = CDROM_AUDIO_PAUSED; - if (-1 == mcdx_requestsubqcode(stuffp, &stuffp->start, 1)) + if (stuffp->audiostatus != CDROM_AUDIO_PLAY) + return -EINVAL; + if (-1 == mcdx_stop(stuffp, 1)) + return -EIO; + stuffp->audiostatus = CDROM_AUDIO_PAUSED; + if (-1 == + mcdx_requestsubqcode(stuffp, &stuffp->start, + 1)) return -EIO; return 0; } - case CDROMMULTISESSION: { - struct cdrom_multisession *ms=(struct cdrom_multisession *) arg; + case CDROMMULTISESSION:{ + struct cdrom_multisession *ms = + (struct cdrom_multisession *) arg; xtrace(IOCTL, "ioctl() MULTISESSION\n"); /* Always return stuff in LBA, and let the Uniform cdrom driver - worry about what the user actually wants */ + worry about what the user actually wants */ ms->addr.lba = msf2log(&stuffp->multi.msf_last); ms->xa_flag = !!stuffp->multi.multi; - xtrace(MS, "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n", - ms->xa_flag, ms->addr.lba, stuffp->multi.msf_last.minute, - stuffp->multi.msf_last.second,stuffp->multi.msf_last.frame); - + xtrace(MS, + "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n", + ms->xa_flag, ms->addr.lba, + stuffp->multi.msf_last.minute, + stuffp->multi.msf_last.second, + stuffp->multi.msf_last.frame); + return 0; } - case CDROMEJECT: { + case CDROMEJECT:{ xtrace(IOCTL, "ioctl() EJECT\n"); - if (stuffp->users > 1) return -EBUSY; - return(mcdx_tray_move(cdi, 1)); + if (stuffp->users > 1) + return -EBUSY; + return (mcdx_tray_move(cdi, 1)); } - case CDROMCLOSETRAY: { - xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n"); - return(mcdx_tray_move(cdi, 0)); - } + case CDROMCLOSETRAY:{ + xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n"); + return (mcdx_tray_move(cdi, 0)); + } - case CDROMVOLCTRL: { - struct cdrom_volctrl *volctrl=(struct cdrom_volctrl *)arg; - xtrace(IOCTL, "ioctl() VOLCTRL\n"); + case CDROMVOLCTRL:{ + struct cdrom_volctrl *volctrl = + (struct cdrom_volctrl *) arg; + xtrace(IOCTL, "ioctl() VOLCTRL\n"); -#if 0 /* not tested! */ +#if 0 /* not tested! */ /* adjust for the weirdness of workman (md) */ /* can't test it (hs) */ volctrl.channel2 = volctrl.channel1; volctrl.channel1 = volctrl.channel3 = 0x00; #endif - return mcdx_setattentuator(stuffp, volctrl, 2); - } + return mcdx_setattentuator(stuffp, volctrl, 2); + } - default: - xwarn("ioctl(): unknown request 0x%04x\n", cmd); - return -EINVAL; + default: + return -EINVAL; } } void do_mcdx_request(request_queue_t * q) { - int dev; - struct s_drive_stuff *stuffp; + int dev; + struct s_drive_stuff *stuffp; - again: + again: if (QUEUE_EMPTY) { xtrace(REQUEST, "end_request(0): CURRENT == NULL\n"); @@ -525,237 +559,257 @@ } if (CURRENT->rq_status == RQ_INACTIVE) { - xtrace(REQUEST, "end_request(0): rq_status == RQ_INACTIVE\n"); + xtrace(REQUEST, + "end_request(0): rq_status == RQ_INACTIVE\n"); return; } - INIT_REQUEST; + INIT_REQUEST; - dev = MINOR(CURRENT->rq_dev); - stuffp = mcdx_stuffp[dev]; + dev = MINOR(CURRENT->rq_dev); + stuffp = mcdx_stuffp[dev]; if ((dev < 0) - || (dev >= MCDX_NDRIVES) - || !stuffp - || (!stuffp->present)) { + || (dev >= MCDX_NDRIVES) + || !stuffp || (!stuffp->present)) { xwarn("do_request(): bad device: %s\n", - kdevname(CURRENT->rq_dev)); + kdevname(CURRENT->rq_dev)); xtrace(REQUEST, "end_request(0): bad device\n"); - end_request(0); return; - } + end_request(0); + return; + } if (stuffp->audio) { xwarn("do_request() attempt to read from audio cd\n"); xtrace(REQUEST, "end_request(0): read from audio\n"); - end_request(0); return; + end_request(0); + return; } xtrace(REQUEST, "do_request() (%lu + %lu)\n", - CURRENT->sector, CURRENT->nr_sectors); + CURRENT->sector, CURRENT->nr_sectors); - switch (CURRENT->cmd) { - case WRITE: - xwarn("do_request(): attempt to write to cd!!\n"); - xtrace(REQUEST, "end_request(0): write\n"); - end_request(0); return; - - case READ: - stuffp->status = 0; - while (CURRENT->nr_sectors) { - int i; - - i = mcdx_transfer(stuffp, - CURRENT->buffer, - CURRENT->sector, - CURRENT->nr_sectors); - - if (i == -1) { - end_request(0); - goto again; - } - CURRENT->sector += i; - CURRENT->nr_sectors -= i; - CURRENT->buffer += (i * 512); - } - end_request(1); - goto again; - - xtrace(REQUEST, "end_request(1)\n"); - end_request(1); - break; - - default: - panic(MCDX "do_request: unknown command.\n"); - break; - } + switch (CURRENT->cmd) { + case WRITE: + xwarn("do_request(): attempt to write to cd!!\n"); + xtrace(REQUEST, "end_request(0): write\n"); + end_request(0); + return; + + case READ: + stuffp->status = 0; + while (CURRENT->nr_sectors) { + int i; + + i = mcdx_transfer(stuffp, + CURRENT->buffer, + CURRENT->sector, + CURRENT->nr_sectors); + + if (i == -1) { + end_request(0); + goto again; + } + CURRENT->sector += i; + CURRENT->nr_sectors -= i; + CURRENT->buffer += (i * 512); + } + end_request(1); + goto again; + + xtrace(REQUEST, "end_request(1)\n"); + end_request(1); + break; + + default: + panic(MCDX "do_request: unknown command.\n"); + break; + } - goto again; + goto again; } -static int -mcdx_open(struct cdrom_device_info * cdi, int purpose) +static int mcdx_open(struct cdrom_device_info *cdi, int purpose) { - struct s_drive_stuff *stuffp; + struct s_drive_stuff *stuffp; xtrace(OPENCLOSE, "open()\n"); - stuffp = mcdx_stuffp[MINOR(cdi->dev)]; - if (!stuffp->present) return -ENXIO; + stuffp = mcdx_stuffp[MINOR(cdi->dev)]; + if (!stuffp->present) + return -ENXIO; /* Make the modules looking used ... (thanx bjorn). * But we shouldn't forget to decrement the module counter * on error return */ MOD_INC_USE_COUNT; - /* this is only done to test if the drive talks with us */ - if (-1 == mcdx_getstatus(stuffp, 1)) { + /* this is only done to test if the drive talks with us */ + if (-1 == mcdx_getstatus(stuffp, 1)) { MOD_DEC_USE_COUNT; return -EIO; } - if (stuffp->xxx) { + if (stuffp->xxx) { + + xtrace(OPENCLOSE, "open() media changed\n"); + stuffp->audiostatus = CDROM_AUDIO_INVALID; + stuffp->readcmd = 0; + xtrace(OPENCLOSE, "open() Request multisession info\n"); + if (-1 == + mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6)) + xinfo("No multidiskinfo\n"); + } else { + /* multisession ? */ + if (!stuffp->multi.multi) + stuffp->multi.msf_last.second = 2; + + xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n", + stuffp->multi.multi, + stuffp->multi.msf_last.minute, + stuffp->multi.msf_last.second, + stuffp->multi.msf_last.frame); + + {; + } /* got multisession information */ + /* request the disks table of contents (aka diskinfo) */ + if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { + + stuffp->lastsector = -1; - xtrace(OPENCLOSE, "open() media changed\n"); - stuffp->audiostatus = CDROM_AUDIO_INVALID; - stuffp->readcmd = 0; - xtrace(OPENCLOSE, "open() Request multisession info\n"); - if (-1 == mcdx_requestmultidiskinfo( stuffp, &stuffp->multi, 6)) - xinfo("No multidiskinfo\n"); } else { - /* multisession ? */ - if (!stuffp->multi.multi) - stuffp->multi.msf_last.second = 2; - - xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n", - stuffp->multi.multi, - stuffp->multi.msf_last.minute, - stuffp->multi.msf_last.second, - stuffp->multi.msf_last.frame); - - { ; } /* got multisession information */ - /* request the disks table of contents (aka diskinfo) */ - if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { - - stuffp->lastsector = -1; - - } else { - - stuffp->lastsector = (CD_FRAMESIZE / 512) - * msf2log(&stuffp->di.msf_leadout) - 1; - - xtrace(OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n", - stuffp->di.n_first, - stuffp->di.msf_first.minute, - stuffp->di.msf_first.second, - stuffp->di.msf_first.frame, - msf2log(&stuffp->di.msf_first)); - xtrace(OPENCLOSE, "open() last %d (%02x:%02x.%02x) %d\n", - stuffp->di.n_last, - stuffp->di.msf_leadout.minute, - stuffp->di.msf_leadout.second, - stuffp->di.msf_leadout.frame, - msf2log(&stuffp->di.msf_leadout)); - } - - if (stuffp->toc) { - xtrace(MALLOC, "open() free old toc @ %p\n", stuffp->toc); - kfree(stuffp->toc); - - stuffp->toc = NULL; - } - - xtrace(OPENCLOSE, "open() init irq generation\n"); - if (-1 == mcdx_config(stuffp, 1)) { - MOD_DEC_USE_COUNT; - return -EIO; - } + stuffp->lastsector = (CD_FRAMESIZE / 512) + * msf2log(&stuffp->di.msf_leadout) - 1; + + xtrace(OPENCLOSE, + "open() start %d (%02x:%02x.%02x) %d\n", + stuffp->di.n_first, + stuffp->di.msf_first.minute, + stuffp->di.msf_first.second, + stuffp->di.msf_first.frame, + msf2log(&stuffp->di.msf_first)); + xtrace(OPENCLOSE, + "open() last %d (%02x:%02x.%02x) %d\n", + stuffp->di.n_last, + stuffp->di.msf_leadout.minute, + stuffp->di.msf_leadout.second, + stuffp->di.msf_leadout.frame, + msf2log(&stuffp->di.msf_leadout)); + } + + if (stuffp->toc) { + xtrace(MALLOC, "open() free old toc @ %p\n", + stuffp->toc); + kfree(stuffp->toc); + + stuffp->toc = NULL; + } + + xtrace(OPENCLOSE, "open() init irq generation\n"); + if (-1 == mcdx_config(stuffp, 1)) { + MOD_DEC_USE_COUNT; + return -EIO; + } #if FALLBACK - /* Set the read speed */ - xwarn("AAA %x AAA\n", stuffp->readcmd); - if (stuffp->readerrs) stuffp->readcmd = READ1X; - else stuffp->readcmd = - stuffp->present | SINGLE ? READ1X : READ2X; - xwarn("XXX %x XXX\n", stuffp->readcmd); + /* Set the read speed */ + xwarn("AAA %x AAA\n", stuffp->readcmd); + if (stuffp->readerrs) + stuffp->readcmd = READ1X; + else + stuffp->readcmd = + stuffp->present | SINGLE ? READ1X : READ2X; + xwarn("XXX %x XXX\n", stuffp->readcmd); #else - stuffp->readcmd = stuffp->present | SINGLE ? READ1X : READ2X; + stuffp->readcmd = + stuffp->present | SINGLE ? READ1X : READ2X; #endif - /* try to get the first sector, iff any ... */ - if (stuffp->lastsector >= 0) { - char buf[512]; - int ans; - int tries; - - stuffp->xa = 0; - stuffp->audio = 0; - - for (tries = 6; tries; tries--) { - - stuffp->introk = 1; - - xtrace(OPENCLOSE, "open() try as %s\n", - stuffp->xa ? "XA" : "normal"); - /* set data mode */ - if (-1 == (ans = mcdx_setdatamode(stuffp, - stuffp->xa ? MODE2 : MODE1, 1))) { - /* MOD_DEC_USE_COUNT, return -EIO; */ - stuffp->xa = 0; - break; - } - - if ((stuffp->audio = e_audio(ans))) break; - - while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1))) - ; - - if (ans == 1) break; - stuffp->xa = !stuffp->xa; - } - } - /* xa disks will be read in raw mode, others not */ - if (-1 == mcdx_setdrivemode(stuffp, - stuffp->xa ? RAW : COOKED, 1)) { - MOD_DEC_USE_COUNT; - return -EIO; - } - if (stuffp->audio) { - xinfo("open() audio disk found\n"); - } else if (stuffp->lastsector >= 0) { - xinfo("open() %s%s disk found\n", - stuffp->xa ? "XA / " : "", - stuffp->multi.multi ? "Multi Session" : "Single Session"); - } - } + /* try to get the first sector, iff any ... */ + if (stuffp->lastsector >= 0) { + char buf[512]; + int ans; + int tries; + + stuffp->xa = 0; + stuffp->audio = 0; + + for (tries = 6; tries; tries--) { + + stuffp->introk = 1; + + xtrace(OPENCLOSE, "open() try as %s\n", + stuffp->xa ? "XA" : "normal"); + /* set data mode */ + if (-1 == (ans = mcdx_setdatamode(stuffp, + stuffp-> + xa ? + MODE2 : + MODE1, + 1))) { + /* MOD_DEC_USE_COUNT, return -EIO; */ + stuffp->xa = 0; + break; + } + + if ((stuffp->audio = e_audio(ans))) + break; + + while (0 == + (ans = + mcdx_transfer(stuffp, buf, 0, 1))); + + if (ans == 1) + break; + stuffp->xa = !stuffp->xa; + } + } + /* xa disks will be read in raw mode, others not */ + if (-1 == mcdx_setdrivemode(stuffp, + stuffp->xa ? RAW : COOKED, + 1)) { + MOD_DEC_USE_COUNT; + return -EIO; + } + if (stuffp->audio) { + xinfo("open() audio disk found\n"); + } else if (stuffp->lastsector >= 0) { + xinfo("open() %s%s disk found\n", + stuffp->xa ? "XA / " : "", + stuffp->multi. + multi ? "Multi Session" : "Single Session"); + } + } stuffp->xxx = 0; - stuffp->users++; - return 0; + stuffp->users++; + return 0; } -static void mcdx_close(struct cdrom_device_info * cdi) +static void mcdx_close(struct cdrom_device_info *cdi) { - struct s_drive_stuff *stuffp; + struct s_drive_stuff *stuffp; - xtrace(OPENCLOSE, "close()\n"); + xtrace(OPENCLOSE, "close()\n"); - stuffp = mcdx_stuffp[MINOR(cdi->dev)]; + stuffp = mcdx_stuffp[MINOR(cdi->dev)]; - --stuffp->users; + --stuffp->users; - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; } -static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr) +static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr) /* Return: 1 if media changed since last call to this function 0 otherwise */ { - struct s_drive_stuff *stuffp; + struct s_drive_stuff *stuffp; - xinfo("mcdx_media_changed called for device %s\n", - kdevname(cdi->dev)); + xinfo("mcdx_media_changed called for device %s\n", + kdevname(cdi->dev)); stuffp = mcdx_stuffp[MINOR(cdi->dev)]; mcdx_getstatus(stuffp, 1); - if (stuffp->yyy == 0) return 0; + if (stuffp->yyy == 0) + return 0; stuffp->yyy = 0; return 1; @@ -765,10 +819,12 @@ static int __init mcdx_setup(char *str) { int pi[4]; - (void)get_options(str, ARRAY_SIZE(pi), pi); - - if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1]; - if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2]; + (void) get_options(str, ARRAY_SIZE(pi), pi); + + if (pi[0] > 0) + mcdx_drive_map[0][0] = pi[1]; + if (pi[0] > 1) + mcdx_drive_map[0][1] = pi[2]; return 1; } @@ -787,7 +843,8 @@ * May be we could use a simple count loop w/ jumps to itself, but * I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */ { - if (jifs < 0) return; + if (jifs < 0) + return; xtrace(SLEEP, "*** delay: sleepq\n"); interruptible_sleep_on_timeout(&stuff->sleepq, jifs); @@ -797,24 +854,22 @@ } } -static void -mcdx_intr(int irq, void *dev_id, struct pt_regs* regs) +static void mcdx_intr(int irq, void *dev_id, struct pt_regs *regs) { - struct s_drive_stuff *stuffp; + struct s_drive_stuff *stuffp; unsigned char b; - stuffp = mcdx_irq_map[irq]; + stuffp = mcdx_irq_map[irq]; - if (stuffp == NULL ) { + if (stuffp == NULL) { xwarn("mcdx: no device for intr %d\n", irq); return; - } - + } #ifdef AK2 - if ( !stuffp->busy && stuffp->pending ) + if (!stuffp->busy && stuffp->pending) stuffp->int_err = 1; -#endif /* AK2 */ +#endif /* AK2 */ /* get the interrupt status */ b = inb((unsigned int) stuffp->rreg_status); stuffp->introk = ~b & MCDX_RBIT_DTEN; @@ -829,26 +884,23 @@ if (!stuffp->introk) { xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b); if (~b & MCDX_RBIT_STEN) { - xinfo( "intr() irq %d status 0x%02x\n", - irq, inb((unsigned int) stuffp->rreg_data)); + xinfo("intr() irq %d status 0x%02x\n", + irq, inb((unsigned int) stuffp->rreg_data)); } else { - xinfo( "intr() irq %d ambiguous hw status\n", irq); + xinfo("intr() irq %d ambiguous hw status\n", irq); } } else { xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b); - } + } - stuffp->busy = 0; - wake_up_interruptible(&stuffp->busyq); + stuffp->busy = 0; + wake_up_interruptible(&stuffp->busyq); } -static int -mcdx_talk ( - struct s_drive_stuff *stuffp, - const unsigned char *cmd, size_t cmdlen, - void *buffer, size_t size, - unsigned int timeout, int tries) +static int mcdx_talk(struct s_drive_stuff *stuffp, + const unsigned char *cmd, size_t cmdlen, + void *buffer, size_t size, unsigned int timeout, int tries) /* Send a command to the drive, wait for the result. * returns -1 on timeout, drive status otherwise * If buffer is not zero, the result (length size) is stored there. @@ -857,99 +909,108 @@ */ { int st; - char c; - int discard; + char c; + int discard; /* Somebody wants the data read? */ - if ((discard = (buffer == NULL))) buffer = &c; + if ((discard = (buffer == NULL))) + buffer = &c; - while (stuffp->lock) { + while (stuffp->lock) { xtrace(SLEEP, "*** talk: lockq\n"); interruptible_sleep_on(&stuffp->lockq); xtrace(SLEEP, "talk: awoken\n"); } - stuffp->lock = 1; + stuffp->lock = 1; /* An operation other then reading data destroys the - * data already requested and remembered in stuffp->request, ... */ - stuffp->valid = 0; + * data already requested and remembered in stuffp->request, ... */ + stuffp->valid = 0; #if MCDX_DEBUG & TALK { unsigned char i; - xtrace(TALK, "talk() %d / %d tries, res.size %d, command 0x%02x", - tries, timeout, size, (unsigned char) cmd[0]); - for (i = 1; i < cmdlen; i++) xtrace(TALK, " 0x%02x", cmd[i]); + xtrace(TALK, + "talk() %d / %d tries, res.size %d, command 0x%02x", + tries, timeout, size, (unsigned char) cmd[0]); + for (i = 1; i < cmdlen; i++) + xtrace(TALK, " 0x%02x", cmd[i]); xtrace(TALK, "\n"); } #endif - /* give up if all tries are done (bad) or if the status - * st != -1 (good) */ + /* give up if all tries are done (bad) or if the status + * st != -1 (good) */ for (st = -1; st == -1 && tries; tries--) { - char *bp = (char*) buffer; + char *bp = (char *) buffer; size_t sz = size; outsb((unsigned int) stuffp->wreg_data, cmd, cmdlen); - xtrace(TALK, "talk() command sent\n"); + xtrace(TALK, "talk() command sent\n"); - /* get the status byte */ - if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { - xinfo("talk() %02x timed out (status), %d tr%s left\n", - cmd[0], tries - 1, tries == 2 ? "y" : "ies"); - continue; - } - st = *bp; - sz--; - if (!discard) bp++; - - xtrace(TALK, "talk() got status 0x%02x\n", st); - - /* command error? */ - if (e_cmderr(st)) { - xwarn("command error cmd = %02x %s \n", - cmd[0], cmdlen > 1 ? "..." : ""); - st = -1; - continue; - } - - /* audio status? */ - if (stuffp->audiostatus == CDROM_AUDIO_INVALID) - stuffp->audiostatus = - e_audiobusy(st) ? CDROM_AUDIO_PLAY : CDROM_AUDIO_NO_STATUS; - else if (stuffp->audiostatus == CDROM_AUDIO_PLAY - && e_audiobusy(st) == 0) - stuffp->audiostatus = CDROM_AUDIO_COMPLETED; - - /* media change? */ - if (e_changed(st)) { - xinfo("talk() media changed\n"); - stuffp->xxx = stuffp->yyy = 1; - } - - /* now actually get the data */ - while (sz--) { - if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { - xinfo("talk() %02x timed out (data), %d tr%s left\n", - cmd[0], tries - 1, tries == 2 ? "y" : "ies"); - st = -1; break; - } - if (!discard) bp++; - xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1)); - } - } + /* get the status byte */ + if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { + xinfo("talk() %02x timed out (status), %d tr%s left\n", + cmd[0], tries - 1, tries == 2 ? "y" : "ies"); + continue; + } + st = *bp; + sz--; + if (!discard) + bp++; + + xtrace(TALK, "talk() got status 0x%02x\n", st); + + /* command error? */ + if (e_cmderr(st)) { + xwarn("command error cmd = %02x %s \n", + cmd[0], cmdlen > 1 ? "..." : ""); + st = -1; + continue; + } + + /* audio status? */ + if (stuffp->audiostatus == CDROM_AUDIO_INVALID) + stuffp->audiostatus = + e_audiobusy(st) ? CDROM_AUDIO_PLAY : + CDROM_AUDIO_NO_STATUS; + else if (stuffp->audiostatus == CDROM_AUDIO_PLAY + && e_audiobusy(st) == 0) + stuffp->audiostatus = CDROM_AUDIO_COMPLETED; + + /* media change? */ + if (e_changed(st)) { + xinfo("talk() media changed\n"); + stuffp->xxx = stuffp->yyy = 1; + } + + /* now actually get the data */ + while (sz--) { + if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { + xinfo("talk() %02x timed out (data), %d tr%s left\n", + cmd[0], tries - 1, + tries == 2 ? "y" : "ies"); + st = -1; + break; + } + if (!discard) + bp++; + xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1)); + } + } #if !MCDX_QUIET - if (!tries && st == -1) xinfo("talk() giving up\n"); + if (!tries && st == -1) + xinfo("talk() giving up\n"); #endif - stuffp->lock = 0; - wake_up_interruptible(&stuffp->lockq); + stuffp->lock = 0; + wake_up_interruptible(&stuffp->lockq); xtrace(TALK, "talk() done with 0x%02x\n", st); - return st; + return st; } /* MODULE STUFF ***********************************************************/ @@ -962,51 +1023,56 @@ int drives = 0; mcdx_init(); - for (i = 0; i < MCDX_NDRIVES; i++) { + for (i = 0; i < MCDX_NDRIVES; i++) { if (mcdx_stuffp[i]) { - xtrace(INIT, "init_module() drive %d stuff @ %p\n", - i, mcdx_stuffp[i]); + xtrace(INIT, "init_module() drive %d stuff @ %p\n", + i, mcdx_stuffp[i]); drives++; } } - if (!drives) + if (!drives) return -EIO; - return 0; + return 0; } void __exit mcdx_exit(void) { - int i; + int i; xinfo("cleanup_module called\n"); - for (i = 0; i < MCDX_NDRIVES; i++) { + for (i = 0; i < MCDX_NDRIVES; i++) { struct s_drive_stuff *stuffp; - if (unregister_cdrom(&mcdx_info)) { + if (unregister_cdrom(&mcdx_info)) { printk(KERN_WARNING "Can't unregister cdrom mcdx\n"); return; } stuffp = mcdx_stuffp[i]; - if (!stuffp) continue; - release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); + if (!stuffp) + continue; + release_region((unsigned long) stuffp->wreg_data, + MCDX_IO_SIZE); free_irq(stuffp->irq, NULL); if (stuffp->toc) { - xtrace(MALLOC, "cleanup_module() free toc @ %p\n", stuffp->toc); + xtrace(MALLOC, "cleanup_module() free toc @ %p\n", + stuffp->toc); kfree(stuffp->toc); } - xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n", stuffp); + xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n", + stuffp); mcdx_stuffp[i] = NULL; kfree(stuffp); - } + } - if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) { - xwarn("cleanup() unregister_blkdev() failed\n"); - } + if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) { + xwarn("cleanup() unregister_blkdev() failed\n"); + } blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); #if !MCDX_QUIET - else xinfo("cleanup() succeeded\n"); + else + xinfo("cleanup() succeeded\n"); #endif } @@ -1021,7 +1087,7 @@ int __init mcdx_init_drive(int drive) { struct s_version version; - struct s_drive_stuff* stuffp; + struct s_drive_stuff *stuffp; int size = sizeof(*stuffp); char msg[80]; @@ -1047,11 +1113,12 @@ /* setup our irq and i/o addresses */ stuffp->irq = irq(mcdx_drive_map[drive]); - stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]); + stuffp->wreg_data = stuffp->rreg_data = + port(mcdx_drive_map[drive]); stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1; stuffp->wreg_hcon = stuffp->wreg_reset + 1; stuffp->wreg_chn = stuffp->wreg_hcon + 1; - + init_waitqueue_head(&stuffp->busyq); init_waitqueue_head(&stuffp->lockq); init_waitqueue_head(&stuffp->sleepq); @@ -1066,7 +1133,7 @@ xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); kfree(stuffp); xtrace(INIT, "init() continue at next drive\n"); - return 0; /* next drive */ + return 0; /* next drive */ } xtrace(INIT, "init() i/o port is available at 0x%3p\n", @@ -1078,8 +1145,7 @@ if (-1 == mcdx_requestversion(stuffp, &version, 4)) { /* failed, next drive */ xwarn("%s=0x%3p,%d: Init failed. Can't get version.\n", - MCDX, - stuffp->wreg_data, stuffp->irq); + MCDX, stuffp->wreg_data, stuffp->irq); xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); kfree(stuffp); xtrace(INIT, "init() continue at next drive\n"); @@ -1088,35 +1154,35 @@ switch (version.code) { case 'D': - stuffp->readcmd = READ2X; - stuffp->present = DOUBLE | DOOR | MULTI; - break; + stuffp->readcmd = READ2X; + stuffp->present = DOUBLE | DOOR | MULTI; + break; case 'F': - stuffp->readcmd = READ1X; - stuffp->present = SINGLE | DOOR | MULTI; - break; + stuffp->readcmd = READ1X; + stuffp->present = SINGLE | DOOR | MULTI; + break; case 'M': - stuffp->readcmd = READ1X; - stuffp->present = SINGLE; - break; + stuffp->readcmd = READ1X; + stuffp->present = SINGLE; + break; default: - stuffp->present = 0; break; + stuffp->present = 0; + break; } - stuffp->playcmd = READ1X; + stuffp->playcmd = READ1X; if (!stuffp->present) { xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n", MCDX, stuffp->wreg_data, stuffp->irq); kfree(stuffp); - return 0; /* next drive */ + return 0; /* next drive */ } xtrace(INIT, "init() register blkdev\n"); if (devfs_register_blkdev(MAJOR_NR, "mcdx", &cdrom_fops) != 0) { xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n", - MCDX, - stuffp->wreg_data, stuffp->irq, MAJOR_NR); + MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR); kfree(stuffp); return 1; } @@ -1129,21 +1195,19 @@ mcdx_irq_map[stuffp->irq] = stuffp; if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) { xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n", - MCDX, - stuffp->wreg_data, stuffp->irq, stuffp->irq); + MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq); stuffp->irq = 0; blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); kfree(stuffp); return 0; } request_region((unsigned int) stuffp->wreg_data, - MCDX_IO_SIZE, - "mcdx"); + MCDX_IO_SIZE, "mcdx"); xtrace(INIT, "init() get garbage\n"); { int i; - mcdx_delay(stuffp, HZ/2); + mcdx_delay(stuffp, HZ / 2); for (i = 100; i; i--) (void) inb((unsigned int) stuffp->rreg_status); } @@ -1160,24 +1224,23 @@ stuffp->minor = drive; sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d." - " (Firmware version %c %x)\n", - stuffp->wreg_data, stuffp->irq, version.code, - version.ver); + " (Firmware version %c %x)\n", + stuffp->wreg_data, stuffp->irq, version.code, version.ver); mcdx_stuffp[drive] = stuffp; xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp); - mcdx_info.dev = MKDEV(MAJOR_NR,0); - if (register_cdrom(&mcdx_info) != 0) { + mcdx_info.dev = MKDEV(MAJOR_NR, 0); + if (register_cdrom(&mcdx_info) != 0) { printk("Cannot register Mitsumi CD-ROM!\n"); release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); free_irq(stuffp->irq, NULL); kfree(stuffp); if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) - xwarn("cleanup() unregister_blkdev() failed\n"); + xwarn("cleanup() unregister_blkdev() failed\n"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); return 2; - } - printk(msg); + } + printk(msg); return 0; } @@ -1198,7 +1261,7 @@ /* do the initialisation */ for (drive = 0; drive < MCDX_NDRIVES; drive++) { - switch(mcdx_init_drive(drive)) { + switch (mcdx_init_drive(drive)) { case 2: return -EIO; case 1: @@ -1208,9 +1271,8 @@ return 0; } -static int -mcdx_transfer(struct s_drive_stuff *stuffp, - char *p, int sector, int nr_sectors) +static int mcdx_transfer(struct s_drive_stuff *stuffp, + char *p, int sector, int nr_sectors) /* This seems to do the actually transfer. But it does more. It keeps track of errors occurred and will (if possible) fall back to single speed on error. @@ -1222,8 +1284,10 @@ ans = mcdx_xfer(stuffp, p, sector, nr_sectors); return ans; #if FALLBACK - if (-1 == ans) stuffp->readerrs++; - else return ans; + if (-1 == ans) + stuffp->readerrs++; + else + return ans; if (stuffp->readerrs && stuffp->readcmd == READ1X) { xwarn("XXX Already reading 1x -- no chance\n"); @@ -1240,99 +1304,109 @@ static int mcdx_xfer(struct s_drive_stuff *stuffp, - char *p, int sector, int nr_sectors) + char *p, int sector, int nr_sectors) /* This does actually the transfer from the drive. Return: -1 on timeout or other error else status byte (as in stuff->st) */ { - int border; - int done = 0; + int border; + int done = 0; long timeout; if (stuffp->audio) { - xwarn("Attempt to read from audio CD.\n"); - return -1; + xwarn("Attempt to read from audio CD.\n"); + return -1; } if (!stuffp->readcmd) { - xinfo("Can't transfer from missing disk.\n"); - return -1; + xinfo("Can't transfer from missing disk.\n"); + return -1; } - while (stuffp->lock) { + while (stuffp->lock) { interruptible_sleep_on(&stuffp->lockq); } - if (stuffp->valid - && (sector >= stuffp->pending) - && (sector < stuffp->low_border)) { + if (stuffp->valid && (sector >= stuffp->pending) + && (sector < stuffp->low_border)) { /* All (or at least a part of the sectors requested) seems - * to be already requested, so we don't need to bother the - * drive with new requests ... - * Wait for the drive become idle, but first - * check for possible occurred errors --- the drive - * seems to report them asynchronously */ - - - border = stuffp->high_border < (border = sector + nr_sectors) - ? stuffp->high_border : border; - - stuffp->lock = current->pid; - - do { - - while (stuffp->busy) { - - timeout = interruptible_sleep_on_timeout(&stuffp->busyq, 5*HZ); + * to be already requested, so we don't need to bother the + * drive with new requests ... + * Wait for the drive become idle, but first + * check for possible occurred errors --- the drive + * seems to report them asynchronously */ + + + border = stuffp->high_border < (border = + sector + nr_sectors) + ? stuffp->high_border : border; + + stuffp->lock = current->pid; + + do { + + while (stuffp->busy) { + + timeout = + interruptible_sleep_on_timeout + (&stuffp->busyq, 5 * HZ); + + if (!stuffp->introk) { + xtrace(XFER, + "error via interrupt\n"); + } else if (!timeout) { + xtrace(XFER, "timeout\n"); + } else if (signal_pending(current)) { + xtrace(XFER, "signal\n"); + } else + continue; + + stuffp->lock = 0; + stuffp->busy = 0; + stuffp->valid = 0; + + wake_up_interruptible(&stuffp->lockq); + xtrace(XFER, "transfer() done (-1)\n"); + return -1; + } - if (!stuffp->introk) { xtrace(XFER, "error via interrupt\n"); } - else if (!timeout) { xtrace(XFER, "timeout\n"); } - else if (signal_pending(current)) { - xtrace(XFER, "signal\n"); - } else continue; + /* check if we need to set the busy flag (as we + * expect an interrupt */ + stuffp->busy = (3 == (stuffp->pending & 3)); + + /* Test if it's the first sector of a block, + * there we have to skip some bytes as we read raw data */ + if (stuffp->xa && (0 == (stuffp->pending & 3))) { + const int HEAD = + CD_FRAMESIZE_RAW - CD_XA_TAIL - + CD_FRAMESIZE; + insb((unsigned int) stuffp->rreg_data, p, + HEAD); + } - stuffp->lock = 0; - stuffp->busy = 0; - stuffp->valid = 0; + /* now actually read the data */ + insb((unsigned int) stuffp->rreg_data, p, 512); - wake_up_interruptible(&stuffp->lockq); - xtrace(XFER, "transfer() done (-1)\n"); - return -1; - } + /* test if it's the last sector of a block, + * if so, we have to handle XA special */ + if ((3 == (stuffp->pending & 3)) && stuffp->xa) { + char dummy[CD_XA_TAIL]; + insb((unsigned int) stuffp->rreg_data, + &dummy[0], CD_XA_TAIL); + } - /* check if we need to set the busy flag (as we - * expect an interrupt */ - stuffp->busy = (3 == (stuffp->pending & 3)); - - /* Test if it's the first sector of a block, - * there we have to skip some bytes as we read raw data */ - if (stuffp->xa && (0 == (stuffp->pending & 3))) { - const int HEAD = CD_FRAMESIZE_RAW - CD_XA_TAIL - CD_FRAMESIZE; - insb((unsigned int) stuffp->rreg_data, p, HEAD); - } - - /* now actually read the data */ - insb((unsigned int) stuffp->rreg_data, p, 512); - - /* test if it's the last sector of a block, - * if so, we have to handle XA special */ - if ((3 == (stuffp->pending & 3)) && stuffp->xa) { - char dummy[CD_XA_TAIL]; - insb((unsigned int) stuffp->rreg_data, &dummy[0], CD_XA_TAIL); - } - - if (stuffp->pending == sector) { - p += 512; - done++; - sector++; - } - } while (++(stuffp->pending) < border); + if (stuffp->pending == sector) { + p += 512; + done++; + sector++; + } + } while (++(stuffp->pending) < border); - stuffp->lock = 0; - wake_up_interruptible(&stuffp->lockq); + stuffp->lock = 0; + wake_up_interruptible(&stuffp->lockq); - } else { + } else { /* The requested sector(s) is/are out of the * already requested range, so we have to bother the drive @@ -1352,8 +1426,9 @@ /* do some sanity checks */ if (stuffp->pending > stuffp->lastsector) { - xwarn("transfer() sector %d from nirvana requested.\n", - stuffp->pending); + xwarn + ("transfer() sector %d from nirvana requested.\n", + stuffp->pending); stuffp->status = MCDX_ST_EOM; stuffp->valid = 0; xtrace(XFER, "transfer() done (-1)\n"); @@ -1361,17 +1436,17 @@ } if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE) - > stuffp->lastsector + 1) { + > stuffp->lastsector + 1) { xtrace(XFER, "cut low_border\n"); stuffp->low_border = stuffp->lastsector + 1; } if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE) - > stuffp->lastsector + 1) { - xtrace(XFER, "cut high_border\n"); + > stuffp->lastsector + 1) { + xtrace(XFER, "cut high_border\n"); stuffp->high_border = stuffp->lastsector + 1; } - { /* Convert the sector to be requested to MSF format */ + { /* Convert the sector to be requested to MSF format */ struct cdrom_msf0 pending; log2msf(stuffp->pending / 4, &pending); cmd[1] = pending.minute; @@ -1379,59 +1454,71 @@ cmd[3] = pending.frame; } - cmd[6] = (unsigned char) ((stuffp->high_border - stuffp->pending) / 4); + cmd[6] = + (unsigned + char) ((stuffp->high_border - stuffp->pending) / 4); xtrace(XFER, "[%2d]\n", cmd[6]); stuffp->busy = 1; /* Now really issue the request command */ outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd); - } + } #ifdef AK2 - if ( stuffp->int_err ) { + if (stuffp->int_err) { stuffp->valid = 0; stuffp->int_err = 0; return -1; } -#endif /* AK2 */ +#endif /* AK2 */ - stuffp->low_border = (stuffp->low_border += done) < stuffp->high_border - ? stuffp->low_border : stuffp->high_border; + stuffp->low_border = (stuffp->low_border += + done) < + stuffp->high_border ? stuffp->low_border : stuffp->high_border; - return done; + return done; } /* Access to elements of the mcdx_drive_map members */ -static char* port(int *ip) { return (char*) ip[0]; } -static int irq(int *ip) { return ip[1]; } +static char *port(int *ip) +{ + return (char *) ip[0]; +} +static int irq(int *ip) +{ + return ip[1]; +} /* Misc number converters */ static unsigned int bcd2uint(unsigned char c) -{ return (c >> 4) * 10 + (c & 0x0f); } +{ + return (c >> 4) * 10 + (c & 0x0f); +} static unsigned int uint2bcd(unsigned int ival) -{ return ((ival / 10) << 4) | (ival % 10); } +{ + return ((ival / 10) << 4) | (ival % 10); +} -static void log2msf(unsigned int l, struct cdrom_msf0* pmsf) +static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf) { - l += CD_MSF_OFFSET; - pmsf->minute = uint2bcd(l / 4500), l %= 4500; - pmsf->second = uint2bcd(l / 75); - pmsf->frame = uint2bcd(l % 75); + l += CD_MSF_OFFSET; + pmsf->minute = uint2bcd(l / 4500), l %= 4500; + pmsf->second = uint2bcd(l / 75); + pmsf->frame = uint2bcd(l % 75); } -static unsigned int msf2log(const struct cdrom_msf0* pmsf) +static unsigned int msf2log(const struct cdrom_msf0 *pmsf) { - return bcd2uint(pmsf->frame) - + bcd2uint(pmsf->second) * 75 - + bcd2uint(pmsf->minute) * 4500 - - CD_MSF_OFFSET; + return bcd2uint(pmsf->frame) + + bcd2uint(pmsf->second) * 75 + + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET; } -int mcdx_readtoc(struct s_drive_stuff* stuffp) +int mcdx_readtoc(struct s_drive_stuff *stuffp) /* Read the toc entries from the CD, * Return: -1 on failure, else 0 */ { @@ -1442,17 +1529,21 @@ } xtrace(READTOC, "ioctl() readtoc for %d tracks\n", - stuffp->di.n_last - stuffp->di.n_first + 1); + stuffp->di.n_last - stuffp->di.n_first + 1); - if (-1 == mcdx_hold(stuffp, 1)) return -1; + if (-1 == mcdx_hold(stuffp, 1)) + return -1; xtrace(READTOC, "ioctl() tocmode\n"); - if (-1 == mcdx_setdrivemode(stuffp, TOC, 1)) return -EIO; + if (-1 == mcdx_setdrivemode(stuffp, TOC, 1)) + return -EIO; /* all seems to be ok so far ... malloc */ { int size; - size = sizeof(struct s_subqcode) * (stuffp->di.n_last - stuffp->di.n_first + 2); + size = + sizeof(struct s_subqcode) * (stuffp->di.n_last - + stuffp->di.n_first + 2); xtrace(MALLOC, "ioctl() malloc %d bytes\n", size); stuffp->toc = kmalloc(size, GFP_KERNEL); @@ -1469,11 +1560,11 @@ int retries; for (trk = 0; - trk < (stuffp->di.n_last - stuffp->di.n_first + 1); - trk++) + trk < (stuffp->di.n_last - stuffp->di.n_first + 1); + trk++) stuffp->toc[trk].index = 0; - for (retries = 300; retries; retries--) { /* why 300? */ + for (retries = 300; retries; retries--) { /* why 300? */ struct s_subqcode q; unsigned int idx; @@ -1485,19 +1576,24 @@ idx = bcd2uint(q.index); if ((idx > 0) - && (idx <= stuffp->di.n_last) - && (q.tno == 0) - && (stuffp->toc[idx - stuffp->di.n_first].index == 0)) { + && (idx <= stuffp->di.n_last) + && (q.tno == 0) + && (stuffp->toc[idx - stuffp->di.n_first]. + index == 0)) { stuffp->toc[idx - stuffp->di.n_first] = q; - xtrace(READTOC, "ioctl() toc idx %d (trk %d)\n", idx, trk); + xtrace(READTOC, + "ioctl() toc idx %d (trk %d)\n", + idx, trk); trk--; } - if (trk == 0) break; + if (trk == 0) + break; } - memset(&stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1], - 0, sizeof(stuffp->toc[0])); - stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1].dt - = stuffp->di.msf_leadout; + memset(&stuffp-> + toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0, + sizeof(stuffp->toc[0])); + stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + + 1].dt = stuffp->di.msf_leadout; } /* unset toc mode */ @@ -1506,16 +1602,23 @@ return -EIO; #if MCDX_DEBUG && READTOC - { int trk; - for (trk = 0; - trk < (stuffp->di.n_last - stuffp->di.n_first + 2); - trk++) - xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x" - " %02x:%02x.%02x %02x:%02x.%02x\n", - trk + stuffp->di.n_first, - stuffp->toc[trk].control, stuffp->toc[trk].tno, stuffp->toc[trk].index, - stuffp->toc[trk].tt.minute, stuffp->toc[trk].tt.second, stuffp->toc[trk].tt.frame, - stuffp->toc[trk].dt.minute, stuffp->toc[trk].dt.second, stuffp->toc[trk].dt.frame); + { + int trk; + for (trk = 0; + trk < (stuffp->di.n_last - stuffp->di.n_first + 2); + trk++) + xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x" + " %02x:%02x.%02x %02x:%02x.%02x\n", + trk + stuffp->di.n_first, + stuffp->toc[trk].control, + stuffp->toc[trk].tno, + stuffp->toc[trk].index, + stuffp->toc[trk].tt.minute, + stuffp->toc[trk].tt.second, + stuffp->toc[trk].tt.frame, + stuffp->toc[trk].dt.minute, + stuffp->toc[trk].dt.second, + stuffp->toc[trk].dt.frame); } #endif @@ -1523,109 +1626,110 @@ } static int -mcdx_playmsf(struct s_drive_stuff* stuffp, const struct cdrom_msf* msf) +mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf) { - unsigned char cmd[7] = { - 0, 0, 0, 0, 0, 0, 0 - }; + unsigned char cmd[7] = { + 0, 0, 0, 0, 0, 0, 0 + }; if (!stuffp->readcmd) { xinfo("Can't play from missing disk.\n"); return -1; } - cmd[0] = stuffp->playcmd; + cmd[0] = stuffp->playcmd; + + cmd[1] = msf->cdmsf_min0; + cmd[2] = msf->cdmsf_sec0; + cmd[3] = msf->cdmsf_frame0; + cmd[4] = msf->cdmsf_min1; + cmd[5] = msf->cdmsf_sec1; + cmd[6] = msf->cdmsf_frame1; + + xtrace(PLAYMSF, "ioctl(): play %x " + "%02x:%02x:%02x -- %02x:%02x:%02x\n", + cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]); - cmd[1] = msf->cdmsf_min0; - cmd[2] = msf->cdmsf_sec0; - cmd[3] = msf->cdmsf_frame0; - cmd[4] = msf->cdmsf_min1; - cmd[5] = msf->cdmsf_sec1; - cmd[6] = msf->cdmsf_frame1; - - xtrace(PLAYMSF, "ioctl(): play %x " - "%02x:%02x:%02x -- %02x:%02x:%02x\n", - cmd[0], cmd[1], cmd[2], cmd[3], - cmd[4], cmd[5], cmd[6]); - - outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd); - - if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) { - xwarn("playmsf() timeout\n"); - return -1; - } + outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd); - stuffp->audiostatus = CDROM_AUDIO_PLAY; - return 0; + if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) { + xwarn("playmsf() timeout\n"); + return -1; + } + + stuffp->audiostatus = CDROM_AUDIO_PLAY; + return 0; } static int -mcdx_playtrk(struct s_drive_stuff* stuffp, const struct cdrom_ti* ti) +mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti) { - struct s_subqcode* p; - struct cdrom_msf msf; - - if (-1 == mcdx_readtoc(stuffp)) return -1; - - if (ti) p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first]; - else p = &stuffp->start; + struct s_subqcode *p; + struct cdrom_msf msf; - msf.cdmsf_min0 = p->dt.minute; - msf.cdmsf_sec0 = p->dt.second; - msf.cdmsf_frame0 = p->dt.frame; - - if (ti) { - p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1]; - stuffp->stop = *p; - } else p = &stuffp->stop; + if (-1 == mcdx_readtoc(stuffp)) + return -1; - msf.cdmsf_min1 = p->dt.minute; - msf.cdmsf_sec1 = p->dt.second; - msf.cdmsf_frame1 = p->dt.frame; + if (ti) + p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first]; + else + p = &stuffp->start; + + msf.cdmsf_min0 = p->dt.minute; + msf.cdmsf_sec0 = p->dt.second; + msf.cdmsf_frame0 = p->dt.frame; + + if (ti) { + p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1]; + stuffp->stop = *p; + } else + p = &stuffp->stop; + + msf.cdmsf_min1 = p->dt.minute; + msf.cdmsf_sec1 = p->dt.second; + msf.cdmsf_frame1 = p->dt.frame; - return mcdx_playmsf(stuffp, &msf); + return mcdx_playmsf(stuffp, &msf); } /* Drive functions ************************************************/ -static int -mcdx_tray_move(struct cdrom_device_info * cdi, int position) +static int mcdx_tray_move(struct cdrom_device_info *cdi, int position) { - struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)]; + struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)]; - if (!stuffp->present) + if (!stuffp->present) return -ENXIO; if (!(stuffp->present & DOOR)) - return -ENOSYS; + return -ENOSYS; - if (position) /* 1: eject */ - return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3); - else /* 0: close */ - return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3); - return 1; + if (position) /* 1: eject */ + return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3); + else /* 0: close */ + return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3); + return 1; } -static int -mcdx_stop(struct s_drive_stuff *stuffp, int tries) -{ return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries); } +static int mcdx_stop(struct s_drive_stuff *stuffp, int tries) +{ + return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries); +} -static int -mcdx_hold(struct s_drive_stuff *stuffp, int tries) -{ return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries); } +static int mcdx_hold(struct s_drive_stuff *stuffp, int tries) +{ + return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries); +} -static int -mcdx_requestsubqcode(struct s_drive_stuff *stuffp, - struct s_subqcode *sub, - int tries) +static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp, + struct s_subqcode *sub, int tries) { char buf[11]; int ans; - if (-1 == (ans = mcdx_talk( - stuffp, "\x20", 1, buf, sizeof(buf), - 2 * HZ, tries))) - return -1; + if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf), + 2 * HZ, tries))) + return -1; sub->control = buf[1]; sub->tno = buf[2]; sub->index = buf[3]; @@ -1639,31 +1743,34 @@ return ans; } -static int -mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp, struct s_multi *multi, int tries) +static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp, + struct s_multi *multi, int tries) { char buf[5]; int ans; - if (stuffp->present & MULTI) { - ans = mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ, tries); + if (stuffp->present & MULTI) { + ans = + mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ, + tries); multi->multi = buf[1]; - multi->msf_last.minute = buf[2]; - multi->msf_last.second = buf[3]; - multi->msf_last.frame = buf[4]; - return ans; - } else { - multi->multi = 0; - return 0; - } + multi->msf_last.minute = buf[2]; + multi->msf_last.second = buf[3]; + multi->msf_last.frame = buf[4]; + return ans; + } else { + multi->multi = 0; + return 0; + } } -static int -mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info, int tries) +static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info, + int tries) { char buf[9]; int ans; - ans = mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries); + ans = + mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries); if (ans == -1) { info->n_first = 0; info->n_last = 0; @@ -1680,8 +1787,8 @@ return ans; } -static int -mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, int tries) +static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, + int tries) { char cmd[2]; int ans; @@ -1692,32 +1799,47 @@ return -1; switch (mode) { - case TOC: cmd[1] |= 0x04; break; - case DATA: cmd[1] &= ~0x04; break; - case RAW: cmd[1] |= 0x40; break; - case COOKED: cmd[1] &= ~0x40; break; - default: break; + case TOC: + cmd[1] |= 0x04; + break; + case DATA: + cmd[1] &= ~0x04; + break; + case RAW: + cmd[1] |= 0x40; + break; + case COOKED: + cmd[1] &= ~0x40; + break; + default: + break; } cmd[0] = 0x50; return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries); } -static int -mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode, int tries) +static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode, + int tries) { unsigned char cmd[2] = { 0xa0 }; xtrace(HW, "setdatamode() %d\n", mode); switch (mode) { - case MODE0: cmd[1] = 0x00; break; - case MODE1: cmd[1] = 0x01; break; - case MODE2: cmd[1] = 0x02; break; - default: return -EINVAL; + case MODE0: + cmd[1] = 0x00; + break; + case MODE1: + cmd[1] = 0x01; + break; + case MODE2: + cmd[1] = 0x02; + break; + default: + return -EINVAL; } return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries); } -static int -mcdx_config(struct s_drive_stuff *stuffp, int tries) +static int mcdx_config(struct s_drive_stuff *stuffp, int tries) { char cmd[4]; @@ -1737,14 +1859,14 @@ return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries); } -static int -mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver, int tries) +static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver, + int tries) { char buf[3]; int ans; if (-1 == (ans = mcdx_talk(stuffp, "\xdc", - 1, buf, sizeof(buf), 2 * HZ, tries))) + 1, buf, sizeof(buf), 2 * HZ, tries))) return ans; ver->code = buf[1]; @@ -1753,65 +1875,66 @@ return ans; } -static int -mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries) +static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries) { if (mode == HARD) { - outb(0, (unsigned int) stuffp->wreg_chn); /* no dma, no irq -> hardware */ - outb(0, (unsigned int) stuffp->wreg_reset); /* hw reset */ + outb(0, (unsigned int) stuffp->wreg_chn); /* no dma, no irq -> hardware */ + outb(0, (unsigned int) stuffp->wreg_reset); /* hw reset */ return 0; - } else return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries); + } else + return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries); } -static int mcdx_lockdoor(struct cdrom_device_info * cdi, int lock) +static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock) { - struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)]; + struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)]; char cmd[2] = { 0xfe }; - if (!(stuffp->present & DOOR)) + if (!(stuffp->present & DOOR)) return -ENOSYS; - if (stuffp->present & DOOR) { - cmd[1] = lock ? 0x01 : 0x00; - return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3); - } else return 0; + if (stuffp->present & DOOR) { + cmd[1] = lock ? 0x01 : 0x00; + return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3); + } else + return 0; } -static int -mcdx_getstatus(struct s_drive_stuff *stuffp, int tries) -{ return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries); } +static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries) +{ + return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries); +} static int -mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char* buf) +mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf) { - unsigned long timeout = to + jiffies; - char c; + unsigned long timeout = to + jiffies; + char c; - if (!buf) buf = &c; + if (!buf) + buf = &c; - while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) { - if (time_after(jiffies, timeout)) return -1; - mcdx_delay(stuffp, delay); - } + while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) { + if (time_after(jiffies, timeout)) + return -1; + mcdx_delay(stuffp, delay); + } - *buf = (unsigned char) inb((unsigned int) stuffp->rreg_data) & 0xff; + *buf = (unsigned char) inb((unsigned int) stuffp->rreg_data) & 0xff; - return 0; + return 0; } -static int -mcdx_setattentuator( - struct s_drive_stuff* stuffp, - struct cdrom_volctrl* vol, - int tries) -{ - char cmd[5]; - cmd[0] = 0xae; - cmd[1] = vol->channel0; - cmd[2] = 0; - cmd[3] = vol->channel1; - cmd[4] = 0; +static int mcdx_setattentuator(struct s_drive_stuff *stuffp, + struct cdrom_volctrl *vol, int tries) +{ + char cmd[5]; + cmd[0] = 0xae; + cmd[1] = vol->channel0; + cmd[2] = 0; + cmd[3] = vol->channel1; + cmd[4] = 0; - return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries); + return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries); } -/* ex:set ts=4 sw=4 ai si: */ +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c --- v2.4.9/linux/drivers/cdrom/sjcd.c Thu Oct 26 23:35:48 2000 +++ linux/drivers/cdrom/sjcd.c Fri Sep 7 09:28:38 2001 @@ -82,13 +82,13 @@ static int sjcd_present = 0; -#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */ +#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */ /* * buffer for block size conversion */ -static char sjcd_buf[ 2048 * SJCD_BUF_SIZ ]; -static volatile int sjcd_buf_bn[ SJCD_BUF_SIZ ], sjcd_next_bn; +static char sjcd_buf[2048 * SJCD_BUF_SIZ]; +static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn; static volatile int sjcd_buf_in, sjcd_buf_out = -1; /* @@ -113,9 +113,7 @@ static int sjcd_base = SJCD_BASE_ADDR; -#ifdef MODULE MODULE_PARM(sjcd_base, "i"); -#endif static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq); @@ -125,13 +123,13 @@ static volatile unsigned short sjcd_transfer_is_active = 0; enum sjcd_transfer_state { - SJCD_S_IDLE = 0, - SJCD_S_START = 1, - SJCD_S_MODE = 2, - SJCD_S_READ = 3, - SJCD_S_DATA = 4, - SJCD_S_STOP = 5, - SJCD_S_STOPPING = 6 + SJCD_S_IDLE = 0, + SJCD_S_START = 1, + SJCD_S_MODE = 2, + SJCD_S_READ = 3, + SJCD_S_DATA = 4, + SJCD_S_STOP = 5, + SJCD_S_STOPPING = 6 }; static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE; static long sjcd_transfer_timeout = 0; @@ -166,14 +164,14 @@ * base address. */ #ifndef MODULE -static int __init sjcd_setup( char *str) +static int __init sjcd_setup(char *str) { - int ints[2]; - (void)get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] > 0) - sjcd_base = ints[1]; + int ints[2]; + (void) get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] > 0) + sjcd_base = ints[1]; - return 1; + return 1; } __setup("sjcd=", sjcd_setup); @@ -183,168 +181,191 @@ /* * Special converters. */ -static unsigned char bin2bcd( int bin ){ - int u, v; +static unsigned char bin2bcd(int bin) +{ + int u, v; - u = bin % 10; v = bin / 10; - return( u | ( v << 4 ) ); + u = bin % 10; + v = bin / 10; + return (u | (v << 4)); } -static int bcd2bin( unsigned char bcd ){ - return( ( bcd >> 4 ) * 10 + ( bcd & 0x0F ) ); +static int bcd2bin(unsigned char bcd) +{ + return ((bcd >> 4) * 10 + (bcd & 0x0F)); } -static long msf2hsg( struct msf *mp ){ - return( bcd2bin( mp->frame ) + bcd2bin( mp->sec ) * 75 - + bcd2bin( mp->min ) * 4500 - 150 ); +static long msf2hsg(struct msf *mp) +{ + return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75 + + bcd2bin(mp->min) * 4500 - 150); } -static void hsg2msf( long hsg, struct msf *msf ){ - hsg += 150; msf->min = hsg / 4500; - hsg %= 4500; msf->sec = hsg / 75; msf->frame = hsg % 75; - msf->min = bin2bcd( msf->min ); /* convert to BCD */ - msf->sec = bin2bcd( msf->sec ); - msf->frame = bin2bcd( msf->frame ); +static void hsg2msf(long hsg, struct msf *msf) +{ + hsg += 150; + msf->min = hsg / 4500; + hsg %= 4500; + msf->sec = hsg / 75; + msf->frame = hsg % 75; + msf->min = bin2bcd(msf->min); /* convert to BCD */ + msf->sec = bin2bcd(msf->sec); + msf->frame = bin2bcd(msf->frame); } /* * Send a command to cdrom. Invalidate status. */ -static void sjcd_send_cmd( unsigned char cmd ){ +static void sjcd_send_cmd(unsigned char cmd) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: send_cmd( 0x%x )\n", cmd ); + printk("SJCD: send_cmd( 0x%x )\n", cmd); #endif - outb( cmd, SJCDPORT( 0 ) ); - sjcd_command_is_in_progress = 1; - sjcd_status_valid = 0; - sjcd_command_failed = 0; + outb(cmd, SJCDPORT(0)); + sjcd_command_is_in_progress = 1; + sjcd_status_valid = 0; + sjcd_command_failed = 0; } /* * Send a command with one arg to cdrom. Invalidate status. */ -static void sjcd_send_1_cmd( unsigned char cmd, unsigned char a ){ +static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a ); + printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a); #endif - outb( cmd, SJCDPORT( 0 ) ); - outb( a, SJCDPORT( 0 ) ); - sjcd_command_is_in_progress = 1; - sjcd_status_valid = 0; - sjcd_command_failed = 0; + outb(cmd, SJCDPORT(0)); + outb(a, SJCDPORT(0)); + sjcd_command_is_in_progress = 1; + sjcd_status_valid = 0; + sjcd_command_failed = 0; } /* * Send a command with four args to cdrom. Invalidate status. */ -static void sjcd_send_4_cmd( unsigned char cmd, unsigned char a, - unsigned char b, unsigned char c, unsigned char d ){ +static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a, + unsigned char b, unsigned char c, + unsigned char d) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: send_4_cmd( 0x%x )\n", cmd ); + printk("SJCD: send_4_cmd( 0x%x )\n", cmd); #endif - outb( cmd, SJCDPORT( 0 ) ); - outb( a, SJCDPORT( 0 ) ); - outb( b, SJCDPORT( 0 ) ); - outb( c, SJCDPORT( 0 ) ); - outb( d, SJCDPORT( 0 ) ); - sjcd_command_is_in_progress = 1; - sjcd_status_valid = 0; - sjcd_command_failed = 0; + outb(cmd, SJCDPORT(0)); + outb(a, SJCDPORT(0)); + outb(b, SJCDPORT(0)); + outb(c, SJCDPORT(0)); + outb(d, SJCDPORT(0)); + sjcd_command_is_in_progress = 1; + sjcd_status_valid = 0; + sjcd_command_failed = 0; } /* * Send a play or read command to cdrom. Invalidate Status. */ -static void sjcd_send_6_cmd( unsigned char cmd, struct sjcd_play_msf *pms ){ +static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: send_long_cmd( 0x%x )\n", cmd ); + printk("SJCD: send_long_cmd( 0x%x )\n", cmd); #endif - outb( cmd, SJCDPORT( 0 ) ); - outb( pms->start.min, SJCDPORT( 0 ) ); - outb( pms->start.sec, SJCDPORT( 0 ) ); - outb( pms->start.frame, SJCDPORT( 0 ) ); - outb( pms->end.min, SJCDPORT( 0 ) ); - outb( pms->end.sec, SJCDPORT( 0 ) ); - outb( pms->end.frame, SJCDPORT( 0 ) ); - sjcd_command_is_in_progress = 1; - sjcd_status_valid = 0; - sjcd_command_failed = 0; + outb(cmd, SJCDPORT(0)); + outb(pms->start.min, SJCDPORT(0)); + outb(pms->start.sec, SJCDPORT(0)); + outb(pms->start.frame, SJCDPORT(0)); + outb(pms->end.min, SJCDPORT(0)); + outb(pms->end.sec, SJCDPORT(0)); + outb(pms->end.frame, SJCDPORT(0)); + sjcd_command_is_in_progress = 1; + sjcd_status_valid = 0; + sjcd_command_failed = 0; } /* * Get a value from the data port. Should not block, so we use a little * wait for a while. Returns 0 if OK. */ -static int sjcd_load_response( void *buf, int len ){ - unsigned char *resp = ( unsigned char * )buf; +static int sjcd_load_response(void *buf, int len) +{ + unsigned char *resp = (unsigned char *) buf; - for( ; len; --len ){ - int i; - for( i = 200; i-- && !SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ); ); - if( i > 0 ) *resp++ = ( unsigned char )inb( SJCDPORT( 0 ) ); - else break; - } - return( len ); + for (; len; --len) { + int i; + for (i = 200; + i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)));); + if (i > 0) + *resp++ = (unsigned char) inb(SJCDPORT(0)); + else + break; + } + return (len); } /* * Load and parse command completion status (drive info byte and maybe error). * Sorry, no error classification yet. */ -static void sjcd_load_status( void ){ - sjcd_media_is_changed = 0; - sjcd_completion_error = 0; - sjcd_completion_status = inb( SJCDPORT( 0 ) ); - if( sjcd_completion_status & SST_DOOR_OPENED ){ - sjcd_door_closed = sjcd_media_is_available = 0; - } else { - sjcd_door_closed = 1; - if( sjcd_completion_status & SST_MEDIA_CHANGED ) - sjcd_media_is_available = sjcd_media_is_changed = 1; - else if( sjcd_completion_status & 0x0F ){ - /* - * OK, we seem to catch an error ... - */ - while( !SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ) ); - sjcd_completion_error = inb( SJCDPORT( 0 ) ); - if( ( sjcd_completion_status & 0x08 ) && - ( sjcd_completion_error & 0x40 ) ) - sjcd_media_is_available = 0; - else sjcd_command_failed = 1; - } else sjcd_media_is_available = 1; - } - /* - * Ok, status loaded successfully. - */ - sjcd_status_valid = 1, sjcd_error_reported = 0; - sjcd_command_is_in_progress = 0; - - /* - * If the disk is changed, the TOC is not valid. - */ - if( sjcd_media_is_changed ) sjcd_toc_uptodate = 0; +static void sjcd_load_status(void) +{ + sjcd_media_is_changed = 0; + sjcd_completion_error = 0; + sjcd_completion_status = inb(SJCDPORT(0)); + if (sjcd_completion_status & SST_DOOR_OPENED) { + sjcd_door_closed = sjcd_media_is_available = 0; + } else { + sjcd_door_closed = 1; + if (sjcd_completion_status & SST_MEDIA_CHANGED) + sjcd_media_is_available = sjcd_media_is_changed = + 1; + else if (sjcd_completion_status & 0x0F) { + /* + * OK, we seem to catch an error ... + */ + while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))); + sjcd_completion_error = inb(SJCDPORT(0)); + if ((sjcd_completion_status & 0x08) && + (sjcd_completion_error & 0x40)) + sjcd_media_is_available = 0; + else + sjcd_command_failed = 1; + } else + sjcd_media_is_available = 1; + } + /* + * Ok, status loaded successfully. + */ + sjcd_status_valid = 1, sjcd_error_reported = 0; + sjcd_command_is_in_progress = 0; + + /* + * If the disk is changed, the TOC is not valid. + */ + if (sjcd_media_is_changed) + sjcd_toc_uptodate = 0; #if defined( SJCD_TRACE ) - printk( "SJCD: status %02x.%02x loaded.\n", - ( int )sjcd_completion_status, ( int )sjcd_completion_error ); + printk("SJCD: status %02x.%02x loaded.\n", + (int) sjcd_completion_status, (int) sjcd_completion_error); #endif } /* * Read status from cdrom. Check to see if the status is available. */ -static int sjcd_check_status( void ){ - /* - * Try to load the response from cdrom into buffer. - */ - if( SJCD_STATUS_AVAILABLE( inb( SJCDPORT( 1 ) ) ) ){ - sjcd_load_status(); - return( 1 ); - } else { - /* - * No status is available. - */ - return( 0 ); - } +static int sjcd_check_status(void) +{ + /* + * Try to load the response from cdrom into buffer. + */ + if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) { + sjcd_load_status(); + return (1); + } else { + /* + * No status is available. + */ + return (0); + } } /* @@ -359,575 +380,692 @@ */ #define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000 -static void sjcd_status_timer( void ){ - if( sjcd_check_status() ){ - /* - * The command completed and status is loaded, stop waiting. - */ - wake_up( &sjcd_waitq ); - } else if( --sjcd_status_timeout <= 0 ){ - /* - * We are timed out. - */ - wake_up( &sjcd_waitq ); - } else { - /* - * We have still some time to wait. Try again. - */ - SJCD_SET_TIMER( sjcd_status_timer, 1 ); - } +static void sjcd_status_timer(void) +{ + if (sjcd_check_status()) { + /* + * The command completed and status is loaded, stop waiting. + */ + wake_up(&sjcd_waitq); + } else if (--sjcd_status_timeout <= 0) { + /* + * We are timed out. + */ + wake_up(&sjcd_waitq); + } else { + /* + * We have still some time to wait. Try again. + */ + SJCD_SET_TIMER(sjcd_status_timer, 1); + } } /* * Wait for status for 10 sec approx. Returns non-positive when timed out. * Should not be used while reading data CDs. */ -static int sjcd_wait_for_status( void ){ - sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT; - SJCD_SET_TIMER( sjcd_status_timer, 1 ); - sleep_on( &sjcd_waitq ); +static int sjcd_wait_for_status(void) +{ + sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT; + SJCD_SET_TIMER(sjcd_status_timer, 1); + sleep_on(&sjcd_waitq); #if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE ) - if( sjcd_status_timeout <= 0 ) - printk( "SJCD: Error Wait For Status.\n" ); + if (sjcd_status_timeout <= 0) + printk("SJCD: Error Wait For Status.\n"); #endif - return( sjcd_status_timeout ); + return (sjcd_status_timeout); } -static int sjcd_receive_status( void ){ - int i; +static int sjcd_receive_status(void) +{ + int i; #if defined( SJCD_TRACE ) - printk( "SJCD: receive_status\n" ); + printk("SJCD: receive_status\n"); #endif - /* - * Wait a bit for status available. - */ - for( i = 200; i-- && ( sjcd_check_status() == 0 ); ); - if( i < 0 ){ + /* + * Wait a bit for status available. + */ + for (i = 200; i-- && (sjcd_check_status() == 0);); + if (i < 0) { #if defined( SJCD_TRACE ) - printk( "SJCD: long wait for status\n" ); + printk("SJCD: long wait for status\n"); #endif - if( sjcd_wait_for_status() <= 0 ) - printk( "SJCD: Timeout when read status.\n" ); - else i = 0; - } - return( i ); + if (sjcd_wait_for_status() <= 0) + printk("SJCD: Timeout when read status.\n"); + else + i = 0; + } + return (i); } /* * Load the status. Issue get status command and wait for status available. */ -static void sjcd_get_status( void ){ +static void sjcd_get_status(void) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: get_status\n" ); + printk("SJCD: get_status\n"); #endif - sjcd_send_cmd( SCMD_GET_STATUS ); - sjcd_receive_status(); + sjcd_send_cmd(SCMD_GET_STATUS); + sjcd_receive_status(); } /* * Check the drive if the disk is changed. Should be revised. */ -static int sjcd_disk_change( kdev_t full_dev ){ +static int sjcd_disk_change(kdev_t full_dev) +{ #if 0 - printk( "SJCD: sjcd_disk_change( 0x%x )\n", full_dev ); + printk("SJCD: sjcd_disk_change( 0x%x )\n", full_dev); #endif - if( MINOR( full_dev ) > 0 ){ - printk( "SJCD: request error: invalid device minor.\n" ); - return 0; - } - if( !sjcd_command_is_in_progress ) - sjcd_get_status(); - return( sjcd_status_valid ? sjcd_media_is_changed : 0 ); + if (MINOR(full_dev) > 0) { + printk("SJCD: request error: invalid device minor.\n"); + return 0; + } + if (!sjcd_command_is_in_progress) + sjcd_get_status(); + return (sjcd_status_valid ? sjcd_media_is_changed : 0); } /* * Read the table of contents (TOC) and TOC header if necessary. * We assume that the drive contains no more than 99 toc entries. */ -static struct sjcd_hw_disk_info sjcd_table_of_contents[ SJCD_MAX_TRACKS ]; +static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS]; static unsigned char sjcd_first_track_no, sjcd_last_track_no; #define sjcd_disk_length sjcd_table_of_contents[0].un.track_msf -static int sjcd_update_toc( void ){ - struct sjcd_hw_disk_info info; - int i; -#if defined( SJCD_TRACE ) - printk( "SJCD: update toc:\n" ); -#endif - /* - * check to see if we need to do anything - */ - if( sjcd_toc_uptodate ) return( 0 ); - - /* - * Get the TOC start information. - */ - sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK ); - sjcd_receive_status(); - - if( !sjcd_status_valid ){ - printk( "SJCD: cannot load status.\n" ); - return( -1 ); - } - - if( !sjcd_media_is_available ){ - printk( "SJCD: no disk in drive\n" ); - return( -1 ); - } - - if( !sjcd_command_failed ){ - if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){ - printk( "SJCD: cannot load response about TOC start.\n" ); - return( -1 ); - } - sjcd_first_track_no = bcd2bin( info.un.track_no ); - } else { - printk( "SJCD: get first failed\n" ); - return( -1 ); - } -#if defined( SJCD_TRACE ) - printk( "SJCD: TOC start 0x%02x ", sjcd_first_track_no ); -#endif - /* - * Get the TOC finish information. - */ - sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK ); - sjcd_receive_status(); - - if( !sjcd_status_valid ){ - printk( "SJCD: cannot load status.\n" ); - return( -1 ); - } - - if( !sjcd_media_is_available ){ - printk( "SJCD: no disk in drive\n" ); - return( -1 ); - } - - if( !sjcd_command_failed ){ - if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){ - printk( "SJCD: cannot load response about TOC finish.\n" ); - return( -1 ); - } - sjcd_last_track_no = bcd2bin( info.un.track_no ); - } else { - printk( "SJCD: get last failed\n" ); - return( -1 ); - } -#if defined( SJCD_TRACE ) - printk( "SJCD: TOC finish 0x%02x ", sjcd_last_track_no ); -#endif - for( i = sjcd_first_track_no; i <= sjcd_last_track_no; i++ ){ - /* - * Get the first track information. - */ - sjcd_send_1_cmd( SCMD_GET_DISK_INFO, bin2bcd( i ) ); - sjcd_receive_status(); - - if( !sjcd_status_valid ){ - printk( "SJCD: cannot load status.\n" ); - return( -1 ); - } - - if( !sjcd_media_is_available ){ - printk( "SJCD: no disk in drive\n" ); - return( -1 ); - } - - if( !sjcd_command_failed ){ - if( sjcd_load_response( &sjcd_table_of_contents[ i ], - sizeof( struct sjcd_hw_disk_info ) ) != 0 ){ - printk( "SJCD: cannot load info for %d track\n", i ); - return( -1 ); - } - } else { - printk( "SJCD: get info %d failed\n", i ); - return( -1 ); - } - } - - /* - * Get the disk length info. - */ - sjcd_send_1_cmd( SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE ); - sjcd_receive_status(); - - if( !sjcd_status_valid ){ - printk( "SJCD: cannot load status.\n" ); - return( -1 ); - } - - if( !sjcd_media_is_available ){ - printk( "SJCD: no disk in drive\n" ); - return( -1 ); - } - - if( !sjcd_command_failed ){ - if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){ - printk( "SJCD: cannot load response about disk size.\n" ); - return( -1 ); - } - sjcd_disk_length.min = info.un.track_msf.min; - sjcd_disk_length.sec = info.un.track_msf.sec; - sjcd_disk_length.frame = info.un.track_msf.frame; - } else { - printk( "SJCD: get size failed\n" ); - return( 1 ); - } +static int sjcd_update_toc(void) +{ + struct sjcd_hw_disk_info info; + int i; #if defined( SJCD_TRACE ) - printk( "SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min, - sjcd_disk_length.sec, sjcd_disk_length.frame ); + printk("SJCD: update toc:\n"); #endif - return( 0 ); + /* + * check to see if we need to do anything + */ + if (sjcd_toc_uptodate) + return (0); + + /* + * Get the TOC start information. + */ + sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK); + sjcd_receive_status(); + + if (!sjcd_status_valid) { + printk("SJCD: cannot load status.\n"); + return (-1); + } + + if (!sjcd_media_is_available) { + printk("SJCD: no disk in drive\n"); + return (-1); + } + + if (!sjcd_command_failed) { + if (sjcd_load_response(&info, sizeof(info)) != 0) { + printk + ("SJCD: cannot load response about TOC start.\n"); + return (-1); + } + sjcd_first_track_no = bcd2bin(info.un.track_no); + } else { + printk("SJCD: get first failed\n"); + return (-1); + } +#if defined( SJCD_TRACE ) + printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no); +#endif + /* + * Get the TOC finish information. + */ + sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK); + sjcd_receive_status(); + + if (!sjcd_status_valid) { + printk("SJCD: cannot load status.\n"); + return (-1); + } + + if (!sjcd_media_is_available) { + printk("SJCD: no disk in drive\n"); + return (-1); + } + + if (!sjcd_command_failed) { + if (sjcd_load_response(&info, sizeof(info)) != 0) { + printk + ("SJCD: cannot load response about TOC finish.\n"); + return (-1); + } + sjcd_last_track_no = bcd2bin(info.un.track_no); + } else { + printk("SJCD: get last failed\n"); + return (-1); + } +#if defined( SJCD_TRACE ) + printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no); +#endif + for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) { + /* + * Get the first track information. + */ + sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i)); + sjcd_receive_status(); + + if (!sjcd_status_valid) { + printk("SJCD: cannot load status.\n"); + return (-1); + } + + if (!sjcd_media_is_available) { + printk("SJCD: no disk in drive\n"); + return (-1); + } + + if (!sjcd_command_failed) { + if (sjcd_load_response(&sjcd_table_of_contents[i], + sizeof(struct + sjcd_hw_disk_info)) + != 0) { + printk + ("SJCD: cannot load info for %d track\n", + i); + return (-1); + } + } else { + printk("SJCD: get info %d failed\n", i); + return (-1); + } + } + + /* + * Get the disk length info. + */ + sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE); + sjcd_receive_status(); + + if (!sjcd_status_valid) { + printk("SJCD: cannot load status.\n"); + return (-1); + } + + if (!sjcd_media_is_available) { + printk("SJCD: no disk in drive\n"); + return (-1); + } + + if (!sjcd_command_failed) { + if (sjcd_load_response(&info, sizeof(info)) != 0) { + printk + ("SJCD: cannot load response about disk size.\n"); + return (-1); + } + sjcd_disk_length.min = info.un.track_msf.min; + sjcd_disk_length.sec = info.un.track_msf.sec; + sjcd_disk_length.frame = info.un.track_msf.frame; + } else { + printk("SJCD: get size failed\n"); + return (1); + } +#if defined( SJCD_TRACE ) + printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min, + sjcd_disk_length.sec, sjcd_disk_length.frame); +#endif + return (0); } /* * Load subchannel information. */ -static int sjcd_get_q_info( struct sjcd_hw_qinfo *qp ){ - int s; +static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp) +{ + int s; #if defined( SJCD_TRACE ) - printk( "SJCD: load sub q\n" ); + printk("SJCD: load sub q\n"); #endif - sjcd_send_cmd( SCMD_GET_QINFO ); - s = sjcd_receive_status(); - if( s < 0 || sjcd_command_failed || !sjcd_status_valid ){ - sjcd_send_cmd( 0xF2 ); - s = sjcd_receive_status(); - if( s < 0 || sjcd_command_failed || !sjcd_status_valid ) return( -1 ); - sjcd_send_cmd( SCMD_GET_QINFO ); - s = sjcd_receive_status(); - if( s < 0 || sjcd_command_failed || !sjcd_status_valid ) return( -1 ); - } - if( sjcd_media_is_available ) - if( sjcd_load_response( qp, sizeof( *qp ) ) == 0 ) return( 0 ); - return( -1 ); + sjcd_send_cmd(SCMD_GET_QINFO); + s = sjcd_receive_status(); + if (s < 0 || sjcd_command_failed || !sjcd_status_valid) { + sjcd_send_cmd(0xF2); + s = sjcd_receive_status(); + if (s < 0 || sjcd_command_failed || !sjcd_status_valid) + return (-1); + sjcd_send_cmd(SCMD_GET_QINFO); + s = sjcd_receive_status(); + if (s < 0 || sjcd_command_failed || !sjcd_status_valid) + return (-1); + } + if (sjcd_media_is_available) + if (sjcd_load_response(qp, sizeof(*qp)) == 0) + return (0); + return (-1); } /* * Start playing from the specified position. */ -static int sjcd_play( struct sjcd_play_msf *mp ){ - struct sjcd_play_msf msf; +static int sjcd_play(struct sjcd_play_msf *mp) +{ + struct sjcd_play_msf msf; - /* - * Turn the device to play mode. - */ - sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_PLAY ); - if( sjcd_receive_status() < 0 ) return( -1 ); - - /* - * Seek to the starting point. - */ - msf.start = mp->start; - msf.end.min = msf.end.sec = msf.end.frame = 0x00; - sjcd_send_6_cmd( SCMD_SEEK, &msf ); - if( sjcd_receive_status() < 0 ) return( -1 ); - - /* - * Start playing. - */ - sjcd_send_6_cmd( SCMD_PLAY, mp ); - return( sjcd_receive_status() ); + /* + * Turn the device to play mode. + */ + sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY); + if (sjcd_receive_status() < 0) + return (-1); + + /* + * Seek to the starting point. + */ + msf.start = mp->start; + msf.end.min = msf.end.sec = msf.end.frame = 0x00; + sjcd_send_6_cmd(SCMD_SEEK, &msf); + if (sjcd_receive_status() < 0) + return (-1); + + /* + * Start playing. + */ + sjcd_send_6_cmd(SCMD_PLAY, mp); + return (sjcd_receive_status()); } /* * Tray control functions. */ -static int sjcd_tray_close( void ){ +static int sjcd_tray_close(void) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: tray_close\n" ); + printk("SJCD: tray_close\n"); #endif - sjcd_send_cmd( SCMD_CLOSE_TRAY ); - return( sjcd_receive_status() ); + sjcd_send_cmd(SCMD_CLOSE_TRAY); + return (sjcd_receive_status()); } -static int sjcd_tray_lock( void ){ +static int sjcd_tray_lock(void) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: tray_lock\n" ); + printk("SJCD: tray_lock\n"); #endif - sjcd_send_cmd( SCMD_LOCK_TRAY ); - return( sjcd_receive_status() ); + sjcd_send_cmd(SCMD_LOCK_TRAY); + return (sjcd_receive_status()); } -static int sjcd_tray_unlock( void ){ +static int sjcd_tray_unlock(void) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: tray_unlock\n" ); + printk("SJCD: tray_unlock\n"); #endif - sjcd_send_cmd( SCMD_UNLOCK_TRAY ); - return( sjcd_receive_status() ); + sjcd_send_cmd(SCMD_UNLOCK_TRAY); + return (sjcd_receive_status()); } -static int sjcd_tray_open( void ){ +static int sjcd_tray_open(void) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: tray_open\n" ); + printk("SJCD: tray_open\n"); #endif - sjcd_send_cmd( SCMD_EJECT_TRAY ); - return( sjcd_receive_status() ); + sjcd_send_cmd(SCMD_EJECT_TRAY); + return (sjcd_receive_status()); } /* * Do some user commands. */ -static int sjcd_ioctl( struct inode *ip, struct file *fp, - unsigned int cmd, unsigned long arg ){ -#if defined( SJCD_TRACE ) - printk( "SJCD:ioctl\n" ); -#endif - - if( ip == NULL ) return( -EINVAL ); - - sjcd_get_status(); - if( !sjcd_status_valid ) return( -EIO ); - if( sjcd_update_toc() < 0 ) return( -EIO ); - - switch( cmd ){ - case CDROMSTART:{ -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: start\n" ); -#endif - return( 0 ); - } - - case CDROMSTOP:{ +static int sjcd_ioctl(struct inode *ip, struct file *fp, + unsigned int cmd, unsigned long arg) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: stop\n" ); + printk("SJCD:ioctl\n"); #endif - sjcd_send_cmd( SCMD_PAUSE ); - ( void )sjcd_receive_status(); - sjcd_audio_status = CDROM_AUDIO_NO_STATUS; - return( 0 ); - } - case CDROMPAUSE:{ - struct sjcd_hw_qinfo q_info; -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: pause\n" ); -#endif - if( sjcd_audio_status == CDROM_AUDIO_PLAY ){ - sjcd_send_cmd( SCMD_PAUSE ); - ( void )sjcd_receive_status(); - if( sjcd_get_q_info( &q_info ) < 0 ){ - sjcd_audio_status = CDROM_AUDIO_NO_STATUS; - } else { - sjcd_audio_status = CDROM_AUDIO_PAUSED; - sjcd_playing.start = q_info.abs; - } - return( 0 ); - } else return( -EINVAL ); - } - - case CDROMRESUME:{ -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: resume\n" ); -#endif - if( sjcd_audio_status == CDROM_AUDIO_PAUSED ){ - /* - * continue play starting at saved location - */ - if( sjcd_play( &sjcd_playing ) < 0 ){ - sjcd_audio_status = CDROM_AUDIO_ERROR; - return( -EIO ); - } else { - sjcd_audio_status = CDROM_AUDIO_PLAY; - return( 0 ); - } - } else return( -EINVAL ); - } - - case CDROMPLAYTRKIND:{ - struct cdrom_ti ti; int s; -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: playtrkind\n" ); -#endif - if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( ti ) ) ) == 0 ){ - copy_from_user( &ti, (void *)arg, sizeof( ti ) ); - - if( ti.cdti_trk0 < sjcd_first_track_no ) return( -EINVAL ); - if( ti.cdti_trk1 > sjcd_last_track_no ) - ti.cdti_trk1 = sjcd_last_track_no; - if( ti.cdti_trk0 > ti.cdti_trk1 ) return( -EINVAL ); - - sjcd_playing.start = sjcd_table_of_contents[ ti.cdti_trk0 ].un.track_msf; - sjcd_playing.end = ( ti.cdti_trk1 < sjcd_last_track_no ) ? - sjcd_table_of_contents[ ti.cdti_trk1 + 1 ].un.track_msf : - sjcd_table_of_contents[ 0 ].un.track_msf; - - if( sjcd_play( &sjcd_playing ) < 0 ){ - sjcd_audio_status = CDROM_AUDIO_ERROR; - return( -EIO ); - } else sjcd_audio_status = CDROM_AUDIO_PLAY; - } - return( s ); - } - - case CDROMPLAYMSF:{ - struct cdrom_msf sjcd_msf; int s; -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: playmsf\n" ); -#endif - if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( sjcd_msf ) ) ) == 0 ){ - if( sjcd_audio_status == CDROM_AUDIO_PLAY ){ - sjcd_send_cmd( SCMD_PAUSE ); - ( void )sjcd_receive_status(); - sjcd_audio_status = CDROM_AUDIO_NO_STATUS; - } - - copy_from_user( &sjcd_msf, (void *)arg, sizeof( sjcd_msf ) ); - - sjcd_playing.start.min = bin2bcd( sjcd_msf.cdmsf_min0 ); - sjcd_playing.start.sec = bin2bcd( sjcd_msf.cdmsf_sec0 ); - sjcd_playing.start.frame = bin2bcd( sjcd_msf.cdmsf_frame0 ); - sjcd_playing.end.min = bin2bcd( sjcd_msf.cdmsf_min1 ); - sjcd_playing.end.sec = bin2bcd( sjcd_msf.cdmsf_sec1 ); - sjcd_playing.end.frame = bin2bcd( sjcd_msf.cdmsf_frame1 ); - - if( sjcd_play( &sjcd_playing ) < 0 ){ - sjcd_audio_status = CDROM_AUDIO_ERROR; - return( -EIO ); - } else sjcd_audio_status = CDROM_AUDIO_PLAY; - } - return( s ); - } + if (ip == NULL) + return (-EINVAL); - case CDROMREADTOCHDR:{ - struct cdrom_tochdr toc_header; int s; + sjcd_get_status(); + if (!sjcd_status_valid) + return (-EIO); + if (sjcd_update_toc() < 0) + return (-EIO); + + switch (cmd) { + case CDROMSTART:{ +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: start\n"); +#endif + return (0); + } + + case CDROMSTOP:{ +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: stop\n"); +#endif + sjcd_send_cmd(SCMD_PAUSE); + (void) sjcd_receive_status(); + sjcd_audio_status = CDROM_AUDIO_NO_STATUS; + return (0); + } + + case CDROMPAUSE:{ + struct sjcd_hw_qinfo q_info; +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: pause\n"); +#endif + if (sjcd_audio_status == CDROM_AUDIO_PLAY) { + sjcd_send_cmd(SCMD_PAUSE); + (void) sjcd_receive_status(); + if (sjcd_get_q_info(&q_info) < 0) { + sjcd_audio_status = + CDROM_AUDIO_NO_STATUS; + } else { + sjcd_audio_status = + CDROM_AUDIO_PAUSED; + sjcd_playing.start = q_info.abs; + } + return (0); + } else + return (-EINVAL); + } + + case CDROMRESUME:{ +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: resume\n"); +#endif + if (sjcd_audio_status == CDROM_AUDIO_PAUSED) { + /* + * continue play starting at saved location + */ + if (sjcd_play(&sjcd_playing) < 0) { + sjcd_audio_status = + CDROM_AUDIO_ERROR; + return (-EIO); + } else { + sjcd_audio_status = + CDROM_AUDIO_PLAY; + return (0); + } + } else + return (-EINVAL); + } + + case CDROMPLAYTRKIND:{ + struct cdrom_ti ti; + int s; +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: playtrkind\n"); +#endif + if ((s = + verify_area(VERIFY_READ, (void *) arg, + sizeof(ti))) == 0) { + copy_from_user(&ti, (void *) arg, + sizeof(ti)); + + if (ti.cdti_trk0 < sjcd_first_track_no) + return (-EINVAL); + if (ti.cdti_trk1 > sjcd_last_track_no) + ti.cdti_trk1 = sjcd_last_track_no; + if (ti.cdti_trk0 > ti.cdti_trk1) + return (-EINVAL); + + sjcd_playing.start = + sjcd_table_of_contents[ti.cdti_trk0]. + un.track_msf; + sjcd_playing.end = + (ti.cdti_trk1 < + sjcd_last_track_no) ? + sjcd_table_of_contents[ti.cdti_trk1 + + 1].un. + track_msf : sjcd_table_of_contents[0]. + un.track_msf; + + if (sjcd_play(&sjcd_playing) < 0) { + sjcd_audio_status = + CDROM_AUDIO_ERROR; + return (-EIO); + } else + sjcd_audio_status = + CDROM_AUDIO_PLAY; + } + return (s); + } + + case CDROMPLAYMSF:{ + struct cdrom_msf sjcd_msf; + int s; +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: playmsf\n"); +#endif + if ((s = + verify_area(VERIFY_READ, (void *) arg, + sizeof(sjcd_msf))) == 0) { + if (sjcd_audio_status == CDROM_AUDIO_PLAY) { + sjcd_send_cmd(SCMD_PAUSE); + (void) sjcd_receive_status(); + sjcd_audio_status = + CDROM_AUDIO_NO_STATUS; + } + + copy_from_user(&sjcd_msf, (void *) arg, + sizeof(sjcd_msf)); + + sjcd_playing.start.min = + bin2bcd(sjcd_msf.cdmsf_min0); + sjcd_playing.start.sec = + bin2bcd(sjcd_msf.cdmsf_sec0); + sjcd_playing.start.frame = + bin2bcd(sjcd_msf.cdmsf_frame0); + sjcd_playing.end.min = + bin2bcd(sjcd_msf.cdmsf_min1); + sjcd_playing.end.sec = + bin2bcd(sjcd_msf.cdmsf_sec1); + sjcd_playing.end.frame = + bin2bcd(sjcd_msf.cdmsf_frame1); + + if (sjcd_play(&sjcd_playing) < 0) { + sjcd_audio_status = + CDROM_AUDIO_ERROR; + return (-EIO); + } else + sjcd_audio_status = + CDROM_AUDIO_PLAY; + } + return (s); + } + + case CDROMREADTOCHDR:{ + struct cdrom_tochdr toc_header; + int s; #if defined (SJCD_TRACE ) - printk( "SJCD: ioctl: readtocheader\n" ); + printk("SJCD: ioctl: readtocheader\n"); #endif - if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_header ) ) ) == 0 ){ - toc_header.cdth_trk0 = sjcd_first_track_no; - toc_header.cdth_trk1 = sjcd_last_track_no; - copy_to_user( (void *)arg, &toc_header, sizeof( toc_header ) ); - } - return( s ); - } - - case CDROMREADTOCENTRY:{ - struct cdrom_tocentry toc_entry; int s; -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: readtocentry\n" ); -#endif - if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_entry ) ) ) == 0 ){ - struct sjcd_hw_disk_info *tp; - - copy_from_user( &toc_entry, (void *)arg, sizeof( toc_entry ) ); - - if( toc_entry.cdte_track == CDROM_LEADOUT ) - tp = &sjcd_table_of_contents[ 0 ]; - else if( toc_entry.cdte_track < sjcd_first_track_no ) return( -EINVAL ); - else if( toc_entry.cdte_track > sjcd_last_track_no ) return( -EINVAL ); - else tp = &sjcd_table_of_contents[ toc_entry.cdte_track ]; - - toc_entry.cdte_adr = tp->track_control & 0x0F; - toc_entry.cdte_ctrl = tp->track_control >> 4; - - switch( toc_entry.cdte_format ){ - case CDROM_LBA: - toc_entry.cdte_addr.lba = msf2hsg( &( tp->un.track_msf ) ); - break; - case CDROM_MSF: - toc_entry.cdte_addr.msf.minute = bcd2bin( tp->un.track_msf.min ); - toc_entry.cdte_addr.msf.second = bcd2bin( tp->un.track_msf.sec ); - toc_entry.cdte_addr.msf.frame = bcd2bin( tp->un.track_msf.frame ); - break; - default: return( -EINVAL ); - } - copy_to_user( (void *)arg, &toc_entry, sizeof( toc_entry ) ); - } - return( s ); - } - - case CDROMSUBCHNL:{ - struct cdrom_subchnl subchnl; int s; -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: subchnl\n" ); -#endif - if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( subchnl ) ) ) == 0 ){ - struct sjcd_hw_qinfo q_info; - - copy_from_user( &subchnl, (void *)arg, sizeof( subchnl ) ); - if( sjcd_get_q_info( &q_info ) < 0 ) return( -EIO ); - - subchnl.cdsc_audiostatus = sjcd_audio_status; - subchnl.cdsc_adr = q_info.track_control & 0x0F; - subchnl.cdsc_ctrl = q_info.track_control >> 4; - subchnl.cdsc_trk = bcd2bin( q_info.track_no ); - subchnl.cdsc_ind = bcd2bin( q_info.x ); - - switch( subchnl.cdsc_format ){ - case CDROM_LBA: - subchnl.cdsc_absaddr.lba = msf2hsg( &( q_info.abs ) ); - subchnl.cdsc_reladdr.lba = msf2hsg( &( q_info.rel ) ); - break; - case CDROM_MSF: - subchnl.cdsc_absaddr.msf.minute = bcd2bin( q_info.abs.min ); - subchnl.cdsc_absaddr.msf.second = bcd2bin( q_info.abs.sec ); - subchnl.cdsc_absaddr.msf.frame = bcd2bin( q_info.abs.frame ); - subchnl.cdsc_reladdr.msf.minute = bcd2bin( q_info.rel.min ); - subchnl.cdsc_reladdr.msf.second = bcd2bin( q_info.rel.sec ); - subchnl.cdsc_reladdr.msf.frame = bcd2bin( q_info.rel.frame ); - break; - default: return( -EINVAL ); - } - copy_to_user( (void *)arg, &subchnl, sizeof( subchnl ) ); - } - return( s ); - } - - case CDROMVOLCTRL:{ - struct cdrom_volctrl vol_ctrl; int s; -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: volctrl\n" ); -#endif - if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( vol_ctrl ) ) ) == 0 ){ - unsigned char dummy[ 4 ]; - - copy_from_user( &vol_ctrl, (void *)arg, sizeof( vol_ctrl ) ); - sjcd_send_4_cmd( SCMD_SET_VOLUME, vol_ctrl.channel0, 0xFF, - vol_ctrl.channel1, 0xFF ); - if( sjcd_receive_status() < 0 ) return( -EIO ); - ( void )sjcd_load_response( dummy, 4 ); - } - return( s ); - } - - case CDROMEJECT:{ -#if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: eject\n" ); -#endif - if( !sjcd_command_is_in_progress ){ - sjcd_tray_unlock(); - sjcd_send_cmd( SCMD_EJECT_TRAY ); - ( void )sjcd_receive_status(); - } - return( 0 ); - } + if ((s = + verify_area(VERIFY_WRITE, (void *) arg, + sizeof(toc_header))) == 0) { + toc_header.cdth_trk0 = sjcd_first_track_no; + toc_header.cdth_trk1 = sjcd_last_track_no; + copy_to_user((void *) arg, &toc_header, + sizeof(toc_header)); + } + return (s); + } + + case CDROMREADTOCENTRY:{ + struct cdrom_tocentry toc_entry; + int s; +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: readtocentry\n"); +#endif + if ((s = + verify_area(VERIFY_WRITE, (void *) arg, + sizeof(toc_entry))) == 0) { + struct sjcd_hw_disk_info *tp; + + copy_from_user(&toc_entry, (void *) arg, + sizeof(toc_entry)); + + if (toc_entry.cdte_track == CDROM_LEADOUT) + tp = &sjcd_table_of_contents[0]; + else if (toc_entry.cdte_track < + sjcd_first_track_no) + return (-EINVAL); + else if (toc_entry.cdte_track > + sjcd_last_track_no) + return (-EINVAL); + else + tp = &sjcd_table_of_contents + [toc_entry.cdte_track]; + + toc_entry.cdte_adr = + tp->track_control & 0x0F; + toc_entry.cdte_ctrl = + tp->track_control >> 4; + + switch (toc_entry.cdte_format) { + case CDROM_LBA: + toc_entry.cdte_addr.lba = + msf2hsg(&(tp->un.track_msf)); + break; + case CDROM_MSF: + toc_entry.cdte_addr.msf.minute = + bcd2bin(tp->un.track_msf.min); + toc_entry.cdte_addr.msf.second = + bcd2bin(tp->un.track_msf.sec); + toc_entry.cdte_addr.msf.frame = + bcd2bin(tp->un.track_msf. + frame); + break; + default: + return (-EINVAL); + } + copy_to_user((void *) arg, &toc_entry, + sizeof(toc_entry)); + } + return (s); + } + + case CDROMSUBCHNL:{ + struct cdrom_subchnl subchnl; + int s; +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: subchnl\n"); +#endif + if ((s = + verify_area(VERIFY_WRITE, (void *) arg, + sizeof(subchnl))) == 0) { + struct sjcd_hw_qinfo q_info; + + copy_from_user(&subchnl, (void *) arg, + sizeof(subchnl)); + if (sjcd_get_q_info(&q_info) < 0) + return (-EIO); + + subchnl.cdsc_audiostatus = + sjcd_audio_status; + subchnl.cdsc_adr = + q_info.track_control & 0x0F; + subchnl.cdsc_ctrl = + q_info.track_control >> 4; + subchnl.cdsc_trk = + bcd2bin(q_info.track_no); + subchnl.cdsc_ind = bcd2bin(q_info.x); + + switch (subchnl.cdsc_format) { + case CDROM_LBA: + subchnl.cdsc_absaddr.lba = + msf2hsg(&(q_info.abs)); + subchnl.cdsc_reladdr.lba = + msf2hsg(&(q_info.rel)); + break; + case CDROM_MSF: + subchnl.cdsc_absaddr.msf.minute = + bcd2bin(q_info.abs.min); + subchnl.cdsc_absaddr.msf.second = + bcd2bin(q_info.abs.sec); + subchnl.cdsc_absaddr.msf.frame = + bcd2bin(q_info.abs.frame); + subchnl.cdsc_reladdr.msf.minute = + bcd2bin(q_info.rel.min); + subchnl.cdsc_reladdr.msf.second = + bcd2bin(q_info.rel.sec); + subchnl.cdsc_reladdr.msf.frame = + bcd2bin(q_info.rel.frame); + break; + default: + return (-EINVAL); + } + copy_to_user((void *) arg, &subchnl, + sizeof(subchnl)); + } + return (s); + } + + case CDROMVOLCTRL:{ + struct cdrom_volctrl vol_ctrl; + int s; +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: volctrl\n"); +#endif + if ((s = + verify_area(VERIFY_READ, (void *) arg, + sizeof(vol_ctrl))) == 0) { + unsigned char dummy[4]; + + copy_from_user(&vol_ctrl, (void *) arg, + sizeof(vol_ctrl)); + sjcd_send_4_cmd(SCMD_SET_VOLUME, + vol_ctrl.channel0, 0xFF, + vol_ctrl.channel1, 0xFF); + if (sjcd_receive_status() < 0) + return (-EIO); + (void) sjcd_load_response(dummy, 4); + } + return (s); + } + + case CDROMEJECT:{ +#if defined( SJCD_TRACE ) + printk("SJCD: ioctl: eject\n"); +#endif + if (!sjcd_command_is_in_progress) { + sjcd_tray_unlock(); + sjcd_send_cmd(SCMD_EJECT_TRAY); + (void) sjcd_receive_status(); + } + return (0); + } #if defined( SJCD_GATHER_STAT ) - case 0xABCD:{ - int s; + case 0xABCD:{ + int s; #if defined( SJCD_TRACE ) - printk( "SJCD: ioctl: statistic\n" ); + printk("SJCD: ioctl: statistic\n"); #endif - if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( statistic ) ) ) == 0 ) - copy_to_user( (void *)arg, &statistic, sizeof( statistic ) ); - return( s ); - } + if ((s = + verify_area(VERIFY_WRITE, (void *) arg, + sizeof(statistic))) == 0) + copy_to_user((void *) arg, &statistic, + sizeof(statistic)); + return (s); + } #endif - default: - return( -EINVAL ); - } + default: + return (-EINVAL); + } } /* * Invalidate internal buffers of the driver. */ -static void sjcd_invalidate_buffers( void ){ - int i; - for( i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[ i++ ] = -1 ); - sjcd_buf_out = -1; +static void sjcd_invalidate_buffers(void) +{ + int i; + for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1); + sjcd_buf_out = -1; } /* @@ -939,508 +1077,595 @@ ( !QUEUE_EMPTY && MAJOR( CURRENT->rq_dev ) == MAJOR_NR && \ CURRENT->cmd == READ && CURRENT->sector != -1 ) -static void sjcd_transfer( void ){ +static void sjcd_transfer(void) +{ #if defined( SJCD_TRACE ) - printk( "SJCD: transfer:\n" ); + printk("SJCD: transfer:\n"); #endif - if( CURRENT_IS_VALID ){ - while( CURRENT->nr_sectors ){ - int i, bn = CURRENT->sector / 4; - for( i = 0; i < SJCD_BUF_SIZ && sjcd_buf_bn[ i ] != bn; i++ ); - if( i < SJCD_BUF_SIZ ){ - int offs = ( i * 4 + ( CURRENT->sector & 3 ) ) * 512; - int nr_sectors = 4 - ( CURRENT->sector & 3 ); - if( sjcd_buf_out != i ){ - sjcd_buf_out = i; - if( sjcd_buf_bn[ i ] != bn ){ - sjcd_buf_out = -1; - continue; - } - } - if( nr_sectors > CURRENT->nr_sectors ) - nr_sectors = CURRENT->nr_sectors; -#if defined( SJCD_TRACE ) - printk( "SJCD: copy out\n" ); -#endif - memcpy( CURRENT->buffer, sjcd_buf + offs, nr_sectors * 512 ); - CURRENT->nr_sectors -= nr_sectors; - CURRENT->sector += nr_sectors; - CURRENT->buffer += nr_sectors * 512; - } else { - sjcd_buf_out = -1; - break; - } - } - } + if (CURRENT_IS_VALID) { + while (CURRENT->nr_sectors) { + int i, bn = CURRENT->sector / 4; + for (i = 0; + i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn; + i++); + if (i < SJCD_BUF_SIZ) { + int offs = + (i * 4 + (CURRENT->sector & 3)) * 512; + int nr_sectors = 4 - (CURRENT->sector & 3); + if (sjcd_buf_out != i) { + sjcd_buf_out = i; + if (sjcd_buf_bn[i] != bn) { + sjcd_buf_out = -1; + continue; + } + } + if (nr_sectors > CURRENT->nr_sectors) + nr_sectors = CURRENT->nr_sectors; +#if defined( SJCD_TRACE ) + printk("SJCD: copy out\n"); +#endif + memcpy(CURRENT->buffer, sjcd_buf + offs, + nr_sectors * 512); + CURRENT->nr_sectors -= nr_sectors; + CURRENT->sector += nr_sectors; + CURRENT->buffer += nr_sectors * 512; + } else { + sjcd_buf_out = -1; + break; + } + } + } #if defined( SJCD_TRACE ) - printk( "SJCD: transfer: done\n" ); + printk("SJCD: transfer: done\n"); #endif } -static void sjcd_poll( void ){ +static void sjcd_poll(void) +{ #if defined( SJCD_GATHER_STAT ) - /* - * Update total number of ticks. - */ - statistic.ticks++; - statistic.tticks[ sjcd_transfer_state ]++; + /* + * Update total number of ticks. + */ + statistic.ticks++; + statistic.tticks[sjcd_transfer_state]++; #endif - ReSwitch: switch( sjcd_transfer_state ){ - - case SJCD_S_IDLE:{ + ReSwitch:switch (sjcd_transfer_state) { + + case SJCD_S_IDLE:{ #if defined( SJCD_GATHER_STAT ) - statistic.idle_ticks++; + statistic.idle_ticks++; #endif #if defined( SJCD_TRACE ) - printk( "SJCD_S_IDLE\n" ); + printk("SJCD_S_IDLE\n"); #endif - return; - } + return; + } - case SJCD_S_START:{ + case SJCD_S_START:{ #if defined( SJCD_GATHER_STAT ) - statistic.start_ticks++; + statistic.start_ticks++; #endif - sjcd_send_cmd( SCMD_GET_STATUS ); - sjcd_transfer_state = - sjcd_mode == SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE; - sjcd_transfer_timeout = 500; -#if defined( SJCD_TRACE ) - printk( "SJCD_S_START: goto SJCD_S_%s mode\n", - sjcd_transfer_state == SJCD_S_READ ? "READ" : "MODE" ); -#endif - break; - } - - case SJCD_S_MODE:{ - if( sjcd_check_status() ){ - /* - * Previous command is completed. - */ - if( !sjcd_status_valid || sjcd_command_failed ){ -#if defined( SJCD_TRACE ) - printk( "SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n" ); -#endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } - - sjcd_mode = 0; /* unknown mode; should not be valid when failed */ - sjcd_send_1_cmd( SCMD_SET_MODE, SCMD_MODE_COOKED ); - sjcd_transfer_state = SJCD_S_READ; sjcd_transfer_timeout = 1000; + sjcd_send_cmd(SCMD_GET_STATUS); + sjcd_transfer_state = + sjcd_mode == + SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE; + sjcd_transfer_timeout = 500; +#if defined( SJCD_TRACE ) + printk("SJCD_S_START: goto SJCD_S_%s mode\n", + sjcd_transfer_state == + SJCD_S_READ ? "READ" : "MODE"); +#endif + break; + } + + case SJCD_S_MODE:{ + if (sjcd_check_status()) { + /* + * Previous command is completed. + */ + if (!sjcd_status_valid + || sjcd_command_failed) { +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n"); +#endif + sjcd_transfer_state = SJCD_S_STOP; + goto ReSwitch; + } + + sjcd_mode = 0; /* unknown mode; should not be valid when failed */ + sjcd_send_1_cmd(SCMD_SET_MODE, + SCMD_MODE_COOKED); + sjcd_transfer_state = SJCD_S_READ; + sjcd_transfer_timeout = 1000; #if defined( SJCD_TRACE ) - printk( "SJCD_S_MODE: goto SJCD_S_READ mode\n" ); + printk + ("SJCD_S_MODE: goto SJCD_S_READ mode\n"); #endif - } + } #if defined( SJCD_GATHER_STAT ) - else statistic.mode_ticks++; + else + statistic.mode_ticks++; #endif - break; - } + break; + } - case SJCD_S_READ:{ - if( sjcd_status_valid ? 1 : sjcd_check_status() ){ - /* - * Previous command is completed. - */ - if( !sjcd_status_valid || sjcd_command_failed ){ -#if defined( SJCD_TRACE ) - printk( "SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n" ); -#endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } - if( !sjcd_media_is_available ){ -#if defined( SJCD_TRACE ) - printk( "SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n" ); -#endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } - if( sjcd_mode != SCMD_MODE_COOKED ){ - /* - * We seem to come from set mode. So discard one byte of result. - */ - if( sjcd_load_response( &sjcd_mode, 1 ) != 0 ){ -#if defined( SJCD_TRACE ) - printk( "SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n" ); -#endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } - if( sjcd_mode != SCMD_MODE_COOKED ){ -#if defined( SJCD_TRACE ) - printk( "SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n" ); + case SJCD_S_READ:{ + if (sjcd_status_valid ? 1 : sjcd_check_status()) { + /* + * Previous command is completed. + */ + if (!sjcd_status_valid + || sjcd_command_failed) { +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n"); +#endif + sjcd_transfer_state = SJCD_S_STOP; + goto ReSwitch; + } + if (!sjcd_media_is_available) { +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n"); +#endif + sjcd_transfer_state = SJCD_S_STOP; + goto ReSwitch; + } + if (sjcd_mode != SCMD_MODE_COOKED) { + /* + * We seem to come from set mode. So discard one byte of result. + */ + if (sjcd_load_response + (&sjcd_mode, 1) != 0) { +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n"); +#endif + sjcd_transfer_state = + SJCD_S_STOP; + goto ReSwitch; + } + if (sjcd_mode != SCMD_MODE_COOKED) { +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n"); +#endif + sjcd_transfer_state = + SJCD_S_STOP; + goto ReSwitch; + } + } + + if (CURRENT_IS_VALID) { + struct sjcd_play_msf msf; + + sjcd_next_bn = CURRENT->sector / 4; + hsg2msf(sjcd_next_bn, &msf.start); + msf.end.min = 0; + msf.end.sec = 0; + msf.end.frame = sjcd_read_count = + SJCD_BUF_SIZ; +#if defined( SJCD_TRACE ) + printk + ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n", + msf.start.min, msf.start.sec, + msf.start.frame, msf.end.min, + msf.end.sec, msf.end.frame); + printk + ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", + sjcd_next_bn, sjcd_buf_in, + sjcd_buf_out, + sjcd_buf_bn[sjcd_buf_in]); +#endif + sjcd_send_6_cmd(SCMD_DATA_READ, + &msf); + sjcd_transfer_state = SJCD_S_DATA; + sjcd_transfer_timeout = 500; +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_READ: go to SJCD_S_DATA mode\n"); +#endif + } else { +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n"); +#endif + sjcd_transfer_state = SJCD_S_STOP; + goto ReSwitch; + } + } +#if defined( SJCD_GATHER_STAT ) + else + statistic.read_ticks++; #endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } - } + break; + } - if( CURRENT_IS_VALID ){ - struct sjcd_play_msf msf; + case SJCD_S_DATA:{ + unsigned char stat; - sjcd_next_bn = CURRENT->sector / 4; - hsg2msf( sjcd_next_bn, &msf.start ); - msf.end.min = 0; msf.end.sec = 0; - msf.end.frame = sjcd_read_count = SJCD_BUF_SIZ; -#if defined( SJCD_TRACE ) - printk( "SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n", - msf.start.min, msf.start.sec, msf.start.frame, - msf.end.min, msf.end.sec, msf.end.frame ); - printk( "sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", \ - sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, - sjcd_buf_bn[ sjcd_buf_in ] ); -#endif - sjcd_send_6_cmd( SCMD_DATA_READ, &msf ); - sjcd_transfer_state = SJCD_S_DATA; - sjcd_transfer_timeout = 500; -#if defined( SJCD_TRACE ) - printk( "SJCD_S_READ: go to SJCD_S_DATA mode\n" ); -#endif - } else { -#if defined( SJCD_TRACE ) - printk( "SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n" ); -#endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } - } + sjcd_s_data:stat = + inb(SJCDPORT + (1)); +#if defined( SJCD_TRACE ) + printk("SJCD_S_DATA: status = 0x%02x\n", stat); +#endif + if (SJCD_STATUS_AVAILABLE(stat)) { + /* + * No data is waiting for us in the drive buffer. Status of operation + * completion is available. Read and parse it. + */ + sjcd_load_status(); + + if (!sjcd_status_valid + || sjcd_command_failed) { +#if defined( SJCD_TRACE ) + printk + ("SJCD: read block %d failed, maybe audio disk? Giving up\n", + sjcd_next_bn); +#endif + if (CURRENT_IS_VALID) + end_request(0); +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n"); +#endif + sjcd_transfer_state = SJCD_S_STOP; + goto ReSwitch; + } + + if (!sjcd_media_is_available) { + printk + ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n"); + sjcd_transfer_state = SJCD_S_STOP; + goto ReSwitch; + } + + sjcd_transfer_state = SJCD_S_READ; + goto ReSwitch; + } else if (SJCD_DATA_AVAILABLE(stat)) { + /* + * One frame is read into device buffer. We must copy it to our memory. + * Otherwise cdrom hangs up. Check to see if we have something to copy + * to. + */ + if (!CURRENT_IS_VALID + && sjcd_buf_in == sjcd_buf_out) { +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n"); + printk + (" ... all the date would be discarded\n"); +#endif + sjcd_transfer_state = SJCD_S_STOP; + goto ReSwitch; + } + + /* + * Everything seems to be OK. Just read the frame and recalculate + * indices. + */ + sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */ + insb(SJCDPORT(2), + sjcd_buf + 2048 * sjcd_buf_in, 2048); +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n", + sjcd_next_bn, sjcd_buf_in, + sjcd_buf_out, + sjcd_buf_bn[sjcd_buf_in]); +#endif + sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++; + if (sjcd_buf_out == -1) + sjcd_buf_out = sjcd_buf_in; + if (++sjcd_buf_in == SJCD_BUF_SIZ) + sjcd_buf_in = 0; + + /* + * Only one frame is ready at time. So we should turn over to wait for + * another frame. If we need that, of course. + */ + if (--sjcd_read_count == 0) { + /* + * OK, request seems to be precessed. Continue transferring... + */ + if (!sjcd_transfer_is_active) { + while (CURRENT_IS_VALID) { + /* + * Continue transferring. + */ + sjcd_transfer(); + if (CURRENT-> + nr_sectors == + 0) + end_request + (1); + else + break; + } + } + if (CURRENT_IS_VALID && + (CURRENT->sector / 4 < + sjcd_next_bn + || CURRENT->sector / 4 > + sjcd_next_bn + + SJCD_BUF_SIZ)) { +#if defined( SJCD_TRACE ) + printk + ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n"); +#endif + sjcd_transfer_state = + SJCD_S_STOP; + goto ReSwitch; + } + } + /* + * Now we should turn around rather than wait for while. + */ + goto sjcd_s_data; + } #if defined( SJCD_GATHER_STAT ) - else statistic.read_ticks++; + else + statistic.data_ticks++; #endif - break; - } + break; + } - case SJCD_S_DATA:{ - unsigned char stat; - - sjcd_s_data: stat = inb( SJCDPORT( 1 ) ); -#if defined( SJCD_TRACE ) - printk( "SJCD_S_DATA: status = 0x%02x\n", stat ); + case SJCD_S_STOP:{ + sjcd_read_count = 0; + sjcd_send_cmd(SCMD_STOP); + sjcd_transfer_state = SJCD_S_STOPPING; + sjcd_transfer_timeout = 500; +#if defined( SJCD_GATHER_STAT ) + statistic.stop_ticks++; #endif - if( SJCD_STATUS_AVAILABLE( stat ) ){ - /* - * No data is waiting for us in the drive buffer. Status of operation - * completion is available. Read and parse it. - */ - sjcd_load_status(); + break; + } - if( !sjcd_status_valid || sjcd_command_failed ){ -#if defined( SJCD_TRACE ) - printk( "SJCD: read block %d failed, maybe audio disk? Giving up\n", - sjcd_next_bn ); -#endif - if( CURRENT_IS_VALID ) end_request( 0 ); -#if defined( SJCD_TRACE ) - printk( "SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n" ); + case SJCD_S_STOPPING:{ + unsigned char stat; + + stat = inb(SJCDPORT(1)); +#if defined( SJCD_TRACE ) + printk("SJCD_S_STOP: status = 0x%02x\n", stat); +#endif + if (SJCD_DATA_AVAILABLE(stat)) { + int i; +#if defined( SJCD_TRACE ) + printk("SJCD_S_STOP: discard data\n"); +#endif + /* + * Discard all the data from the pipe. Foolish method. + */ + for (i = 2048; i--; + (void) inb(SJCDPORT(2))); + sjcd_transfer_timeout = 500; + } else if (SJCD_STATUS_AVAILABLE(stat)) { + sjcd_load_status(); + if (sjcd_status_valid + && sjcd_media_is_changed) { + sjcd_toc_uptodate = 0; + sjcd_invalidate_buffers(); + } + if (CURRENT_IS_VALID) { + if (sjcd_status_valid) + sjcd_transfer_state = + SJCD_S_READ; + else + sjcd_transfer_state = + SJCD_S_START; + } else + sjcd_transfer_state = SJCD_S_IDLE; + goto ReSwitch; + } +#if defined( SJCD_GATHER_STAT ) + else + statistic.stopping_ticks++; #endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } + break; + } - if( !sjcd_media_is_available ){ - printk( "SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n" ); - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } + default: + printk("SJCD: poll: invalid state %d\n", + sjcd_transfer_state); + return; + } - sjcd_transfer_state = SJCD_S_READ; - goto ReSwitch; - } else if( SJCD_DATA_AVAILABLE( stat ) ){ - /* - * One frame is read into device buffer. We must copy it to our memory. - * Otherwise cdrom hangs up. Check to see if we have something to copy - * to. - */ - if( !CURRENT_IS_VALID && sjcd_buf_in == sjcd_buf_out ){ -#if defined( SJCD_TRACE ) - printk( "SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n" ); - printk( " ... all the date would be discarded\n" ); -#endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } + if (--sjcd_transfer_timeout == 0) { + printk("SJCD: timeout in state %d\n", sjcd_transfer_state); + while (CURRENT_IS_VALID) + end_request(0); + sjcd_send_cmd(SCMD_STOP); + sjcd_transfer_state = SJCD_S_IDLE; + goto ReSwitch; + } - /* - * Everything seems to be OK. Just read the frame and recalculate - * indices. - */ - sjcd_buf_bn[ sjcd_buf_in ] = -1; /* ??? */ - insb( SJCDPORT( 2 ), sjcd_buf + 2048 * sjcd_buf_in, 2048 ); -#if defined( SJCD_TRACE ) - printk( "SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n", - sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, - sjcd_buf_bn[ sjcd_buf_in ] ); -#endif - sjcd_buf_bn[ sjcd_buf_in ] = sjcd_next_bn++; - if( sjcd_buf_out == -1 ) sjcd_buf_out = sjcd_buf_in; - if( ++sjcd_buf_in == SJCD_BUF_SIZ ) sjcd_buf_in = 0; - - /* - * Only one frame is ready at time. So we should turn over to wait for - * another frame. If we need that, of course. - */ - if( --sjcd_read_count == 0 ){ /* - * OK, request seems to be precessed. Continue transferring... + * Get back in some time. 1 should be replaced with count variable to + * avoid unnecessary testings. */ - if( !sjcd_transfer_is_active ){ - while( CURRENT_IS_VALID ){ - /* - * Continue transferring. - */ - sjcd_transfer(); - if( CURRENT->nr_sectors == 0 ) end_request( 1 ); - else break; - } - } - if( CURRENT_IS_VALID && - ( CURRENT->sector / 4 < sjcd_next_bn || - CURRENT->sector / 4 > sjcd_next_bn + SJCD_BUF_SIZ ) ){ -#if defined( SJCD_TRACE ) - printk( "SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n" ); -#endif - sjcd_transfer_state = SJCD_S_STOP; - goto ReSwitch; - } - } - /* - * Now we should turn around rather than wait for while. - */ - goto sjcd_s_data; - } -#if defined( SJCD_GATHER_STAT ) - else statistic.data_ticks++; -#endif - break; - } - - case SJCD_S_STOP:{ - sjcd_read_count = 0; - sjcd_send_cmd( SCMD_STOP ); - sjcd_transfer_state = SJCD_S_STOPPING; - sjcd_transfer_timeout = 500; -#if defined( SJCD_GATHER_STAT ) - statistic.stop_ticks++; -#endif - break; - } + SJCD_SET_TIMER(sjcd_poll, 1); +} - case SJCD_S_STOPPING:{ - unsigned char stat; - - stat = inb( SJCDPORT( 1 ) ); -#if defined( SJCD_TRACE ) - printk( "SJCD_S_STOP: status = 0x%02x\n", stat ); -#endif - if( SJCD_DATA_AVAILABLE( stat ) ){ - int i; -#if defined( SJCD_TRACE ) - printk( "SJCD_S_STOP: discard data\n" ); -#endif - /* - * Discard all the data from the pipe. Foolish method. - */ - for( i = 2048; i--; ( void )inb( SJCDPORT( 2 ) ) ); - sjcd_transfer_timeout = 500; - } else if( SJCD_STATUS_AVAILABLE( stat ) ){ - sjcd_load_status(); - if( sjcd_status_valid && sjcd_media_is_changed ) { - sjcd_toc_uptodate = 0; - sjcd_invalidate_buffers(); - } - if( CURRENT_IS_VALID ){ - if( sjcd_status_valid ) sjcd_transfer_state = SJCD_S_READ; - else sjcd_transfer_state = SJCD_S_START; - } else sjcd_transfer_state = SJCD_S_IDLE; - goto ReSwitch; - } -#if defined( SJCD_GATHER_STAT ) - else statistic.stopping_ticks++; +static void do_sjcd_request(request_queue_t * q) +{ +#if defined( SJCD_TRACE ) + printk("SJCD: do_sjcd_request(%ld+%ld)\n", + CURRENT->sector, CURRENT->nr_sectors); #endif - break; - } - - default: - printk( "SJCD: poll: invalid state %d\n", sjcd_transfer_state ); - return; - } - - if( --sjcd_transfer_timeout == 0 ){ - printk( "SJCD: timeout in state %d\n", sjcd_transfer_state ); - while( CURRENT_IS_VALID ) end_request( 0 ); - sjcd_send_cmd( SCMD_STOP ); - sjcd_transfer_state = SJCD_S_IDLE; - goto ReSwitch; - } - - /* - * Get back in some time. 1 should be replaced with count variable to - * avoid unnecessary testings. - */ - SJCD_SET_TIMER( sjcd_poll, 1 ); -} - -static void do_sjcd_request( request_queue_t * q ){ -#if defined( SJCD_TRACE ) - printk( "SJCD: do_sjcd_request(%ld+%ld)\n", - CURRENT->sector, CURRENT->nr_sectors ); -#endif - sjcd_transfer_is_active = 1; - while( CURRENT_IS_VALID ){ - /* - * Who of us are paranoiac? - */ - if( CURRENT->bh && !buffer_locked(CURRENT->bh) ) - panic( DEVICE_NAME ": block not locked" ); - - sjcd_transfer(); - if( CURRENT->nr_sectors == 0 ) end_request( 1 ); - else { - sjcd_buf_out = -1; /* Want to read a block not in buffer */ - if( sjcd_transfer_state == SJCD_S_IDLE ){ - if( !sjcd_toc_uptodate ){ - if( sjcd_update_toc() < 0 ){ - printk( "SJCD: transfer: discard\n" ); - while( CURRENT_IS_VALID ) end_request( 0 ); - break; - } - } - sjcd_transfer_state = SJCD_S_START; - SJCD_SET_TIMER( sjcd_poll, HZ/100 ); - } - break; - } - } - sjcd_transfer_is_active = 0; -#if defined( SJCD_TRACE ) - printk( "sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n", - sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, sjcd_buf_bn[ sjcd_buf_in ] ); - printk( "do_sjcd_request ends\n" ); + sjcd_transfer_is_active = 1; + while (CURRENT_IS_VALID) { + /* + * Who of us are paranoiac? + */ + if (CURRENT->bh && !buffer_locked(CURRENT->bh)) + panic(DEVICE_NAME ": block not locked"); + + sjcd_transfer(); + if (CURRENT->nr_sectors == 0) + end_request(1); + else { + sjcd_buf_out = -1; /* Want to read a block not in buffer */ + if (sjcd_transfer_state == SJCD_S_IDLE) { + if (!sjcd_toc_uptodate) { + if (sjcd_update_toc() < 0) { + printk + ("SJCD: transfer: discard\n"); + while (CURRENT_IS_VALID) + end_request(0); + break; + } + } + sjcd_transfer_state = SJCD_S_START; + SJCD_SET_TIMER(sjcd_poll, HZ / 100); + } + break; + } + } + sjcd_transfer_is_active = 0; +#if defined( SJCD_TRACE ) + printk + ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n", + sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, + sjcd_buf_bn[sjcd_buf_in]); + printk("do_sjcd_request ends\n"); #endif } /* * Open the device special file. Check disk is in. */ -int sjcd_open( struct inode *ip, struct file *fp ){ - /* - * Check the presence of device. - */ - if( !sjcd_present ) return( -ENXIO ); - - /* - * Only read operations are allowed. Really? (:-) - */ - if( fp->f_mode & 2 ) return( -EROFS ); - - MOD_INC_USE_COUNT; +int sjcd_open(struct inode *ip, struct file *fp) +{ + /* + * Check the presence of device. + */ + if (!sjcd_present) + return (-ENXIO); - if( sjcd_open_count == 0 ){ - int s, sjcd_open_tries; + /* + * Only read operations are allowed. Really? (:-) + */ + if (fp->f_mode & 2) + return (-EROFS); + + MOD_INC_USE_COUNT; + + if (sjcd_open_count == 0) { + int s, sjcd_open_tries; /* We don't know that, do we? */ /* sjcd_audio_status = CDROM_AUDIO_NO_STATUS; */ - sjcd_mode = 0; - sjcd_door_was_open = 0; - sjcd_transfer_state = SJCD_S_IDLE; - sjcd_invalidate_buffers(); - sjcd_status_valid = 0; - - /* - * Strict status checking. - */ - for( sjcd_open_tries = 4; --sjcd_open_tries; ){ - if( !sjcd_status_valid ) sjcd_get_status(); - if( !sjcd_status_valid ){ + sjcd_mode = 0; + sjcd_door_was_open = 0; + sjcd_transfer_state = SJCD_S_IDLE; + sjcd_invalidate_buffers(); + sjcd_status_valid = 0; + + /* + * Strict status checking. + */ + for (sjcd_open_tries = 4; --sjcd_open_tries;) { + if (!sjcd_status_valid) + sjcd_get_status(); + if (!sjcd_status_valid) { #if defined( SJCD_DIAGNOSTIC ) - printk( "SJCD: open: timed out when check status.\n" ); + printk + ("SJCD: open: timed out when check status.\n"); #endif - goto err_out; - } else if( !sjcd_media_is_available ){ + goto err_out; + } else if (!sjcd_media_is_available) { #if defined( SJCD_DIAGNOSTIC ) - printk("SJCD: open: no disk in drive\n"); + printk("SJCD: open: no disk in drive\n"); #endif - if( !sjcd_door_closed ){ - sjcd_door_was_open = 1; + if (!sjcd_door_closed) { + sjcd_door_was_open = 1; #if defined( SJCD_TRACE ) - printk("SJCD: open: close the tray\n"); + printk + ("SJCD: open: close the tray\n"); #endif - s = sjcd_tray_close(); - if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ + s = sjcd_tray_close(); + if (s < 0 || !sjcd_status_valid + || sjcd_command_failed) { #if defined( SJCD_DIAGNOSTIC ) - printk("SJCD: open: tray close attempt failed\n"); + printk + ("SJCD: open: tray close attempt failed\n"); #endif - goto err_out; - } - continue; - } else goto err_out; - } - break; - } - s = sjcd_tray_lock(); - if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ + goto err_out; + } + continue; + } else + goto err_out; + } + break; + } + s = sjcd_tray_lock(); + if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { #if defined( SJCD_DIAGNOSTIC ) - printk("SJCD: open: tray lock attempt failed\n"); + printk("SJCD: open: tray lock attempt failed\n"); #endif - goto err_out; - } + goto err_out; + } #if defined( SJCD_TRACE ) - printk( "SJCD: open: done\n" ); + printk("SJCD: open: done\n"); #endif - } + } - ++sjcd_open_count; - return( 0 ); + ++sjcd_open_count; + return (0); -err_out: - MOD_DEC_USE_COUNT; - return( -EIO ); + err_out: + MOD_DEC_USE_COUNT; + return (-EIO); } /* * On close, we flush all sjcd blocks from the buffer cache. */ -static int sjcd_release( struct inode *inode, struct file *file ){ - int s; +static int sjcd_release(struct inode *inode, struct file *file) +{ + int s; #if defined( SJCD_TRACE ) - printk( "SJCD: release\n" ); + printk("SJCD: release\n"); #endif #ifdef MODULE - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; #endif - if( --sjcd_open_count == 0 ){ - sjcd_invalidate_buffers(); - s = sjcd_tray_unlock(); - if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ + if (--sjcd_open_count == 0) { + sjcd_invalidate_buffers(); + s = sjcd_tray_unlock(); + if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { #if defined( SJCD_DIAGNOSTIC ) - printk("SJCD: release: tray unlock attempt failed.\n"); + printk + ("SJCD: release: tray unlock attempt failed.\n"); #endif - } - if( sjcd_door_was_open ){ - s = sjcd_tray_open(); - if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ + } + if (sjcd_door_was_open) { + s = sjcd_tray_open(); + if (s < 0 || !sjcd_status_valid + || sjcd_command_failed) { #if defined( SJCD_DIAGNOSTIC ) - printk("SJCD: release: tray unload attempt failed.\n"); + printk + ("SJCD: release: tray unload attempt failed.\n"); #endif - } - } - } - return 0; + } + } + } + return 0; } /* * A list of file operations allowed for this cdrom. */ static struct block_device_operations sjcd_fops = { - open: sjcd_open, - release: sjcd_release, - ioctl: sjcd_ioctl, - check_media_change: sjcd_disk_change, + open:sjcd_open, + release:sjcd_release, + ioctl:sjcd_ioctl, + check_media_change:sjcd_disk_change, }; static int blksize = 2048; @@ -1453,146 +1678,156 @@ * The version is two BCD-coded bytes. */ static struct { - unsigned char major, minor; + unsigned char major, minor; } sjcd_version; /* * Test for presence of drive and initialize it. Called at boot time. * Probe cdrom, find out version and status. */ -int __init sjcd_init( void ){ - int i; +int __init sjcd_init(void) +{ + int i; - printk(KERN_INFO "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", SJCD_VERSION_MAJOR, - SJCD_VERSION_MINOR); + printk(KERN_INFO + "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", + SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR); #if defined( SJCD_TRACE ) - printk("SJCD: sjcd=0x%x: ", sjcd_base); -#endif + printk("SJCD: sjcd=0x%x: ", sjcd_base); +#endif hardsect_size[MAJOR_NR] = &secsize; blksize_size[MAJOR_NR] = &blksize; - if( devfs_register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){ - printk( "SJCD: Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR ); - return( -EIO ); - } - - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); - read_ahead[ MAJOR_NR ] = 4; - register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &sjcd_fops, 0); - - if( check_region( sjcd_base, 4 ) ){ - printk( "SJCD: Init failed, I/O port (%X) is already in use\n", - sjcd_base ); - sjcd_cleanup(); - return( -EIO ); - } - - /* - * Check for card. Since we are booting now, we can't use standard - * wait algorithm. - */ - printk(KERN_INFO "SJCD: Resetting: " ); - sjcd_send_cmd( SCMD_RESET ); - for( i = 1000; i > 0 && !sjcd_status_valid; --i ){ - unsigned long timer; - - /* - * Wait 10ms approx. - */ - for( timer = jiffies; time_before_eq(jiffies, timer); ); - if ( (i % 100) == 0 ) printk( "." ); - ( void )sjcd_check_status(); - } - if( i == 0 || sjcd_command_failed ){ - printk( " reset failed, no drive found.\n" ); - sjcd_cleanup(); - return( -EIO ); - } else printk( "\n" ); - - /* - * Get and print out cdrom version. - */ - printk(KERN_INFO "SJCD: Getting version: " ); - sjcd_send_cmd( SCMD_GET_VERSION ); - for( i = 1000; i > 0 && !sjcd_status_valid; --i ){ - unsigned long timer; - - /* - * Wait 10ms approx. - */ - for( timer = jiffies; time_before_eq(jiffies, timer); ); - if ( (i % 100) == 0 ) printk( "." ); - ( void )sjcd_check_status(); - } - if( i == 0 || sjcd_command_failed ){ - printk( " get version failed, no drive found.\n" ); - sjcd_cleanup(); - return( -EIO ); - } - - if( sjcd_load_response( &sjcd_version, sizeof( sjcd_version ) ) == 0 ){ - printk( " %1x.%02x\n", ( int )sjcd_version.major, - ( int )sjcd_version.minor ); - } else { - printk( " read version failed, no drive found.\n" ); - sjcd_cleanup(); - return( -EIO ); - } - - /* - * Check and print out the tray state. (if it is needed?). - */ - if( !sjcd_status_valid ){ - printk(KERN_INFO "SJCD: Getting status: " ); - sjcd_send_cmd( SCMD_GET_STATUS ); - for( i = 1000; i > 0 && !sjcd_status_valid; --i ){ - unsigned long timer; - - /* - * Wait 10ms approx. - */ - for( timer = jiffies; time_before_eq(jiffies, timer); ); - if ( (i % 100) == 0 ) printk( "." ); - ( void )sjcd_check_status(); - } - if( i == 0 || sjcd_command_failed ){ - printk( " get status failed, no drive found.\n" ); - sjcd_cleanup(); - return( -EIO ); - } else printk( "\n" ); - } - - printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); - devfs_register (NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, - S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL); - - sjcd_present++; - return( 0 ); -} - -static int -sjcd_cleanup(void) -{ - if( (devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL) ) - printk( "SJCD: cannot unregister device.\n" ); - else { - release_region( sjcd_base, 4 ); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - } + if (devfs_register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) { + printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n", + MAJOR_NR); + return (-EIO); + } + + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + read_ahead[MAJOR_NR] = 4; + register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &sjcd_fops, 0); + + if (check_region(sjcd_base, 4)) { + printk + ("SJCD: Init failed, I/O port (%X) is already in use\n", + sjcd_base); + sjcd_cleanup(); + return (-EIO); + } + + /* + * Check for card. Since we are booting now, we can't use standard + * wait algorithm. + */ + printk(KERN_INFO "SJCD: Resetting: "); + sjcd_send_cmd(SCMD_RESET); + for (i = 1000; i > 0 && !sjcd_status_valid; --i) { + unsigned long timer; + + /* + * Wait 10ms approx. + */ + for (timer = jiffies; time_before_eq(jiffies, timer);); + if ((i % 100) == 0) + printk("."); + (void) sjcd_check_status(); + } + if (i == 0 || sjcd_command_failed) { + printk(" reset failed, no drive found.\n"); + sjcd_cleanup(); + return (-EIO); + } else + printk("\n"); + + /* + * Get and print out cdrom version. + */ + printk(KERN_INFO "SJCD: Getting version: "); + sjcd_send_cmd(SCMD_GET_VERSION); + for (i = 1000; i > 0 && !sjcd_status_valid; --i) { + unsigned long timer; + + /* + * Wait 10ms approx. + */ + for (timer = jiffies; time_before_eq(jiffies, timer);); + if ((i % 100) == 0) + printk("."); + (void) sjcd_check_status(); + } + if (i == 0 || sjcd_command_failed) { + printk(" get version failed, no drive found.\n"); + sjcd_cleanup(); + return (-EIO); + } + + if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) { + printk(" %1x.%02x\n", (int) sjcd_version.major, + (int) sjcd_version.minor); + } else { + printk(" read version failed, no drive found.\n"); + sjcd_cleanup(); + return (-EIO); + } + + /* + * Check and print out the tray state. (if it is needed?). + */ + if (!sjcd_status_valid) { + printk(KERN_INFO "SJCD: Getting status: "); + sjcd_send_cmd(SCMD_GET_STATUS); + for (i = 1000; i > 0 && !sjcd_status_valid; --i) { + unsigned long timer; + + /* + * Wait 10ms approx. + */ + for (timer = jiffies; + time_before_eq(jiffies, timer);); + if ((i % 100) == 0) + printk("."); + (void) sjcd_check_status(); + } + if (i == 0 || sjcd_command_failed) { + printk(" get status failed, no drive found.\n"); + sjcd_cleanup(); + return (-EIO); + } else + printk("\n"); + } + + printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); + devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, + S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL); + + sjcd_present++; + return (0); +} + +static int sjcd_cleanup(void) +{ + if ((devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) + printk("SJCD: cannot unregister device.\n"); + else { + release_region(sjcd_base, 4); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + } - return(0); + return (0); } void __exit sjcd_exit(void) { - devfs_unregister(devfs_find_handle(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK,0)); - if ( sjcd_cleanup() ) - printk( "SJCD: module: cannot be removed.\n" ); - else - printk(KERN_INFO "SJCD: module: removed.\n"); + devfs_unregister(devfs_find_handle + (NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0)); + if (sjcd_cleanup()) + printk("SJCD: module: cannot be removed.\n"); + else + printk(KERN_INFO "SJCD: module: removed.\n"); } #ifdef MODULE @@ -1601,3 +1836,4 @@ module_exit(sjcd_exit); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.4.9/linux/drivers/char/Makefile Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/Makefile Sun Sep 2 07:48:02 2001 @@ -48,20 +48,6 @@ SERIAL = endif -ifeq ($(ARCH),s390) - KEYMAP = - KEYBD = - CONSOLE = - SERIAL = -endif - -ifeq ($(ARCH),s390x) - KEYMAP = - KEYBD = - CONSOLE = - SERIAL = -endif - ifeq ($(ARCH),m68k) ifdef CONFIG_AMIGA KEYBD = amikeyb.o @@ -241,5 +227,7 @@ consolemap_deftbl.o: consolemap_deftbl.c $(TOPDIR)/include/linux/types.h +.DELETE_ON_ERROR: + defkeymap.c: defkeymap.map - loadkeys --mktable defkeymap.map > defkeymap.c + set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ diff -u --recursive --new-file v2.4.9/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h --- v2.4.9/linux/drivers/char/agp/agp.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/agp/agp.h Mon Aug 27 07:40:33 2001 @@ -101,6 +101,7 @@ int num_aperture_sizes; int num_of_masks; int capndx; + int cant_use_aperture; /* Links to driver specific functions */ diff -u --recursive --new-file v2.4.9/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c --- v2.4.9/linux/drivers/char/agp/agpgart_be.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/agp/agpgart_be.c Mon Aug 27 07:40:33 2001 @@ -305,6 +305,9 @@ void agp_copy_info(agp_kern_info * info) { + unsigned long page_mask = 0; + int i; + memset(info, 0, sizeof(agp_kern_info)); if (agp_bridge.type == NOT_SUPPORTED) { info->chipset = agp_bridge.type; @@ -319,6 +322,12 @@ info->aper_size = agp_return_size(); info->max_memory = agp_bridge.max_memory_agp; info->current_memory = atomic_read(&agp_bridge.current_memory_agp); + info->cant_use_aperture = agp_bridge.cant_use_aperture; + + for(i = 0; i < agp_bridge.num_of_masks; i++) + page_mask |= agp_bridge.mask_memory(page_mask, i); + + info->page_mask = ~page_mask; } /* End - Routine to copy over information structure */ @@ -1083,6 +1092,7 @@ agp_bridge.free_by_type = intel_i810_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; } @@ -1275,6 +1285,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1305,6 +1316,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1335,6 +1347,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1452,6 +1465,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1563,6 +1577,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; } @@ -1938,6 +1953,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -2181,6 +2197,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = ali_alloc_page; agp_bridge.agp_destroy_page = ali_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -2766,6 +2783,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; pci_read_config_dword(agp_bridge.dev, SVWRKS_APSIZE, diff -u --recursive --new-file v2.4.9/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c --- v2.4.9/linux/drivers/char/busmouse.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/busmouse.c Fri Sep 7 09:28:38 2001 @@ -29,7 +29,7 @@ /* Uncomment this if your mouse drivers expect the kernel to * return with EAGAIN if the mouse does not have any events - * available, even if the mouse is opened in nonblocking mode. + * available, even if the mouse is opened in blocking mode. * Please report use of this "feature" to the author using the * above address. */ @@ -444,3 +444,5 @@ EXPORT_SYMBOL(busmouse_add_buttons); EXPORT_SYMBOL(register_busmouse); EXPORT_SYMBOL(unregister_busmouse); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/ati_pcigart.h linux/drivers/char/drm/ati_pcigart.h --- v2.4.9/linux/drivers/char/drm/ati_pcigart.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/ati_pcigart.h Sat Sep 8 18:57:19 2001 @@ -72,8 +72,6 @@ int i; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !address ) return; - page = virt_to_page( address ); for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) { @@ -84,23 +82,40 @@ free_pages( address, ATI_PCIGART_TABLE_ORDER ); } -unsigned long DRM(ati_pcigart_init)( drm_device_t *dev ) +int DRM(ati_pcigart_init)( drm_device_t *dev, + unsigned long *addr, + dma_addr_t *bus_addr) { drm_sg_mem_t *entry = dev->sg; - unsigned long address; + unsigned long address = 0; unsigned long pages; - u32 *pci_gart, page_base; - int i, j; + u32 *pci_gart, page_base, bus_address = 0; + int i, j, ret = 0; if ( !entry ) { DRM_ERROR( "no scatter/gather memory!\n" ); - return 0; + goto done; } address = DRM(ati_alloc_pcigart_table)(); if ( !address ) { DRM_ERROR( "cannot allocate PCI GART page!\n" ); - return 0; + goto done; + } + + if ( !dev->pdev ) { + DRM_ERROR( "PCI device unknown!\n" ); + goto done; + } + + bus_address = pci_map_single(dev->pdev, (void *)address, + ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, + PCI_DMA_TODEVICE); + if (bus_address == 0) { + DRM_ERROR( "unable to map PCIGART pages!\n" ); + DRM(ati_free_pcigart_table)( address ); + address = 0; + goto done; } pci_gart = (u32 *)address; @@ -111,28 +126,72 @@ memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) ); for ( i = 0 ; i < pages ; i++ ) { - page_base = page_to_bus( entry->pagelist[i] ); + /* we need to support large memory configurations */ + entry->busaddr[i] = pci_map_single(dev->pdev, + page_address( entry->pagelist[i] ), + PAGE_SIZE, + PCI_DMA_TODEVICE); + if (entry->busaddr[i] == 0) { + DRM_ERROR( "unable to map PCIGART pages!\n" ); + DRM(ati_pcigart_cleanup)( dev, address, bus_address ); + address = 0; + bus_address = 0; + goto done; + } + page_base = (u32) entry->busaddr[i]; + for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { *pci_gart++ = cpu_to_le32( page_base ); page_base += ATI_PCIGART_PAGE_SIZE; } } + ret = 1; + #if __i386__ asm volatile ( "wbinvd" ::: "memory" ); #else mb(); #endif - return address; +done: + *addr = address; + *bus_addr = bus_address; + return ret; } -int DRM(ati_pcigart_cleanup)( unsigned long address ) +int DRM(ati_pcigart_cleanup)( drm_device_t *dev, + unsigned long addr, + dma_addr_t bus_addr) { + drm_sg_mem_t *entry = dev->sg; + unsigned long pages; + int i; - if ( address ) { - DRM(ati_free_pcigart_table)( address ); + /* we need to support large memory configurations */ + if ( !entry ) { + DRM_ERROR( "no scatter/gather memory!\n" ); + return 0; + } + + if ( bus_addr ) { + pci_unmap_single(dev->pdev, bus_addr, + ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, + PCI_DMA_TODEVICE); + + pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) + ? entry->pages : ATI_MAX_PCIGART_PAGES; + + for ( i = 0 ; i < pages ; i++ ) { + if ( !entry->busaddr[i] ) break; + pci_unmap_single(dev->pdev, entry->busaddr[i], + PAGE_SIZE, PCI_DMA_TODEVICE); + } + } + + if ( addr ) { + DRM(ati_free_pcigart_table)( addr ); } - return 0; + return 1; } diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drmP.h linux/drivers/char/drm/drmP.h --- v2.4.9/linux/drivers/char/drm/drmP.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/drmP.h Sat Sep 8 18:57:19 2001 @@ -76,6 +76,17 @@ #include #include "drm.h" +/* page_to_bus for earlier kernels, not optimal in all cases */ +#ifndef page_to_bus +#define page_to_bus(page) ((unsigned int)(virt_to_bus(page_address(page)))) +#endif + +/* We just use virt_to_bus for pci_map_single on older kernels */ +#if LINUX_VERSION_CODE < 0x020400 +#define pci_map_single(hwdev, ptr, size, direction) virt_to_bus(ptr) +#define pci_unmap_single(hwdev, dma_addr, size, direction) +#endif + /* DRM template customization defaults */ #ifndef __HAVE_AGP @@ -616,6 +627,8 @@ int acquired; unsigned long base; int agp_mtrr; + int cant_use_aperture; + unsigned long page_mask; } drm_agp_head_t; #endif @@ -624,6 +637,7 @@ void *virtual; int pages; struct page **pagelist; + dma_addr_t *busaddr; } drm_sg_mem_t; typedef struct drm_sigdata { @@ -714,6 +728,7 @@ #if __REALLY_HAVE_AGP drm_agp_head_t *agp; #endif + struct pci_dev *pdev; #ifdef __alpha__ #if LINUX_VERSION_CODE < 0x020403 struct pci_controler *hose; @@ -1018,8 +1033,12 @@ #endif /* ATI PCIGART support (ati_pcigart.h) */ -extern unsigned long DRM(ati_pcigart_init)(drm_device_t *dev); -extern int DRM(ati_pcigart_cleanup)(unsigned long address); +extern int DRM(ati_pcigart_init)(drm_device_t *dev, + unsigned long *addr, + dma_addr_t *bus_addr); +extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev, + unsigned long addr, + dma_addr_t bus_addr); #endif /* __KERNEL__ */ #endif diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_agpsupport.h linux/drivers/char/drm/drm_agpsupport.h --- v2.4.9/linux/drivers/char/drm/drm_agpsupport.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/drm_agpsupport.h Sat Sep 8 18:57:19 2001 @@ -316,6 +316,14 @@ default: head->chipset = "Unknown"; break; } +#if LINUX_VERSION_CODE <= 0x020408 + head->cant_use_aperture = 0; + head->page_mask = ~(0xfff); +#else + head->cant_use_aperture = head->agp_info.cant_use_aperture; + head->page_mask = head->agp_info.page_mask; +#endif + DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n", head->agp_info.version.major, head->agp_info.version.minor, diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_ioctl.h linux/drivers/char/drm/drm_ioctl.h --- v2.4.9/linux/drivers/char/drm/drm_ioctl.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/drm_ioctl.h Sat Sep 8 18:57:19 2001 @@ -98,7 +98,6 @@ } sprintf(dev->devname, "%s@%s", dev->name, dev->unique); -#ifdef __alpha__ do { struct pci_dev *pci_dev; int b, d, f; @@ -114,10 +113,13 @@ if (*p) break; pci_dev = pci_find_slot(b, PCI_DEVFN(d,f)); - if (pci_dev) - dev->hose = pci_dev->sysdata; - } while(0); + if (pci_dev) { + dev->pdev = pci_dev; +#ifdef __alpha__ + dev->hose = pci_dev->sysdata; #endif + } + } while(0); return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_scatter.h linux/drivers/char/drm/drm_scatter.h --- v2.4.9/linux/drivers/char/drm/drm_scatter.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/drm_scatter.h Sat Sep 8 18:57:20 2001 @@ -47,12 +47,15 @@ vfree( entry->virtual ); + DRM(free)( entry->busaddr, + entry->pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); DRM(free)( entry->pagelist, - entry->pages * sizeof(*entry->pagelist), - DRM_MEM_PAGES ); + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); DRM(free)( entry, - sizeof(*entry), - DRM_MEM_SGLISTS ); + sizeof(*entry), + DRM_MEM_SGLISTS ); } int DRM(sg_alloc)( struct inode *inode, struct file *filp, @@ -93,16 +96,31 @@ DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); return -ENOMEM; } - memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); + + entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); + if ( !entry->busaddr ) { + DRM(free)( entry->pagelist, + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + DRM(free)( entry, + sizeof(*entry), + DRM_MEM_SGLISTS ); + return -ENOMEM; + } + memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) ); entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); if ( !entry->virtual ) { + DRM(free)( entry->busaddr, + entry->pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); DRM(free)( entry->pagelist, - entry->pages * sizeof(*entry->pagelist), - DRM_MEM_PAGES ); + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); DRM(free)( entry, - sizeof(*entry), - DRM_MEM_SGLISTS ); + sizeof(*entry), + DRM_MEM_SGLISTS ); return -ENOMEM; } diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_vm.h linux/drivers/char/drm/drm_vm.h --- v2.4.9/linux/drivers/char/drm/drm_vm.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/drm_vm.h Sat Sep 8 18:57:19 2001 @@ -67,6 +67,70 @@ int write_access) #endif { +#if __REALLY_HAVE_AGP + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_map_t *map = NULL; + drm_map_list_t *r_list; + struct list_head *list; + + /* + * Find the right map + */ + + if(!dev->agp->cant_use_aperture) goto vm_nopage_error; + + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *)list; + map = r_list->map; + if (!map) continue; + if (map->offset == VM_OFFSET(vma)) break; + } + + if (map && map->type == _DRM_AGP) { + unsigned long offset = address - vma->vm_start; + unsigned long baddr = VM_OFFSET(vma) + offset; + struct drm_agp_mem *agpmem; + struct page *page; + +#if __alpha__ + /* + * Adjust to a bus-relative address + */ + baddr -= dev->hose->mem_space->start; +#endif + + /* + * It's AGP memory - find the real physical page to map + */ + for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) { + if (agpmem->bound <= baddr && + agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) + break; + } + + if (!agpmem) goto vm_nopage_error; + + /* + * Get the page, inc the use count, and return it + */ + offset = (baddr - agpmem->bound) >> PAGE_SHIFT; + agpmem->memory->memory[offset] &= dev->agp->page_mask; + page = virt_to_page(__va(agpmem->memory->memory[offset])); + get_page(page); + + DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n", + baddr, __va(agpmem->memory->memory[offset]), offset); + +#if LINUX_VERSION_CODE < 0x020317 + return page_address(page); +#else + return page; +#endif + } +vm_nopage_error: +#endif /* __REALLY_HAVE_AGP */ + return NOPAGE_SIGBUS; /* Disallow mremap */ } @@ -220,24 +284,27 @@ drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; - unsigned long physical; unsigned long offset; - unsigned long page; + unsigned long page_nr; + struct page *page; if (!dma) return NOPAGE_SIGBUS; /* Error */ if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */ offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ - page = offset >> PAGE_SHIFT; - physical = dma->pagelist[page] + (offset & (~PAGE_MASK)); - atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */ + page_nr = offset >> PAGE_SHIFT; + page = virt_to_page((dma->pagelist[page_nr] + + (offset & (~PAGE_MASK)))); - DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical); + get_page(page); + + DRM_DEBUG("0x%08lx (page %lu) => 0x%08x\n", address, page_nr, + page_to_bus(page)); #if LINUX_VERSION_CODE < 0x020317 - return physical; + return page_address(page); #else - return virt_to_page(physical); + return page; #endif } @@ -274,10 +341,10 @@ map_offset = map->offset - dev->sg->handle; page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); page = entry->pagelist[page_offset]; - atomic_inc(&page->count); /* Dec. by kernel */ + get_page(page); #if LINUX_VERSION_CODE < 0x020317 - return (unsigned long)virt_to_phys(page->virtual); + return page_address(page); #else return page; #endif @@ -435,9 +502,20 @@ } switch (map->type) { + case _DRM_AGP: +#if defined(__alpha__) + /* + * On Alpha we can't talk to bus dma address from the + * CPU, so for memory of type DRM_AGP, we'll deal with + * sorting out the real physical pages and mappings + * in nopage() + */ + vma->vm_ops = &DRM(vm_ops); + break; +#endif + /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: - case _DRM_AGP: if (VM_OFFSET(vma) >= __pa(high_memory)) { #if defined(__i386__) if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/mga_drv.h linux/drivers/char/drm/mga_drv.h --- v2.4.9/linux/drivers/char/drm/mga_drv.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/mga_drv.h Mon Aug 27 07:40:33 2001 @@ -145,14 +145,28 @@ #define mga_flush_write_combine() mb() -#define MGA_BASE( reg ) ((u32)(dev_priv->mmio->handle)) +#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 ) + +#ifdef __alpha__ +#define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg))) +#define MGA_WRITE( reg, val ) do { wmb(); MGA_DEREF( reg ) = val; } while (0) +#define MGA_WRITE8( reg, val ) do { wmb(); MGA_DEREF8( reg ) = val; } while (0) + +static inline u32 _MGA_READ(u32 *addr) +{ + mb(); + return *(volatile u32 *)addr; +} + +#else #define MGA_READ( reg ) MGA_DEREF( reg ) #define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0) -#define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg ) #define MGA_WRITE8( reg, val ) do { MGA_DEREF8( reg ) = val; } while (0) +#endif #define DWGREG0 0x1c00 #define DWGREG0_END 0x1dff diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/r128_cce.c linux/drivers/char/drm/r128_cce.c --- v2.4.9/linux/drivers/char/drm/r128_cce.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/r128_cce.c Mon Aug 27 07:40:33 2001 @@ -351,11 +351,10 @@ page_ofs = tmp_ofs >> PAGE_SHIFT; R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, - page_to_bus(entry->pagelist[page_ofs])); - - DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", - page_to_bus(entry->pagelist[page_ofs]), - entry->handle + tmp_ofs ); + entry->busaddr[page_ofs]); + DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", + entry->busaddr[page_ofs], + entry->handle + tmp_ofs ); } /* Set watermark control */ @@ -599,15 +598,14 @@ dev_priv->sarea_priv->last_dispatch ); if ( dev_priv->is_pci ) { - dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev ); - if ( !dev_priv->phys_pci_gart ) { + if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, + &dev_priv->bus_pci_gart) ) { DRM_ERROR( "failed to init PCI GART!\n" ); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); return -ENOMEM; } - R128_WRITE( R128_PCI_GART_PAGE, - virt_to_bus( (void *)dev_priv->phys_pci_gart ) ); + R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart ); } r128_cce_init_ring_buffer( dev, dev_priv ); @@ -629,6 +627,11 @@ DRM_IOREMAPFREE( dev_priv->cce_ring ); DRM_IOREMAPFREE( dev_priv->ring_rptr ); DRM_IOREMAPFREE( dev_priv->buffers ); + } else { + if (!DRM(ati_pcigart_cleanup)( dev, + dev_priv->phys_pci_gart, + dev_priv->bus_pci_gart )) + DRM_ERROR( "failed to cleanup PCI GART!\n" ); } DRM(free)( dev->dev_private, sizeof(drm_r128_private_t), diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/r128_drv.h linux/drivers/char/drm/r128_drv.h --- v2.4.9/linux/drivers/char/drm/r128_drv.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/r128_drv.h Mon Aug 27 07:40:33 2001 @@ -72,6 +72,7 @@ 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; diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/radeon_cp.c linux/drivers/char/drm/radeon_cp.c --- v2.4.9/linux/drivers/char/drm/radeon_cp.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/radeon_cp.c Mon Aug 27 07:40:33 2001 @@ -624,10 +624,9 @@ page_ofs = tmp_ofs >> PAGE_SHIFT; RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, - page_to_bus(entry->pagelist[page_ofs])); - + entry->busaddr[page_ofs]); DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - page_to_bus(entry->pagelist[page_ofs]), + entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -929,8 +928,8 @@ dev_priv->sarea_priv->last_clear ); if ( dev_priv->is_pci ) { - dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev ); - if ( !dev_priv->phys_pci_gart ) { + if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, + &dev_priv->bus_pci_gart)) { DRM_ERROR( "failed to init PCI GART!\n" ); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); @@ -944,8 +943,7 @@ /* set PCI GART page-table base address */ - RADEON_WRITE( RADEON_AIC_PT_BASE, - virt_to_bus( (void *)dev_priv->phys_pci_gart ) ); + RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart ); /* set address range for PCI address translate */ @@ -990,6 +988,11 @@ DRM_IOREMAPFREE( dev_priv->cp_ring ); DRM_IOREMAPFREE( dev_priv->ring_rptr ); DRM_IOREMAPFREE( dev_priv->buffers ); + } else { + if (!DRM(ati_pcigart_cleanup)( dev, + dev_priv->phys_pci_gart, + dev_priv->bus_pci_gart )) + DRM_ERROR( "failed to cleanup PCI GART!\n" ); } DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/radeon_drv.h linux/drivers/char/drm/radeon_drv.h --- v2.4.9/linux/drivers/char/drm/radeon_drv.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/radeon_drv.h Mon Aug 27 07:40:33 2001 @@ -84,6 +84,7 @@ int usec_timeout; int is_pci; unsigned long phys_pci_gart; + dma_addr_t bus_pci_gart; atomic_t idle_count; diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/tdfx_drv.c linux/drivers/char/drm/tdfx_drv.c --- v2.4.9/linux/drivers/char/drm/tdfx_drv.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/tdfx_drv.c Mon Aug 27 07:40:33 2001 @@ -44,13 +44,30 @@ #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 +#ifndef PCI_VENDOR_ID_3DFX +#define PCI_VENDOR_ID_3DFX 0x121A +#endif #ifndef PCI_DEVICE_ID_3DFX_VOODOO5 #define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009 #endif +#ifndef PCI_DEVICE_ID_3DFX_VOODOO4 +#define PCI_DEVICE_ID_3DFX_VOODOO4 0x0007 +#endif +#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_3000 /* Voodoo3 3000 */ +#define PCI_DEVICE_ID_3DFX_VOODOO3_3000 0x0005 +#endif +#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_2000 /* Voodoo3 3000 */ +#define PCI_DEVICE_ID_3DFX_VOODOO3_2000 0x0004 +#endif +#ifndef PCI_DEVICE_ID_3DFX_BANSHEE +#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003 +#endif static drm_pci_list_t DRM(idlist)[] = { { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE }, - { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3 }, + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_2000 }, + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_3000 }, + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO4 }, { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5 }, { 0, 0 } }; diff -u --recursive --new-file v2.4.9/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c --- v2.4.9/linux/drivers/char/dsp56k.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/dsp56k.c Fri Sep 7 09:28:38 2001 @@ -502,7 +502,7 @@ static devfs_handle_t devfs_handle; -static const char banner[] __initdata = KERN_INFO "DSP56k driver installed\n"; +static char banner[] __initdata = KERN_INFO "DSP56k driver installed\n"; static int __init dsp56k_init_driver(void) { @@ -531,3 +531,5 @@ devfs_unregister(devfs_handle); } module_exit(dsp56k_cleanup_driver); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.4.9/linux/drivers/char/misc.c Thu May 24 15:14:08 2001 +++ linux/drivers/char/misc.c Fri Sep 7 09:28:38 2001 @@ -273,9 +273,6 @@ #ifdef CONFIG_SGI_NEWPORT_GFX gfx_register (); #endif -#ifdef CONFIG_SGI - streamable_init (); -#endif #ifdef CONFIG_TOSHIBA tosh_init(); #endif diff -u --recursive --new-file v2.4.9/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c --- v2.4.9/linux/drivers/char/pc110pad.c Tue May 22 10:23:16 2001 +++ linux/drivers/char/pc110pad.c Fri Sep 7 09:28:38 2001 @@ -798,7 +798,7 @@ * asked to open it by an application. */ -static const char banner[] __initdata = KERN_INFO "PC110 digitizer pad at 0x%X, irq %d.\n"; +static char banner[] __initdata = KERN_INFO "PC110 digitizer pad at 0x%X, irq %d.\n"; static int __init pc110pad_init_driver(void) { @@ -840,3 +840,9 @@ module_init(pc110pad_init_driver); module_exit(pc110pad_exit_driver); + +MODULE_AUTHOR("Alan Cox, Robin O'Leary"); +MODULE_DESCRIPTION("Driver for the touchpad on the IBM PC110 palmtop"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.4.9/linux/drivers/char/pc_keyb.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/pc_keyb.c Tue Aug 28 07:09:44 2001 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -602,7 +603,7 @@ return 1; } -int pckbd_rate(struct kbd_repeat *rep) +static int pckbd_rate(struct kbd_repeat *rep) { if (rep == NULL) return -EINVAL; @@ -834,6 +835,8 @@ #if defined CONFIG_PSMOUSE psaux_init(); #endif + + kbd_rate = pckbd_rate; /* Ok, finally allocate the IRQ, and off we go.. */ kbd_request_irq(keyboard_interrupt); diff -u --recursive --new-file v2.4.9/linux/drivers/char/qpmouse.c linux/drivers/char/qpmouse.c --- v2.4.9/linux/drivers/char/qpmouse.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/char/qpmouse.c Fri Sep 7 09:28:38 2001 @@ -338,8 +338,8 @@ return 1; } -static const char msg_banner[] __initdata = KERN_INFO "82C710 type pointing device detected -- driver installed.\n"; -static const char msg_nomem[] __initdata = KERN_ERR "qpmouse: no queue memory.\n"; +static char msg_banner[] __initdata = KERN_INFO "82C710 type pointing device detected -- driver installed.\n"; +static char msg_nomem[] __initdata = KERN_ERR "qpmouse: no queue memory.\n"; static int __init qpmouse_init_driver(void) { @@ -371,3 +371,6 @@ module_init(qpmouse_init_driver); module_exit(qpmouse_exit_driver); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/rio/rio_linux.c linux/drivers/char/rio/rio_linux.c --- v2.4.9/linux/drivers/char/rio/rio_linux.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/rio/rio_linux.c Fri Sep 7 09:28:38 2001 @@ -248,6 +248,7 @@ #ifndef TWO_ZERO MODULE_AUTHOR("Rogier Wolff , Patrick van de Lageweg "); MODULE_DESCRIPTION("RIO driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(rio_poll, "i"); MODULE_PARM(rio_debug, "i"); MODULE_PARM(rio_irqmask, "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/rio/riocmd.c linux/drivers/char/rio/riocmd.c --- v2.4.9/linux/drivers/char/rio/riocmd.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/rio/riocmd.c Fri Sep 7 09:28:38 2001 @@ -481,7 +481,7 @@ not freed. */ /* Call tmgr HANGUP HERE */ /* Fix this later when every thing works !!!! RAMRAJ */ - gs_got_break (PortP); + gs_got_break (&PortP->gs); break; case COMPLETE: diff -u --recursive --new-file v2.4.9/linux/drivers/char/selection.c linux/drivers/char/selection.c --- v2.4.9/linux/drivers/char/selection.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/selection.c Fri Sep 7 09:28:38 2001 @@ -96,11 +96,7 @@ /* set inwordLut contents. Invoked by ioctl(). */ int sel_loadlut(const unsigned long arg) { - int err = -EFAULT; - - if (!copy_from_user(inwordLut, (u32 *)(arg+4), 32)) - err = 0; - return err; + return copy_from_user(inwordLut, (u32 *)(arg+4), 32) ? -EFAULT : 0; } /* does screen address p correspond to character at LH/RH edge of screen? */ @@ -130,15 +126,13 @@ args = (unsigned short *)(arg + 1); if (user) { - int err; - err = verify_area(VERIFY_READ, args, sizeof(short) * 5); - if (err) - return err; - get_user(xs, args++); - get_user(ys, args++); - get_user(xe, args++); - get_user(ye, args++); - get_user(sel_mode, args); + if (verify_area(VERIFY_READ, args, sizeof(short) * 5)) + return -EFAULT; + __get_user(xs, args++); + __get_user(ys, args++); + __get_user(xe, args++); + __get_user(ye, args++); + __get_user(sel_mode, args); } else { xs = *(args++); /* set selection from kernel */ ys = *(args++); diff -u --recursive --new-file v2.4.9/linux/drivers/char/serial_tx3912.c linux/drivers/char/serial_tx3912.c --- v2.4.9/linux/drivers/char/serial_tx3912.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/serial_tx3912.c Fri Sep 7 09:28:38 2001 @@ -0,0 +1,1079 @@ +/* + * drivers/char/serial_tx3912.c + * + * Copyright (C) 1999 Harald Koerfgen + * Copyright (C) 2000 Jim Pick + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Serial driver for TMPR3912/05 and PR31700 processors + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "serial_tx3912.h" + +/* + * Forward declarations for serial routines + */ +static void rs_disable_tx_interrupts (void * ptr); +static void rs_enable_tx_interrupts (void * ptr); +static void rs_disable_rx_interrupts (void * ptr); +static void rs_enable_rx_interrupts (void * ptr); +static int rs_get_CD (void * ptr); +static void rs_shutdown_port (void * ptr); +static int rs_set_real_termios (void *ptr); +static int rs_chars_in_buffer (void * ptr); +static void rs_hungup (void *ptr); +static void rs_close (void *ptr); + +/* + * Used by generic serial driver to access hardware + */ +static struct real_driver rs_real_driver = { + disable_tx_interrupts: rs_disable_tx_interrupts, + enable_tx_interrupts: rs_enable_tx_interrupts, + disable_rx_interrupts: rs_disable_rx_interrupts, + enable_rx_interrupts: rs_enable_rx_interrupts, + get_CD: rs_get_CD, + shutdown_port: rs_shutdown_port, + set_real_termios: rs_set_real_termios, + chars_in_buffer: rs_chars_in_buffer, + close: rs_close, + hungup: rs_hungup, +}; + +/* + * Structures and such for TTY sessions and usage counts + */ +static struct tty_driver rs_driver, rs_callout_driver; +static struct tty_struct * rs_table[TX3912_UART_NPORTS] = { NULL, }; +static struct termios ** rs_termios; +static struct termios ** rs_termios_locked; +struct rs_port *rs_ports; +int rs_refcount; +int rs_initialized = 0; + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c + * + * and look at the resulting assemble code in serial.s. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ +static inline void receive_char_pio(struct rs_port *port) +{ + struct tty_struct *tty = port->gs.tty; + unsigned char ch; + int counter = 2048; + + /* While there are characters, get them ... */ + while (counter>0) { + if (!(inl(port->base + TX3912_UART_CTRL1) & UART_RX_HOLD_FULL)) + break; + ch = inb(port->base + TX3912_UART_DATA); + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + *tty->flip.char_buf_ptr++ = ch; + *tty->flip.flag_buf_ptr++ = 0; + tty->flip.count++; + } + udelay(1); /* Allow things to happen - it take a while */ + counter--; + } + if (!counter) + printk( "Ugh, looped in receive_char_pio!\n" ); + + tty_flip_buffer_push(tty); + +#if 0 + /* Now handle error conditions */ + if (*status & (INTTYPE(UART_RXOVERRUN_INT) | + INTTYPE(UART_FRAMEERR_INT) | + INTTYPE(UART_PARITYERR_INT) | + INTTYPE(UART_BREAK_INT))) { + + /* + * Now check to see if character should be + * ignored, and mask off conditions which + * should be ignored. + */ + if (*status & port->ignore_status_mask) { + goto ignore_char; + } + *status &= port->read_status_mask; + + if (*status & INTTYPE(UART_BREAK_INT)) { + rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "handling break...."); + *tty->flip.flag_buf_ptr = TTY_BREAK; + } + else if (*status & INTTYPE(UART_PARITYERR_INT)) { + *tty->flip.flag_buf_ptr = TTY_PARITY; + } + else if (*status & INTTYPE(UART_FRAMEERR_INT)) { + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + if (*status & INTTYPE(UART_RXOVERRUN_INT)) { + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } + } + } + + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + +ignore_char: + tty_flip_buffer_push(tty); +#endif +} + +static inline void transmit_char_pio(struct rs_port *port) +{ + /* While I'm able to transmit ... */ + for (;;) { + if (!(inl(port->base + TX3912_UART_CTRL1) & UART_TX_EMPTY)) + break; + else if (port->x_char) { + outb(port->x_char, port->base + TX3912_UART_DATA); + port->icount.tx++; + port->x_char = 0; + } + else if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped || + port->gs.tty->hw_stopped) { + break; + } + else { + outb(port->gs.xmit_buf[port->gs.xmit_tail++], + port->base + TX3912_UART_DATA); + port->icount.tx++; + port->gs.xmit_tail &= SERIAL_XMIT_SIZE-1; + if (--port->gs.xmit_cnt <= 0) { + break; + } + } + udelay(10); /* Allow things to happen - it take a while */ + } + + if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped || + port->gs.tty->hw_stopped) { + rs_disable_tx_interrupts(port); + } + + if (port->gs.xmit_cnt <= port->gs.wakeup_chars) { + if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + port->gs.tty->ldisc.write_wakeup) + (port->gs.tty->ldisc.write_wakeup)(port->gs.tty); + rs_dprintk (TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", + port->gs.wakeup_chars); + wake_up_interruptible(&port->gs.tty->write_wait); + } +} + + + +static inline void check_modem_status(struct rs_port *port) +{ + /* We don't have a carrier detect line - but just respond + like we had one anyways so that open() becomes unblocked */ + wake_up_interruptible(&port->gs.open_wait); +} + +int count = 0; + +/* + * This is the serial driver's interrupt routine (inlined, because + * there are two different versions of this, one for each serial port, + * differing only by the bits used in interrupt status 2 register) + */ + +static inline void rs_rx_interrupt(int irq, void *dev_id, + struct pt_regs * regs, int intshift) +{ + struct rs_port * port; + unsigned long int2status; + unsigned long flags; + unsigned long ints; + + save_and_cli(flags); + + port = (struct rs_port *)dev_id; + rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "rs_interrupt (port %p, shift %d)...", port, intshift); + + /* Get the interrrupts we have enabled */ + int2status = IntStatus2 & IntEnable2; + + /* Get interrupts in easy to use form */ + ints = int2status >> intshift; + + /* Clear any interrupts we might be about to handle */ + IntClear2 = int2status & ( + (INTTYPE(UART_RXOVERRUN_INT) | + INTTYPE(UART_FRAMEERR_INT) | + INTTYPE(UART_BREAK_INT) | + INTTYPE(UART_PARITYERR_INT) | + INTTYPE(UART_RX_INT)) << intshift); + + if (!port || !port->gs.tty) { + restore_flags(flags); + return; + } + + /* RX Receiver Holding Register Overrun */ + if (ints & INTTYPE(UART_RXOVERRUN_INT)) { + rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "overrun"); + port->icount.overrun++; + } + + /* RX Frame Error */ + if (ints & INTTYPE(UART_FRAMEERR_INT)) { + rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "frame error"); + port->icount.frame++; + } + + /* Break signal received */ + if (ints & INTTYPE(UART_BREAK_INT)) { + rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "break"); + port->icount.brk++; + } + + /* RX Parity Error */ + if (ints & INTTYPE(UART_PARITYERR_INT)) { + rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "parity error"); + port->icount.parity++; + } + + /* Receive byte (non-DMA) */ + if (ints & INTTYPE(UART_RX_INT)) { + receive_char_pio(port); + } + + restore_flags(flags); + + rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "end.\n"); +} + +static inline void rs_tx_interrupt(int irq, void *dev_id, + struct pt_regs * regs, int intshift) +{ + struct rs_port * port; + unsigned long int2status; + unsigned long flags; + unsigned long ints; + + save_and_cli(flags); + + port = (struct rs_port *)dev_id; + rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "rs_interrupt (port %p, shift %d)...", port, intshift); + + /* Get the interrrupts we have enabled */ + int2status = IntStatus2 & IntEnable2; + + if (!port || !port->gs.tty) { + restore_flags(flags); + return; + } + + /* Get interrupts in easy to use form */ + ints = int2status >> intshift; + + /* Clear any interrupts we might be about to handle */ + IntClear2 = int2status & ( + (INTTYPE(UART_TX_INT) | + INTTYPE(UART_EMPTY_INT) | + INTTYPE(UART_TXOVERRUN_INT)) << intshift); + + /* TX holding register empty, so transmit byte (non-DMA) */ + if (ints & (INTTYPE(UART_TX_INT) | INTTYPE(UART_EMPTY_INT))) { + transmit_char_pio(port); + } + + /* TX Transmit Holding Register Overrun (shouldn't happen) */ + if (ints & INTTYPE(UART_TXOVERRUN_INT)) { + printk ( "rs: TX overrun\n"); + } + + /* + check_modem_status(); + */ + + restore_flags(flags); + + rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "end.\n"); +} + +static void rs_rx_interrupt_uarta(int irq, void *dev_id, + struct pt_regs * regs) +{ + rs_rx_interrupt(irq, dev_id, regs, UARTA_SHIFT); +} + +static void rs_tx_interrupt_uarta(int irq, void *dev_id, + struct pt_regs * regs) +{ + rs_tx_interrupt(irq, dev_id, regs, UARTA_SHIFT); +} + +/* + *********************************************************************** + * Here are the routines that actually * + * interface with the generic_serial driver * + *********************************************************************** + */ +static void rs_disable_tx_interrupts (void * ptr) +{ + struct rs_port *port = ptr; + unsigned long flags; + + save_and_cli(flags); + port->gs.flags &= ~GS_TX_INTEN; + + IntEnable2 &= ~((INTTYPE(UART_TX_INT) | + INTTYPE(UART_EMPTY_INT) | + INTTYPE(UART_TXOVERRUN_INT)) << port->intshift); + + IntClear2 = (INTTYPE(UART_TX_INT) | + INTTYPE(UART_EMPTY_INT) | + INTTYPE(UART_TXOVERRUN_INT)) << port->intshift; + + restore_flags(flags); +} + +static void rs_enable_tx_interrupts (void * ptr) +{ + struct rs_port *port = ptr; + unsigned long flags; + + save_and_cli(flags); + + IntClear2 = (INTTYPE(UART_TX_INT) | + INTTYPE(UART_EMPTY_INT) | + INTTYPE(UART_TXOVERRUN_INT)) << port->intshift; + + IntEnable2 |= (INTTYPE(UART_TX_INT) | + INTTYPE(UART_EMPTY_INT) | + INTTYPE(UART_TXOVERRUN_INT)) << port->intshift; + + /* Send a char to start TX interrupts happening */ + transmit_char_pio(port); + + restore_flags(flags); +} + +static void rs_disable_rx_interrupts (void * ptr) +{ + struct rs_port *port = ptr; + unsigned long flags; + + save_and_cli(flags); + + IntEnable2 &= ~((INTTYPE(UART_RX_INT) | + INTTYPE(UART_RXOVERRUN_INT) | + INTTYPE(UART_FRAMEERR_INT) | + INTTYPE(UART_BREAK_INT) | + INTTYPE(UART_PARITYERR_INT)) << port->intshift); + + IntClear2 = (INTTYPE(UART_RX_INT) | + INTTYPE(UART_RXOVERRUN_INT) | + INTTYPE(UART_FRAMEERR_INT) | + INTTYPE(UART_BREAK_INT) | + INTTYPE(UART_PARITYERR_INT)) << port->intshift; + + restore_flags(flags); +} + +static void rs_enable_rx_interrupts (void * ptr) +{ + struct rs_port *port = ptr; + unsigned long flags; + + save_and_cli(flags); + + IntEnable2 |= (INTTYPE(UART_RX_INT) | + INTTYPE(UART_RXOVERRUN_INT) | + INTTYPE(UART_FRAMEERR_INT) | + INTTYPE(UART_BREAK_INT) | + INTTYPE(UART_PARITYERR_INT)) << port->intshift; + + /* Empty the input buffer - apparently this is *vital* */ + while (inl(port->base + TX3912_UART_CTRL1) & UART_RX_HOLD_FULL) { + inb(port->base + TX3912_UART_DATA); + } + + IntClear2 = (INTTYPE(UART_RX_INT) | + INTTYPE(UART_RXOVERRUN_INT) | + INTTYPE(UART_FRAMEERR_INT) | + INTTYPE(UART_BREAK_INT) | + INTTYPE(UART_PARITYERR_INT)) << port->intshift; + + restore_flags(flags); +} + + +static int rs_get_CD (void * ptr) +{ + /* No Carried Detect in Hardware - just return true */ + func_exit(); + return (1); +} + +static void rs_shutdown_port (void * ptr) +{ + struct rs_port *port = ptr; + + func_enter(); + + port->gs.flags &= ~GS_ACTIVE; + + func_exit(); +} + +static int rs_set_real_termios (void *ptr) +{ + struct rs_port *port = ptr; + int t; + + switch (port->gs.baud) { + /* Save some typing work... */ +#define e(x) case x:t= TX3912_UART_CTRL2_B ## x ; break + e(300);e(600);e(1200);e(2400);e(4800);e(9600); + e(19200);e(38400);e(57600);e(76800);e(115200);e(230400); + case 0 :t = -1; + break; + default: + /* Can I return "invalid"? */ + t = TX3912_UART_CTRL2_B9600; + printk (KERN_INFO "rs: unsupported baud rate: %d.\n", port->gs.baud); + break; + } +#undef e + if (t >= 0) { + /* Jim: Set Hardware Baud rate - there is some good + code in drivers/char/serial.c */ + + /* Program hardware for parity, data bits, stop bits (note: these are hardcoded to 8N1 */ + UartA_Ctrl1 &= 0xf000000f; + UartA_Ctrl1 &= ~(UART_DIS_TXD | SER_SEVEN_BIT | SER_EVEN_PARITY | SER_TWO_STOP); + +#define CFLAG port->gs.tty->termios->c_cflag + if (C_PARENB(port->gs.tty)) { + if (!C_PARODD(port->gs.tty)) + UartA_Ctrl1 |= SER_EVEN_PARITY; + else + UartA_Ctrl1 |= SER_ODD_PARITY; + } + if ((CFLAG & CSIZE)==CS6) + printk(KERN_ERR "6 bits not supported\n"); + if ((CFLAG & CSIZE)==CS5) + printk(KERN_ERR "5 bits not supported\n"); + if ((CFLAG & CSIZE)==CS7) + UartA_Ctrl1 |= SER_SEVEN_BIT; + if (C_CSTOPB(port->gs.tty)) + UartA_Ctrl1 |= SER_TWO_STOP; + + outl(t, port->base + TX3912_UART_CTRL2); + outl(0, port->base + TX3912_UART_DMA_CTRL1); + outl(0, port->base + TX3912_UART_DMA_CTRL2); + UartA_Ctrl1 |= TX3912_UART_CTRL1_UARTON; + + /* wait until UARTA is stable */ + while (~UartA_Ctrl1 & TX3912_UART_CTRL1_UARTON); + } + + func_exit (); + return 0; +} + +static int rs_chars_in_buffer (void * ptr) +{ + struct rs_port *port = ptr; + int scratch; + + scratch = inl(port->base + TX3912_UART_CTRL1); + + return ((scratch & UART_TX_EMPTY) ? 0 : 1); +} + +/* ********************************************************************** * + * Here are the routines that actually * + * interface with the rest of the system * + * ********************************************************************** */ +static int rs_open (struct tty_struct * tty, struct file * filp) +{ + struct rs_port *port; + int retval, line; + + func_enter(); + + if (!rs_initialized) { + return -EIO; + } + + line = MINOR(tty->device) - tty->driver.minor_start; + rs_dprintk (TX3912_UART_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p)\n", + (int) current->pid, line, tty, current->tty); + + if ((line < 0) || (line >= TX3912_UART_NPORTS)) + return -ENODEV; + + /* Pre-initialized already */ + port = & rs_ports[line]; + + rs_dprintk (TX3912_UART_DEBUG_OPEN, "port = %p\n", port); + + tty->driver_data = port; + port->gs.tty = tty; + port->gs.count++; + + rs_dprintk (TX3912_UART_DEBUG_OPEN, "starting port\n"); + + /* + * Start up serial port + */ + retval = gs_init_port(&port->gs); + rs_dprintk (TX3912_UART_DEBUG_OPEN, "done gs_init\n"); + if (retval) { + port->gs.count--; + return retval; + } + + port->gs.flags |= GS_ACTIVE; + + rs_dprintk (TX3912_UART_DEBUG_OPEN, "before inc_use_count (count=%d.\n", + port->gs.count); + if (port->gs.count == 1) { + MOD_INC_USE_COUNT; + } + rs_dprintk (TX3912_UART_DEBUG_OPEN, "after inc_use_count\n"); + + /* Jim: Initialize port hardware here */ + + /* Enable high-priority interrupts for UARTA */ + IntEnable6 |= INT6_UARTARXINT; + rs_enable_rx_interrupts(&rs_ports[0]); + + retval = gs_block_til_ready(&port->gs, filp); + rs_dprintk (TX3912_UART_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", + retval, port->gs.count); + + if (retval) { + MOD_DEC_USE_COUNT; + port->gs.count--; + return retval; + } + /* tty->low_latency = 1; */ + + if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = port->gs.normal_termios; + else + *tty->termios = port->gs.callout_termios; + rs_set_real_termios (port); + } + + port->gs.session = current->session; + port->gs.pgrp = current->pgrp; + func_exit(); + + /* Jim */ +/* cli(); */ + + return 0; + +} + + + +static void rs_close (void *ptr) +{ + func_enter (); + + /* Anything to do here? */ + + MOD_DEC_USE_COUNT; + func_exit (); +} + + +/* I haven't the foggiest why the decrement use count has to happen + here. The whole linux serial drivers stuff needs to be redesigned. + My guess is that this is a hack to minimize the impact of a bug + elsewhere. Thinking about it some more. (try it sometime) Try + running minicom on a serial port that is driven by a modularized + driver. Have the modem hangup. Then remove the driver module. Then + exit minicom. I expect an "oops". -- REW */ +static void rs_hungup (void *ptr) +{ + func_enter (); + MOD_DEC_USE_COUNT; + func_exit (); +} + +static int rs_ioctl (struct tty_struct * tty, struct file * filp, + unsigned int cmd, unsigned long arg) +{ + int rc; + struct rs_port *port = tty->driver_data; + int ival; + + rc = 0; + switch (cmd) { + case TIOCGSOFTCAR: + rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), + (unsigned int *) arg); + break; + case TIOCSSOFTCAR: + if ((rc = verify_area(VERIFY_READ, (void *) arg, + sizeof(int))) == 0) { + get_user(ival, (unsigned int *) arg); + tty->termios->c_cflag = + (tty->termios->c_cflag & ~CLOCAL) | + (ival ? CLOCAL : 0); + } + break; + case TIOCGSERIAL: + if ((rc = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_struct))) == 0) + gs_getserial(&port->gs, (struct serial_struct *) arg); + break; + case TIOCSSERIAL: + if ((rc = verify_area(VERIFY_READ, (void *) arg, + sizeof(struct serial_struct))) == 0) + rc = gs_setserial(&port->gs, (struct serial_struct *) arg); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + + /* func_exit(); */ + return rc; +} + + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void rs_send_xchar(struct tty_struct * tty, char ch) +{ + struct rs_port *port = (struct rs_port *)tty->driver_data; + func_enter (); + + port->x_char = ch; + if (ch) { + /* Make sure transmit interrupts are on */ + rs_enable_tx_interrupts(tty); + } + + func_exit(); +} + + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ +#ifdef TX3912_UART_DEBUG_THROTTLE + char buf[64]; + + printk("throttle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + func_enter (); + + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); + + func_exit (); +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct rs_port *port = (struct rs_port *)tty->driver_data; +#ifdef TX3912_UART_DEBUG_THROTTLE + char buf[64]; + + printk("unthrottle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + func_enter(); + + if (I_IXOFF(tty)) { + if (port->x_char) + port->x_char = 0; + else + rs_send_xchar(tty, START_CHAR(tty)); + } + + func_exit(); +} + + + + + +/* ********************************************************************** * + * Here are the initialization routines. * + * ********************************************************************** */ + +void * ckmalloc (int size) +{ + void *p; + + p = kmalloc(size, GFP_KERNEL); + if (p) + memset(p, 0, size); + return p; +} + + + +static int rs_init_portstructs(void) +{ + struct rs_port *port; + int i; + + /* Debugging */ + func_enter(); + + rs_ports = ckmalloc(TX3912_UART_NPORTS * sizeof (struct rs_port)); + if (!rs_ports) + return -ENOMEM; + + rs_termios = ckmalloc(TX3912_UART_NPORTS * sizeof (struct termios *)); + if (!rs_termios) { + kfree (rs_ports); + return -ENOMEM; + } + + rs_termios_locked = ckmalloc(TX3912_UART_NPORTS * sizeof (struct termios *)); + if (!rs_termios_locked) { + kfree (rs_ports); + kfree (rs_termios); + return -ENOMEM; + } + + /* Adjust the values in the "driver" */ + rs_driver.termios = rs_termios; + rs_driver.termios_locked = rs_termios_locked; + + port = rs_ports; + for (i=0; i < TX3912_UART_NPORTS;i++) { + rs_dprintk (TX3912_UART_DEBUG_INIT, "initing port %d\n", i); + port->gs.callout_termios = tty_std_termios; + port->gs.normal_termios = tty_std_termios; + port->gs.magic = SERIAL_MAGIC; + port->gs.close_delay = HZ/2; + port->gs.closing_wait = 30 * HZ; + port->gs.rd = &rs_real_driver; +#ifdef NEW_WRITE_LOCKING + port->gs.port_write_sem = MUTEX; +#endif +#ifdef DECLARE_WAITQUEUE + init_waitqueue_head(&port->gs.open_wait); + init_waitqueue_head(&port->gs.close_wait); +#endif + port->base = (i == 0) ? TX3912_UARTA_BASE : TX3912_UARTB_BASE; + port->intshift = (i == 0) ? UARTA_SHIFT : UARTB_SHIFT; + rs_dprintk (TX3912_UART_DEBUG_INIT, "base 0x%08lx intshift %d\n", + port->base, port->intshift); + port++; + } + + func_exit(); + return 0; +} + +static int rs_init_drivers(void) +{ + int error; + + func_enter(); + + memset(&rs_driver, 0, sizeof(rs_driver)); + rs_driver.magic = TTY_DRIVER_MAGIC; + rs_driver.driver_name = "serial"; + rs_driver.name = "ttyS"; + rs_driver.major = TTY_MAJOR; + rs_driver.minor_start = 64; + rs_driver.num = TX3912_UART_NPORTS; + rs_driver.type = TTY_DRIVER_TYPE_SERIAL; + rs_driver.subtype = SERIAL_TYPE_NORMAL; + rs_driver.init_termios = tty_std_termios; + rs_driver.init_termios.c_cflag = + B115200 | CS8 | CREAD | HUPCL | CLOCAL; + rs_driver.refcount = &rs_refcount; + rs_driver.table = rs_table; + rs_driver.termios = rs_termios; + rs_driver.termios_locked = rs_termios_locked; + + rs_driver.open = rs_open; + rs_driver.close = gs_close; + rs_driver.write = gs_write; + rs_driver.put_char = gs_put_char; + rs_driver.flush_chars = gs_flush_chars; + rs_driver.write_room = gs_write_room; + rs_driver.chars_in_buffer = gs_chars_in_buffer; + rs_driver.flush_buffer = gs_flush_buffer; + rs_driver.ioctl = rs_ioctl; + rs_driver.throttle = rs_throttle; + rs_driver.unthrottle = rs_unthrottle; + rs_driver.set_termios = gs_set_termios; + rs_driver.stop = gs_stop; + rs_driver.start = gs_start; + rs_driver.hangup = gs_hangup; + + rs_callout_driver = rs_driver; + rs_callout_driver.name = "cua"; + rs_callout_driver.major = TTYAUX_MAJOR; + rs_callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if ((error = tty_register_driver(&rs_driver))) { + printk(KERN_ERR "Couldn't register serial driver, error = %d\n", + error); + return 1; + } + if ((error = tty_register_driver(&rs_callout_driver))) { + tty_unregister_driver(&rs_driver); + printk(KERN_ERR "Couldn't register callout driver, error = %d\n", + error); + return 1; + } + + func_exit(); + return 0; +} + + +void __init tx3912_rs_init(void) +{ + int rc; + + + func_enter(); + rs_dprintk (TX3912_UART_DEBUG_INIT, "Initing serial module... (rs_debug=%d)\n", rs_debug); + + rc = rs_init_portstructs (); + rs_init_drivers (); + if (request_irq(2, rs_tx_interrupt_uarta, SA_SHIRQ | SA_INTERRUPT, + "serial", &rs_ports[0])) { + printk(KERN_ERR "rs: Cannot allocate irq for UARTA.\n"); + rc = 0; + } + if (request_irq(3, rs_rx_interrupt_uarta, SA_SHIRQ | SA_INTERRUPT, + "serial", &rs_ports[0])) { + printk(KERN_ERR "rs: Cannot allocate irq for UARTA.\n"); + rc = 0; + } + + IntEnable6 |= INT6_UARTARXINT; + rs_enable_rx_interrupts(&rs_ports[0]); + +#ifndef CONFIG_SERIAL_TX3912_CONSOLE +{ + unsigned int scratch = 0; + + /* Setup master clock for UART */ + scratch = inl(TX3912_CLK_CTRL_BASE); + scratch &= ~TX3912_CLK_CTRL_SIBMCLKDIV_MASK; + scratch |= ((0x2 << TX3912_CLK_CTRL_SIBMCLKDIV_SHIFT) & + TX3912_CLK_CTRL_SIBMCLKDIV_MASK) + | TX3912_CLK_CTRL_SIBMCLKDIR + | TX3912_CLK_CTRL_ENSIBMCLK + | TX3912_CLK_CTRL_CSERSEL; + outl(scratch, TX3912_CLK_CTRL_BASE); + + /* Configure UARTA clock */ + scratch = inl(TX3912_CLK_CTRL_BASE); + scratch |= ((0x3 << TX3912_CLK_CTRL_CSERDIV_SHIFT) & + TX3912_CLK_CTRL_CSERDIV_MASK) + | TX3912_CLK_CTRL_ENCSERCLK + | TX3912_CLK_CTRL_ENUARTACLK; + outl(scratch, TX3912_CLK_CTRL_BASE); + + /* Setup UARTA for 115200,8N1 */ + outl(0, TX3912_UARTA_BASE + TX3912_UART_CTRL1); + outl(TX3912_UART_CTRL2_B115200, TX3912_UARTA_BASE + TX3912_UART_CTRL2); + outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL1); + outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL2); + + /* Enable UARTA */ + outl(TX3912_UART_CTRL1_ENUART, TX3912_UARTA_BASE + TX3912_UART_CTRL1); + while (~inl(TX3912_UARTA_BASE + TX3912_UART_CTRL1) & + TX3912_UART_CTRL1_UARTON); +} +#endif + + /* Note: I didn't do anything to enable the second UART */ + if (rc >= 0) + rs_initialized++; + + func_exit(); +} + +/* + * Begin serial console routines + */ +#ifdef CONFIG_SERIAL_TX3912_CONSOLE + +void serial_outc(unsigned char c) +{ + int i; + unsigned long int2; + #define BUSY_WAIT 10000 + + /* + * Turn UARTA interrupts off + */ + int2 = IntEnable2; + IntEnable2 &= + ~(INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY); + + /* + * The UART_TX_EMPTY bit in UartA_Ctrl1 seems + * not to be very reliable :-( + * + * Wait for the Tx register to become empty + */ + for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < BUSY_WAIT); i++); + + IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; + UartA_Data = c; + for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < BUSY_WAIT); i++); + IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; + + IntEnable2 = int2; +} + +static int serial_console_wait_key(struct console *co) +{ + unsigned int int2, res; + + int2 = IntEnable2; + IntEnable2 = 0; + + while (!(UartA_Ctrl1 & UART_RX_HOLD_FULL)); + res = UartA_Data; + udelay(10); + + IntEnable2 = int2; + return res; +} + +static void serial_console_write(struct console *co, const char *s, + unsigned count) +{ + unsigned int i; + + for (i = 0; i < count; i++) { + if (*s == '\n') + serial_outc('\r'); + serial_outc(*s++); + } +} + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +static __init int serial_console_setup(struct console *co, char *options) +{ + unsigned int scratch = 0; + + /* Setup master clock for UART */ + scratch = inl(TX3912_CLK_CTRL_BASE); + scratch &= ~TX3912_CLK_CTRL_SIBMCLKDIV_MASK; + scratch |= ((0x2 << TX3912_CLK_CTRL_SIBMCLKDIV_SHIFT) & + TX3912_CLK_CTRL_SIBMCLKDIV_MASK) + | TX3912_CLK_CTRL_SIBMCLKDIR + | TX3912_CLK_CTRL_ENSIBMCLK + | TX3912_CLK_CTRL_CSERSEL; + outl(scratch, TX3912_CLK_CTRL_BASE); + + /* Configure UARTA clock */ + scratch = inl(TX3912_CLK_CTRL_BASE); + scratch |= ((0x3 << TX3912_CLK_CTRL_CSERDIV_SHIFT) & + TX3912_CLK_CTRL_CSERDIV_MASK) + | TX3912_CLK_CTRL_ENCSERCLK + | TX3912_CLK_CTRL_ENUARTACLK; + outl(scratch, TX3912_CLK_CTRL_BASE); + + /* Setup UARTA for 115200,8N1 */ + outl(0, TX3912_UARTA_BASE + TX3912_UART_CTRL1); + outl(TX3912_UART_CTRL2_B115200, TX3912_UARTA_BASE + TX3912_UART_CTRL2); + outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL1); + outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL2); + + /* Enable UARTA */ + outl(TX3912_UART_CTRL1_ENUART, TX3912_UARTA_BASE + TX3912_UART_CTRL1); + while (~inl(TX3912_UARTA_BASE + TX3912_UART_CTRL1) & + TX3912_UART_CTRL1_UARTON); + + return 0; +} + +static struct console sercons = { + name: "ttyS", + write: serial_console_write, + device: serial_console_device, + wait_key: serial_console_wait_key, + setup: serial_console_setup, + flags: CON_PRINTBUFFER, + index: -1 +}; + +void __init tx3912_console_init(void) +{ + register_console(&sercons); +} + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/char/serial_tx3912.h linux/drivers/char/serial_tx3912.h --- v2.4.9/linux/drivers/char/serial_tx3912.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/serial_tx3912.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,92 @@ +/* + * drivers/char/serial_tx3912.h + * + * Copyright (C) 1999 Harald Koerfgen + * Copyright (C) 2000 Jim Pick + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Serial driver for TMPR3912/05 and PR31700 processors + */ +#include +#include + +/* UART Interrupt (Interrupt 2) bits (UARTA,UARTB) */ +#define UART_RX_INT 9 /* receiver holding register full (31, 21) */ +#define UART_RXOVERRUN_INT 8 /* receiver overrun error (30, 20) */ +#define UART_FRAMEERR_INT 7 /* receiver frame error (29, 19) */ +#define UART_BREAK_INT 6 /* received break signal (28, 18) */ +#define UART_PARITYERR_INT 5 /* receiver parity error (27, 17) */ +#define UART_TX_INT 4 /* transmit holding register empty (26, 16) */ +#define UART_TXOVERRUN_INT 3 /* transmit overrun error (25, 15) */ +#define UART_EMPTY_INT 2 /* both trans/recv regs empty (24, 14) */ +#define UART_DMAFULL_INT 1 /* DMA at end of buffer (23, 13) */ +#define UART_DMAHALF_INT 0 /* DMA halfway through buffer */ (22, 12) */ + +#define UARTA_SHIFT 22 +#define UARTB_SHIFT 12 + +#define INTTYPE(interrupttype) (1 << interrupttype) + +/* + * This driver can spew a whole lot of debugging output at you. If you + * need maximum performance, you should disable the DEBUG define. + */ +#undef TX3912_UART_DEBUG + +#ifdef TX3912_UART_DEBUG +#define TX3912_UART_DEBUG_OPEN 0x00000001 +#define TX3912_UART_DEBUG_SETTING 0x00000002 +#define TX3912_UART_DEBUG_FLOW 0x00000004 +#define TX3912_UART_DEBUG_MODEMSIGNALS 0x00000008 +#define TX3912_UART_DEBUG_TERMIOS 0x00000010 +#define TX3912_UART_DEBUG_TRANSMIT 0x00000020 +#define TX3912_UART_DEBUG_RECEIVE 0x00000040 +#define TX3912_UART_DEBUG_INTERRUPTS 0x00000080 +#define TX3912_UART_DEBUG_PROBE 0x00000100 +#define TX3912_UART_DEBUG_INIT 0x00000200 +#define TX3912_UART_DEBUG_CLEANUP 0x00000400 +#define TX3912_UART_DEBUG_CLOSE 0x00000800 +#define TX3912_UART_DEBUG_FIRMWARE 0x00001000 +#define TX3912_UART_DEBUG_MEMTEST 0x00002000 +#define TX3912_UART_DEBUG_THROTTLE 0x00004000 +#define TX3912_UART_DEBUG_ALL 0xffffffff + +int rs_debug = TX3912_UART_DEBUG_ALL & ~TX3912_UART_DEBUG_TRANSMIT; + +#define rs_dprintk(f, str...) if (rs_debug & f) printk (str) +#define func_enter() rs_dprintk (TX3912_UART_DEBUG_FLOW, \ + "rs: enter " __FUNCTION__ "\n") +#define func_exit() rs_dprintk (TX3912_UART_DEBUG_FLOW, \ + "rs: exit " __FUNCTION__ "\n") + +#else +#define rs_dprintk(f, str...) +#define func_enter() +#define func_exit() + +#endif /* TX3912_UART_DEBUG */ + +/* + * Number of serial ports + */ +#define TX3912_UART_NPORTS 2 + +/* + * Hardware specific serial port structure + */ +struct rs_port { + struct gs_port gs; /* Must be first field! */ + + unsigned long base; + int intshift; /* Register shift */ + struct wait_queue *shutdown_wait; + int stat_flags; + struct async_icount icount; /* Counters for 4 input IRQs */ + int read_status_mask; + int ignore_status_mask; + int x_char; /* XON/XOFF character */ +}; diff -u --recursive --new-file v2.4.9/linux/drivers/char/sh-sci.c linux/drivers/char/sh-sci.c --- v2.4.9/linux/drivers/char/sh-sci.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/char/sh-sci.c Sat Sep 8 12:29:09 2001 @@ -44,7 +44,7 @@ #include -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB +#ifdef CONFIG_SH_STANDARD_BIOS #include #endif @@ -94,6 +94,7 @@ #define dprintk(x...) do { if (sci_debug) printk(x); } while(0) +#ifdef CONFIG_SERIAL_CONSOLE static void put_char(struct sci_port *port, char c) { unsigned long flags; @@ -111,8 +112,9 @@ restore_flags(flags); } +#endif -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB +#ifdef CONFIG_SH_STANDARD_BIOS static void handle_error(struct sci_port *port) { /* Clear error flags */ @@ -161,12 +163,12 @@ * This routine does not wait for a positive acknowledge. */ -static void put_string(struct sci_port *port, - const char *buffer, int count) +#ifdef CONFIG_SERIAL_CONSOLE +static void put_string(struct sci_port *port, const char *buffer, int count) { int i; const unsigned char *p = buffer; -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB +#ifdef CONFIG_SH_STANDARD_BIOS int checksum; /* This call only does a trap the first time it is @@ -202,7 +204,7 @@ put_char(port, *p++); } } - +#endif static struct real_driver sci_real_driver = { @@ -1159,7 +1161,7 @@ sci_init_drivers(); -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB +#ifdef CONFIG_SH_STANDARD_BIOS sh_bios_gdb_detach(); #endif return 0; /* Return -EIO when not detected */ diff -u --recursive --new-file v2.4.9/linux/drivers/char/softdog.c linux/drivers/char/softdog.c --- v2.4.9/linux/drivers/char/softdog.c Sat May 19 17:43:05 2001 +++ linux/drivers/char/softdog.c Fri Sep 7 09:28:38 2001 @@ -160,7 +160,7 @@ fops: &softdog_fops, }; -static const char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.05, timer margin: %d sec\n"; +static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.05, timer margin: %d sec\n"; static int __init watchdog_init(void) { diff -u --recursive --new-file v2.4.9/linux/drivers/char/sx.c linux/drivers/char/sx.c --- v2.4.9/linux/drivers/char/sx.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/char/sx.c Fri Sep 7 09:28:38 2001 @@ -365,6 +365,8 @@ MODULE_PARM(sx_debug, "i"); MODULE_PARM(sx_irqmask, "i"); +MODULE_LICENSE("GPL"); + static struct real_driver sx_real_driver = { sx_disable_tx_interrupts, sx_enable_tx_interrupts, @@ -1139,7 +1141,7 @@ sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n"); sx_write_channel_byte (port, hi_state, hi_state); - gs_got_break (port); + gs_got_break (&port->gs); } if (hi_state & ST_DCD) { hi_state &= ~ST_DCD; @@ -1614,6 +1616,7 @@ #define R0 if (read_sx_word (board, i) != 0x55aa) return 1 #define R1 if (read_sx_word (board, i) != 0xaa55) return 1 +#if 0 /* This memtest takes a human-noticable time. You normally only do it once a boot, so I guess that it is worth it. */ static int do_memtest_w (struct sx_board *board, int min, int max) @@ -1628,6 +1631,7 @@ return 0; } +#endif static int sx_fw_ioctl (struct inode *inode, struct file *filp, diff -u --recursive --new-file v2.4.9/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c --- v2.4.9/linux/drivers/char/tpqic02.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/tpqic02.c Fri Sep 7 09:28:38 2001 @@ -92,7 +92,7 @@ #include #include #include -#include +#include #include #include @@ -116,8 +116,8 @@ * card+drive info if runtime configuration has been selected. */ -static struct mtconfiginfo qic02_tape_dynconf = /* user settable */ - { 0, 0, BOGUS_IRQ, 0, 0, TPQD_DEFAULT_FLAGS, }; +static struct mtconfiginfo qic02_tape_dynconf = /* user settable */ +{ 0, 0, BOGUS_IRQ, 0, 0, TPQD_DEFAULT_FLAGS, }; static struct qic02_ccb qic02_tape_ccb; /* private stuff */ #else @@ -127,11 +127,11 @@ # if ((QIC02_TAPE_IFC!=WANGTEK) && (QIC02_TAPE_IFC!=ARCHIVE) && (QIC02_TAPE_IFC!=MOUNTAIN)) # error No valid interface card specified # endif -#endif /* CONFIG_QIC02_DYNCONF */ +#endif /* CONFIG_QIC02_DYNCONF */ -static volatile int ctlbits; /* control reg bits for tape interface */ +static volatile int ctlbits; /* control reg bits for tape interface */ -static wait_queue_head_t qic02_tape_transfer; /* sync rw with interrupts */ +static wait_queue_head_t qic02_tape_transfer; /* sync rw with interrupts */ static volatile struct mtget ioctl_status; /* current generic status */ @@ -146,15 +146,15 @@ * by an interrupt. */ static volatile flag status_dead = YES; /* device is legally dead until proven alive */ -static flag status_zombie = YES; /* it's `zombie' until irq/dma allocated */ +static flag status_zombie = YES; /* it's `zombie' until irq/dma allocated */ static volatile flag status_bytes_wr = NO; /* write FM at close or not */ static volatile flag status_bytes_rd = NO; /* (rd|wr) used for rewinding */ -static volatile unsigned long status_cmd_pending; /* cmd in progress */ +static volatile unsigned long status_cmd_pending; /* cmd in progress */ static volatile flag status_expect_int = NO; /* ready for interrupts */ -static volatile flag status_timer_on = NO; /* using time-out */ -static volatile int status_error; /* int handler may detect error */ +static volatile flag status_timer_on = NO; /* using time-out */ +static volatile int status_error; /* int handler may detect error */ static volatile flag status_eof_detected = NO; /* end of file */ static volatile flag status_eom_detected = NO; /* end of recorded media */ static volatile flag status_eot_detected = NO; /* end of tape */ @@ -163,8 +163,8 @@ static volatile unsigned long dma_bytes_todo; static volatile unsigned long dma_bytes_done; -static volatile unsigned dma_mode; /* !=0 also means DMA in use */ -static flag need_rewind = YES; +static volatile unsigned dma_mode; /* !=0 also means DMA in use */ +static flag need_rewind = YES; static kdev_t current_tape_dev; static int extra_blocks_left = BLOCKS_BEYOND_EW; @@ -198,7 +198,7 @@ * mode is allowed as long as no actual writing has been done. After writing * the File Mark, repositioning and reading are allowed again. */ -static int mode_access; /* access mode: READ or WRITE */ +static int mode_access; /* access mode: READ or WRITE */ static int qic02_get_resources(void); static void qic02_release_resources(void); @@ -210,17 +210,17 @@ * must ensure that a large enough buffer is passed to the kernel, in order * to reduce tape repositioning wear and tear. */ -static void *buffaddr; /* virtual address of buffer */ +static void *buffaddr; /* virtual address of buffer */ /* This translates minor numbers to the corresponding recording format: */ static const char *format_names[] = { - "not set", /* for dumb drives unable to handle format selection */ - "11", /* extinct */ + "not set", /* for dumb drives unable to handle format selection */ + "11", /* extinct */ "24", "120", "150", - "300", /* untested. */ - "600" /* untested. */ + "300", /* untested. */ + "600" /* untested. */ }; @@ -248,52 +248,72 @@ const char *msg; /* EXC_nr attribute should match with tpqic02.h */ } exception_list[] = { - {0, 0, - "Unknown exception status code", /* extra: 0 */}, - {~(0), TP_ST0|TP_CNI|TP_USL|TP_WRP, - "Drive not online" /* 1 */}, - /* Drive presence goes before cartridge presence. */ - {~(TP_WRP|TP_USL), TP_ST0|TP_CNI, - /* My Wangtek 5150EQ sometimes reports a status code - * of 0x00e0, which is not a valid exception code, but - * I think it should be recognized as "NO CARTRIDGE". - */ - "Cartridge not in place" /* 2 */}, - {(unsigned short) ~(TP_ST1|TP_BOM), (TP_ST0|TP_WRP), - "Write protected cartridge" /* 3 */}, - {(unsigned short) ~(TP_ST1|TP_EOR), (TP_ST0|TP_EOM), - "End of media" /* 4 */}, - {~TP_WRP, TP_ST0|TP_UDA| TP_ST1|TP_BOM, - "Read or Write abort. Rewind tape." /* 5 */}, - {~TP_WRP, TP_ST0|TP_UDA, - "Read error. Bad block transferred." /* 6 */}, - {~TP_WRP, TP_ST0|TP_UDA|TP_BNL, - "Read error. Filler block transferred." /* 7 */}, - {~TP_WRP, TP_ST0|TP_UDA|TP_BNL |TP_ST1|TP_NDT, - "Read error. No data detected." /* 8 */}, - {~TP_WRP, TP_ST0|TP_EOM|TP_UDA|TP_BNL |TP_ST1|TP_NDT, - "Read error. No data detected. EOM." /* 9 */}, - {~(TP_WRP|TP_MBD|TP_PAR|TP_EOR), TP_ST0|TP_UDA|TP_BNL |TP_ST1|TP_NDT|TP_BOM, - "Read error. No data detected. BOM." /* 10 */}, - {~(TP_WRP|TP_EOM), TP_ST0|TP_FIL, - /* Status 0x0089 (EOM & FM) is viewed as an FM, - * because it can only happen during a read. - * EOM is checked separately for an FM condition. - */ - "File mark detected" /* 11 */}, - {~(TP_ST0|TP_CNI|TP_USL|TP_WRP|TP_BOM), TP_ST1|TP_ILL, - "Illegal command" /* 12 */}, - {~(TP_ST0|TP_CNI|TP_USL|TP_WRP|TP_BOM), TP_ST1|TP_POR, - "Reset occurred" /* 13 */}, - {~TP_WRP, TP_ST0|TP_FIL|TP_MBD, /* NOTE: ST1 not set! */ - "Marginal block detected" /* 14 */}, - {~(TP_ST0|TP_WRP|TP_EOM|TP_UDA|TP_BNL|TP_FIL |TP_NDT), TP_ST1|TP_EOR, + { + 0, 0, "Unknown exception status code", /* extra: 0 */ }, + { + ~(0), TP_ST0 | TP_CNI | TP_USL | TP_WRP, + "Drive not online" /* 1 */ }, + /* Drive presence goes before cartridge presence. */ + { + ~(TP_WRP | TP_USL), TP_ST0 | TP_CNI, + /* My Wangtek 5150EQ sometimes reports a status code + * of 0x00e0, which is not a valid exception code, but + * I think it should be recognized as "NO CARTRIDGE". + */ + "Cartridge not in place" /* 2 */ }, + { + (unsigned short) ~(TP_ST1 | TP_BOM), (TP_ST0 | TP_WRP), + "Write protected cartridge" /* 3 */ }, + { + (unsigned short) ~(TP_ST1 | TP_EOR), (TP_ST0 | TP_EOM), + "End of media" /* 4 */ }, + { + ~TP_WRP, TP_ST0 | TP_UDA | TP_ST1 | TP_BOM, + "Read or Write abort. Rewind tape." /* 5 */ }, + { + ~TP_WRP, TP_ST0 | TP_UDA, + "Read error. Bad block transferred." /* 6 */ }, + { + ~TP_WRP, TP_ST0 | TP_UDA | TP_BNL, + "Read error. Filler block transferred." /* 7 */ }, + { + ~TP_WRP, TP_ST0 | TP_UDA | TP_BNL | TP_ST1 | TP_NDT, + "Read error. No data detected." /* 8 */ }, + { + ~TP_WRP, + TP_ST0 | TP_EOM | TP_UDA | TP_BNL | TP_ST1 | + TP_NDT, "Read error. No data detected. EOM." /* 9 */ }, + { + ~(TP_WRP | TP_MBD | TP_PAR | TP_EOR), + TP_ST0 | TP_UDA | TP_BNL | TP_ST1 | TP_NDT | + TP_BOM, + "Read error. No data detected. BOM." /* 10 */ }, + { + ~(TP_WRP | TP_EOM), TP_ST0 | TP_FIL, + /* Status 0x0089 (EOM & FM) is viewed as an FM, + * because it can only happen during a read. + * EOM is checked separately for an FM condition. + */ + "File mark detected" /* 11 */ }, + { + ~(TP_ST0 | TP_CNI | TP_USL | TP_WRP | TP_BOM), + TP_ST1 | TP_ILL, "Illegal command" /* 12 */ }, + { + ~(TP_ST0 | TP_CNI | TP_USL | TP_WRP | TP_BOM), + TP_ST1 | TP_POR, "Reset occurred" /* 13 */ }, + { + ~TP_WRP, TP_ST0 | TP_FIL | TP_MBD, /* NOTE: ST1 not set! */ + "Marginal block detected" /* 14 */ }, + { + ~(TP_ST0 | TP_WRP | TP_EOM | TP_UDA | TP_BNL | TP_FIL | + TP_NDT), TP_ST1 | TP_EOR, /********** Is the extra TP_NDT really needed Eddy? **********/ - "End of recorded media" /* extra: 15 */}, - /* 15 is returned when SEEKEOD completes successfully */ - {~(TP_WRP|TP_ST0), TP_ST1|TP_BOM, - "Beginning of media" /* extra: 16 */} + "End of recorded media" /* extra: 15 */ }, + /* 15 is returned when SEEKEOD completes successfully */ + { + ~(TP_WRP | TP_ST0), TP_ST1 | TP_BOM, "Beginning of media" /* extra: 16 */ } }; + #define NR_OF_EXC (sizeof(exception_list)/sizeof(struct exception_list_type)) /* Compare expected struct size and actual struct size. This @@ -310,7 +330,7 @@ { if ((flags & TPQD_ALWAYS) || (flags & QIC02_TAPE_DEBUG)) printk(TPQIC02_NAME ": %s\n", s); -} /* tpqputs */ +} /* tpqputs */ /* Perform byte order swapping for a 16-bit word. @@ -318,11 +338,10 @@ * [FIXME] This should probably be in include/asm/ * ([FIXME] i486 can do this faster) */ -static inline void byte_swap_w(volatile unsigned short * w) +static inline void byte_swap_w(volatile unsigned short *w) { int t = *w; - - *w = (t>>8) | ((t & 0xff)<<8); + *w = (t >> 8) | ((t & 0xff) << 8); } @@ -334,37 +353,32 @@ */ static void ifc_init(void) { - if (QIC02_TAPE_IFC == WANGTEK) /* || (QIC02_TAPE_IFC == EVEREX) */ - { - ctlbits = WT_CTL_ONLINE; /* online */ - outb_p(ctlbits, QIC02_CTL_PORT); - } - else if (QIC02_TAPE_IFC == ARCHIVE) - { - ctlbits = 0; /* no interrupts yet */ - outb_p(ctlbits, QIC02_CTL_PORT); - outb_p(0, AR_RESET_DMA_PORT); /* dummy write to reset DMA */ - } - else /* MOUNTAIN */ - { - ctlbits = MTN_CTL_ONLINE; /* online, and logic enabled */ - outb_p(ctlbits, QIC02_CTL_PORT); - } -} /* ifc_init */ + if (QIC02_TAPE_IFC == WANGTEK) { /* || (QIC02_TAPE_IFC == EVEREX) */ + ctlbits = WT_CTL_ONLINE; /* online */ + outb_p(ctlbits, QIC02_CTL_PORT); + } else if (QIC02_TAPE_IFC == ARCHIVE) { + ctlbits = 0; /* no interrupts yet */ + outb_p(ctlbits, QIC02_CTL_PORT); + outb_p(0, AR_RESET_DMA_PORT); /* dummy write to reset DMA */ + } else { /* MOUNTAIN */ + + ctlbits = MTN_CTL_ONLINE; /* online, and logic enabled */ + outb_p(ctlbits, QIC02_CTL_PORT); + } +} /* ifc_init */ static void report_qic_exception(unsigned n) { - if (n >= NR_OF_EXC) - { - tpqputs(TPQD_ALWAYS, "Oops -- report_qic_exception"); - n = 0; - } - if (TPQDBG(SENSE_TEXT) || n==0) - { - printk(TPQIC02_NAME ": sense: %s\n", exception_list[n].msg); - } -} /* report_qic_exception */ + if (n >= NR_OF_EXC) { + tpqputs(TPQD_ALWAYS, "Oops -- report_qic_exception"); + n = 0; + } + if (TPQDBG(SENSE_TEXT) || n == 0) { + printk(TPQIC02_NAME ": sense: %s\n", + exception_list[n].msg); + } +} /* report_qic_exception */ /* Try to map the drive-exception bits `s' to a predefined "exception number", @@ -374,18 +388,18 @@ */ static int decode_qic_exception_nr(unsigned s) { - int i; + int i; - for (i=1; i=25 usec. */ - udelay(30); - - /* after reset, we will be at BOT (modulo an automatic rewind) */ - status_eof_detected = NO; - status_eom_detected = NO; - status_cmd_pending = 0; - need_rewind = YES; - doing_read = doing_write = NO; - ioctl_status.mt_fileno = ioctl_status.mt_blkno = 0; - - /* de-assert reset */ - if (QIC02_TAPE_IFC == MOUNTAIN) - { - outb_p(ctlbits | MTN_QIC02_CTL_RESET_NOT, QIC02_CTL_PORT); - } - else - { - outb_p(ctlbits & ~QIC02_CTL_RESET, QIC02_CTL_PORT); - } - - /* KLUDGE FOR G++ BUG */ - { int stat = inb_p(QIC02_STAT_PORT); - status_dead = ((stat & QIC02_STAT_RESETMASK) != QIC02_STAT_RESETVAL); } - /* if successful, inb(STAT) returned RESETVAL */ - if (status_dead == YES) - { - printk(TPQIC02_NAME ": reset failed!\n"); - } - else if (verbose) - { - printk(TPQIC02_NAME ": reset successful\n"); - } - - return (status_dead == YES)? TE_DEAD : TE_OK; -} /* tape_reset */ + /* assert reset */ + if (QIC02_TAPE_IFC == MOUNTAIN) { + outb_p(ctlbits & ~MTN_QIC02_CTL_RESET_NOT, QIC02_CTL_PORT); + } else { /* WANGTEK, ARCHIVE */ + + outb_p(ctlbits | QIC02_CTL_RESET, QIC02_CTL_PORT); + } + + /* Next, we need to wait >=25 usec. */ + udelay(30); + + /* after reset, we will be at BOT (modulo an automatic rewind) */ + status_eof_detected = NO; + status_eom_detected = NO; + status_cmd_pending = 0; + need_rewind = YES; + doing_read = doing_write = NO; + ioctl_status.mt_fileno = ioctl_status.mt_blkno = 0; + + /* de-assert reset */ + if (QIC02_TAPE_IFC == MOUNTAIN) { + outb_p(ctlbits | MTN_QIC02_CTL_RESET_NOT, QIC02_CTL_PORT); + } else { + outb_p(ctlbits & ~QIC02_CTL_RESET, QIC02_CTL_PORT); + } + + /* KLUDGE FOR G++ BUG */ + { + int stat = inb_p(QIC02_STAT_PORT); + status_dead = + ((stat & QIC02_STAT_RESETMASK) != QIC02_STAT_RESETVAL); + } + /* if successful, inb(STAT) returned RESETVAL */ + if (status_dead == YES) { + printk(TPQIC02_NAME ": reset failed!\n"); + } else if (verbose) { + printk(TPQIC02_NAME ": reset successful\n"); + } + + return (status_dead == YES) ? TE_DEAD : TE_OK; +} /* tape_reset */ @@ -504,7 +505,7 @@ { int i; - outb_p(cmd, QIC02_CMD_PORT); /* output the command */ + outb_p(cmd, QIC02_CMD_PORT); /* output the command */ /* wait 1 usec before asserting /REQUEST */ udelay(1); @@ -512,7 +513,7 @@ if ((!ignore_ex) && is_exception()) { tpqputs(TPQD_ALWAYS, "*** exception detected in notify_cmd"); /** force a reset here **/ - if (tape_reset(1)==TE_DEAD) + if (tape_reset(1) == TE_DEAD) return TE_DEAD; if (is_exception()) { tpqputs(TPQD_ALWAYS, "exception persists after reset."); @@ -520,33 +521,36 @@ } } - outb_p(ctlbits | QIC02_CTL_REQUEST, QIC02_CTL_PORT); /* set request bit */ + outb_p(ctlbits | QIC02_CTL_REQUEST, QIC02_CTL_PORT); /* set request bit */ i = TAPE_NOTIFY_TIMEOUT; /* The specs say this takes about 500 usec, but there is no upper limit! * If the drive were busy retensioning or something like that, * it could be *much* longer! */ - while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) && (--i>0)) - /*skip*/; /* wait for ready */ - if (i==0) { - tpqputs(TPQD_ALWAYS, "timed out waiting for ready in notify_cmd"); + while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) && (--i > 0)) + /*skip */ ; + /* wait for ready */ + if (i == 0) { + tpqputs(TPQD_ALWAYS, + "timed out waiting for ready in notify_cmd"); status_dead = YES; return TE_TIM; } - outb_p(ctlbits & ~QIC02_CTL_REQUEST, QIC02_CTL_PORT); /* reset request bit */ + outb_p(ctlbits & ~QIC02_CTL_REQUEST, QIC02_CTL_PORT); /* reset request bit */ i = TAPE_NOTIFY_TIMEOUT; /* according to the specs this one should never time-out */ - while (((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) == 0) && (--i>0)) - /*skip*/; /* wait for not ready */ - if (i==0) { + while (((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) == 0) && (--i > 0)) + /*skip */ ; + /* wait for not ready */ + if (i == 0) { tpqputs(TPQD_ALWAYS, "timed out waiting for !ready in notify_cmd"); status_dead = YES; return TE_TIM; } /* command accepted */ return TE_OK; -} /* notify_cmd */ +} /* notify_cmd */ @@ -563,20 +567,22 @@ * First, busy wait a few usec: */ spin_t = 50; - while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && (--spin_t>0)) + while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && (--spin_t > 0)) /*SKIP*/; if ((stat & QIC02_STAT_READY) == 0) - return TE_OK; /* covers 99.99% of all calls */ + return TE_OK; /* covers 99.99% of all calls */ /* Then use schedule() a few times */ - spin_t = 3; /* max 0.03 sec busy waiting */ + spin_t = 3; /* max 0.03 sec busy waiting */ if (spin_t > timeout) spin_t = timeout; timeout -= spin_t; spin_t += jiffies; - while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && time_before(jiffies, spin_t)) - schedule(); /* don't waste all the CPU time */ + /* FIXME...*/ + while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) + && time_before(jiffies, spin_t)) + schedule(); /* don't waste all the CPU time */ if ((stat & QIC02_STAT_READY) == 0) return TE_OK; @@ -589,13 +595,13 @@ spin_t += timeout; TPQDEB({printk("wait_for_ready: additional timeout: %d\n", spin_t);}) - /* not ready and no exception && timeout not expired yet */ + /* not ready and no exception && timeout not expired yet */ while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && time_before(jiffies, spin_t)) { /* be `nice` to other processes on long operations... */ current->state = TASK_INTERRUPTIBLE; /* nap 0.30 sec between checks, */ /* but could be woken up earlier by signals... */ - schedule_timeout(3*HZ/10); + schedule_timeout(3 * HZ / 10); } /* don't use jiffies for this test because it may have changed by now */ @@ -605,12 +611,13 @@ } if ((stat & QIC02_STAT_EXCEPTION) == 0) { - tpqputs(TPQD_ALWAYS, "exception detected after waiting_for_ready"); + tpqputs(TPQD_ALWAYS, + "exception detected after waiting_for_ready"); return TE_EX; } else { return TE_OK; } -} /* wait_for_ready */ +} /* wait_for_ready */ @@ -619,7 +626,7 @@ { int i, stat; - for (i=0; i0) && ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK)) - n--; /* wait for ready or exception or timeout */ - if (n==0) { + n = 1000; /* 500 is not enough on a 486/33 */ + while ((n > 0) && ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK)) + n--; /* wait for ready or exception or timeout */ + if (n == 0) { /* n (above) should be chosen such that on your machine * you rarely ever see the message below, and it should * be small enough to give reasonable response time.] */ + /* FIXME */ tpqputs(TPQD_ALWAYS, "waiting looong in rdstatus() -- drive dead?"); while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) schedule(); tpqputs(TPQD_ALWAYS, "finished waiting in rdstatus()"); } - (void) notify_cmd(qcmd, 1); /* send read status command */ + (void) notify_cmd(qcmd, 1); /* send read status command */ /* ignore return code -- should always be ok, STAT may contain * exception flag from previous exception which we are trying to clear. */ @@ -715,21 +723,22 @@ if (TP_DIAGS(current_tape_dev)) printk(TPQIC02_NAME ": reading status bytes: "); - for (q=stp; q0) || dma_mode) { + if ((status_cmd_pending > 0) || dma_mode) { /* takes tooo long, shut it down */ status_dead = YES; status_cmd_pending = 0; @@ -1614,7 +1655,7 @@ wake_up(&qic02_tape_transfer); } } -} /* qic02_tape_times_out */ +} /* qic02_tape_times_out */ /* * Interrupt handling: @@ -1647,7 +1688,8 @@ * When we are finished, set flags to indicate end, disable timer. * NOTE: This *must* be fast! */ -static void qic02_tape_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void qic02_tape_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { int stat, r, i; unsigned long flags; @@ -1662,20 +1704,21 @@ stat = inb(QIC02_STAT_PORT); /* Knock, knock */ if (QIC02_TAPE_IFC == ARCHIVE) { /* "Who's there?" */ if (((stat & (AR_STAT_DMADONE)) == 0) && - ((stat & (QIC02_STAT_EXCEPTION)) != 0)) { + ((stat & (QIC02_STAT_EXCEPTION)) != 0)) { TIMERCONT; - return; /* "Linux with IRQ sharing" */ + return; /* "Linux with IRQ sharing" */ } } if ((stat & QIC02_STAT_EXCEPTION) == 0) { /* exception occurred */ /* Possible causes for an exception during a transfer: - * - during a write-cycle: end of tape (EW) hole detected. - * - during a read-cycle: filemark or EOD detected. - * - something went wrong + * - during a write-cycle: end of tape (EW) hole detected. + * - during a read-cycle: filemark or EOD detected. + * - something went wrong * So don't continue with the next block. */ - tpqputs(TPQD_ALWAYS, "isr: exception on tape controller"); + tpqputs(TPQD_ALWAYS, + "isr: exception on tape controller"); printk(" status %02x\n", stat); status_error = TE_EX; @@ -1691,25 +1734,27 @@ */ r = 0; - /* Skip next ready check for Archive controller because - * it may be busy reading ahead. Weird. --hhb - */ + /* Skip next ready check for Archive controller because + * it may be busy reading ahead. Weird. --hhb + */ if (QIC02_TAPE_IFC == WANGTEK) /* I think this is a drive-dependency, not IFC -- hhb */ - if (stat & QIC02_STAT_READY) { /* not ready */ - tpqputs(TPQD_ALWAYS, "isr: ? Tape controller not ready"); + if (stat & QIC02_STAT_READY) { /* not ready */ + tpqputs(TPQD_ALWAYS, + "isr: ? Tape controller not ready"); r = 1; } - flags=claim_dma_lock(); - - if ( (i = get_dma_residue(QIC02_TAPE_DMA)) != 0 ) { - printk(TPQIC02_NAME ": dma_residue == %x !!!\n", i); + flags = claim_dma_lock(); + + if ((i = get_dma_residue(QIC02_TAPE_DMA)) != 0) { + printk(TPQIC02_NAME ": dma_residue == %x !!!\n", + i); r = 1; /* big trouble, but can't do much about it... */ } - + release_dma_lock(flags); - if (r) + if (r) return; /* finish DMA cycle */ @@ -1724,14 +1769,14 @@ wake_up(&qic02_tape_transfer); } else { /* start next transfer, account for track-switching time */ - mod_timer(&tp_timer, jiffies + 6*HZ); + mod_timer(&tp_timer, jiffies + 6 * HZ); dma_transfer(); } } else { printk(TPQIC02_NAME ": Unexpected interrupt, stat == %x\n", inb(QIC02_STAT_PORT)); } -} /* qic02_tape_interrupt */ +} /* qic02_tape_interrupt */ /* read/write routines: @@ -1766,190 +1811,173 @@ * request would return the EOF flag for the previous file. */ -static ssize_t qic02_tape_read(struct file * filp, char * buf, size_t count, loff_t *ppos) +static ssize_t qic02_tape_read(struct file *filp, char *buf, size_t count, + loff_t * ppos) { - int err; - kdev_t dev = filp->f_dentry->d_inode->i_rdev; - unsigned short flags = filp->f_flags; - unsigned long bytes_todo, bytes_done, total_bytes_done = 0; - int stat; - - if (status_zombie==YES) - { - tpqputs(TPQD_ALWAYS, "configs not set"); - return -ENXIO; - } - - if (TP_DIAGS(current_tape_dev)) - /* can't print a ``long long'' (for filp->f_pos), so chop it */ - printk(TPQIC02_NAME ": request READ, minor=%x, buf=%p, count=%lx" - ", pos=%lx, flags=%x\n", - MINOR(dev), buf, (long) count, - (unsigned long) filp->f_pos, flags); - - if (count % TAPE_BLKSIZE) /* Only allow mod 512 bytes at a time. */ - { - tpqputs(TPQD_BLKSZ, "Wrong block size"); - return -EINVAL; - } + int err; + kdev_t dev = filp->f_dentry->d_inode->i_rdev; + unsigned short flags = filp->f_flags; + unsigned long bytes_todo, bytes_done, total_bytes_done = 0; + int stat; + + if (status_zombie == YES) { + tpqputs(TPQD_ALWAYS, "configs not set"); + return -ENXIO; + } - /* Just assume everything is ok. Controller will scream if not. */ + if (TP_DIAGS(current_tape_dev)) + /* can't print a ``long long'' (for filp->f_pos), so chop it */ + printk(TPQIC02_NAME + ": request READ, minor=%x, buf=%p, count=%lx" + ", pos=%lx, flags=%x\n", MINOR(dev), buf, + (long) count, (unsigned long) filp->f_pos, flags); - if (status_bytes_wr) /* Once written, no more reads, 'till after WFM. */ - { - return -EACCES; - } - - /* This is rather ugly because it has to implement a finite state - * machine in order to handle the EOF situations properly. - */ - while ((signed)count>=0) - { - bytes_done = 0; - /* see how much fits in the kernel buffer */ - bytes_todo = TPQBUF_SIZE; - if (bytes_todo>count) - { - bytes_todo = count; + if (count % TAPE_BLKSIZE) { /* Only allow mod 512 bytes at a time. */ + tpqputs(TPQD_BLKSZ, "Wrong block size"); + return -EINVAL; } - - /* Must ensure that user program sees exactly one EOF token (==0) */ - if (return_read_eof==YES) - { - if (TPQDBG(DEBUG)) - { - printk("read: return_read_eof==%d, reported_read_eof==%d, total_bytes_done==%lu\n", return_read_eof, reported_read_eof, total_bytes_done); - } - - if (reported_read_eof==NO) - { - /* have not yet returned EOF to user program */ - if (total_bytes_done>0) - { - return total_bytes_done; /* next time return EOF */ - } - else - { - reported_read_eof = YES; /* move on next time */ - return 0; /* return EOF */ - } - } - else - { - /* Application program has already received EOF - * (above), now continue with next file on tape, - * if possible. - * When the FM is reached, EXCEPTION is set, - * causing a sense(). Subsequent read/writes will - * continue after the FM. - */ + + /* Just assume everything is ok. Controller will scream if not. */ + + if (status_bytes_wr) { /* Once written, no more reads, 'till after WFM. */ + return -EACCES; + } + + /* This is rather ugly because it has to implement a finite state + * machine in order to handle the EOF situations properly. + */ + while ((signed) count >= 0) { + bytes_done = 0; + /* see how much fits in the kernel buffer */ + bytes_todo = TPQBUF_SIZE; + if (bytes_todo > count) { + bytes_todo = count; + } + + /* Must ensure that user program sees exactly one EOF token (==0) */ + if (return_read_eof == YES) { + if (TPQDBG(DEBUG)) { + printk + ("read: return_read_eof==%d, reported_read_eof==%d, total_bytes_done==%lu\n", + return_read_eof, reported_read_eof, + total_bytes_done); + } + + if (reported_read_eof == NO) { + /* have not yet returned EOF to user program */ + if (total_bytes_done > 0) { + return total_bytes_done; /* next time return EOF */ + } else { + reported_read_eof = YES; /* move on next time */ + return 0; /* return EOF */ + } + } else { + /* Application program has already received EOF + * (above), now continue with next file on tape, + * if possible. + * When the FM is reached, EXCEPTION is set, + * causing a sense(). Subsequent read/writes will + * continue after the FM. + */ /*********** ?????????? this should check for (EOD|NDT), not EOM, 'cause we can read past EW: ************/ - if (status_eom_detected) - { - /* If EOM, nothing left to read, so keep returning EOFs. - *** should probably set some flag to avoid clearing - *** status_eom_detected through ioctls or something - */ - return 0; - } - else - { - /* just eof, there may be more files ahead... */ - return_read_eof = NO; - reported_read_eof = NO; - status_eof_detected = NO; /* reset this too */ - /*fall through*/ + if (status_eom_detected) { + /* If EOM, nothing left to read, so keep returning EOFs. + *** should probably set some flag to avoid clearing + *** status_eom_detected through ioctls or something + */ + return 0; + } else { + /* just eof, there may be more files ahead... */ + return_read_eof = NO; + reported_read_eof = NO; + status_eof_detected = NO; /* reset this too */ + /*fall through */ + } + } } - } - } - + /*****************************/ - if (bytes_todo==0) - { - return total_bytes_done; - } - - if (bytes_todo>0) - { - /* start reading data */ - if (is_exception()) /****************************************/ - { - tpqputs(TPQD_DMAX, "is_exception() before start_dma()!"); - } - + if (bytes_todo == 0) { + return total_bytes_done; + } + + if (bytes_todo > 0) { + /* start reading data */ + if (is_exception()) { +/****************************************/ + tpqputs(TPQD_DMAX, + "is_exception() before start_dma()!"); + } + /****************************************************************** ***** if start_dma() fails because the head is positioned 0 bytes ***** before the FM, (causing EXCEPTION to be set) return_read_eof should ***** be set to YES, and we should return total_bytes_done, rather than -ENXIO. ***** The app should recognize this as an EOF condition. ***************************************************************************/ - stat = start_dma(READ, bytes_todo); - if (stat == TE_OK) - { - /* Wait for transfer to complete, interrupt should wake us */ - while (dma_mode != 0) - { - sleep_on(&qic02_tape_transfer); - } - if (status_error) - { - return_read_eof = YES; - } - - } - else if (stat != TE_END) - { - /* should do sense() on error here */ + stat = start_dma(READ, bytes_todo); + if (stat == TE_OK) { + /* Wait for transfer to complete, interrupt should wake us */ + while (dma_mode != 0) { + sleep_on(&qic02_tape_transfer); + } + if (status_error) { + return_read_eof = YES; + } + + } else if (stat != TE_END) { + /* should do sense() on error here */ #if 0 - return -ENXIO; + return -ENXIO; #else - printk("Trouble: stat==%02x\n", stat); - return_read_eof = YES; + printk("Trouble: stat==%02x\n", stat); + return_read_eof = YES; /*************** check EOF/EOT handling!!!!!! **/ #endif - } - end_dma(&bytes_done); - if (bytes_done>bytes_todo) - { - tpqputs(TPQD_ALWAYS, "read: Oops, read more bytes than requested"); - return -EIO; - } - /* copy buffer to user-space in one go */ - if (bytes_done>0) - { - err = copy_to_user(buf, buffaddr, bytes_done); - if (err) - { - return -EFAULT; - } - } + } + end_dma(&bytes_done); + if (bytes_done > bytes_todo) { + tpqputs(TPQD_ALWAYS, + "read: Oops, read more bytes than requested"); + return -EIO; + } + /* copy buffer to user-space in one go */ + if (bytes_done > 0) { + err = + copy_to_user(buf, buffaddr, + bytes_done); + if (err) { + return -EFAULT; + } + } #if 1 - /* Checks Ton's patch below */ - if ((return_read_eof == NO) && (status_eof_detected == YES)) - { - printk(TPQIC02_NAME ": read(): return_read_eof=%d, status_eof_detected=YES. return_read_eof:=YES\n", return_read_eof); - } + /* Checks Ton's patch below */ + if ((return_read_eof == NO) + && (status_eof_detected == YES)) { + printk(TPQIC02_NAME + ": read(): return_read_eof=%d, status_eof_detected=YES. return_read_eof:=YES\n", + return_read_eof); + } #endif - if ((bytes_todo != bytes_done) || (status_eof_detected == YES)) - { - /* EOF or EOM detected. return EOF next time. */ - return_read_eof = YES; - } - - } /* else: ignore read request for 0 bytes */ + if ((bytes_todo != bytes_done) + || (status_eof_detected == YES)) { + /* EOF or EOM detected. return EOF next time. */ + return_read_eof = YES; + } - if (bytes_done>0) - { - status_bytes_rd = YES; - buf += bytes_done; - *ppos += bytes_done; - total_bytes_done += bytes_done; - count -= bytes_done; - } - } - tpqputs(TPQD_ALWAYS, "read request for <0 bytes"); - return -EINVAL; -} /* qic02_tape_read */ + } + /* else: ignore read request for 0 bytes */ + if (bytes_done > 0) { + status_bytes_rd = YES; + buf += bytes_done; + *ppos += bytes_done; + total_bytes_done += bytes_done; + count -= bytes_done; + } + } + tpqputs(TPQD_ALWAYS, "read request for <0 bytes"); + return -EINVAL; +} /* qic02_tape_read */ @@ -1981,100 +2009,85 @@ * tape device again. The driver will detect an exception status in (No Cartridge) * and force a rewind. After that tar may continue writing. */ -static ssize_t qic02_tape_write( struct file * filp, const char * buf, - size_t count, loff_t *ppos) +static ssize_t qic02_tape_write(struct file *filp, const char *buf, + size_t count, loff_t * ppos) { - int err; - kdev_t dev = filp->f_dentry->d_inode->i_rdev; - unsigned short flags = filp->f_flags; - unsigned long bytes_todo, bytes_done, total_bytes_done = 0; - - if (status_zombie==YES) - { - tpqputs(TPQD_ALWAYS, "configs not set"); - return -ENXIO; - } - - if (TP_DIAGS(current_tape_dev)) - { - /* can't print a ``long long'' (for filp->f_pos), so chop it */ - printk(TPQIC02_NAME ": request WRITE, minor=%x, buf=%p" - ", count=%lx, pos=%lx, flags=%x\n", - MINOR(dev), buf, - (long) count, (unsigned long) filp->f_pos, flags); - } - - if (count % TAPE_BLKSIZE) /* only allow mod 512 bytes at a time */ - { - tpqputs(TPQD_BLKSZ, "Wrong block size"); - return -EINVAL; - } + int err; + kdev_t dev = filp->f_dentry->d_inode->i_rdev; + unsigned short flags = filp->f_flags; + unsigned long bytes_todo, bytes_done, total_bytes_done = 0; - if (mode_access==READ) - { - tpqputs(TPQD_ALWAYS, "Not in write mode"); - return -EACCES; - } - - /* open() does a sense() and we can assume the tape isn't changed - * between open() and release(), so the tperror.exs bits will still - * be valid. - */ - if ((tperror.exs & TP_ST0) && (tperror.exs & TP_WRP)) - { - tpqputs(TPQD_ALWAYS, "Cartridge is write-protected."); - return -EACCES; /* don't even try when write protected */ - } - - if (doing_read == YES) - { - terminate_read(0); - } - - while ((signed)count>=0) - { - /* see how much fits in the kernel buffer */ - bytes_done = 0; - bytes_todo = TPQBUF_SIZE; - if (bytes_todo>count) - { - bytes_todo = count; + if (status_zombie == YES) { + tpqputs(TPQD_ALWAYS, "configs not set"); + return -ENXIO; } - - if (return_write_eof == YES) - { - /* return_write_eof should be reset on reverse tape movements. */ - - if (reported_write_eof==NO) - { - if (bytes_todo>0) - { - tpqputs(TPQD_ALWAYS, "partial write"); - /* partial write signals EOF to user program */ - } - reported_write_eof = YES; - return total_bytes_done; - } - else - { - return -ENOSPC; /* return error */ - } - } - - /* Quit when done. */ - if (bytes_todo==0) - { - return total_bytes_done; + + if (TP_DIAGS(current_tape_dev)) { + /* can't print a ``long long'' (for filp->f_pos), so chop it */ + printk(TPQIC02_NAME ": request WRITE, minor=%x, buf=%p" + ", count=%lx, pos=%lx, flags=%x\n", + MINOR(dev), buf, + (long) count, (unsigned long) filp->f_pos, flags); + } + + if (count % TAPE_BLKSIZE) { /* only allow mod 512 bytes at a time */ + tpqputs(TPQD_BLKSZ, "Wrong block size"); + return -EINVAL; + } + + if (mode_access == READ) { + tpqputs(TPQD_ALWAYS, "Not in write mode"); + return -EACCES; + } + + /* open() does a sense() and we can assume the tape isn't changed + * between open() and release(), so the tperror.exs bits will still + * be valid. + */ + if ((tperror.exs & TP_ST0) && (tperror.exs & TP_WRP)) { + tpqputs(TPQD_ALWAYS, "Cartridge is write-protected."); + return -EACCES; /* don't even try when write protected */ + } + + if (doing_read == YES) { + terminate_read(0); } - - /* copy from user to DMA buffer and initiate transfer. */ - if (bytes_todo>0) - { - err = copy_from_user(buffaddr, buf, bytes_todo); - if (err) - { - return -EFAULT; - } + + while ((signed) count >= 0) { + /* see how much fits in the kernel buffer */ + bytes_done = 0; + bytes_todo = TPQBUF_SIZE; + if (bytes_todo > count) { + bytes_todo = count; + } + + if (return_write_eof == YES) { + /* return_write_eof should be reset on reverse tape movements. */ + + if (reported_write_eof == NO) { + if (bytes_todo > 0) { + tpqputs(TPQD_ALWAYS, + "partial write"); + /* partial write signals EOF to user program */ + } + reported_write_eof = YES; + return total_bytes_done; + } else { + return -ENOSPC; /* return error */ + } + } + + /* Quit when done. */ + if (bytes_todo == 0) { + return total_bytes_done; + } + + /* copy from user to DMA buffer and initiate transfer. */ + if (bytes_todo > 0) { + err = copy_from_user(buffaddr, buf, bytes_todo); + if (err) { + return -EFAULT; + } /****************** similar problem with read() at FM could happen here at EOT. ******************/ @@ -2082,78 +2095,74 @@ /***** if at EOT, 0 bytes can be written. start_dma() will ***** fail and write() will return ENXIO error *****/ - if (start_dma(WRITE, bytes_todo) != TE_OK) - { - tpqputs(TPQD_ALWAYS, "write: start_dma() failed"); - /* should do sense() on error here */ - return -ENXIO; /*********** FIXTHIS **************/ - } - - /* Wait for write to complete, interrupt should wake us. */ - while ((status_error == 0) && (dma_mode != 0)) - { - sleep_on(&qic02_tape_transfer); - } - - end_dma(&bytes_done); - if (bytes_done>bytes_todo) - { - tpqputs(TPQD_ALWAYS, "write: Oops, wrote more bytes than requested"); - return -EIO; - } - /* If the dma-transfer was aborted because of an exception, - * status_error will have been set in the interrupt handler. - * Then end_dma() will do a sense(). - * If the exception was EXC_EOM, the EW-hole was encountered - * and two more blocks could be written. For the time being we'll - * just consider this to be the EOT. - * Otherwise, something Bad happened, such as the maximum number - * of block-rewrites was exceeded. [e.g. A very bad spot on tape was - * encountered. Normally short dropouts are compensated for by - * rewriting the block in error, up to 16 times. I'm not sure - * QIC-24 drives can do this.] - */ - if (status_error) - { - if (status_eom_detected == YES) - { - tpqputs(TPQD_ALWAYS, "write: EW detected"); - return_write_eof = YES; - } - else - { - /* probably EXC_RWA */ - tpqputs(TPQD_ALWAYS, "write: dma: error in writing"); - return -EIO; - } - } - if (bytes_todo != bytes_done) - { - /* EOF or EOM detected. return EOT next time. */ - return_write_eof = YES; - } - } - /* else: ignore write request for 0 bytes. */ - - if (bytes_done>0) - { - status_bytes_wr = YES; - buf += bytes_done; - *ppos += bytes_done; - total_bytes_done += bytes_done; - count -= bytes_done; - } - } - - tpqputs(TPQD_ALWAYS, "write request for <0 bytes"); - if (TPQDBG(DEBUG)) - { - printk(TPQIC02_NAME ": status_bytes_wr %x, buf %p" - ", total_bytes_done %lx, count %lx\n", - status_bytes_wr, buf, total_bytes_done, (long) count); - } - return -EINVAL; -} /* qic02_tape_write */ + if (start_dma(WRITE, bytes_todo) != TE_OK) { + tpqputs(TPQD_ALWAYS, + "write: start_dma() failed"); + /* should do sense() on error here */ + return -ENXIO; + /*********** FIXTHIS **************/ + } + + /* Wait for write to complete, interrupt should wake us. */ + while ((status_error == 0) && (dma_mode != 0)) { + sleep_on(&qic02_tape_transfer); + } + + end_dma(&bytes_done); + if (bytes_done > bytes_todo) { + tpqputs(TPQD_ALWAYS, + "write: Oops, wrote more bytes than requested"); + return -EIO; + } + /* If the dma-transfer was aborted because of an exception, + * status_error will have been set in the interrupt handler. + * Then end_dma() will do a sense(). + * If the exception was EXC_EOM, the EW-hole was encountered + * and two more blocks could be written. For the time being we'll + * just consider this to be the EOT. + * Otherwise, something Bad happened, such as the maximum number + * of block-rewrites was exceeded. [e.g. A very bad spot on tape was + * encountered. Normally short dropouts are compensated for by + * rewriting the block in error, up to 16 times. I'm not sure + * QIC-24 drives can do this.] + */ + if (status_error) { + if (status_eom_detected == YES) { + tpqputs(TPQD_ALWAYS, + "write: EW detected"); + return_write_eof = YES; + } else { + /* probably EXC_RWA */ + tpqputs(TPQD_ALWAYS, + "write: dma: error in writing"); + return -EIO; + } + } + if (bytes_todo != bytes_done) { + /* EOF or EOM detected. return EOT next time. */ + return_write_eof = YES; + } + } + /* else: ignore write request for 0 bytes. */ + + if (bytes_done > 0) { + status_bytes_wr = YES; + buf += bytes_done; + *ppos += bytes_done; + total_bytes_done += bytes_done; + count -= bytes_done; + } + } + + tpqputs(TPQD_ALWAYS, "write request for <0 bytes"); + if (TPQDBG(DEBUG)) { + printk(TPQIC02_NAME ": status_bytes_wr %x, buf %p" + ", total_bytes_done %lx, count %lx\n", + status_bytes_wr, buf, total_bytes_done, + (long) count); + } + return -EINVAL; +} /* qic02_tape_write */ @@ -2169,846 +2178,810 @@ * Don't rewind if the minor bits specify density 0. */ -static int qic02_tape_open(struct inode * inode, struct file * filp) +static int qic02_tape_open(struct inode *inode, struct file *filp) { - static int qic02_tape_open_no_use_count(struct inode *, struct file *); - int open_error; + static int qic02_tape_open_no_use_count(struct inode *, + struct file *); + int open_error; - open_error = qic02_tape_open_no_use_count(inode, filp); - return open_error; + open_error = qic02_tape_open_no_use_count(inode, filp); + return open_error; } -static int qic02_tape_open_no_use_count(struct inode * inode, struct file * filp) +static int qic02_tape_open_no_use_count(struct inode *inode, + struct file *filp) { - kdev_t dev = inode->i_rdev; - unsigned short flags = filp->f_flags; - unsigned short dens = 0; - int s; - - - if (TP_DIAGS(dev)) - { - printk("qic02_tape_open: dev=%s, flags=%x ", - kdevname(dev), flags); - } - - if (MINOR(dev)==255) /* special case for resetting */ - { - if (capable(CAP_SYS_ADMIN)) - { - return (tape_reset(1)==TE_OK) ? -EAGAIN : -ENXIO; + kdev_t dev = inode->i_rdev; + unsigned short flags = filp->f_flags; + unsigned short dens = 0; + int s; + + + if (TP_DIAGS(dev)) { + printk("qic02_tape_open: dev=%s, flags=%x ", + kdevname(dev), flags); } - else - { - return -EPERM; + + if (MINOR(dev) == 255) { /* special case for resetting */ + if (capable(CAP_SYS_ADMIN)) { + return (tape_reset(1) == TE_OK) ? -EAGAIN : -ENXIO; + } else { + return -EPERM; + } } - } - - if (status_dead==YES) - { - /* Allow `mt reset' ioctl() even when already open()ed. */ - return 0; - } - + + if (status_dead == YES) { + /* Allow `mt reset' ioctl() even when already open()ed. */ + return 0; + } + /* Only one at a time from here on... */ - if (file_count(filp)>1) /* filp->f_count==1 for the first open() */ - { - return -EBUSY; - } - - if (status_zombie==YES) - { - /* no irq/dma/port stuff allocated yet, no reset done - * yet, so return until MTSETCONFIG has been done. + if (file_count(filp) > 1) { /* filp->f_count==1 for the first open() */ + return -EBUSY; + } + + if (status_zombie == YES) { + /* no irq/dma/port stuff allocated yet, no reset done + * yet, so return until MTSETCONFIG has been done. + */ + return 0; + } + + status_bytes_rd = NO; + status_bytes_wr = NO; + + return_read_eof = NO; /********????????????????*****/ + return_write_eof = (status_eot_detected) ? YES : NO; + + /* Clear this in case user app close()d before reading EOF token */ + status_eof_detected = NO; + + reported_read_eof = NO; + reported_write_eof = NO; + + + switch (flags & O_ACCMODE) { + case O_RDONLY: + mode_access = READ; + break; + case O_WRONLY: /* Fallthru... Strictly speaking this is not correct... */ + case O_RDWR: /* Reads are allowed as long as nothing is written */ + mode_access = WRITE; + break; + } + + /* This is to avoid tape-changed problems (TP_CNI exception). + * + * Since removing the cartridge will not raise an exception, + * we always do a tp_sense() to make sure we have the proper + * CNI status, the 2150L may need an additional sense.... - Eddy */ - return 0; - } - - status_bytes_rd = NO; - status_bytes_wr = NO; - - return_read_eof = NO; /********????????????????*****/ - return_write_eof = (status_eot_detected)? YES : NO; - - /* Clear this in case user app close()d before reading EOF token */ - status_eof_detected = NO; - - reported_read_eof = NO; - reported_write_eof = NO; - - - switch (flags & O_ACCMODE) - { - case O_RDONLY: - mode_access = READ; - break; - case O_WRONLY: /* Fallthru... Strictly speaking this is not correct... */ - case O_RDWR: /* Reads are allowed as long as nothing is written */ - mode_access = WRITE; - break; - } - - /* This is to avoid tape-changed problems (TP_CNI exception). - * - * Since removing the cartridge will not raise an exception, - * we always do a tp_sense() to make sure we have the proper - * CNI status, the 2150L may need an additional sense.... - Eddy - */ - s = tp_sense(TP_WRP|TP_EOM|TP_BOM|TP_CNI|TP_EOR); - - if (s == TE_OK) - { - /* Try to clear cartridge-changed status for Archive-2150L */ - if ((tperror.exs & TP_ST0) && (tperror.exs & TP_CNI)) - { - s = tp_sense(TP_WRP|TP_EOM|TP_BOM|TP_CNI|TP_EOR); + s = tp_sense(TP_WRP | TP_EOM | TP_BOM | TP_CNI | TP_EOR); + + if (s == TE_OK) { + /* Try to clear cartridge-changed status for Archive-2150L */ + if ((tperror.exs & TP_ST0) && (tperror.exs & TP_CNI)) { + s = tp_sense(TP_WRP | TP_EOM | TP_BOM | TP_CNI | + TP_EOR); + } + } + + if (s != TE_OK) { + tpqputs(TPQD_ALWAYS, "open: sense() failed"); + return -EIO; } - } - - if (s != TE_OK) - { - tpqputs(TPQD_ALWAYS, "open: sense() failed"); - return -EIO; - } - - /* exception bits should be up-to-date now, so check for - * tape presence and exit if absent. - * Even `mt stat' will fail without a tape. - */ - if ((tperror.exs & TP_ST0) && (tperror.exs & TP_CNI)) - { - tpqputs(TPQD_ALWAYS, "No tape present."); - return -EIO; - } - - /* At this point we can assume that a tape is present and - * that it will remain present until release() is called. - */ - - /* not allowed to do QCMD_DENS_* unless tape is rewound */ - if ((TP_DENS(dev)!=0) && (TP_DENS(current_tape_dev) != TP_DENS(dev))) - { - /* force rewind if minor bits have changed, - * i.e. user wants to use tape in different format. - * [assuming single drive operation] + + /* exception bits should be up-to-date now, so check for + * tape presence and exit if absent. + * Even `mt stat' will fail without a tape. */ - if (TP_HAVE_DENS) - { - tpqputs(TPQD_REWIND, "Density minor bits have changed. Forcing rewind."); - need_rewind = YES; + if ((tperror.exs & TP_ST0) && (tperror.exs & TP_CNI)) { + tpqputs(TPQD_ALWAYS, "No tape present."); + return -EIO; } - } - else - { - /* density bits still the same, but TP_DIAGS bit - * may have changed. + + /* At this point we can assume that a tape is present and + * that it will remain present until release() is called. */ - current_tape_dev = dev; - } - - if (need_rewind == YES) /***************** CHECK THIS!!!!!!!! **********/ - { - s = do_qic_cmd(QCMD_REWIND, TIM_R); - if (s != 0) - { - tpqputs(TPQD_ALWAYS, "open: rewind failed"); - return -EIO; + + /* not allowed to do QCMD_DENS_* unless tape is rewound */ + if ((TP_DENS(dev) != 0) + && (TP_DENS(current_tape_dev) != TP_DENS(dev))) { + /* force rewind if minor bits have changed, + * i.e. user wants to use tape in different format. + * [assuming single drive operation] + */ + if (TP_HAVE_DENS) { + tpqputs(TPQD_REWIND, + "Density minor bits have changed. Forcing rewind."); + need_rewind = YES; + } + } else { + /* density bits still the same, but TP_DIAGS bit + * may have changed. + */ + current_tape_dev = dev; + } + + if (need_rewind == YES) { +/***************** CHECK THIS!!!!!!!! **********/ + s = do_qic_cmd(QCMD_REWIND, TIM_R); + if (s != 0) { + tpqputs(TPQD_ALWAYS, "open: rewind failed"); + return -EIO; + } } - } /* Note: After a reset command, the controller will rewind the tape * just before performing any tape movement operation! ************ SO SET need_rewind flag!!!!! - */ - if (status_dead==YES) - { - tpqputs(TPQD_ALWAYS, "open: tape dead, attempting reset"); - if (tape_reset(1)!=TE_OK) - { - return -ENXIO; + */ + if (status_dead == YES) { + tpqputs(TPQD_ALWAYS, "open: tape dead, attempting reset"); + if (tape_reset(1) != TE_OK) { + return -ENXIO; + } else { + status_dead = NO; + if (tp_sense(~(TP_ST1 | TP_ILL)) != TE_OK) { + tpqputs(TPQD_ALWAYS, + "open: tp_sense() failed\n"); + status_dead = YES; /* try reset next time */ + return -EIO; + } + } } - else - { - status_dead = NO; - if (tp_sense(~(TP_ST1|TP_ILL)) != TE_OK) - { - tpqputs(TPQD_ALWAYS, "open: tp_sense() failed\n"); - status_dead = YES; /* try reset next time */ + + /* things should be ok, once we get here */ + + + /* set density: only allowed when TP_BOM status bit is set, + * so we must have done a rewind by now. If not, just skip over. + * Only give set density command when minor bits have changed. + */ + if (TP_DENS(current_tape_dev) == TP_DENS(dev)) { + return 0; + } + + current_tape_dev = dev; + need_rewind = NO; + if (TP_HAVE_DENS) { + dens = TP_DENS(dev); + } + + if (dens < sizeof(format_names) / sizeof(char *)) { + printk(TPQIC02_NAME ": format: %s%s\n", + (dens != 0) ? "QIC-" : "", format_names[dens]); + } else { + tpqputs(TPQD_REWIND, "Wait for retensioning..."); + } + + switch (TP_DENS(dev)) { + case 0: /* Minor 0 is for drives without set-density support */ + s = 0; + break; + case 1: + s = do_qic_cmd(QCMD_DENS_11, TIM_S); + break; + case 2: + s = do_qic_cmd(QCMD_DENS_24, TIM_S); + break; + case 3: + s = do_qic_cmd(QCMD_DENS_120, TIM_S); + break; + case 4: + s = do_qic_cmd(QCMD_DENS_150, TIM_S); + break; + case 5: + s = do_qic_cmd(QCMD_DENS_300, TIM_S); + break; + case 6: + s = do_qic_cmd(QCMD_DENS_600, TIM_S); + break; + default: /* otherwise do a retension before anything else */ + s = do_qic_cmd(QCMD_RETEN, TIM_R); + } + if (s != 0) { + status_dead = YES; /* force reset */ + current_tape_dev = 0; /* earlier 0xff80 */ return -EIO; - } } - } - - /* things should be ok, once we get here */ - - - /* set density: only allowed when TP_BOM status bit is set, - * so we must have done a rewind by now. If not, just skip over. - * Only give set density command when minor bits have changed. - */ - if (TP_DENS(current_tape_dev) == TP_DENS(dev) ) - { + return 0; - } - - current_tape_dev = dev; - need_rewind = NO; - if (TP_HAVE_DENS) - { - dens = TP_DENS(dev); - } - - if (dens < sizeof(format_names)/sizeof(char *)) - { - printk(TPQIC02_NAME ": format: %s%s\n", (dens!=0)? "QIC-" : "", format_names[dens]); - } - else - { - tpqputs(TPQD_REWIND, "Wait for retensioning..."); - } - - switch (TP_DENS(dev)) - { - case 0: /* Minor 0 is for drives without set-density support */ - s = 0; - break; - case 1: - s = do_qic_cmd(QCMD_DENS_11, TIM_S); - break; - case 2: - s = do_qic_cmd(QCMD_DENS_24, TIM_S); - break; - case 3: - s = do_qic_cmd(QCMD_DENS_120, TIM_S); - break; - case 4: - s = do_qic_cmd(QCMD_DENS_150, TIM_S); - break; - case 5: - s = do_qic_cmd(QCMD_DENS_300, TIM_S); - break; - case 6: - s = do_qic_cmd(QCMD_DENS_600, TIM_S); - break; - default: /* otherwise do a retension before anything else */ - s = do_qic_cmd(QCMD_RETEN, TIM_R); - } - if (s != 0) - { - status_dead = YES; /* force reset */ - current_tape_dev = 0; /* earlier 0xff80 */ - return -EIO; - } - - return 0; -} /* qic02_tape_open */ - - -static int qic02_tape_release(struct inode * inode, struct file * filp) -{ - kdev_t dev = inode->i_rdev; - - lock_kernel(); - if (TP_DIAGS(dev)) - { - printk("qic02_tape_release: dev=%s\n", kdevname(dev)); - } - - if (status_zombie==NO) /* don't rewind in zombie mode */ - { - /* Terminate any pending write cycle. Terminating the read-cycle - * is delayed until it is required to do so for a new command. - */ - terminate_write(-1); - - if (status_dead==YES) - { - tpqputs(TPQD_ALWAYS, "release: device dead!?"); +} /* qic02_tape_open */ + + +static int qic02_tape_release(struct inode *inode, struct file *filp) +{ + kdev_t dev = inode->i_rdev; + + lock_kernel(); + if (TP_DIAGS(dev)) { + printk("qic02_tape_release: dev=%s\n", kdevname(dev)); } - - /* Rewind only if minor number requires it AND - * read/writes have been done. ************* IS THIS CORRECT?????????? - */ - if ((TP_REWCLOSE(dev)) && (status_bytes_rd | status_bytes_wr)) - { - tpqputs(TPQD_REWIND, "release: Doing rewind..."); - (void) do_qic_cmd(QCMD_REWIND, TIM_R); + + if (status_zombie == NO) { /* don't rewind in zombie mode */ + /* Terminate any pending write cycle. Terminating the read-cycle + * is delayed until it is required to do so for a new command. + */ + terminate_write(-1); + + if (status_dead == YES) { + tpqputs(TPQD_ALWAYS, "release: device dead!?"); + } + + /* Rewind only if minor number requires it AND + * read/writes have been done. ************* IS THIS CORRECT?????????? + */ + if ((TP_REWCLOSE(dev)) + && (status_bytes_rd | status_bytes_wr)) { + tpqputs(TPQD_REWIND, "release: Doing rewind..."); + (void) do_qic_cmd(QCMD_REWIND, TIM_R); + } } - } - unlock_kernel(); - return 0; -} /* qic02_tape_release */ + unlock_kernel(); + return 0; +} /* qic02_tape_release */ #ifdef CONFIG_QIC02_DYNCONF /* Set masks etc. based on the interface card type. */ static int update_ifc_masks(int ifc) { - QIC02_TAPE_IFC = ifc; + QIC02_TAPE_IFC = ifc; - if ((QIC02_TAPE_IFC == WANGTEK) || (QIC02_TAPE_IFC == EVEREX)) - { - QIC02_STAT_PORT = QIC02_TAPE_PORT; - QIC02_CTL_PORT = QIC02_TAPE_PORT; - QIC02_CMD_PORT = QIC02_TAPE_PORT+1; - QIC02_DATA_PORT = QIC02_TAPE_PORT+1; - QIC02_STAT_READY = WT_QIC02_STAT_READY; - QIC02_STAT_EXCEPTION = WT_QIC02_STAT_EXCEPTION; - QIC02_STAT_MASK = WT_QIC02_STAT_MASK; - - QIC02_STAT_RESETMASK = WT_QIC02_STAT_RESETMASK; - QIC02_STAT_RESETVAL = WT_QIC02_STAT_RESETVAL; - - QIC02_CTL_RESET = WT_QIC02_CTL_RESET; - QIC02_CTL_REQUEST = WT_QIC02_CTL_REQUEST; - - if (QIC02_TAPE_DMA == 3) - { - WT_CTL_DMA = WT_CTL_DMA3; - } - else if (QIC02_TAPE_DMA == 1) - { - WT_CTL_DMA = WT_CTL_DMA1; - } - else - { - tpqputs(TPQD_ALWAYS, "Unsupported or incorrect DMA channel"); - return -EIO; - } + if ((QIC02_TAPE_IFC == WANGTEK) || (QIC02_TAPE_IFC == EVEREX)) { + QIC02_STAT_PORT = QIC02_TAPE_PORT; + QIC02_CTL_PORT = QIC02_TAPE_PORT; + QIC02_CMD_PORT = QIC02_TAPE_PORT + 1; + QIC02_DATA_PORT = QIC02_TAPE_PORT + 1; + QIC02_STAT_READY = WT_QIC02_STAT_READY; + QIC02_STAT_EXCEPTION = WT_QIC02_STAT_EXCEPTION; + QIC02_STAT_MASK = WT_QIC02_STAT_MASK; + + QIC02_STAT_RESETMASK = WT_QIC02_STAT_RESETMASK; + QIC02_STAT_RESETVAL = WT_QIC02_STAT_RESETVAL; + + QIC02_CTL_RESET = WT_QIC02_CTL_RESET; + QIC02_CTL_REQUEST = WT_QIC02_CTL_REQUEST; + + if (QIC02_TAPE_DMA == 3) { + WT_CTL_DMA = WT_CTL_DMA3; + } else if (QIC02_TAPE_DMA == 1) { + WT_CTL_DMA = WT_CTL_DMA1; + } else { + tpqputs(TPQD_ALWAYS, + "Unsupported or incorrect DMA channel"); + return -EIO; + } - if (QIC02_TAPE_IFC == EVEREX) - { - /* Everex is a special case for Wangtek (actually - * it's the other way 'round, but I saw Wangtek first) - */ - if (QIC02_TAPE_DMA==3) - { - WT_CTL_DMA = WT_CTL_DMA1; - } - - /* Fixup the kernel copy of the IFC type to that - * we don't have to distinguish between Wangtek and - * and Everex at runtime. - */ - QIC02_TAPE_IFC = WANGTEK; - } - } - else if (QIC02_TAPE_IFC == ARCHIVE) - { - QIC02_STAT_PORT = QIC02_TAPE_PORT+1; - QIC02_CTL_PORT = QIC02_TAPE_PORT+1; - QIC02_CMD_PORT = QIC02_TAPE_PORT; - QIC02_DATA_PORT = QIC02_TAPE_PORT; - QIC02_STAT_READY = AR_QIC02_STAT_READY; - QIC02_STAT_EXCEPTION = AR_QIC02_STAT_EXCEPTION; - QIC02_STAT_MASK = AR_QIC02_STAT_MASK; - - QIC02_STAT_RESETMASK = AR_QIC02_STAT_RESETMASK; - QIC02_STAT_RESETVAL = AR_QIC02_STAT_RESETVAL; - - QIC02_CTL_RESET = AR_QIC02_CTL_RESET; - QIC02_CTL_REQUEST = AR_QIC02_CTL_REQUEST; - - if (QIC02_TAPE_DMA > 3) - { - tpqputs(TPQD_ALWAYS, "Unsupported or incorrect DMA channel"); - return -EIO; - } - } - else if (QIC02_TAPE_IFC == MOUNTAIN) - { - QIC02_STAT_PORT = QIC02_TAPE_PORT+1; - QIC02_CTL_PORT = QIC02_TAPE_PORT+1; - QIC02_CMD_PORT = QIC02_TAPE_PORT; - QIC02_DATA_PORT = QIC02_TAPE_PORT; - - QIC02_STAT_READY = MTN_QIC02_STAT_READY; - QIC02_STAT_EXCEPTION = MTN_QIC02_STAT_EXCEPTION; - QIC02_STAT_MASK = MTN_QIC02_STAT_MASK; - - QIC02_STAT_RESETMASK = MTN_QIC02_STAT_RESETMASK; - QIC02_STAT_RESETVAL = MTN_QIC02_STAT_RESETVAL; - - QIC02_CTL_RESET = MTN_QIC02_CTL_RESET; - QIC02_CTL_REQUEST = MTN_QIC02_CTL_REQUEST; - - if (QIC02_TAPE_DMA > 3) - { - tpqputs(TPQD_ALWAYS, "Unsupported or incorrect DMA channel"); - return -EIO; - } - } - else - { - tpqputs(TPQD_ALWAYS, "Invalid interface type"); - return -ENXIO; - } - return qic02_get_resources(); -} /* update_ifc_masks */ + if (QIC02_TAPE_IFC == EVEREX) { + /* Everex is a special case for Wangtek (actually + * it's the other way 'round, but I saw Wangtek first) + */ + if (QIC02_TAPE_DMA == 3) { + WT_CTL_DMA = WT_CTL_DMA1; + } + + /* Fixup the kernel copy of the IFC type to that + * we don't have to distinguish between Wangtek and + * and Everex at runtime. + */ + QIC02_TAPE_IFC = WANGTEK; + } + } else if (QIC02_TAPE_IFC == ARCHIVE) { + QIC02_STAT_PORT = QIC02_TAPE_PORT + 1; + QIC02_CTL_PORT = QIC02_TAPE_PORT + 1; + QIC02_CMD_PORT = QIC02_TAPE_PORT; + QIC02_DATA_PORT = QIC02_TAPE_PORT; + QIC02_STAT_READY = AR_QIC02_STAT_READY; + QIC02_STAT_EXCEPTION = AR_QIC02_STAT_EXCEPTION; + QIC02_STAT_MASK = AR_QIC02_STAT_MASK; + + QIC02_STAT_RESETMASK = AR_QIC02_STAT_RESETMASK; + QIC02_STAT_RESETVAL = AR_QIC02_STAT_RESETVAL; + + QIC02_CTL_RESET = AR_QIC02_CTL_RESET; + QIC02_CTL_REQUEST = AR_QIC02_CTL_REQUEST; + + if (QIC02_TAPE_DMA > 3) { + tpqputs(TPQD_ALWAYS, + "Unsupported or incorrect DMA channel"); + return -EIO; + } + } else if (QIC02_TAPE_IFC == MOUNTAIN) { + QIC02_STAT_PORT = QIC02_TAPE_PORT + 1; + QIC02_CTL_PORT = QIC02_TAPE_PORT + 1; + QIC02_CMD_PORT = QIC02_TAPE_PORT; + QIC02_DATA_PORT = QIC02_TAPE_PORT; + + QIC02_STAT_READY = MTN_QIC02_STAT_READY; + QIC02_STAT_EXCEPTION = MTN_QIC02_STAT_EXCEPTION; + QIC02_STAT_MASK = MTN_QIC02_STAT_MASK; + + QIC02_STAT_RESETMASK = MTN_QIC02_STAT_RESETMASK; + QIC02_STAT_RESETVAL = MTN_QIC02_STAT_RESETVAL; + + QIC02_CTL_RESET = MTN_QIC02_CTL_RESET; + QIC02_CTL_REQUEST = MTN_QIC02_CTL_REQUEST; + + if (QIC02_TAPE_DMA > 3) { + tpqputs(TPQD_ALWAYS, + "Unsupported or incorrect DMA channel"); + return -EIO; + } + } else { + tpqputs(TPQD_ALWAYS, "Invalid interface type"); + return -ENXIO; + } + return qic02_get_resources(); +} /* update_ifc_masks */ #endif /* ioctl allows user programs to rewind the tape and stuff like that */ -static int qic02_tape_ioctl(struct inode * inode, struct file * filp, - unsigned int iocmd, unsigned long ioarg) +static int qic02_tape_ioctl(struct inode *inode, struct file *filp, + unsigned int iocmd, unsigned long ioarg) { - int error; - int dev_maj = MAJOR(inode->i_rdev); - int c; - struct mtop operation; - unsigned char blk_addr[6]; - struct mtpos ioctl_tell; - - - if (TP_DIAGS(current_tape_dev)) - { - printk(TPQIC02_NAME ": ioctl(%4x, %4x, %4lx)\n", dev_maj, iocmd, ioarg); - } - - if (!inode || !ioarg) - { - return -EINVAL; - } - - /* check iocmd first */ - - if (dev_maj != QIC02_TAPE_MAJOR) - { - printk(TPQIC02_NAME ": Oops! Wrong device?\n"); - /* A panic() would be appropriate here */ - return -ENODEV; - } - - c = _IOC_NR(iocmd); + int error; + int dev_maj = MAJOR(inode->i_rdev); + int c; + struct mtop operation; + unsigned char blk_addr[6]; + struct mtpos ioctl_tell; -#ifdef CONFIG_QIC02_DYNCONF - if (c == _IOC_NR(MTIOCGETCONFIG)) - { - CHECK_IOC_SIZE(mtconfiginfo); - if (copy_to_user((char *) ioarg, (char *) &qic02_tape_dynconf, sizeof(qic02_tape_dynconf))) - { - return -EFAULT; + if (TP_DIAGS(current_tape_dev)) { + printk(TPQIC02_NAME ": ioctl(%4x, %4x, %4lx)\n", dev_maj, + iocmd, ioarg); } - return 0; - } - else if (c == _IOC_NR(MTIOCSETCONFIG)) - { - /* One should always do a MTIOCGETCONFIG first, then update - * user-settings, then write back with MTIOCSETCONFIG. - * The qic02conf program should re-open() the device before actual - * use, to make sure everything is initialized. - */ - - CHECK_IOC_SIZE(mtconfiginfo); - - if (!capable(CAP_SYS_ADMIN)) - { - return -EPERM; + if (!inode || !ioarg) { + return -EINVAL; } - - if ((doing_read!=NO) || (doing_write!=NO)) - { - return -EBUSY; + + /* check iocmd first */ + + if (dev_maj != QIC02_TAPE_MAJOR) { + printk(TPQIC02_NAME ": Oops! Wrong device?\n"); + /* A panic() would be appropriate here */ + return -ENODEV; } - - if (status_zombie==NO) - { - qic02_release_resources(); /* and go zombie */ + + c = _IOC_NR(iocmd); + +#ifdef CONFIG_QIC02_DYNCONF + if (c == _IOC_NR(MTIOCGETCONFIG)) { + CHECK_IOC_SIZE(mtconfiginfo); + + if (copy_to_user + ((char *) ioarg, (char *) &qic02_tape_dynconf, + sizeof(qic02_tape_dynconf))) { + return -EFAULT; + } + return 0; + + } else if (c == _IOC_NR(MTIOCSETCONFIG)) { + /* One should always do a MTIOCGETCONFIG first, then update + * user-settings, then write back with MTIOCSETCONFIG. + * The qic02conf program should re-open() the device before actual + * use, to make sure everything is initialized. + */ + + CHECK_IOC_SIZE(mtconfiginfo); + + if (!capable(CAP_SYS_ADMIN)) { + return -EPERM; + } + + if ((doing_read != NO) || (doing_write != NO)) { + return -EBUSY; + } + + if (status_zombie == NO) { + qic02_release_resources(); /* and go zombie */ + } + + /* copy struct from user space to kernel space */ + if (copy_from_user + ((char *) &qic02_tape_dynconf, (char *) ioarg, + sizeof(qic02_tape_dynconf))) { + return -EFAULT; + } + return update_ifc_masks(qic02_tape_dynconf.ifc_type); } - - /* copy struct from user space to kernel space */ - if (copy_from_user((char *) &qic02_tape_dynconf, (char *) ioarg, sizeof(qic02_tape_dynconf))) - { - return -EFAULT; + if (status_zombie == YES) { + tpqputs(TPQD_ALWAYS, "Configs not set"); + return -ENXIO; } - return update_ifc_masks(qic02_tape_dynconf.ifc_type); - } - if (status_zombie==YES) - { - tpqputs(TPQD_ALWAYS, "Configs not set"); - return -ENXIO; - } #endif - if (c == _IOC_NR(MTIOCTOP)) - { - CHECK_IOC_SIZE(mtop); + if (c == _IOC_NR(MTIOCTOP)) { + CHECK_IOC_SIZE(mtop); - /* copy mtop struct from user space to kernel space */ - if (copy_from_user((char *) &operation, (char *) ioarg, sizeof(operation))) - { - return -EFAULT; - } + /* copy mtop struct from user space to kernel space */ + if (copy_from_user + ((char *) &operation, (char *) ioarg, + sizeof(operation))) { + return -EFAULT; + } - /* ---note: mt_count is signed, negative seeks must be - * --- translated to seeks in opposite direction! - * (only needed for Sun-programs, I think.) - */ - /* ---note: MTFSF with count 0 should position the - * --- tape at the beginning of the current file. - */ + /* ---note: mt_count is signed, negative seeks must be + * --- translated to seeks in opposite direction! + * (only needed for Sun-programs, I think.) + */ + /* ---note: MTFSF with count 0 should position the + * --- tape at the beginning of the current file. + */ - if (TP_DIAGS(current_tape_dev)) - { - printk("OP op=%4x, count=%4x\n", operation.mt_op, operation.mt_count); - } - - if (operation.mt_count < 0) - { - tpqputs(TPQD_ALWAYS, "Warning: negative mt_count ignored"); - } - - ioctl_status.mt_resid = operation.mt_count; - if (operation.mt_op == MTSEEK) - { - if (!TP_HAVE_SEEK) - { - return -ENOTTY; - } - - seek_addr_buf[0] = (operation.mt_count>>16)&0xff; - seek_addr_buf[1] = (operation.mt_count>>8)&0xff; - seek_addr_buf[2] = (operation.mt_count)&0xff; - if (operation.mt_count>>24) - { - return -EINVAL; - } - if ((error = do_ioctl_cmd(operation.mt_op)) != 0) - { - return error; - } - - ioctl_status.mt_resid = 0; - } - else - { - while (operation.mt_count > 0) - { - operation.mt_count--; - if ((error = do_ioctl_cmd(operation.mt_op)) != 0) - { - return error; + if (TP_DIAGS(current_tape_dev)) { + printk("OP op=%4x, count=%4x\n", operation.mt_op, + operation.mt_count); + } + + if (operation.mt_count < 0) { + tpqputs(TPQD_ALWAYS, + "Warning: negative mt_count ignored"); } - + ioctl_status.mt_resid = operation.mt_count; - } - } - return 0; - - } - else if (c == _IOC_NR(MTIOCGET)) - { - if (TP_DIAGS(current_tape_dev)) - { - printk("GET "); - } - - CHECK_IOC_SIZE(mtget); + if (operation.mt_op == MTSEEK) { + if (!TP_HAVE_SEEK) { + return -ENOTTY; + } - /* It appears (gmt(1)) that it is normal behaviour to - * first set the status with MTNOP, and then to read - * it out with MTIOCGET - */ + seek_addr_buf[0] = + (operation.mt_count >> 16) & 0xff; + seek_addr_buf[1] = + (operation.mt_count >> 8) & 0xff; + seek_addr_buf[2] = (operation.mt_count) & 0xff; + if (operation.mt_count >> 24) { + return -EINVAL; + } + if ((error = do_ioctl_cmd(operation.mt_op)) != 0) { + return error; + } - /* copy results to user space */ - if (copy_to_user((char *) ioarg, (char *) &ioctl_status, sizeof(ioctl_status))) - { - return -EFAULT; - } - return 0; - } - else if (TP_HAVE_TELL && (c == _IOC_NR(MTIOCPOS))) - { - if (TP_DIAGS(current_tape_dev)) - { - printk("POS "); - } - - CHECK_IOC_SIZE(mtpos); - - tpqputs(TPQD_IOCTLS, "MTTELL reading block address"); - if ((doing_read==YES) || (doing_write==YES)) - { - finish_rw(AR_QCMDV_TELL_BLK); - } - - c = rdstatus((char *) blk_addr, sizeof(blk_addr), AR_QCMDV_TELL_BLK); - if (c!=TE_OK) - { - return -EIO; - } - - ioctl_tell.mt_blkno = (blk_addr[3] << 16) | (blk_addr[4] << 8) | blk_addr[5]; + ioctl_status.mt_resid = 0; + } else { + while (operation.mt_count > 0) { + operation.mt_count--; + if ((error = + do_ioctl_cmd(operation.mt_op)) != 0) { + return error; + } - /* copy results to user space */ - if (copy_to_user((char *) ioarg, (char *) &ioctl_tell, sizeof(ioctl_tell))) - { - return -EFAULT; - } - return 0; + ioctl_status.mt_resid = operation.mt_count; + } + } + return 0; + + } else if (c == _IOC_NR(MTIOCGET)) { + if (TP_DIAGS(current_tape_dev)) { + printk("GET "); + } + + CHECK_IOC_SIZE(mtget); - } - else - { - return -ENOTTY; /* Other cmds not supported. */ - } -} /* qic02_tape_ioctl */ + /* It appears (gmt(1)) that it is normal behaviour to + * first set the status with MTNOP, and then to read + * it out with MTIOCGET + */ + + /* copy results to user space */ + if (copy_to_user + ((char *) ioarg, (char *) &ioctl_status, + sizeof(ioctl_status))) { + return -EFAULT; + } + return 0; + } else if (TP_HAVE_TELL && (c == _IOC_NR(MTIOCPOS))) { + if (TP_DIAGS(current_tape_dev)) { + printk("POS "); + } + + CHECK_IOC_SIZE(mtpos); + + tpqputs(TPQD_IOCTLS, "MTTELL reading block address"); + if ((doing_read == YES) || (doing_write == YES)) { + finish_rw(AR_QCMDV_TELL_BLK); + } + + c = rdstatus((char *) blk_addr, sizeof(blk_addr), + AR_QCMDV_TELL_BLK); + if (c != TE_OK) { + return -EIO; + } + + ioctl_tell.mt_blkno = + (blk_addr[3] << 16) | (blk_addr[4] << 8) | blk_addr[5]; + + /* copy results to user space */ + if (copy_to_user + ((char *) ioarg, (char *) &ioctl_tell, + sizeof(ioctl_tell))) { + return -EFAULT; + } + return 0; + + } else { + return -ENOTTY; /* Other cmds not supported. */ + } +} /* qic02_tape_ioctl */ /* These are (most) of the interface functions: */ static struct file_operations qic02_tape_fops = { - owner: THIS_MODULE, - llseek: no_llseek, - read: qic02_tape_read, - write: qic02_tape_write, - ioctl: qic02_tape_ioctl, - open: qic02_tape_open, - release: qic02_tape_release, + owner:THIS_MODULE, + llseek:no_llseek, + read:qic02_tape_read, + write:qic02_tape_write, + ioctl:qic02_tape_ioctl, + open:qic02_tape_open, + release:qic02_tape_release, }; static void qic02_release_resources(void) { - free_irq(QIC02_TAPE_IRQ, NULL); - free_dma(QIC02_TAPE_DMA); - release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE); - if (buffaddr) - { - free_pages((unsigned long)buffaddr, get_order(TPQBUF_SIZE)); - } - buffaddr = 0; /* Better to cause a panic than overwite someone else */ - status_zombie = YES; -} /* qic02_release_resources */ + free_irq(QIC02_TAPE_IRQ, NULL); + free_dma(QIC02_TAPE_DMA); + release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE); + if (buffaddr) { + free_pages((unsigned long) buffaddr, + get_order(TPQBUF_SIZE)); + } + buffaddr = 0; /* Better to cause a panic than overwite someone else */ + status_zombie = YES; +} /* qic02_release_resources */ static int qic02_get_resources(void) { - /* First perform some checks. If one of them fails, - * the tape driver will not be registered to the system. - */ - if (QIC02_TAPE_IRQ>16) - { - tpqputs(TPQD_ALWAYS, "Bogus interrupt number."); - return -ENXIO; - } - - /* for DYNCONF, allocating IO, DMA and IRQ should not be done until - * the config parameters have been set using MTSETCONFIG. - */ - - if (check_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE)) - { - printk(TPQIC02_NAME ": IO space at 0x%x [%d ports] already reserved\n", - QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE); - return -ENXIO; - } - - /* get IRQ */ - if (request_irq(QIC02_TAPE_IRQ, qic02_tape_interrupt, SA_INTERRUPT, "QIC-02", NULL)) - { - printk(TPQIC02_NAME ": can't allocate IRQ%d for QIC-02 tape\n", - QIC02_TAPE_IRQ); - return -EBUSY; - } - - /* After IRQ, allocate DMA channel */ - if (request_dma(QIC02_TAPE_DMA,"QIC-02")) - { - printk(TPQIC02_NAME ": can't allocate DMA%d for QIC-02 tape\n", - QIC02_TAPE_DMA); - free_irq(QIC02_TAPE_IRQ, NULL); - return -EBUSY; - } + /* First perform some checks. If one of them fails, + * the tape driver will not be registered to the system. + */ + if (QIC02_TAPE_IRQ > 16) { + tpqputs(TPQD_ALWAYS, "Bogus interrupt number."); + return -ENXIO; + } + + /* for DYNCONF, allocating IO, DMA and IRQ should not be done until + * the config parameters have been set using MTSETCONFIG. + */ - /* Grab the IO region. We already made sure it's available. */ - request_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE, TPQIC02_NAME); - - /* Setup the page-address for the dma transfer. */ - buffaddr = (void *)__get_dma_pages(GFP_KERNEL, get_order(TPQBUF_SIZE)); - - if (!buffaddr) - { - qic02_release_resources(); - return -EBUSY; /* Not ideal, EAGAIN perhaps? */ - } - - memset(buffaddr, 0, TPQBUF_SIZE); - - printk(TPQIC02_NAME ": Settings: IRQ %d, DMA %d, IO 0x%x, IFC %s\n", - QIC02_TAPE_IRQ, QIC02_TAPE_DMA, - ((QIC02_TAPE_IFC==ARCHIVE) || (QIC02_TAPE_IFC==MOUNTAIN))? - QIC02_CMD_PORT : QIC02_STAT_PORT, - (QIC02_TAPE_IFC==MOUNTAIN)? "Mountain" : - ((QIC02_TAPE_IFC==ARCHIVE)? "Archive" : "Wangtek")); - - if (tape_reset(0)!=TE_OK || tp_sense(TP_WRP|TP_POR|TP_CNI)!=TE_OK) - { - /* No drive detected, so vanish */ - tpqputs(TPQD_ALWAYS, "No drive detected -- releasing IO/IRQ/DMA."); - status_dead = YES; - qic02_release_resources(); - return -EIO; - } - - /* All should be ok now */ - status_zombie = NO; - return 0; -} /* qic02_get_resources */ + if (check_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE)) { + printk(TPQIC02_NAME + ": IO space at 0x%x [%d ports] already reserved\n", + QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE); + return -ENXIO; + } + + /* get IRQ */ + if (request_irq + (QIC02_TAPE_IRQ, qic02_tape_interrupt, SA_INTERRUPT, "QIC-02", + NULL)) { + printk(TPQIC02_NAME + ": can't allocate IRQ%d for QIC-02 tape\n", + QIC02_TAPE_IRQ); + return -EBUSY; + } + + /* After IRQ, allocate DMA channel */ + if (request_dma(QIC02_TAPE_DMA, "QIC-02")) { + printk(TPQIC02_NAME + ": can't allocate DMA%d for QIC-02 tape\n", + QIC02_TAPE_DMA); + free_irq(QIC02_TAPE_IRQ, NULL); + return -EBUSY; + } + + /* Grab the IO region. We already made sure it's available. */ + request_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE, + TPQIC02_NAME); + + /* Setup the page-address for the dma transfer. */ + buffaddr = + (void *) __get_dma_pages(GFP_KERNEL, get_order(TPQBUF_SIZE)); + + if (!buffaddr) { + qic02_release_resources(); + return -EBUSY; /* Not ideal, EAGAIN perhaps? */ + } + + memset(buffaddr, 0, TPQBUF_SIZE); + + printk(TPQIC02_NAME + ": Settings: IRQ %d, DMA %d, IO 0x%x, IFC %s\n", + QIC02_TAPE_IRQ, QIC02_TAPE_DMA, ((QIC02_TAPE_IFC == ARCHIVE) + || (QIC02_TAPE_IFC == + MOUNTAIN)) ? + QIC02_CMD_PORT : QIC02_STAT_PORT, + (QIC02_TAPE_IFC == + MOUNTAIN) ? "Mountain" : ((QIC02_TAPE_IFC == + ARCHIVE) ? "Archive" : + "Wangtek")); + + if (tape_reset(0) != TE_OK + || tp_sense(TP_WRP | TP_POR | TP_CNI) != TE_OK) { + /* No drive detected, so vanish */ + tpqputs(TPQD_ALWAYS, + "No drive detected -- releasing IO/IRQ/DMA."); + status_dead = YES; + qic02_release_resources(); + return -EIO; + } + + /* All should be ok now */ + status_zombie = NO; + return 0; +} /* qic02_get_resources */ int __init qic02_tape_init(void) { - if (TPSTATSIZE != 6) - { - printk(TPQIC02_NAME ": internal error: tpstatus struct incorrect!\n"); - return -ENODEV; - } - if ((TPQBUF_SIZE<512) || (TPQBUF_SIZE>=0x10000)) - { - printk(TPQIC02_NAME ": internal error: DMA buffer size out of range\n"); - return -ENODEV; - } + if (TPSTATSIZE != 6) { + printk(TPQIC02_NAME + ": internal error: tpstatus struct incorrect!\n"); + return -ENODEV; + } + if ((TPQBUF_SIZE < 512) || (TPQBUF_SIZE >= 0x10000)) { + printk(TPQIC02_NAME + ": internal error: DMA buffer size out of range\n"); + return -ENODEV; + } - current_tape_dev = MKDEV(QIC02_TAPE_MAJOR, 0); + current_tape_dev = MKDEV(QIC02_TAPE_MAJOR, 0); #ifndef CONFIG_QIC02_DYNCONF - printk(TPQIC02_NAME ": IRQ %d, DMA %d, IO 0x%x, IFC %s, %s, %s\n", - QIC02_TAPE_IRQ, QIC02_TAPE_DMA, + printk(TPQIC02_NAME ": IRQ %d, DMA %d, IO 0x%x, IFC %s, %s, %s\n", + QIC02_TAPE_IRQ, QIC02_TAPE_DMA, # if QIC02_TAPE_IFC == WANGTEK - QIC02_STAT_PORT, "Wangtek", + QIC02_STAT_PORT, "Wangtek", # elif QIC02_TAPE_IFC == ARCHIVE - QIC02_CMD_PORT, "Archive", + QIC02_CMD_PORT, "Archive", # elif QIC02_TAPE_IFC == MOUNTAIN - QIC02_CMD_PORT, "Mountain", + QIC02_CMD_PORT, "Mountain", # else # error # endif - rcs_revision, rcs_date); - if (qic02_get_resources()) - { - return -ENODEV; - } + rcs_revision, rcs_date); + if (qic02_get_resources()) { + return -ENODEV; + } #else - printk(TPQIC02_NAME ": Runtime config, %s, %s\n", - rcs_revision, rcs_date); + printk(TPQIC02_NAME ": Runtime config, %s, %s\n", + rcs_revision, rcs_date); #endif - printk(TPQIC02_NAME ": DMA buffers: %u blocks\n", NR_BLK_BUF); - /* If we got this far, install driver functions */ - if (devfs_register_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME, &qic02_tape_fops)) - { - printk(TPQIC02_NAME ": Unable to get chrdev major %d\n", QIC02_TAPE_MAJOR); + printk(TPQIC02_NAME ": DMA buffers: %u blocks\n", NR_BLK_BUF); + /* If we got this far, install driver functions */ + if (devfs_register_chrdev + (QIC02_TAPE_MAJOR, TPQIC02_NAME, &qic02_tape_fops)) { + printk(TPQIC02_NAME ": Unable to get chrdev major %d\n", + QIC02_TAPE_MAJOR); #ifndef CONFIG_QIC02_DYNCONF - qic02_release_resources(); + qic02_release_resources(); #endif - return -ENODEV; - } - devfs_register (NULL, "ntpqic11", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 2, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register (NULL, "tpqic11", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 3, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register (NULL, "ntpqic24", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 4, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register (NULL, "tpqic24", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 5, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register (NULL, "ntpqic120", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 6, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register (NULL, "tpqic120", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 7, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register (NULL, "ntpqic150", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 8, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register (NULL, "tpqic150", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 9, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - init_waitqueue_head(&qic02_tape_transfer); - /* prepare timer */ - TIMEROFF; - init_timer(&tp_timer); - tp_timer.function = qic02_tape_times_out; - + return -ENODEV; + } + devfs_register(NULL, "ntpqic11", DEVFS_FL_DEFAULT, + QIC02_TAPE_MAJOR, 2, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + &qic02_tape_fops, NULL); + devfs_register(NULL, "tpqic11", DEVFS_FL_DEFAULT, + QIC02_TAPE_MAJOR, 3, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + &qic02_tape_fops, NULL); + devfs_register(NULL, "ntpqic24", DEVFS_FL_DEFAULT, + QIC02_TAPE_MAJOR, 4, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + &qic02_tape_fops, NULL); + devfs_register(NULL, "tpqic24", DEVFS_FL_DEFAULT, + QIC02_TAPE_MAJOR, 5, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + &qic02_tape_fops, NULL); + devfs_register(NULL, "ntpqic120", DEVFS_FL_DEFAULT, + QIC02_TAPE_MAJOR, 6, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + &qic02_tape_fops, NULL); + devfs_register(NULL, "tpqic120", DEVFS_FL_DEFAULT, + QIC02_TAPE_MAJOR, 7, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + &qic02_tape_fops, NULL); + devfs_register(NULL, "ntpqic150", DEVFS_FL_DEFAULT, + QIC02_TAPE_MAJOR, 8, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + &qic02_tape_fops, NULL); + devfs_register(NULL, "tpqic150", DEVFS_FL_DEFAULT, + QIC02_TAPE_MAJOR, 9, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + &qic02_tape_fops, NULL); + init_waitqueue_head(&qic02_tape_transfer); + /* prepare timer */ + TIMEROFF; + init_timer(&tp_timer); + tp_timer.function = qic02_tape_times_out; + #ifndef CONFIG_QIC02_DYNCONF - if (tape_reset(0)!=TE_OK || tp_sense(TP_WRP|TP_POR|TP_CNI)!=TE_OK) - { - /* No drive detected, so vanish */ - tpqputs(TPQD_ALWAYS, "No drive detected -- driver going on vacation..."); - qic02_release_resources(); - status_dead = YES; - return -ENODEV; - } - else - { - if (is_exception()) - { - tpqputs(TPQD_ALWAYS, "exception detected\n"); - (void) tp_sense(TP_WRP|TP_POR|TP_CNI); + if (tape_reset(0) != TE_OK + || tp_sense(TP_WRP | TP_POR | TP_CNI) != TE_OK) { + /* No drive detected, so vanish */ + tpqputs(TPQD_ALWAYS, + "No drive detected -- driver going on vacation..."); + qic02_release_resources(); + status_dead = YES; + return -ENODEV; + } else { + if (is_exception()) { + tpqputs(TPQD_ALWAYS, "exception detected\n"); + (void) tp_sense(TP_WRP | TP_POR | TP_CNI); + } } - } #endif - /* initialize generic status for ioctl requests */ - - ioctl_status.mt_type = QIC02_TAPE_DRIVE; /* MT_IS* id nr */ - - ioctl_status.mt_resid = 0; /* ---residual count */ - ioctl_status.mt_gstat = 0; /* ---generic status */ - ioctl_status.mt_erreg = 0; /* not used */ - ioctl_status.mt_fileno = 0; /* number of current file on tape */ - ioctl_status.mt_blkno = 0; /* number of current (logical) block */ + /* initialize generic status for ioctl requests */ + + ioctl_status.mt_type = QIC02_TAPE_DRIVE; /* MT_IS* id nr */ - return 0; -} /* qic02_tape_init */ + ioctl_status.mt_resid = 0; /* ---residual count */ + ioctl_status.mt_gstat = 0; /* ---generic status */ + ioctl_status.mt_erreg = 0; /* not used */ + ioctl_status.mt_fileno = 0; /* number of current file on tape */ + ioctl_status.mt_blkno = 0; /* number of current (logical) block */ + + return 0; +} /* qic02_tape_init */ #ifdef MODULE void cleanup_module(void) { - if (status_zombie == NO) - { - qic02_release_resources(); - } - devfs_unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME); - devfs_unregister(devfs_find_handle(NULL, "ntpqic11", QIC02_TAPE_MAJOR, 2, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "tpqic11", QIC02_TAPE_MAJOR, 3, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "ntpqic24", QIC02_TAPE_MAJOR, 4, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "tpqic24", QIC02_TAPE_MAJOR, 5, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "ntpqic120", QIC02_TAPE_MAJOR, 6, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "tpqic120", QIC02_TAPE_MAJOR, 7, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "ntpqic150", QIC02_TAPE_MAJOR, 8, DEVFS_SPECIAL_CHR, 0)); - devfs_unregister(devfs_find_handle(NULL, "tpqic150", QIC02_TAPE_MAJOR, 9, DEVFS_SPECIAL_CHR, 0)); + if (status_zombie == NO) { + qic02_release_resources(); + } + devfs_unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME); + devfs_unregister(devfs_find_handle + (NULL, "ntpqic11", QIC02_TAPE_MAJOR, 2, + DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle + (NULL, "tpqic11", QIC02_TAPE_MAJOR, 3, + DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle + (NULL, "ntpqic24", QIC02_TAPE_MAJOR, 4, + DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle + (NULL, "tpqic24", QIC02_TAPE_MAJOR, 5, + DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle + (NULL, "ntpqic120", QIC02_TAPE_MAJOR, 6, + DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle + (NULL, "tpqic120", QIC02_TAPE_MAJOR, 7, + DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle + (NULL, "ntpqic150", QIC02_TAPE_MAJOR, 8, + DEVFS_SPECIAL_CHR, 0)); + devfs_unregister(devfs_find_handle + (NULL, "tpqic150", QIC02_TAPE_MAJOR, 9, + DEVFS_SPECIAL_CHR, 0)); } int init_module(void) { - int retval; - retval=qic02_tape_init(); + int retval; + retval = qic02_tape_init(); # ifdef CONFIG_QIC02_DYNCONF - /* This allows the dynamic config program to setup the card - * by presetting qic02_tape_dynconf via insmod - */ - if (!retval && qic02_tape_dynconf.ifc_type) - { - retval=update_ifc_masks(qic02_tape_dynconf.ifc_type); - if (retval) - { - cleanup_module(); + /* This allows the dynamic config program to setup the card + * by presetting qic02_tape_dynconf via insmod + */ + if (!retval && qic02_tape_dynconf.ifc_type) { + retval = update_ifc_masks(qic02_tape_dynconf.ifc_type); + if (retval) { + cleanup_module(); + } } - } # endif - return retval; + return retval; } #endif + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.4.9/linux/drivers/char/tty_io.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/tty_io.c Fri Sep 7 10:53:59 2001 @@ -442,8 +442,6 @@ file_list_lock(); for (l = tty->tty_files.next; l != &tty->tty_files; l = l->next) { struct file * filp = list_entry(l, struct file, f_list); - if (!filp->f_dentry) - continue; if (filp->f_dentry->d_inode->i_rdev == CONSOLE_DEV || filp->f_dentry->d_inode->i_rdev == SYSCONS_DEV) { cons_filp = filp; diff -u --recursive --new-file v2.4.9/linux/drivers/char/vino.h linux/drivers/char/vino.h --- v2.4.9/linux/drivers/char/vino.h Fri Jun 25 17:39:14 1999 +++ linux/drivers/char/vino.h Wed Dec 31 16:00:00 1969 @@ -1,118 +0,0 @@ -/* $Id: vino.h,v 1.2 1999/02/09 23:03:53 ulfc Exp $ - * drivers/sgi/vino.h - * - * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) - */ - -#define VINO_BASE 0x0008000 - -#define VINO_REVID 0x0000 -#define VINO_CTRL 0x0008 -#define VINO_INTSTAT 0x0010 /* Interrupt status */ -#define VINO_I2C_CTRL 0x0018 -#define VINO_I2C_DATA 0x0020 -#define VINO_A_ALPHA 0x0028 /* Channel A ... */ -#define VINO_A_CLIPS 0x0030 /* Clipping start */ -#define VINO_A_CLIPE 0x0038 /* Clipping end */ -#define VINO_A_FRAMERT 0x0040 /* Framerate */ -#define VINO_A_FLDCNT 0x0048 /* Field counter */ -#define VINO_A_LNSZ 0x0050 -#define VINO_A_LNCNT 0x0058 -#define VINO_A_PGIX 0x0060 /* Page index */ -#define VINO_A_DESC_PTR 0x0068 /* Ptr to next four descriptors */ -#define VINO_A_DESC_TLB_PTR 0x0070 /* Ptr to start of descriptor table */ -#define VINO_A_DESC_DATA0 0x0078 /* Descriptor data 0 */ -#define VINO_A_DESC_DATA1 0x0080 /* ... */ -#define VINO_A_DESC_DATA2 0x0088 -#define VINO_A_DESC_DATA3 0x0090 -#define VINO_A_FIFO_THRESHOLD 0x0098 /* FIFO threshold */ -#define VINO_A_FIFO_RP 0x00a0 -#define VINO_A_FIFO_WP 0x00a8 -#define VINO_B_ALPHA 0x00b0 /* Channel B ... */ -#define VINO_B_CLIPS 0x00b8 -#define VINO_B_CLIPE 0x00c0 -#define VINO_B_FRAMERT 0x00c8 -#define VINO_B_FLDCNT 0x00d0 -#define VINO_B_LNSZ 0x00d8 -#define VINO_B_LNCNT 0x00e0 -#define VINO_B_PGIX 0x00e8 -#define VINO_B_DESC_PTR 0x00f0 -#define VINO_B_DESC_TLB_PTR 0x00f8 -#define VINO_B_DESC_DATA0 0x0100 -#define VINO_B_DESC_DATA1 0x0108 -#define VINO_B_DESC_DATA2 0x0110 -#define VINO_B_DESC_DATA3 0x0118 -#define VINO_B_FIFO_THRESHOLD 0x0120 -#define VINO_B_FIFO_RP 0x0128 -#define VINO_B_FIFO_WP 0x0130 - -/* Bits in the VINO_REVID register */ - -#define VINO_REVID_REV_MASK 0x000f /* bits 0:3 */ -#define VINO_REVID_ID_MASK 0x00f0 /* bits 4:7 */ - -/* Bits in the VINO_CTRL register */ - -#define VINO_CTRL_LITTLE_ENDIAN (1<<0) -#define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */ -#define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */ -#define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */ -#define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */ -#define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */ -#define VINO_CTRL_B_END_DESC_TLB_INT (1<<6) /* End of desc table int */ -#define VINO_CTRL_A_DMA_ENBL (1<<7) -#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8) -#define VINO_CTRL_A_SYNC_ENBL (1<<9) -#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */ -#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */ -#define VINO_CTRL_A_LUMA_ONLY (1<<12) -#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */ -#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */ -#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */ -#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */ -#define VINO_CTRL_B_DMA_ENBL (1<<19) -#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20) -#define VINO_CTRL_B_SYNC_ENBL (1<<21) -#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */ -#define VINO_CTRL_B_RGB (1<<22) /* 1=RGB 0=YUV */ -#define VINO_CTRL_B_LUMA_ONLY (1<<23) -#define VINO_CTRL_B_DEC_ENBL (1<<24) /* Decimation */ -#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 25:28 */ -#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */ -#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */ - -/* Bits in the Interrupt and Status register */ - -#define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */ -#define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */ -#define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */ -#define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */ -#define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */ -#define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */ - -/* Bits in the Clipping Start register */ - -#define VINO_CLIPS_START 0x3ff /* bits 0:9 */ -#define VINO_CLIPS_ODD_MASK 0x7fc00 /* bits 10:18 */ -#define VINO_CLIPS_EVEN_MASK 0xff80000 /* bits 19:27 */ - -/* Bits in the Clipping End register */ - -#define VINO_CLIPE_END 0x3ff /* bits 0:9 */ -#define VINO_CLIPE_ODD_MASK 0x7fc00 /* bits 10:18 */ -#define VINO_CLIPE_EVEN_MASK 0xff80000 /* bits 19:27 */ - -/* Bits in the Frame Rate register */ - -#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */ -#define VINO_FRAMERT_RT_MASK 0x1ffe /* bits 1:12 */ - -/* Bits in the VINO_I2C_CTRL */ - -#define VINO_CTRL_I2C_IDLE (1<<0) /* write: 0=force idle - * read: 0=idle 1=not idle */ -#define VINO_CTRL_I2C_DIR (1<<1) /* 0=read 1=write */ -#define VINO_CTRL_I2C_MORE_BYTES (1<<2) /* 0=last byte 1=more bytes */ -#define VINO_CTRL_I2C_TRANS_BUSY (1<<4) /* 0=trans done 1=trans busy */ -#define VINO_CTRL_I2C_ACK (1<<5) /* 0=ack received 1=ack not */ -#define VINO_CTRL_I2C_BUS_ERROR (1<<7) /* 0=no bus err 1=bus err */ diff -u --recursive --new-file v2.4.9/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.4.9/linux/drivers/char/vt.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/vt.c Tue Aug 28 07:09:44 2001 @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -145,8 +144,13 @@ #endif -void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound; +int _kbd_rate(struct kbd_repeat *rep) +{ + return -EINVAL; +} +void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound; +int (*kbd_rate)(struct kbd_repeat *rep) = _kbd_rate; #define i (tmp.kb_index) #define s (tmp.kb_table) @@ -504,7 +508,6 @@ { struct kbd_repeat kbrep; - if (!kbd_rate) return( -EINVAL ); if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff -u --recursive --new-file v2.4.9/linux/drivers/char/wdt.c linux/drivers/char/wdt.c --- v2.4.9/linux/drivers/char/wdt.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/wdt.c Fri Sep 7 09:28:38 2001 @@ -538,3 +538,7 @@ module_init(wdt_init); module_exit(wdt_exit); +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)"); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/wdt285.c linux/drivers/char/wdt285.c --- v2.4.9/linux/drivers/char/wdt285.c Sat May 19 17:43:05 2001 +++ linux/drivers/char/wdt285.c Fri Sep 7 09:28:38 2001 @@ -190,6 +190,7 @@ MODULE_AUTHOR("Phil Blundell "); MODULE_DESCRIPTION("21285 watchdog driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(soft_margin,"i"); MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/wdt977.c linux/drivers/char/wdt977.c --- v2.4.9/linux/drivers/char/wdt977.c Mon Oct 16 12:58:51 2000 +++ linux/drivers/char/wdt977.c Fri Sep 7 09:28:38 2001 @@ -199,3 +199,5 @@ module_init(nwwatchdog_init); module_exit(nwwatchdog_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c --- v2.4.9/linux/drivers/char/wdt_pci.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/wdt_pci.c Fri Sep 7 09:28:38 2001 @@ -626,3 +626,9 @@ module_init(wdtpci_init); module_exit(wdtpci_cleanup); + +MODULE_AUTHOR("JP Nollmann, Alan Cox"); +MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c --- v2.4.9/linux/drivers/i2o/i2o_block.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/i2o/i2o_block.c Sat Sep 8 12:02:32 2001 @@ -1195,9 +1195,6 @@ if(!dev->i2odev) return 0; - /* Sync the device so we don't get errors */ - fsync_dev(inode->i_rdev); - if (dev->refcnt <= 0) printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt); dev->refcnt--; @@ -1978,9 +1975,8 @@ /* * Adding i2ob_gendisk into the gendisk list. - */ - i2ob_gendisk.next = gendisk_head; - gendisk_head = &i2ob_gendisk; + */ + add_gendisk(&i2ob_gendisk); return 0; } @@ -2050,20 +2046,6 @@ */ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - /* - * Why isnt register/unregister gendisk in the kernel ??? - */ - - if (gendisk_head == &i2ob_gendisk) { - gendisk_head = i2ob_gendisk.next; - } - else { - for (gdp = gendisk_head; gdp; gdp = gdp->next) - if (gdp->next == &i2ob_gendisk) - { - gdp->next = i2ob_gendisk.next; - break; - } - } + del_gendisk(&i2ob_gendisk); } #endif diff -u --recursive --new-file v2.4.9/linux/drivers/ide/Config.in linux/drivers/ide/Config.in --- v2.4.9/linux/drivers/ide/Config.in Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/Config.in Fri Sep 7 09:28:38 2001 @@ -135,7 +135,7 @@ if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 fi - bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580 + bool ' QDI QD65xx support' CONFIG_BLK_DEV_QD65XX bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672 fi fi diff -u --recursive --new-file v2.4.9/linux/drivers/ide/Makefile linux/drivers/ide/Makefile --- v2.4.9/linux/drivers/ide/Makefile Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/Makefile Fri Sep 7 09:28:38 2001 @@ -56,7 +56,7 @@ ide-obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o ide-obj-$(CONFIG_BLK_DEV_PDC_ADMA) += pdcadma.o ide-obj-$(CONFIG_BLK_DEV_PIIX) += piix.o -ide-obj-$(CONFIG_BLK_DEV_QD6580) += qd6580.o +ide-obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o ide-obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o ide-obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o diff -u --recursive --new-file v2.4.9/linux/drivers/ide/hd.c linux/drivers/ide/hd.c --- v2.4.9/linux/drivers/ide/hd.c Sat Apr 28 11:27:53 2001 +++ linux/drivers/ide/hd.c Sat Sep 8 12:02:32 2001 @@ -842,8 +842,7 @@ } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ - hd_gendisk.next = gendisk_head; - gendisk_head = &hd_gendisk; + add_gendisk(&hd_gendisk, MAJOR_NR); init_timer(&device_timer); device_timer.function = hd_times_out; hd_geninit(); diff -u --recursive --new-file v2.4.9/linux/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c --- v2.4.9/linux/drivers/ide/ide-floppy.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/ide-floppy.c Fri Sep 7 09:28:38 2001 @@ -1,7 +1,8 @@ /* - * linux/drivers/ide/ide-floppy.c Version 0.9.sv Jan 6 2001 + * linux/drivers/ide/ide-floppy.c Version 0.97.sv Jan 14 2001 * * Copyright (C) 1996 - 1999 Gadi Oxman + * Copyright (C) 2000 - 2001 Paul Bristow */ /* @@ -10,6 +11,12 @@ * The driver currently doesn't have any fancy features, just the bare * minimum read/write support. * + * This driver supports the following IDE floppy drives: + * + * LS-120 SuperDisk + * Iomega Zip 100/250 + * Iomega PC Card Clik!/PocketZip + * * Many thanks to Lode Leroy , who tested so many * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive. * @@ -38,6 +45,20 @@ * mode page. Implemented four IOCTLs in order to * implement formatting. IOCTls begin with 0x4600, * 0x46 is 'F' as in Format. + * Jan 9 01 Userland option to select format verify. + * Added PC_SUPPRESS_ERROR flag - some idefloppy drives + * do not implement IDEFLOPPY_CAPABILITIES_PAGE, and + * return a sense error. Suppress error reporting in + * this particular case in order to avoid spurious + * errors in syslog. The culprit is + * idefloppy_get_capability_page(), so move it to + * idefloppy_begin_format() so that it's not used + * unless absolutely necessary. + * If drive does not support format progress indication + * monitor the dsc bit in the status register. + * Also, O_NDELAY on open will allow the device to be + * opened without a disk available. This can be used to + * open an unformatted disk, or get the device capacity. * Ver 0.91 Dec 11 99 Added IOMEGA Clik! drive support by * * Ver 0.92 Oct 22 00 Paul Bristow became official maintainer for this @@ -49,9 +70,10 @@ * Ver 0.96 Jan 7 01 Actually in line with release version of 2.4.0 * including set_bit patch from Rusty Russel * Ver 0.97 Jul 22 01 Merge 0.91-0.96 onto 0.9.sv for ac series + * Ver 0.97.sv Aug 3 01 Backported from 2.4.7-ac3 */ -#define IDEFLOPPY_VERSION "0.97" +#define IDEFLOPPY_VERSION "0.97.sv" #include #include @@ -140,6 +162,8 @@ #define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */ #define PC_WRITING 5 /* Data direction */ +#define PC_SUPPRESS_ERROR 6 /* Suppress error reporting */ + /* * Removable Block Access Capabilities Page */ @@ -1022,8 +1046,11 @@ * a legitimate error code was received. */ if (!test_bit (PC_ABORT, &pc->flags)) { - printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", + if (!test_bit (PC_SUPPRESS_ERROR, &pc->flags)) { + ; + printk( KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", drive->name, pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); + } pc->error = IDEFLOPPY_ERROR_GENERAL; /* Giving up */ } floppy->failed_pc=NULL; @@ -1101,14 +1128,19 @@ pc->request_transfer = 255; } -static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l) +static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l, + int flags) { idefloppy_init_pc (pc); pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD; pc->c[1] = 0x17; memset(pc->buffer, 0, 12); - pc->buffer[1] = 0xA2; /* Format list header, byte 1: FOV/DCRT/IMM */ + pc->buffer[1] = 0xA2; + /* Default format list header, byte 1: FOV/DCRT/IMM bits set */ + + if (flags & 1) /* Verify bit on... */ + pc->buffer[1] ^= 0x20; /* ... turn off DCRT bit */ pc->buffer[3] = 8; put_unaligned(htonl(b), (unsigned int *)(&pc->buffer[4])); @@ -1300,9 +1332,12 @@ floppy->srfp=0; idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_CAPABILITIES_PAGE, MODE_SENSE_CURRENT); + + set_bit(PC_SUPPRESS_ERROR, &pc.flags); if (idefloppy_queue_pc_tail (drive,&pc)) { return 1; } + header = (idefloppy_mode_parameter_header_t *) pc.buffer; page= (idefloppy_capabilities_page_t *)(header+1); floppy->srfp=page->srfp; @@ -1378,7 +1413,6 @@ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { (void) idefloppy_get_flexible_disk_page (drive); - (void) idefloppy_get_capability_page (drive); } drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor; @@ -1478,7 +1512,12 @@ ** struct idefloppy_format_command { ** int nblocks; ** int blocksize; +** int flags; ** } ; +** +** flags is a bitmask, currently, the only defined flag is: +** +** 0x01 - verify media after format. */ static int idefloppy_begin_format(ide_drive_t *drive, @@ -1488,15 +1527,18 @@ { int blocks; int length; + int flags; idefloppy_pc_t pc; if (get_user(blocks, arg) - || get_user(length, arg+1)) + || get_user(length, arg+1) + || get_user(flags, arg+2)) { return (-EFAULT); } - idefloppy_create_format_unit_cmd(&pc, blocks, length); + (void) idefloppy_get_capability_page (drive); /* Get the SFRP bit */ + idefloppy_create_format_unit_cmd(&pc, blocks, length, flags); if (idefloppy_queue_pc_tail (drive, &pc)) { return (-EIO); @@ -1510,8 +1552,8 @@ ** Userland gives a pointer to an int. The int is set to a progresss ** indicator 0-65536, with 65536=100%. ** -** If the drive does not support format progress indication, we just return -** a 65536, screw it. +** If the drive does not support format progress indication, we just check +** the dsc bit, and return either 0 or 65536. */ static int idefloppy_get_format_progress(ide_drive_t *drive, @@ -1536,8 +1578,21 @@ { progress_indication=floppy->progress_indication; } + /* Else assume format_unit has finished, and we're + ** at 0x10000 */ } + else + { + idefloppy_status_reg_t status; + unsigned long flags; + __save_flags(flags); + __cli(); + status.all=GET_STAT(); + __restore_flags(flags); + + progress_indication= !status.b.dsc ? 0:0x10000; + } if (put_user(progress_indication, arg)) return (-EFAULT); @@ -1587,8 +1642,6 @@ { idefloppy_floppy_t *floppy = drive->driver_data; - set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); - if (drive->usage > 1) { /* Don't format if someone is using the disk */ @@ -1599,7 +1652,12 @@ } else { - int rc=idefloppy_begin_format(drive, inode, + int rc; + + set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, + &floppy->flags); + + rc=idefloppy_begin_format(drive, inode, file, (int *)arg); @@ -1637,7 +1695,6 @@ MOD_INC_USE_COUNT; if (drive->usage == 1) { - clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); /* Just in case */ @@ -1647,7 +1704,14 @@ (void) idefloppy_queue_pc_tail (drive, &pc); } - if (idefloppy_get_capacity (drive)) { + if (idefloppy_get_capacity (drive) + && (filp->f_flags & O_NDELAY) == 0 + /* + ** Allow O_NDELAY to open a drive without a disk, or with + ** an unreadable disk, so that we can get the format + ** capacity of the drive or begin the format - Sam + */ + ) { drive->usage--; MOD_DEC_USE_COUNT; return -EIO; @@ -1893,6 +1957,17 @@ for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; } + /* + * Guess what? The IOMEGA Clik! drive also needs the + * above fix. It makes nasty clicking noises without + * it, so please don't remove this. + */ + if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) + { + for (i = 0; i < 1 << PARTN_BITS; i++) + max_sectors[major][minor + i] = 64; + set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags); + } /* * Guess what? The IOMEGA Clik! drive also needs the diff -u --recursive --new-file v2.4.9/linux/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c --- v2.4.9/linux/drivers/ide/ide-probe.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/ide-probe.c Sat Sep 8 12:02:32 2001 @@ -747,7 +747,7 @@ */ static void init_gendisk (ide_hwif_t *hwif) { - struct gendisk *gd, **gdp; + struct gendisk *gd; unsigned int unit, units, minors; int *bs, *max_sect, *max_ra; extern devfs_handle_t ide_devfs_handle; @@ -800,8 +800,8 @@ if (gd->flags) memset (gd->flags, 0, sizeof *gd->flags * units); - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) ; - hwif->gd = *gdp = gd; /* link onto tail of list */ + hwif->gd = gd; + add_gendisk(gd); for (unit = 0; unit < units; ++unit) { if (hwif->drives[unit].present) { diff -u --recursive --new-file v2.4.9/linux/drivers/ide/ide-proc.c linux/drivers/ide/ide-proc.c --- v2.4.9/linux/drivers/ide/ide-proc.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/ide-proc.c Fri Sep 7 09:28:38 2001 @@ -404,7 +404,7 @@ case ide_cmd640: name = "cmd640"; break; case ide_dtc2278: name = "dtc2278"; break; case ide_ali14xx: name = "ali14xx"; break; - case ide_qd6580: name = "qd6580"; break; + case ide_qd65xx: name = "qd65xx"; break; case ide_umc8672: name = "umc8672"; break; case ide_ht6560b: name = "ht6560b"; break; case ide_pdc4030: name = "pdc4030"; break; diff -u --recursive --new-file v2.4.9/linux/drivers/ide/ide.c linux/drivers/ide/ide.c --- v2.4.9/linux/drivers/ide/ide.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/ide.c Sat Sep 8 12:02:32 2001 @@ -2059,7 +2059,7 @@ void ide_unregister (unsigned int index) { - struct gendisk *gd, **gdp; + struct gendisk *gd; ide_drive_t *drive, *d; ide_hwif_t *hwif, *g; ide_hwgroup_t *hwgroup; @@ -2179,13 +2179,9 @@ blk_dev[hwif->major].data = NULL; blk_dev[hwif->major].queue = NULL; blksize_size[hwif->major] = NULL; - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) - if (*gdp == hwif->gd) - break; - if (*gdp == NULL) - printk("gd not in disk chain!\n"); - else { - gd = *gdp; *gdp = gd->next; + gd = hwif->gd; + if (gd) { + del_gendisk(gd); kfree(gd->sizes); kfree(gd->part); if (gd->de_arr) @@ -2193,6 +2189,7 @@ if (gd->flags) kfree (gd->flags); kfree(gd); + hwif->gd = NULL; } old_hwif = *hwif; init_hwif_data (index); /* restore hwif data to pristine status */ @@ -2788,6 +2785,8 @@ case BLKPG: case BLKELVGET: case BLKELVSET: + case BLKBSZGET: + case BLKBSZSET: return blk_ioctl(inode->i_rdev, cmd, arg); case HDIO_GET_BUSSTATE: @@ -2987,7 +2986,7 @@ * "ide0=ht6560b" : probe/support HT6560B interface * "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip * (not for PCI -- automatically detected) - * "ide0=qd6580" : probe/support qd6580 interface + * "ide0=qd65xx" : probe/support qd65xx interface * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) * "ide0=umc8672" : probe/support umc8672 chipsets * "idex=dc4030" : probe/support Promise DC4030VL interface @@ -3155,7 +3154,7 @@ const char *ide_words[] = { "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", "minus8", "minus9", "minus10", - "four", "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; + "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); @@ -3222,14 +3221,14 @@ goto done; } #endif /* CONFIG_BLK_DEV_HT6560B */ -#if CONFIG_BLK_DEV_QD6580 - case -12: /* "qd6580" */ +#if CONFIG_BLK_DEV_QD65XX + case -12: /* "qd65xx" */ { - extern void init_qd6580 (void); - init_qd6580(); + extern void init_qd65xx (void); + init_qd65xx(); goto done; } -#endif /* CONFIG_BLK_DEV_QD6580 */ +#endif /* CONFIG_BLK_DEV_QD65XX */ #ifdef CONFIG_BLK_DEV_4DRIVES case -11: /* "four" drives on one set of ports */ { diff -u --recursive --new-file v2.4.9/linux/drivers/ide/it8172.c linux/drivers/ide/it8172.c --- v2.4.9/linux/drivers/ide/it8172.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/it8172.c Fri Sep 7 09:28:38 2001 @@ -5,7 +5,7 @@ * * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * stevel@mvista.com or support@mvista.com + * stevel@mvista.com or source@mvista.com * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -57,50 +57,41 @@ void __init ide_init_it8172 (ide_hwif_t *hwif); -/* - * Based on settings done by AMI BIOS - * (might be usefull if drive is not registered in CMOS for any reason). - */ static void it8172_tune_drive (ide_drive_t *drive, byte pio) { unsigned long flags; u16 master_data; - byte slave_data; + u32 slave_data; int is_slave = (&HWIF(drive)->drives[1] == drive); - int master_port = HWIF(drive)->index ? 0x42 : 0x40; - int slave_port = 0x44; - /* ISP RTC */ - byte timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - + int master_port = 0x40; + int slave_port = 0x44; + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data); + pci_read_config_dword(HWIF(drive)->pci_dev, slave_port, &slave_data); + + /* + * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44 + * are being left at the default values of 8 PCI clocks (242 nsec + * for a 33 MHz clock). These can be safely shortened at higher + * PIO modes. + */ + if (is_slave) { - master_data = master_data | 0x4000; + master_data |= 0x4000; if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0070; - pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data); - slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0); - slave_data = slave_data | - ((timings[pio][0] << 2) | (timings[pio][1] - << (HWIF(drive)->index ? 4 : 0))); + /* enable PPE and IE */ + master_data |= 0x0060; } else { - master_data = master_data & 0xccf8; + master_data &= 0xc060; if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0007; - master_data = master_data | (timings[pio][0] << 12) | - (timings[pio][1] << 8); + /* enable PPE and IE */ + master_data |= 0x0006; } + save_flags(flags); cli(); pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data); restore_flags(flags); } @@ -150,12 +141,22 @@ pci_read_config_byte(dev, 0x48, ®48); pci_read_config_byte(dev, 0x4a, ®4a); + /* + * Setting the DMA cycle time to 2 or 3 PCI clocks (60 and 91 nsec + * at 33 MHz PCI clock) seems to cause BadCRC errors during DMA + * transfers on some drives, even though both numbers meet the minimum + * ATAPI-4 spec of 73 and 54 nsec for UDMA 1 and 2 respectively. + * So the faster times are just commented out here. The good news is + * that the slower cycle time has very little affect on transfer + * performance. + */ + switch(speed) { case XFER_UDMA_4: - case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_2: //u_speed = 2 << (drive->dn * 4); break; case XFER_UDMA_5: case XFER_UDMA_3: - case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_1: //u_speed = 1 << (drive->dn * 4); break; case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; case XFER_MW_DMA_2: case XFER_MW_DMA_1: @@ -164,25 +165,16 @@ } if (speed >= XFER_UDMA_0) { - if (!(reg48 & u_flag)) - pci_write_config_byte(dev, 0x48, reg48|u_flag); - if (!(reg4a & u_speed)) { - pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); - pci_write_config_byte(dev, 0x4a, reg4a|u_speed); - } - } - if (speed < XFER_UDMA_0) { - if (reg48 & u_flag) - pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + reg4a &= ~a_speed; + pci_write_config_byte(dev, 0x4a, reg4a | u_speed); + } else { + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); } it8172_tune_drive(drive, it8172_dma_2_pio(speed)); -#if IT8172_DEBUG - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); -#endif if (!drive->init_speed) drive->init_speed = speed; err = ide_config_drive_speed(drive, speed); @@ -236,7 +228,9 @@ /* Other cases are done by generic IDE-DMA code. */ return ide_dmaproc(func, drive); } + #endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_IT8172_TUNING) */ + unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name) { diff -u --recursive --new-file v2.4.9/linux/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c --- v2.4.9/linux/drivers/ide/pdc202xx.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/pdc202xx.c Fri Sep 7 09:28:38 2001 @@ -133,6 +133,7 @@ switch(dev->device) { case PCI_DEVICE_ID_PROMISE_20268: + case PCI_DEVICE_ID_PROMISE_20268R: p += sprintf(p, "\n PDC20268 TX2 Chipset.\n"); invalid_data_set = 1; break; diff -u --recursive --new-file v2.4.9/linux/drivers/ide/qd6580.c linux/drivers/ide/qd6580.c --- v2.4.9/linux/drivers/ide/qd6580.c Tue Jun 20 07:52:36 2000 +++ linux/drivers/ide/qd6580.c Wed Dec 31 16:00:00 1969 @@ -1,410 +0,0 @@ -/* - * linux/drivers/ide/qd6580.c Version 0.04 June 4, 2000 - * - * Copyright (C) 1996-2000 Linus Torvalds & author (see below) - */ - -/* - * Version 0.03 Cleaned auto-tune, added probe - * Version 0.04 Added second channel tuning - * - * QDI QD6580 EIDE controller fast support - * - * To activate controller support use kernel parameter "ide0=qd6580" - * To enable tuning use kernel parameter "ide0=autotune" - * To enable tuning second channel (not really tested), - * use parameter "ide1=autotune" - */ - -/* - * Rewritten from the work of Colten Edwards by - * Samuel Thibault - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -/* - * I/O ports are 0xb0-0xb3 - * or 0x30-0x33 - * -- this is a dual IDE interface with I/O chips - * - * More research on qd6580 being done by willmore@cig.mot.com (David) - * More Information given by Petr Sourcek (petr@ryston.cz) - * http://www.ryston.cz/petr/vlb - */ - -/* - * 0xb0: Timer1 - * - * - * 0xb1: Config - * - * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 - * (? Strange: the Dos driver uses it, and then forces baseport to 0x1f0 ?) - * bit 1: qd baseport: 1 = 0xb0 ; 0 = 0x30 - * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz - * bit 3: 1 for qd6580 - * upper nibble is either 1010 or 0101, or else it isn't a qd6580 - * - * - * 0xb2: Timer2 - * - * - * 0xb3: Control - * - * bits 0-3 must always be set 1 - * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock - * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb - * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb - * channel 1 for hdc & hdd - * bit 1 : 1 = only disks on primary port - * 0 = disks & ATAPI devices on primary port - * bit 2-4 : always 0 - * bit 5 : status, but of what ? - * bit 6 : always set 1 by dos driver - * bit 7 : set 1 for non-ATAPI devices (read-ahead and post-write buffer ?) - */ - -/* truncates a in [b,c] */ -#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) - -typedef struct ide_hd_timings_s { - int active_time; /* Active pulse (ns) minimum */ - int recovery_time; /* Recovery pulse (ns) minimum */ -} ide_hd_timings_t; - -static int basePort; /* base port address (0x30 or 0xb0) */ -static byte config; /* config register of qd6580 */ -static byte control; /* control register of qd6580 */ - -static int bus_clock; /* Vesa local bus clock (ns) */ -static int tuned=0; /* to remember whether we've already been tuned */ -static int snd_tuned=0; /* to remember whether we've already been tuned */ -static int nb_disks_prim=0; /* number of disk drives on primary port */ - -/* - * write_reg - * - * writes the specified byte on the specified register - */ - -static void write_reg ( byte content, byte reg ) -{ - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - outb_p(content,reg); - inb(0x3f6); - restore_flags(flags); /* all CPUs */ -} - -/* - * tune_drive - * - * Finds timings for the specified drive, returns it in struct t - */ - -static void tune_drive ( ide_drive_t *drive, byte pio, ide_hd_timings_t *t ) -{ - ide_pio_data_t d; - - t->active_time = 175; - t->recovery_time = 415; /* worst cases values from the dos driver */ - - if (!drive->present) { /* not present : free to give any timing */ - t->active_time = 0; - t->recovery_time = 0; - return; - } - - pio = ide_get_best_pio_mode(drive, pio, 255, &d); - pio = IDE_MIN(pio,4); - - switch (pio) { - case 0: break; - case 3: - if (d.cycle_time >= 110) { - t->active_time = 86; - t->recovery_time = d.cycle_time-102; - } else { - printk("%s: Strange recovery time !\n",drive->name); - return; - } - break; - case 4: - if (d.cycle_time >= 69) { - t->active_time = 70; - t->recovery_time = d.cycle_time-61; - } else { - printk("%s: Strange recovery time !\n",drive->name); - return; - } - break; - default: - if (d.cycle_time >= 180) { - t->active_time = 110; - t->recovery_time = d.cycle_time - 120; - } else { - t->active_time = ide_pio_timings[pio].active_time; - t->recovery_time = d.cycle_time - -t->active_time; - } - } - printk("%s: PIO mode%d, tim1=%dns tim2=%dns\n", drive->name, pio, t->active_time, t->recovery_time); - - if (drive->media == ide_disk) - nb_disks_prim++; - else { -/* need to disable read-ahead FIFO and post-write buffer for ATAPI drives*/ - write_reg(0x5f,basePort+0x03); - printk("%s: Warning: please try to connect this drive to secondary IDE port\nto improve data transfer rate on primary IDE port.\n",drive->name); - } -} - -/* - * tune_snd_drive - * - * Finds timings for the specified drive, using second channel rules - */ - -static void tune_snd_drive ( ide_drive_t *drive, byte pio, ide_hd_timings_t *t ) -{ - ide_pio_data_t d; - - t->active_time = 175; - t->recovery_time = 415; - - if (!drive->present) { /* not present : free to give any timing */ - t->active_time = 0; - t->recovery_time = 0; - return; - } - - pio = ide_get_best_pio_mode(drive, pio, 255, &d); - - if ((pio) && (d.cycle_time >= 180)) { - t->active_time = 115; - t->recovery_time = d.cycle_time - 115; - } - printk("%s: PIO mode%d, tim1=%dns tim2=%dns\n", drive->name, pio, t->active_time, t->recovery_time); - - if ((drive->media == ide_disk) && (nb_disks_prim<2)) { -/* a disk drive on secondary port while there's room on primary, which is the - * only one that has read-ahead fifo and post-write buffer ? What a waste !*/ - printk("%s: Warning: please try to connect this drive to primary IDE port\nto improve data transfer rate.\n",drive->name); - } -} - -/* - * compute_timing - * - * computes the timing value where - * lower nibble is active time, in count of VLB clocks, 17-(from 2 to 17) - * upper nibble is recovery time, in count of VLB clocks, 15-(from 2 to 15) - */ - -static byte compute_timing ( char name[6], ide_hd_timings_t *t ) -{ - byte active_cycle; - byte recovery_cycle; - byte parameter; - - active_cycle = 17-IDE_IN(t->active_time / bus_clock + 1, 2, 17); - recovery_cycle = 15-IDE_IN(t->recovery_time / bus_clock + 1, 2, 15); - - parameter = active_cycle | (recovery_cycle<<4); - - printk("%s: tim1=%dns tim2=%dns => %#x\n", name, t[0].active_time, t[0].recovery_time, parameter); - return(parameter); -} - -/* - * tune_ide - * - * Tunes the whole hwif, ie tunes each drives, and in case we have to share, - * takes the worse timings to tune qd6580 - */ - -static void tune_ide ( ide_hwif_t *hwif, byte pio ) -{ - unsigned long flags; - ide_hd_timings_t t[2]={{0,0},{0,0}}; - int bus_speed = ide_system_bus_speed (); - - bus_clock = 1000 / bus_speed; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - outb( (bus_clock<30) ? 0x0 : 0x0a, basePort + 0x02); - outb( 0x40 | ((control & 0x02) ? 0x9f:0x1f), basePort+0x03); - restore_flags(flags); - - tune_drive (&hwif->drives[0], pio, &t[0]); - tune_drive (&hwif->drives[1], pio, &t[1]); - - if (control & 0x01) { /* only primary port enabled, can tune separately */ - write_reg(compute_timing (hwif->drives[0].name, &t[0]),basePort); - write_reg(compute_timing (hwif->drives[1].name, &t[1]),basePort+0x02); - } else { /* both ports enabled, we have to share */ - - t[0].active_time = IDE_MAX(t[0].active_time, t[1].active_time); - t[0].recovery_time = IDE_MAX(t[0].recovery_time,t[1].recovery_time); - write_reg(compute_timing (hwif->name, &t[0]),basePort); - } -} - -/* - * tune_snd_ide - * - * Tunes the whole secondary hwif, ie tunes each drives, and takes the worse - * timings to tune qd6580 - */ - -static void tune_snd_ide ( ide_hwif_t *hwif, byte pio ) -{ - ide_hd_timings_t t[2]={{0,0},{0,0}}; - - tune_snd_drive (&hwif->drives[0], pio, &t[0]); - tune_snd_drive (&hwif->drives[1], pio, &t[1]); - - t[0].active_time = IDE_MAX(t[0].active_time, t[1].active_time); - t[0].recovery_time = IDE_MAX(t[0].recovery_time,t[1].recovery_time); - - write_reg(compute_timing (hwif->name, &t[0]),basePort+0x02); -} - -/* - * tune_qd6580 - * - * tunes the hwif if not tuned - */ - -static void tune_qd6580 (ide_drive_t *drive, byte pio) -{ - if (! tuned) { - tune_ide(HWIF(drive), pio); - tuned = 1; - } -} - -/* - * tune_snd_qd6580 - * - * tunes the second hwif if not tuned - */ - -static void tune_snd_qd6580 (ide_drive_t *drive, byte pio) -{ - if (! snd_tuned) { - tune_snd_ide(HWIF(drive), pio); - snd_tuned = 1; - } -} - -/* - * testreg - * - * tests if the given port is a register - */ - -static int __init testreg(int port) -{ - byte savereg; - byte readreg; - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - savereg = inb(port); - outb_p(0x15,port); /* safe value */ - readreg = inb_p(port); - outb(savereg,port); - restore_flags(flags); /* all CPUs */ - - if (savereg == 0x15) { - printk("Outch ! the probe for qd6580 isn't reliable !\n"); - printk("Please contact maintainers to tell about your hardware\n"); - printk("Assuming qd6580 is not present.\n"); - return 0; - } - - return (readreg == 0x15); -} - -/* - * trybase: - * - * tries to find a qd6580 at the given base and save it if found - */ - -static int __init trybase (int base) -{ - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - config = inb(base+0x01); - control = inb(base+0x03); - restore_flags(flags); /* all CPUs */ - - if (((config & 0xf0) != 0x50) && ((config & 0xf0) != 0xa0)) return(0); - if (! ( ((config & 0x02) == 0x0) == (base == 0x30) ) ) return (0); - - /* Seems to be OK, let's use it */ - - basePort = base; - return(testreg(base)); -} - -/* - * probe: - * - * probes qd6580 at 0xb0 (the default) or 0x30 - */ - -static int __init probe (void) -{ - return (trybase(0xb0) ? 1 : trybase(0x30)); -} - -/* - * init_qd6580: - * - * called at the very beginning of initialization ; should just probe and link - */ - -void __init init_qd6580 (void) -{ - if (! probe()) { - printk("qd6580: not found\n"); - return; - } - - printk("qd6580: base=%#x, config=%#x, control=%#x\n", basePort, config, control); - - ide_hwifs[0].chipset = ide_qd6580; - ide_hwifs[0].tuneproc = &tune_qd6580; - if (!(control & 0x01)) { - ide_hwifs[1].chipset = ide_qd6580; - ide_hwifs[1].tuneproc = &tune_snd_qd6580; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; - } -} diff -u --recursive --new-file v2.4.9/linux/drivers/ide/qd65xx.c linux/drivers/ide/qd65xx.c --- v2.4.9/linux/drivers/ide/qd65xx.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/ide/qd65xx.c Fri Sep 7 09:28:38 2001 @@ -0,0 +1,453 @@ +/* + * linux/drivers/ide/qd65xx.c Version 0.06 Aug 3, 2000 + * + * Copyright (C) 1996-2000 Linus Torvalds & author (see below) + */ + +/* + * Version 0.03 Cleaned auto-tune, added probe + * Version 0.04 Added second channel tuning + * Version 0.05 Enhanced tuning ; added qd6500 support + * Version 0.06 added dos driver's list + * + * QDI QD6500/QD6580 EIDE controller fast support + * + * Please set local bus speed using kernel parameter idebus + * for example, "idebus=33" stands for 33Mhz VLbus + * To activate controller support, use "ide0=qd65xx" + * To enable tuning, use "ide0=autotune" + * To enable second channel tuning (qd6580 only), use "ide1=autotune" + */ + +/* + * Rewritten from the work of Colten Edwards by + * Samuel Thibault + */ + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide_modes.h" +#include "qd65xx.h" + +/* + * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580) + * or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580) + * -- qd6500 is a single IDE interface + * -- qd6580 is a dual IDE interface + * + * More research on qd6580 being done by willmore@cig.mot.com (David) + * More Information given by Petr Soucek (petr@ryston.cz) + * http://www.ryston.cz/petr/vlb + */ + +/* + * base: Timer1 + * + * + * base+0x01: Config (R/O) + * + * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500) + * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30 + * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz + * bit 3: qd6500: 1 = disabled, 0 = enabled + * qd6580: 1 + * upper nibble: + * qd6500: 1100 + * qd6580: either 1010 or 0101 + * + * base+0x02: Timer2 (qd6580 only) + * + * + * base+0x03: Control (qd6580 only) + * + * bits 0-3 must always be set 1 + * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock + * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb + * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb + * channel 1 for hdc & hdd + * bit 1 : 1 = only disks on primary port + * 0 = disks & ATAPI devices on primary port + * bit 2-4 : always 0 + * bit 5 : status, but of what ? + * bit 6 : always set 1 by dos driver + * bit 7 : set 1 for non-ATAPI devices on primary port + * (maybe read-ahead and post-write buffer ?) + */ + +static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ + +static void qd_write_reg (byte content, byte reg) +{ + unsigned long flags; + + save_flags(flags); /* all CPUs */ + cli(); /* all CPUs */ + outb(content,reg); + restore_flags(flags); /* all CPUs */ +} + +byte __init qd_read_reg (byte reg) +{ + unsigned long flags; + byte read; + + save_flags(flags); /* all CPUs */ + cli(); /* all CPUs */ + read = inb(reg); + restore_flags(flags); /* all CPUs */ + return read; +} + +/* + * qd_select: + * + * This routine is invoked from ide.c to prepare for access to a given drive. + */ + +static void qd_select (ide_drive_t *drive) +{ + byte index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | + (QD_TIMREG(drive) & 0x02); + + if (timings[index] != QD_TIMING(drive)) + qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); +} + +/* + * qd6500_compute_timing + * + * computes the timing value where + * lower nibble represents active time, in count of VLB clocks + * upper nibble represents recovery time, in count of VLB clocks + */ + +static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time) +{ + byte active_cycle,recovery_cycle; + + if (system_bus_clock()<=33) { + active_cycle = 9 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 9); + recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 0, 15); + } else { + active_cycle = 8 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 1, 8); + recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 3, 18); + } + + return((recovery_cycle<<4) | 0x08 | active_cycle); +} + +/* + * qd6580_compute_timing + * + * idem for qd6580 + */ + +static byte qd6580_compute_timing (int active_time, int recovery_time) +{ + byte active_cycle = 17-IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 17); + byte recovery_cycle = 15-IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 2, 15); + + return((recovery_cycle<<4) | active_cycle); +} + +/* + * qd_find_disk_type + * + * tries to find timing from dos driver's table + */ + +static int qd_find_disk_type (ide_drive_t *drive, + int *active_time, int *recovery_time) +{ + struct qd65xx_timing_s *p; + char model[40]; + + if (!*drive->id->model) return 0; + + strncpy(model,drive->id->model,40); + ide_fixstring(model,40,1); /* byte-swap */ + + for (p = qd65xx_timing ; p->offset != -1 ; p++) { + if (!strncmp(p->model, model+p->offset,4)) { + printk(KERN_DEBUG "%s: listed !\n",drive->name); + *active_time = p->active; + *recovery_time = p->recovery; + return 1; + } + } + return 0; +} + +/* + * qd_timing_ok: + * + * check whether timings don't conflict + */ + +static int qd_timing_ok (ide_drive_t drives[]) +{ + return (IDE_IMPLY(drives[0].present && drives[1].present, + IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1), + QD_TIMING(drives) == QD_TIMING(drives+1)))); + /* if same timing register, must be same timing */ +} + +/* + * qd_set_timing: + * + * records the timing, and enables selectproc as needed + */ + +static void qd_set_timing (ide_drive_t *drive, byte timing) +{ + ide_hwif_t *hwif = HWIF(drive); + + drive->drive_data &= 0xff00; + drive->drive_data |= timing; + if (qd_timing_ok(hwif->drives)) { + qd_select(drive); /* selects once */ + hwif->selectproc = NULL; + } else + hwif->selectproc = &qd_select; + + printk(KERN_DEBUG "%s: %#x\n",drive->name,timing); +} + +/* + * qd6500_tune_drive + */ + +static void qd6500_tune_drive (ide_drive_t *drive, byte pio) +{ + int active_time = 175; + int recovery_time = 415; /* worst case values from the dos driver */ + + if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time) + && drive->id->tPIO && (drive->id->field_valid & 0x02) + && drive->id->eide_pio >= 240) { + + printk(KERN_INFO "%s: PIO mode%d\n", drive->name, + drive->id->tPIO); + active_time = 110; + recovery_time = drive->id->eide_pio - 120; + } + + qd_set_timing(drive,qd6500_compute_timing(HWIF(drive),active_time,recovery_time)); +} + +/* + * qd6580_tune_drive + */ + +static void qd6580_tune_drive (ide_drive_t *drive, byte pio) +{ + ide_pio_data_t d; + int base = HWIF(drive)->select_data; + int active_time = 175; + int recovery_time = 415; /* worst case values from the dos driver */ + + if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time)) { + pio = ide_get_best_pio_mode(drive, pio, 255, &d); + pio = IDE_MIN(pio,4); + + switch (pio) { + case 0: break; + case 3: + if (d.cycle_time >= 110) { + active_time = 86; + recovery_time = d.cycle_time-102; + } else + printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); + break; + case 4: + if (d.cycle_time >= 69) { + active_time = 70; + recovery_time = d.cycle_time-61; + } else + printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); + break; + default: + if (d.cycle_time >= 180) { + active_time = 110; + recovery_time = d.cycle_time - 120; + } else { + active_time = ide_pio_timings[pio].active_time; + recovery_time = d.cycle_time + -active_time; + } + } + printk(KERN_INFO "%s: PIO mode%d\n",drive->name,pio); + } + + if (!HWIF(drive)->channel && drive->media != ide_disk) { + qd_write_reg(0x5f,QD_CONTROL_PORT); + printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n",drive->name,HWIF(drive)->name); + } + + qd_set_timing(drive,qd6580_compute_timing(active_time,recovery_time)); +} + +/* + * qd_testreg + * + * tests if the given port is a register + */ + +static int __init qd_testreg(int port) +{ + byte savereg; + byte readreg; + unsigned long flags; + + save_flags(flags); /* all CPUs */ + cli(); /* all CPUs */ + savereg = inb_p(port); + outb_p(QD_TESTVAL,port); /* safe value */ + readreg = inb_p(port); + outb(savereg,port); + restore_flags(flags); /* all CPUs */ + + if (savereg == QD_TESTVAL) { + printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); + printk(KERN_ERR "Please contact maintainers to tell about your hardware\n"); + printk(KERN_ERR "Assuming qd65xx is not present.\n"); + return 1; + } + + return (readreg != QD_TESTVAL); +} + +/* + * probe: + * + * looks at the specified baseport, and if qd found, registers & initialises it + * return 1 if another qd may be probed + */ + +int __init probe (int base) +{ + byte config; + byte index; + + config = qd_read_reg(QD_CONFIG_PORT); + + if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1; + + index = ! (config & QD_CONFIG_IDE_BASEPORT); + + if ((config & 0xf0) == QD_CONFIG_QD6500) { + ide_hwif_t *hwif = &ide_hwifs[index]; + + if (qd_testreg(base)) return 1; /* bad register */ + + /* qd6500 found */ + + printk(KERN_NOTICE "%s: qd6500 at %#x\n", + ide_hwifs[index].name, base); + + printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", + config, QD_ID3); + + if (config & QD_CONFIG_DISABLED) { + printk(KERN_WARNING "qd6500 is disabled !\n"); + return 1; + } + + hwif->chipset = ide_qd65xx; + hwif->select_data = base; + hwif->config_data = config; + hwif->drives[0].drive_data = + hwif->drives[1].drive_data = QD6500_DEF_DATA; + hwif->drives[0].io_32bit = + hwif->drives[1].io_32bit = 1; + hwif->tuneproc = &qd6500_tune_drive; + return 1; + } + + if (((config & 0xf0) == QD_CONFIG_QD6580_A) || ((config & 0xf0) == QD_CONFIG_QD6580_B)) { + + byte control; + + if (qd_testreg(base) || qd_testreg(base+0x02)) return 1; + /* bad registers */ + + /* qd6580 found */ + + control = qd_read_reg(QD_CONTROL_PORT); + + printk(KERN_NOTICE "qd6580 at %#x\n", base); + printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", + config, control, QD_ID3); + + if (control & QD_CONTR_SEC_DISABLED) { + ide_hwif_t *hwif = &ide_hwifs[index]; + + /* secondary disabled */ + printk(KERN_INFO "%s: qd6580: single IDE board\n", + ide_hwifs[index].name); + + hwif->chipset = ide_qd65xx; + hwif->select_data = base; + hwif->config_data = config | (control <<8); + hwif->drives[0].drive_data = + hwif->drives[1].drive_data = QD6580_DEF_DATA; + hwif->drives[0].io_32bit = + hwif->drives[1].io_32bit = 1; + hwif->tuneproc = &qd6580_tune_drive; + + qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + + return 1; + } else { + int i,j; + /* secondary enabled */ + printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", + ide_hwifs[0].name,ide_hwifs[1].name); + + for (i=0;i<2;i++) { + + ide_hwifs[i].chipset = ide_qd65xx; + ide_hwifs[i].mate = &ide_hwifs[i^1]; + ide_hwifs[i].channel = i; + + ide_hwifs[i].select_data = base; + ide_hwifs[i].config_data = config | (control <<8); + ide_hwifs[i].tuneproc = &qd6580_tune_drive; + + for (j=0;j<2;j++) { + ide_hwifs[i].drives[j].drive_data = QD6580_DEF_DATA; + ide_hwifs[i].drives[j].io_32bit = 1; + } + } + + qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + + return 0; /* no other qd65xx possible */ + } + } + /* no qd65xx found */ + return 1; +} + +/* + * init_qd65xx: + * + * called at the very beginning of initialization ; should just probe and link + */ + +void __init init_qd65xx (void) +{ + if (probe(0x30)) probe(0xb0); +} diff -u --recursive --new-file v2.4.9/linux/drivers/ide/qd65xx.h linux/drivers/ide/qd65xx.h --- v2.4.9/linux/drivers/ide/qd65xx.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/ide/qd65xx.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,139 @@ +/* + * linux/drivers/ide/qd65xx.h + * + * Copyright (c) 2000 Linus Torvalds & authors + */ + +/* + * Authors: Petr Soucek + * Samuel Thibault + */ + +/* truncates a in [b,c] */ +#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) + +#define IDE_IMPLY(a,b) ((!(a)) || (b)) + +#define QD_TIM1_PORT (base) +#define QD_CONFIG_PORT (base+0x01) +#define QD_TIM2_PORT (base+0x02) +#define QD_CONTROL_PORT (base+0x03) + +#define QD_CONFIG_IDE_BASEPORT 0x01 +#define QD_CONFIG_BASEPORT 0x02 +#define QD_CONFIG_ID3 0x04 +#define QD_CONFIG_DISABLED 0x08 +#define QD_CONFIG_QD6500 0xc0 +#define QD_CONFIG_QD6580_A 0xa0 +#define QD_CONFIG_QD6580_B 0x50 + +#define QD_CONTR_SEC_DISABLED 0x01 + +#define QD_ID3 (config & QD_CONFIG_ID3) + +#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff) +#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8) + +#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff) +#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8) + +#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08)) +#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) +#define QD_DEF_CONTR (0x40 | ((control & 0x02) ? 0x9f : 0x1f)) + +#define QD_TESTVAL 0x19 /* safe value */ + +/* Drive specific timing taken from DOS driver v3.7 */ + +struct qd65xx_timing_s { + char offset; /* ofset from the beginning of Model Number" */ + char model[4]; /* 4 chars from Model number, no conversion */ + short active; /* active time */ + short recovery; /* recovery time */ +} qd65xx_timing [] = { + { 30, "2040", 110, 225 }, /* Conner CP30204 */ + { 30, "2045", 135, 225 }, /* Conner CP30254 */ + { 30, "1040", 155, 325 }, /* Conner CP30104 */ + { 30, "1047", 135, 265 }, /* Conner CP30174 */ + { 30, "5344", 135, 225 }, /* Conner CP3544 */ + { 30, "01 4", 175, 405 }, /* Conner CP-3104 */ + { 27, "C030", 175, 375 }, /* Conner CP3000 */ + { 8, "PL42", 110, 295 }, /* Quantum LP240 */ + { 8, "PL21", 110, 315 }, /* Quantum LP120 */ + { 8, "PL25", 175, 385 }, /* Quantum LP52 */ + { 4, "PA24", 110, 285 }, /* WD Piranha SP4200 */ + { 6, "2200", 110, 260 }, /* WD Caviar AC2200 */ + { 6, "3204", 110, 235 }, /* WD Caviar AC2340 */ + { 6, "1202", 110, 265 }, /* WD Caviar AC2120 */ + { 0, "DS3-", 135, 315 }, /* Teac SD340 */ + { 8, "KM32", 175, 355 }, /* Toshiba MK234 */ + { 2, "53A1", 175, 355 }, /* Seagate ST351A */ + { 2, "4108", 175, 295 }, /* Seagate ST1480A */ + { 2, "1344", 175, 335 }, /* Seagate ST3144A */ + { 6, "7 12", 110, 225 }, /* Maxtor 7213A */ + { 30, "02F4", 145, 295 }, /* Conner 3204F */ + { 2, "1302", 175, 335 }, /* Seagate ST3120A */ + { 2, "2334", 145, 265 }, /* Seagate ST3243A */ + { 2, "2338", 145, 275 }, /* Seagate ST3283A */ + { 2, "3309", 145, 275 }, /* Seagate ST3390A */ + { 2, "5305", 145, 275 }, /* Seagate ST3550A */ + { 2, "4100", 175, 295 }, /* Seagate ST1400A */ + { 2, "4110", 175, 295 }, /* Seagate ST1401A */ + { 2, "6300", 135, 265 }, /* Seagate ST3600A */ + { 2, "5300", 135, 265 }, /* Seagate ST3500A */ + { 6, "7 31", 135, 225 }, /* Maxtor 7131 AT */ + { 6, "7 43", 115, 265 }, /* Maxtor 7345 AT */ + { 6, "7 42", 110, 255 }, /* Maxtor 7245 AT */ + { 6, "3 04", 135, 265 }, /* Maxtor 340 AT */ + { 6, "61 0", 135, 285 }, /* WD AC160 */ + { 6, "1107", 135, 235 }, /* WD AC1170 */ + { 6, "2101", 110, 220 }, /* WD AC1210 */ + { 6, "4202", 135, 245 }, /* WD AC2420 */ + { 6, "41 0", 175, 355 }, /* WD Caviar 140 */ + { 6, "82 0", 175, 355 }, /* WD Caviar 280 */ + { 8, "PL01", 175, 375 }, /* Quantum LP105 */ + { 8, "PL25", 110, 295 }, /* Quantum LP525 */ + { 10, "4S 2", 175, 385 }, /* Quantum ELS42 */ + { 10, "8S 5", 175, 385 }, /* Quantum ELS85 */ + { 10, "1S72", 175, 385 }, /* Quantum ELS127 */ + { 10, "1S07", 175, 385 }, /* Quantum ELS170 */ + { 8, "ZE42", 135, 295 }, /* Quantum EZ240 */ + { 8, "ZE21", 175, 385 }, /* Quantum EZ127 */ + { 8, "ZE58", 175, 385 }, /* Quantum EZ85 */ + { 8, "ZE24", 175, 385 }, /* Quantum EZ42 */ + { 27, "C036", 155, 325 }, /* Conner CP30064 */ + { 27, "C038", 155, 325 }, /* Conner CP30084 */ + { 6, "2205", 110, 255 }, /* WDC AC2250 */ + { 2, " CHA", 140, 415 }, /* WDC AH series; WDC AH260, WDC */ + { 2, " CLA", 140, 415 }, /* WDC AL series: WDC AL2120, 2170, */ + { 4, "UC41", 140, 415 }, /* WDC CU140 */ + { 6, "1207", 130, 275 }, /* WDC AC2170 */ + { 6, "2107", 130, 275 }, /* WDC AC1270 */ + { 6, "5204", 130, 275 }, /* WDC AC2540 */ + { 30, "3004", 110, 235 }, /* Conner CP30340 */ + { 30, "0345", 135, 255 }, /* Conner CP30544 */ + { 12, "12A3", 175, 320 }, /* MAXTOR LXT-213A */ + { 12, "43A0", 145, 240 }, /* MAXTOR LXT-340A */ + { 6, "7 21", 180, 290 }, /* Maxtor 7120 AT */ + { 6, "7 71", 135, 240 }, /* Maxtor 7170 AT */ + { 12, "45\0000", 110, 205 }, /* MAXTOR MXT-540 */ + { 8, "PL11", 180, 290 }, /* QUANTUM LP110A */ + { 8, "OG21", 150, 275 }, /* QUANTUM GO120 */ + { 12, "42A5", 175, 320 }, /* MAXTOR LXT-245A */ + { 2, "2309", 175, 295 }, /* ST3290A */ + { 2, "3358", 180, 310 }, /* ST3385A */ + { 2, "6355", 180, 310 }, /* ST3655A */ + { 2, "1900", 175, 270 }, /* ST9100A */ + { 2, "1954", 175, 270 }, /* ST9145A */ + { 2, "1909", 175, 270 }, /* ST9190AG */ + { 2, "2953", 175, 270 }, /* ST9235A */ + { 2, "1359", 175, 270 }, /* ST3195A */ + { 24, "3R11", 175, 290 }, /* ALPS ELECTRIC Co.,LTD, DR311C */ + { 0, "2M26", 175, 215 }, /* M262XT-0Ah */ + { 4, "2253", 175, 300 }, /* HP C2235A */ + { 4, "-32A", 145, 245 }, /* H3133-A2 */ + { 30, "0326", 150, 270 }, /* Samsung Electronics 120MB */ + { 30, "3044", 110, 195 }, /* Conner CFA340A */ + { 30, "43A0", 110, 195 }, /* Conner CFA340A */ + { -1, " ", 175, 415 } /* unknown disk name */ +}; diff -u --recursive --new-file v2.4.9/linux/drivers/ide/sis5513.c linux/drivers/ide/sis5513.c --- v2.4.9/linux/drivers/ide/sis5513.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/ide/sis5513.c Fri Sep 7 09:28:38 2001 @@ -96,7 +96,7 @@ { 4, "Mode 2" }, { 3, "Mode 3" }, { 2, "Mode 4" }, - { 0, "Undefined" } + { 0, "Mode 5" } }; static __inline__ char * find_udma_mode (byte cycle_time) @@ -135,7 +135,7 @@ }; static char * cycle_time [] = { - "Undefined", "2 CLCK", + "2 CLK", "2 CLK", "3 CLK", "4 CLK", "5 CLK", "6 CLK", "7 CLK", "8 CLK" @@ -495,7 +495,7 @@ printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); #endif /* SIS5513_DEBUG_DRIVE_INFO */ - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : @@ -515,7 +515,7 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x003F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive, 1); if ((id->field_valid & 2) && diff -u --recursive --new-file v2.4.9/linux/drivers/ide/sl82c105.c linux/drivers/ide/sl82c105.c --- v2.4.9/linux/drivers/ide/sl82c105.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/ide/sl82c105.c Fri Sep 7 10:45:30 2001 @@ -28,7 +28,6 @@ extern char *ide_xfer_verbose (byte xfer_rate); -#ifdef CONFIG_ARCH_NETWINDER /* * Convert a PIO mode and cycle time to the required on/off * times for the interface. This has protection against run-away @@ -272,37 +271,4 @@ { hwif->tuneproc = tune_sl82c105; } - -#else - -unsigned int pci_init_sl82c105(struct pci_dev *dev, const char *msg) -{ - return ide_special_settings(dev, msg); -} - -void dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) -{ - ide_setup_dma(hwif, dma_base, 8); -} - -void __init ide_init_sl82c105(ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - unsigned short t16; - unsigned int t32; - pci_read_config_word(dev, PCI_COMMAND, &t16); - printk("SL82C105 command word: %x\n",t16); - t16 |= PCI_COMMAND_IO; - pci_write_config_word(dev, PCI_COMMAND, t16); - /* IDE timing */ - pci_read_config_dword(dev, 0x44, &t32); - printk("IDE timing: %08x, resetting to PIO0 timing\n",t32); - pci_write_config_dword(dev, 0x44, 0x03e4); -#ifndef CONFIG_MBX - pci_read_config_dword(dev, 0x40, &t32); - printk("IDE control/status register: %08x\n",t32); - pci_write_config_dword(dev, 0x40, 0x10ff08a1); -#endif /* CONFIG_MBX */ -} -#endif diff -u --recursive --new-file v2.4.9/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c --- v2.4.9/linux/drivers/ide/via82cxxx.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/via82cxxx.c Fri Sep 7 09:28:38 2001 @@ -1,5 +1,5 @@ /* - * $Id: via82cxxx.c,v 3.23 2001/03/09 09:30:00 vojtech Exp $ + * $Id: via82cxxx.c,v 3.28 2001/09/01 21:10:00 vojtech Exp $ * * Copyright (c) 2000-2001 Vojtech Pavlik * @@ -14,17 +14,20 @@ /* * VIA IDE driver for Linux. Supports * - * vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, + * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233 * * southbridges, which can be found in * - * VIA Apollo VP, VPX, VPX/97, VP2, VP2/97, VP3, MVP3, MVP4, P6, Pro, - * Pro Plus, Pro 133, Pro 133A, ProMedia PM601, ProSavage PM133, PLE133, - * Pro 266, KX133, KT133, ProSavage KM133, KT133A, KT266 - * PC-Chips VXPro, VXPro+, TXPro-III, TXPro-AGP, ViaGra, BXToo, BXTel - * AMD 640, 640 AGP, 750 IronGate - * ETEQ 6618, 6628, 6638 + * VIA Apollo Master, VP, VP2, VP2/97, VP3, VPX, VPX/97, MVP3, MVP4, P6, Pro, + * ProII, ProPlus, Pro133, Pro133+, Pro133A, Pro133A Dual, Pro133T, Pro133Z, + * PLE133, PLE133T, Pro266, Pro266T, ProP4X266, PM601, PM133, PN133, PL133T, + * PX266, PM266, KX133, KT133, KT133A, KLE133, KT266, KX266, KM133, KM133A, + * KL133, KN133, KM266 + * PC-Chips VXPro, VXPro+, VXTwo, TXPro-III, TXPro-AGP, AGPPro, ViaGra, BXToo, + * BXTel, BXpert + * AMD 640, 640 AGP, 750 IronGate, 760, 760MP + * ETEQ 6618, 6628, 6629, 6638 * Micron Samurai * * chipsets. Supports @@ -88,7 +91,6 @@ #define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */ #define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */ #define VIA_SET_THRESH 0x080 /* Needs to have FIFO thresholds set */ -#define VIA_BAD_PIO 0x100 /* Always uses 26 PCICLK/xfer regardles of PIO mode */ /* * VIA SouthBridge chips. @@ -101,19 +103,24 @@ unsigned char rev_max; unsigned short flags; } via_isa_bridges[] = { -#ifdef VIA_NEW_BRIDGES_TESTED - { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_66 }, +#ifdef FUTURE_BRIDGES + { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_100 }, + { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_100 }, + { "vt8233c", PCI_DEVICE_ID_VIA_8233C, 0x30, 0x4f, VIA_UDMA_100 }, #endif - { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 | VIA_BAD_PIO }, + { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, + { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, + { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 }, { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO }, { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO }, { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO }, + { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO }, { NULL } }; @@ -154,7 +161,7 @@ via_print("----------VIA BusMastering IDE Configuration----------------"); - via_print("Driver Version: 3.23"); + via_print("Driver Version: 3.27"); via_print("South Bridge: VIA %s", via_config->name); pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t); @@ -220,8 +227,8 @@ switch (via_config->flags & VIA_UDMA) { case VIA_UDMA_100: - speed[i] = 2000 / udma[i]; - cycle[i] = 10 * udma[i]; + speed[i] = 60 * via_clock / udma[i]; + cycle[i] = 333 / via_clock * udma[i]; break; case VIA_UDMA_66: @@ -301,7 +308,7 @@ switch (via_config->flags & VIA_UDMA) { case VIA_UDMA_33: UT = T; break; case VIA_UDMA_66: UT = T/2; break; - case VIA_UDMA_100: UT = 10; break; + case VIA_UDMA_100: UT = T/3; break; default: UT = T; break; } diff -u --recursive --new-file v2.4.9/linux/drivers/ieee1394/highlevel.c linux/drivers/ieee1394/highlevel.c --- v2.4.9/linux/drivers/ieee1394/highlevel.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/ieee1394/highlevel.c Fri Sep 7 09:28:38 2001 @@ -157,15 +157,16 @@ #define DEFINE_MULTIPLEXER(Function) \ void highlevel_##Function(struct hpsb_host *host) \ { \ - struct list_head *entry; \ + struct list_head *entry,*next; \ void (*funcptr)(struct hpsb_host*); \ read_lock(&hl_drivers_lock); \ entry = hl_drivers.next; \ while (entry != &hl_drivers) { \ + next = entry->next; \ funcptr = list_entry(entry, struct hpsb_highlevel, hl_list) \ ->op->Function; \ if (funcptr) funcptr(host); \ - entry = entry->next; \ + entry = next; \ } \ read_unlock(&hl_drivers_lock); \ } diff -u --recursive --new-file v2.4.9/linux/drivers/ieee1394/ieee1394_core.c linux/drivers/ieee1394/ieee1394_core.c --- v2.4.9/linux/drivers/ieee1394/ieee1394_core.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ieee1394/ieee1394_core.c Fri Sep 7 09:28:38 2001 @@ -352,7 +352,7 @@ } if (ackcode != ACK_PENDING || !packet->expect_response) { - packet->state = complete; + packet->state = completed; up(&packet->state_change); up(&packet->state_change); run_task_queue(&packet->complete_tq); @@ -503,7 +503,7 @@ break; } - packet->state = complete; + packet->state = completed; up(&packet->state_change); run_task_queue(&packet->complete_tq); } @@ -720,7 +720,7 @@ list_for_each(lh, &llist) { packet = list_entry(lh, struct hpsb_packet, list); - packet->state = complete; + packet->state = completed; packet->ack_code = ACKX_ABORTED; up(&packet->state_change); run_task_queue(&packet->complete_tq); @@ -761,7 +761,7 @@ list_for_each(lh, &expiredlist) { packet = list_entry(lh, struct hpsb_packet, list); - packet->state = complete; + packet->state = completed; packet->ack_code = ACKX_TIMEOUT; up(&packet->state_change); run_task_queue(&packet->complete_tq); diff -u --recursive --new-file v2.4.9/linux/drivers/ieee1394/ieee1394_core.h linux/drivers/ieee1394/ieee1394_core.h --- v2.4.9/linux/drivers/ieee1394/ieee1394_core.h Mon Aug 27 12:41:41 2001 +++ linux/drivers/ieee1394/ieee1394_core.h Fri Sep 7 09:28:38 2001 @@ -25,11 +25,11 @@ /* Okay, this is core internal and a no care for hosts. * queued = queued for sending * pending = sent, waiting for response - * complete = processing completed, successful or not + * completed = processing completed, successful or not * incoming = incoming packet */ enum { - unused, queued, pending, complete, incoming + unused, queued, pending, completed, incoming } __attribute__((packed)) state; /* These are core internal. */ diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/isar.c linux/drivers/isdn/hisax/isar.c --- v2.4.9/linux/drivers/isdn/hisax/isar.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/isdn/hisax/isar.c Fri Sep 7 09:28:38 2001 @@ -1,4 +1,4 @@ -/* $Id: isar.c,v 1.17.6.3 2001/06/09 15:14:17 kai Exp $ +/* $Id: isar.c,v 1.17.6.4 2001/08/17 12:34:26 kai Exp $ * * isar.c ISAR (Siemens PSB 7110) specific routines * @@ -18,8 +18,6 @@ #define DBG_LOADFIRM 0 #define DUMP_MBOXFRAME 2 -#define MIN(a,b) ((a0) { - noc = MIN(126, left); + noc = left; + if (noc > 126) + noc = 126; nom = 2*noc; mp = msg; *mp++ = sadr / 256; diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c --- v2.4.9/linux/drivers/isdn/icn/icn.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/isdn/icn/icn.c Fri Sep 7 09:28:38 2001 @@ -1,4 +1,4 @@ -/* $Id: icn.c,v 1.65.6.6 2001/07/13 09:20:12 kai Exp $ +/* $Id: icn.c,v 1.65.6.7 2001/08/17 12:34:27 kai Exp $ * ISDN low-level module for the ICN active ISDN-Card. * @@ -34,7 +34,7 @@ #undef MAP_DEBUG static char -*revision = "$Revision: 1.65.6.6 $"; +*revision = "$Revision: 1.65.6.7 $"; static int icn_addcard(int, char *, char *); @@ -930,7 +930,9 @@ restore_flags(flags); while (left) { if (sbfree) { /* If there is a free buffer... */ - cnt = MIN(256, left); + cnt = left; + if (cnt > 256) + cnt = 256; if (copy_from_user(codebuf, p, cnt)) { icn_maprelease_channel(card, 0); return -EFAULT; @@ -1029,7 +1031,6 @@ icn_writecmd(const u_char * buf, int len, int user, icn_card * card) { int mch = card->secondhalf ? 2 : 0; - int avail; int pp; int i; int count; @@ -1046,8 +1047,9 @@ ocount = 1; xcount = loop = 0; while (len) { - avail = cmd_free; - count = MIN(avail, len); + count = cmd_free; + if (count > len) + count = len; if (user) copy_from_user(msg, buf, count); else diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h --- v2.4.9/linux/drivers/isdn/icn/icn.h Thu Apr 19 22:30:23 2001 +++ linux/drivers/isdn/icn/icn.h Fri Sep 7 09:28:38 2001 @@ -1,4 +1,4 @@ -/* $Id: icn.h,v 1.30.6.3 2001/04/20 02:42:01 keil Exp $ +/* $Id: icn.h,v 1.30.6.4 2001/08/17 12:34:27 kai Exp $ * ISDN lowlevel-module for the ICN active ISDN-Card. * @@ -284,9 +284,6 @@ readb(&msg_i)-readb(&msg_o)) #define CID (card->interface.id) - -#define MIN(a,b) ((ab)?a:b) #endif /* defined(__KERNEL__) || defined(__DEBUGVAR__) */ #endif /* icn_h */ diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/isdn_audio.c linux/drivers/isdn/isdn_audio.c --- v2.4.9/linux/drivers/isdn/isdn_audio.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/isdn_audio.c Fri Sep 7 09:28:38 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_audio.c,v 1.21 2000/06/20 18:01:55 keil Exp $ +/* $Id: isdn_audio.c,v 1.21.6.1 2001/08/17 12:34:25 kai Exp $ * Linux ISDN subsystem, audio conversion and compression (linklevel). * @@ -28,7 +28,7 @@ #include "isdn_audio.h" #include "isdn_common.h" -char *isdn_audio_revision = "$Revision: 1.21 $"; +char *isdn_audio_revision = "$Revision: 1.21.6.1 $"; /* * Misc. lookup-tables. @@ -607,7 +607,9 @@ int c; while (len) { - c = MIN(len, (DTMF_NPOINTS - s->idx)); + c = DTMF_NPOINTS - s->idx; + if (c > len) + c = len; if (c <= 0) break; for (i = 0; i < c; i++) { diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/pcbit/layer2.c linux/drivers/isdn/pcbit/layer2.c --- v2.4.9/linux/drivers/isdn/pcbit/layer2.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/pcbit/layer2.c Fri Sep 7 09:28:38 2001 @@ -176,7 +176,6 @@ struct frame_buf *frame = NULL; unsigned char unacked; int flen; /* fragment frame length including all headers */ - int totlen; /* non-fragmented frame length */ int free; int count, cp_len; @@ -213,11 +212,12 @@ ulong msg; if (frame->skb) - totlen = FRAME_HDR_LEN + PREHDR_LEN + frame->skb->len; + flen = FRAME_HDR_LEN + PREHDR_LEN + frame->skb->len; else - totlen = FRAME_HDR_LEN + PREHDR_LEN; + flen = FRAME_HDR_LEN + PREHDR_LEN; - flen = MIN(totlen, free); + if (flen > free) + flen = free; msg = frame->msg; @@ -259,9 +259,10 @@ } else { /* Type 1 frame */ - totlen = 2 + (frame->skb->len - frame->copied); + flen = 2 + (frame->skb->len - frame->copied); - flen = MIN(totlen, free); + if (flen > free) + flen = free; /* TT */ tt = ((ushort) (flen - 2)) | 0x8000U; /* Type 1 */ @@ -271,8 +272,9 @@ } if (frame->skb) { - cp_len = MIN(frame->skb->len - frame->copied, - flen - count); + cp_len = frame->skb->len - frame->copied; + if (cp_len > flen - count) + cp_len = flen - count; memcpy_topcbit(dev, frame->skb->data + frame->copied, cp_len); diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/pcbit/layer2.h linux/drivers/isdn/pcbit/layer2.h --- v2.4.9/linux/drivers/isdn/pcbit/layer2.h Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/pcbit/layer2.h Fri Sep 7 09:28:38 2001 @@ -121,8 +121,6 @@ struct frame_buf * next; }; -#define MIN(a,b) ((a -#include +#include #include #include #include @@ -185,9 +185,9 @@ dev_t device, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = + static const char badmagic[] = KERN_WARNING "Warning: bad magic number for serial struct (%d, %d) in %s\n"; - static const char *badinfo = + static const char badinfo[] = KERN_WARNING "Warning: null mac_serial for (%d, %d) in %s\n"; if (!info) { @@ -418,7 +418,8 @@ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { static int flip_buf_ovf; if (++flip_buf_ovf <= 1) - printk("FB. overflow: %d\n", flip_buf_ovf); + printk(KERN_WARNING "FB. overflow: %d\n", + flip_buf_ovf); break; } tty->flip.count++; @@ -513,7 +514,7 @@ if ((status & CTS) == 0) { if (info->tx_stopped) { #ifdef SERIAL_DEBUG_FLOW - printk("CTS up\n"); + printk(KERN_DEBUG "CTS up\n"); #endif info->tx_stopped = 0; if (!info->tx_active) @@ -521,7 +522,7 @@ } } else { #ifdef SERIAL_DEBUG_FLOW - printk("CTS down\n"); + printk(KERN_DEBUG "CTS down\n"); #endif info->tx_stopped = 1; } @@ -568,7 +569,8 @@ int shift; if (!(info->flags & ZILOG_INITIALIZED)) { - printk("rs_interrupt: irq %d, port not initialized\n", irq); + printk(KERN_WARNING "rs_interrupt: irq %d, port not " + "initialized\n", irq); disable_irq(irq); return; } @@ -589,7 +591,7 @@ for (;;) { zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; #ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt: irq %d, zs_intreg 0x%x\n", + printk(KERN_DEBUG "rs_interrupt: irq %d, zs_intreg 0x%x\n", irq, (int)zs_intreg); #endif @@ -662,7 +664,7 @@ struct mac_serial *info = (struct mac_serial *)tty->driver_data; #ifdef SERIAL_DEBUG_STOP - printk("rs_stop %ld....\n", + printk(KERN_DEBUG "rs_stop %ld....\n", tty->ldisc.chars_in_buffer(tty)); #endif @@ -686,7 +688,7 @@ unsigned long flags; #ifdef SERIAL_DEBUG_STOP - printk("rs_start %ld....\n", + printk(KERN_DEBUG "rs_start %ld....\n", tty->ldisc.chars_in_buffer(tty)); #endif @@ -1214,13 +1216,8 @@ else feature_set(info->dev_node, FEATURE_Serial_IO_B); delay = 10; - if (info->is_cobalt_modem){ - mdelay(300); - feature_set(info->dev_node, FEATURE_Modem_power); - mdelay(5); - feature_clear(info->dev_node, FEATURE_Modem_power); - mdelay(10); - feature_set(info->dev_node, FEATURE_Modem_power); + if (info->is_cobalt_modem) { + feature_set_modem_power(info->dev_node, 1); delay = 2500; /* wait for 2.5s before using */ } #ifdef CONFIG_PMAC_PBOOK @@ -1228,11 +1225,13 @@ pmu_enable_irled(1); #endif /* CONFIG_PMAC_PBOOK */ } else { + /* TODO: Make that depend on a timer, don't power down + * immediately + */ PWRDBG("ttyS%02d: shutting down hardware\n", info->line); if (info->is_cobalt_modem) { PWRDBG("ttyS%02d: shutting down modem\n", info->line); - feature_clear(info->dev_node, FEATURE_Modem_power); - mdelay(10); + feature_set_modem_power(info->dev_node, 0); } #ifdef CONFIG_PMAC_PBOOK if (info->is_irda) @@ -1648,7 +1647,7 @@ struct mac_serial *info = (struct mac_serial *)tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %ld....\n",tty->ldisc.chars_in_buffer(tty)); + printk(KERN_DEBUG "throttle %ld....\n",tty->ldisc.chars_in_buffer(tty)); #endif if (serial_paranoia_check(info, tty->device, "rs_throttle")) @@ -1701,7 +1700,8 @@ struct mac_serial *info = (struct mac_serial *)tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s: %d....\n",tty->ldisc.chars_in_buffer(tty)); + printk(KERN_DEBUG "unthrottle %s: %d....\n", + tty->ldisc.chars_in_buffer(tty)); #endif if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) @@ -1855,13 +1855,11 @@ static int set_modem_info(struct mac_serial *info, unsigned int cmd, unsigned int *value) { - int error; unsigned int arg, bits; unsigned long flags; - error = get_user(arg, value); - if (error) - return error; + if (get_user(arg, value)) + return -EFAULT; bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); save_flags(flags); cli(); switch (cmd) { @@ -2000,13 +1998,13 @@ * one, we've got real problems, since it means the * serial port won't be shutdown. */ - printk("rs_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); + printk(KERN_ERR "rs_close: bad serial port count; tty->count " + "is 1, info->count is %d\n", info->count); info->count = 1; } if (--info->count < 0) { - printk("rs_close: bad serial port count for ttys%d: %d\n", - info->line, info->count); + printk(KERN_ERR "rs_close: bad serial port count for " + "ttys%d: %d\n", info->line, info->count); info->count = 0; } if (info->count) { @@ -2104,14 +2102,16 @@ * interval should also be less than the timeout. */ if (info->timeout <= HZ/50) { - printk("macserial: invalid info->timeout=%d\n", info->timeout); + printk(KERN_INFO "macserial: invalid info->timeout=%d\n", + info->timeout); info->timeout = HZ/50+1; } char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; char_time = char_time / 5; if (char_time > HZ) { - printk("macserial: char_time %ld >HZ !!!\n", char_time); + printk(KERN_WARNING "macserial: char_time %ld >HZ !!!\n", + char_time); char_time = 1; } else if (char_time == 0) char_time = 1; @@ -2374,7 +2374,7 @@ static void show_serial_version(void) { - printk("PowerMac Z8530 serial driver version 2.0\n"); + printk(KERN_INFO "PowerMac Z8530 serial driver version 2.0\n"); } /* @@ -2461,8 +2461,8 @@ nchan = 0; chip = n; if (n >= NUM_CHANNELS) { - printk("Sorry, can't use %s: no more channels\n", - dev->full_name); + printk(KERN_WARNING "Sorry, can't use %s: no more " + "channels\n", dev->full_name); continue; } chan_a_index = 0; @@ -2631,7 +2631,8 @@ /* If console serial line, then enable interrupts. */ if (zs_soft[channel].is_cons) { - printk("macserial: console line, enabling interrupt %d\n", zs_soft[channel].irq); + printk(KERN_INFO "macserial: console line, enabling " + "interrupt %d\n", zs_soft[channel].irq); panic("macserial: console not supported yet !"); write_zsreg(zs_soft[channel].zs_channel, R1, (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); @@ -2669,7 +2670,7 @@ init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); info->timeout = HZ; - printk("tty%02d at 0x%08x (irq = %d)", info->line, + printk(KERN_INFO "tty%02d at 0x%08x (irq = %d)", info->line, info->port, info->irq); printk(" is a Z8530 ESCC"); connector = get_property(info->dev_node, "AAPL,connector", &lenp); diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/mediabay.c linux/drivers/macintosh/mediabay.c --- v2.4.9/linux/drivers/macintosh/mediabay.c Sun Sep 17 09:48:05 2000 +++ linux/drivers/macintosh/mediabay.c Sat Sep 8 12:38:42 2001 @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c --- v2.4.9/linux/drivers/macintosh/nvram.c Sun Sep 17 09:48:05 2000 +++ linux/drivers/macintosh/nvram.c Fri Sep 7 09:28:38 2001 @@ -18,7 +18,7 @@ #define NVRAM_SIZE 8192 -static long long nvram_llseek(struct file *file, loff_t offset, int origin) +static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) { switch (origin) { case 1: diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/rtc.c linux/drivers/macintosh/rtc.c --- v2.4.9/linux/drivers/macintosh/rtc.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/macintosh/rtc.c Sat Sep 8 12:38:42 2001 @@ -49,11 +49,7 @@ { unsigned long nowtime; - printk(KERN_INFO "rtc.c:set_rtc_time: %04d-%02d-%02d %02d:%02d:%02d.\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - nowtime = mktime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - - printk(KERN_INFO "rtc.c:set_rtc_time: set rtc time to %ld seconds.\n", nowtime); (ppc_md.set_rtc_time)(nowtime); } diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c --- v2.4.9/linux/drivers/macintosh/via-pmu.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/macintosh/via-pmu.c Sat Sep 8 12:38:42 2001 @@ -32,24 +32,30 @@ #include #include #include +#include #include +#include +#include +#include #include #include #include #include #include -#include +#include #include #include #include #include #include +#include #ifdef CONFIG_PMAC_BACKLIGHT #include #endif /* Some compile options */ #undef SUSPEND_USES_PMU +#define DEBUG_SLEEP /* Misc minor number allocated for /dev/pmu */ #define PMU_MINOR 154 @@ -102,13 +108,11 @@ static struct adb_request *current_req; static struct adb_request *last_req; static struct adb_request *req_awaiting_reply; -static unsigned char interrupt_data[256]; /* Made bigger: I've been told that might happen */ +static unsigned char interrupt_data[32]; static unsigned char *reply_ptr; static int data_index; static int data_len; static volatile int adb_int_pending; -static int pmu_adb_flags; -static int adb_dev_map = 0; static struct adb_request bright_req_1, bright_req_2, bright_req_3; static struct device_node *vias; static int pmu_kind = PMU_UNKNOWN; @@ -118,11 +122,20 @@ static int gpio_irq = -1; static volatile int pmu_suspended = 0; static spinlock_t pmu_lock; +static u8 pmu_intr_mask; +static int pmu_version; +static int drop_interrupts; +#ifdef CONFIG_PMAC_PBOOK +static int sleep_in_progress; +#endif /* CONFIG_PMAC_PBOOK */ int asleep; struct notifier_block *sleep_notifier_list; #ifdef CONFIG_ADB +static int adb_dev_map = 0; +static int pmu_adb_flags; + static int pmu_probe(void); static int pmu_init(void); static int pmu_send_request(struct adb_request *req, int sync); @@ -163,8 +176,25 @@ #endif /* CONFIG_ADB */ extern void low_sleep_handler(void); -extern void sleep_save_intrs(int); -extern void sleep_restore_intrs(void); +extern void pmac_sleep_save_intrs(int); +extern void pmac_sleep_restore_intrs(void); +extern void openpic_sleep_save_intrs(void); +extern void openpic_sleep_restore_intrs(void); +extern void enable_kernel_altivec(void); +extern void enable_kernel_fp(void); + +#ifdef DEBUG_SLEEP +int pmu_polled_request(struct adb_request *req); +int pmu_wink(struct adb_request *req); +#endif + +#if defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM) +static int generic_notify_sleep(struct pmu_sleep_notifier *self, int when); +static struct pmu_sleep_notifier generic_sleep_notifier = { + generic_notify_sleep, + SLEEP_LEVEL_MISC, +}; +#endif /* defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM) */ /* * This table indicates for each PMU opcode: @@ -246,6 +276,11 @@ pmu_has_adb = 1; + pmu_intr_mask = PMU_INT_PCEJECT | + PMU_INT_SNDBRT | + PMU_INT_ADB | + PMU_INT_TICK; + if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0) || device_is_compatible(vias->parent, "ohare"))) pmu_kind = PMU_OHARE_BASED; @@ -258,7 +293,12 @@ pmu_kind = PMU_KEYLARGO_BASED; pmu_has_adb = (find_type_devices("adb") != NULL); - + pmu_intr_mask = PMU_INT_PCEJECT | + PMU_INT_SNDBRT | + PMU_INT_ADB | + PMU_INT_TICK | + PMU_INT_ENVIRONMENT; + gpiop = find_devices("gpio"); if (gpiop && gpiop->n_addrs) { gpio_reg = ioremap(gpiop->addrs->address, 0x10); @@ -281,11 +321,16 @@ return 0; } - printk(KERN_INFO "PMU driver initialized for %s\n", - pbook_type[pmu_kind]); + printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n", + PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version); sys_ctrler = SYS_CTRLER_PMU; +#if defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM) + pmu_register_sleep_notifier(&generic_sleep_notifier); + pm_active = 1; +#endif + return 1; } @@ -367,7 +412,7 @@ out_8(&via[B], via[B] | TREQ); /* negate TREQ */ out_8(&via[DIRB], (via[DIRB] | TREQ) & ~TACK); /* TACK in, TREQ out */ - pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc); + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); timeout = 100000; while (!req.complete) { if (--timeout < 0) { @@ -392,13 +437,20 @@ udelay(10); } - /* Tell PMU we are ready. Which PMU support this ? */ + /* Tell PMU we are ready. */ if (pmu_kind == PMU_KEYLARGO_BASED) { pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2); while (!req.complete) pmu_poll(); } - + + /* Read PMU version */ + pmu_request(&req, NULL, 1, PMU_GET_VERSION); + while (!req.complete) + pmu_poll(); + if (req.reply_len > 1) + pmu_version = req.reply[1]; + return 1; } @@ -529,7 +581,7 @@ req.done = NULL; req.data[0] = PMU_ADB_CMD; req.data[1] = 0; - req.data[2] = ADB_BUSRESET; /* 3 ??? */ + req.data[2] = ADB_BUSRESET; req.data[3] = 0; req.data[4] = 0; req.reply_len = 0; @@ -759,7 +811,7 @@ } adb_int_pending = 1; #ifdef SUSPEND_USES_PMU - pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc); + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); spin_unlock_irqrestore(&pmu_lock, flags); while(!req.complete) pmu_poll(); @@ -789,16 +841,11 @@ "intr=%x pmu_state=%d\n", intr, pmu_state); break; } + out_8(&via[IFR], intr); if (intr & SR_INT) pmu_sr_intr(regs); - else if (intr & CB1_INT) { + else if (intr & CB1_INT) adb_int_pending = 1; - out_8(&via[IFR], CB1_INT); - } - intr &= ~(SR_INT | CB1_INT); - if (intr != 0) { - out_8(&via[IFR], intr); - } } /* This is not necessary except if synchronous ADB requests are done * with interrupts off, which should not happen. Since I'm not sure @@ -846,23 +893,17 @@ out_8(&via[IFR], SR_INT); return; } - /* This one seems to appear with PMU99. According to OF methods, - * the protocol didn't change... - */ - if (via[B] & TACK) { - while ((in_8(&via[B]) & TACK) != 0) + /* The ack may not yet be low when we get the interrupt */ + while ((in_8(&via[B]) & TACK) != 0) ; - } - - /* reset TREQ and wait for TACK to go high */ - out_8(&via[B], in_8(&via[B]) | TREQ); - wait_for_ack(); /* if reading grab the byte, and reset the interrupt */ if (pmu_state == reading || pmu_state == reading_intr) bite = in_8(&via[SR]); - out_8(&via[IFR], SR_INT); + /* reset TREQ and wait for TACK to go high */ + out_8(&via[B], in_8(&via[B]) | TREQ); + wait_for_ack(); switch (pmu_state) { case sending: @@ -909,9 +950,8 @@ if (data_len == -1) { data_len = bite; if (bite > 32) - printk(KERN_ERR "PMU: bad reply len %d\n", - bite); - } else { + printk(KERN_ERR "PMU: bad reply len %d\n", bite); + } else if (data_index < 32) { reply_ptr[data_index++] = bite; } if (data_index < data_len) { @@ -954,11 +994,14 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) { asleep = 0; - if (len < 1) { -// xmon_printk("empty ADB\n"); + if (drop_interrupts || len < 1) { adb_int_pending = 0; return; } + /* Note: for some reason, we get an interrupt with len=1, + * data[0]==0 after each normal ADB interrupt, at least + * on the Pismo. Still investigating... --BenH + */ if (data[0] & PMU_INT_ADB) { if ((data[0] & PMU_INT_ADB_AUTO) == 0) { struct adb_request *req = req_awaiting_reply; @@ -1085,10 +1128,14 @@ cli(); - pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | - PMU_INT_TICK ); - while(!req.complete) - pmu_poll(); + drop_interrupts = 1; + + if (pmu_kind != PMU_KEYLARGO_BASED) { + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | + PMU_INT_TICK ); + while(!req.complete) + pmu_poll(); + } pmu_request(&req, NULL, 1, PMU_RESET); while(!req.complete || (pmu_state != idle)) @@ -1104,10 +1151,14 @@ cli(); - pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | - PMU_INT_TICK ); - while(!req.complete) - pmu_poll(); + drop_interrupts = 1; + + if (pmu_kind != PMU_KEYLARGO_BASED) { + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | + PMU_INT_TICK ); + while(!req.complete) + pmu_poll(); + } pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T'); @@ -1127,6 +1178,22 @@ static LIST_HEAD(sleep_notifiers); +#ifdef CONFIG_PM +static int +generic_notify_sleep(struct pmu_sleep_notifier *self, int when) +{ + switch (when) { + case PBOOK_SLEEP_NOW: + if (pm_send_all(PM_SUSPEND, (void *)3)) + return PBOOK_SLEEP_REJECT; + break; + case PBOOK_WAKE: + (void) pm_send_all(PM_RESUME, (void *)0); + } + return PBOOK_SLEEP_OK; +} +#endif /* CONFIG_PM */ + int pmu_register_sleep_notifier(struct pmu_sleep_notifier *n) { @@ -1268,23 +1335,42 @@ } } -#if 0 +#ifdef DEBUG_SLEEP /* N.B. This doesn't work on the 3400 */ -void pmu_blink(int n) +void +pmu_blink(int n) { struct adb_request req; + memset(&req, 0, sizeof(req)); + for (; n > 0; --n) { - pmu_request(&req, NULL, 4, 0xee, 4, 0, 1); - while (!req.complete) pmu_poll(); - udelay(50000); - pmu_request(&req, NULL, 4, 0xee, 4, 0, 0); - while (!req.complete) pmu_poll(); - udelay(50000); + req.nbytes = 4; + req.done = NULL; + req.data[0] = 0xee; + req.data[1] = 4; + req.data[2] = 0; + req.data[3] = 1; + req.reply[0] = ADB_RET_OK; + req.reply_len = 1; + req.reply_expected = 0; + pmu_polled_request(&req); + mdelay(50); + req.nbytes = 4; + req.done = NULL; + req.data[0] = 0xee; + req.data[1] = 4; + req.data[2] = 0; + req.data[3] = 0; + req.reply[0] = ADB_RET_OK; + req.reply_len = 1; + req.reply_expected = 0; + pmu_polled_request(&req); + mdelay(50); } - udelay(150000); + mdelay(50); } -#endif +#endif /* DEBUG_SLEEP */ /* * Put the powerbook to sleep. @@ -1317,7 +1403,6 @@ out_8(&via[IER], IER_SET | SR_INT | CB1_INT); } -#define FEATURE_CTRL(base) ((unsigned int *)(base + 0x38)) #define GRACKLE_PM (1<<7) #define GRACKLE_DOZE (1<<5) #define GRACKLE_NAP (1<<4) @@ -1363,7 +1448,8 @@ mb(); /* Wait for completion of async backlight requests */ - while (!bright_req_1.complete || !bright_req_2.complete || !bright_req_3.complete) + while (!bright_req_1.complete || !bright_req_2.complete || + !bright_req_3.complete) pmu_poll(); /* Turn off various things. Darwin does some retry tests here... */ @@ -1375,8 +1461,8 @@ while (!req.complete) pmu_poll(); - /* Disable all interrupts except pmu */ - sleep_save_intrs(vias->intrs[0].line); + /* Disable all interrupts */ + pmac_sleep_save_intrs(-1); /* Make sure the PMU is idle */ while (pmu_state != idle) @@ -1393,6 +1479,9 @@ if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0) giveup_fpu(current); + /* We can now disable MSR_EE */ + cli(); + /* For 750, save backside cache setting and disable it */ save_l2cr = _get_L2CR(); /* (returns 0 if not 750) */ if (save_l2cr) @@ -1431,7 +1520,7 @@ _set_L2CR(save_l2cr); /* Restore userland MMU context */ - set_context(current->mm->context); + set_context(current->active_mm->context, current->active_mm->pgd); /* Re-enable DEC interrupts and kick DEC */ asm volatile("mtdec %0" : : "r" (0x7fffffff)); @@ -1464,26 +1553,29 @@ } /* reenable interrupt controller */ - sleep_restore_intrs(); + pmac_sleep_restore_intrs(); /* Leave some time for HW to settle down */ mdelay(100); /* Notify drivers */ - mdelay(10); broadcast_wake(); return 0; } -/* Not finished yet */ int __openfirmware powerbook_sleep_Core99(void) { - int ret; unsigned long save_l2cr; unsigned long wait; struct adb_request req; - + int ret, timeout; + + if (!feature_can_sleep()) { + printk(KERN_ERR "Sleep mode not supported on this machine\n"); + return -ENOSYS; + } + /* Notify device drivers */ ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT); if (ret != PBOOK_SLEEP_OK) { @@ -1507,89 +1599,157 @@ } /* Give the disks a little time to actually finish writing */ - for (wait = jiffies + (HZ/4); time_before(jiffies, wait); ) + for (wait = jiffies + HZ; time_before(jiffies, wait); ) mb(); + /* Wait for completion of async backlight requests */ + while (!bright_req_1.complete || !bright_req_2.complete || + !bright_req_3.complete) + pmu_poll(); + /* Tell PMU what events will wake us up */ pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS, 0xff, 0xff); while (!req.complete) pmu_poll(); + pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS, 0, PMU_PWR_WAKEUP_KEY | PMU_PWR_WAKEUP_LID_OPEN); while (!req.complete) pmu_poll(); - /* Disable all interrupts except pmu */ - sleep_save_intrs(vias->intrs[0].line); + /* Save & disable all interrupts */ + openpic_sleep_save_intrs(); + + /* Make sure the PMU is idle */ + while (pmu_state != idle) + pmu_poll(); /* Make sure the decrementer won't interrupt us */ asm volatile("mtdec %0" : : "r" (0x7fffffff)); + /* Make sure any pending DEC interrupt occuring while we did + * the above didn't re-enable the DEC */ + mb(); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); - /* Save the state of PCI config space for some slots */ - pbook_pci_save(); + /* Giveup the FPU & vec */ + enable_kernel_fp(); - feature_prepare_for_sleep(); +#ifdef CONFIG_ALTIVEC + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC) + enable_kernel_altivec(); +#endif /* CONFIG_ALTIVEC */ + + /* We can now disable MSR_EE */ + cli(); /* For 750, save backside cache setting and disable it */ save_l2cr = _get_L2CR(); /* (returns 0 if not 750) */ if (save_l2cr) - _set_L2CR(0); + _set_L2CR(save_l2cr & 0x7fffffff); - if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0) - giveup_fpu(current); + /* Save the state of PCI config space for some slots */ + //pbook_pci_save(); /* Ask the PMU to put us to sleep */ pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); - while (!req.complete) - mb(); - - cli(); - while (pmu_state != idle) + while (!req.complete && pmu_state != idle) pmu_poll(); - /* Call low-level ASM sleep handler */ - low_sleep_handler(); + out_8(&via[B], in_8(&via[B]) | TREQ); + wait_for_ack(); - /* Make sure the PMU is idle */ - while (pmu_state != idle) - pmu_poll(); + /* The VIA is supposed not to be restored correctly*/ + save_via_state(); - sti(); + /* Shut down various ASICs. There's a chance that we can no longer + * talk to the PMU after this, so I moved it to _after_ sending the + * sleep command to it. Still need to be checked. + */ + feature_prepare_for_sleep(); + /* Call low-level ASM sleep handler */ + low_sleep_handler(); + + /* Restore Apple core ASICs state */ feature_wake_up(); - pbook_pci_restore(); - set_context(current->mm->context); + /* Restore VIA */ + restore_via_state(); + + /* Restore PCI config space. This should be overridable by PCI device + * drivers as some of them may need special restore code. That's yet + * another issue that should be handled by the common code properly, + * maybe one day ? + */ + /* Don't restore PCI for now, it crashes. Maybe unnecessary on pbook */ + //pbook_pci_restore(); + pmu_blink(2); + /* Restore L2 cache */ if (save_l2cr) - _set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */ + _set_L2CR(save_l2cr); + + /* Restore userland MMU context */ + set_context(current->active_mm->context, current->active_mm->pgd); - /* reenable interrupts */ - sleep_restore_intrs(); + /* Re-enable DEC interrupts and kick DEC */ + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + sti(); + asm volatile("mtdec %0" : : "r" (0x10000000)); /* Tell PMU we are ready */ pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2); while (!req.complete) pmu_poll(); + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc); + while (!req.complete) + pmu_poll(); + /* ack all pending interrupts */ + timeout = 100000; + interrupt_data[0] = 1; + while (interrupt_data[0] || pmu_state != idle) { + if (--timeout < 0) + break; + if (pmu_state == idle) + adb_int_pending = 1; + via_pmu_interrupt(0, 0, 0); + udelay(10); + } + + /* reenable interrupt controller */ + openpic_sleep_restore_intrs(); + + /* Leave some time for HW to settle down */ + mdelay(100); + /* Notify drivers */ - mdelay(10); broadcast_wake(); return 0; } -#define PB3400_MEM_CTRL ((unsigned int *)0xf8000070) +#define PB3400_MEM_CTRL 0xf8000000 +#define PB3400_MEM_CTRL_SLEEP 0x70 int __openfirmware powerbook_sleep_3400(void) { int ret, i, x; - unsigned long msr; unsigned int hid0; unsigned long p, wait; struct adb_request sleep_req; + char *mem_ctrl; + unsigned int *mem_ctrl_sleep; + + /* first map in the memory controller registers */ + mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100); + if (mem_ctrl == NULL) { + printk("powerbook_sleep_3400: ioremap failed\n"); + return -ENOMEM; + } + mem_ctrl_sleep = (unsigned int *) (mem_ctrl + PB3400_MEM_CTRL_SLEEP); /* Notify device drivers */ ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT); @@ -1617,11 +1777,20 @@ for (wait = jiffies + (HZ/4); time_before(jiffies, wait); ) mb(); + /* Wait for completion of async backlight requests */ + while (!bright_req_1.complete || !bright_req_2.complete || + !bright_req_3.complete) + pmu_poll(); + /* Disable all interrupts except pmu */ - sleep_save_intrs(vias->intrs[0].line); + pmac_sleep_save_intrs(vias->intrs[0].line); /* Make sure the decrementer won't interrupt us */ asm volatile("mtdec %0" : : "r" (0x7fffffff)); + /* Make sure any pending DEC interrupt occuring while we did + * the above didn't re-enable the DEC */ + mb(); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); /* Save the state of PCI config space for some slots */ pbook_pci_save(); @@ -1629,9 +1798,9 @@ /* Set the memory controller to keep the memory refreshed while we're asleep */ for (i = 0x403f; i >= 0x4000; --i) { - out_be32(PB3400_MEM_CTRL, i); + out_be32(mem_ctrl_sleep, i); do { - x = (in_be32(PB3400_MEM_CTRL) >> 16) & 0x3ff; + x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff; } while (x == 0); if (x >= 0x100) break; @@ -1651,32 +1820,36 @@ asm volatile("mfspr %0,1008" : "=r" (hid0) :); hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP; asm volatile("mtspr 1008,%0" : : "r" (hid0)); - save_flags(msr); - msr |= MSR_POW | MSR_EE; - restore_flags(msr); + _nmask_and_or_msr(0, MSR_POW | MSR_EE); udelay(10); /* OK, we're awake again, start restoring things */ - out_be32(PB3400_MEM_CTRL, 0x3f); + out_be32(mem_ctrl_sleep, 0x3f); pbook_pci_restore(); /* wait for the PMU interrupt sequence to complete */ while (asleep) mb(); + /* Re-enable DEC interrupts and kick DEC */ + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + sti(); + asm volatile("mtdec %0" : : "r" (0x10000000)); + /* reenable interrupts */ - sleep_restore_intrs(); + pmac_sleep_restore_intrs(); /* Notify drivers */ broadcast_wake(); + iounmap(mem_ctrl); return 0; } /* * Support for /dev/pmu device */ -#define RB_SIZE 10 +#define RB_SIZE 0x10 struct pmu_private { struct list_head list; int rb_get; @@ -1830,6 +2003,11 @@ switch (cmd) { case PMU_IOC_SLEEP: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (sleep_in_progress) + return -EBUSY; + sleep_in_progress = 1; switch (pmu_kind) { case PMU_OHARE_BASED: error = powerbook_sleep_3400(); @@ -1838,20 +2016,24 @@ case PMU_PADDINGTON_BASED: error = powerbook_sleep_G3(); break; -#if 0 /* Not ready yet */ case PMU_KEYLARGO_BASED: error = powerbook_sleep_Core99(); break; -#endif default: error = -ENOSYS; } + sleep_in_progress = 0; return error; + case PMU_IOC_CAN_SLEEP: + return put_user(feature_can_sleep(), (__u32 *)arg); + #ifdef CONFIG_PMAC_BACKLIGHT /* Backlight should have its own device or go via * the fbdev */ case PMU_IOC_GET_BACKLIGHT: + if (sleep_in_progress) + return -EBUSY; error = get_backlight_level(); if (error < 0) return error; @@ -1859,6 +2041,8 @@ case PMU_IOC_SET_BACKLIGHT: { __u32 value; + if (sleep_in_progress) + return -EBUSY; error = get_user(value, (__u32 *)arg); if (!error) error = set_backlight_level(value); @@ -1893,7 +2077,7 @@ } #endif /* CONFIG_PMAC_PBOOK */ -#if 0 +#ifdef DEBUG_SLEEP static inline void polled_handshake(volatile unsigned char *via) { via[B] &= ~TREQ; eieio(); @@ -1939,6 +2123,8 @@ while (pmu_state != idle) pmu_poll(); + while ((via[B] & TACK) == 0) + ; polled_send_byte(v, c); if (l < 0) { l = req->nbytes - 1; @@ -1959,4 +2145,15 @@ restore_flags(flags); return 0; } -#endif /* 0 */ +#endif /* DEBUG_SLEEP */ + +EXPORT_SYMBOL(pmu_request); +EXPORT_SYMBOL(pmu_poll); +EXPORT_SYMBOL(pmu_suspend); +EXPORT_SYMBOL(pmu_resume); +#ifdef CONFIG_PMAC_PBOOK +EXPORT_SYMBOL(pmu_register_sleep_notifier); +EXPORT_SYMBOL(pmu_unregister_sleep_notifier); +EXPORT_SYMBOL(pmu_enable_irled); +#endif /* CONFIG_PMAC_PBOOK */ + diff -u --recursive --new-file v2.4.9/linux/drivers/md/lvm.c linux/drivers/md/lvm.c --- v2.4.9/linux/drivers/md/lvm.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/md/lvm.c Sat Sep 8 12:02:32 2001 @@ -394,8 +394,6 @@ */ int lvm_init(void) { - struct gendisk *gendisk_ptr = NULL; - if (register_chrdev(LVM_CHAR_MAJOR, lvm_name, &lvm_chr_fops) < 0) { printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name); return -EIO; @@ -423,19 +421,7 @@ lvm_init_vars(); lvm_geninit(&lvm_gendisk); - /* insert our gendisk at the corresponding major */ - if (gendisk_head != NULL) { - gendisk_ptr = gendisk_head; - while (gendisk_ptr->next != NULL && - gendisk_ptr->major > lvm_gendisk.major) { - gendisk_ptr = gendisk_ptr->next; - } - lvm_gendisk.next = gendisk_ptr->next; - gendisk_ptr->next = &lvm_gendisk; - } else { - gendisk_head = &lvm_gendisk; - lvm_gendisk.next = NULL; - } + add_gendisk(&lvm_gendisk); #ifdef LVM_HD_NAME /* reference from drivers/block/genhd.c */ @@ -469,8 +455,6 @@ */ static void lvm_cleanup(void) { - struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL; - devfs_unregister (lvm_devfs_handle); if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) { @@ -481,16 +465,7 @@ } - gendisk_ptr = gendisk_ptr_prev = gendisk_head; - while (gendisk_ptr != NULL) { - if (gendisk_ptr == &lvm_gendisk) - break; - gendisk_ptr_prev = gendisk_ptr; - gendisk_ptr = gendisk_ptr->next; - } - /* delete our gendisk from chain */ - if (gendisk_ptr == &lvm_gendisk) - gendisk_ptr_prev->next = gendisk_ptr->next; + del_gendisk(&lvm_gendisk); blk_size[MAJOR_NR] = NULL; blksize_size[MAJOR_NR] = NULL; @@ -1059,7 +1034,6 @@ lvm_name, minor, VG_BLK(minor), LV_BLK(minor)); #endif - sync_dev(inode->i_rdev); if (lv_ptr->lv_open == 1) vg_ptr->lv_open--; lv_ptr->lv_open--; diff -u --recursive --new-file v2.4.9/linux/drivers/md/md.c linux/drivers/md/md.c --- v2.4.9/linux/drivers/md/md.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/md/md.c Sat Sep 8 12:02:32 2001 @@ -222,18 +222,6 @@ return mddev; } -struct gendisk * find_gendisk (kdev_t dev) -{ - struct gendisk *tmp = gendisk_head; - - while (tmp != NULL) { - if (tmp->major == MAJOR(dev)) - return (tmp); - tmp = tmp->next; - } - return (NULL); -} - mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) { mdk_rdev_t * rdev; @@ -281,7 +269,7 @@ /* * ok, add this new device name to the list */ - hd = find_gendisk (dev); + hd = get_gendisk (dev); dname->name = NULL; if (hd) dname->name = disk_name (hd, MINOR(dev), dname->namebuf); @@ -569,7 +557,7 @@ static kdev_t dev_unit(kdev_t dev) { unsigned int mask; - struct gendisk *hd = find_gendisk(dev); + struct gendisk *hd = get_gendisk(dev); if (!hd) return 0; @@ -921,17 +909,19 @@ dev = rdev->dev; sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1); if (rdev->sb_offset != sb_offset) { - printk("%s's sb offset has changed from %ld to %ld, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset); + printk("%s's sb offset has changed from %ld to %ld, skipping\n", + partition_name(dev), rdev->sb_offset, sb_offset); goto skip; } /* * If the disk went offline meanwhile and it's just a spare, then - * it's size has changed to zero silently, and the MD code does + * its size has changed to zero silently, and the MD code does * not yet know that it's faulty. */ size = calc_dev_size(dev, rdev->mddev, 1); if (size != rdev->size) { - printk("%s's size has changed from %ld to %ld since import, skipping\n", partition_name(dev), rdev->size, size); + printk("%s's size has changed from %ld to %ld since import, skipping\n", + partition_name(dev), rdev->size, size); goto skip; } @@ -2488,27 +2478,14 @@ (long *) arg); goto done; - case BLKFLSBUF: - fsync_dev(dev); - invalidate_buffers(dev); - goto done; - + case BLKRAGET: case BLKRASET: - if (arg > 0xff) { - err = -EINVAL; - goto abort; - } - read_ahead[MAJOR(dev)] = arg; - goto done; + case BLKFLSBUF: + case BLKBSZGET: + case BLKBSZSET: + err = blk_ioctl (dev, cmd, arg); + goto abort; - case BLKRAGET: - if (!arg) { - err = -EINVAL; - goto abort; - } - err = md_put_user (read_ahead[ - MAJOR(dev)], (long *) arg); - goto done; default:; } @@ -2780,7 +2757,6 @@ int md_thread(void * arg) { mdk_thread_t *thread = arg; - struct completion *event; md_lock_kernel(); @@ -2921,7 +2897,7 @@ return 0; } rrdev = find_rdev(mddev, rdev); - if (rrdev->faulty) + if (!rrdev || rrdev->faulty) return 0; if (mddev->pers->error_handler == NULL || mddev->pers->error_handler(mddev,rdev) <= 0) { @@ -3224,7 +3200,7 @@ if (mddev2 == mddev) continue; if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { - printk(KERN_INFO "md: serializing resync, md%d shares one or more physical units with md%d!\n", mdidx(mddev), mdidx(mddev2)); + printk(KERN_INFO "md: delaying resync of md%d until md%d has finished resync (they share one or more physical units)\n", mdidx(mddev), mdidx(mddev2)); serialize = 1; break; } @@ -3286,9 +3262,12 @@ if (last_check + window > j) continue; + + last_check = j; - run_task_queue(&tq_disk); //?? + run_task_queue(&tq_disk); + repeat: if (jiffies >= mark[last_mark] + SYNC_MARK_STEP ) { /* step marks */ int next = (last_mark+1) % SYNC_MARKS; @@ -3320,7 +3299,6 @@ * about not overloading the IO subsystem. (things like an * e2fsck being done on the RAID array should execute fast) */ -repeat: if (md_need_resched(current)) schedule(); @@ -3333,8 +3311,7 @@ !is_mddev_idle(mddev)) { current->state = TASK_INTERRUPTIBLE; md_schedule_timeout(HZ/4); - if (!md_signal_pending(current)) - goto repeat; + goto repeat; } } else current->nice = -20; @@ -3526,9 +3503,8 @@ read_ahead[MAJOR_NR] = INT_MAX; - md_gendisk.next = gendisk_head; - gendisk_head = &md_gendisk; + add_gendisk(&md_gendisk); md_recovery_thread = md_register_thread(md_do_recovery, NULL, name); if (!md_recovery_thread) @@ -3759,7 +3735,7 @@ ainfo.md_minor =minor; ainfo.not_persistent = 1; - ainfo.state = MD_SB_CLEAN; + ainfo.state = (1 << MD_SB_CLEAN); ainfo.active_disks = 0; ainfo.working_disks = 0; ainfo.failed_disks = 0; @@ -3854,8 +3830,6 @@ void cleanup_module (void) { - struct gendisk **gendisk_ptr; - md_unregister_thread(md_recovery_thread); devfs_unregister(devfs_handle); @@ -3865,15 +3839,9 @@ #ifdef CONFIG_PROC_FS remove_proc_entry("mdstat", NULL); #endif - - gendisk_ptr = &gendisk_head; - while (*gendisk_ptr) { - if (*gendisk_ptr == &md_gendisk) { - *gendisk_ptr = md_gendisk.next; - break; - } - gendisk_ptr = & (*gendisk_ptr)->next; - } + + del_gendisk(&md_gendisk); + blk_dev[MAJOR_NR].queue = NULL; blksize_size[MAJOR_NR] = NULL; blk_size[MAJOR_NR] = NULL; diff -u --recursive --new-file v2.4.9/linux/drivers/md/raid1.c linux/drivers/md/raid1.c --- v2.4.9/linux/drivers/md/raid1.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/md/raid1.c Wed Aug 29 20:47:41 2001 @@ -162,7 +162,7 @@ conf->freer1 = r1_bh->next_r1; conf->freer1_cnt--; r1_bh->next_r1 = NULL; - r1_bh->state = 0; + r1_bh->state = (1 << R1BH_PreAlloc); r1_bh->bh_req.b_state = 0; } md_spin_unlock_irq(&conf->device_lock); diff -u --recursive --new-file v2.4.9/linux/drivers/md/raid5.c linux/drivers/md/raid5.c --- v2.4.9/linux/drivers/md/raid5.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/md/raid5.c Fri Sep 7 10:48:39 2001 @@ -485,7 +485,7 @@ int i; PRINTK("raid5_error called\n"); - conf->resync_parity = 0; + for (i = 0, disk = conf->disks; i < conf->raid_disks; i++, disk++) { if (disk->dev == dev && disk->operational) { disk->operational = 0; @@ -516,7 +516,7 @@ "raid5: Disk failure on spare %s\n", partition_name (dev)); if (!conf->spare->operational) { - MD_BUG(); + /* probably a SET_DISK_FAULTY ioctl */ return -EIO; } disk->operational = 0; @@ -529,6 +529,9 @@ sb->working_disks--; sb->failed_disks++; + mddev->sb_dirty = 1; + md_wakeup_thread(conf->thread); + return 0; } } @@ -898,11 +901,11 @@ spin_unlock_irq(&conf->device_lock); } } - if (syncing) { - md_done_sync(conf->mddev, (sh->size>>9) - sh->sync_redone,0); - clear_bit(STRIPE_SYNCING, &sh->state); - syncing = 0; - } + } + if (failed > 1 && syncing) { + md_done_sync(conf->mddev, (sh->size>>9) - sh->sync_redone,0); + clear_bit(STRIPE_SYNCING, &sh->state); + syncing = 0; } /* might be able to return some write requests if the parity block @@ -1076,6 +1079,7 @@ } } if (!test_bit(STRIPE_INSYNC, &sh->state)) { + struct disk_info *spare; if (failed==0) failed_num = sh->pd_idx; /* should be able to compute the missing block and write it to spare */ @@ -1094,8 +1098,8 @@ set_bit(STRIPE_INSYNC, &sh->state); if (conf->disks[failed_num].operational) md_sync_acct(conf->disks[failed_num].dev, bh->b_size>>9); - else if (conf->spare) - md_sync_acct(conf->spare->dev, bh->b_size>>9); + else if ((spare=conf->spare)) + md_sync_acct(spare->dev, bh->b_size>>9); } } @@ -1120,6 +1124,7 @@ for (i=disks; i-- ;) if (action[i]) { struct buffer_head *bh = sh->bh_cache[i]; + struct disk_info *spare = conf->spare; int skip = 0; if (action[i] == READ+1) bh->b_end_io = raid5_end_read_request; @@ -1127,8 +1132,8 @@ bh->b_end_io = raid5_end_write_request; if (conf->disks[i].operational) bh->b_dev = conf->disks[i].dev; - else if (conf->spare && action[i] == WRITE+1) - bh->b_dev = conf->spare->dev; + else if (spare && action[i] == WRITE+1) + bh->b_dev = spare->dev; else skip=1; if (!skip) { PRINTK("for %ld schedule op %d on disc %d\n", sh->sector, action[i]-1, i); diff -u --recursive --new-file v2.4.9/linux/drivers/media/video/videodev.c linux/drivers/media/video/videodev.c --- v2.4.9/linux/drivers/media/video/videodev.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/media/video/videodev.c Tue Aug 28 07:00:58 2001 @@ -164,7 +164,6 @@ if(vfl->owner) __MOD_INC_USE_COUNT(vfl->owner); - unlock_kernel(); if(vfl->open) { @@ -175,9 +174,11 @@ if(vfl->owner) __MOD_DEC_USE_COUNT(vfl->owner); + unlock_kernel(); return err; } } + unlock_kernel(); return 0; error_out: unlock_kernel(); diff -u --recursive --new-file v2.4.9/linux/drivers/media/video/vino.h linux/drivers/media/video/vino.h --- v2.4.9/linux/drivers/media/video/vino.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/video/vino.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,117 @@ +/* + * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) + * Copyright (C) 2001 Ralf Baechle (ralf@gnu.org) + */ + +#define VINO_BASE 0x00080000 /* In EISA address space */ + +#define VINO_REVID 0x0000 +#define VINO_CTRL 0x0008 +#define VINO_INTSTAT 0x0010 /* Interrupt status */ +#define VINO_I2C_CTRL 0x0018 +#define VINO_I2C_DATA 0x0020 +#define VINO_A_ALPHA 0x0028 /* Channel A ... */ +#define VINO_A_CLIPS 0x0030 /* Clipping start */ +#define VINO_A_CLIPE 0x0038 /* Clipping end */ +#define VINO_A_FRAMERT 0x0040 /* Framerate */ +#define VINO_A_FLDCNT 0x0048 /* Field counter */ +#define VINO_A_LNSZ 0x0050 +#define VINO_A_LNCNT 0x0058 +#define VINO_A_PGIX 0x0060 /* Page index */ +#define VINO_A_DESC_PTR 0x0068 /* Ptr to next four descriptors */ +#define VINO_A_DESC_TLB_PTR 0x0070 /* Ptr to start of descriptor table */ +#define VINO_A_DESC_DATA0 0x0078 /* Descriptor data 0 */ +#define VINO_A_DESC_DATA1 0x0080 /* ... */ +#define VINO_A_DESC_DATA2 0x0088 +#define VINO_A_DESC_DATA3 0x0090 +#define VINO_A_FIFO_THRESHOLD 0x0098 /* FIFO threshold */ +#define VINO_A_FIFO_RP 0x00a0 +#define VINO_A_FIFO_WP 0x00a8 +#define VINO_B_ALPHA 0x00b0 /* Channel B ... */ +#define VINO_B_CLIPS 0x00b8 +#define VINO_B_CLIPE 0x00c0 +#define VINO_B_FRAMERT 0x00c8 +#define VINO_B_FLDCNT 0x00d0 +#define VINO_B_LNSZ 0x00d8 +#define VINO_B_LNCNT 0x00e0 +#define VINO_B_PGIX 0x00e8 +#define VINO_B_DESC_PTR 0x00f0 +#define VINO_B_DESC_TLB_PTR 0x00f8 +#define VINO_B_DESC_DATA0 0x0100 +#define VINO_B_DESC_DATA1 0x0108 +#define VINO_B_DESC_DATA2 0x0110 +#define VINO_B_DESC_DATA3 0x0118 +#define VINO_B_FIFO_THRESHOLD 0x0120 +#define VINO_B_FIFO_RP 0x0128 +#define VINO_B_FIFO_WP 0x0130 + +/* Bits in the VINO_REVID register */ + +#define VINO_REVID_REV_MASK 0x000f /* bits 0:3 */ +#define VINO_REVID_ID_MASK 0x00f0 /* bits 4:7 */ + +/* Bits in the VINO_CTRL register */ + +#define VINO_CTRL_LITTLE_ENDIAN (1<<0) +#define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */ +#define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */ +#define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */ +#define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */ +#define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */ +#define VINO_CTRL_B_END_DESC_TLB_INT (1<<6) /* End of desc table int */ +#define VINO_CTRL_A_DMA_ENBL (1<<7) +#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8) +#define VINO_CTRL_A_SYNC_ENBL (1<<9) +#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */ +#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */ +#define VINO_CTRL_A_LUMA_ONLY (1<<12) +#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */ +#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */ +#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */ +#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */ +#define VINO_CTRL_B_DMA_ENBL (1<<19) +#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20) +#define VINO_CTRL_B_SYNC_ENBL (1<<21) +#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */ +#define VINO_CTRL_B_RGB (1<<22) /* 1=RGB 0=YUV */ +#define VINO_CTRL_B_LUMA_ONLY (1<<23) +#define VINO_CTRL_B_DEC_ENBL (1<<24) /* Decimation */ +#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 25:28 */ +#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */ +#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */ + +/* Bits in the Interrupt and Status register */ + +#define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */ +#define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */ +#define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */ +#define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */ +#define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */ +#define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */ + +/* Bits in the Clipping Start register */ + +#define VINO_CLIPS_START 0x3ff /* bits 0:9 */ +#define VINO_CLIPS_ODD_MASK 0x7fc00 /* bits 10:18 */ +#define VINO_CLIPS_EVEN_MASK 0xff80000 /* bits 19:27 */ + +/* Bits in the Clipping End register */ + +#define VINO_CLIPE_END 0x3ff /* bits 0:9 */ +#define VINO_CLIPE_ODD_MASK 0x7fc00 /* bits 10:18 */ +#define VINO_CLIPE_EVEN_MASK 0xff80000 /* bits 19:27 */ + +/* Bits in the Frame Rate register */ + +#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */ +#define VINO_FRAMERT_RT_MASK 0x1ffe /* bits 1:12 */ + +/* Bits in the VINO_I2C_CTRL */ + +#define VINO_CTRL_I2C_IDLE (1<<0) /* write: 0=force idle + * read: 0=idle 1=not idle */ +#define VINO_CTRL_I2C_DIR (1<<1) /* 0=read 1=write */ +#define VINO_CTRL_I2C_MORE_BYTES (1<<2) /* 0=last byte 1=more bytes */ +#define VINO_CTRL_I2C_TRANS_BUSY (1<<4) /* 0=trans done 1=trans busy */ +#define VINO_CTRL_I2C_ACK (1<<5) /* 0=ack received 1=ack not */ +#define VINO_CTRL_I2C_BUS_ERROR (1<<7) /* 0=no bus err 1=bus err */ diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/Makefile linux/drivers/message/fusion/Makefile --- v2.4.9/linux/drivers/message/fusion/Makefile Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/Makefile Fri Sep 7 09:28:38 2001 @@ -27,18 +27,22 @@ #EXTRA_CFLAGS += -DDEBUG #EXTRA_CFLAGS += -DMPT_DEBUG #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME -#EXTRA_CFLAGS += -DMPT_DEBUG_SPINLOCK +# # driver/module specifics... +# # For mptbase: #CFLAGS_mptbase.o += -DMPT_DEBUG_HANDSHAKE #CFLAGS_mptbase.o += -DMPT_DEBUG_IRQ +# # For {mptscsih, mptctl}: #CFLAGS_mptscsih.o += -DMPT_SCSI_USE_NEW_EH -#CFLAGS_mptscsih.o += -DMPT_SCSI_CACHE_AUTOSENSE +#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCANDV #CFLAGS_mptscsih.o += -DMPT_DEBUG_SG #CFLAGS_mptctl.o += -DMPT_DEBUG_SG +# # For mptlan: #CFLAGS_mptlan.o += -DMPT_LAN_IO_DEBUG +# # For isense: # EXP... diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/isense.c linux/drivers/message/fusion/isense.c --- v2.4.9/linux/drivers/message/fusion/isense.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/isense.c Fri Sep 7 09:28:38 2001 @@ -10,7 +10,7 @@ * (yes I wrote some of the orig. code back in 1991!) * (mailto:Steve.Ralston@lsil.com) * - * $Id: isense.c,v 1.28 2001/01/14 23:11:09 sralston Exp $ + * $Id: isense.c,v 1.28.14.1 2001/08/24 20:07:04 sralston Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -61,7 +61,7 @@ #endif #define MODULEAUTHOR "Steven J. Ralston" -#define COPYRIGHT "Copyright (c) 2000 " MODULEAUTHOR +#define COPYRIGHT "Copyright (c) 2001 " MODULEAUTHOR #include "mptbase.h" #include "isense.h" diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/fc_log.h linux/drivers/message/fusion/lsi/fc_log.h --- v2.4.9/linux/drivers/message/fusion/lsi/fc_log.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/fc_log.h Fri Sep 7 09:28:38 2001 @@ -7,7 +7,7 @@ * in the IOCLogInfo field of a MPI Default Reply Message. * * CREATION DATE: 6/02/2000 - * ID: $Id: fc_log.h,v 4.2 2001/03/01 18:28:59 fibre Exp $ + * ID: $Id: fc_log.h,v 4.5 2001/06/07 19:18:00 sschremm Exp $ */ @@ -38,11 +38,16 @@ { MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000, MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */ - MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* bad start of frame primative */ - MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* bad end of frame primative */ - MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Receiver hardware detected overrun */ + MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */ + MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */ + MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */ MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */ + MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */ + MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */ + MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */ + MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */ + MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */ MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000, MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */ @@ -72,10 +77,11 @@ MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */ MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */ MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */ + MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */ MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000, - MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid. */ + MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */ MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff, MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */ diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/mpi.h linux/drivers/message/fusion/lsi/mpi.h --- v2.4.9/linux/drivers/message/fusion/lsi/mpi.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/mpi.h Fri Sep 7 09:28:38 2001 @@ -6,7 +6,7 @@ * Title: MPI Message independent structures and definitions * Creation Date: July 27, 2000 * - * MPI Version: 01.01.06 + * MPI Version: 01.01.07 * * Version History * --------------- @@ -37,6 +37,8 @@ * Obsoleted MPI_IOCSTATUS_TARGET_FC_ defines. * 02-27-01 01.01.06 Removed MPI_HOST_INDEX_REGISTER define. * Added function codes for RAID. + * 04-09-01 01.01.07 Added alternate define for MPI_DOORBELL_ACTIVE, + * MPI_DOORBELL_USED, to better match the spec. * -------------------------------------------------------------------------- */ @@ -90,7 +92,8 @@ /* S y s t e m D o o r b e l l */ #define MPI_DOORBELL_OFFSET (0x00000000) -#define MPI_DOORBELL_ACTIVE (0x08000000) +#define MPI_DOORBELL_ACTIVE (0x08000000) /* DoorbellUsed */ +#define MPI_DOORBELL_USED (MPI_DOORBELL_ACTIVE) #define MPI_DOORBELL_ACTIVE_SHIFT (27) #define MPI_DOORBELL_WHO_INIT_MASK (0x07000000) #define MPI_DOORBELL_WHO_INIT_SHIFT (24) @@ -634,9 +637,9 @@ /****************************************************************************/ #define MPI_IOCLOGINFO_TYPE_MASK (0xF0000000) -#define MPI_IOCLOGINFO_TYPE_NONE (0x00) -#define MPI_IOCLOGINFO_TYPE_SCSI (0x01) -#define MPI_IOCLOGINFO_TYPE_FC (0x02) +#define MPI_IOCLOGINFO_TYPE_NONE (0x0) +#define MPI_IOCLOGINFO_TYPE_SCSI (0x1) +#define MPI_IOCLOGINFO_TYPE_FC (0x2) #define MPI_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/mpi_cnfg.h linux/drivers/message/fusion/lsi/mpi_cnfg.h --- v2.4.9/linux/drivers/message/fusion/lsi/mpi_cnfg.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/mpi_cnfg.h Fri Sep 7 09:28:38 2001 @@ -6,7 +6,7 @@ * Title: MPI Config message, structures, and Pages * Creation Date: July 27, 2000 * - * MPI Version: 01.01.09 + * MPI Version: 01.01.11 * * Version History * --------------- @@ -60,6 +60,18 @@ * MPI_CONFIG_PAGETYPE_RAID_VOLUME. * Added definitions and structures for IOC Page 2 and * RAID Volume Page 2. + * 03-27-01 01.01.10 Added CONFIG_PAGE_FC_PORT_8 and CONFIG_PAGE_FC_PORT_9. + * CONFIG_PAGE_FC_PORT_3 now supports persistent by DID. + * Added VendorId and ProductRevLevel fields to + * RAIDVOL2_IM_PHYS_ID struct. + * Modified values for MPI_FCPORTPAGE0_FLAGS_ATTACH_ + * defines to make them compatible to MPI version 1.0. + * Added structure offset comments. + * 04-09-01 01.01.11 Added some new defines for the PageAddress field and + * removed some obsolete ones. + * Added IO Unit Page 3. + * Modified defines for Scsi Port Page 2. + * Modified RAID Volume Pages. * -------------------------------------------------------------------------- */ @@ -75,10 +87,10 @@ typedef struct _CONFIG_PAGE_HEADER { - U8 PageVersion; - U8 PageLength; - U8 PageNumber; - U8 PageType; + U8 PageVersion; /* 00h */ + U8 PageLength; /* 01h */ + U8 PageNumber; /* 02h */ + U8 PageType; /* 03h */ } fCONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER, ConfigPageHeader_t, MPI_POINTER pConfigPageHeader_t; @@ -120,17 +132,19 @@ ****************************************************************************/ #define MPI_SCSI_PORT_PGAD_PORT_MASK (0x000000FF) +#define MPI_SCSI_DEVICE_FORM_MASK (0xF0000000) +#define MPI_SCSI_DEVICE_FORM_TARGETID (0x00000000) +#define MPI_SCSI_DEVICE_FORM_RAID_PHYS_DEV_NUM (0x10000000) #define MPI_SCSI_DEVICE_TARGET_ID_MASK (0x000000FF) #define MPI_SCSI_DEVICE_TARGET_ID_SHIFT (0) #define MPI_SCSI_DEVICE_BUS_MASK (0x0000FF00) #define MPI_SCSI_DEVICE_BUS_SHIFT (8) - -#define MPI_SCSI_LUN_TARGET_ID_MASK (0x000000FF) -#define MPI_SCSI_LUN_TARGET_ID_SHIFT (0) -#define MPI_SCSI_LUN_BUS_MASK (0x0000FF00) -#define MPI_SCSI_LUN_BUS_SHIFT (8) -#define MPI_SCSI_LUN_LUN_MASK (0x00FF0000) -#define MPI_SCSI_LUN_LUN_SHIFT (16) +#define MPI_SCSI_DEVICE_VOLUME_TARG_ID_MASK (0x000000FF) +#define MPI_SCSI_DEVICE_VOLUME_TARG_ID_SHIFT (0) +#define MPI_SCSI_DEVICE_VOLUME_BUS_MASK (0x0000FF00) +#define MPI_SCSI_DEVICE_VOLUME_BUS_SHIFT (8) +#define MPI_SCSI_DEVICE_PHYS_DISK_NUM_MASK (0x00FF0000) +#define MPI_SCSI_DEVICE_PHYS_DISK_NUM_SHIFT (16) #define MPI_FC_PORT_PGAD_PORT_MASK (0xF0000000) #define MPI_FC_PORT_PGAD_PORT_SHIFT (28) @@ -159,17 +173,17 @@ /****************************************************************************/ typedef struct _MSG_CONFIG { - U8 Action; - U8 Reserved; - U8 ChainOffset; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; - U8 Reserved2[8]; - fCONFIG_PAGE_HEADER Header; - U32 PageAddress; - SGE_IO_UNION PageBufferSGE; + U8 Action; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2[8]; /* 0Ch */ + fCONFIG_PAGE_HEADER Header; /* 14h */ + U32 PageAddress; /* 18h */ + SGE_IO_UNION PageBufferSGE; /* 1Ch */ } MSG_CONFIG, MPI_POINTER PTR_MSG_CONFIG, Config_t, MPI_POINTER pConfig_t; @@ -178,12 +192,9 @@ /* Action field values */ /****************************************************************************/ #define MPI_CONFIG_ACTION_PAGE_HEADER (0x00) -/*#define MPI_CONFIG_ACTION_PAGE_READ (0x01) *//* obsolete */ #define MPI_CONFIG_ACTION_PAGE_READ_CURRENT (0x01) -/*#define MPI_CONFIG_ACTION_PAGE_WRITE (0x02) *//* obsolete */ #define MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02) #define MPI_CONFIG_ACTION_PAGE_DEFAULT (0x03) -/*#define MPI_CONFIG_ACTION_PAGE_WRITE_COMMIT (0x04) */ /* obsolete */ #define MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04) #define MPI_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05) #define MPI_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) @@ -192,17 +203,17 @@ /* Config Reply Message */ typedef struct _MSG_CONFIG_REPLY { - U8 Action; - U8 Reserved; - U8 MsgLength; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; - U8 Reserved2[2]; - U16 IOCStatus; - U32 IOCLogInfo; - fCONFIG_PAGE_HEADER Header; + U8 Action; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2[2]; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + fCONFIG_PAGE_HEADER Header; /* 14h */ } MSG_CONFIG_REPLY, MPI_POINTER PTR_MSG_CONFIG_REPLY, ConfigReply_t, MPI_POINTER pConfigReply_t; @@ -226,12 +237,12 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_0 { - fCONFIG_PAGE_HEADER Header; - U8 ChipName[16]; - U8 ChipRevision[8]; - U8 BoardName[16]; - U8 BoardAssembly[16]; - U8 BoardTracerNumber[16]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U8 ChipName[16]; /* 04h */ + U8 ChipRevision[8]; /* 14h */ + U8 BoardName[16]; /* 1Ch */ + U8 BoardAssembly[16]; /* 2Ch */ + U8 BoardTracerNumber[16]; /* 3Ch */ } fCONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0, ManufacturingPage0_t, MPI_POINTER pManufacturingPage0_t; @@ -241,8 +252,8 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_1 { - fCONFIG_PAGE_HEADER Header; - U8 VPD[256]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U8 VPD[256]; /* 04h */ } fCONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1, ManufacturingPage1_t, MPI_POINTER pManufacturingPage1_t; @@ -251,18 +262,18 @@ typedef struct _MPI_CHIP_REVISION_ID { - U16 DeviceID; - U8 PCIRevisionID; - U8 Reserved; + U16 DeviceID; /* 00h */ + U8 PCIRevisionID; /* 02h */ + U8 Reserved; /* 03h */ } MPI_CHIP_REVISION_ID, MPI_POINTER PTR_MPI_CHIP_REVISION_ID, MpiChipRevisionId_t, MPI_POINTER pMpiChipRevisionId_t; typedef struct _CONFIG_PAGE_MANUFACTURING_2 { - fCONFIG_PAGE_HEADER Header; - MPI_CHIP_REVISION_ID ChipId; - U32 HwSettings[1]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + MPI_CHIP_REVISION_ID ChipId; /* 04h */ + U32 HwSettings[1]; /* 08h */ } fCONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2, ManufacturingPage2_t, MPI_POINTER pManufacturingPage2_t; @@ -271,9 +282,9 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_3 { - fCONFIG_PAGE_HEADER Header; - MPI_CHIP_REVISION_ID ChipId; - U32 Info[1]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + MPI_CHIP_REVISION_ID ChipId; /* 04h */ + U32 Info[1]; /* 08h */ } fCONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3, ManufacturingPage3_t, MPI_POINTER pManufacturingPage3_t; @@ -286,8 +297,8 @@ typedef struct _CONFIG_PAGE_IO_UNIT_0 { - fCONFIG_PAGE_HEADER Header; - U64 UniqueValue; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U64 UniqueValue; /* 04h */ } fCONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0, IOUnitPage0_t, MPI_POINTER pIOUnitPage0_t; @@ -296,8 +307,8 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1 { - fCONFIG_PAGE_HEADER Header; - U32 Flags; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ } fCONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; @@ -313,9 +324,9 @@ typedef struct _MPI_ADAPTER_INFO { - U8 PciBusNumber; - U8 PciDeviceAndFunctionNumber; - U16 AdapterFlags; + U8 PciBusNumber; /* 00h */ + U8 PciDeviceAndFunctionNumber; /* 01h */ + U16 AdapterFlags; /* 02h */ } MPI_ADAPTER_INFO, MPI_POINTER PTR_MPI_ADAPTER_INFO, MpiAdapterInfo_t, MPI_POINTER pMpiAdapterInfo_t; @@ -324,10 +335,10 @@ typedef struct _CONFIG_PAGE_IO_UNIT_2 { - fCONFIG_PAGE_HEADER Header; - U32 Flags; - U32 BiosVersion; - MPI_ADAPTER_INFO AdapterOrder[4]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ + U32 BiosVersion; /* 08h */ + MPI_ADAPTER_INFO AdapterOrder[4]; /* 0Ch */ } fCONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2, IOUnitPage2_t, MPI_POINTER pIOUnitPage2_t; @@ -340,34 +351,53 @@ #define MPI_IOUNITPAGE2_FLAGS_DONT_HOOK_INT_40 (0x00000010) +typedef struct _CONFIG_PAGE_IO_UNIT_3 +{ + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 VolumeSettings; /* 04h */ + U8 InfoOffset0; /* 08h */ + U8 InfoSize0; /* 09h */ + U8 InfoOffset1; /* 0Ah */ + U8 InfoSize1; /* 0Bh */ + U8 InquirySize; /* 0Ch */ + U8 Reserved; /* 0Dh */ + U16 Reserved2; /* 0Eh */ + U8 InquiryData[56]; /* 10h */ +} fCONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3, + IOUnitPage3_t, MPI_POINTER pIOUnitPage3_t; + +#define MPI_IOUNITPAGE3_PAGEVERSION (0x00) + + /****************************************************************************/ /* IOC Config Pages */ /****************************************************************************/ typedef struct _CONFIG_PAGE_IOC_0 { - fCONFIG_PAGE_HEADER Header; - U32 TotalNVStore; - U32 FreeNVStore; - U16 VendorID; - U16 DeviceID; - U8 RevisionID; - U8 Reserved[3]; - U32 ClassCode; - U16 SubsystemVendorID; - U16 SubsystemID; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 TotalNVStore; /* 04h */ + U32 FreeNVStore; /* 08h */ + U16 VendorID; /* 0Ch */ + U16 DeviceID; /* 0Eh */ + U8 RevisionID; /* 10h */ + U8 Reserved[3]; /* 11h */ + U32 ClassCode; /* 14h */ + U16 SubsystemVendorID; /* 18h */ + U16 SubsystemID; /* 1Ah */ } fCONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0, IOCPage0_t, MPI_POINTER pIOCPage0_t; #define MPI_IOCPAGE0_PAGEVERSION (0x01) + typedef struct _CONFIG_PAGE_IOC_1 { - fCONFIG_PAGE_HEADER Header; - U32 Flags; - U32 CoalescingTimeout; - U8 CoalescingDepth; - U8 Reserved[3]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ + U32 CoalescingTimeout; /* 08h */ + U8 CoalescingDepth; /* 0Ch */ + U8 Reserved[3]; /* 0Dh */ } fCONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1, IOCPage1_t, MPI_POINTER pIOCPage1_t; @@ -375,26 +405,27 @@ #define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001) + typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL { - U8 VolumeTargetID; - U8 VolumeBus; - U16 Reserved; - U8 VolumeVersionMinor; - U8 VolumeVersionMajor; - U8 VolumeRaidType; - U8 Reserved1; + U8 VolumeTargetID; /* 00h */ + U8 VolumeBus; /* 01h */ + U16 Reserved; /* 02h */ + U8 VolumeVersionMinor; /* 04h */ + U8 VolumeVersionMajor; /* 05h */ + U8 VolumeRaidType; /* 06h */ + U8 Reserved1; /* 07h */ } fCONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL, ConfigPageIoc2RaidVol_t, MPI_POINTER pConfigPageIoc2RaidVol_t; typedef struct _CONFIG_PAGE_IOC_2 { - fCONFIG_PAGE_HEADER Header; - U32 CapabilitiesFlags; - U8 NumActiveVolumes; - U8 MaxVolumes; - U16 Reserved; - fCONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[1]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 CapabilitiesFlags; /* 04h */ + U8 NumActiveVolumes; /* 08h */ + U8 MaxVolumes; /* 09h */ + U16 Reserved; /* 0Ah */ + fCONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[1]; /* 0Ch */ } fCONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2, IOCPage2_t, MPI_POINTER pIOCPage2_t; @@ -423,9 +454,9 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0 { - fCONFIG_PAGE_HEADER Header; - U32 Capabilities; - U32 PhysicalInterface; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Capabilities; /* 04h */ + U32 PhysicalInterface; /* 08h */ } fCONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0, SCSIPortPage0_t, MPI_POINTER pSCSIPortPage0_t; @@ -445,10 +476,11 @@ #define MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE (0x02) #define MPI_SCSIPORTPAGE0_PHY_SIGNAL_LVD (0x03) + typedef struct _CONFIG_PAGE_SCSI_PORT_1 { - fCONFIG_PAGE_HEADER Header; - U32 Configuration; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Configuration; /* 04h */ } fCONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1, SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t; @@ -457,20 +489,21 @@ #define MPI_SCSIPORTPAGE1_CFG_PORT_SCSI_ID_MASK (0x000000FF) #define MPI_SCSIPORTPAGE1_CFG_PORT_RESPONSE_ID_MASK (0xFFFF0000) + typedef struct _MPI_DEVICE_INFO { - U8 Timeout; - U8 SyncFactor; - U16 DeviceFlags; + U8 Timeout; /* 00h */ + U8 SyncFactor; /* 01h */ + U16 DeviceFlags; /* 02h */ } MPI_DEVICE_INFO, MPI_POINTER PTR_MPI_DEVICE_INFO, MpiDeviceInfo_t, MPI_POINTER pMpiDeviceInfo_t; typedef struct _CONFIG_PAGE_SCSI_PORT_2 { - fCONFIG_PAGE_HEADER Header; - U32 PortFlags; - U32 PortSettings; - MPI_DEVICE_INFO DeviceSettings[16]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 PortFlags; /* 04h */ + U32 PortSettings; /* 08h */ + MPI_DEVICE_INFO DeviceSettings[16]; /* 0Ch */ } fCONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2, SCSIPortPage2_t, MPI_POINTER pSCSIPortPage2_t; @@ -492,15 +525,15 @@ #define MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK (0x00000F00) #define MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS (0x00003000) #define MPI_SCSIPORTPAGE2_PORT_NEGO_MASTER_SETTINGS (0x00000000) -#define MPI_SCSIPORTPAGE2_PORT_NONE_MASTER_SETTINGS (0x00000001) -#define MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS (0x00000003) +#define MPI_SCSIPORTPAGE2_PORT_NONE_MASTER_SETTINGS (0x00001000) +#define MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS (0x00003000) -#define MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE (0x00000001) -#define MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE (0x00000002) -#define MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE (0x00000004) -#define MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE (0x00000008) -#define MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE (0x00000010) -#define MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE (0x00000020) +#define MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE (0x0001) +#define MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE (0x0002) +#define MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE (0x0004) +#define MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE (0x0008) +#define MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE (0x0010) +#define MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE (0x0020) /****************************************************************************/ @@ -509,9 +542,9 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_0 { - fCONFIG_PAGE_HEADER Header; - U32 NegotiatedParameters; - U32 Information; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 NegotiatedParameters; /* 04h */ + U32 Information; /* 08h */ } fCONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0, SCSIDevicePage0_t, MPI_POINTER pSCSIDevicePage0_t; @@ -528,16 +561,17 @@ #define MPI_SCSIDEVPAGE0_INFO_PARAMS_NEGOTIATED (0x00000001) + typedef struct _CONFIG_PAGE_SCSI_DEVICE_1 { - fCONFIG_PAGE_HEADER Header; - U32 RequestedParameters; - U32 DomainValidation; - U32 Configuration; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 RequestedParameters; /* 04h */ + U32 Reserved; /* 08h */ + U32 Configuration; /* 0Ch */ } fCONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1, SCSIDevicePage1_t, MPI_POINTER pSCSIDevicePage1_t; -#define MPI_SCSIDEVPAGE1_PAGEVERSION (0x01) +#define MPI_SCSIDEVPAGE1_PAGEVERSION (0x02) #define MPI_SCSIDEVPAGE1_RP_IU (0x00000001) #define MPI_SCSIDEVPAGE1_RP_DT (0x00000002) @@ -553,29 +587,71 @@ #define MPI_SCSIDEVPAGE1_CONF_PPR_ALLOWED (0x00000001) + +typedef struct _CONFIG_PAGE_SCSI_DEVICE_2 +{ + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 DomainValidation; /* 04h */ + U32 ParityPipeSelect; /* 08h */ + U32 DataPipeSelect; /* 0Ch */ +} fCONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2, + SCSIDevicePage2_t, MPI_POINTER pSCSIDevicePage2_t; + +#define MPI_SCSIDEVPAGE2_PAGEVERSION (0x00) + +#define MPI_SCSIDEVPAGE2_DV_ISI_ENABLE (0x00000010) +#define MPI_SCSIDEVPAGE2_DV_SECONDARY_DRIVER_ENABLE (0x00000020) +#define MPI_SCSIDEVPAGE2_DV_SLEW_RATE_CTRL (0x00000380) +#define MPI_SCSIDEVPAGE2_DV_PRIM_DRIVE_STR_CTRL (0x00001C00) +#define MPI_SCSIDEVPAGE2_DV_SECOND_DRIVE_STR_CTRL (0x0000E000) +#define MPI_SCSIDEVPAGE2_DV_XCLKH_ST (0x10000000) +#define MPI_SCSIDEVPAGE2_DV_XCLKS_ST (0x20000000) +#define MPI_SCSIDEVPAGE2_DV_XCLKH_DT (0x40000000) +#define MPI_SCSIDEVPAGE2_DV_XCLKS_DT (0x80000000) + +#define MPI_SCSIDEVPAGE2_PPS_PPS_MASK (0x00000003) + +#define MPI_SCSIDEVPAGE2_DPS_BIT_0_PL_SELECT_MASK (0x00000003) +#define MPI_SCSIDEVPAGE2_DPS_BIT_1_PL_SELECT_MASK (0x0000000C) +#define MPI_SCSIDEVPAGE2_DPS_BIT_2_PL_SELECT_MASK (0x00000030) +#define MPI_SCSIDEVPAGE2_DPS_BIT_3_PL_SELECT_MASK (0x000000C0) +#define MPI_SCSIDEVPAGE2_DPS_BIT_4_PL_SELECT_MASK (0x00000300) +#define MPI_SCSIDEVPAGE2_DPS_BIT_5_PL_SELECT_MASK (0x00000C00) +#define MPI_SCSIDEVPAGE2_DPS_BIT_6_PL_SELECT_MASK (0x00003000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_7_PL_SELECT_MASK (0x0000C000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_8_PL_SELECT_MASK (0x00030000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_9_PL_SELECT_MASK (0x000C0000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_10_PL_SELECT_MASK (0x00300000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_11_PL_SELECT_MASK (0x00C00000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_12_PL_SELECT_MASK (0x03000000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_13_PL_SELECT_MASK (0x0C000000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_14_PL_SELECT_MASK (0x30000000) +#define MPI_SCSIDEVPAGE2_DPS_BIT_15_PL_SELECT_MASK (0xC0000000) + + /****************************************************************************/ /* FC Port Config Pages */ /****************************************************************************/ typedef struct _CONFIG_PAGE_FC_PORT_0 { - fCONFIG_PAGE_HEADER Header; - U32 Flags; - U8 MPIPortNumber; - U8 LinkType; - U8 PortState; - U8 Reserved; - U32 PortIdentifier; - U64 WWNN; - U64 WWPN; - U32 SupportedServiceClass; - U32 SupportedSpeeds; - U32 CurrentSpeed; - U32 MaxFrameSize; - U64 FabricWWNN; - U64 FabricWWPN; - U32 DiscoveredPortsCount; - U32 MaxInitiators; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ + U8 MPIPortNumber; /* 08h */ + U8 LinkType; /* 09h */ + U8 PortState; /* 0Ah */ + U8 Reserved; /* 0Bh */ + U32 PortIdentifier; /* 0Ch */ + U64 WWNN; /* 10h */ + U64 WWPN; /* 18h */ + U32 SupportedServiceClass; /* 20h */ + U32 SupportedSpeeds; /* 24h */ + U32 CurrentSpeed; /* 28h */ + U32 MaxFrameSize; /* 2Ch */ + U64 FabricWWNN; /* 30h */ + U64 FabricWWPN; /* 38h */ + U32 DiscoveredPortsCount; /* 40h */ + U32 MaxInitiators; /* 44h */ } fCONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0, FCPortPage0_t, MPI_POINTER pFCPortPage0_t; @@ -591,12 +667,12 @@ #define MPI_FCPORTPAGE0_FLAGS_ALIAS_WWN_SUPPORTED (0x00000020) #define MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID (0x00000030) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK (0x00000700) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT (0x00000000) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP (0x00000100) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT (0x00000200) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP (0x00000300) -#define MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT (0x00000700) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK (0x00000F00) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT (0x00000000) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT (0x00000100) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP (0x00000200) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT (0x00000400) +#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP (0x00000800) #define MPI_FCPORTPAGE0_LTYPE_RESERVED (0x00) #define MPI_FCPORTPAGE0_LTYPE_OTHER (0x01) @@ -639,14 +715,14 @@ typedef struct _CONFIG_PAGE_FC_PORT_1 { - fCONFIG_PAGE_HEADER Header; - U32 Flags; - U64 NoSEEPROMWWNN; - U64 NoSEEPROMWWPN; - U8 HardALPA; - U8 LinkConfig; - U8 TopologyConfig; - U8 Reserved; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Flags; /* 04h */ + U64 NoSEEPROMWWNN; /* 08h */ + U64 NoSEEPROMWWPN; /* 10h */ + U8 HardALPA; /* 18h */ + U8 LinkConfig; /* 19h */ + U8 TopologyConfig; /* 1Ah */ + U8 Reserved; /* 1Bh */ } fCONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1, FCPortPage1_t, MPI_POINTER pFCPortPage1_t; @@ -679,23 +755,36 @@ typedef struct _CONFIG_PAGE_FC_PORT_2 { - fCONFIG_PAGE_HEADER Header; - U8 NumberActive; - U8 ALPA[126]; - U8 Reserved; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U8 NumberActive; /* 04h */ + U8 ALPA[126]; /* 05h */ + U8 Reserved; /* 83h */ } fCONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2, FCPortPage2_t, MPI_POINTER pFCPortPage2_t; #define MPI_FCPORTPAGE2_PAGEVERSION (0x00) +typedef struct _WWN_FORMAT +{ + U64 WWNN; /* 00h */ + U64 WWPN; /* 08h */ +} WWN_FORMAT, MPI_POINTER PTR_WWN_FORMAT, + WWNFormat, MPI_POINTER pWWNFormat; + +typedef union _FC_PORT_PERSISTENT_PHYSICAL_ID +{ + WWN_FORMAT WWN; + U32 Did; +} FC_PORT_PERSISTENT_PHYSICAL_ID, MPI_POINTER PTR_FC_PORT_PERSISTENT_PHYSICAL_ID, + PersistentPhysicalId_t, MPI_POINTER pPersistentPhysicalId_t; + typedef struct _FC_PORT_PERSISTENT { - U64 WWNN; - U64 WWPN; - U8 TargetID; - U8 Bus; - U16 Flags; + FC_PORT_PERSISTENT_PHYSICAL_ID PhysicalIdentifier; /* 00h */ + U8 TargetID; /* 10h */ + U8 Bus; /* 11h */ + U16 Flags; /* 12h */ } FC_PORT_PERSISTENT, MPI_POINTER PTR_FC_PORT_PERSISTENT, PersistentData_t, MPI_POINTER pPersistentData_t; @@ -704,22 +793,23 @@ #define MPI_PERSISTENT_FLAGS_SCAN_ID (0x0002) #define MPI_PERSISTENT_FLAGS_SCAN_LUNS (0x0004) #define MPI_PERSISTENT_FLAGS_BOOT_DEVICE (0x0008) +#define MPI_PERSISTENT_FLAGS_BY_DID (0x0080) typedef struct _CONFIG_PAGE_FC_PORT_3 { - fCONFIG_PAGE_HEADER Header; - FC_PORT_PERSISTENT Entry[1]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + FC_PORT_PERSISTENT Entry[1]; /* 04h */ } fCONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3, FCPortPage3_t, MPI_POINTER pFCPortPage3_t; -#define MPI_FCPORTPAGE3_PAGEVERSION (0x00) +#define MPI_FCPORTPAGE3_PAGEVERSION (0x01) typedef struct _CONFIG_PAGE_FC_PORT_4 { - fCONFIG_PAGE_HEADER Header; - U32 PortFlags; - U32 PortSettings; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 PortFlags; /* 04h */ + U32 PortSettings; /* 08h */ } fCONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4, FCPortPage4_t, MPI_POINTER pFCPortPage4_t; @@ -738,18 +828,18 @@ typedef struct _CONFIG_PAGE_FC_PORT_5_ALIAS_INFO { - U8 Flags; - U8 AliasAlpa; - U16 Reserved; - U64 AliasWWNN; - U64 AliasWWPN; + U8 Flags; /* 00h */ + U8 AliasAlpa; /* 01h */ + U16 Reserved; /* 02h */ + U64 AliasWWNN; /* 04h */ + U64 AliasWWPN; /* 0Ch */ } fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5_ALIAS_INFO, FcPortPage5AliasInfo_t, MPI_POINTER pFcPortPage5AliasInfo_t; typedef struct _CONFIG_PAGE_FC_PORT_5 { - fCONFIG_PAGE_HEADER Header; - fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO AliasInfo[1]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO AliasInfo[1]; /* 04h */ } fCONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5, FCPortPage5_t, MPI_POINTER pFCPortPage5_t; @@ -761,24 +851,24 @@ typedef struct _CONFIG_PAGE_FC_PORT_6 { - fCONFIG_PAGE_HEADER Header; - U32 Reserved; - U64 TimeSinceReset; - U64 TxFrames; - U64 RxFrames; - U64 TxWords; - U64 RxWords; - U64 LipCount; - U64 NosCount; - U64 ErrorFrames; - U64 DumpedFrames; - U64 LinkFailureCount; - U64 LossOfSyncCount; - U64 LossOfSignalCount; - U64 PrimativeSeqErrCount; - U64 InvalidTxWordCount; - U64 InvalidCrcCount; - U64 FcpInitiatorIoCount; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved; /* 04h */ + U64 TimeSinceReset; /* 08h */ + U64 TxFrames; /* 10h */ + U64 RxFrames; /* 18h */ + U64 TxWords; /* 20h */ + U64 RxWords; /* 28h */ + U64 LipCount; /* 30h */ + U64 NosCount; /* 38h */ + U64 ErrorFrames; /* 40h */ + U64 DumpedFrames; /* 48h */ + U64 LinkFailureCount; /* 50h */ + U64 LossOfSyncCount; /* 58h */ + U64 LossOfSignalCount; /* 60h */ + U64 PrimativeSeqErrCount; /* 68h */ + U64 InvalidTxWordCount; /* 70h */ + U64 InvalidCrcCount; /* 78h */ + U64 FcpInitiatorIoCount; /* 80h */ } fCONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6, FCPortPage6_t, MPI_POINTER pFCPortPage6_t; @@ -787,35 +877,65 @@ typedef struct _CONFIG_PAGE_FC_PORT_7 { - fCONFIG_PAGE_HEADER Header; - U32 Reserved; - U8 PortSymbolicName[256]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved; /* 04h */ + U8 PortSymbolicName[256]; /* 08h */ } fCONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7, FCPortPage7_t, MPI_POINTER pFCPortPage7_t; #define MPI_FCPORTPAGE7_PAGEVERSION (0x00) +typedef struct _CONFIG_PAGE_FC_PORT_8 +{ + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 BitVector[8]; /* 04h */ +} fCONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8, + FCPortPage8_t, MPI_POINTER pFCPortPage8_t; + +#define MPI_FCPORTPAGE8_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_FC_PORT_9 +{ + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved; /* 04h */ + U64 GlobalWWPN; /* 08h */ + U64 GlobalWWNN; /* 10h */ + U32 UnitType; /* 18h */ + U32 PhysicalPortNumber; /* 1Ch */ + U32 NumAttachedNodes; /* 20h */ + U16 IPVersion; /* 24h */ + U16 UDPPortNumber; /* 26h */ + U8 IPAddress[16]; /* 28h */ + U16 Reserved1; /* 38h */ + U16 TopologyDiscoveryFlags; /* 3Ah */ +} fCONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9, + FCPortPage9_t, MPI_POINTER pFCPortPage9_t; + +#define MPI_FCPORTPAGE9_PAGEVERSION (0x00) + + /****************************************************************************/ /* FC Device Config Pages */ /****************************************************************************/ typedef struct _CONFIG_PAGE_FC_DEVICE_0 { - fCONFIG_PAGE_HEADER Header; - U64 WWNN; - U64 WWPN; - U32 PortIdentifier; - U8 Protocol; - U8 Flags; - U16 BBCredit; - U16 MaxRxFrameSize; - U8 Reserved1; - U8 PortNumber; - U8 FcPhLowestVersion; - U8 FcPhHighestVersion; - U8 CurrentTargetID; - U8 CurrentBus; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U64 WWNN; /* 04h */ + U64 WWPN; /* 0Ch */ + U32 PortIdentifier; /* 14h */ + U8 Protocol; /* 18h */ + U8 Flags; /* 19h */ + U16 BBCredit; /* 1Ah */ + U16 MaxRxFrameSize; /* 1Ch */ + U8 Reserved1; /* 1Eh */ + U8 PortNumber; /* 1Fh */ + U8 FcPhLowestVersion; /* 20h */ + U8 FcPhHighestVersion; /* 21h */ + U8 CurrentTargetID; /* 22h */ + U8 CurrentBus; /* 23h */ } fCONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0, FCDevicePage0_t, MPI_POINTER pFCDevicePage0_t; @@ -841,70 +961,75 @@ /* RAID Volume Config Pages */ /****************************************************************************/ -typedef struct _RAIDVOL2_EM_PHYS_ID +typedef struct _RAIDVOL2_IM_PHYS_ID { - U8 TargetID; - U8 Bus; - U8 IocNumber; - U8 PhysDiskNumber; - U8 Reserved[8]; - U8 PhysicalDiskIdentifier[16]; - U8 ProductId[16]; - U8 InfoOffset0; - U8 InfoSize0; - U8 InfoOffset1; - U8 InfoSize1; - U8 Info[32]; -} RAIDVOL2_EM_PHYS_ID, MPI_POINTER PTR_RAIDVOL2_EM_PHYS_ID, - RaidVol2EmPhysicalID_t, MPI_POINTER pRaidVol2EmPhysicalID_t; - -typedef struct _RAIDVOL2_EM_DISK_INFO -{ - U32 DiskStatus; - U32 DeviceSettings; - U16 ErrorCount; - U16 Reserved; - U8 ErrorCdbByte; - U8 ErrorSenseKey; - U8 ErrorASC; - U8 ErrorASCQ; - U16 SmartCount; - U8 SmartASC; - U8 SmartASCQ; -} RAIDVOL2_EM_DISK_INFO, MPI_POINTER PTR_RAIDVOL2_EM_DISK_INFO, - RaidVol2EmDiskInfo_t, MPI_POINTER pRaidVol2EmDiskInfo_t; - -/* RAID Volume 2 EM Physical Disk DiskStatus flags */ - -#define MPI_RAIDVOLPAGE2_PHYS_DISK_PRIMARY (0x00000001) -#define MPI_RAIDVOLPAGE2_PHYS_DISK_SECONDARY (0x00000002) -#define MPI_RAIDVOLPAGE2_PHYS_DISK_HOT_SPARE (0x00000004) -#define MPI_RAIDVOLPAGE2_PHYS_DISK_OUT_OF_SYNC (0x00000008) -#define MPI_RAIDVOLPAGE2_PHYS_DISK_OFFLINE (0x00000010) -#define MPI_RAIDVOLPAGE2_PHYS_DISK_NOT_RESPONDING (0x00000020) - -typedef struct _RAIDVOL2_EM_PHYSICAL_DISK -{ - RAIDVOL2_EM_PHYS_ID Id; - RAIDVOL2_EM_DISK_INFO Info; -} RAIDVOL2_EM_PHYSICAL_DISK, MPI_POINTER PTR_RAIDVOL2_EM_PHYSICAL_DISK, - RaidVol2EmPhysicalDisk_t, MPI_POINTER pRaidVol2EmPhysicalDisk_t; + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 IocNumber; /* 02h */ + U8 PhysDiskNumber; /* 03h */ + U8 Reserved[8]; /* 04h */ + U8 PhysicalDiskIdentifier[16]; /* 0Ch */ + U8 VendorId[8]; /* 1Ch */ + U8 ProductId[16]; /* 24h */ + U8 ProductRevLevel[4]; /* 34h */ + U32 Reserved1; /* 38h */ + U8 Info[32]; /* 3Ch */ +} RAIDVOL2_IM_PHYS_ID, MPI_POINTER PTR_RAIDVOL2_IM_PHYS_ID, + RaidVol2ImPhysicalID_t, MPI_POINTER pRaidVol2ImPhysicalID_t; + +typedef struct _RAIDVOL2_IM_DISK_INFO +{ + U32 DiskStatus; /* 00h */ + U32 DeviceSettings; /* 04h */ + U16 ErrorCount; /* 08h */ + U16 Reserved; /* 0Ah */ + U8 ErrorCdbByte; /* 0Ch */ + U8 ErrorSenseKey; /* 0Dh */ + U8 ErrorASC; /* 0Eh */ + U8 ErrorASCQ; /* 0Fh */ + U16 SmartCount; /* 10h */ + U8 SmartASC; /* 12h */ + U8 SmartASCQ; /* 13h */ +} RAIDVOL2_IM_DISK_INFO, MPI_POINTER PTR_RAIDVOL2_IM_DISK_INFO, + RaidVol2ImDiskInfo_t, MPI_POINTER pRaidVol2ImDiskInfo_t; + +/* RAID Volume 2 IM Physical Disk DiskStatus flags */ + +#define MPI_RVP2_PHYS_DISK_PRIMARY (0x00000001) +#define MPI_RVP2_PHYS_DISK_SECONDARY (0x00000002) +#define MPI_RVP2_PHYS_DISK_HOT_SPARE (0x00000004) +#define MPI_RVP2_PHYS_DISK_OUT_OF_SYNC (0x00000008) +#define MPI_RVP2_PHYS_DISK_STATUS_MASK (0x00000F00) +#define MPI_RVP2_PHYS_DISK_STATUS_ONLINE (0x00000000) +#define MPI_RVP2_PHYS_DISK_STATUS_MISSING (0x00000100) +#define MPI_RVP2_PHYS_DISK_STATUS_NOT_COMPATIBLE (0x00000200) +#define MPI_RVP2_PHYS_DISK_STATUS_FAILED (0x00000300) +#define MPI_RVP2_PHYS_DISK_STATUS_INITIALIZING (0x00000400) +#define MPI_RVP2_PHYS_DISK_STATUS_OFFLINE_REQUESTED (0x00000500) +#define MPI_RVP2_PHYS_DISK_STATUS_OTHER_OFFLINE (0x00000F00) + + +typedef struct _RAIDVOL2_IM_PHYSICAL_DISK +{ + RAIDVOL2_IM_PHYS_ID Id; /* 00h */ + RAIDVOL2_IM_DISK_INFO Info; /* 5Ch */ +} RAIDVOL2_IM_PHYSICAL_DISK, MPI_POINTER PTR_RAIDVOL2_IM_PHYSICAL_DISK, + RaidVol2ImPhysicalDisk_t, MPI_POINTER pRaidVol2ImPhysicalDisk_t; #define MPI_RAIDVOLPAGE2_MAX_DISKS (3) typedef struct _CONFIG_PAGE_RAID_VOL_2 { - fCONFIG_PAGE_HEADER Header; - U32 VolumeStatus; - U32 VolumeSettings; - U32 Reserved; - U64 MaxLba; - U32 BlockSize; - U8 InquirySize; - U8 NumPhysicalDisks; - U16 Reserved1; - U8 InquiryData[56]; - RAIDVOL2_EM_PHYSICAL_DISK EMPhysicalDisk[MPI_RAIDVOLPAGE2_MAX_DISKS]; + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 VolumeStatus; /* 04h */ + U32 VolumeSettings; /* 08h */ + U32 Reserved; /* 0Ch */ + U64 MaxLba; /* 10h */ + U32 BlockSize; /* 18h */ + U8 Reserved1; /* 1Ch */ + U8 NumPhysicalDisks; /* 1Dh */ + U16 Reserved2; /* 1Eh */ + RAIDVOL2_IM_PHYSICAL_DISK IMPhysicalDisk[MPI_RAIDVOLPAGE2_MAX_DISKS]; } fCONFIG_PAGE_RAID_VOL_2, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_2, RaidVolumePage2_t, MPI_POINTER pRaidVolumePage2_t; @@ -922,6 +1047,7 @@ #define MPI_RAIDVOLPAGE2_SETTING_WRITE_CACHING_ENABLE (0x00000001) #define MPI_RAIDVOLPAGE2_SETTING_OFFLINE_ON_SMART (0x00000002) #define MPI_RAIDVOLPAGE2_SETTING_AUTO_CONFIGURE (0x00000004) +#define MPI_RAIDVOLPAGE2_SETTING_USE_DEFAULTS (0x80000000) /****************************************************************************/ @@ -930,10 +1056,10 @@ typedef struct _CONFIG_PAGE_LAN_0 { - ConfigPageHeader_t Header; - U16 TxRxModes; - U16 Reserved; - U32 PacketPrePad; + ConfigPageHeader_t Header; /* 00h */ + U16 TxRxModes; /* 04h */ + U16 Reserved; /* 06h */ + U32 PacketPrePad; /* 08h */ } fCONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0, LANPage0_t, MPI_POINTER pLANPage0_t; @@ -945,20 +1071,20 @@ typedef struct _CONFIG_PAGE_LAN_1 { - ConfigPageHeader_t Header; - U16 Reserved; - U8 CurrentDeviceState; - U8 Reserved1; - U32 MinPacketSize; - U32 MaxPacketSize; - U32 HardwareAddressLow; - U32 HardwareAddressHigh; - U32 MaxWireSpeedLow; - U32 MaxWireSpeedHigh; - U32 BucketsRemaining; - U32 MaxReplySize; - U32 NegWireSpeedHigh; - U32 NegWireSpeedLow; + ConfigPageHeader_t Header; /* 00h */ + U16 Reserved; /* 04h */ + U8 CurrentDeviceState; /* 06h */ + U8 Reserved1; /* 07h */ + U32 MinPacketSize; /* 08h */ + U32 MaxPacketSize; /* 0Ch */ + U32 HardwareAddressLow; /* 10h */ + U32 HardwareAddressHigh; /* 14h */ + U32 MaxWireSpeedLow; /* 18h */ + U32 MaxWireSpeedHigh; /* 1Ch */ + U32 BucketsRemaining; /* 20h */ + U32 MaxReplySize; /* 24h */ + U32 NegWireSpeedHigh; /* 28h */ + U32 NegWireSpeedLow; /* 2Ch */ } fCONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1, LANPage1_t, MPI_POINTER pLANPage1_t; diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/mpi_fc.h linux/drivers/message/fusion/lsi/mpi_fc.h --- v2.4.9/linux/drivers/message/fusion/lsi/mpi_fc.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/mpi_fc.h Fri Sep 7 09:28:38 2001 @@ -6,7 +6,7 @@ * Title: MPI Fibre Channel messages and structures * Creation Date: June 12, 2000 * - * MPI Version: 01.01.05 + * MPI Version: 01.01.07 * * Version History * --------------- @@ -27,6 +27,11 @@ * FC_ABORT_TYPE_EXLINKSEND_REQUEST for FcAbort request. * Added MPI_FC_PRIM_SEND_FLAGS_STOP_SEND. * 02-20-01 01.01.05 Started using MPI_POINTER. + * 03-27-01 01.01.06 Added Flags field to MSG_LINK_SERVICE_BUFFER_POST_REPLY + * and defined MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED. + * Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define. + * Added structure offset comments. + * 04-09-01 01.01.07 Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST. * -------------------------------------------------------------------------- */ @@ -136,7 +141,7 @@ typedef struct _MSG_LINK_SERVICE_RSP_REQUEST { U8 RspFlags; /* 00h */ - U8 Reserved; /* 01h */ + U8 RspLength; /* 01h */ U8 ChainOffset; /* 02h */ U8 Function; /* 03h */ U16 Reserved1; /* 04h */ @@ -224,14 +229,14 @@ typedef struct _MSG_FC_ABORT_REQUEST { - U8 AbortFlags; /* 00h */ - U8 AbortType; /* 01h */ - U8 ChainOffset; /* 02h */ - U8 Function; /* 03h */ - U16 Reserved1; /* 04h */ - U8 Reserved2; /* 06h */ - U8 MsgFlags; /* 07h */ - U32 MsgContext; /* 08h */ + U8 AbortFlags; /* 00h */ + U8 AbortType; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ U32 TransactionContextToAbort; /* 0Ch */ } MSG_FC_ABORT_REQUEST, MPI_POINTER PTR_MSG_FC_ABORT_REQUEST, FcAbortRequest_t, MPI_POINTER pFcAbortRequest_t; @@ -323,6 +328,7 @@ FcPrimitiveSendRequest_t, MPI_POINTER pFcPrimitiveSendRequest_t; #define MPI_FC_PRIM_SEND_FLAGS_PORT_MASK (0x01) +#define MPI_FC_PRIM_SEND_FLAGS_RESET_LINK (0x04) #define MPI_FC_PRIM_SEND_FLAGS_STOP_SEND (0x08) #define MPI_FC_PRIM_SEND_FLAGS_SEND_ONCE (0x10) #define MPI_FC_PRIM_SEND_FLAGS_SEND_AROUND (0x20) diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/mpi_history.txt linux/drivers/message/fusion/lsi/mpi_history.txt --- v2.4.9/linux/drivers/message/fusion/lsi/mpi_history.txt Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/mpi_history.txt Fri Sep 7 09:28:38 2001 @@ -6,22 +6,22 @@ Copyright (c) 2000-2001 LSI Logic Corporation. --------------------------------------- - Header Set Release Version: 01.01.08 - Header Set Release Date: 02-27-01 + Header Set Release Version: 01.01.10 + Header Set Release Date: 04-09-01 --------------------------------------- Filename Current version Prior version ---------- --------------- ------------- - mpi.h 01.01.06 01.01.05 - mpi_ioc.h 01.01.05 01.01.04 - mpi_cnfg.h 01.01.09 01.01.08 - mpi_init.h 01.01.03 01.01.03 - mpi_targ.h 01.01.03 01.01.03 - mpi_fc.h 01.01.05 01.01.05 - mpi_lan.h 01.01.02 01.01.02 - mpi_raid.h 01.01.01 none + mpi.h 01.01.07 01.01.06 + mpi_ioc.h 01.01.07 01.01.06 + mpi_cnfg.h 01.01.11 01.01.10 + mpi_init.h 01.01.05 01.01.04 + mpi_targ.h 01.01.04 01.01.04 + mpi_fc.h 01.01.07 01.01.06 + mpi_lan.h 01.01.03 01.01.03 + mpi_raid.h 01.01.02 01.01.02 mpi_type.h 01.01.02 01.01.02 - mpi_history.txt 01.01.08 01.01.07 + mpi_history.txt 01.01.09 01.01.09 * Date Version Description @@ -51,6 +51,8 @@ * Obsoleted MPI_IOCSTATUS_TARGET_FC_ defines. * 02-27-01 01.01.06 Removed MPI_HOST_INDEX_REGISTER define. * Added function codes for RAID. + * 04-09-01 01.01.07 Added alternate define for MPI_DOORBELL_ACTIVE, + * MPI_DOORBELL_USED, to better match the spec. * -------------------------------------------------------------------------- mpi_ioc.h @@ -76,6 +78,9 @@ * 02-20-01 01.01.04 Started using MPI_POINTER. * 02-27-01 01.01.05 Added event for RAID status change and its event data. * Added IocNumber field to MSG_IOC_FACTS_REPLY. + * 03-27-01 01.01.06 Added defines for ProductId field of MPI_FW_HEADER. + * Added structure offset comments. + * 04-09-01 01.01.07 Added structure EVENT_DATA_EVENT_CHANGE. * -------------------------------------------------------------------------- mpi_cnfg.h @@ -125,6 +130,18 @@ * MPI_CONFIG_PAGETYPE_RAID_VOLUME. * Added definitions and structures for IOC Page 2 and * RAID Volume Page 2. + * 03-27-01 01.01.10 Added CONFIG_PAGE_FC_PORT_8 and CONFIG_PAGE_FC_PORT_9. + * CONFIG_PAGE_FC_PORT_3 now supports persistent by DID. + * Added VendorId and ProductRevLevel fields to + * RAIDVOL2_IM_PHYS_ID struct. + * Modified values for MPI_FCPORTPAGE0_FLAGS_ATTACH_ + * defines to make them compatible to MPI version 1.0. + * Added structure offset comments. + * 04-09-01 01.01.11 Added some new defines for the PageAddress field and + * removed some obsolete ones. + * Added IO Unit Page 3. + * Modified defines for Scsi Port Page 2. + * Modified RAID Volume Pages. * -------------------------------------------------------------------------- mpi_init.h @@ -135,6 +152,8 @@ * 11-02-00 01.01.01 Original release for post 1.0 work * 12-04-00 01.01.02 Added MPI_SCSIIO_CONTROL_NO_DISCONNECT. * 02-20-01 01.01.03 Started using MPI_POINTER. + * 03-27-01 01.01.04 Added structure offset comments. + * 04-10-01 01.01.05 Added new MsgFlag for MSG_SCSI_TASK_MGMT. * -------------------------------------------------------------------------- mpi_targ.h @@ -150,6 +169,7 @@ * 02-20-01 01.01.03 Started using MPI_POINTER. * Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and * MPI_TARGET_FCP_CMD_BUFFER. + * 03-27-01 01.01.04 Added structure offset comments. * -------------------------------------------------------------------------- mpi_fc.h @@ -167,6 +187,11 @@ * FC_ABORT_TYPE_EXLINKSEND_REQUEST for FcAbort request. * Added MPI_FC_PRIM_SEND_FLAGS_STOP_SEND. * 02-20-01 01.01.05 Started using MPI_POINTER. + * 03-27-01 01.01.06 Added Flags field to MSG_LINK_SERVICE_BUFFER_POST_REPLY + * and defined MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED. + * Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define. + * Added structure offset comments. + * 04-09-01 01.01.07 Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST. * -------------------------------------------------------------------------- mpi_lan.h @@ -183,10 +208,12 @@ * to lan private header file * 11-02-00 01.01.01 Original release for post 1.0 work * 02-20-01 01.01.02 Started using MPI_POINTER. + * 03-27-01 01.01.03 Added structure offset comments. * -------------------------------------------------------------------------- mpi_raid.h * 02-27-01 01.01.01 Original release for this file. + * 03-27-01 01.01.02 Added structure offset comments. * -------------------------------------------------------------------------- mpi_type.h @@ -198,17 +225,29 @@ mpi_history.txt Parts list history -Filename 01.01.08 01.01.07 01.01.06 01.01.05 01.01.04 ----------- -------- -------- -------- -------- -------- -mpi.h 01.01.06 01.01.05 01.01.04 01.01.04 01.01.03 -mpi_ioc.h 01.01.05 01.01.04 01.01.03 01.01.03 01.01.03 -mpi_cnfg.h 01.01.09 01.01.08 01.01.07 01.01.06 01.01.05 -mpi_init.h 01.01.03 01.01.03 01.01.02 01.01.02 01.01.02 -mpi_targ.h 01.01.03 01.01.03 01.01.02 01.01.02 01.01.02 -mpi_fc.h 01.01.05 01.01.05 01.01.04 01.01.04 01.01.03 -mpi_lan.h 01.01.02 01.01.02 01.01.01 01.01.01 01.01.01 -mpi_raid.h 01.01.01 -mpi_type.h 01.01.02 01.01.02 01.01.01 01.01.01 01.01.01 +Filename 01.01.10 +---------- -------- +mpi.h 01.01.07 +mpi_ioc.h 01.01.07 +mpi_cnfg.h 01.01.11 +mpi_init.h 01.01.05 +mpi_targ.h 01.01.04 +mpi_fc.h 01.01.07 +mpi_lan.h 01.01.03 +mpi_raid.h 01.01.02 +mpi_type.h 01.01.02 + +Filename 01.01.09 01.01.08 01.01.07 01.01.06 01.01.05 01.01.04 +---------- -------- -------- -------- -------- -------- -------- +mpi.h 01.01.06 01.01.06 01.01.05 01.01.04 01.01.04 01.01.03 +mpi_ioc.h 01.01.06 01.01.05 01.01.04 01.01.03 01.01.03 01.01.03 +mpi_cnfg.h 01.01.10 01.01.09 01.01.08 01.01.07 01.01.06 01.01.05 +mpi_init.h 01.01.04 01.01.03 01.01.03 01.01.02 01.01.02 01.01.02 +mpi_targ.h 01.01.04 01.01.03 01.01.03 01.01.02 01.01.02 01.01.02 +mpi_fc.h 01.01.06 01.01.05 01.01.05 01.01.04 01.01.04 01.01.03 +mpi_lan.h 01.01.03 01.01.02 01.01.02 01.01.01 01.01.01 01.01.01 +mpi_raid.h 01.01.02 01.01.01 +mpi_type.h 01.01.02 01.01.02 01.01.02 01.01.01 01.01.01 01.01.01 Filename 01.01.03 01.01.02 01.01.01 01.00.07 01.00.06 01.00.05 ---------- -------- -------- -------- -------- -------- -------- diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/mpi_init.h linux/drivers/message/fusion/lsi/mpi_init.h --- v2.4.9/linux/drivers/message/fusion/lsi/mpi_init.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/mpi_init.h Fri Sep 7 09:28:38 2001 @@ -6,7 +6,7 @@ * Title: MPI initiator mode messages and structures * Creation Date: June 8, 2000 * - * MPI Version: 01.01.03 + * MPI Version: 01.01.05 * * Version History * --------------- @@ -20,6 +20,8 @@ * 11-02-00 01.01.01 Original release for post 1.0 work. * 12-04-00 01.01.02 Added MPI_SCSIIO_CONTROL_NO_DISCONNECT. * 02-20-01 01.01.03 Started using MPI_POINTER. + * 03-27-01 01.01.04 Added structure offset comments. + * 04-10-01 01.01.05 Added new MsgFlag for MSG_SCSI_TASK_MGMT. * -------------------------------------------------------------------------- */ @@ -39,21 +41,21 @@ typedef struct _MSG_SCSI_IO_REQUEST { - U8 TargetID; - U8 Bus; - U8 ChainOffset; - U8 Function; - U8 CDBLength; - U8 SenseBufferLength; - U8 Reserved; - U8 MsgFlags; - U32 MsgContext; - U8 LUN[8]; - U32 Control; - U8 CDB[16]; - U32 DataLength; - U32 SenseBufferLowAddr; - SGE_IO_UNION SGL; + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Reserved; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 LUN[8]; /* 0Ch */ + U32 Control; /* 14h */ + U8 CDB[16]; /* 18h */ + U32 DataLength; /* 28h */ + U32 SenseBufferLowAddr; /* 2Ch */ + SGE_IO_UNION SGL; /* 30h */ } MSG_SCSI_IO_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO_REQUEST, SCSIIORequest_t, MPI_POINTER pSCSIIORequest_t; @@ -108,22 +110,22 @@ /* SCSIIO reply structure */ typedef struct _MSG_SCSI_IO_REPLY { - U8 TargetID; - U8 Bus; - U8 MsgLength; - U8 Function; - U8 CDBLength; - U8 SenseBufferLength; - U8 Reserved; - U8 MsgFlags; - U32 MsgContext; - U8 SCSIStatus; - U8 SCSIState; - U16 IOCStatus; - U32 IOCLogInfo; - U32 TransferCount; - U32 SenseCount; - U32 ResponseInfo; + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Reserved; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 SCSIStatus; /* 0Ch */ + U8 SCSIState; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferCount; /* 14h */ + U32 SenseCount; /* 18h */ + U32 ResponseInfo; /* 1Ch */ } MSG_SCSI_IO_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_REPLY, SCSIIOReply_t, MPI_POINTER pSCSIIOReply_t; @@ -168,47 +170,49 @@ typedef struct _MSG_SCSI_TASK_MGMT { - U8 TargetID; - U8 Bus; - U8 ChainOffset; - U8 Function; - U8 Reserved; - U8 TaskType; - U8 Reserved1; - U8 MsgFlags; - U32 MsgContext; - U8 LUN[8]; - U32 Reserved2[7]; - U32 TaskMsgContext; + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved; /* 04h */ + U8 TaskType; /* 05h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 LUN[8]; /* 0Ch */ + U32 Reserved2[7]; /* 14h */ + U32 TaskMsgContext; /* 30h */ } MSG_SCSI_TASK_MGMT, MPI_POINTER PTR_SCSI_TASK_MGMT, SCSITaskMgmt_t, MPI_POINTER pSCSITaskMgmt_t; /* TaskType values */ -#define MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x00000001) -#define MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x00000002) -#define MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x00000003) -#define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS (0x00000004) +#define MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) +#define MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02) +#define MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) +#define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS (0x04) /* MsgFlags bits */ -#define MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION (0x00000002) +#define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00) +#define MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION (0x02) +#define MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION (0x04) /* SCSI Task Management Reply */ typedef struct _MSG_SCSI_TASK_MGMT_REPLY { - U8 TargetID; - U8 Bus; - U8 MsgLength; - U8 Function; - U8 Reserved; - U8 TaskType; - U8 Reserved1; - U8 MsgFlags; - U32 MsgContext; - U8 Reserved2[2]; - U16 IOCStatus; - U32 IOCLogInfo; - U32 TerminationCount; + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved; /* 04h */ + U8 TaskType; /* 05h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2[2]; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TerminationCount; /* 14h */ } MSG_SCSI_TASK_MGMT_REPLY, MPI_POINTER PTR_MSG_SCSI_TASK_MGMT_REPLY, SCSITaskMgmtReply_t, MPI_POINTER pSCSITaskMgmtReply_t; diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/mpi_ioc.h linux/drivers/message/fusion/lsi/mpi_ioc.h --- v2.4.9/linux/drivers/message/fusion/lsi/mpi_ioc.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/mpi_ioc.h Fri Sep 7 09:28:38 2001 @@ -3,10 +3,10 @@ * * * Name: MPI_IOC.H - * Title: MPI IOC, Port, Event, FW Load, and ToolBox messages + * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: August 11, 2000 * - * MPI Version: 01.01.05 + * MPI Version: 01.01.07 * * Version History * --------------- @@ -35,6 +35,9 @@ * 02-20-01 01.01.04 Started using MPI_POINTER. * 02-27-01 01.01.05 Added event for RAID status change and its event data. * Added IocNumber field to MSG_IOC_FACTS_REPLY. + * 03-27-01 01.01.06 Added defines for ProductId field of MPI_FW_HEADER. + * Added structure offset comments. + * 04-09-01 01.01.07 Added structure EVENT_DATA_EVENT_CHANGE. * -------------------------------------------------------------------------- */ @@ -54,36 +57,36 @@ typedef struct _MSG_IOC_INIT { - U8 WhoInit; - U8 Reserved; - U8 ChainOffset; - U8 Function; - U8 Flags; - U8 MaxDevices; - U8 MaxBuses; - U8 MsgFlags; - U32 MsgContext; - U16 ReplyFrameSize; - U8 Reserved1[2]; - U32 HostMfaHighAddr; - U32 SenseBufferHighAddr; + U8 WhoInit; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Flags; /* 04h */ + U8 MaxDevices; /* 05h */ + U8 MaxBuses; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 ReplyFrameSize; /* 0Ch */ + U8 Reserved1[2]; /* 0Eh */ + U32 HostMfaHighAddr; /* 10h */ + U32 SenseBufferHighAddr; /* 14h */ } MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT, IOCInit_t, MPI_POINTER pIOCInit_t; typedef struct _MSG_IOC_INIT_REPLY { - U8 WhoInit; - U8 Reserved; - U8 MsgLength; - U8 Function; - U8 Flags; - U8 MaxDevices; - U8 MaxBuses; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved2; - U16 IOCStatus; - U32 IOCLogInfo; + U8 WhoInit; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Flags; /* 04h */ + U8 MaxDevices; /* 05h */ + U8 MaxBuses; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ } MSG_IOC_INIT_REPLY, MPI_POINTER PTR_MSG_IOC_INIT_REPLY, IOCInitReply_t, MPI_POINTER pIOCInitReply_t; @@ -103,12 +106,12 @@ typedef struct _MSG_IOC_FACTS { - U8 Reserved[2]; - U8 ChainOffset; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; + U8 Reserved[2]; /* 00h */ + U8 ChainOffset; /* 01h */ + U8 Function; /* 02h */ + U8 Reserved1[3]; /* 03h */ + U8 MsgFlags; /* 04h */ + U32 MsgContext; /* 08h */ } MSG_IOC_FACTS, MPI_POINTER PTR_IOC_FACTS, IOCFacts_t, MPI_POINTER pIOCFacts_t; @@ -116,34 +119,34 @@ typedef struct _MSG_IOC_FACTS_REPLY { - U16 MsgVersion; - U8 MsgLength; - U8 Function; - U16 Reserved; - U8 IOCNumber; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved2; - U16 IOCStatus; - U32 IOCLogInfo; - U8 MaxChainDepth; - U8 WhoInit; - U8 BlockSize; - U8 Flags; - U16 ReplyQueueDepth; - U16 RequestFrameSize; - U16 FWVersion; - U16 ProductID; - U32 CurrentHostMfaHighAddr; - U16 GlobalCredits; - U8 NumberOfPorts; - U8 EventState; - U32 CurrentSenseBufferHighAddr; - U16 CurReplyFrameSize; - U8 MaxDevices; - U8 MaxBuses; - U32 FWImageSize; - U32 DataImageSize; + U16 MsgVersion; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved; /* 04h */ + U8 IOCNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U8 MaxChainDepth; /* 14h */ + U8 WhoInit; /* 15h */ + U8 BlockSize; /* 16h */ + U8 Flags; /* 17h */ + U16 ReplyQueueDepth; /* 18h */ + U16 RequestFrameSize; /* 1Ah */ + U16 FWVersion; /* 1Ch */ + U16 ProductID; /* 1Eh */ + U32 CurrentHostMfaHighAddr; /* 20h */ + U16 GlobalCredits; /* 24h */ + U8 NumberOfPorts; /* 26h */ + U8 EventState; /* 27h */ + U32 CurrentSenseBufferHighAddr; /* 28h */ + U16 CurReplyFrameSize; /* 2Ch */ + U8 MaxDevices; /* 2Eh */ + U8 MaxBuses; /* 2Fh */ + U32 FWImageSize; /* 30h */ + U32 DataImageSize; /* 34h */ } MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY, IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t; @@ -170,38 +173,38 @@ typedef struct _MSG_PORT_FACTS { - U8 Reserved[2]; - U8 ChainOffset; - U8 Function; - U8 Reserved1[2]; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; + U8 Reserved[2]; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[2]; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ } MSG_PORT_FACTS, MPI_POINTER PTR_MSG_PORT_FACTS, PortFacts_t, MPI_POINTER pPortFacts_t; typedef struct _MSG_PORT_FACTS_REPLY { - U16 Reserved; - U8 MsgLength; - U8 Function; - U16 Reserved1; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved2; - U16 IOCStatus; - U32 IOCLogInfo; - U8 Reserved3; - U8 PortType; - U16 MaxDevices; - U16 PortSCSIID; - U16 ProtocolFlags; - U16 MaxPostedCmdBuffers; - U16 MaxPersistentIDs; - U16 MaxLanBuckets; - U16 Reserved4; - U32 Reserved5; + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U8 Reserved3; /* 14h */ + U8 PortType; /* 15h */ + U16 MaxDevices; /* 16h */ + U16 PortSCSIID; /* 18h */ + U16 ProtocolFlags; /* 1Ah */ + U16 MaxPostedCmdBuffers; /* 1Ch */ + U16 MaxPersistentIDs; /* 1Eh */ + U16 MaxLanBuckets; /* 20h */ + U16 Reserved4; /* 22h */ + U32 Reserved5; /* 24h */ } MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY, PortFactsReply_t, MPI_POINTER pPortFactsReply_t; @@ -226,28 +229,28 @@ typedef struct _MSG_PORT_ENABLE { - U8 Reserved[2]; - U8 ChainOffset; - U8 Function; - U8 Reserved1[2]; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; + U8 Reserved[2]; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[2]; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ } MSG_PORT_ENABLE, MPI_POINTER PTR_MSG_PORT_ENABLE, PortEnable_t, MPI_POINTER pPortEnable_t; typedef struct _MSG_PORT_ENABLE_REPLY { - U8 Reserved[2]; - U8 MsgLength; - U8 Function; - U8 Reserved1[2]; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved2; - U16 IOCStatus; - U32 IOCLogInfo; + U8 Reserved[2]; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[2]; /* 04h */ + U8 PortNumber; /* 05h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ } MSG_PORT_ENABLE_REPLY, MPI_POINTER PTR_MSG_PORT_ENABLE_REPLY, PortEnableReply_t, MPI_POINTER pPortEnableReply_t; @@ -264,13 +267,13 @@ typedef struct _MSG_EVENT_NOTIFY { - U8 Switch; - U8 Reserved; - U8 ChainOffset; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; + U8 Switch; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ } MSG_EVENT_NOTIFY, MPI_POINTER PTR_MSG_EVENT_NOTIFY, EventNotification_t, MPI_POINTER pEventNotification_t; @@ -278,19 +281,19 @@ typedef struct _MSG_EVENT_NOTIFY_REPLY { - U16 EventDataLength; - U8 MsgLength; - U8 Function; - U8 Reserved1[2]; - U8 AckRequired; - U8 MsgFlags; - U32 MsgContext; - U8 Reserved2[2]; - U16 IOCStatus; - U32 IOCLogInfo; - U32 Event; - U32 EventContext; - U32 Data[1]; + U16 EventDataLength; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[2]; /* 04h */ + U8 AckRequired; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2[2]; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 Event; /* 14h */ + U32 EventContext; /* 18h */ + U32 Data[1]; /* 1Ch */ } MSG_EVENT_NOTIFY_REPLY, MPI_POINTER PTR_MSG_EVENT_NOTIFY_REPLY, EventNotificationReply_t, MPI_POINTER pEventNotificationReply_t; @@ -298,28 +301,28 @@ typedef struct _MSG_EVENT_ACK { - U8 Reserved[2]; - U8 ChainOffset; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; - U32 Event; - U32 EventContext; + U8 Reserved[2]; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Event; /* 0Ch */ + U32 EventContext; /* 10h */ } MSG_EVENT_ACK, MPI_POINTER PTR_MSG_EVENT_ACK, EventAck_t, MPI_POINTER pEventAck_t; typedef struct _MSG_EVENT_ACK_REPLY { - U8 Reserved[2]; - U8 MsgLength; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved2; - U16 IOCStatus; - U32 IOCLogInfo; + U8 Reserved[2]; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ } MSG_EVENT_ACK_REPLY, MPI_POINTER PTR_MSG_EVENT_ACK_REPLY, EventAckReply_t, MPI_POINTER pEventAckReply_t; @@ -349,13 +352,23 @@ #define MPI_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) #define MPI_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) -/* SCSI Event data for Port, Bus and Device forms) */ +/* EventChange Event data */ + +typedef struct _EVENT_DATA_EVENT_CHANGE +{ + U8 EventState; /* 00h */ + U8 Reserved; /* 01h */ + U16 Reserved1; /* 02h */ +} EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE, + EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t; + +/* SCSI Event data for Port, Bus and Device forms */ typedef struct _EVENT_DATA_SCSI { - U8 TargetID; - U8 BusPort; - U16 Reserved; + U8 TargetID; /* 00h */ + U8 BusPort; /* 01h */ + U16 Reserved; /* 02h */ } EVENT_DATA_SCSI, MPI_POINTER PTR_EVENT_DATA_SCSI, EventDataScsi_t, MPI_POINTER pEventDataScsi_t; @@ -363,12 +376,12 @@ typedef struct _EVENT_DATA_LINK_STATUS { - U8 State; - U8 Reserved; - U16 Reserved1; - U8 Reserved2; - U8 Port; - U16 Reserved3; + U8 State; /* 00h */ + U8 Reserved; /* 01h */ + U16 Reserved1; /* 02h */ + U8 Reserved2; /* 04h */ + U8 Port; /* 05h */ + U16 Reserved3; /* 06h */ } EVENT_DATA_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_LINK_STATUS, EventDataLinkStatus_t, MPI_POINTER pEventDataLinkStatus_t; @@ -379,13 +392,13 @@ typedef struct _EVENT_DATA_LOOP_STATE { - U8 Character4; - U8 Character3; - U8 Type; - U8 Reserved; - U8 Reserved1; - U8 Port; - U16 Reserved2; + U8 Character4; /* 00h */ + U8 Character3; /* 01h */ + U8 Type; /* 02h */ + U8 Reserved; /* 03h */ + U8 Reserved1; /* 04h */ + U8 Port; /* 05h */ + U16 Reserved2; /* 06h */ } EVENT_DATA_LOOP_STATE, MPI_POINTER PTR_EVENT_DATA_LOOP_STATE, EventDataLoopState_t, MPI_POINTER pEventDataLoopState_t; @@ -397,10 +410,10 @@ typedef struct _EVENT_DATA_LOGOUT { - U32 NPortID; - U8 Reserved; - U8 Port; - U16 Reserved1; + U32 NPortID; /* 00h */ + U8 Reserved; /* 04h */ + U8 Port; /* 05h */ + U16 Reserved1; /* 06h */ } EVENT_DATA_LOGOUT, MPI_POINTER PTR_EVENT_DATA_LOGOUT, EventDataLogout_t, MPI_POINTER pEventDataLogout_t; @@ -408,13 +421,13 @@ typedef struct _EVENT_DATA_RAID_STATUS_CHANGE { - U8 VolumeTargetID; - U8 VolumeBus; - U8 ReasonCode; - U8 PhysDiskNum; - U8 ASC; - U8 ASCQ; - U16 Reserved; + U8 VolumeTargetID; /* 00h */ + U8 VolumeBus; /* 01h */ + U8 ReasonCode; /* 02h */ + U8 PhysDiskNum; /* 03h */ + U8 ASC; /* 04h */ + U8 ASCQ; /* 05h */ + U16 Reserved; /* 06h */ } EVENT_DATA_RAID_STATUS_CHANGE, MPI_POINTER PTR_EVENT_DATA_RAID_STATUS_CHANGE, MpiEventDataRaidStatusChange_t, MPI_POINTER pMpiEventDataRaidStatusChange_t; @@ -441,14 +454,14 @@ typedef struct _MSG_FW_DOWNLOAD { - U8 ImageType; - U8 Reserved; - U8 ChainOffset; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; - SGE_MPI_UNION SGL; + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + SGE_MPI_UNION SGL; /* 0Ch */ } MSG_FW_DOWNLOAD, MPI_POINTER PTR_MSG_FW_DOWNLOAD, FWDownload_t, MPI_POINTER pFWDownload_t; @@ -459,29 +472,29 @@ typedef struct _FWDownloadTCSGE { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 Reserved1; - U32 ImageOffset; - U32 ImageSize; + U8 Reserved; /* 00h */ + U8 ContextSize; /* 01h */ + U8 DetailsLength; /* 02h */ + U8 Flags; /* 03h */ + U32 Reserved1; /* 04h */ + U32 ImageOffset; /* 08h */ + U32 ImageSize; /* 0Ch */ } FW_DOWNLOAD_TCSGE, MPI_POINTER PTR_FW_DOWNLOAD_TCSGE, FWDownloadTCSGE_t, MPI_POINTER pFWDownloadTCSGE_t; /* Firmware Download reply */ typedef struct _MSG_FW_DOWNLOAD_REPLY { - U8 ImageType; - U8 Reserved; - U8 MsgLength; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved2; - U16 IOCStatus; - U32 IOCLogInfo; + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ } MSG_FW_DOWNLOAD_REPLY, MPI_POINTER PTR_MSG_FW_DOWNLOAD_REPLY, FWDownloadReply_t, MPI_POINTER pFWDownloadReply_t; @@ -492,14 +505,14 @@ typedef struct _MSG_FW_UPLOAD { - U8 ImageType; - U8 Reserved; - U8 ChainOffset; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; - SGE_MPI_UNION SGL; + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + SGE_MPI_UNION SGL; /* 0Ch */ } MSG_FW_UPLOAD, MPI_POINTER PTR_MSG_FW_UPLOAD, FWUpload_t, MPI_POINTER pFWUpload_t; @@ -510,74 +523,88 @@ typedef struct _FWUploadTCSGE { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 Reserved1; - U32 ImageOffset; - U32 ImageSize; + U8 Reserved; /* 00h */ + U8 ContextSize; /* 01h */ + U8 DetailsLength; /* 02h */ + U8 Flags; /* 03h */ + U32 Reserved1; /* 04h */ + U32 ImageOffset; /* 08h */ + U32 ImageSize; /* 0Ch */ } FW_UPLOAD_TCSGE, MPI_POINTER PTR_FW_UPLOAD_TCSGE, FWUploadTCSGE_t, MPI_POINTER pFWUploadTCSGE_t; /* Firmware Upload reply */ typedef struct _MSG_FW_UPLOAD_REPLY { - U8 ImageType; - U8 Reserved; - U8 MsgLength; - U8 Function; - U8 Reserved1[3]; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved2; - U16 IOCStatus; - U32 IOCLogInfo; - U32 ActualImageSize; + U8 ImageType; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved1[3]; /* 04h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ActualImageSize; /* 14h */ } MSG_FW_UPLOAD_REPLY, MPI_POINTER PTR_MSG_FW_UPLOAD_REPLY, FWUploadReply_t, MPI_POINTER pFWUploadReply_t; typedef struct _MPI_FW_HEADER { - U32 ArmBranchInstruction0; - U32 Signature0; - U32 Signature1; - U32 Signature2; - U32 ArmBranchInstruction1; - U32 ArmBranchInstruction2; - U32 Reserved; - U32 Checksum; - U16 VendorId; - U16 ProductId; - U16 FwVersion; - U16 Reserved1; - U32 SeqCodeVersion; - U32 ImageSize; - U32 Reserved2; - U32 LoadStartAddress; - U32 IopResetVectorValue; - U32 IopResetRegAddr; - U32 VersionNameWhat; - U8 VersionName[32]; - U32 VendorNameWhat; - U8 VendorName[32]; + U32 ArmBranchInstruction0; /* 00h */ + U32 Signature0; /* 04h */ + U32 Signature1; /* 08h */ + U32 Signature2; /* 0Ch */ + U32 ArmBranchInstruction1; /* 10h */ + U32 ArmBranchInstruction2; /* 14h */ + U32 Reserved; /* 18h */ + U32 Checksum; /* 1Ch */ + U16 VendorId; /* 20h */ + U16 ProductId; /* 22h */ + U16 FwVersion; /* 24h */ + U16 Reserved1; /* 26h */ + U32 SeqCodeVersion; /* 28h */ + U32 ImageSize; /* 2Ch */ + U32 Reserved2; /* 30h */ + U32 LoadStartAddress; /* 34h */ + U32 IopResetVectorValue; /* 38h */ + U32 IopResetRegAddr; /* 3Ch */ + U32 VersionNameWhat; /* 40h */ + U8 VersionName[32]; /* 44h */ + U32 VendorNameWhat; /* 64h */ + U8 VendorName[32]; /* 68h */ } MPI_FW_HEADER, MPI_POINTER PTR_MPI_FW_HEADER, MpiFwHeader_t, MPI_POINTER pMpiFwHeader_t; -#define MPI_FW_HEADER_WHAT_SIGNATURE (0x29232840) +#define MPI_FW_HEADER_WHAT_SIGNATURE (0x29232840) + +/* defines for using the ProductId field */ +#define MPI_FW_HEADER_PID_TYPE_MASK (0xF000) +#define MPI_FW_HEADER_PID_TYPE_SCSI (0x0000) +#define MPI_FW_HEADER_PID_TYPE_FC (0x1000) + +#define MPI_FW_HEADER_PID_FW_VENDOR_MASK (0x0F00) +#define MPI_FW_HEADER_PID_FW_VENDOR_LSI (0x0000) + +#define MPI_FW_HEADER_PID_FAMILY_MASK (0x000F) +#define MPI_FW_HEADER_PID_FAMILY_1030_SCSI (0x0000) +#define MPI_FW_HEADER_PID_FAMILY_909_FC (0x0000) +#define MPI_FW_HEADER_PID_FAMILY_919_FC (0x0001) +#define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002) typedef struct _MPI_DATA_HEADER { - U32 Signature; - U16 FunctionNumber; - U16 Length; - U32 Checksum; - U32 LoadStartAddress; + U32 Signature; /* 00h */ + U16 FunctionNumber; /* 04h */ + U16 Length; /* 06h */ + U32 Checksum; /* 08h */ + U32 LoadStartAddress; /* 0Ch */ } MPI_DATA_HEADER, MPI_POINTER PTR_MPI_DATA_HEADER, MpiDataHeader_t, MPI_POINTER pMpiDataHeader_t; -#define MPI_DATA_HEADER_SIGNATURE (0x43504147) +#define MPI_DATA_HEADER_SIGNATURE (0x43504147) #endif diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/mpi_lan.h linux/drivers/message/fusion/lsi/mpi_lan.h --- v2.4.9/linux/drivers/message/fusion/lsi/mpi_lan.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/mpi_lan.h Fri Sep 7 09:28:38 2001 @@ -6,7 +6,7 @@ * Title: MPI LAN messages and structures * Creation Date: June 30, 2000 * - * MPI Version: 01.01.02 + * MPI Version: 01.01.03 * * Version History * --------------- @@ -26,6 +26,7 @@ * to lan private header file * 11-02-00 01.01.01 Original release for post 1.0 work * 02-20-01 01.01.02 Started using MPI_POINTER. + * 03-27-01 01.01.03 Added structure offset comments. * -------------------------------------------------------------------------- */ @@ -43,32 +44,32 @@ typedef struct _MSG_LAN_SEND_REQUEST { - U16 Reserved; - U8 ChainOffset; - U8 Function; - U16 Reserved2; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; - SGE_MPI_UNION SG_List[1]; + U16 Reserved; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + SGE_MPI_UNION SG_List[1]; /* 0Ch */ } MSG_LAN_SEND_REQUEST, MPI_POINTER PTR_MSG_LAN_SEND_REQUEST, LANSendRequest_t, MPI_POINTER pLANSendRequest_t; typedef struct _MSG_LAN_SEND_REPLY { - U16 Reserved; - U8 MsgLength; - U8 Function; - U8 Reserved2; - U8 NumberOfContexts; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved3; - U16 IOCStatus; - U32 IOCLogInfo; - U32 BufferContext; + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved2; /* 04h */ + U8 NumberOfContexts; /* 05h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 BufferContext; /* 14h */ } MSG_LAN_SEND_REPLY, MPI_POINTER PTR_MSG_LAN_SEND_REPLY, LANSendReply_t, MPI_POINTER pLANSendReply_t; @@ -77,36 +78,36 @@ typedef struct _MSG_LAN_RECEIVE_POST_REQUEST { - U16 Reserved; - U8 ChainOffset; - U8 Function; - U16 Reserved2; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; - U32 BucketCount; - SGE_MPI_UNION SG_List[1]; + U16 Reserved; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 BucketCount; /* 0Ch */ + SGE_MPI_UNION SG_List[1]; /* 10h */ } MSG_LAN_RECEIVE_POST_REQUEST, MPI_POINTER PTR_MSG_LAN_RECEIVE_POST_REQUEST, LANReceivePostRequest_t, MPI_POINTER pLANReceivePostRequest_t; typedef struct _MSG_LAN_RECEIVE_POST_REPLY { - U16 Reserved; - U8 MsgLength; - U8 Function; - U8 Reserved2; - U8 NumberOfContexts; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved3; - U16 IOCStatus; - U32 IOCLogInfo; - U32 BucketsRemaining; - U32 PacketOffset; - U32 PacketLength; - U32 BucketContext[1]; + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 Reserved2; /* 04h */ + U8 NumberOfContexts; /* 05h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 BucketsRemaining; /* 14h */ + U32 PacketOffset; /* 18h */ + U32 PacketLength; /* 1Ch */ + U32 BucketContext[1]; /* 20h */ } MSG_LAN_RECEIVE_POST_REPLY, MPI_POINTER PTR_MSG_LAN_RECEIVE_POST_REPLY, LANReceivePostReply_t, MPI_POINTER pLANReceivePostReply_t; @@ -115,29 +116,29 @@ typedef struct _MSG_LAN_RESET_REQUEST { - U16 Reserved; - U8 ChainOffset; - U8 Function; - U16 Reserved2; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; + U16 Reserved; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 PortNumber; /* 05h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ } MSG_LAN_RESET_REQUEST, MPI_POINTER PTR_MSG_LAN_RESET_REQUEST, LANResetRequest_t, MPI_POINTER pLANResetRequest_t; typedef struct _MSG_LAN_RESET_REPLY { - U16 Reserved; - U8 MsgLength; - U8 Function; - U16 Reserved2; - U8 PortNumber; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved3; - U16 IOCStatus; - U32 IOCLogInfo; + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 PortNumber; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ } MSG_LAN_RESET_REPLY, MPI_POINTER PTR_MSG_LAN_RESET_REPLY, LANResetReply_t, MPI_POINTER pLANResetReply_t; @@ -199,6 +200,12 @@ #define MPI_LAN_DEVICE_STATE_RESET (0x00) #define MPI_LAN_DEVICE_STATE_OPERATIONAL (0x01) + +/****************************************************************************/ +/* LAN Loopback defines */ +/****************************************************************************/ + +#define MPI_LAN_TX_MODES_ENABLE_LOOPBACK_SUPPRESSION (0x01) #endif diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/lsi/mpi_targ.h linux/drivers/message/fusion/lsi/mpi_targ.h --- v2.4.9/linux/drivers/message/fusion/lsi/mpi_targ.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/lsi/mpi_targ.h Fri Sep 7 09:28:38 2001 @@ -6,7 +6,7 @@ * Title: MPI Target mode messages and structures * Creation Date: June 22, 2000 * - * MPI Version: 01.01.03 + * MPI Version: 01.01.04 * * Version History * --------------- @@ -25,6 +25,7 @@ * 02-20-01 01.01.03 Started using MPI_POINTER. * Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and * MPI_TARGET_FCP_CMD_BUFFER. + * 03-27-01 01.01.04 Added structure offset comments. * -------------------------------------------------------------------------- */ @@ -40,9 +41,9 @@ typedef struct _CMD_BUFFER_DESCRIPTOR { - U16 IoIndex; - U16 Reserved; - union + U16 IoIndex; /* 00h */ + U16 Reserved; /* 02h */ + union /* 04h */ { U32 PhysicalAddress32; U64 PhysicalAddress64; @@ -57,16 +58,16 @@ typedef struct _MSG_TARGET_CMD_BUFFER_POST_REQUEST { - U8 BufferPostFlags; - U8 BufferCount; - U8 ChainOffset; - U8 Function; - U8 BufferLength; - U8 Reserved; - U8 Reserved1; - U8 MsgFlags; - U32 MsgContext; - CMD_BUFFER_DESCRIPTOR Buffer[1]; + U8 BufferPostFlags; /* 00h */ + U8 BufferCount; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 BufferLength; /* 04h */ + U8 Reserved; /* 05h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + CMD_BUFFER_DESCRIPTOR Buffer[1]; /* 0Ch */ } MSG_TARGET_CMD_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_REQUEST, TargetCmdBufferPostRequest_t, MPI_POINTER pTargetCmdBufferPostRequest_t; @@ -81,36 +82,36 @@ typedef struct _MSG_TARGET_CMD_BUFFER_POST_REPLY { - U8 BufferPostFlags; - U8 BufferCount; - U8 MsgLength; - U8 Function; - U8 BufferLength; - U8 Reserved; - U8 Reserved1; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved2; - U16 IOCStatus; - U32 IOCLogInfo; + U8 BufferPostFlags; /* 00h */ + U8 BufferCount; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 BufferLength; /* 04h */ + U8 Reserved; /* 05h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved2; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ } MSG_TARGET_CMD_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_REPLY, TargetCmdBufferPostReply_t, MPI_POINTER pTargetCmdBufferPostReply_t; typedef struct _MSG_PRIORITY_CMD_RECEIVED_REPLY { - U16 Reserved; - U8 MsgLength; - U8 Function; - U16 Reserved1; - U8 Reserved2; - U8 MsgFlags; - U32 MsgContext; - U8 PriorityReason; - U8 Reserved3; - U16 IOCStatus; - U32 IOCLogInfo; - U32 ReplyWord; + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 PriorityReason; /* 0Ch */ + U8 Reserved3; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ReplyWord; /* 14h */ } MSG_PRIORITY_CMD_RECEIVED_REPLY, MPI_POINTER PTR_MSG_PRIORITY_CMD_RECEIVED_REPLY, PriorityCommandReceivedReply_t, MPI_POINTER pPriorityCommandReceivedReply_t; @@ -121,17 +122,17 @@ typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY { - U16 Reserved; - U8 MsgLength; - U8 Function; - U16 Reserved1; - U8 Reserved2; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved3; - U16 IOCStatus; - U32 IOCLogInfo; - U32 ReplyWord; + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ReplyWord; /* 14h */ } MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY, MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY, TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t; @@ -139,10 +140,10 @@ typedef struct _MPI_TARGET_FCP_CMD_BUFFER { - U8 FcpLun[8]; - U8 FcpCntl[4]; - U8 FcpCdb[16]; - U32 FcpDl; + U8 FcpLun[8]; /* 00h */ + U8 FcpCntl[4]; /* 08h */ + U8 FcpCdb[16]; /* 0Ch */ + U32 FcpDl; /* 1Ch */ } MPI_TARGET_FCP_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_FCP_CMD_BUFFER, MpiTargetFcpCmdBuffer, MPI_POINTER pMpiTargetFcpCmdBuffer; @@ -150,17 +151,17 @@ typedef struct _MPI_TARGET_SCSI_SPI_CMD_BUFFER { /* SPI L_Q information unit */ - U8 L_QType; - U8 Reserved; - U16 Tag; - U8 LogicalUnitNumber[8]; - U32 DataLength; + U8 L_QType; /* 00h */ + U8 Reserved; /* 01h */ + U16 Tag; /* 02h */ + U8 LogicalUnitNumber[8]; /* 04h */ + U32 DataLength; /* 0Ch */ /* SPI command information unit */ - U8 ReservedFirstByteOfCommandIU; - U8 TaskAttribute; - U8 TaskManagementFlags; - U8 AdditionalCDBLength; - U8 CDB[16]; + U8 ReservedFirstByteOfCommandIU; /* 10h */ + U8 TaskAttribute; /* 11h */ + U8 TaskManagementFlags; /* 12h */ + U8 AdditionalCDBLength; /* 13h */ + U8 CDB[16]; /* 14h */ } MPI_TARGET_SCSI_SPI_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER, MpiTargetScsiSpiCmdBuffer, MPI_POINTER pMpiTargetScsiSpiCmdBuffer; @@ -172,19 +173,19 @@ typedef struct _MSG_TARGET_ASSIST_REQUEST { - U8 StatusCode; - U8 TargetAssistFlags; - U8 ChainOffset; - U8 Function; - U16 QueueTag; - U8 Reserved; - U8 MsgFlags; - U32 MsgContext; - U32 ReplyWord; - U8 LUN[8]; - U32 RelativeOffset; - U32 DataLength; - SGE_IO_UNION SGL[1]; + U8 StatusCode; /* 00h */ + U8 TargetAssistFlags; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 QueueTag; /* 04h */ + U8 Reserved; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 ReplyWord; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 RelativeOffset; /* 18h */ + U32 DataLength; /* 1Ch */ + SGE_IO_UNION SGL[1]; /* 20h */ } MSG_TARGET_ASSIST_REQUEST, MPI_POINTER PTR_MSG_TARGET_ASSIST_REQUEST, TargetAssistRequest_t, MPI_POINTER pTargetAssistRequest_t; @@ -196,18 +197,18 @@ typedef struct _MSG_TARGET_ERROR_REPLY { - U16 Reserved; - U8 MsgLength; - U8 Function; - U16 Reserved1; - U8 Reserved2; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved3; - U16 IOCStatus; - U32 IOCLogInfo; - U32 ReplyWord; - U32 TransferCount; + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ReplyWord; /* 14h */ + U32 TransferCount; /* 18h */ } MSG_TARGET_ERROR_REPLY, MPI_POINTER PTR_MSG_TARGET_ERROR_REPLY, TargetErrorReply_t, MPI_POINTER pTargetErrorReply_t; @@ -218,17 +219,17 @@ typedef struct _MSG_TARGET_STATUS_SEND_REQUEST { - U8 StatusCode; - U8 StatusFlags; - U8 ChainOffset; - U8 Function; - U16 QueueTag; - U8 Reserved; - U8 MsgFlags; - U32 MsgContext; - U32 ReplyWord; - U8 LUN[8]; - SGE_SIMPLE_UNION StatusDataSGE; + U8 StatusCode; /* 00h */ + U8 StatusFlags; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 QueueTag; /* 04h */ + U8 Reserved; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 ReplyWord; /* 0Ch */ + U8 LUN[8]; /* 10h */ + SGE_SIMPLE_UNION StatusDataSGE; /* 18h */ } MSG_TARGET_STATUS_SEND_REQUEST, MPI_POINTER PTR_MSG_TARGET_STATUS_SEND_REQUEST, TargetStatusSendRequest_t, MPI_POINTER pTargetStatusSendRequest_t; @@ -242,16 +243,16 @@ typedef struct _MSG_TARGET_MODE_ABORT_REQUEST { - U8 AbortType; - U8 Reserved; - U8 ChainOffset; - U8 Function; - U16 Reserved1; - U8 Reserved2; - U8 MsgFlags; - U32 MsgContext; - U32 ReplyWord; - U32 MsgContextToAbort; + U8 AbortType; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 ReplyWord; /* 0Ch */ + U32 MsgContextToAbort; /* 10h */ } MSG_TARGET_MODE_ABORT, MPI_POINTER PTR_MSG_TARGET_MODE_ABORT, TargetModeAbort_t, MPI_POINTER pTargetModeAbort_t; @@ -264,17 +265,17 @@ typedef struct _MSG_TARGET_MODE_ABORT_REPLY { - U16 Reserved; - U8 MsgLength; - U8 Function; - U16 Reserved1; - U8 Reserved2; - U8 MsgFlags; - U32 MsgContext; - U16 Reserved3; - U16 IOCStatus; - U32 IOCLogInfo; - U32 AbortCount; + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 AbortCount; /* 14h */ } MSG_TARGET_MODE_ABORT_REPLY, MPI_POINTER PTR_MSG_TARGET_MODE_ABORT_REPLY, TargetModeAbortReply_t, MPI_POINTER pTargetModeAbortReply_t; diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/mptbase.c linux/drivers/message/fusion/mptbase.c --- v2.4.9/linux/drivers/message/fusion/mptbase.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/mptbase.c Fri Sep 7 09:28:38 2001 @@ -42,7 +42,7 @@ * Originally By: Steven J. Ralston * (mailto:Steve.Ralston@lsil.com) * - * $Id: mptbase.c,v 1.47 2001/03/22 10:32:23 sralston Exp $ + * $Id: mptbase.c,v 1.53.4.1 2001/08/24 20:07:05 sralston Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -130,6 +130,8 @@ const char **mpt_ScsiOpcodesPtr = NULL; int mpt_ASCQ_TableSz = 0; +#define WHOINIT_UNKNOWN 0xAA + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Private data... @@ -143,6 +145,8 @@ static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS]; /* Event handler lookup table */ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; + /* Reset handler lookup table */ +static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; static int FusionInitCalled = 0; static int mpt_base_index = -1; @@ -154,25 +158,27 @@ static void mpt_interrupt(int irq, void *bus_id, struct pt_regs *r); static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); +static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason); static int mpt_adapter_install(struct pci_dev *pdev); static void mpt_detect_929_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev); -static void mpt_adapter_disable(MPT_ADAPTER *ioc); +static void mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup); static void mpt_adapter_dispose(MPT_ADAPTER *ioc); static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); +static int MakeIocReady(MPT_ADAPTER *ioc, int force); static u32 GetIocState(MPT_ADAPTER *ioc, int cooked); static int GetIocFacts(MPT_ADAPTER *ioc); -static int GetPortFacts(MPT_ADAPTER *ioc); +static int GetPortFacts(MPT_ADAPTER *ioc, int portnum); static int SendIocInit(MPT_ADAPTER *ioc); static int SendPortEnable(MPT_ADAPTER *ioc, int portnum); -static int mpt_fc9x9_reset(MPT_ADAPTER *ioc); -static int KickStart(MPT_ADAPTER *ioc); +static int mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore); +static int KickStart(MPT_ADAPTER *ioc, int ignore); static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type); static int PrimeIocFifos(MPT_ADAPTER *ioc); -static int HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply); -static int WaitForDoorbellAck(MPT_ADAPTER *ioc); -static int WaitForDoorbellInt(MPT_ADAPTER *ioc); -static int WaitForDoorbellReply(MPT_ADAPTER *ioc); +static int HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait); +static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong); +static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong); +static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong); static int GetLanConfigPages(MPT_ADAPTER *ioc); static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); @@ -192,6 +198,7 @@ static struct proc_dir_entry *procmpt_root_dir = NULL; int fusion_init(void); +static void fusion_exit(void); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* 20000207 -sralston @@ -586,6 +593,45 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** + * mpt_reset_register - Register protocol-specific IOC reset handler. + * @cb_idx: previously registered (via mpt_register) callback handle + * @reset_func: reset function + * + * This routine can be called by one or more protocol-specific drivers + * if/when they choose to be notified of IOC resets. + * + * Returns 0 for success. + */ +int +mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func) +{ + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + return -1; + + MptResetHandlers[cb_idx] = reset_func; + return 0; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_reset_deregister - Deregister protocol-specific IOC reset handler. + * @cb_idx: previously registered callback handle + * + * Each protocol-specific driver should call this routine + * when it does not (or can no longer) handle IOC reset handling, + * or when it's module is unloaded. + */ +void +mpt_reset_deregister(int cb_idx) +{ + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + return; + + MptResetHandlers[cb_idx] = NULL; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024) * allocated per MPT adapter. * @handle: Handle of registered MPT protocol driver @@ -723,13 +769,29 @@ iocp = mpt_adapters[iocid]; if (iocp != NULL) { - u8 *req_as_bytes; - int i; + u8 *req_as_bytes; + u32 ioc_raw_state; + int i; + + /* YIKES! We already know something is amiss. + * Do upfront check on IOC state. + */ + ioc_raw_state = GetIocState(iocp, 0); + if ((ioc_raw_state & MPI_DOORBELL_ACTIVE) || + ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL)) { + printk(KERN_WARNING MYNAM ": %s: Bad IOC state (%08x) WARNING!\n", + iocp->name, ioc_raw_state); + if ((r = mpt_do_ioc_recovery(iocp, MPT_HOSTEVENT_IOC_RECOVER)) != 0) { + printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n", + r, iocp->name); + return r; + } + } /* - * Emulate what mpt_put_msg_frame() does /wrt to sanity - * setting cb_idx/req_idx. But ONLY if this request - * is in proper (pre-alloc'd) request buffer range... + * Emulate what mpt_put_msg_frame() does /wrt to sanity + * setting cb_idx/req_idx. But ONLY if this request + * is in proper (pre-alloc'd) request buffer range... */ i = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req); if (reqBytes >= 12 && i >= 0 && i < iocp->req_depth) { @@ -738,17 +800,15 @@ mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; } - /* Make sure there are no doorbells */ + /* Make sure there are no doorbells */ CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); CHIPREG_WRITE32(&iocp->chip->Doorbell, ((MPI_FUNCTION_HANDSHAKE<chip->IntStatus, 0); - if ((r = WaitForDoorbellAck(iocp)) < 0) + if ((r = WaitForDoorbellAck(iocp, 1)) < 0) { return -2; + } - /* Send request via doorbell handshake */ + /* Send request via doorbell handshake */ req_as_bytes = (u8 *) req; for (i = 0; i < reqBytes/4; i++) { u32 word; @@ -770,15 +831,19 @@ (req_as_bytes[(i*4) + 2] << 16) | (req_as_bytes[(i*4) + 3] << 24)); CHIPREG_WRITE32(&iocp->chip->Doorbell, word); - if ((r = WaitForDoorbellAck(iocp)) < 0) { + if ((r = WaitForDoorbellAck(iocp, 1)) < 0) { r = -3; break; } } - /* Make sure there are no doorbells */ - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); + if ((r = WaitForDoorbellInt(iocp, 2)) >= 0) + r = 0; + else + r = -4; + /* Make sure there are no doorbells */ + CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); } return r; @@ -849,9 +914,8 @@ if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) && -#if 0 - /* FIXME! FC919 */ (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) && +#if 0 /* FIXME! C103x family */ (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) && (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) && @@ -897,8 +961,10 @@ printk(KERN_INFO MYNAM ": %d MPT adapter%s found, %d installed.\n", found, (found==1) ? "" : "s", count); - if (count == 0) + if (!found || !count) { + fusion_exit(); return -ENODEV; + } #ifdef CONFIG_PROC_FS if (procmpt_create() != 0) @@ -962,12 +1028,9 @@ unsigned long port; u32 msize; u32 psize; - u32 ioc_state; int i; int r = -ENODEV; - int cntdn; int len; - int statefault = 0; ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_KERNEL); if (ioc == NULL) { @@ -980,7 +1043,7 @@ ioc->pcidev = pdev; - /* Find lookup slot. GRRRR... */ + /* Find lookup slot. */ for (i=0; i < MPT_MAX_ADAPTERS; i++) { if (mpt_adapters[i] == NULL) { ioc->id = i; /* Assign adapter unique id (lookup) */ @@ -997,11 +1060,11 @@ port = psize = 0; for (i=0; i < DEVICE_COUNT_RESOURCE; i++) { if (pdev->PCI_BASEADDR_FLAGS(i) & PCI_BASE_ADDRESS_SPACE_IO) { - /* Get I/O space! */ + /* Get I/O space! */ port = pdev->PCI_BASEADDR_START(i); psize = PCI_BASEADDR_SIZE(pdev,i); } else { - /* Get memmap */ + /* Get memmap */ mem_phys = pdev->PCI_BASEADDR_START(i); msize = PCI_BASEADDR_SIZE(pdev,i); break; @@ -1021,7 +1084,7 @@ mem = NULL; if (! PortIo) { - /* Get logical ptr for PciMem0 space */ + /* Get logical ptr for PciMem0 space */ /*mem = ioremap(mem_phys, msize);*/ mem = ioremap(mem_phys, 0x100); if (mem == NULL) { @@ -1051,11 +1114,11 @@ ioc->chip_type = FC929; ioc->prod_name = "LSIFC929"; } -#if 0 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) { - ioc->chip_type = C1030; + ioc->chip_type = FC919; ioc->prod_name = "LSIFC919"; } +#if 0 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_53C1030) { ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; @@ -1070,10 +1133,10 @@ Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); spin_lock_init(&ioc->FreeQlock); - /* Disable all! */ + /* Disable all! */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); ioc->active = 0; + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); ioc->pci_irq = -1; if (pdev->irq) { @@ -1094,7 +1157,7 @@ dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); } - /* tack onto tail of our MPT adapter list */ + /* tack onto tail of our MPT adapter list */ Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER); /* Set lookup ptr. */ @@ -1106,115 +1169,168 @@ if (ioc->chip_type == FC929) mpt_detect_929_bound_ports(ioc, pdev); - /* Get current [raw] IOC state */ - ioc_state = GetIocState(ioc, 0); - dhsprintk((KERN_INFO MYNAM ": %s initial [raw] state=%08x\n", ioc->name, ioc_state)); + if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) { + printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", + ioc->name, r); + } - /* - * Check to see if IOC got left/stuck in doorbell handshake - * grip of death. If so, hard reset the IOC. - */ - if (ioc_state & MPI_DOORBELL_ACTIVE) { - statefault = 1; - printk(KERN_WARNING MYNAM ": %s: Uh-oh, unexpected doorbell active!\n", + return r; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_do_ioc_recovery - Initialize or recover MPT adapter. + * @ioc: Pointer to MPT adapter structure + * @reason: Event word / reason + * + * This routine performs all the steps necessary to bring the IOC + * to a OPERATIONAL state. + * + * This routine also pre-fetches the LAN MAC address of a Fibre Channel + * MPT adapter. + * + * Returns 0 for success. + */ +static int +mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason) +{ + int hard_reset_done = 0; + int alt_ioc_ready = 0; + int hard; + int r; + int i; + int handlers; + + printk(KERN_INFO MYNAM ": Initiating %s %s\n", + ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); + + /* Disable reply interrupts */ + CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); + ioc->active = 0; + /* NOTE: Access to IOC's request FreeQ is now blocked! */ + +// FIXME? Cleanup all IOC requests here! (or below?) +// But watch out for event associated request? + + hard = HardReset; + if (ioc->alt_ioc && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) + hard = 0; + + if ((hard_reset_done = MakeIocReady(ioc, hard)) < 0) { + printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", ioc->name); + return -1; } - /* - * Check to see if IOC is in FAULT state. - * If so, hard reset the IOC. - */ - if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { - statefault = 2; - printk(KERN_WARNING MYNAM ": %s: Uh-oh, IOC is in FAULT state!!!\n", - ioc->name); - printk(KERN_WARNING " FAULT code = %04xh\n", - ioc_state & MPI_DOORBELL_DATA_MASK); +// NEW! +#if 0 // Kiss-of-death!?! + if (ioc->alt_ioc) { +// Grrr... Hold off any alt-IOC interrupts (and events) while +// handshaking to IOC, needed because? + /* Disable alt-IOC's reply interrupts for a bit ... */ + alt_ioc_intmask = CHIPREG_READ32(&ioc->alt_ioc->chip->IntMask); + CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); + ioc->alt_ioc->active = 0; + /* NOTE: Access to alt-IOC's request FreeQ is now blocked! */ } +#endif - if (HardReset || statefault) { - if ((r = KickStart(ioc)) != 0) { - r = -ENODEV; - goto ioc_up_fail; - } + if (hard_reset_done && ioc->alt_ioc) { + if ((r = MakeIocReady(ioc->alt_ioc, 0)) == 0) + alt_ioc_ready = 1; + else + printk(KERN_WARNING MYNAM ": alt-%s: (%d) Not ready WARNING!\n", + ioc->alt_ioc->name, r); + } + + if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { + /* Get IOC facts! */ + if ((r = GetIocFacts(ioc)) != 0) + return -2; + MptDisplayIocCapabilities(ioc); } /* - * Loop here waiting for IOC to come READY. - */ - i = 0; - cntdn = HZ * 10; - while ((ioc_state = GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { - if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { - /* - * BIOS or previous driver load left IOC in OP state. - * Reset messaging FIFOs. - */ - dprintk((KERN_WARNING MYNAM ": %s: Sending IOC msg unit reset!\n", ioc->name)); - if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)) != 0) { - printk(KERN_ERR MYNAM ": %s: ERROR - IOC msg unit reset failed!\n", ioc->name); - r = -ENODEV; - goto ioc_up_fail; - } - } else if (ioc_state == MPI_IOC_STATE_RESET) { - /* - * Something is wrong. Try to get IOC back - * to a known state. - */ - dprintk((KERN_WARNING MYNAM ": %s: Sending IO unit reset!\n", ioc->name)); - if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET)) != 0) { - printk(KERN_ERR MYNAM ": %s: ERROR - IO unit reset failed!\n", ioc->name); - r = -ENODEV; - goto ioc_up_fail; + * Call each currently registered protocol IOC reset handler + * with pre-reset indication. + * NOTE: If we're doing _IOC_BRINGUP, there can be no + * MptResetHandlers[] registered yet. + */ + if (hard_reset_done) { + r = handlers = 0; + for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) { + if (MptResetHandlers[i]) { + dprintk((KERN_INFO MYNAM ": %s: Calling IOC pre_reset handler #%d\n", + ioc->name, i)); + r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_PRE_RESET); + handlers++; + + if (alt_ioc_ready) { + dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC pre_reset handler #%d\n", + ioc->alt_ioc->name, i)); + r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_PRE_RESET); + handlers++; + } } } + /* FIXME? Examine results here? */ + } - i++; cntdn--; - if (!cntdn) { - printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n", - ioc->name, (i+5)/HZ); - r = -ETIME; - goto ioc_up_fail; - } + // May need to check/upload firmware & data here! - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + if ((r = SendIocInit(ioc)) != 0) + return -3; +// NEW! + if (alt_ioc_ready) { + if ((r = SendIocInit(ioc->alt_ioc)) != 0) { + alt_ioc_ready = 0; + printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n", + ioc->alt_ioc->name, r); + } } - if (statefault) { - printk(KERN_WARNING MYNAM ": %s: Whew! Recovered from %s\n", - ioc->name, statefault==1 ? "stuck handshake" : "IOC FAULT"); + /* + * Call each currently registered protocol IOC reset handler + * with post-reset indication. + * NOTE: If we're doing _IOC_BRINGUP, there can be no + * MptResetHandlers[] registered yet. + */ + if (hard_reset_done) { + r = handlers = 0; + for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) { + if (MptResetHandlers[i]) { + dprintk((KERN_INFO MYNAM ": %s: Calling IOC post_reset handler #%d\n", + ioc->name, i)); + r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_POST_RESET); + handlers++; + + if (alt_ioc_ready) { + dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC post_reset handler #%d\n", + ioc->alt_ioc->name, i)); + r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_POST_RESET); + handlers++; + } + } + } + /* FIXME? Examine results here? */ } - /* Enable! (reply interrupt) */ - CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); - ioc->active = 1; - - /* Get IOC facts! (first time, ioc->facts0 and ioc->pfacts0) */ - if ((r = GetIocFacts(ioc)) != 0) - goto ioc_up_fail; - - /* Does IocFacts.EventState need any looking at / attention here? */ - - if ((r = SendIocInit(ioc)) != 0) - goto ioc_up_fail; - /* - * Prime reply & request queues! - * (mucho alloc's) + * Prime reply & request queues! + * (mucho alloc's) */ if ((r = PrimeIocFifos(ioc)) != 0) - goto ioc_up_fail; - - /* Get IOC facts again! (2nd time, ioc->factsN and ioc->pfactsN) */ - if ((r = GetIocFacts(ioc)) != 0) - goto ioc_up_fail; - - /* Does IocFacts.EventState need any looking at / attention here? */ + return -4; +// NEW! + if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) { + printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", + ioc->alt_ioc->name, r); + } - MptDisplayIocCapabilities(ioc); +// FIXME! Cleanup all IOC (and alt-IOC?) requests here! - if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { + if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && + (ioc->lan_cnfg_page0.Header.PageLength == 0)) { /* * Pre-fetch the ports LAN MAC address! * (LANPage1_t stuff) @@ -1229,19 +1345,34 @@ #endif } + /* Enable! (reply interrupt) */ + CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); + ioc->active = 1; + +// NEW! +#if 0 // Kiss-of-death!?! + if (alt_ioc_ready && (r==0)) { + /* (re)Enable alt-IOC! (reply interrupt) */ + dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", + ioc->alt_ioc->name)); + CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); + ioc->alt_ioc->active = 1; + } +#endif + /* NEW! 20010120 -sralston * Enable MPT base driver management of EventNotification * and EventAck handling. */ - (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */ + if (!ioc->facts.EventState) + (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */ +// NEW! +// FIXME!?! +// if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) { +// (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */ +// } return 0; - -ioc_up_fail: - //Q_DEL_ITEM(ioc); - //mpt_adapter_dispose(ioc); - mpt_adapter_disable(ioc); - return r; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1297,20 +1428,25 @@ /* * mpt_adapter_disable - Disable misbehaving MPT adapter. * @this: Pointer to MPT adapter structure + * @free: Free up alloc'd reply, request, etc. */ static void -mpt_adapter_disable(MPT_ADAPTER *this) +mpt_adapter_disable(MPT_ADAPTER *this, int freeup) { if (this != NULL) { int sz; + /* Disable the FW */ + if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET) != 0) + (void) KickStart(this, 1); + /* Disable adapter interrupts! */ CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); + this->active = 0; /* Clear any lingering interrupt */ CHIPREG_WRITE32(&this->chip->IntStatus, 0); - this->active = 0; - if (this->reply_alloc != NULL) { + if (freeup && this->reply_alloc != NULL) { sz = (this->reply_sz * this->reply_depth) + 128; pci_free_consistent(this->pcidev, sz, this->reply_alloc, this->reply_alloc_dma); @@ -1319,7 +1455,7 @@ this->alloc_total -= sz; } - if (this->req_alloc != NULL) { + if (freeup && this->req_alloc != NULL) { sz = (this->req_sz * this->req_depth) + 128; /* * Rounding UP to nearest 4-kB boundary here... @@ -1332,7 +1468,7 @@ this->alloc_total -= sz; } - if (this->sense_buf_pool != NULL) { + if (freeup && this->sense_buf_pool != NULL) { sz = (this->req_depth * 256); pci_free_consistent(this->pcidev, sz, this->sense_buf_pool, this->sense_buf_pool_dma); @@ -1359,7 +1495,7 @@ sz_first = this->alloc_total; - mpt_adapter_disable(this); + mpt_adapter_disable(this, 1); if (this->pci_irq != -1) { free_irq(this->pci_irq, this); @@ -1401,17 +1537,17 @@ printk("%s: ", ioc->prod_name+3); printk("Capabilities={"); - if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { + if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { printk("Initiator"); i++; } - if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { + if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { printk("%sTarget", i ? "," : ""); i++; } - if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { + if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { printk("%sLAN", i ? "," : ""); i++; } @@ -1420,7 +1556,7 @@ /* * This would probably evoke more questions than it's worth */ - if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { + if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { printk("%sLogBusAddr", i ? "," : ""); i++; } @@ -1431,6 +1567,113 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* + * MakeIocReady - Get IOC to a READY state, using KickStart if needed. + * @ioc: Pointer to MPT_ADAPTER structure + * @kick: Force hard KickStart of IOC + * + * Returns 0 for already-READY, 1 for hard reset success, + * else negative for failure. + */ +static int +MakeIocReady(MPT_ADAPTER *ioc, int force) +{ + u32 ioc_state; + int statefault = 0; + int cntdn; + int hard_reset_done = 0; + int r; + int i; + + /* Get current [raw] IOC state */ + ioc_state = GetIocState(ioc, 0); + dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state)); + + /* + * Check to see if IOC got left/stuck in doorbell handshake + * grip of death. If so, hard reset the IOC. + */ + if (ioc_state & MPI_DOORBELL_ACTIVE) { + statefault = 1; + printk(KERN_WARNING MYNAM ": %s: Uh-oh, unexpected doorbell active!\n", + ioc->name); + } + + /* Is it already READY? */ + if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) + return 0; + + /* + * Check to see if IOC is in FAULT state. + */ + if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { + statefault = 2; + printk(KERN_WARNING MYNAM ": %s: Uh-oh, IOC is in FAULT state!!!\n", + ioc->name); + printk(KERN_WARNING " FAULT code = %04xh\n", + ioc_state & MPI_DOORBELL_DATA_MASK); + } + + /* + * Hmmm... Did it get left operational? + */ + if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) { + statefault = 3; + dprintk((KERN_WARNING MYNAM ": %s: Hmmm... IOC operational unexpected\n", + ioc->name)); + } + + hard_reset_done = KickStart(ioc, statefault||force); + if (hard_reset_done < 0) + return -1; + + /* + * Loop here waiting for IOC to come READY. + */ + i = 0; + cntdn = HZ * 15; + while ((ioc_state = GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { + if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { + /* + * BIOS or previous driver load left IOC in OP state. + * Reset messaging FIFOs. + */ + if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)) != 0) { + printk(KERN_ERR MYNAM ": %s: ERROR - IOC msg unit reset failed!\n", ioc->name); + return -2; + } + } else if (ioc_state == MPI_IOC_STATE_RESET) { + /* + * Something is wrong. Try to get IOC back + * to a known state. + */ + if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET)) != 0) { + printk(KERN_ERR MYNAM ": %s: ERROR - IO unit reset failed!\n", ioc->name); + return -3; + } + } + + i++; cntdn--; + if (!cntdn) { + printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n", + ioc->name, (i+5)/HZ); + return -ETIME; + } + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + + if (statefault < 3) { + printk(KERN_WARNING MYNAM ": %s: Whew! Recovered from %s\n", + ioc->name, + statefault==1 ? "stuck handshake" : "IOC FAULT"); + } + + return hard_reset_done; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* * GetIocState - Get the current state of a MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @cooked: Request raw or cooked IOC state @@ -1471,7 +1714,7 @@ int reply_sz; u32 status; - /* IOC *must* NOT be in RESET state! */ + /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n", ioc->name, @@ -1479,44 +1722,45 @@ return -44; } - facts = &ioc->facts0; - /* Nth (2,3,...) time thru? (been here, done that?) */ - if (ioc->facts0.Function == MPI_FUNCTION_IOC_FACTS) { - facts = &ioc->factsN; - } + facts = &ioc->facts; - /* Destination (reply area)... */ + /* Destination (reply area)... */ reply_sz = sizeof(*facts); memset(facts, 0, reply_sz); - /* Request area (get_facts on the stack right now!) */ + /* Request area (get_facts on the stack right now!) */ req_sz = sizeof(get_facts); memset(&get_facts, 0, req_sz); get_facts.Function = MPI_FUNCTION_IOC_FACTS; - /* Assert: All other get_facts fields are zero! */ + /* Assert: All other get_facts fields are zero! */ - dprintk((KERN_INFO MYNAM ": %s: Sending IocFacts%s request\n", - ioc->name, facts == &ioc->facts0 ? "0" : "N" )); + dprintk((KERN_INFO MYNAM ": %s: Sending get IocFacts request\n", ioc->name)); /* No non-zero fields in the get_facts request are greater than * 1 byte in size, so we can just fire it off as is. */ r = HandShakeReqAndReply(ioc, req_sz, (u32*)&get_facts, - reply_sz, (u16*)facts); + reply_sz, (u16*)facts, 3); if (r != 0) return r; /* - * Now byte swap the necessary fields before any further - * inspection of reply contents. + * Now byte swap (GRRR) the necessary fields before any further + * inspection of reply contents. * - * But need to do some sanity checks on MsgLength (byte) field - * to make sure we don't zero IOC's req_sz! + * But need to do some sanity checks on MsgLength (byte) field + * to make sure we don't zero IOC's req_sz! */ /* Did we get a valid reply? */ if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) { + /* + * If not been here, done that, save off first WhoInit value + */ + if (ioc->FirstWhoInit == WHOINIT_UNKNOWN) + ioc->FirstWhoInit = facts->WhoInit; + facts->MsgVersion = le16_to_cpu(facts->MsgVersion); facts->MsgContext = le32_to_cpu(facts->MsgContext); facts->IOCStatus = le16_to_cpu(facts->IOCStatus); @@ -1537,9 +1781,9 @@ le16_to_cpu(facts->CurReplyFrameSize); /* - * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx - * Older MPI-1.00.xx struct had 13 dwords, and enlarged - * to 14 in MPI-1.01.0x. + * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx + * Older MPI-1.00.xx struct had 13 dwords, and enlarged + * to 14 in MPI-1.01.0x. */ if (facts->MsgLength >= sizeof(IOCFactsReply_t)/sizeof(u32) && facts->MsgVersion > 0x0100) { facts->FWImageSize = le32_to_cpu(facts->FWImageSize); @@ -1548,7 +1792,7 @@ if (facts->RequestFrameSize) { /* - * Set values for this IOC's REQUEST queue size & depth... + * Set values for this IOC's REQUEST queue size & depth... */ ioc->req_sz = MIN(MPT_REQ_SIZE, facts->RequestFrameSize * 4); @@ -1582,8 +1826,8 @@ dprintk((KERN_INFO MYNAM ": %s: req_sz =%3d, req_depth =%4d\n", ioc->name, ioc->req_sz, ioc->req_depth)); - /* Get port facts! */ - if ( (r = GetPortFacts(ioc)) != 0 ) + /* Get port facts! */ + if ( (r = GetPortFacts(ioc, 0)) != 0 ) return r; } else { printk(KERN_ERR MYNAM ": %s: ERROR - Invalid IOC facts reply!\n", @@ -1598,11 +1842,12 @@ /* * GetPortFacts - Send PortFacts request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure + * @portnum: Port number * * Returns 0 for success, non-zero for failure. */ static int -GetPortFacts(MPT_ADAPTER *ioc) +GetPortFacts(MPT_ADAPTER *ioc, int portnum) { PortFacts_t get_pfacts; PortFactsReply_t *pfacts; @@ -1610,7 +1855,7 @@ int req_sz; int reply_sz; - /* IOC *must* NOT be in RESET state! */ + /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n", ioc->name, @@ -1618,31 +1863,28 @@ return -4; } - pfacts = &ioc->pfacts0; - /* Nth (2,3,...) time thru? (been here, done that?) */ - if (ioc->pfacts0.Function == MPI_FUNCTION_PORT_FACTS) { - pfacts = &ioc->pfactsN; - } + pfacts = &ioc->pfacts[portnum]; - /* Destination (reply area)... */ + /* Destination (reply area)... */ reply_sz = sizeof(*pfacts); memset(pfacts, 0, reply_sz); - /* Request area (get_pfacts on the stack right now!) */ + /* Request area (get_pfacts on the stack right now!) */ req_sz = sizeof(get_pfacts); memset(&get_pfacts, 0, req_sz); get_pfacts.Function = MPI_FUNCTION_PORT_FACTS; - /* Assert: All other get_pfacts fields are zero! */ + get_pfacts.PortNumber = portnum; + /* Assert: All other get_pfacts fields are zero! */ - dprintk((KERN_INFO MYNAM ": %s: Sending PortFacts%s request\n", - ioc->name, pfacts == &ioc->pfacts0 ? "0" : "N" )); + dprintk((KERN_INFO MYNAM ": %s: Sending get PortFacts(%d) request\n", + ioc->name, portnum)); /* No non-zero fields in the get_pfacts request are greater than * 1 byte in size, so we can just fire it off as is. */ i = HandShakeReqAndReply(ioc, req_sz, (u32*)&get_pfacts, - reply_sz, (u16*)pfacts); + reply_sz, (u16*)pfacts, 3); if (i != 0) return i; @@ -1702,7 +1944,7 @@ dprintk((KERN_INFO MYNAM ": %s: Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init)); r = HandShakeReqAndReply(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, - sizeof(MPIDefaultReply_t), (u16*)&init_reply); + sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10); if (r != 0) return r; @@ -1775,7 +2017,7 @@ ioc->name, portnum, &port_enable)); i = HandShakeReqAndReply(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf); + reply_sz, (u16*)&reply_buf, 65); if (i != 0) return i; @@ -1790,24 +2032,28 @@ /* * KickStart - Perform hard reset of MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure + * @force: Force hard reset * * This routine places MPT adapter in diagnostic mode via the * WriteSequence register, and then performs a hard reset of adapter * via the Diagnostic register. * - * Returns 0 for success, non-zero for failure. + * Returns 0 for soft reset success, 1 for hard reset success, + * else a negative value for failure. */ static int -KickStart(MPT_ADAPTER *ioc) +KickStart(MPT_ADAPTER *ioc, int force) { - int r; + int hard_reset_done = 0; u32 ioc_state; int cnt = 0; dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); - if (ioc->chip_type == FC909) { - r = mpt_fc9x9_reset(ioc); + hard_reset_done = mpt_fc9x9_reset(ioc, force); +#if 0 + if (ioc->chip_type == FC909 || ioc->chip-type == FC919) { + hard_reset_done = mpt_fc9x9_reset(ioc, force); } else if (ioc->chip_type == FC929) { unsigned long delta; @@ -1815,15 +2061,12 @@ dprintk((KERN_INFO MYNAM ": %s: 929 KickStart, last=%ld, delta = %ld\n", ioc->name, ioc->last_kickstart, delta)); if ((ioc->sod_reset == 0) || (delta >= 10*HZ)) - r = mpt_fc9x9_reset(ioc); + hard_reset_done = mpt_fc9x9_reset(ioc, ignore); else { dprintk((KERN_INFO MYNAM ": %s: Skipping KickStart (delta=%ld)!\n", ioc->name, delta)); return 0; } - /* TODO! Add FC919! - } else if (ioc->chip_type == FC919) { - */ /* TODO! Add C1030! } else if (ioc->chip_type == C1030) { */ @@ -1832,9 +2075,10 @@ ioc->name, ioc->chip_type); return -5; } +#endif - if (r != 0) - return -r; + if (hard_reset_done < 0) + return hard_reset_done; dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset successful\n", ioc->name)); @@ -1843,7 +2087,7 @@ if ((ioc_state = GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) { dprintk((KERN_INFO MYNAM ": %s: KickStart successful! (cnt=%d)\n", ioc->name, cnt)); - return 0; + return hard_reset_done; } /* udelay(10000) ? */ current->state = TASK_INTERRUPTIBLE; @@ -1867,52 +2111,112 @@ * Returns 0 for success, non-zero for failure. */ static int -mpt_fc9x9_reset(MPT_ADAPTER *ioc) +mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore) { - u32 diagval; + u32 diag0val; + int hard_reset_done = 0; /* Use "Diagnostic reset" method! (only thing available!) */ - /* - * Extra read to handle 909 B.0 chip problem with reset - * logic not finishing the RAM access before hard reset hits. - * (? comment taken from NT SYMMPI source) - */ - (void) CHIPREG_READ32(&ioc->chip->Fubar); + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +#ifdef MPT_DEBUG +{ + u32 diag1val = 0; + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + dprintk((KERN_INFO MYNAM ": %s: DBG1: diag0=%08x, diag1=%08x\n", + ioc->name, diag0val, diag1val)); +} +#endif + if (diag0val & MPI_DIAG_DRWE) { + dprintk((KERN_INFO MYNAM ": %s: DiagWriteEn bit already set\n", + ioc->name)); + } else { + /* Write magic sequence to WriteSequence register */ + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); + dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence [spot#1]\n", + ioc->name)); + } - /* - * Write magic sequence to WriteSequence register. - * But, send 0x0F first to insure a reset to the beginning of the sequence. - */ - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_KEY_VALUE_MASK); + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +#ifdef MPT_DEBUG +{ + u32 diag1val = 0; + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + dprintk((KERN_INFO MYNAM ": %s: DbG2: diag0=%08x, diag1=%08x\n", + ioc->name, diag0val, diag1val)); +} +#endif + if (!ignore && (diag0val & MPI_DIAG_RESET_HISTORY)) { + dprintk((KERN_INFO MYNAM ": %s: Skipping due to ResetHistory bit set!\n", + ioc->name)); + } else { + /* + * Now hit the reset bit in the Diagnostic register + * (THE BIG HAMMER!) + */ + CHIPREG_WRITE32(&ioc->chip->Diagnostic, MPI_DIAG_RESET_ADAPTER); + hard_reset_done = 1; + dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset performed\n", + ioc->name)); - /* Now write magic sequence */ - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); - dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence\n", - ioc->name)); + /* want udelay(100) */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); - /* Now hit the reset bit in the Diagnostic register */ - CHIPREG_WRITE32(&ioc->chip->Diagnostic, MPI_DIAG_RESET_ADAPTER); + /* Write magic sequence to WriteSequence register */ + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); + dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence [spot#2]\n", + ioc->name)); + } - udelay(100); + /* Clear RESET_HISTORY bit! */ + CHIPREG_WRITE32(&ioc->chip->Diagnostic, 0x0); - if ((diagval = CHIPREG_READ32(&ioc->chip->Diagnostic)) & - (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_DISABLE_ARM)) { - printk(KERN_ERR MYNAM ": %s: ERROR - Diagnostic reset FAILED!\n", + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +#ifdef MPT_DEBUG +{ + u32 diag1val = 0; + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + dprintk((KERN_INFO MYNAM ": %s: DbG3: diag0=%08x, diag1=%08x\n", + ioc->name, diag0val, diag1val)); +} +#endif + if (diag0val & MPI_DIAG_RESET_HISTORY) { + printk(KERN_WARNING MYNAM ": %s: WARNING - ResetHistory bit failed to clear!\n", ioc->name); - return -9; } - /* TODO! - * Cleanup all event stuff for this IOC; - * re-issue EventNotification request if needed. + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +#ifdef MPT_DEBUG +{ + u32 diag1val = 0; + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + dprintk((KERN_INFO MYNAM ": %s: DbG4: diag0=%08x, diag1=%08x\n", + ioc->name, diag0val, diag1val)); +} +#endif + if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) { + printk(KERN_ERR MYNAM ": %s: ERROR - Diagnostic reset FAILED! (%02xh)\n", + ioc->name, diag0val); + return -3; + } + + /* + * Reset flag that says we've enabled event notification */ - if (ioc->factsN.Function) - ioc->factsN.EventState = 0; + ioc->facts.EventState = 0; /* NEW! 20010220 -sralston * Try to avoid redundant resets of the 929. @@ -1924,7 +2228,7 @@ ioc->alt_ioc->last_kickstart = ioc->last_kickstart; } - return 0; + return hard_reset_done; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1943,18 +2247,18 @@ { int r; - printk(KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n", - ioc->name, reset_type); + dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n", + ioc->name, reset_type)); CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<factsN.Function) - ioc->factsN.EventState = 0; + if (ioc->facts.Function) + ioc->facts.EventState = 0; return 0; } @@ -2125,6 +2429,7 @@ * @req: Pointer to MPT request frame * @replyBytes: Expected size of the reply in bytes * @u16reply: Pointer to area where reply should be written + * @maxwait: Max wait time for a reply (in seconds) * * NOTES: It is the callers responsibility to byte-swap fields in the * request which are greater than 1 byte in size. It is also the @@ -2134,7 +2439,7 @@ * Returns 0 for success, non-zero for failure. */ static int -HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply) +HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait) { MPIDefaultReply_t *mptReply; int failcnt = 0; @@ -2160,7 +2465,7 @@ /* * Wait for IOC's doorbell handshake int */ - if ((t = WaitForDoorbellInt(ioc)) < 0) + if ((t = WaitForDoorbellInt(ioc, 2)) < 0) failcnt++; dhsprintk((KERN_INFO MYNAM ": %s: HandShake request start, WaitCnt=%d%s\n", @@ -2172,7 +2477,7 @@ * our handshake request. */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - if (!failcnt && (t = WaitForDoorbellAck(ioc)) < 0) + if (!failcnt && (t = WaitForDoorbellAck(ioc, 2)) < 0) failcnt++; if (!failcnt) { @@ -2190,7 +2495,7 @@ (req_as_bytes[(i*4) + 3] << 24)); CHIPREG_WRITE32(&ioc->chip->Doorbell, word); - if ((t = WaitForDoorbellAck(ioc)) < 0) + if ((t = WaitForDoorbellAck(ioc, 2)) < 0) failcnt++; } @@ -2203,7 +2508,7 @@ /* * Wait for completion of doorbell handshake reply from the IOC */ - if (!failcnt && (t = WaitForDoorbellReply(ioc)) < 0) + if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait)) < 0) failcnt++; /* @@ -2223,16 +2528,17 @@ * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit * in it's IntStatus register. * @ioc: Pointer to MPT_ADAPTER structure + * @howlong: How long to wait (in seconds) * - * This routine waits (up to ~30 seconds max) for IOC doorbell + * This routine waits (up to ~2 seconds max) for IOC doorbell * handshake ACKnowledge. * * Returns a negative value on failure, else wait loop count. */ static int -WaitForDoorbellAck(MPT_ADAPTER *ioc) +WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong) { - int cntdn = HZ * 30; /* ~30 seconds */ + int cntdn = HZ * howlong; int count = 0; u32 intstat; @@ -2261,15 +2567,16 @@ * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit * in it's IntStatus register. * @ioc: Pointer to MPT_ADAPTER structure + * @howlong: How long to wait (in seconds) * - * This routine waits (up to ~30 seconds max) for IOC doorbell interrupt. + * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt. * * Returns a negative value on failure, else wait loop count. */ static int -WaitForDoorbellInt(MPT_ADAPTER *ioc) +WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong) { - int cntdn = HZ * 30; /* ~30 seconds */ + int cntdn = HZ * howlong; int count = 0; u32 intstat; @@ -2297,6 +2604,7 @@ /* * WaitForDoorbellReply - Wait for and capture a IOC handshake reply. * @ioc: Pointer to MPT_ADAPTER structure + * @howlong: How long to wait (in seconds) * * This routine polls the IOC for a handshake reply, 16 bits at a time. * Reply is cached to IOC private area large enough to hold a maximum @@ -2305,7 +2613,7 @@ * Returns a negative value on failure, else size of reply in WORDS. */ static int -WaitForDoorbellReply(MPT_ADAPTER *ioc) +WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong) { int u16cnt = 0; int failcnt = 0; @@ -2319,11 +2627,18 @@ /* * Get first two u16's so we can look at IOC's intended reply MsgLength */ - for (u16cnt=0; !failcnt && u16cnt < 2; u16cnt++) { - if ((t = WaitForDoorbellInt(ioc)) < 0) - failcnt++; - hs_reply[u16cnt] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); + u16cnt=0; + if ((t = WaitForDoorbellInt(ioc, howlong)) < 0) { + failcnt++; + } else { + hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + if ((t = WaitForDoorbellInt(ioc, 2)) < 0) + failcnt++; + else { + hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + } } dhsprintk((KERN_INFO MYNAM ": %s: First handshake reply word=%08x%s\n", @@ -2335,7 +2650,7 @@ * reply 16 bits at a time. */ for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) { - if ((t = WaitForDoorbellInt(ioc)) < 0) + if ((t = WaitForDoorbellInt(ioc, 2)) < 0) failcnt++; hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); /* don't overflow our IOC hs_reply[] buffer! */ @@ -2344,7 +2659,7 @@ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); } - if (!failcnt && (t = WaitForDoorbellInt(ioc)) < 0) + if (!failcnt && (t = WaitForDoorbellInt(ioc, 2)) < 0) failcnt++; CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); @@ -2428,7 +2743,7 @@ ioc->name)); i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req, - reply_sz, (u16*)&config_reply); + reply_sz, (u16*)&config_reply, 3); pci_unmap_single(ioc->pcidev, page0_dma, data_sz, PCI_DMA_FROMDEVICE); if (i != 0) return i; @@ -2472,7 +2787,7 @@ ioc->name)); i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req, - reply_sz, (u16*)&config_reply); + reply_sz, (u16*)&config_reply, 3); pci_unmap_single(ioc->pcidev, page1_dma, data_sz, PCI_DMA_FROMDEVICE); if (i != 0) return i; @@ -2564,7 +2879,6 @@ return len; \ } - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries. @@ -2653,6 +2967,9 @@ { MPT_ADAPTER *ioc; + if (!procmpt_root_dir) + return 0; + /* * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt" * (single level) to multi level (e.g. "driver/message/fusion") @@ -2685,6 +3002,7 @@ if (atomic_read((atomic_t *)&procmpt_root_dir->count) == 0) { remove_proc_entry(MPT_PROCFS_MPTBASEDIR, 0); + procmpt_root_dir = NULL; return 0; } @@ -2724,7 +3042,7 @@ // Too verbose! // mpt_print_ioc_facts(ioc, out, &more, 0); - mpt_print_ioc_summary(ioc, out, &more, 0); + mpt_print_ioc_summary(ioc, out, &more, 0, 1); out += more; if ((out-page) >= count) { @@ -2784,15 +3102,15 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc) { - if ((ioc->facts0.FWVersion & 0xF000) == 0xE000) + if ((ioc->facts.FWVersion & 0xF000) == 0xE000) sprintf(buf, " (Exp %02d%02d)", - (ioc->facts0.FWVersion & 0x0F00) >> 8, /* Month */ - ioc->facts0.FWVersion & 0x001F); /* Day */ + (ioc->facts.FWVersion & 0x0F00) >> 8, /* Month */ + ioc->facts.FWVersion & 0x001F); /* Day */ else buf[0] ='\0'; /* insider hack! */ - if (ioc->facts0.FWVersion & 0x0080) { + if (ioc->facts.FWVersion & 0x0080) { strcat(buf, " [MDBG]"); } } @@ -2804,17 +3122,17 @@ * @buffer: Pointer to buffer where IOC summary info should be written * @size: Pointer to number of bytes we wrote (set by this routine) * @len: Offset at which to start writing in buffer + * @showlan: Display LAN stuff? * * This routine writes (english readable) ASCII text, which represents * a summary of IOC information, to a buffer. */ void -mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len) +mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan) { char expVer[32]; int y; - mpt_get_fw_exp_ver(expVer, ioc); /* @@ -2824,17 +3142,20 @@ ioc->name, ioc->prod_name, MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */ - ioc->facts0.FWVersion, + ioc->facts.FWVersion, expVer, - ioc->facts0.NumberOfPorts, + ioc->facts.NumberOfPorts, ioc->req_depth); - if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { + if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X", a[5], a[4], a[3], a[2], a[1], a[0]); } + if (ioc->pci_irq < 100) + y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq); + if (!ioc->active) y += sprintf(buffer+len+y, " (disabled)"); @@ -2861,32 +3182,34 @@ char iocName[16]; int sz; int y; - + int p; mpt_get_fw_exp_ver(expVer, ioc); strcpy(iocName, ioc->name); y = sprintf(buffer+len, "%s:\n", iocName); - y += sprintf(buffer+len+y, " ProductID = 0x%04x\n", ioc->facts0.ProductID); - y += sprintf(buffer+len+y, " PortNumber = %d (of %d)\n", - ioc->pfacts0.PortNumber+1, - ioc->facts0.NumberOfPorts); - if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { - u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - y += sprintf(buffer+len+y, " LanAddr = 0x%02x:%02x:%02x:%02x:%02x:%02x\n", - a[5], a[4], a[3], a[2], a[1], a[0]); + y += sprintf(buffer+len+y, " ProductID = 0x%04x\n", ioc->facts.ProductID); + for (p=0; p < ioc->facts.NumberOfPorts; p++) { + y += sprintf(buffer+len+y, " PortNumber = %d (of %d)\n", + p+1, + ioc->facts.NumberOfPorts); + if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { + u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; + y += sprintf(buffer+len+y, " LanAddr = 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + a[5], a[4], a[3], a[2], a[1], a[0]); + } } - y += sprintf(buffer+len+y, " FWVersion = 0x%04x%s\n", ioc->facts0.FWVersion, expVer); - y += sprintf(buffer+len+y, " MsgVersion = 0x%04x\n", ioc->facts0.MsgVersion); - y += sprintf(buffer+len+y, " WhoInit = 0x%02x\n", ioc->facts0.WhoInit); - y += sprintf(buffer+len+y, " EventState = 0x%02x\n", ioc->facts0.EventState); + y += sprintf(buffer+len+y, " FWVersion = 0x%04x%s\n", ioc->facts.FWVersion, expVer); + y += sprintf(buffer+len+y, " MsgVersion = 0x%04x\n", ioc->facts.MsgVersion); + y += sprintf(buffer+len+y, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit); + y += sprintf(buffer+len+y, " EventState = 0x%02x\n", ioc->facts.EventState); y += sprintf(buffer+len+y, " CurrentHostMfaHighAddr = 0x%08x\n", - ioc->facts0.CurrentHostMfaHighAddr); + ioc->facts.CurrentHostMfaHighAddr); y += sprintf(buffer+len+y, " CurrentSenseBufferHighAddr = 0x%08x\n", - ioc->facts0.CurrentSenseBufferHighAddr); - y += sprintf(buffer+len+y, " MaxChainDepth = 0x%02x frames\n", ioc->facts0.MaxChainDepth); - y += sprintf(buffer+len+y, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts0.BlockSize); + ioc->facts.CurrentSenseBufferHighAddr); + y += sprintf(buffer+len+y, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth); + y += sprintf(buffer+len+y, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); y += sprintf(buffer+len+y, " RequestFrames @ 0x%p (Dma @ 0x%08x)\n", ioc->req_alloc, ioc->req_alloc_dma); @@ -2898,8 +3221,8 @@ y += sprintf(buffer+len+y, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n", ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz); y += sprintf(buffer+len+y, " {MaxReqSz=%d} {MaxReqDepth=%d}\n", - 4*ioc->facts0.RequestFrameSize, - ioc->facts0.GlobalCredits); + 4*ioc->facts.RequestFrameSize, + ioc->facts.GlobalCredits); y += sprintf(buffer+len+y, " ReplyFrames @ 0x%p (Dma @ 0x%08x)\n", ioc->reply_alloc, ioc->reply_alloc_dma); @@ -2907,8 +3230,8 @@ y += sprintf(buffer+len+y, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); y += sprintf(buffer+len+y, " {MaxRepSz=%d} {MaxRepDepth=%d}\n", - ioc->factsN.CurReplyFrameSize, - ioc->facts0.ReplyQueueDepth); + ioc->facts.CurReplyFrameSize, + ioc->facts.ReplyQueueDepth); *size = y; } @@ -3045,8 +3368,8 @@ /* CHECKME! What if evState unexpectedly says OFF (0)? */ /* Update EventState field in cached IocFacts */ - if (ioc->factsN.Function) { - ioc->factsN.EventState = evState; + if (ioc->facts.Function) { + ioc->facts.EventState = evState; } } break; @@ -3182,6 +3505,9 @@ case MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED: desc = "Not synchronized to signal or still negotiating (possible cable problem)"; break; + case MPI_IOCLOGINFO_FC_LINK_CRC_ERROR: + desc = "CRC check detected error on received frame"; + break; } printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x): SubCl={%s}", @@ -3259,6 +3585,8 @@ EXPORT_SYMBOL(mpt_deregister); EXPORT_SYMBOL(mpt_event_register); EXPORT_SYMBOL(mpt_event_deregister); +EXPORT_SYMBOL(mpt_reset_register); +EXPORT_SYMBOL(mpt_reset_deregister); EXPORT_SYMBOL(mpt_get_msg_frame); EXPORT_SYMBOL(mpt_put_msg_frame); EXPORT_SYMBOL(mpt_free_msg_frame); @@ -3299,6 +3627,7 @@ MptCallbacks[i] = NULL; MptDriverClass[i] = MPTUNKNOWN_DRIVER; MptEvHandlers[i] = NULL; + MptResetHandlers[i] = NULL; } /* NEW! 20010120 -sralston @@ -3323,22 +3652,8 @@ static void fusion_exit(void) { MPT_ADAPTER *this; - int i; dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n")); - - /* - * Paranoia; disable interrupts on all MPT adapters. - */ - for (i=0; ichip->IntMask, 0xFFFFFFFF); - /* Clear any lingering interrupt */ - CHIPREG_WRITE32(&this->chip->IntStatus, 0); - this->active = 0; - } - } /* Whups? 20010120 -sralston * Moved this *above* removal of all MptAdapters! diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/mptbase.h linux/drivers/message/fusion/mptbase.h --- v2.4.9/linux/drivers/message/fusion/mptbase.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/mptbase.h Fri Sep 7 09:28:38 2001 @@ -12,7 +12,7 @@ * Originally By: Steven J. Ralston * (mailto:Steve.Ralston@lsil.com) * - * $Id: mptbase.h,v 1.38 2001/03/22 10:54:30 sralston Exp $ + * $Id: mptbase.h,v 1.46.2.2.2.1 2001/08/24 20:07:05 sralston Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -63,8 +63,8 @@ #include "lsi/mpi_init.h" /* SCSI Host (initiator) protocol support */ #include "lsi/mpi_lan.h" /* LAN over FC protocol support */ -//#include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */ -//#include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */ +#include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */ +#include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */ #include "lsi/fc_log.h" /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -77,9 +77,8 @@ #define COPYRIGHT "Copyright (c) 1999-2001 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "1.00.11" -#define MPT_LINUX_VERSION_EXP "0.09.66-EXP" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-1.00.11" +#define MPT_LINUX_VERSION_COMMON "1.02.01" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-1.02.01" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -91,6 +90,7 @@ */ #define MPT_MAX_ADAPTERS 16 #define MPT_MAX_PROTOCOL_DRIVERS 8 +#define MPT_MAX_FC_DEVICES 255 #define MPT_MISCDEV_BASENAME "mptctl" #define MPT_MISCDEV_PATHNAME "/dev/" MPT_MISCDEV_BASENAME @@ -262,8 +262,6 @@ struct _MPT_ADAPTER *back; int id; /* Unique adapter id {0,1,2,...} */ int pci_irq; - IOCFactsReply_t facts0; - IOCFactsReply_t factsN; char name[32]; /* "iocN" */ char *prod_name; /* "LSIFC9x9" */ u32 mem_phys; /* == f4020000 (mmap) */ @@ -275,10 +273,6 @@ int active; int sod_reset; unsigned long last_kickstart; - PortFactsReply_t pfacts0; - PortFactsReply_t pfactsN; - LANPage0_t lan_cnfg_page0; - LANPage1_t lan_cnfg_page1; u8 *reply_alloc; /* Reply frames alloc ptr */ dma_addr_t reply_alloc_dma; MPT_FRAME_HDR *reply_frames; /* Reply frames - rounded up! */ @@ -292,24 +286,30 @@ dma_addr_t req_frames_dma; int req_depth; int req_sz; - spinlock_t FreeQlock; MPT_Q_TRACKER FreeQ; + spinlock_t FreeQlock; /* Pool of SCSI sense buffers for commands coming from * the SCSI mid-layer. We have one 256 byte sense buffer * for each REQ entry. */ u8 *sense_buf_pool; dma_addr_t sense_buf_pool_dma; - int hs_reply_idx; - u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)]; - u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)]; struct pci_dev *pcidev; - struct _MPT_ADAPTER *alt_ioc; /* atomic_t userCnt; */ u8 *memmap; int mtrr_reg; struct Scsi_Host *sh; struct proc_dir_entry *ioc_dentry; + struct _MPT_ADAPTER *alt_ioc; + int hs_reply_idx; + u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)]; + u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)]; + IOCFactsReply_t facts; + PortFactsReply_t pfacts[2]; + LANPage0_t lan_cnfg_page0; + LANPage1_t lan_cnfg_page1; + u8 FirstWhoInit; + u8 pad1[3]; } MPT_ADAPTER; @@ -324,26 +324,25 @@ * 0 = not Ok ... */ typedef int (*MPT_CALLBACK)(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); -typedef int (*MPT_EVHANDLER)(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply); -/* - * Fibre Channel (SCSI) target device... - */ -typedef struct _FC_TARGET { - struct _FC_TARGET *forw; - struct _FC_TARGET *back; - int bus_id; - int target_id; - int lun_exists[32]; - u8 inquiry_data[36]; - u8 last_sense[256]; -} FC_TARGET; - -typedef struct _FCDEV_TRACKER { - FC_TARGET *head; - FC_TARGET *tail; -} FCDEV_TRACKER; +typedef int (*MPT_EVHANDLER)(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply); +typedef int (*MPT_RESETHANDLER)(MPT_ADAPTER *ioc, int reset_phase); +/* reset_phase defs */ +#define MPT_IOC_PRE_RESET 0 +#define MPT_IOC_POST_RESET 1 + +/* + * Invent MPT host event (super-set of MPI Events) + * Fitted to 1030's 64-byte [max] request frame size + */ +typedef struct _MPT_HOST_EVENT { + EventNotificationReply_t MpiEvent; /* 8 32-bit words! */ + u32 pad[6]; + void *next; +} MPT_HOST_EVENT; +#define MPT_HOSTEVENT_IOC_BRINGUP 0x91 +#define MPT_HOSTEVENT_IOC_RECOVER 0x92 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -523,6 +522,8 @@ extern void mpt_deregister(int cb_idx); extern int mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc); extern void mpt_event_deregister(int cb_idx); +extern int mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func); +extern void mpt_reset_deregister(int cb_idx); extern int mpt_register_ascqops_strings(/*ASCQ_Table_t*/void *ascqTable, int ascqtbl_sz, const char **opsTable); extern void mpt_deregister_ascqops_strings(void); extern MPT_FRAME_HDR *mpt_get_msg_frame(int handle, int iocid); @@ -532,7 +533,7 @@ extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); extern MPT_ADAPTER *mpt_adapter_find_first(void); extern MPT_ADAPTER *mpt_adapter_find_next(MPT_ADAPTER *prev); -extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len); +extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); extern void mpt_print_ioc_facts(MPT_ADAPTER *ioc, char *buf, int *size, int len); /* diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/mptctl.c linux/drivers/message/fusion/mptctl.c --- v2.4.9/linux/drivers/message/fusion/mptctl.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/message/fusion/mptctl.c Fri Sep 7 09:28:38 2001 @@ -27,7 +27,7 @@ * Originally By: Steven J. Ralston, Noah Romer * (mailto:Steve.Ralston@lsil.com) * - * $Id: mptctl.c,v 1.23 2001/03/21 19:42:31 sralston Exp $ + * $Id: mptctl.c,v 1.25.4.1 2001/08/24 20:07:06 sralston Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -205,6 +205,22 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * struct file_operations functionality. + * Members: + * llseek, write, read, ioctl, open, release + */ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) +static loff_t +mptctl_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} +#define no_llseek mptctl_llseek +#endif + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static ssize_t mptctl_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { @@ -335,8 +351,8 @@ SGESimple32_t *sgl; SGESimple32_t *sgOut, *sgIn; dma_addr_t sgl_dma; - struct buflist *buflist; - struct buflist *bl; + struct buflist *buflist = NULL; + struct buflist *bl = NULL; int numfrags = 0; int maxfrags; int n = 0; @@ -421,7 +437,7 @@ sgIn = sgl; bl = buflist; for (i=0; i < numfrags; i++) { - nib = (sgIn->FlagsLength & 0xF0000000) >> 28; + nib = (le32_to_cpu(sgIn->FlagsLength) & 0xF0000000) >> 28; /* skip ignore/chain. */ if (nib == 0 || nib == 3) { ; @@ -654,7 +670,7 @@ u8 *kptr; int len; - if ((sglbuf[i].FlagsLength >> 24) == 0x30) + if ((le32_to_cpu(sglbuf[i].FlagsLength) >> 24) == 0x30) continue; dma_addr = le32_to_cpu(sglbuf[i].Address); @@ -679,12 +695,12 @@ int dir; int n = 0; - if (sg->FlagsLength & 0x04000000) + if (le32_to_cpu(sg->FlagsLength) & 0x04000000) dir = PCI_DMA_TODEVICE; else dir = PCI_DMA_FROMDEVICE; - nib = (sg->FlagsLength & 0xF0000000) >> 28; + nib = (le32_to_cpu(sg->FlagsLength) & 0xF0000000) >> 28; while (! (nib & 0x4)) { /* eob */ /* skip ignore/chain. */ if (nib == 0 || nib == 3) { @@ -703,7 +719,7 @@ } sg++; bl++; - nib = (sg->FlagsLength & 0xF0000000) >> 28; + nib = (le32_to_cpu(sg->FlagsLength) & 0xF0000000) >> 28; } /* we're at eob! */ @@ -1081,10 +1097,14 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static struct file_operations mptctl_fops = { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51) - owner: THIS_MODULE, +#define owner_THIS_MODULE owner: THIS_MODULE, +#else +#define owner_THIS_MODULE #endif + +static struct file_operations mptctl_fops = { + owner_THIS_MODULE llseek: no_llseek, read: mptctl_read, write: mptctl_write, @@ -1162,48 +1182,6 @@ return ret; } -#if 0 /* { */ -static int -sparc32_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *filp) -{ - struct mpt_fw_xfer32 kfw32; - struct mpt_fw_xfer kfw; - mm_segment_t old_fs; - int ret; - - dprintk((KERN_INFO MYNAM "::sparc32_mptfwxfer_ioctl() called\n")); - - if (copy_from_user(&kfw32, (char *)arg, sizeof(kfw32))) - return -EFAULT; - - /* Verify intended MPT adapter */ - iocnumX = kfw32.iocnum & 0xFF; - if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || - (iocp == NULL)) { - printk(KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n", - __LINE__, iocnumX); - return -ENODEV; - } - - if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) - return ret; - - kfw.iocnum = iocnum; - kfw.fwlen = kfw32.fwlen; - kfw.bufp = (void *)(unsigned long)kfw32.bufp; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, MPTFWDOWNLOAD, (unsigned long)&kfw); - set_fs(old_fs); - - up(&mptctl_syscall_sem_ioc[iocp->id]); - - return ret; -} -#endif /* #if 0 } */ - #endif /*} linux >= 2.3.x */ #endif /*} sparc */ @@ -1228,8 +1206,7 @@ if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTRWPERF_RESET, NULL); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTFWDOWNLOAD32, - sparc32_mptfwxfer_ioctl); + err = register_ioctl32_conversion(MPTFWDOWNLOAD32, sparc32_mptfwxfer_ioctl); if (++where && err) goto out_fail; #endif /*} linux >= 2.3.x */ #endif /*} sparc */ @@ -1247,7 +1224,7 @@ * Install our handler */ ++where; - if ((mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER)) < 0) { + if ((mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER)) <= 0) { printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n"); misc_deregister(&mptctl_miscdev); err = -EBUSY; @@ -1275,6 +1252,16 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ void mptctl_exit(void) { + +#if defined(__sparc__) && defined(__sparc_v9__) /*{*/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) /*{*/ + unregister_ioctl32_conversion(MPTRWPERF); + unregister_ioctl32_conversion(MPTRWPERF_CHK); + unregister_ioctl32_conversion(MPTRWPERF_RESET); + unregister_ioctl32_conversion(MPTFWDOWNLOAD32); +#endif /*} linux >= 2.3.x */ +#endif /*} sparc */ + misc_deregister(&mptctl_miscdev); printk(KERN_INFO MYNAM ": /dev/%s @ (major,minor=%d,%d)\n", mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor); diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/mptlan.c linux/drivers/message/fusion/mptlan.c --- v2.4.9/linux/drivers/message/fusion/mptlan.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/mptlan.c Fri Sep 7 09:28:38 2001 @@ -26,7 +26,7 @@ * Copyright (c) 2000-2001 LSI Logic Corporation * Originally By: Noah Romer * - * $Id: mptlan.c,v 1.25 2001/03/02 22:12:04 sralston Exp $ + * $Id: mptlan.c,v 1.32.2.2 2001/07/12 19:43:33 nromer Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -93,6 +93,12 @@ * Fusion MPT LAN private structures */ +struct NAA_Hosed { + u16 NAA; + u8 ieee[FC_ALEN]; + struct NAA_Hosed *next; +}; + struct BufferControl { struct sk_buff *skb; dma_addr_t dma; @@ -153,6 +159,7 @@ static int mpt_lan_send_turbo(struct net_device *dev, u32 tmsg); static int mpt_lan_send_reply(struct net_device *dev, LANSendReply_t *pSendRep); +static int mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase); static int mpt_lan_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); static unsigned short mpt_lan_type_trans(struct sk_buff *skb, struct net_device *dev); @@ -168,6 +175,9 @@ static struct net_device *mpt_landev[MPT_MAX_ADAPTERS+1]; +static struct NAA_Hosed *mpt_bad_naa = NULL; +rwlock_t bad_naa_lock; + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Fusion MPT LAN external data @@ -318,6 +328,41 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static int +mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) +{ + struct net_device *dev = mpt_landev[ioc->id]; + struct mpt_lan_priv *priv = (struct mpt_lan_priv *) dev->priv; + + dprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n", + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")); + + if (priv->mpt_rxfidx == NULL) + return (1); + + if (reset_phase == MPT_IOC_PRE_RESET) { + int i; + unsigned long flags; + + netif_stop_queue(dev); + + atomic_set(&priv->buckets_out, 0); + + /* Reset Rx Free Tail index and re-populate the queue. */ + spin_lock_irqsave(&priv->rxfidx_lock, flags); + priv->mpt_rxfidx_tail = -1; + for (i = 0; i < priv->max_buckets_out; i++) + priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; + spin_unlock_irqrestore(&priv->rxfidx_lock, flags); + } else { + mpt_lan_post_receive_buckets(dev); + netif_wake_queue(dev); + } + + return 1; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +static int mpt_lan_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { dprintk((KERN_INFO MYNAM ": MPT event routed to LAN driver!\n")); @@ -356,7 +401,19 @@ struct mpt_lan_priv *priv = (struct mpt_lan_priv *) dev->priv; int i; - mpt_lan_reset(dev); + if (mpt_lan_reset(dev) != 0) { + MPT_ADAPTER *mpt_dev = priv->mpt_dev; + + printk (KERN_WARNING MYNAM "/lan_open: lan_reset failed."); + + if (mpt_dev->active) + printk ("The ioc is active. Perhaps it needs to be" + " reset?\n"); + else + printk ("The ioc in inactive, most likely in the " + "process of being reset. Please try again in " + "a moment.\n"); + } priv->mpt_txfidx = kmalloc(priv->tx_max_out * sizeof(int), GFP_KERNEL); if (priv->mpt_txfidx == NULL) @@ -402,7 +459,10 @@ IOC_AND_NETDEV_NAMES_s_s(dev)); if (mpt_event_register(LanCtx, mpt_lan_event_process) != 0) { - /* FIXME! */ + printk (KERN_WARNING MYNAM "/lo: Unable to register for Event" + " Notifications. This is a bad thing! We're not going " + "to go ahead, but I'd be leery of system stability at " + "this point.\n"); } netif_start_queue(dev); @@ -422,6 +482,8 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* Send a LanReset message to the FW. This should result in the FW returning + any buckets it still has. */ static int mpt_lan_reset(struct net_device *dev) { @@ -660,6 +722,8 @@ dma_addr_t dma; unsigned long flags; int ctx; + struct NAA_Hosed *nh; + u16 cur_naa = 0x1000; dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n", __FUNCTION__, skb)); @@ -707,8 +771,10 @@ priv->SendCtl[ctx].len = skb->len; /* Message Header */ + pSendReq->Reserved = 0; pSendReq->Function = MPI_FUNCTION_LAN_SEND; pSendReq->ChainOffset = 0; + pSendReq->Reserved2 = 0; pSendReq->MsgFlags = 0; pSendReq->PortNumber = priv->pnum; @@ -725,7 +791,26 @@ // IOC_AND_NETDEV_NAMES_s_s(dev), // ctx, skb, skb->data)); - pTrans->TransactionDetails[0] = cpu_to_le32((0x1000 << 16) | + /* Munge the NAA for Tx packets to QLogic boards, which don't follow + RFC 2625. The longer I look at this, the more my opinion of Qlogic + drops. */ + read_lock_irq(&bad_naa_lock); + for (nh = mpt_bad_naa; nh != NULL; nh=nh->next) { + if ((nh->ieee[0] == skb->mac.raw[0]) && + (nh->ieee[1] == skb->mac.raw[1]) && + (nh->ieee[2] == skb->mac.raw[2]) && + (nh->ieee[3] == skb->mac.raw[3]) && + (nh->ieee[4] == skb->mac.raw[4]) && + (nh->ieee[5] == skb->mac.raw[5])) { + cur_naa = nh->NAA; + dprintk ((KERN_INFO "mptlan/sdu_send: using NAA value " + "= %04x.\n", cur_naa)); + break; + } + } + read_unlock_irq(&bad_naa_lock); + + pTrans->TransactionDetails[0] = cpu_to_le32((cur_naa << 16) | (skb->mac.raw[0] << 8) | (skb->mac.raw[1] << 0)); pTrans->TransactionDetails[1] = cpu_to_le32((skb->mac.raw[2] << 24) | @@ -735,9 +820,15 @@ pSimple = (SGESimple64_t *) &pTrans->TransactionDetails[2]; + /* If we ever decide to send more than one Simple SGE per LANSend, then + we will need to make sure that LAST_ELEMENT only gets set on the + last one. Otherwise, bad voodoo and evil funkiness will commence. */ pSimple->FlagsLength = cpu_to_le32( - ((MPI_SGE_FLAGS_END_OF_BUFFER | + ((MPI_SGE_FLAGS_LAST_ELEMENT | + MPI_SGE_FLAGS_END_OF_BUFFER | MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_SYSTEM_ADDRESS | + MPI_SGE_FLAGS_HOST_TO_IOC | MPI_SGE_FLAGS_64_BIT_ADDRESSING | MPI_SGE_FLAGS_END_OF_LIST) << MPI_SGE_FLAGS_SHIFT) | skb->len); @@ -1252,12 +1343,12 @@ priv->total_posted = 0; priv->total_received = 0; priv->max_buckets_out = max_buckets_out; - if (mpt_dev->pfacts0.MaxLanBuckets < max_buckets_out) - priv->max_buckets_out = mpt_dev->pfacts0.MaxLanBuckets; + if (mpt_dev->pfacts[0].MaxLanBuckets < max_buckets_out) + priv->max_buckets_out = mpt_dev->pfacts[0].MaxLanBuckets; dprintk((KERN_INFO MYNAM "@%d: MaxLanBuckets=%d, max_buckets_out/priv=%d/%d\n", __LINE__, - mpt_dev->pfacts0.MaxLanBuckets, + mpt_dev->pfacts[0].MaxLanBuckets, max_buckets_out, priv->max_buckets_out)); @@ -1316,7 +1407,11 @@ show_mptmod_ver(LANAME, LANVER); - if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) < 0) { + /* Init the global r/w lock for the bad_naa list. We want to do this + before any boards are initialized and may be used. */ + rwlock_init(&bad_naa_lock); + + if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) <= 0) { printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n"); return -EBUSY; } @@ -1326,6 +1421,15 @@ dprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx)); + if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset) == 0) { + dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); + } else { + printk(KERN_ERR MYNAM ": Eieee! unable to register a reset " + "handler with mptbase! The world is at an end! " + "Everything is fading to black! Goodbye.\n"); + return -EBUSY; + } + for (j = 0; j < MPT_MAX_ADAPTERS; j++) { mpt_landev[j] = NULL; } @@ -1333,14 +1437,14 @@ curadapter = mpt_adapter_find_first(); while (curadapter != NULL) { - for (i = 0; i < curadapter->facts0.NumberOfPorts; i++) { + for (i = 0; i < curadapter->facts.NumberOfPorts; i++) { printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n", curadapter->name, - curadapter->pfacts0.PortNumber, - curadapter->pfacts0.ProtocolFlags, - MPT_PROTOCOL_FLAGS_c_c_c_c(curadapter->pfacts0.ProtocolFlags)); + curadapter->pfacts[i].PortNumber, + curadapter->pfacts[i].ProtocolFlags, + MPT_PROTOCOL_FLAGS_c_c_c_c(curadapter->pfacts[i].ProtocolFlags)); - if (curadapter->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { + if (curadapter->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { dev = mpt_register_lan_device (curadapter, i); if (dev != NULL) { printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n", @@ -1361,7 +1465,7 @@ } else { printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n", curadapter->name, - curadapter->pfacts0.PortNumber); + curadapter->pfacts[i].PortNumber); } } else { printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n", @@ -1379,6 +1483,8 @@ { int i; + mpt_reset_deregister(LanCtx); + for (i = 0; mpt_landev[i] != NULL; i++) { struct net_device *dev = mpt_landev[i]; @@ -1411,6 +1517,7 @@ { struct mpt_lan_ohdr *fch = (struct mpt_lan_ohdr *)skb->data; struct fcllc *fcllc; + u16 source_naa = fch->stype, found = 0; skb->mac.raw = skb->data; skb_pull(skb, sizeof(struct mpt_lan_ohdr)); @@ -1444,11 +1551,80 @@ } } + fcllc = (struct fcllc *)skb->data; + + /* Workaround for QLogic not following RFC 2625 in regards to the NAA + value. */ + + if ((source_naa & 0xF000) == 0) + source_naa = swab16(source_naa); + + if (fcllc->ethertype == htons(ETH_P_ARP)) + dprintk ((KERN_INFO "mptlan/type_trans: got arp req/rep w/ naa of " + "%04x.\n", source_naa)); + + if ((fcllc->ethertype == htons(ETH_P_ARP)) && + ((source_naa >> 12) != MPT_LAN_NAA_RFC2625)){ + struct NAA_Hosed *nh, *prevnh; + int i; + + dprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep from " + "system with non-RFC 2625 NAA value (%04x).\n", + source_naa)); + + write_lock_irq(&bad_naa_lock); + for (prevnh = nh = mpt_bad_naa; nh != NULL; + prevnh=nh, nh=nh->next) { + if ((nh->ieee[0] == fch->saddr[0]) && + (nh->ieee[1] == fch->saddr[1]) && + (nh->ieee[2] == fch->saddr[2]) && + (nh->ieee[3] == fch->saddr[3]) && + (nh->ieee[4] == fch->saddr[4]) && + (nh->ieee[5] == fch->saddr[5])) { + found = 1; + dprintk ((KERN_INFO "mptlan/type_trans: ARP Re" + "q/Rep w/ bad NAA from system already" + " in DB.\n")); + break; + } + } + + if ((!found) && (nh == NULL)) { + + nh = kmalloc(sizeof(struct NAA_Hosed), GFP_KERNEL); + dprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep w/" + " bad NAA from system not yet in DB.\n")); + + if (nh != NULL) { + nh->next = NULL; + if (!mpt_bad_naa) + mpt_bad_naa = nh; + if (prevnh) + prevnh->next = nh; + + nh->NAA = source_naa; /* Set the S_NAA value. */ + for (i = 0; i < FC_ALEN; i++) + nh->ieee[i] = fch->saddr[i]; + dprintk ((KERN_INFO "Got ARP from %02x:%02x:%02x:%02x:" + "%02x:%02x with non-compliant S_NAA value.\n", + fch->saddr[0], fch->saddr[1], fch->saddr[2], + fch->saddr[3], fch->saddr[4],fch->saddr[5])); + } else { + printk (KERN_ERR "mptlan/type_trans: Unable to" + " kmalloc a NAA_Hosed struct.\n"); + } + } else if (!found) { + printk (KERN_ERR "mptlan/type_trans: found not" + " set, but nh isn't null. Evil " + "funkiness abounds.\n"); + } + write_unlock_irq(&bad_naa_lock); + } + + /* Strip the SNAP header from ARP packets since we don't * pass them through to the 802.2/SNAP layers. */ - fcllc = (struct fcllc *)skb->data; - if (fcllc->dsap == EXTENDED_SAP && (fcllc->ethertype == htons(ETH_P_IP) || fcllc->ethertype == htons(ETH_P_ARP))) { diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/mptlan.h linux/drivers/message/fusion/mptlan.h --- v2.4.9/linux/drivers/message/fusion/mptlan.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/mptlan.h Fri Sep 7 09:28:38 2001 @@ -51,6 +51,9 @@ #define MPT_LAN_MAX_MTU 65280 /* RFC2625 */ #define MPT_LAN_MTU 16128 /* be nice to slab allocator */ +#define MPT_LAN_NAA_RFC2625 0x1 +#define MPT_LAN_NAA_QLOGIC 0x2 + /* MPT LAN Reset and Suspend Resource Flags Defines */ #define MPT_LAN_RESOURCE_FLAG_RETURN_POSTED_BUCKETS 0x01 diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/mptscsih.c linux/drivers/message/fusion/mptscsih.c --- v2.4.9/linux/drivers/message/fusion/mptscsih.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/mptscsih.c Fri Sep 7 09:28:38 2001 @@ -19,7 +19,7 @@ * Original author: Steven J. Ralston * (mailto:Steve.Ralston@lsil.com) * - * $Id: mptscsih.c,v 1.24 2001/03/22 08:45:08 sralston Exp $ + * $Id: mptscsih.c,v 1.29 2001/06/18 18:59:05 sralston Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -95,7 +95,6 @@ u8 *SgHunks; dma_addr_t SgHunksDMA; u32 qtag_tick; - FCDEV_TRACKER TargetsQ; } MPT_SCSI_HOST; typedef struct _MPT_SCSI_DEV { @@ -119,6 +118,7 @@ static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); static u32 SCPNT_TO_MSGCTX(Scsi_Cmnd *sc); +static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); @@ -205,7 +205,7 @@ dprintk((KERN_INFO MYNAM ": *NEW* SCSI device (%d:%d:%d)!\n", sc->device->id, sc->device->lun, sc->device->channel)); if ((sc->device->hostdata = kmalloc(sizeof(MPT_SCSI_DEV), GFP_ATOMIC)) == NULL) { - printk(KERN_ERR MYNAM ": ERROR: kmalloc(%d) FAILED!\n", (int)sizeof(MPT_SCSI_DEV)); + printk(KERN_ERR MYNAM ": ERROR - kmalloc(%d) FAILED!\n", (int)sizeof(MPT_SCSI_DEV)); } else { memset(sc->device->hostdata, 0, sizeof(MPT_SCSI_DEV)); mpt_sdev = (MPT_SCSI_DEV *) sc->device->hostdata; @@ -555,8 +555,14 @@ if (! BeenHereDoneThat++) { show_mptmod_ver(my_NAME, my_VERSION); - ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER); - ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER); + if ((ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER)) <= 0) { + printk(KERN_ERR MYNAM ": Failed to register callback1 with MPT base driver\n"); + return mpt_scsi_hosts; + } + if ((ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER)) <= 0) { + printk(KERN_ERR MYNAM ": Failed to register callback2 with MPT base driver\n"); + return mpt_scsi_hosts; + } #ifndef MPT_SCSI_USE_NEW_EH Q_INIT(&mpt_scsih_taskQ, MPT_FRAME_HDR); @@ -568,6 +574,12 @@ } else { /* FIXME! */ } + + if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) { + dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); + } else { + /* FIXME! */ + } } dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()\n")); @@ -582,7 +594,7 @@ * Added sanity check on SCSI Initiator-mode enabled * for this MPT adapter. */ - if (!(this->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) { + if (!(this->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) { printk(KERN_ERR MYNAM ": Skipping %s because SCSI Initiator mode is NOT enabled!\n", this->name); this = mpt_adapter_find_next(this); @@ -612,10 +624,18 @@ /* Yikes! This is important! * Otherwise, by default, linux only scans target IDs 0-7! + * + * BUG FIX! 20010618 -sralston & pdelaney + * FC919 testing was encountering "duplicate" FC devices, + * as it turns out because the 919 was returning 512 + * for PortFacts.MaxDevices, causing a wraparound effect + * in SCSI IO requests. So instead of using: + * sh->max_id = this->pfacts[0].MaxDevices - 1 + * we'll use a definitive max here. */ - sh->max_id = this->pfacts0.MaxDevices - 1; + sh->max_id = MPT_MAX_FC_DEVICES; - sh->this_id = this->pfacts0.PortSCSIID; + sh->this_id = this->pfacts[0].PortSCSIID; restore_flags(flags); @@ -730,6 +750,9 @@ #if 0 mptscsih_flush_pending(); #endif + mpt_reset_deregister(ScsiDoneCtx); + dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n")); + mpt_event_deregister(ScsiDoneCtx); dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n")); @@ -765,7 +788,7 @@ h = (MPT_SCSI_HOST *)SChost->hostdata; info_kbuf[0] = '\0'; - mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0); + mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0); info_kbuf[size-1] = '\0'; return info_kbuf; @@ -1235,7 +1258,6 @@ dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd)); } - mb(); dmfprintk((KERN_INFO MYNAM ": Issued SCSI cmd (%p)\n", SCpnt)); return 0; @@ -1265,6 +1287,7 @@ u32 *msg; u32 ctx2abort; int i; + unsigned long flags; printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO (=%p)\n", SCpnt); printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); @@ -1309,41 +1332,59 @@ * the controller, so it does not matter. -DaveM */ ctx2abort = SCPNT_TO_MSGCTX(SCpnt); - dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort)); - pScsiTm->TaskMsgContext = ctx2abort; - - wmb(); + if (ctx2abort == -1) { + printk(KERN_ERR MYNAM ": ERROR - ScsiLookup fail(#2) for SCpnt=%p\n", SCpnt); + SCpnt->result = DID_SOFT_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + SCpnt->scsi_done(SCpnt); + spin_unlock_irqrestore(&io_request_lock, flags); + mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); + } else { + dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort)); + pScsiTm->TaskMsgContext = ctx2abort; -/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake - mpt_put_msg_frame(hd->ioc->id, mf); -*/ -/* FIXME! Check return status! */ - (void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg); - wmb(); + /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake + mpt_put_msg_frame(hd->ioc->id, mf); + */ + if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, + sizeof(SCSITaskMgmt_t), msg)) + != 0) { + printk(KERN_WARNING MYNAM + ": WARNING[2] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n", + i, mf, SCpnt); + SCpnt->result = DID_SOFT_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + SCpnt->scsi_done(SCpnt); + spin_unlock_irqrestore(&io_request_lock, flags); + mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); + } + } - return SUCCESS; + //return SUCCESS; + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant + * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to * - * (linux Scsi_Host_Template.eh_bus_reset_handler routine) + * (linux Scsi_Host_Template.eh_dev_reset_handler routine) * * Returns SUCCESS or FAILED. */ int -mptscsih_bus_reset(Scsi_Cmnd * SCpnt) +mptscsih_dev_reset(Scsi_Cmnd * SCpnt) { MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; MPT_SCSI_HOST *hd; u32 *msg; int i; + unsigned long flags; - printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET (%p)\n", SCpnt); + printk(KERN_WARNING MYNAM ": Attempting _TARGET_RESET (%p)\n", SCpnt); printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata; @@ -1356,7 +1397,7 @@ } pScsiTm = (SCSITaskMgmt_t *) mf; - msg = (u32 *) mf; + msg = (u32*)mf; pScsiTm->TargetID = SCpnt->target; pScsiTm->Bus = hd->port; @@ -1364,10 +1405,11 @@ pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; pScsiTm->Reserved = 0; - pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; + pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; pScsiTm->Reserved1 = 0; pScsiTm->MsgFlags = 0; + /* _TARGET_RESET goes to LUN 0 always! */ for (i = 0; i < 8; i++) pScsiTm->LUN[i] = 0; @@ -1377,38 +1419,47 @@ pScsiTm->TaskMsgContext = cpu_to_le32(0); - wmb(); - /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake mpt_put_msg_frame(hd->ioc->id, mf); */ /* FIXME! Check return status! */ - (void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg); - - wmb(); + if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, + sizeof(SCSITaskMgmt_t), msg)) + != 0) { + printk(KERN_WARNING MYNAM + ": WARNING[3] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n", + i, mf, SCpnt); + SCpnt->result = DID_SOFT_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + SCpnt->scsi_done(SCpnt); + spin_unlock_irqrestore(&io_request_lock, flags); + mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); + } - return SUCCESS; + //return SUCCESS; + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant + * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to * - * (linux Scsi_Host_Template.eh_dev_reset_handler routine) + * (linux Scsi_Host_Template.eh_bus_reset_handler routine) * * Returns SUCCESS or FAILED. */ int -mptscsih_dev_reset(Scsi_Cmnd * SCpnt) +mptscsih_bus_reset(Scsi_Cmnd * SCpnt) { MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; MPT_SCSI_HOST *hd; u32 *msg; int i; + unsigned long flags; - printk(KERN_WARNING MYNAM ": Attempting _TARGET_RESET (%p)\n", SCpnt); + printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET (%p)\n", SCpnt); printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata; @@ -1421,7 +1472,7 @@ } pScsiTm = (SCSITaskMgmt_t *) mf; - msg = (u32*)mf; + msg = (u32 *) mf; pScsiTm->TargetID = SCpnt->target; pScsiTm->Bus = hd->port; @@ -1429,11 +1480,10 @@ pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; pScsiTm->Reserved = 0; - pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; + pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; pScsiTm->Reserved1 = 0; pScsiTm->MsgFlags = 0; - /* _TARGET_RESET goes to LUN 0 always! */ for (i = 0; i < 8; i++) pScsiTm->LUN[i] = 0; @@ -1443,15 +1493,22 @@ pScsiTm->TaskMsgContext = cpu_to_le32(0); - wmb(); - /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake mpt_put_msg_frame(hd->ioc->id, mf); */ /* FIXME! Check return status! */ - (void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg); - - wmb(); + if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, + sizeof(SCSITaskMgmt_t), msg)) + != 0) { + printk(KERN_WARNING MYNAM + ": WARNING[4] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n", + i, mf, SCpnt); + SCpnt->result = DID_SOFT_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + SCpnt->scsi_done(SCpnt); + spin_unlock_irqrestore(&io_request_lock, flags); + mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); + } return SUCCESS; } @@ -1646,6 +1703,9 @@ spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags); while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/4); + /* * We MUST remove item from taskQ *before* we format the * frame as a SCSITaskMgmt request and send it down to the IOC. @@ -1664,9 +1724,10 @@ SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1; if (SCpnt == NULL) { - printk(KERN_ERR MYNAM ": ERROR: TaskMgmt has NULL SCpnt! (%p:%p)\n", mf, SCpnt); + printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (%p:%p)\n", mf, SCpnt); continue; } + hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata; pScsiTm = (SCSITaskMgmt_t *) mf; for (i = 0; i < 8; i++) { @@ -1674,9 +1735,9 @@ } task_type = mf->u.frame.linkage.arg1; - if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - { - printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO! (mf:sc=%p:%p)\n", mf, SCpnt); + if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { + printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO! (mf=%p:sc=%p)\n", + mf, SCpnt); /* Most important! Set TaskMsgContext to SCpnt's MsgContext! * (the IO to be ABORT'd) @@ -1686,11 +1747,20 @@ * the controller, so it does not matter. -DaveM */ ctx2abort = SCPNT_TO_MSGCTX(SCpnt); + if (ctx2abort == -1) { + printk(KERN_ERR MYNAM ": ERROR - ScsiLookup fail(#1) for SCpnt=%p\n", SCpnt); + SCpnt->result = DID_SOFT_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + SCpnt->scsi_done(SCpnt); + spin_unlock_irqrestore(&io_request_lock, flags); + mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); + continue; + } pScsiTm->LUN[1] = SCpnt->lun; } else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET! (against SCSI IO mf:sc=%p:%p)\n", mf, SCpnt); + printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET! (against SCSI IO mf=%p:sc=%p)\n", mf, SCpnt); } #if 0 else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {} @@ -1699,8 +1769,6 @@ printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); - hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata; - pScsiTm->TargetID = SCpnt->target; pScsiTm->Bus = hd->port; pScsiTm->ChainOffset = 0; @@ -1725,15 +1793,22 @@ * mpt_put_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); * SCSITaskMgmt requests MUST be sent ONLY via * Doorbell/handshake now. :-( - * - * FIXME! Check return status! */ - (void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), (u32*)mf); - - /* Spin-Wait for TaskMgmt complete!!! */ - while (mpt_scsih_active_taskmgmt_mf != NULL) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/2); + if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, + sizeof(SCSITaskMgmt_t), (u32*) mf)) + != 0) { + printk(KERN_WARNING MYNAM ": WARNING[1] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n", i, mf, SCpnt); + SCpnt->result = DID_SOFT_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + SCpnt->scsi_done(SCpnt); + spin_unlock_irqrestore(&io_request_lock, flags); + mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); + } else { + /* Spin-Wait for TaskMgmt complete!!! */ + while (mpt_scsih_active_taskmgmt_mf != NULL) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/4); + } } } @@ -2002,6 +2077,22 @@ # include "../../scsi/scsi_module.c" #endif + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +static int +mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) +{ + dprintk((KERN_INFO MYNAM ": IOC %s_reset routed to SCSI host driver!\n", + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")); + + if (reset_phase == MPT_IOC_PRE_RESET) { + /* FIXME! Do pre-reset cleanup */ + } else { + /* FIXME! Do post-reset cleanup */ + } + + return 1; /* currently means nothing really */ +} /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static int diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/scsi3.h linux/drivers/message/fusion/scsi3.h --- v2.4.9/linux/drivers/message/fusion/scsi3.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/message/fusion/scsi3.h Fri Sep 7 09:28:38 2001 @@ -8,7 +8,7 @@ * Written By: Steven J. Ralston (19960517) * (mailto:Steve.Ralston@lsil.com) * - * $Id: scsi3.h,v 1.4 2001/01/06 15:54:25 sralston Exp $ + * $Id: scsi3.h,v 1.5 2001/04/06 14:31:32 sralston Exp $ */ #ifndef SCSI3_H_INCLUDED @@ -64,12 +64,15 @@ #define CMD_WriteVerify 0x2E #define CMD_Verify 0x2F #define CMD_ReadDefectData 0x37 +#define CMD_ReadLong 0x3E #define CMD_LogSelect 0x4C #define CMD_LogSense 0x4D #define CMD_ModeSelect10 0x55 #define CMD_Reserve10 0x56 #define CMD_Release10 0x57 #define CMD_ModeSense10 0x5A +#define CMD_PersistReserveIn 0x5E +#define CMD_PersistReserveOut 0x5F #define CMD_ReportLuns 0xA0 /* diff -u --recursive --new-file v2.4.9/linux/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c --- v2.4.9/linux/drivers/mtd/ftl.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/mtd/ftl.c Sat Sep 8 12:02:32 2001 @@ -1428,8 +1428,7 @@ blksize_size[FTL_MAJOR] = ftl_blocksizes; ftl_gendisk.major = FTL_MAJOR; blk_init_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR), &do_ftl_request); - ftl_gendisk.next = gendisk_head; - gendisk_head = &ftl_gendisk; + add_gendisk(&ftl_gendisk); register_mtd_user(&ftl_notifier); @@ -1438,19 +1437,13 @@ mod_exit_t cleanup_ftl(void) { - struct gendisk *gd, **gdp; - unregister_mtd_user(&ftl_notifier); unregister_blkdev(FTL_MAJOR, "ftl"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR)); blksize_size[FTL_MAJOR] = NULL; - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) - if (*gdp == &ftl_gendisk) { - gd = *gdp; *gdp = gd->next; - break; - } + del_gendisk(&ftl_gendisk); } module_init(init_ftl); diff -u --recursive --new-file v2.4.9/linux/drivers/mtd/nftlcore.c linux/drivers/mtd/nftlcore.c --- v2.4.9/linux/drivers/mtd/nftlcore.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/mtd/nftlcore.c Sat Sep 8 12:02:32 2001 @@ -1059,8 +1059,7 @@ } blksize_size[MAJOR_NR] = nftl_blocksizes; - nftl_gendisk.next = gendisk_head; - gendisk_head = &nftl_gendisk; + add_gendisk(&nftl_gendisk); } register_mtd_user(&nftl_notifier); @@ -1083,11 +1082,7 @@ /* remove ourself from generic harddisk list FIXME: why can't I found this partition on /proc/partition */ - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) - if (*gdp == &nftl_gendisk) { - gd = *gdp; *gdp = gd->next; - break; - } + del_gendisk(&nftl_gendisk);: } module_init(init_nftl); diff -u --recursive --new-file v2.4.9/linux/drivers/net/8139too.c linux/drivers/net/8139too.c --- v2.4.9/linux/drivers/net/8139too.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/8139too.c Sun Sep 2 07:59:04 2001 @@ -1610,6 +1610,7 @@ unsigned long timeout; daemonize (); + reparent_to_init(); spin_lock_irq(¤t->sigmask_lock); sigemptyset(¤t->blocked); recalc_sigpending(current); diff -u --recursive --new-file v2.4.9/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.4.9/linux/drivers/net/Makefile Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/Makefile Sun Sep 2 07:24:13 2001 @@ -137,12 +137,8 @@ obj-$(CONFIG_PPPOE) += pppox.o pppoe.o obj-$(CONFIG_SLIP) += slip.o -ifeq ($(CONFIG_SLIP),y) - obj-$(CONFIG_SLIP_COMPRESSED) += slhc.o -else - ifeq ($(CONFIG_SLIP),m) - obj-$(CONFIG_SLIP_COMPRESSED) += slhc.o - endif +ifeq ($(CONFIG_SLIP_COMPRESSED),y) + obj-$(CONFIG_SLIP) += slhc.o endif obj-$(CONFIG_STRIP) += strip.o diff -u --recursive --new-file v2.4.9/linux/drivers/net/irda/irda-usb.c linux/drivers/net/irda/irda-usb.c --- v2.4.9/linux/drivers/net/irda/irda-usb.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/net/irda/irda-usb.c Sat Sep 8 12:16:26 2001 @@ -76,7 +76,8 @@ { USB_DEVICE(0x50f, 0x180), driver_info: IUC_SPEED_BUG | IUC_NO_WINDOW }, /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ { USB_DEVICE(0x8e9, 0x100), driver_info: IUC_SPEED_BUG | IUC_NO_WINDOW }, - { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS, + { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS, bInterfaceClass: USB_CLASS_APP_SPEC, bInterfaceSubClass: USB_CLASS_IRDA, driver_info: IUC_DEFAULT, }, diff -u --recursive --new-file v2.4.9/linux/drivers/net/macsonic.c linux/drivers/net/macsonic.c --- v2.4.9/linux/drivers/net/macsonic.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/macsonic.c Sat Sep 1 11:01:28 2001 @@ -135,8 +135,9 @@ unsigned long desc_base, desc_top; if ((lp->sonic_desc = kmalloc(SIZEOF_SONIC_DESC - * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_DMA)) == NULL) { + * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_KERNEL | GFP_DMA)) == NULL) { printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name); + return -ENOMEM; } desc_base = (unsigned long) lp->sonic_desc; desc_top = desc_base + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode); @@ -165,7 +166,7 @@ /* FIXME, maybe we should use skbs */ if ((lp->rba = (char *) - kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_DMA)) == NULL) { + kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) { printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name); return -ENOMEM; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/net_init.c linux/drivers/net/net_init.c --- v2.4.9/linux/drivers/net/net_init.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/net_init.c Fri Sep 7 16:18:50 2001 @@ -165,9 +165,16 @@ setup(dev); if (new_device) { + int err; + rtnl_lock(); - register_netdevice(dev); + err = register_netdevice(dev); rtnl_unlock(); + + if (err < 0) { + kfree(dev); + dev = NULL; + } } return dev; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/ni5010.c linux/drivers/net/ni5010.c --- v2.4.9/linux/drivers/net/ni5010.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/ni5010.c Fri Sep 7 09:28:38 2001 @@ -575,7 +575,6 @@ outb(0xff, EDLC_XCLR); /* Clear all pending xmit IRQ's */ if (xmit_stat & XS_COLL){ - printk("ether collision\n"); /* FIXME: remove */ PRINTK((KERN_DEBUG "%s: collision detected, retransmitting\n", dev->name)); outw(NI5010_BUFSIZE - lp->o_pkt_size, IE_GP); diff -u --recursive --new-file v2.4.9/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c --- v2.4.9/linux/drivers/net/smc9194.c Wed Jul 25 17:10:22 2001 +++ linux/drivers/net/smc9194.c Sat Sep 8 12:14:25 2001 @@ -88,7 +88,11 @@ . Do you want to use 32 bit xfers? This should work on all chips, as . the chipset is designed to accommodate them. */ +#ifdef __sh__ +#undef USE_32_BIT +#else #define USE_32_BIT 1 +#endif /* .the SMC9194 can be at any of the following port addresses. To change, @@ -983,12 +987,6 @@ retval = -ENODEV; goto err_out; } - if (dev->irq == 2) { - /* Fixup for users that don't know that IRQ 2 is really IRQ 9, - * or don't know which one to set. - */ - dev->irq = 9; - } /* now, print out the card info, in a short format.. */ @@ -1369,13 +1367,11 @@ packet_length & 0x3 ); #else PRINTK3((" Reading %d words and %d byte(s) \n", - (packet_length >> 1 ), packet_length & 1 ); - if ( packet_length & 1 ) - *(data++) = inb( ioaddr + DATA_1 ); - insw(ioaddr + DATA_1 , data, (packet_length + 1 ) >> 1); + (packet_length >> 1 ), packet_length & 1 )); + insw(ioaddr + DATA_1 , data, packet_length >> 1); if ( packet_length & 1 ) { data += packet_length & ~1; - *((data++) = inb( ioaddr + DATA_1 ); + *(data++) = inb( ioaddr + DATA_1 ); } #endif #if SMC_DEBUG > 2 diff -u --recursive --new-file v2.4.9/linux/drivers/net/smc9194.h linux/drivers/net/smc9194.h --- v2.4.9/linux/drivers/net/smc9194.h Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/smc9194.h Sat Sep 8 12:13:55 2001 @@ -169,7 +169,8 @@ /* 5 */ "SMC91C95", NULL, /* 7 */ "SMC91C100", - NULL, NULL, NULL, NULL, + /* 8 */ "SMC91C100FD", + NULL, NULL, NULL, NULL, NULL, NULL}; /* diff -u --recursive --new-file v2.4.9/linux/drivers/net/starfire.c linux/drivers/net/starfire.c --- v2.4.9/linux/drivers/net/starfire.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/net/starfire.c Fri Sep 7 09:28:38 2001 @@ -89,13 +89,29 @@ - Initialize the TxMode register properly - Don't dereference dev->priv after freeing it + LK1.3.4 (Ion Badulescu) + - Fixed initialization timing problems + - Fixed interrupt mask definitions + TODO: - implement tx_timeout() properly */ #define DRV_NAME "starfire" -#define DRV_VERSION "1.03+LK1.3.3" -#define DRV_RELDATE "July 05, 2001" +#define DRV_VERSION "1.03+LK1.3.4" +#define DRV_RELDATE "August 14, 2001" + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Processor type for cache alignment. */ +#include +#include /* * Adaptec's license for their Novell drivers (which is where I got the @@ -124,6 +140,10 @@ #define ZEROCOPY #endif +#ifdef HAS_FIRMWARE +#include "starfire_firmware.h" +#endif /* HAS_FIRMWARE */ + /* The user-configurable values. These may be modified when a driver module is loaded.*/ @@ -196,22 +216,6 @@ #define skb_first_frag_len(skb) (skb->len) #endif /* not ZEROCOPY */ -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Processor type for cache alignment. */ -#include -#include - -#ifdef HAS_FIRMWARE -#include "starfire_firmware.h" -#endif /* HAS_FIRMWARE */ - /* 2.2.x compatibility code */ #if LINUX_VERSION_CODE < 0x20300 @@ -242,7 +246,6 @@ /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker \n" -KERN_INFO " Updates and info at http://www.scyld.com/network/starfire.html\n" KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker "); @@ -417,7 +420,7 @@ /* not quite bits */ IntrRxDone=IntrRxQ2Done | IntrRxQ1Done, IntrRxEmpty=IntrRxDescQ1Low | IntrRxDescQ2Low, - IntrNormalMask=0xf0, IntrAbnormalMask=0x3f0e, + IntrNormalMask=0xff00, IntrAbnormalMask=0x3ff00fe, }; /* Bits in the RxFilterMode register. */ @@ -656,10 +659,7 @@ #ifdef ZEROCOPY /* Starfire can do SG and TCP/UDP checksumming */ - dev->features |= NETIF_F_SG; -#ifdef HAS_FIRMWARE - dev->features |= NETIF_F_IP_CSUM; -#endif /* HAS_FIRMWARE */ + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; #endif /* ZEROCOPY */ /* Serial EEPROM reads are hidden by the hardware. */ @@ -745,7 +745,7 @@ int mii_status; for (phy = 0; phy < 32 && phy_idx < PHY_CNT; phy++) { mdio_write(dev, phy, MII_BMCR, BMCR_RESET); - udelay(500); + mdelay(100); boguscnt = 1000; while (--boguscnt > 0) if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0) @@ -768,6 +768,14 @@ np->phy_cnt = phy_idx; } +#ifdef ZEROCOPY + printk(KERN_INFO "%s: scatter-gather and hardware TCP cksumming enabled.\n", + dev->name, +#else /* not ZEROCOPY */ + printk(KERN_INFO "%s: scatter-gather and hardware TCP cksumming disabled.\n", + dev->name); +#endif /* not ZEROCOPY */ + return 0; err_out_cleardev: @@ -931,6 +939,7 @@ /* Configure the PCI bus bursts and FIFO thresholds. */ np->tx_mode = 0x0C04; /* modified when link is up. */ writel(0x8000 | np->tx_mode, ioaddr + TxMode); + udelay(1000); writel(np->tx_mode, ioaddr + TxMode); np->tx_threshold = 4; writel(np->tx_threshold, ioaddr + TxThreshold); @@ -1546,6 +1555,7 @@ if (np->tx_mode != new_tx_mode) { np->tx_mode = new_tx_mode; writel(np->tx_mode | 0x8000, ioaddr + TxMode); + udelay(1000); writel(np->tx_mode, ioaddr + TxMode); } } else { diff -u --recursive --new-file v2.4.9/linux/drivers/net/starfire_firmware.pl linux/drivers/net/starfire_firmware.pl --- v2.4.9/linux/drivers/net/starfire_firmware.pl Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/starfire_firmware.pl Fri Sep 7 09:28:38 2001 @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +# This script can be used to generate a new starfire_firmware.h +# from GFP_RX.DAT and GFP_TX.DAT, files included with the DDK +# and also with the Novell drivers. + +open FW, "GFP_RX.DAT" || die; +open FWH, ">starfire_firmware.h" || die; + +printf(FWH "static u32 firmware_rx[] = {\n"); +$counter = 0; +while ($foo = ) { + chomp; + printf(FWH " 0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4)); + $counter++; +} + +close FW; +open FW, "GFP_TX.DAT" || die; + +printf(FWH "};\t/* %d Rx instructions */\n#define FIRMWARE_RX_SIZE %d\n\nstatic u32 firmware_tx[] = {\n", $counter, $counter); +$counter = 0; +while ($foo = ) { + chomp; + printf(FWH " 0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4)); + $counter++; +} + +close FW; +printf(FWH "};\t/* %d Tx instructions */\n#define FIRMWARE_TX_SIZE %d\n", $counter, $counter); +close(FWH); diff -u --recursive --new-file v2.4.9/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c --- v2.4.9/linux/drivers/net/via-rhine.c Wed Jul 25 17:10:22 2001 +++ linux/drivers/net/via-rhine.c Fri Sep 7 09:28:38 2001 @@ -69,6 +69,10 @@ - Manfred Spraul: use "singlecopy" for unaligned buffers don't allocate bounce buffers for !ReqTxAlign cards + LK1.1.11: + - David Woodhouse: Set dev->base_addr before the first time we call + wait_for_reset(). It's a lot happier that way. + Free np->tx_bufs only if we actually allocated it. */ @@ -151,7 +155,7 @@ /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO "via-rhine.c:v1.10-LK1.1.10 07/12/2001 Written by Donald Becker\n" +KERN_INFO "via-rhine.c:v1.10-LK1.1.11 20/08/2001 Written by Donald Becker\n" KERN_INFO " http://www.scyld.com/network/via-rhine.html\n"; static char shortname[] __devinitdata = "via-rhine"; @@ -584,6 +588,8 @@ /* Reset the chip to erase previous misconfiguration. */ writew(CmdReset, ioaddr + ChipCmd); + + dev->base_addr = ioaddr; wait_for_reset(dev, shortname); /* Reload the station address from the EEPROM. */ @@ -609,7 +615,6 @@ writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA); } - dev->base_addr = ioaddr; dev->irq = pdev->irq; np = dev->priv; @@ -758,8 +763,11 @@ TX_RING_SIZE * sizeof(struct tx_desc), np->rx_ring, np->rx_ring_dma); - pci_free_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE, - np->tx_bufs, np->tx_bufs_dma); + if (np->tx_bufs) + pci_free_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE, + np->tx_bufs, np->tx_bufs_dma); + + np->tx_bufs = NULL; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/dscc4.c linux/drivers/net/wan/dscc4.c --- v2.4.9/linux/drivers/net/wan/dscc4.c Fri Apr 20 11:54:22 2001 +++ linux/drivers/net/wan/dscc4.c Sat Sep 1 11:01:28 2001 @@ -348,7 +348,7 @@ { struct sk_buff *skb; - skb = dev_alloc_skb(RX_MAX(dev->mtu+2)); + skb = dev_alloc_skb(RX_MAX(HDLC_MAX_MRU+2)); priv->rx_skbuff[cur] = skb; if (!skb) { priv->rx_fd[cur--].data = (u32) NULL; @@ -428,9 +428,9 @@ int pkt_len; skb = dpriv->rx_skbuff[cur]; - pkt_len = TO_SIZE(rx_fd->state2); - pci_dma_sync_single(pdev, rx_fd->data, pkt_len, PCI_DMA_FROMDEVICE); - if((skb->data[pkt_len - 1] & FrameOk) == FrameOk) { + pkt_len = TO_SIZE(rx_fd->state2) - 1; + pci_dma_sync_single(pdev, rx_fd->data, pkt_len + 1, PCI_DMA_FROMDEVICE); + if((skb->data[pkt_len] & FrameOk) == FrameOk) { pci_unmap_single(pdev, rx_fd->data, skb->len, PCI_DMA_FROMDEVICE); dpriv->stats.rx_packets++; dpriv->stats.rx_bytes += pkt_len; @@ -442,11 +442,11 @@ netif_rx(skb); try_get_rx_skb(dpriv, cur, dev); } else { - if(skb->data[pkt_len - 1] & FrameRdo) + if(skb->data[pkt_len] & FrameRdo) dpriv->stats.rx_fifo_errors++; - else if(!(skb->data[pkt_len - 1] | ~FrameCrc)) + else if(!(skb->data[pkt_len] | ~FrameCrc)) dpriv->stats.rx_crc_errors++; - else if(!(skb->data[pkt_len - 1] | ~FrameVfr)) + else if(!(skb->data[pkt_len] | ~FrameVfr)) dpriv->stats.rx_length_errors++; else dpriv->stats.rx_errors++; @@ -760,7 +760,7 @@ /* FIXME: VIS */ writel(readl(ioaddr + CCR0) | 0x80001000, ioaddr + CCR0); - writel(LengthCheck | (dev->mtu >> 5), ioaddr + RLCR); + writel(LengthCheck | (HDLC_MAX_MRU >> 5), ioaddr + RLCR); /* no address recognition/crc-CCITT/cts enabled */ writel(readl(ioaddr + CCR1) | 0x021c8000, ioaddr + CCR1); @@ -1224,7 +1224,7 @@ dev->name, SOURCE_ID(state), state ); return; } - if (state & 0x0df80c01) { + if (state & 0x0df80c00) { printk(KERN_DEBUG "%s (Tx): state=%08x (UFO alert)\n", dev->name, state); return; @@ -1377,7 +1377,7 @@ dev->name, SOURCE_ID(state), state); goto try; } - if (state & 0x0df80c01) { + if (state & 0x0df80c00) { printk(KERN_DEBUG "%s (Rx): state=%08x (UFO alert)\n", dev->name, state); goto try; @@ -1609,7 +1609,7 @@ rx_fd->state1 = HiDesc; /* Hi, no Hold */ rx_fd->state2 = 0x00000000; rx_fd->end = 0xbabeface; - rx_fd->state1 |= ((u32)(dev->mtu & RxSizeMax)) << 16; + rx_fd->state1 |= ((u32)(HDLC_MAX_MRU & RxSizeMax)) << 16; try_get_rx_skb(dpriv, i, dev); i++; rx_fd->next = (u32)(dpriv->rx_fd_dma + i*sizeof(struct RxFD)); @@ -1720,7 +1720,7 @@ hdlc = &dpriv->hdlc; /* XXX: Don't look at the next line */ hdlc->netdev.base_addr = (unsigned long)dev; - // FIXME: set hdlc->set_mode ? + hdlc->set_mode = NULL; hdlc->open = dscc4_hdlc_open; hdlc->close = dscc4_hdlc_close; hdlc->ioctl = dscc4_hdlc_ioctl; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/farsync.c linux/drivers/net/wan/farsync.c --- v2.4.9/linux/drivers/net/wan/farsync.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/farsync.c Sat Sep 8 12:17:18 2001 @@ -1200,7 +1200,8 @@ /* Sanity check the parameters. We don't support partial writes * when going over the top */ - if ( wrthdr.size + wrthdr.offset > FST_MEMSIZE ) + if ( wrthdr.size > FST_MEMSIZE || wrthdr.offset > FST_MEMSIZE + || wrthdr.size + wrthdr.offset > FST_MEMSIZE ) { return -ENXIO; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sdla_chdlc.c linux/drivers/net/wan/sdla_chdlc.c --- v2.4.9/linux/drivers/net/wan/sdla_chdlc.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/sdla_chdlc.c Sat Sep 8 12:32:09 2001 @@ -48,6 +48,7 @@ * Aug 07, 1998 David Fong Initial version. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sdla_fr.c linux/drivers/net/wan/sdla_fr.c --- v2.4.9/linux/drivers/net/wan/sdla_fr.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/sdla_fr.c Sat Sep 8 12:32:09 2001 @@ -138,6 +138,7 @@ * Jan 02, 1997 Gene Kozin Initial version. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sdla_ft1.c linux/drivers/net/wan/sdla_ft1.c --- v2.4.9/linux/drivers/net/wan/sdla_ft1.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/sdla_ft1.c Sat Sep 8 12:32:09 2001 @@ -20,6 +20,7 @@ * Aug 07, 1998 David Fong Initial version. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sdla_ppp.c linux/drivers/net/wan/sdla_ppp.c --- v2.4.9/linux/drivers/net/wan/sdla_ppp.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/sdla_ppp.c Sat Sep 8 12:32:09 2001 @@ -90,6 +90,7 @@ * Jan 06, 1997 Gene Kozin Initial version. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sdla_x25.c linux/drivers/net/wan/sdla_x25.c --- v2.4.9/linux/drivers/net/wan/sdla_x25.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/sdla_x25.c Sat Sep 8 12:32:09 2001 @@ -81,6 +81,7 @@ * Includes *=====================================================*/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/wanpipe_multppp.c linux/drivers/net/wan/wanpipe_multppp.c --- v2.4.9/linux/drivers/net/wan/wanpipe_multppp.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/wanpipe_multppp.c Sat Sep 8 12:32:09 2001 @@ -17,6 +17,7 @@ * module. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wireless/airport.c linux/drivers/net/wireless/airport.c --- v2.4.9/linux/drivers/net/wireless/airport.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wireless/airport.c Mon Aug 27 09:00:37 2001 @@ -5,6 +5,10 @@ * * Copyright notice & release notes in file orinoco.c * + * Note specific to airport stub: + * + * 0.05 : first version of the new split driver + * 0.06 : fix possible hang on powerup, add sleep support */ #include @@ -25,9 +29,12 @@ #include #include #include +#include +#include #include #include +#include #include "hermes.h" #include "orinoco.h" @@ -40,10 +47,18 @@ struct device_node* node; int irq_requested; int ndev_registered; + int open; /* Common structure (fully included), see orinoco.h */ struct dldwd_priv priv; } dldwd_card_t; +#ifdef CONFIG_PMAC_PBOOK +static int airport_sleep_notify(struct pmu_sleep_notifier *self, int when); +static struct pmu_sleep_notifier airport_sleep_notifier = { + airport_sleep_notify, SLEEP_LEVEL_NET, +}; +#endif + /* * Function prototypes */ @@ -69,24 +84,15 @@ static int airport_init(struct net_device *dev) { dldwd_priv_t *priv = dev->priv; - dldwd_card_t* card = (dldwd_card_t *)priv->card; int rc; TRACE_ENTER(priv->ndev.name); MOD_INC_USE_COUNT; - feature_set_airport_power(card->node, 1); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ); - rc = dldwd_init(dev); - if (rc) { - feature_set_airport_power(card->node, 0); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ); - } - priv->hw_ready = 1; + if (!rc) + priv->hw_ready = 1; MOD_DEC_USE_COUNT; @@ -97,18 +103,20 @@ airport_open(struct net_device *dev) { dldwd_priv_t *priv = dev->priv; + dldwd_card_t* card = (dldwd_card_t *)priv->card; int rc; TRACE_ENTER(priv->ndev.name); - netif_device_attach(dev); rc = dldwd_reset(priv); if (rc) airport_stop(dev); - else - netif_start_queue(dev); + else { + card->open = 1; + netif_device_attach(dev); + } - TRACE_EXIT(priv->ndev.name); +// TRACE_EXIT(priv->ndev.name); return rc; } @@ -117,18 +125,66 @@ airport_stop(struct net_device *dev) { dldwd_priv_t *priv = dev->priv; + dldwd_card_t* card = (dldwd_card_t *)priv->card; TRACE_ENTER(priv->ndev.name); netif_stop_queue(dev); - dldwd_shutdown(priv); + card->open = 0; TRACE_EXIT(priv->ndev.name); return 0; } +#ifdef CONFIG_PMAC_PBOOK +static int +airport_sleep_notify(struct pmu_sleep_notifier *self, int when) +{ + dldwd_priv_t *priv; + struct net_device *ndev; + dldwd_card_t* card; + int rc; + + if (!airport_dev) + return PBOOK_SLEEP_OK; + priv = airport_dev; + ndev = &priv->ndev; + card = (dldwd_card_t *)priv->card; + + switch (when) { + case PBOOK_SLEEP_REQUEST: + break; + case PBOOK_SLEEP_REJECT: + break; + case PBOOK_SLEEP_NOW: + printk(KERN_INFO "%s: Airport entering sleep mode\n", ndev->name); + netif_device_detach(ndev); + if (card->open) + dldwd_shutdown(priv); + disable_irq(ndev->irq); + feature_set_airport_power(card->node, 0); + priv->hw_ready = 0; + break; + case PBOOK_WAKE: + printk(KERN_INFO "%s: Airport waking up\n", ndev->name); + feature_set_airport_power(card->node, 1); + mdelay(200); + hermes_reset(&priv->hw); + priv->hw_ready = 1; + rc = dldwd_reset(priv); + if (rc) + printk(KERN_ERR "airport: Error %d re-initing card !\n", rc); + else if (card->open) + netif_device_attach(ndev); + enable_irq(ndev->irq); + break; + } + return PBOOK_SLEEP_OK; +} +#endif /* CONFIG_PMAC_PBOOK */ + static dldwd_priv_t* airport_attach(struct device_node* of_node) { @@ -175,6 +231,14 @@ hermes_struct_init(hw, ndev->base_addr); + /* Power up card */ + feature_set_airport_power(card->node, 1); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); + + /* Reset it before we get the interrupt */ + hermes_reset(hw); + if (request_irq(ndev->irq, dldwd_interrupt, 0, "Airport", (void *)priv)) { printk(KERN_ERR "airport: Couldn't get IRQ %d\n", ndev->irq); goto failed; @@ -198,6 +262,9 @@ printk(KERN_ERR "airport: Failed to create /proc node for %s\n", ndev->name); +#ifdef CONFIG_PMAC_PBOOK + pmu_register_sleep_notifier(&airport_sleep_notifier); +#endif return priv; failed: @@ -219,6 +286,9 @@ /* Unregister proc entry */ dldwd_proc_dev_cleanup(priv); +#ifdef CONFIG_PMAC_PBOOK + pmu_unregister_sleep_notifier(&airport_sleep_notifier); +#endif if (card->ndev_registered) unregister_netdev(&priv->ndev); card->ndev_registered = 0; @@ -265,8 +335,6 @@ airport_detach(airport_dev); airport_dev = NULL; } - -MODULE_DESCRIPTION("Apple Airport driver"); module_init(init_airport); module_exit(exit_airport); diff -u --recursive --new-file v2.4.9/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog --- v2.4.9/linux/drivers/parport/ChangeLog Mon Aug 27 12:41:43 2001 +++ linux/drivers/parport/ChangeLog Fri Sep 7 18:15:17 2001 @@ -1,3 +1,13 @@ +2001-08-30 Tim Waugh + + * parport_serial.c (parport_serial_pci_probe): Clean-up on partial + registration failure. + +2001-08-14 Tim Waugh + + * parport_pc.c (parport_pc_init_superio): Allow for more than one + SuperIO device. Patch from Rich Lio (ITE). + 2001-08-11 Tim Waugh * parport_pc.c: Support for Titan Electronics cards. diff -u --recursive --new-file v2.4.9/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.4.9/linux/drivers/parport/parport_pc.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/parport/parport_pc.c Fri Sep 7 18:15:17 2001 @@ -2756,17 +2756,20 @@ { const struct pci_device_id *id; struct pci_dev *pdev; + int ret = 0; pci_for_each_dev(pdev) { id = pci_match_device (parport_pc_pci_tbl, pdev); if (id == NULL || id->driver_data >= last_sio) continue; - return parport_pc_superio_info[id->driver_data].probe - (pdev, autoirq, autodma); + if (parport_pc_superio_info[id->driver_data].probe + (pdev, autoirq, autodma)) { + ret++; + } } - return 0; /* zero devices found */ + return ret; /* number of devices found */ } #else static struct pci_driver parport_pc_pci_driver; diff -u --recursive --new-file v2.4.9/linux/drivers/parport/parport_serial.c linux/drivers/parport/parport_serial.c --- v2.4.9/linux/drivers/parport/parport_serial.c Wed Jul 25 17:10:22 2001 +++ linux/drivers/parport/parport_serial.c Fri Sep 7 18:15:17 2001 @@ -296,7 +296,16 @@ return err; } - if (serial_register (dev, id) + parport_register (dev, id)) { + if (parport_register (dev, id)) { + pci_set_drvdata (dev, NULL); + kfree (priv); + return -ENODEV; + } + + if (serial_register (dev, id)) { + int i; + for (i = 0; i < priv->num_par; i++) + parport_pc_unregister_port (priv->port[i]); pci_set_drvdata (dev, NULL); kfree (priv); return -ENODEV; diff -u --recursive --new-file v2.4.9/linux/drivers/pci/names.c linux/drivers/pci/names.c --- v2.4.9/linux/drivers/pci/names.c Mon Oct 2 12:00:16 2000 +++ linux/drivers/pci/names.c Mon Aug 27 08:47:07 2001 @@ -32,9 +32,9 @@ * real memory.. Parse the same file multiple times * to get all the info. */ -#define VENDOR( vendor, name ) static const char __vendorstr_##vendor[] __initdata = name; +#define VENDOR( vendor, name ) static char __vendorstr_##vendor[] __initdata = name; #define ENDVENDOR() -#define DEVICE( vendor, device, name ) static const char __devicestr_##vendor##device[] __initdata = name; +#define DEVICE( vendor, device, name ) static char __devicestr_##vendor##device[] __initdata = name; #include "devlist.h" @@ -43,7 +43,7 @@ #define DEVICE( vendor, device, name ) { 0x##device, 0, __devicestr_##vendor##device }, #include "devlist.h" -static const struct pci_vendor_info __initdata pci_vendor_list[] = { +static struct pci_vendor_info __initdata pci_vendor_list[] = { #define VENDOR( vendor, name ) { 0x##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor }, #define ENDVENDOR() #define DEVICE( vendor, device, name ) diff -u --recursive --new-file v2.4.9/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.4.9/linux/drivers/pci/pci.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/pci/pci.c Sat Sep 1 11:01:28 2001 @@ -307,8 +307,8 @@ /** * pci_save_state - save the PCI configuration space of a device before suspending - * @dev - PCI device that we're dealing with - * @buffer - buffer to hold config space context + * @dev: - PCI device that we're dealing with + * @buffer: - buffer to hold config space context * * @buffer must be large enough to hold the entire PCI 2.2 config space * (>= 64 bytes). @@ -327,8 +327,8 @@ /** * pci_restore_state - Restore the saved state of a PCI device - * @dev - PCI device that we're dealing with - * @buffer - saved PCI config space + * @dev: - PCI device that we're dealing with + * @buffer: - saved PCI config space * */ int @@ -489,6 +489,7 @@ /** * pci_request_regions - Reserved PCI I/O and memory resources * @pdev: PCI device whose resources are to be reserved + * @res_name: Name to be associated with resource. * * Mark all PCI regions associated with PCI device @pdev as * being reserved by owner @res_name. Do not access any diff -u --recursive --new-file v2.4.9/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.4.9/linux/drivers/pci/pci.ids Mon Aug 27 12:41:44 2001 +++ linux/drivers/pci/pci.ids Fri Sep 7 09:28:38 2001 @@ -749,6 +749,7 @@ 0620 620 Host 0630 630 Host 0730 730 Host + 0735 735 Host 0900 SiS900 10/100 Ethernet 1039 0900 SiS900 10/100 Ethernet Adapter 3602 83C602 @@ -781,6 +782,7 @@ 1569 6326 SiS6326 GUI Accelerator 7001 7001 7007 OHCI Compliant FireWire Controller + 7012 SiS7012 PCI Audio Accelerator 7016 SiS7016 10/100 Ethernet Adapter 1039 7016 SiS7016 10/100 Ethernet Adapter 7018 SiS PCI Audio Accelerator @@ -809,6 +811,7 @@ 103a Seiko Epson Corporation 103b Tatung Co. of America 103c Hewlett-Packard Company + 1005 A4977A Visualize EG 1030 J2585A 1031 J2585B 103c 1040 J2973A DeskDirect 10BaseT NIC @@ -1952,7 +1955,7 @@ 0505 VT82C505 0561 VT82C561 0571 Bus Master IDE - 0576 VT82C576 3V [Apollo Master] + 0576 VT82C576 [Apollo Master] 0585 VT82C585VP [Apollo VP1/VPX] 0586 VT82C586/A/B PCI-to-ISA [Apollo VP] 1106 0000 MVP3 ISA Bridge @@ -1975,7 +1978,7 @@ 0926 VT82C926 [Amazon] 1000 VT82C570MV 1106 VT82C570MV - 1571 VT82C416MV + 1571 VT82C576 IDE [Apollo Master] 1595 VT82C595/97 [Apollo VP2/97] 3038 UHCI USB 1234 0925 MVP3 USB Controller @@ -1996,6 +1999,7 @@ 3074 VT8233 PCI to ISA Bridge 3091 VT8633 [Apollo Pro266] 3099 VT8367 [KT266] + 3109 VT8233C PCI to ISA Bridge 5030 VT82C596 ACPI [Apollo PRO] 6100 VT85C100A [Rhine II] 8231 VT8231 [PCI-to-ISA Bridge] @@ -2636,6 +2640,7 @@ 11d2 Intercom Inc. 11d3 Trancell Systems Inc 11d4 Analog Devices + 1889 AD1889 sound chip 11d5 Ikon Corporation 0115 10115 0117 10117 diff -u --recursive --new-file v2.4.9/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.4.9/linux/drivers/pcmcia/yenta.c Wed Jul 25 17:10:22 2001 +++ linux/drivers/pcmcia/yenta.c Wed Aug 29 06:13:40 2001 @@ -702,6 +702,12 @@ u32 start, end; u32 align, size, min, max; unsigned offset; + unsigned mask; + + /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ + mask = ~0xfff; + if (type & IORESOURCE_IO) + mask = ~3; offset = 0x1c + 8*nr; bus = socket->dev->subordinate; @@ -715,8 +721,8 @@ if (!root) return; - start = config_readl(socket, offset); - end = config_readl(socket, offset+4) | 0xfff; + start = config_readl(socket, offset) & mask; + end = config_readl(socket, offset+4) | ~mask; if (start && end > start) { res->start = start; res->end = end; @@ -729,7 +735,7 @@ if (type & IORESOURCE_IO) { align = 1024; size = 256; - min = PCIBIOS_MIN_IO; + min = 0x4000; max = 0xffff; } diff -u --recursive --new-file v2.4.9/linux/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c --- v2.4.9/linux/drivers/s390/block/dasd.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/s390/block/dasd.c Sat Sep 8 12:02:32 2001 @@ -714,10 +714,9 @@ INIT_BLK_DEV (major, do_dasd_request, dasd_get_queue, NULL); - major_info->gendisk.major = major; - major_info->gendisk.next = gendisk_head; major_info->gendisk.sizes = blk_size[major]; - gendisk_head = &major_info->gendisk; + major_info->gendisk.major = major; + add_gendisk (&major_info->gendisk); return major; /* error handling - free the prior allocated memory */ @@ -775,7 +774,6 @@ { int rc = 0; int major; - struct gendisk *dd, *prev = NULL; unsigned long flags; if (major_info == NULL) { @@ -784,20 +782,8 @@ major = major_info->gendisk.major; INIT_BLK_DEV (major, NULL, NULL, NULL); - /* do the gendisk stuff */ - for (dd = gendisk_head; dd; dd = dd->next) { - if (dd == &major_info->gendisk) { - if (prev) - prev->next = dd->next; - else - gendisk_head = dd->next; - break; - } - prev = dd; - } - if (dd == NULL) { - return -ENOENT; - } + del_gendisk (&major_info->gendisk); + kfree (major_info->dasd_device); kfree (major_info->gendisk.part); @@ -2140,13 +2126,7 @@ } for (i = (1 << DASD_PARTN_BITS) - 1; i >= 0; i--) { int major = device->major_info->gendisk.major; - int minor = start + i; - kdev_t devi = MKDEV (major, minor); - struct super_block *sb = get_super (devi); - sync_dev (devi); - if (sb) - invalidate_inodes (sb); - invalidate_buffers (devi); + invalidate_device(MKDEV (major, start+i), 1); } dasd_destroy_partitions(device); dasd_setup_partitions(device); @@ -2517,7 +2497,6 @@ rc = -ENODEV; goto out; } - fsync_dev (inp->i_rdev); /* sync the device */ count = atomic_dec_return (&device->open_count); if ( count == 0) { invalidate_buffers (inp->i_rdev); diff -u --recursive --new-file v2.4.9/linux/drivers/s390/block/xpram.c linux/drivers/s390/block/xpram.c --- v2.4.9/linux/drivers/s390/block/xpram.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/s390/block/xpram.c Mon Aug 27 14:20:21 2001 @@ -625,8 +625,7 @@ */ if (!atomic_dec_return(&(dev->usage))) { /* but flush it right now */ - fsync_dev(inode->i_rdev); - invalidate_buffers(inode->i_rdev); + /* Everything is already flushed by caller -- AV */ } MOD_DEC_USE_COUNT; return(0); diff -u --recursive --new-file v2.4.9/linux/drivers/s390/char/tuball.c linux/drivers/s390/char/tuball.c --- v2.4.9/linux/drivers/s390/char/tuball.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/s390/char/tuball.c Fri Sep 7 09:28:38 2001 @@ -449,7 +449,7 @@ tub3270_con_devno = dp->devno; tubp->cmd = TBC_CONOPEN; - tubp->flags |= TUB_OPEN_STET; + tubp->flags |= TUB_OPEN_STET | TUB_INPUT_HACK; tty3270_size(tubp, &flags); tty3270_aid_init(tubp); tty3270_scl_init(tubp); diff -u --recursive --new-file v2.4.9/linux/drivers/s390/char/tubfs.c linux/drivers/s390/char/tubfs.c --- v2.4.9/linux/drivers/s390/char/tubfs.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/s390/char/tubfs.c Fri Sep 7 09:28:38 2001 @@ -42,11 +42,11 @@ { char name[16]; - sprintf(name, "tub%x", tubp->devno); + sprintf(name, "tub%.3x", tubp->devno); devfs_register(fs3270_devfs_dir, name, DEVFS_FL_DEFAULT, IBM_FS3270_MAJOR, tubp->minor, S_IFCHR | S_IRUSR | S_IWUSR, &fs3270_fops, NULL); - sprintf(name, "tty%x", tubp->devno); + sprintf(name, "tty%.3x", tubp->devno); tty_register_devfs_name(&tty3270_driver, 0, tubp->minor, fs3270_devfs_dir, name); } @@ -56,12 +56,12 @@ char name[16]; devfs_handle_t handle; - sprintf(name, "tub%x", tubp->devno); + sprintf(name, "tub%.3x", tubp->devno); handle = devfs_find_handle (fs3270_devfs_dir, name, IBM_FS3270_MAJOR, tubp->minor, DEVFS_SPECIAL_CHR, 0); devfs_unregister (handle); - sprintf(name, "tty%x", tubp->devno); + sprintf(name, "tty%.3x", tubp->devno); handle = devfs_find_handle (fs3270_devfs_dir, name, IBM_TTY3270_MAJOR, tubp->minor, DEVFS_SPECIAL_CHR, 0); @@ -88,7 +88,7 @@ fs3270_devfs_tub = devfs_register(fs3270_devfs_dir, "tub", DEVFS_FL_DEFAULT, IBM_FS3270_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, + S_IFCHR | S_IRUGO | S_IWUGO, &fs3270_fops, NULL); #else rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops); diff -u --recursive --new-file v2.4.9/linux/drivers/s390/char/tubio.h linux/drivers/s390/char/tubio.h --- v2.4.9/linux/drivers/s390/char/tubio.h Sun Aug 12 13:28:00 2001 +++ linux/drivers/s390/char/tubio.h Fri Sep 7 09:28:38 2001 @@ -282,6 +282,7 @@ #define TUB_UNSOL_DE 0x0200 #define TUB_OPEN_STET 0x0400 /* No screen clear on open */ #define TUB_UE_BUSY 0x0800 +#define TUB_INPUT_HACK 0x1000 /* Early init of command line */ #ifdef CONFIG_TN3270_CONSOLE /* @@ -372,7 +373,7 @@ if (MAJOR(current->tty->device) == IBM_TTY3270_MAJOR) minor = MINOR(current->tty->device); } - if (minor >= tubnummins && minor > 0) + if (minor <= tubnummins && minor > 0) tubp = (*tubminors)[minor]; return tubp; } diff -u --recursive --new-file v2.4.9/linux/drivers/s390/char/tubtty.c linux/drivers/s390/char/tubtty.c --- v2.4.9/linux/drivers/s390/char/tubtty.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/s390/char/tubtty.c Fri Sep 7 09:28:38 2001 @@ -993,7 +993,7 @@ if (tty) len += sprintf(buf+len, " write_wait=%.8x read_wait=%.8x\n", - tty->write_wait, tty->read_wait); + (int)&tty->write_wait, (int)&tty->read_wait); if (tty && ((mp = tty->termios))) len += sprintf(buf+len," iflag=%.8x oflag=%.8x " diff -u --recursive --new-file v2.4.9/linux/drivers/s390/char/tubttybld.c linux/drivers/s390/char/tubttybld.c --- v2.4.9/linux/drivers/s390/char/tubttybld.c Wed Apr 11 19:02:28 2001 +++ linux/drivers/s390/char/tubttybld.c Fri Sep 7 09:28:38 2001 @@ -34,6 +34,8 @@ TUB_BUFADR(GEOM_INPUT, cpp); *(*cpp)++ = '\0'; tubp->tty_oucol = tubp->tty_nextlogx = 0; + *(*cpp)++ = TO_SBA; + TUB_BUFADR(tubp->tty_nextlogx, cpp); } static void @@ -376,12 +378,16 @@ printk(KERN_WARNING "tty3270_build unknown command %d\n", tubp->cmd); return 0; case TBC_OPEN: +tbc_open: + tubp->flags &= ~TUB_INPUT_HACK; chancmd = TC_EWRITEA; tty3270_clear_input_area(tubp, &cp); tty3270_set_status_area(tubp, &cp); tty3270_clear_log_area(tubp, &cp); break; case TBC_UPDLOG: + if (tubp->flags & TUB_INPUT_HACK) + goto tbc_open; chancmd = TC_WRITE; writecc = TW_NONE; tty3270_update_log_area(tubp, &cp); diff -u --recursive --new-file v2.4.9/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c --- v2.4.9/linux/drivers/sbus/char/pcikbd.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/sbus/char/pcikbd.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.59 2001/08/13 14:40:08 davem Exp $ +/* $Id: pcikbd.c,v 1.61 2001/08/18 09:40:46 davem Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,17 @@ "\r\000/"; /* 0x60 - 0x6f */ #endif +#define DEFAULT_KEYB_REP_DELAY 250 +#define DEFAULT_KEYB_REP_RATE 30 /* cps */ + +static struct kbd_repeat kbdrate = { + DEFAULT_KEYB_REP_DELAY, + DEFAULT_KEYB_REP_RATE +}; + +static unsigned char parse_kbd_rate(struct kbd_repeat *r); +static int write_kbd_rate(unsigned char r); + int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode) { if(scancode < SC_LIM || scancode > 255 || keycode > 127) @@ -335,12 +347,7 @@ printk("Prom Leave: Enable Keyboard: no ACK\n"); /* Reset keyboard rate */ - pcikbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE); - if(pcikbd_wait_for_input() != KBD_REPLY_ACK) - printk("Prom Leave: Set rate: no ACK\n"); - pcikbd_write(KBD_DATA_REG, 0x00); - if(pcikbd_wait_for_input() != KBD_REPLY_ACK) - printk("Prom Leave: Set rate: no ACK\n"); + write_kbd_rate(parse_kbd_rate(&kbdrate)); } int pcikbd_translate(unsigned char scancode, unsigned char *keycode, @@ -478,8 +485,81 @@ send_data(KBD_CMD_ENABLE); } -int pcikbd_rate(struct kbd_repeat *rep) +static unsigned char parse_kbd_rate(struct kbd_repeat *r) +{ + static struct r2v { + int rate; + unsigned char val; + } kbd_rates[]={ { 5, 0x14 }, + { 7, 0x10 }, + { 10, 0x0c }, + { 15, 0x08 }, + { 20, 0x04 }, + { 25, 0x02 }, + { 30, 0x00 } }; + static struct d2v { + int delay; + unsigned char val; + } kbd_delays[]={ { 250, 0 }, + { 500, 1 }, + { 750, 2 }, + { 1000, 3 } }; + int rate = 0, delay = 0; + + if (r != NULL) { + int i, new_rate = 30, new_delay = 250; + if (r->rate <= 0) + r->rate = kbdrate.rate; + if (r->delay <= 0) + r->delay = kbdrate.delay; + + for (i = 0; i < sizeof(kbd_rates) / sizeof(struct r2v); i++) { + if (kbd_rates[i].rate == r->rate) { + new_rate = kbd_rates[i].rate; + rate = kbd_rates[i].val; + break; + } + } + for (i=0; i < sizeof(kbd_delays) / sizeof(struct d2v); i++) { + if (kbd_delays[i].delay == r->delay) { + new_delay = kbd_delays[i].delay; + delay = kbd_delays[i].val; + break; + } + } + r->rate = new_rate; + r->delay = new_delay; + } + return (delay << 5) | rate; +} + +static int write_kbd_rate(unsigned char r) +{ + if (!send_data(KBD_CMD_SET_RATE) || !send_data(r)) { + /* re-enable kbd if any errors */ + send_data(KBD_CMD_ENABLE); + return 0; + } + + return 1; +} + +static int pcikbd_rate(struct kbd_repeat *rep) { + unsigned char r; + struct kbd_repeat old_rep; + + if (rep == NULL) + return -EINVAL; + + r = parse_kbd_rate(rep); + memcpy(&old_rep, &kbdrate, sizeof(struct kbd_repeat)); + if (write_kbd_rate(r)) { + memcpy(&kbdrate,rep,sizeof(struct kbd_repeat)); + memcpy(rep,&old_rep,sizeof(struct kbd_repeat)); + return 0; + } + return -EIO; } @@ -641,12 +721,7 @@ if(pcikbd_wait_for_input() != KBD_REPLY_ACK) return "Enable keyboard: no ACK"; - pcikbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE); - if(pcikbd_wait_for_input() != KBD_REPLY_ACK) - return "Set rate: no ACK"; - pcikbd_write(KBD_DATA_REG, 0x00); - if(pcikbd_wait_for_input() != KBD_REPLY_ACK) - return "Set rate: no ACK"; + write_kbd_rate(parse_kbd_rate(&kbdrate)); return NULL; /* success */ } @@ -744,6 +819,7 @@ } kd_mksound = nop_kd_mksound; + kbd_rate = pcikbd_rate; #ifdef __sparc_v9__ edev = 0; diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c --- v2.4.9/linux/drivers/scsi/3w-xxxx.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/scsi/3w-xxxx.c Fri Sep 7 09:28:37 2001 @@ -90,6 +90,16 @@ 1.02.00.007 - Fix possible null pointer dereferences in tw_ioctl(). Remove check for invalid done function pointer from tw_scsi_queue(). + 1.02.00.008 - Set max sectors per io to TW_MAX_SECTORS in tw_findcards(). + Add tw_decode_error() for printing readable error messages. + Print some useful information on certain aen codes. + Add tw_decode_bits() for interpreting status register output. + Make scsi_set_pci_device() for kernels >= 2.4.4 + Fix bug where aen's could be lost before a reset. + Re-add spinlocks in tw_scsi_detect(). + Fix possible null pointer dereference in tw_aen_drain_queue() + during initialization. + Clear pci parity errors during initialization and during io. */ #include @@ -135,7 +145,7 @@ }; /* Globals */ -char *tw_driver_version="1.02.00.007"; +char *tw_driver_version="1.02.00.008"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; @@ -147,6 +157,7 @@ TW_Param *param; unsigned short aen; + dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n"); if (tw_dev->alignment_virtual_address[request_id] == NULL) { printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n"); return 1; @@ -154,6 +165,27 @@ param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; aen = *(unsigned short *)(param->data); dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen); + + /* Print some useful info when certain aen codes come out */ + switch (aen & 0x0ff) { + case TW_AEN_APORT_TIMEOUT: + printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive timeout AEN on port %d, check drive and drive cables.\n", tw_dev->host->host_no, aen >> 8); + break; + case TW_AEN_DRIVE_ERROR: + printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive error AEN on port %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8); + break; + case TW_AEN_SMART_FAIL: + printk(KERN_WARNING "3w-xxxx: scsi%d: Received S.M.A.R.T. threshold AEN on port %d, check drive/cooling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8); + break; + case TW_AEN_SBUF_FAIL: + printk(KERN_WARNING "3w-xxxx: scsi%d: Received SBUF integrity check failure AEN, reseat card or bad card.\n", tw_dev->host->host_no); + break; + default: + printk(KERN_WARNING "3w-xxxx: Received AEN 0x%x\n", aen); + } + + tw_dev->aen_count++; + /* Now queue the code */ tw_dev->aen_queue[tw_dev->aen_tail] = aen; if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { @@ -201,7 +233,7 @@ response_que_addr = tw_dev->registers.response_que_addr; if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 15)) { - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count); return 1; } @@ -258,6 +290,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); return 1; } if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { @@ -322,6 +355,22 @@ dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_QUEUE_FULL.\n"); queue = 1; break; + case TW_AEN_APORT_TIMEOUT: + printk(KERN_WARNING "3w-xxxx: Received drive timeout AEN on port %d, check drive and drive cables.\n", aen >> 8); + queue = 1; + break; + case TW_AEN_DRIVE_ERROR: + printk(KERN_WARNING "3w-xxxx: Received drive error AEN on port %d, check/replace cabling, or possible bad drive.\n", aen >> 8); + queue = 1; + break; + case TW_AEN_SMART_FAIL: + printk(KERN_WARNING "3w-xxxx: Received S.M.A.R.T. threshold AEN on port %d, check drive/cooling, or possible bad drive.\n", aen >> 8); + queue = 1; + break; + case TW_AEN_SBUF_FAIL: + printk(KERN_WARNING "3w-xxxx: Received SBUF integrity check failure AEN, reseat card or bad card.\n"); + queue = 1; + break; default: dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unknown AEN code 0x%x.\n", aen_code); queue = 1; @@ -378,6 +427,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); return 1; } if (tw_dev->command_packet_virtual_address[request_id] == NULL) { @@ -552,6 +602,40 @@ } } /* End tw_copy_mem_info() */ +/* This function will print readable messages from statsu register errors */ +void tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) +{ + dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n"); + switch (status_reg_value & TW_STATUS_UNEXPECTED_BITS) { + case TW_STATUS_PCI_PARITY_ERROR: + printk(KERN_WARNING "3w-xxxx: PCI Parity Error: Reseat card, move card, or buggy device on the bus.\n"); + outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr); + pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PARITY_ERRORS); + break; + case TW_STATUS_MICROCONTROLLER_ERROR: + printk(KERN_WARNING "3w-xxxx: Microcontroller Error.\n"); + break; + } +} /* End tw_decode_bits() */ + +/* This function will print readable messages from flags and status values */ +void tw_decode_error(TW_Device_Extension *tw_dev, unsigned char status, unsigned char flags, unsigned char unit) +{ + dprintk(KERN_WARNING "3w-xxxx: tw_decode_error()\n"); + switch (status) { + case 0xc7: + switch (flags) { + case 0x1b: + printk(KERN_WARNING "3w-xxxx: scsi%d: Drive timeout on unit %d, check drive and drive cables.\n", tw_dev->host->host_no, unit); + break; + case 0x51: + printk(KERN_WARNING "3w-xxxx: scsi%d: Unrecoverable drive error on unit %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, unit); + break; + } + break; + } +} /* End tw_decode_error() */ + /* This function will disable interrupts on the controller */ void tw_disable_interrupts(TW_Device_Extension *tw_dev) { @@ -575,6 +659,7 @@ if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n"); + tw_decode_bits(tw_dev, status_reg_value); return 1; } @@ -583,6 +668,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n"); + tw_decode_bits(tw_dev, status_reg_value); return 1; } } @@ -645,6 +731,11 @@ /* Save pci_dev struct to device extension */ tw_dev->tw_pci_dev = tw_pci_dev; + /* Check for errors and clear them */ + status_reg_value = inl(tw_dev->registers.status_reg_addr); + if (TW_STATUS_ERRORS(status_reg_value)) + tw_decode_bits(tw_dev, status_reg_value); + /* Poll status register for 60 secs for 'Controller Ready' flag */ if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) { printk(KERN_WARNING "3w-xxxx: tw_findcards(): Microcontroller not ready for card %d.\n", numcards); @@ -738,10 +829,18 @@ continue; } + /* Set max sectors per io */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) + host->max_sectors = TW_MAX_SECTORS; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) scsi_set_pci_device(host, tw_pci_dev); +#endif + status_reg_value = inl(tw_dev->registers.status_reg_addr); - dprintk(KERN_NOTICE "scsi%d : Found a 3ware Storage Controller at 0x%x, IRQ: %d P-chip: %d.%d\n", host->host_no, + printk(KERN_NOTICE "scsi%d : Found a 3ware Storage Controller at 0x%x, IRQ: %d, P-chip: %d.%d\n", host->host_no, (u32)(tw_pci_dev->resource[0].start), tw_pci_dev->irq, (status_reg_value & TW_STATUS_MAJOR_VERSION_MASK) >> 28, (status_reg_value & TW_STATUS_MINOR_VERSION_MASK) >> 24); @@ -881,6 +980,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); return 1; } if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { @@ -1034,6 +1134,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); return 1; } if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { @@ -1136,6 +1237,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); return 1; } if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { @@ -1143,14 +1245,12 @@ request_id = (unsigned char)response_queue.u.response_id; if (request_id != 0) { /* unexpected request id */ - printk(KERN_WARNING "3w-xxxx: tw_initia -lize_units(): Unexpected request id.\n"); + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected request id.\n"); return 1; } if (command_packet->status != 0) { /* bad response */ - printk(KERN_WARNING "3w-xxxx: tw_initia -lize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); return 1; } found = 1; @@ -1159,8 +1259,7 @@ } if (found == 0) { /* response never received */ - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No - response.\n"); + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n"); return 1; } @@ -1177,12 +1276,12 @@ /* Now allocate raid5 bounce buffers */ if ((num_raid_five != 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { for (i=0;ibounce_buffer[i] == NULL) { printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bounce buffer allocation failed.\n"); return 1; } - memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*256); + memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*TW_MAX_SECTORS); } } @@ -1282,12 +1381,17 @@ error = 0; if (command_packet->status != 0) { printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit); + tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit); error = 1; } if (tw_dev->state[request_id] != TW_S_POSTED) { printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", request_id, command_packet->byte0.opcode); error = 1; } + if (TW_STATUS_ERRORS(status_reg_value)) { + tw_decode_bits(tw_dev, status_reg_value); + error = 1; + } dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id); /* Check for internal command */ if (tw_dev->srb[request_id] == 0) { @@ -1299,6 +1403,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); } } else { switch (tw_dev->srb[request_id]->cmnd[0]) { @@ -1344,6 +1449,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); } } } @@ -1400,7 +1506,7 @@ param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; memset(param, 0, sizeof(TW_Sector)); - dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id,, ioctl->parameter_size_bytes); + dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes); opcode = ioctl->opcode; switch (opcode) { @@ -1571,8 +1677,10 @@ status_reg_addr = tw_dev->registers.status_reg_addr; status_reg_value = inl(status_reg_addr); - if (tw_check_bits(status_reg_value)) + if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); + } if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) { /* We successfully posted the command packet */ @@ -1737,13 +1845,17 @@ dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_detect()\n"); + printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", tw_driver_version); + /* Check if the kernel has PCI interface compiled in */ if (!pci_present()) { printk(KERN_WARNING "3w-xxxx: tw_scsi_detect(): No pci interface present.\n"); return 0; } + spin_unlock_irq(&io_request_lock); ret = tw_findcards(tw_host); + spin_lock_irq(&io_request_lock); return ret; } /* End tw_scsi_detect() */ @@ -1767,6 +1879,11 @@ return (FAILED); } + /* We have to let AEN requests through before the reset */ + spin_unlock_irq(&io_request_lock); + mdelay(TW_AEN_WAIT_TIME); + spin_lock_irq(&io_request_lock); + spin_lock(&tw_dev->tw_lock); tw_dev->num_aborts++; @@ -1827,6 +1944,11 @@ return (FAILED); } + /* We have to let AEN requests through before the reset */ + spin_unlock_irq(&io_request_lock); + mdelay(TW_AEN_WAIT_TIME); + spin_lock_irq(&io_request_lock); + spin_lock(&tw_dev->tw_lock); tw_dev->num_resets++; @@ -2446,6 +2568,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value); return 1; } if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/3w-xxxx.h linux/drivers/scsi/3w-xxxx.h --- v2.4.9/linux/drivers/scsi/3w-xxxx.h Tue Jul 3 17:08:20 2001 +++ linux/drivers/scsi/3w-xxxx.h Fri Sep 7 09:28:37 2001 @@ -69,6 +69,7 @@ #define TW_CONTROL_ENABLE_INTERRUPTS 0x00000080 #define TW_CONTROL_DISABLE_INTERRUPTS 0x00000040 #define TW_CONTROL_ISSUE_HOST_INTERRUPT 0x00000020 +#define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000 /* Status register bit definitions */ #define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000 @@ -100,6 +101,7 @@ #define TW_DEVICE_ID (0x1000) /* Storage Controller */ #define TW_DEVICE_ID2 (0x1001) /* 7000 series controller */ #define TW_NUMDEVICES 2 +#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100 /* Command packet opcodes */ #define TW_OP_NOP 0x0 @@ -122,6 +124,10 @@ #define TW_AEN_REBUILD_DONE 0x0005 #define TW_AEN_QUEUE_FULL 0x00ff #define TW_AEN_TABLE_UNDEFINED 0x15 +#define TW_AEN_APORT_TIMEOUT 0x0009 +#define TW_AEN_DRIVE_ERROR 0x000A +#define TW_AEN_SMART_FAIL 0x000F +#define TW_AEN_SBUF_FAIL 0x0024 /* Misc defines */ #define TW_ALIGNMENT 0x200 /* 16 D-WORDS */ @@ -143,6 +149,12 @@ #define TW_MAX_AEN_TRIES 100 #define TW_UNIT_ONLINE 1 #define TW_IN_INTR 1 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) +#define TW_MAX_SECTORS 256 +#else +#define TW_MAX_SECTORS 128 +#endif +#define TW_AEN_WAIT_TIME 1000 /* Macros */ #define TW_STATUS_ERRORS(x) \ @@ -308,6 +320,8 @@ int tw_check_errors(TW_Device_Extension *tw_dev); void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev); void tw_clear_host_interrupt(TW_Device_Extension *tw_dev); +void tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value); +void tw_decode_error(TW_Device_Extension *tw_dev, unsigned char status, unsigned char flags, unsigned char unit); void tw_disable_interrupts(TW_Device_Extension *tw_dev); int tw_empty_response_que(TW_Device_Extension *tw_dev); void tw_enable_interrupts(TW_Device_Extension *tw_dev); diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v2.4.9/linux/drivers/scsi/aha1542.c Tue May 1 16:05:00 2001 +++ linux/drivers/scsi/aha1542.c Fri Sep 7 09:28:37 2001 @@ -433,7 +433,7 @@ void (*my_done) (Scsi_Cmnd *) = NULL; int errstatus, mbi, mbo, mbistatus; int number_serviced; - unsigned int flags; + unsigned long flags; struct Scsi_Host *shost; Scsi_Cmnd *SCtmp; int flag; diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpt/dpt_osdutil.h linux/drivers/scsi/dpt/dpt_osdutil.h --- v2.4.9/linux/drivers/scsi/dpt/dpt_osdutil.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpt/dpt_osdutil.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,358 @@ +/* BSDI osd_util.h,v 1.8 1998/06/03 19:14:58 karels Exp */ + +/* + * Copyright (c) 1996-1999 Distributed Processing Technology Corporation + * All rights reserved. + * + * Redistribution and use in source form, with or without modification, are + * permitted provided that redistributions of source code must retain the + * above copyright notice, this list of conditions and the following disclaimer. + * + * This software is provided `as is' by Distributed Processing Technology and + * any express or implied warranties, including, but not limited to, the + * implied warranties of merchantability and fitness for a particular purpose, + * are disclaimed. In no event shall Distributed Processing Technology be + * liable for any direct, indirect, incidental, special, exemplary or + * consequential damages (including, but not limited to, procurement of + * substitute goods or services; loss of use, data, or profits; or business + * interruptions) however caused and on any theory of liability, whether in + * contract, strict liability, or tort (including negligence or otherwise) + * arising in any way out of the use of this driver software, even if advised + * of the possibility of such damage. + * + */ + +#ifndef __OSD_UTIL_H +#define __OSD_UTIL_H + +/*File - OSD_UTIL.H + **************************************************************************** + * + *Description: + * + * This file contains defines and function prototypes that are + *operating system dependent. The resources defined in this file + *are not specific to any particular application. + * + *Copyright Distributed Processing Technology, Corp. + * 140 Candace Dr. + * Maitland, Fl. 32751 USA + * Phone: (407) 830-5522 Fax: (407) 260-5366 + * All Rights Reserved + * + *Author: Doug Anderson + *Date: 1/7/94 + * + *Editors: + * + *Remarks: + * + * + *****************************************************************************/ + + +/*Definitions - Defines & Constants ----------------------------------------- */ + +/*----------------------------- */ +/* Operating system selections: */ +/*----------------------------- */ + +/*#define _DPT_MSDOS */ +/*#define _DPT_WIN_3X */ +/*#define _DPT_WIN_4X */ +/*#define _DPT_WIN_NT */ +/*#define _DPT_NETWARE */ +/*#define _DPT_OS2 */ +/*#define _DPT_SCO */ +/*#define _DPT_UNIXWARE */ +/*#define _DPT_SOLARIS */ +/*#define _DPT_NEXTSTEP */ +/*#define _DPT_BANYAN */ + +/*-------------------------------- */ +/* Include the OS specific defines */ +/*-------------------------------- */ + +/*#define OS_SELECTION From Above List */ +/*#define SEMAPHORE_T ??? */ +/*#define DLL_HANDLE_T ??? */ + +#if (defined(KERNEL) && (defined(__FreeBSD__) || defined(__bsdi__))) +# include "i386/isa/dpt_osd_defs.h" +#else +# include "osd_defs.h" +#endif + +#ifndef DPT_UNALIGNED + #define DPT_UNALIGNED +#endif + +#ifndef DPT_EXPORT + #define DPT_EXPORT +#endif + +#ifndef DPT_IMPORT + #define DPT_IMPORT +#endif + +#ifndef DPT_RUNTIME_IMPORT + #define DPT_RUNTIME_IMPORT DPT_IMPORT +#endif + +/*--------------------- */ +/* OS dependent defines */ +/*--------------------- */ + +#if defined (_DPT_MSDOS) || defined (_DPT_WIN_3X) + #define _DPT_16_BIT +#else + #define _DPT_32_BIT +#endif + +#if defined (_DPT_SCO) || defined (_DPT_UNIXWARE) || defined (_DPT_SOLARIS) || defined (_DPT_AIX) || defined (SNI_MIPS) || defined (_DPT_BSDI) || defined (_DPT_FREE_BSD) || defined(_DPT_LINUX) + #define _DPT_UNIX +#endif + +#if defined (_DPT_WIN_3x) || defined (_DPT_WIN_4X) || defined (_DPT_WIN_NT) \ + || defined (_DPT_OS2) + #define _DPT_DLL_SUPPORT +#endif + +#if !defined (_DPT_MSDOS) && !defined (_DPT_WIN_3X) && !defined (_DPT_NETWARE) + #define _DPT_PREEMPTIVE +#endif + +#if !defined (_DPT_MSDOS) && !defined (_DPT_WIN_3X) + #define _DPT_MULTI_THREADED +#endif + +#if !defined (_DPT_MSDOS) + #define _DPT_MULTI_TASKING +#endif + + /* These exist for platforms that */ + /* chunk when accessing mis-aligned */ + /* data */ +#if defined (SNI_MIPS) || defined (_DPT_SOLARIS) + #if defined (_DPT_BIG_ENDIAN) + #if !defined (_DPT_STRICT_ALIGN) + #define _DPT_STRICT_ALIGN + #endif + #endif +#endif + + /* Determine if in C or C++ mode */ +#ifdef __cplusplus + #define _DPT_CPP +#else + #define _DPT_C +#endif + +/*-------------------------------------------------------------------*/ +/* Under Solaris the compiler refuses to accept code like: */ +/* { {"DPT"}, 0, NULL .... }, */ +/* and complains about the {"DPT"} part by saying "cannot use { } */ +/* to initialize char*". */ +/* */ +/* By defining these ugly macros we can get around this and also */ +/* not have to copy and #ifdef large sections of code. I know that */ +/* these macros are *really* ugly, but they should help reduce */ +/* maintenance in the long run. */ +/* */ +/*-------------------------------------------------------------------*/ +#if !defined (DPTSQO) + #if defined (_DPT_SOLARIS) + #define DPTSQO + #define DPTSQC + #else + #define DPTSQO { + #define DPTSQC } + #endif /* solaris */ +#endif /* DPTSQO */ + + +/*---------------------- */ +/* OS dependent typedefs */ +/*---------------------- */ + +#if defined (_DPT_MSDOS) || defined (_DPT_SCO) + #define BYTE unsigned char + #define WORD unsigned short +#endif + +#ifndef _DPT_TYPEDEFS + #define _DPT_TYPEDEFS + typedef unsigned char uCHAR; + typedef unsigned short uSHORT; + typedef unsigned int uINT; + typedef unsigned long uLONG; + + typedef union { + uCHAR u8[4]; + uSHORT u16[2]; + uLONG u32; + } access_U; +#endif + +#if !defined (NULL) + #define NULL 0 +#endif + + +/*Prototypes - function ----------------------------------------------------- */ + +#ifdef __cplusplus + extern "C" { /* Declare all these functions as "C" functions */ +#endif + +/*------------------------ */ +/* Byte reversal functions */ +/*------------------------ */ + + /* Reverses the byte ordering of a 2 byte variable */ +#if (!defined(osdSwap2)) + uSHORT osdSwap2(DPT_UNALIGNED uSHORT *); +#endif // !osdSwap2 + + /* Reverses the byte ordering of a 4 byte variable and shifts left 8 bits */ +#if (!defined(osdSwap3)) + uLONG osdSwap3(DPT_UNALIGNED uLONG *); +#endif // !osdSwap3 + + +#ifdef _DPT_NETWARE + #include "novpass.h" /* For DPT_Bswapl() prototype */ + /* Inline the byte swap */ + #ifdef __cplusplus + inline uLONG osdSwap4(uLONG *inLong) { + return *inLong = DPT_Bswapl(*inLong); + } + #else + #define osdSwap4(inLong) DPT_Bswapl(inLong) + #endif // cplusplus +#else + /* Reverses the byte ordering of a 4 byte variable */ +# if (!defined(osdSwap4)) + uLONG osdSwap4(DPT_UNALIGNED uLONG *); +# endif // !osdSwap4 + + /* The following functions ALWAYS swap regardless of the * + * presence of DPT_BIG_ENDIAN */ + + uSHORT trueSwap2(DPT_UNALIGNED uSHORT *); + uLONG trueSwap4(DPT_UNALIGNED uLONG *); + +#endif // netware + + +/*-------------------------------------* + * Network order swap functions * + * * + * These functions/macros will be used * + * by the structure insert()/extract() * + * functions. * + * + * We will enclose all structure * + * portability modifications inside * + * #ifdefs. When we are ready, we * + * will #define DPT_PORTABLE to begin * + * using the modifications. * + *-------------------------------------*/ +uLONG netSwap4(uLONG val); + +#if defined (_DPT_BIG_ENDIAN) + +// for big-endian we need to swap + +#ifndef NET_SWAP_2 +#define NET_SWAP_2(x) (((x) >> 8) | ((x) << 8)) +#endif // NET_SWAP_2 + +#ifndef NET_SWAP_4 +#define NET_SWAP_4(x) netSwap4((x)) +#endif // NET_SWAP_4 + +#else + +// for little-endian we don't need to do anything + +#ifndef NET_SWAP_2 +#define NET_SWAP_2(x) (x) +#endif // NET_SWAP_2 + +#ifndef NET_SWAP_4 +#define NET_SWAP_4(x) (x) +#endif // NET_SWAP_4 + +#endif // big endian + + + +/*----------------------------------- */ +/* Run-time loadable module functions */ +/*----------------------------------- */ + + /* Loads the specified run-time loadable DLL */ +DLL_HANDLE_T osdLoadModule(uCHAR *); + /* Unloads the specified run-time loadable DLL */ +uSHORT osdUnloadModule(DLL_HANDLE_T); + /* Returns a pointer to a function inside a run-time loadable DLL */ +void * osdGetFnAddr(DLL_HANDLE_T,uCHAR *); + +/*--------------------------------------- */ +/* Mutually exclusive semaphore functions */ +/*--------------------------------------- */ + + /* Create a named semaphore */ +SEMAPHORE_T osdCreateNamedSemaphore(char *); + /* Create a mutually exlusive semaphore */ +SEMAPHORE_T osdCreateSemaphore(void); + /* create an event semaphore */ +SEMAPHORE_T osdCreateEventSemaphore(void); + /* create a named event semaphore */ +SEMAPHORE_T osdCreateNamedEventSemaphore(char *); + + /* Destroy the specified mutually exclusive semaphore object */ +uSHORT osdDestroySemaphore(SEMAPHORE_T); + /* Request access to the specified mutually exclusive semaphore */ +uLONG osdRequestSemaphore(SEMAPHORE_T,uLONG); + /* Release access to the specified mutually exclusive semaphore */ +uSHORT osdReleaseSemaphore(SEMAPHORE_T); + /* wait for a event to happen */ +uLONG osdWaitForEventSemaphore(SEMAPHORE_T, uLONG); + /* signal an event */ +uLONG osdSignalEventSemaphore(SEMAPHORE_T); + /* reset the event */ +uLONG osdResetEventSemaphore(SEMAPHORE_T); + +/*----------------- */ +/* Thread functions */ +/*----------------- */ + + /* Releases control to the task switcher in non-preemptive */ + /* multitasking operating systems. */ +void osdSwitchThreads(void); + + /* Starts a thread function */ +uLONG osdStartThread(void *,void *); + +/* what is my thread id */ +uLONG osdGetThreadID(void); + +/* wakes up the specifed thread */ +void osdWakeThread(uLONG); + +/* osd sleep for x miliseconds */ +void osdSleep(uLONG); + +#define DPT_THREAD_PRIORITY_LOWEST 0x00 +#define DPT_THREAD_PRIORITY_NORMAL 0x01 +#define DPT_THREAD_PRIORITY_HIGHEST 0x02 + +uCHAR osdSetThreadPriority(uLONG tid, uCHAR priority); + +#ifdef __cplusplus + } /* end the xtern "C" declaration */ +#endif + +#endif /* osd_util_h */ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpt/dpti_i2o.h linux/drivers/scsi/dpt/dpti_i2o.h --- v2.4.9/linux/drivers/scsi/dpt/dpti_i2o.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpt/dpti_i2o.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,464 @@ +#ifndef _SCSI_I2O_H +#define _SCSI_I2O_H + +/* I2O kernel space accessible structures/APIs + * + * (c) Copyright 1999, 2000 Red Hat Software + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + ************************************************************************* + * + * This header file defined the I2O APIs/structures for use by + * the I2O kernel modules. + * + */ + +#ifdef __KERNEL__ /* This file to be included by kernel only */ + +#include + +#include /* Needed for MUTEX init macros */ +#include +#include +#include + + +/* + * Tunable parameters first + */ + +/* How many different OSM's are we allowing */ +#define MAX_I2O_MODULES 64 + +#define I2O_EVT_CAPABILITY_OTHER 0x01 +#define I2O_EVT_CAPABILITY_CHANGED 0x02 + +#define I2O_EVT_SENSOR_STATE_CHANGED 0x01 + +//#ifdef __KERNEL__ /* ioctl stuff only thing exported to users */ + +#define I2O_MAX_MANAGERS 4 + +#include /* Needed for MUTEX init macros */ + +/* + * I2O Interface Objects + */ + +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + +#define DECLARE_MUTEX(name) struct semaphore name=MUTEX + +typedef struct wait_queue *adpt_wait_queue_head_t; +#define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) adpt_wait_queue_head_t wait = NULL +typedef struct wait_queue adpt_wait_queue_t; +#else + +#include +typedef wait_queue_head_t adpt_wait_queue_head_t; +#define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) DECLARE_WAIT_QUEUE_HEAD(wait) +typedef wait_queue_t adpt_wait_queue_t; + +#endif +/* + * message structures + */ + +struct i2o_message +{ + u8 version_offset; + u8 flags; + u16 size; + u32 target_tid:12; + u32 init_tid:12; + u32 function:8; + u32 initiator_context; + /* List follows */ +}; + +struct adpt_device; +struct _adpt_hba; +struct i2o_device +{ + struct i2o_device *next; /* Chain */ + struct i2o_device *prev; + + char dev_name[8]; /* linux /dev name if available */ + i2o_lct_entry lct_data;/* Device LCT information */ + u32 flags; + struct proc_dir_entry* proc_entry; /* /proc dir */ + struct adpt_device *owner; + struct _adpt_hba *controller; /* Controlling IOP */ +}; + +/* + * Each I2O controller has one of these objects + */ + +struct i2o_controller +{ + char name[16]; + int unit; + int type; + int enabled; + + struct notifier_block *event_notifer; /* Events */ + atomic_t users; + struct i2o_device *devices; /* I2O device chain */ + struct i2o_controller *next; /* Controller chain */ + +}; + +/* + * I2O System table entry + */ +struct i2o_sys_tbl_entry +{ + u16 org_id; + u16 reserved1; + u32 iop_id:12; + u32 reserved2:20; + u16 seg_num:12; + u16 i2o_version:4; + u8 iop_state; + u8 msg_type; + u16 frame_size; + u16 reserved3; + u32 last_changed; + u32 iop_capabilities; + u32 inbound_low; + u32 inbound_high; +}; + +struct i2o_sys_tbl +{ + u8 num_entries; + u8 version; + u16 reserved1; + u32 change_ind; + u32 reserved2; + u32 reserved3; + struct i2o_sys_tbl_entry iops[0]; +}; + +/* + * I2O classes / subclasses + */ + +/* Class ID and Code Assignments + * (LCT.ClassID.Version field) + */ +#define I2O_CLASS_VERSION_10 0x00 +#define I2O_CLASS_VERSION_11 0x01 + +/* Class code names + * (from v1.5 Table 6-1 Class Code Assignments.) + */ + +#define I2O_CLASS_EXECUTIVE 0x000 +#define I2O_CLASS_DDM 0x001 +#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010 +#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011 +#define I2O_CLASS_LAN 0x020 +#define I2O_CLASS_WAN 0x030 +#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040 +#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041 +#define I2O_CLASS_SCSI_PERIPHERAL 0x051 +#define I2O_CLASS_ATE_PORT 0x060 +#define I2O_CLASS_ATE_PERIPHERAL 0x061 +#define I2O_CLASS_FLOPPY_CONTROLLER 0x070 +#define I2O_CLASS_FLOPPY_DEVICE 0x071 +#define I2O_CLASS_BUS_ADAPTER_PORT 0x080 +#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090 +#define I2O_CLASS_PEER_TRANSPORT 0x091 + +/* Rest of 0x092 - 0x09f reserved for peer-to-peer classes + */ + +#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff + +/* Subclasses + */ + +#define I2O_SUBCLASS_i960 0x001 +#define I2O_SUBCLASS_HDM 0x020 +#define I2O_SUBCLASS_ISM 0x021 + +/* Operation functions */ + +#define I2O_PARAMS_FIELD_GET 0x0001 +#define I2O_PARAMS_LIST_GET 0x0002 +#define I2O_PARAMS_MORE_GET 0x0003 +#define I2O_PARAMS_SIZE_GET 0x0004 +#define I2O_PARAMS_TABLE_GET 0x0005 +#define I2O_PARAMS_FIELD_SET 0x0006 +#define I2O_PARAMS_LIST_SET 0x0007 +#define I2O_PARAMS_ROW_ADD 0x0008 +#define I2O_PARAMS_ROW_DELETE 0x0009 +#define I2O_PARAMS_TABLE_CLEAR 0x000A + +/* + * I2O serial number conventions / formats + * (circa v1.5) + */ + +#define I2O_SNFORMAT_UNKNOWN 0 +#define I2O_SNFORMAT_BINARY 1 +#define I2O_SNFORMAT_ASCII 2 +#define I2O_SNFORMAT_UNICODE 3 +#define I2O_SNFORMAT_LAN48_MAC 4 +#define I2O_SNFORMAT_WAN 5 + +/* Plus new in v2.0 (Yellowstone pdf doc) + */ + +#define I2O_SNFORMAT_LAN64_MAC 6 +#define I2O_SNFORMAT_DDM 7 +#define I2O_SNFORMAT_IEEE_REG64 8 +#define I2O_SNFORMAT_IEEE_REG128 9 +#define I2O_SNFORMAT_UNKNOWN2 0xff + +/* Transaction Reply Lists (TRL) Control Word structure */ + +#define TRL_SINGLE_FIXED_LENGTH 0x00 +#define TRL_SINGLE_VARIABLE_LENGTH 0x40 +#define TRL_MULTIPLE_FIXED_LENGTH 0x80 + +/* + * Messaging API values + */ + +#define I2O_CMD_ADAPTER_ASSIGN 0xB3 +#define I2O_CMD_ADAPTER_READ 0xB2 +#define I2O_CMD_ADAPTER_RELEASE 0xB5 +#define I2O_CMD_BIOS_INFO_SET 0xA5 +#define I2O_CMD_BOOT_DEVICE_SET 0xA7 +#define I2O_CMD_CONFIG_VALIDATE 0xBB +#define I2O_CMD_CONN_SETUP 0xCA +#define I2O_CMD_DDM_DESTROY 0xB1 +#define I2O_CMD_DDM_ENABLE 0xD5 +#define I2O_CMD_DDM_QUIESCE 0xC7 +#define I2O_CMD_DDM_RESET 0xD9 +#define I2O_CMD_DDM_SUSPEND 0xAF +#define I2O_CMD_DEVICE_ASSIGN 0xB7 +#define I2O_CMD_DEVICE_RELEASE 0xB9 +#define I2O_CMD_HRT_GET 0xA8 +#define I2O_CMD_ADAPTER_CLEAR 0xBE +#define I2O_CMD_ADAPTER_CONNECT 0xC9 +#define I2O_CMD_ADAPTER_RESET 0xBD +#define I2O_CMD_LCT_NOTIFY 0xA2 +#define I2O_CMD_OUTBOUND_INIT 0xA1 +#define I2O_CMD_PATH_ENABLE 0xD3 +#define I2O_CMD_PATH_QUIESCE 0xC5 +#define I2O_CMD_PATH_RESET 0xD7 +#define I2O_CMD_STATIC_MF_CREATE 0xDD +#define I2O_CMD_STATIC_MF_RELEASE 0xDF +#define I2O_CMD_STATUS_GET 0xA0 +#define I2O_CMD_SW_DOWNLOAD 0xA9 +#define I2O_CMD_SW_UPLOAD 0xAB +#define I2O_CMD_SW_REMOVE 0xAD +#define I2O_CMD_SYS_ENABLE 0xD1 +#define I2O_CMD_SYS_MODIFY 0xC1 +#define I2O_CMD_SYS_QUIESCE 0xC3 +#define I2O_CMD_SYS_TAB_SET 0xA3 + +#define I2O_CMD_UTIL_NOP 0x00 +#define I2O_CMD_UTIL_ABORT 0x01 +#define I2O_CMD_UTIL_CLAIM 0x09 +#define I2O_CMD_UTIL_RELEASE 0x0B +#define I2O_CMD_UTIL_PARAMS_GET 0x06 +#define I2O_CMD_UTIL_PARAMS_SET 0x05 +#define I2O_CMD_UTIL_EVT_REGISTER 0x13 +#define I2O_CMD_UTIL_EVT_ACK 0x14 +#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10 +#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D +#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F +#define I2O_CMD_UTIL_LOCK 0x17 +#define I2O_CMD_UTIL_LOCK_RELEASE 0x19 +#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15 + +#define I2O_CMD_SCSI_EXEC 0x81 +#define I2O_CMD_SCSI_ABORT 0x83 +#define I2O_CMD_SCSI_BUSRESET 0x27 + +#define I2O_CMD_BLOCK_READ 0x30 +#define I2O_CMD_BLOCK_WRITE 0x31 +#define I2O_CMD_BLOCK_CFLUSH 0x37 +#define I2O_CMD_BLOCK_MLOCK 0x49 +#define I2O_CMD_BLOCK_MUNLOCK 0x4B +#define I2O_CMD_BLOCK_MMOUNT 0x41 +#define I2O_CMD_BLOCK_MEJECT 0x43 + +#define I2O_PRIVATE_MSG 0xFF + +/* + * Init Outbound Q status + */ + +#define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS 0x01 +#define I2O_CMD_OUTBOUND_INIT_REJECTED 0x02 +#define I2O_CMD_OUTBOUND_INIT_FAILED 0x03 +#define I2O_CMD_OUTBOUND_INIT_COMPLETE 0x04 + +/* + * I2O Get Status State values + */ + +#define ADAPTER_STATE_INITIALIZING 0x01 +#define ADAPTER_STATE_RESET 0x02 +#define ADAPTER_STATE_HOLD 0x04 +#define ADAPTER_STATE_READY 0x05 +#define ADAPTER_STATE_OPERATIONAL 0x08 +#define ADAPTER_STATE_FAILED 0x10 +#define ADAPTER_STATE_FAULTED 0x11 + +/* I2O API function return values */ + +#define I2O_RTN_NO_ERROR 0 +#define I2O_RTN_NOT_INIT 1 +#define I2O_RTN_FREE_Q_EMPTY 2 +#define I2O_RTN_TCB_ERROR 3 +#define I2O_RTN_TRANSACTION_ERROR 4 +#define I2O_RTN_ADAPTER_ALREADY_INIT 5 +#define I2O_RTN_MALLOC_ERROR 6 +#define I2O_RTN_ADPTR_NOT_REGISTERED 7 +#define I2O_RTN_MSG_REPLY_TIMEOUT 8 +#define I2O_RTN_NO_STATUS 9 +#define I2O_RTN_NO_FIRM_VER 10 +#define I2O_RTN_NO_LINK_SPEED 11 + +/* Reply message status defines for all messages */ + +#define I2O_REPLY_STATUS_SUCCESS 0x00 +#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 +#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 +#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 +#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 +#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 +#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 +#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 +#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 +#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A +#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B +#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 + +/* Status codes and Error Information for Parameter functions */ + +#define I2O_PARAMS_STATUS_SUCCESS 0x00 +#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 +#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 +#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 +#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 +#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 +#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 +#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 +#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 +#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 +#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A +#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B +#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C +#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D +#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E +#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F +#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 + +/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error + * messages: Table 3-2 Detailed Status Codes.*/ + +#define I2O_DSC_SUCCESS 0x0000 +#define I2O_DSC_BAD_KEY 0x0002 +#define I2O_DSC_TCL_ERROR 0x0003 +#define I2O_DSC_REPLY_BUFFER_FULL 0x0004 +#define I2O_DSC_NO_SUCH_PAGE 0x0005 +#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006 +#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007 +#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009 +#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A +#define I2O_DSC_DEVICE_LOCKED 0x000B +#define I2O_DSC_DEVICE_RESET 0x000C +#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D +#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E +#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F +#define I2O_DSC_INVALID_OFFSET 0x0010 +#define I2O_DSC_INVALID_PARAMETER 0x0011 +#define I2O_DSC_INVALID_REQUEST 0x0012 +#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013 +#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014 +#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015 +#define I2O_DSC_MISSING_PARAMETER 0x0016 +#define I2O_DSC_TIMEOUT 0x0017 +#define I2O_DSC_UNKNOWN_ERROR 0x0018 +#define I2O_DSC_UNKNOWN_FUNCTION 0x0019 +#define I2O_DSC_UNSUPPORTED_VERSION 0x001A +#define I2O_DSC_DEVICE_BUSY 0x001B +#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C + +/* Device Claim Types */ +#define I2O_CLAIM_PRIMARY 0x01000000 +#define I2O_CLAIM_MANAGEMENT 0x02000000 +#define I2O_CLAIM_AUTHORIZED 0x03000000 +#define I2O_CLAIM_SECONDARY 0x04000000 + +/* Message header defines for VersionOffset */ +#define I2OVER15 0x0001 +#define I2OVER20 0x0002 +/* Default is 1.5, FIXME: Need support for both 1.5 and 2.0 */ +#define I2OVERSION I2OVER15 +#define SGL_OFFSET_0 I2OVERSION +#define SGL_OFFSET_4 (0x0040 | I2OVERSION) +#define SGL_OFFSET_5 (0x0050 | I2OVERSION) +#define SGL_OFFSET_6 (0x0060 | I2OVERSION) +#define SGL_OFFSET_7 (0x0070 | I2OVERSION) +#define SGL_OFFSET_8 (0x0080 | I2OVERSION) +#define SGL_OFFSET_9 (0x0090 | I2OVERSION) +#define SGL_OFFSET_10 (0x00A0 | I2OVERSION) +#define SGL_OFFSET_12 (0x00C0 | I2OVERSION) + +#define TRL_OFFSET_5 (0x0050 | I2OVERSION) +#define TRL_OFFSET_6 (0x0060 | I2OVERSION) + + /* msg header defines for MsgFlags */ +#define MSG_STATIC 0x0100 +#define MSG_64BIT_CNTXT 0x0200 +#define MSG_MULTI_TRANS 0x1000 +#define MSG_FAIL 0x2000 +#define MSG_LAST 0x4000 +#define MSG_REPLY 0x8000 + + /* minimum size msg */ +#define THREE_WORD_MSG_SIZE 0x00030000 +#define FOUR_WORD_MSG_SIZE 0x00040000 +#define FIVE_WORD_MSG_SIZE 0x00050000 +#define SIX_WORD_MSG_SIZE 0x00060000 +#define SEVEN_WORD_MSG_SIZE 0x00070000 +#define EIGHT_WORD_MSG_SIZE 0x00080000 +#define NINE_WORD_MSG_SIZE 0x00090000 +#define TEN_WORD_MSG_SIZE 0x000A0000 +#define I2O_MESSAGE_SIZE(x) ((x)<<16) + + +/* Special TID Assignments */ + +#define ADAPTER_TID 0 +#define HOST_TID 1 + +#define MSG_FRAME_SIZE 128 +#define NMBR_MSG_FRAMES 128 + +#define MSG_POOL_SIZE 16384 + +#define I2O_POST_WAIT_OK 0 +#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT + + +#endif /* __KERNEL__ */ + +#endif /* _SCSI_I2O_H */ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpt/dpti_ioctl.h linux/drivers/scsi/dpt/dpti_ioctl.h --- v2.4.9/linux/drivers/scsi/dpt/dpti_ioctl.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpt/dpti_ioctl.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,139 @@ +/*************************************************************************** + dpti_ioctl.h - description + ------------------- + begin : Thu Sep 7 2000 + copyright : (C) 2001 by Adaptec + email : deanna_bonds@adaptec.com + + See README.dpti for history, notes, license info, and credits + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/*************************************************************************** + * This file is generated from osd_unix.h * + * *************************************************************************/ + +#ifndef _dpti_ioctl_h +#define _dpti_ioctl_h + +// IOCTL interface commands + +#ifndef _IOWR +# define _IOWR(x,y,z) (((x)<<8)|y) +#endif +#ifndef _IOW +# define _IOW(x,y,z) (((x)<<8)|y) +#endif +#ifndef _IOR +# define _IOR(x,y,z) (((x)<<8)|y) +#endif +#ifndef _IO +# define _IO(x,y) (((x)<<8)|y) +#endif +/* EATA PassThrough Command */ +#define EATAUSRCMD _IOWR('D',65,EATA_CP) +/* Set Debug Level If Enabled */ +#define DPT_DEBUG _IOW('D',66,int) +/* Get Signature Structure */ +#define DPT_SIGNATURE _IOR('D',67,dpt_sig_S) +#if defined __bsdi__ +#define DPT_SIGNATURE_PACKED _IOR('D',67,dpt_sig_S_Packed) +#endif +/* Get Number Of DPT Adapters */ +#define DPT_NUMCTRLS _IOR('D',68,int) +/* Get Adapter Info Structure */ +#define DPT_CTRLINFO _IOR('D',69,CtrlInfo) +/* Get Statistics If Enabled */ +#define DPT_STATINFO _IO('D',70) +/* Clear Stats If Enabled */ +#define DPT_CLRSTAT _IO('D',71) +/* Get System Info Structure */ +#define DPT_SYSINFO _IOR('D',72,sysInfo_S) +/* Set Timeout Value */ +#define DPT_TIMEOUT _IO('D',73) +/* Get config Data */ +#define DPT_CONFIG _IO('D',74) +/* Get Blink LED Code */ +#define DPT_BLINKLED _IOR('D',75,int) +/* Get Statistical information (if available) */ +#define DPT_STATS_INFO _IOR('D',80,STATS_DATA) +/* Clear the statistical information */ +#define DPT_STATS_CLEAR _IO('D',81) +/* Get Performance metrics */ +#define DPT_PERF_INFO _IOR('D',82,dpt_perf_t) +/* Send an I2O command */ +#define I2OUSRCMD _IO('D',76) +/* Inform driver to re-acquire LCT information */ +#define I2ORESCANCMD _IO('D',77) +/* Inform driver to reset adapter */ +#define I2ORESETCMD _IO('D',78) +/* See if the target is mounted */ +#define DPT_TARGET_BUSY _IOR('D',79, TARGET_BUSY_T) + + + /* Structure Returned From Get Controller Info */ + +typedef struct { + uCHAR state; /* Operational state */ + uCHAR id; /* Host adapter SCSI id */ + int vect; /* Interrupt vector number */ + int base; /* Base I/O address */ + int njobs; /* # of jobs sent to HA */ + int qdepth; /* Controller queue depth. */ + int wakebase; /* mpx wakeup base index. */ + uLONG SGsize; /* Scatter/Gather list size. */ + unsigned heads; /* heads for drives on cntlr. */ + unsigned sectors; /* sectors for drives on cntlr. */ + uCHAR do_drive32; /* Flag for Above 16 MB Ability */ + uCHAR BusQuiet; /* SCSI Bus Quiet Flag */ + char idPAL[4]; /* 4 Bytes Of The ID Pal */ + uCHAR primary; /* 1 For Primary, 0 For Secondary */ + uCHAR eataVersion; /* EATA Version */ + uLONG cpLength; /* EATA Command Packet Length */ + uLONG spLength; /* EATA Status Packet Length */ + uCHAR drqNum; /* DRQ Index (0,5,6,7) */ + uCHAR flag1; /* EATA Flags 1 (Byte 9) */ + uCHAR flag2; /* EATA Flags 2 (Byte 30) */ +} CtrlInfo; + +typedef struct { + uSHORT length; // Remaining length of this + uSHORT drvrHBAnum; // Relative HBA # used by the driver + uLONG baseAddr; // Base I/O address + uSHORT blinkState; // Blink LED state (0=Not in blink LED) + uCHAR pciBusNum; // PCI Bus # (Optional) + uCHAR pciDeviceNum; // PCI Device # (Optional) + uSHORT hbaFlags; // Miscellaneous HBA flags + uSHORT Interrupt; // Interrupt set for this device. +# if (defined(_DPT_ARC)) + uLONG baseLength; + ADAPTER_OBJECT *AdapterObject; + LARGE_INTEGER DmaLogicalAddress; + PVOID DmaVirtualAddress; + LARGE_INTEGER ReplyLogicalAddress; + PVOID ReplyVirtualAddress; +# else + uLONG reserved1; // Reserved for future expansion + uLONG reserved2; // Reserved for future expansion + uLONG reserved3; // Reserved for future expansion +# endif +} drvrHBAinfo_S; + +typedef struct TARGET_BUSY +{ + uLONG channel; + uLONG id; + uLONG lun; + uLONG isBusy; +} TARGET_BUSY_T; + +#endif + diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpt/dptsig.h linux/drivers/scsi/dpt/dptsig.h --- v2.4.9/linux/drivers/scsi/dpt/dptsig.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpt/dptsig.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,339 @@ +/* BSDI dptsig.h,v 1.7 1998/06/03 19:15:00 karels Exp */ + +/* + * Copyright (c) 1996-1999 Distributed Processing Technology Corporation + * All rights reserved. + * + * Redistribution and use in source form, with or without modification, are + * permitted provided that redistributions of source code must retain the + * above copyright notice, this list of conditions and the following disclaimer. + * + * This software is provided `as is' by Distributed Processing Technology and + * any express or implied warranties, including, but not limited to, the + * implied warranties of merchantability and fitness for a particular purpose, + * are disclaimed. In no event shall Distributed Processing Technology be + * liable for any direct, indirect, incidental, special, exemplary or + * consequential damages (including, but not limited to, procurement of + * substitute goods or services; loss of use, data, or profits; or business + * interruptions) however caused and on any theory of liability, whether in + * contract, strict liability, or tort (including negligence or otherwise) + * arising in any way out of the use of this driver software, even if advised + * of the possibility of such damage. + * + */ + +#ifndef __DPTSIG_H_ +#define __DPTSIG_H_ +#ifdef _SINIX_ADDON +#include "dpt.h" +#endif +/* DPT SIGNATURE SPEC AND HEADER FILE */ +/* Signature Version 1 (sorry no 'A') */ + +/* to make sure we are talking the same size under all OS's */ +typedef unsigned char sigBYTE; +typedef unsigned short sigWORD; +#if (defined(_MULTI_DATAMODEL) && defined(sun) && !defined(_ILP32)) +typedef uint32_t sigLONG; +#else +typedef unsigned long sigLONG; +#endif + +/* + * use sigWORDLittleEndian for: + * dsCapabilities + * dsDeviceSupp + * dsAdapterSupp + * dsApplication + * use sigLONGLittleEndian for: + * dsOS + * so that the sig can be standardised to Little Endian + */ +#if (defined(_DPT_BIG_ENDIAN)) +# define sigWORDLittleEndian(x) ((((x)&0xFF)<<8)|(((x)>>8)&0xFF)) +# define sigLONGLittleEndian(x) \ + ((((x)&0xFF)<<24) | \ + (((x)&0xFF00)<<8) | \ + (((x)&0xFF0000L)>>8) | \ + (((x)&0xFF000000L)>>24)) +#else +# define sigWORDLittleEndian(x) (x) +# define sigLONGLittleEndian(x) (x) +#endif + +/* must make sure the structure is not word or double-word aligned */ +/* --------------------------------------------------------------- */ +/* Borland will ignore the following pragma: */ +/* Word alignment is OFF by default. If in the, IDE make */ +/* sure that Options | Compiler | Code Generation | Word Alignment */ +/* is not checked. If using BCC, do not use the -a option. */ + +#ifndef NO_PACK +#if defined (_DPT_AIX) +#pragma options align=packed +#else +#pragma pack(1) +#endif /* aix */ +#endif +/* For the Macintosh */ +#if STRUCTALIGNMENTSUPPORTED +#pragma options align=mac68k +#endif + + +/* Current Signature Version - sigBYTE dsSigVersion; */ +/* ------------------------------------------------------------------ */ +#define SIG_VERSION 1 + +/* Processor Family - sigBYTE dsProcessorFamily; DISTINCT VALUES */ +/* ------------------------------------------------------------------ */ +/* What type of processor the file is meant to run on. */ +/* This will let us know whether to read sigWORDs as high/low or low/high. */ +#define PROC_INTEL 0x00 /* Intel 80x86 */ +#define PROC_MOTOROLA 0x01 /* Motorola 68K */ +#define PROC_MIPS4000 0x02 /* MIPS RISC 4000 */ +#define PROC_ALPHA 0x03 /* DEC Alpha */ +#define PROC_POWERPC 0x04 /* IBM Power PC */ +#define PROC_i960 0x05 /* Intel i960 */ +#define PROC_ULTRASPARC 0x06 /* SPARC processor */ + +/* Specific Minimim Processor - sigBYTE dsProcessor; FLAG BITS */ +/* ------------------------------------------------------------------ */ +/* Different bit definitions dependent on processor_family */ + +/* PROC_INTEL: */ +#define PROC_8086 0x01 /* Intel 8086 */ +#define PROC_286 0x02 /* Intel 80286 */ +#define PROC_386 0x04 /* Intel 80386 */ +#define PROC_486 0x08 /* Intel 80486 */ +#define PROC_PENTIUM 0x10 /* Intel 586 aka P5 aka Pentium */ +#define PROC_SEXIUM 0x20 /* Intel 686 aka P6 aka Pentium Pro or MMX */ + +/* PROC_i960: */ +#define PROC_960RX 0x01 /* Intel 80960RC/RD */ +#define PROC_960HX 0x02 /* Intel 80960HA/HD/HT */ + +/* PROC_MOTOROLA: */ +#define PROC_68000 0x01 /* Motorola 68000 */ +#define PROC_68010 0x02 /* Motorola 68010 */ +#define PROC_68020 0x04 /* Motorola 68020 */ +#define PROC_68030 0x08 /* Motorola 68030 */ +#define PROC_68040 0x10 /* Motorola 68040 */ + +/* PROC_POWERPC */ +#define PROC_PPC601 0x01 /* PowerPC 601 */ +#define PROC_PPC603 0x02 /* PowerPC 603 */ +#define PROC_PPC604 0x04 /* PowerPC 604 */ + +/* PROC_MIPS4000: */ +#define PROC_R4000 0x01 /* MIPS R4000 */ + +/* Filetype - sigBYTE dsFiletype; DISTINCT VALUES */ +/* ------------------------------------------------------------------ */ +#define FT_EXECUTABLE 0 /* Executable Program */ +#define FT_SCRIPT 1 /* Script/Batch File??? */ +#define FT_HBADRVR 2 /* HBA Driver */ +#define FT_OTHERDRVR 3 /* Other Driver */ +#define FT_IFS 4 /* Installable Filesystem Driver */ +#define FT_ENGINE 5 /* DPT Engine */ +#define FT_COMPDRVR 6 /* Compressed Driver Disk */ +#define FT_LANGUAGE 7 /* Foreign Language file */ +#define FT_FIRMWARE 8 /* Downloadable or actual Firmware */ +#define FT_COMMMODL 9 /* Communications Module */ +#define FT_INT13 10 /* INT 13 style HBA Driver */ +#define FT_HELPFILE 11 /* Help file */ +#define FT_LOGGER 12 /* Event Logger */ +#define FT_INSTALL 13 /* An Install Program */ +#define FT_LIBRARY 14 /* Storage Manager Real-Mode Calls */ +#define FT_RESOURCE 15 /* Storage Manager Resource File */ +#define FT_MODEM_DB 16 /* Storage Manager Modem Database */ + +/* Filetype flags - sigBYTE dsFiletypeFlags; FLAG BITS */ +/* ------------------------------------------------------------------ */ +#define FTF_DLL 0x01 /* Dynamic Link Library */ +#define FTF_NLM 0x02 /* Netware Loadable Module */ +#define FTF_OVERLAYS 0x04 /* Uses overlays */ +#define FTF_DEBUG 0x08 /* Debug version */ +#define FTF_TSR 0x10 /* TSR */ +#define FTF_SYS 0x20 /* DOS Loadable driver */ +#define FTF_PROTECTED 0x40 /* Runs in protected mode */ +#define FTF_APP_SPEC 0x80 /* Application Specific */ +#define FTF_ROM (FTF_SYS|FTF_TSR) /* Special Case */ + +/* OEM - sigBYTE dsOEM; DISTINCT VALUES */ +/* ------------------------------------------------------------------ */ +#define OEM_DPT 0 /* DPT */ +#define OEM_ATT 1 /* ATT */ +#define OEM_NEC 2 /* NEC */ +#define OEM_ALPHA 3 /* Alphatronix */ +#define OEM_AST 4 /* AST */ +#define OEM_OLIVETTI 5 /* Olivetti */ +#define OEM_SNI 6 /* Siemens/Nixdorf */ +#define OEM_SUN 7 /* SUN Microsystems */ + +/* Operating System - sigLONG dsOS; FLAG BITS */ +/* ------------------------------------------------------------------ */ +#define OS_DOS 0x00000001 /* PC/MS-DOS */ +#define OS_WINDOWS 0x00000002 /* Microsoft Windows 3.x */ +#define OS_WINDOWS_NT 0x00000004 /* Microsoft Windows NT */ +#define OS_OS2M 0x00000008 /* OS/2 1.2.x,MS 1.3.0,IBM 1.3.x - Monolithic */ +#define OS_OS2L 0x00000010 /* Microsoft OS/2 1.301 - LADDR */ +#define OS_OS22x 0x00000020 /* IBM OS/2 2.x */ +#define OS_NW286 0x00000040 /* Novell NetWare 286 */ +#define OS_NW386 0x00000080 /* Novell NetWare 386 */ +#define OS_GEN_UNIX 0x00000100 /* Generic Unix */ +#define OS_SCO_UNIX 0x00000200 /* SCO Unix */ +#define OS_ATT_UNIX 0x00000400 /* ATT Unix */ +#define OS_UNIXWARE 0x00000800 /* USL Unix */ +#define OS_INT_UNIX 0x00001000 /* Interactive Unix */ +#define OS_SOLARIS 0x00002000 /* SunSoft Solaris */ +#define OS_QNX 0x00004000 /* QNX for Tom Moch */ +#define OS_NEXTSTEP 0x00008000 /* NeXTSTEP/OPENSTEP/MACH */ +#define OS_BANYAN 0x00010000 /* Banyan Vines */ +#define OS_OLIVETTI_UNIX 0x00020000/* Olivetti Unix */ +#define OS_MAC_OS 0x00040000 /* Mac OS */ +#define OS_WINDOWS_95 0x00080000 /* Microsoft Windows '95 */ +#define OS_NW4x 0x00100000 /* Novell Netware 4.x */ +#define OS_BSDI_UNIX 0x00200000 /* BSDi Unix BSD/OS 2.0 and up */ +#define OS_AIX_UNIX 0x00400000 /* AIX Unix */ +#define OS_FREE_BSD 0x00800000 /* FreeBSD Unix */ +#define OS_LINUX 0x01000000 /* Linux */ +#define OS_DGUX_UNIX 0x02000000 /* Data General Unix */ +#define OS_SINIX_N 0x04000000 /* SNI SINIX-N */ +#define OS_PLAN9 0x08000000 /* ATT Plan 9 */ +#define OS_TSX 0x10000000 /* SNH TSX-32 */ + +#define OS_OTHER 0x80000000 /* Other */ + +/* Capabilities - sigWORD dsCapabilities; FLAG BITS */ +/* ------------------------------------------------------------------ */ +#define CAP_RAID0 0x0001 /* RAID-0 */ +#define CAP_RAID1 0x0002 /* RAID-1 */ +#define CAP_RAID3 0x0004 /* RAID-3 */ +#define CAP_RAID5 0x0008 /* RAID-5 */ +#define CAP_SPAN 0x0010 /* Spanning */ +#define CAP_PASS 0x0020 /* Provides passthrough */ +#define CAP_OVERLAP 0x0040 /* Passthrough supports overlapped commands */ +#define CAP_ASPI 0x0080 /* Supports ASPI Command Requests */ +#define CAP_ABOVE16MB 0x0100 /* ISA Driver supports greater than 16MB */ +#define CAP_EXTEND 0x8000 /* Extended info appears after description */ +#ifdef SNI_MIPS +#define CAP_CACHEMODE 0x1000 /* dpt_force_cache is set in driver */ +#endif + +/* Devices Supported - sigWORD dsDeviceSupp; FLAG BITS */ +/* ------------------------------------------------------------------ */ +#define DEV_DASD 0x0001 /* DASD (hard drives) */ +#define DEV_TAPE 0x0002 /* Tape drives */ +#define DEV_PRINTER 0x0004 /* Printers */ +#define DEV_PROC 0x0008 /* Processors */ +#define DEV_WORM 0x0010 /* WORM drives */ +#define DEV_CDROM 0x0020 /* CD-ROM drives */ +#define DEV_SCANNER 0x0040 /* Scanners */ +#define DEV_OPTICAL 0x0080 /* Optical Drives */ +#define DEV_JUKEBOX 0x0100 /* Jukebox */ +#define DEV_COMM 0x0200 /* Communications Devices */ +#define DEV_OTHER 0x0400 /* Other Devices */ +#define DEV_ALL 0xFFFF /* All SCSI Devices */ + +/* Adapters Families Supported - sigWORD dsAdapterSupp; FLAG BITS */ +/* ------------------------------------------------------------------ */ +#define ADF_2001 0x0001 /* PM2001 */ +#define ADF_2012A 0x0002 /* PM2012A */ +#define ADF_PLUS_ISA 0x0004 /* PM2011,PM2021 */ +#define ADF_PLUS_EISA 0x0008 /* PM2012B,PM2022 */ +#define ADF_SC3_ISA 0x0010 /* PM2021 */ +#define ADF_SC3_EISA 0x0020 /* PM2022,PM2122, etc */ +#define ADF_SC3_PCI 0x0040 /* SmartCache III PCI */ +#define ADF_SC4_ISA 0x0080 /* SmartCache IV ISA */ +#define ADF_SC4_EISA 0x0100 /* SmartCache IV EISA */ +#define ADF_SC4_PCI 0x0200 /* SmartCache IV PCI */ +#define ADF_SC5_PCI 0x0400 /* Fifth Generation I2O products */ +/* + * Combinations of products + */ +#define ADF_ALL_2000 (ADF_2001|ADF_2012A) +#define ADF_ALL_PLUS (ADF_PLUS_ISA|ADF_PLUS_EISA) +#define ADF_ALL_SC3 (ADF_SC3_ISA|ADF_SC3_EISA|ADF_SC3_PCI) +#define ADF_ALL_SC4 (ADF_SC4_ISA|ADF_SC4_EISA|ADF_SC4_PCI) +#define ADF_ALL_SC5 (ADF_SC5_PCI) +/* All EATA Cacheing Products */ +#define ADF_ALL_CACHE (ADF_ALL_PLUS|ADF_ALL_SC3|ADF_ALL_SC4) +/* All EATA Bus Mastering Products */ +#define ADF_ALL_MASTER (ADF_2012A|ADF_ALL_CACHE) +/* All EATA Adapter Products */ +#define ADF_ALL_EATA (ADF_2001|ADF_ALL_MASTER) +#define ADF_ALL ADF_ALL_EATA + +/* Application - sigWORD dsApplication; FLAG BITS */ +/* ------------------------------------------------------------------ */ +#define APP_DPTMGR 0x0001 /* DPT Storage Manager */ +#define APP_ENGINE 0x0002 /* DPT Engine */ +#define APP_SYTOS 0x0004 /* Sytron Sytos Plus */ +#define APP_CHEYENNE 0x0008 /* Cheyenne ARCServe + ARCSolo */ +#define APP_MSCDEX 0x0010 /* Microsoft CD-ROM extensions */ +#define APP_NOVABACK 0x0020 /* NovaStor Novaback */ +#define APP_AIM 0x0040 /* Archive Information Manager */ + +/* Requirements - sigBYTE dsRequirements; FLAG BITS */ +/* ------------------------------------------------------------------ */ +#define REQ_SMARTROM 0x01 /* Requires SmartROM to be present */ +#define REQ_DPTDDL 0x02 /* Requires DPTDDL.SYS to be loaded */ +#define REQ_HBA_DRIVER 0x04 /* Requires an HBA driver to be loaded */ +#define REQ_ASPI_TRAN 0x08 /* Requires an ASPI Transport Modules */ +#define REQ_ENGINE 0x10 /* Requires a DPT Engine to be loaded */ +#define REQ_COMM_ENG 0x20 /* Requires a DPT Communications Engine */ + +/* + * You may adjust dsDescription_size with an override to a value less than + * 50 so that the structure allocates less real space. + */ +#if (!defined(dsDescription_size)) +# define dsDescription_size 50 +#endif + +typedef struct dpt_sig { + char dsSignature[6]; /* ALWAYS "dPtSiG" */ + sigBYTE dsSigVersion; /* signature version (currently 1) */ + sigBYTE dsProcessorFamily; /* what type of processor */ + sigBYTE dsProcessor; /* precise processor */ + sigBYTE dsFiletype; /* type of file */ + sigBYTE dsFiletypeFlags; /* flags to specify load type, etc. */ + sigBYTE dsOEM; /* OEM file was created for */ + sigLONG dsOS; /* which Operating systems */ + sigWORD dsCapabilities; /* RAID levels, etc. */ + sigWORD dsDeviceSupp; /* Types of SCSI devices supported */ + sigWORD dsAdapterSupp; /* DPT adapter families supported */ + sigWORD dsApplication; /* applications file is for */ + sigBYTE dsRequirements; /* Other driver dependencies */ + sigBYTE dsVersion; /* 1 */ + sigBYTE dsRevision; /* 'J' */ + sigBYTE dsSubRevision; /* '9' ' ' if N/A */ + sigBYTE dsMonth; /* creation month */ + sigBYTE dsDay; /* creation day */ + sigBYTE dsYear; /* creation year since 1980 (1993=13) */ + /* description (NULL terminated) */ + char dsDescription[dsDescription_size]; +} dpt_sig_S; +/* 32 bytes minimum - with no description. Put NULL at description[0] */ +/* 81 bytes maximum - with 49 character description plus NULL. */ + +/* This line added at Roycroft's request */ +/* Microsoft's NT compiler gets confused if you do a pack and don't */ +/* restore it. */ + +#ifndef NO_UNPACK +#if defined (_DPT_AIX) +#pragma options align=reset +#elif defined (UNPACK_FOUR) +#pragma pack(4) +#else +#pragma pack() +#endif /* aix */ +#endif +/* For the Macintosh */ +#if STRUCTALIGNMENTSUPPORTED +#pragma options align=reset +#endif + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpt/osd_defs.h linux/drivers/scsi/dpt/osd_defs.h --- v2.4.9/linux/drivers/scsi/dpt/osd_defs.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpt/osd_defs.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,79 @@ +/* BSDI osd_defs.h,v 1.4 1998/06/03 19:14:58 karels Exp */ +/* + * Copyright (c) 1996-1999 Distributed Processing Technology Corporation + * All rights reserved. + * + * Redistribution and use in source form, with or without modification, are + * permitted provided that redistributions of source code must retain the + * above copyright notice, this list of conditions and the following disclaimer. + * + * This software is provided `as is' by Distributed Processing Technology and + * any express or implied warranties, including, but not limited to, the + * implied warranties of merchantability and fitness for a particular purpose, + * are disclaimed. In no event shall Distributed Processing Technology be + * liable for any direct, indirect, incidental, special, exemplary or + * consequential damages (including, but not limited to, procurement of + * substitute goods or services; loss of use, data, or profits; or business + * interruptions) however caused and on any theory of liability, whether in + * contract, strict liability, or tort (including negligence or otherwise) + * arising in any way out of the use of this driver software, even if advised + * of the possibility of such damage. + * + */ + +#ifndef _OSD_DEFS_H +#define _OSD_DEFS_H + +/*File - OSD_DEFS.H + **************************************************************************** + * + *Description: + * + * This file contains the OS dependent defines. This file is included + *in osd_util.h and provides the OS specific defines for that file. + * + *Copyright Distributed Processing Technology, Corp. + * 140 Candace Dr. + * Maitland, Fl. 32751 USA + * Phone: (407) 830-5522 Fax: (407) 260-5366 + * All Rights Reserved + * + *Author: Doug Anderson + *Date: 1/31/94 + * + *Editors: + * + *Remarks: + * + * + *****************************************************************************/ + + +/*Definitions - Defines & Constants ----------------------------------------- */ + + /* Define the operating system */ +#if (defined(__linux__)) +# define _DPT_LINUX +#elif (defined(__bsdi__)) +# define _DPT_BSDI +#elif (defined(__FreeBSD__)) +# define _DPT_FREE_BSD +#else +# define _DPT_SCO +#endif + +#if defined (ZIL_CURSES) +#define _DPT_CURSES +#else +#define _DPT_MOTIF +#endif + + /* Redefine 'far' to nothing - no far pointer type required in UNIX */ +#define far + + /* Define the mutually exclusive semaphore type */ +#define SEMAPHORE_T unsigned int * + /* Define a handle to a DLL */ +#define DLL_HANDLE_T unsigned int * + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpt/osd_util.h linux/drivers/scsi/dpt/osd_util.h --- v2.4.9/linux/drivers/scsi/dpt/osd_util.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpt/osd_util.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,358 @@ +/* BSDI osd_util.h,v 1.8 1998/06/03 19:14:58 karels Exp */ + +/* + * Copyright (c) 1996-1999 Distributed Processing Technology Corporation + * All rights reserved. + * + * Redistribution and use in source form, with or without modification, are + * permitted provided that redistributions of source code must retain the + * above copyright notice, this list of conditions and the following disclaimer. + * + * This software is provided `as is' by Distributed Processing Technology and + * any express or implied warranties, including, but not limited to, the + * implied warranties of merchantability and fitness for a particular purpose, + * are disclaimed. In no event shall Distributed Processing Technology be + * liable for any direct, indirect, incidental, special, exemplary or + * consequential damages (including, but not limited to, procurement of + * substitute goods or services; loss of use, data, or profits; or business + * interruptions) however caused and on any theory of liability, whether in + * contract, strict liability, or tort (including negligence or otherwise) + * arising in any way out of the use of this driver software, even if advised + * of the possibility of such damage. + * + */ + +#ifndef __OSD_UTIL_H +#define __OSD_UTIL_H + +/*File - OSD_UTIL.H + **************************************************************************** + * + *Description: + * + * This file contains defines and function prototypes that are + *operating system dependent. The resources defined in this file + *are not specific to any particular application. + * + *Copyright Distributed Processing Technology, Corp. + * 140 Candace Dr. + * Maitland, Fl. 32751 USA + * Phone: (407) 830-5522 Fax: (407) 260-5366 + * All Rights Reserved + * + *Author: Doug Anderson + *Date: 1/7/94 + * + *Editors: + * + *Remarks: + * + * + *****************************************************************************/ + + +/*Definitions - Defines & Constants ----------------------------------------- */ + +/*----------------------------- */ +/* Operating system selections: */ +/*----------------------------- */ + +/*#define _DPT_MSDOS */ +/*#define _DPT_WIN_3X */ +/*#define _DPT_WIN_4X */ +/*#define _DPT_WIN_NT */ +/*#define _DPT_NETWARE */ +/*#define _DPT_OS2 */ +/*#define _DPT_SCO */ +/*#define _DPT_UNIXWARE */ +/*#define _DPT_SOLARIS */ +/*#define _DPT_NEXTSTEP */ +/*#define _DPT_BANYAN */ + +/*-------------------------------- */ +/* Include the OS specific defines */ +/*-------------------------------- */ + +/*#define OS_SELECTION From Above List */ +/*#define SEMAPHORE_T ??? */ +/*#define DLL_HANDLE_T ??? */ + +#if (defined(KERNEL) && (defined(__FreeBSD__) || defined(__bsdi__))) +# include "i386/isa/dpt_osd_defs.h" +#else +# include "osd_defs.h" +#endif + +#ifndef DPT_UNALIGNED + #define DPT_UNALIGNED +#endif + +#ifndef DPT_EXPORT + #define DPT_EXPORT +#endif + +#ifndef DPT_IMPORT + #define DPT_IMPORT +#endif + +#ifndef DPT_RUNTIME_IMPORT + #define DPT_RUNTIME_IMPORT DPT_IMPORT +#endif + +/*--------------------- */ +/* OS dependent defines */ +/*--------------------- */ + +#if defined (_DPT_MSDOS) || defined (_DPT_WIN_3X) + #define _DPT_16_BIT +#else + #define _DPT_32_BIT +#endif + +#if defined (_DPT_SCO) || defined (_DPT_UNIXWARE) || defined (_DPT_SOLARIS) || defined (_DPT_AIX) || defined (SNI_MIPS) || defined (_DPT_BSDI) || defined (_DPT_FREE_BSD) || defined(_DPT_LINUX) + #define _DPT_UNIX +#endif + +#if defined (_DPT_WIN_3x) || defined (_DPT_WIN_4X) || defined (_DPT_WIN_NT) \ + || defined (_DPT_OS2) + #define _DPT_DLL_SUPPORT +#endif + +#if !defined (_DPT_MSDOS) && !defined (_DPT_WIN_3X) && !defined (_DPT_NETWARE) + #define _DPT_PREEMPTIVE +#endif + +#if !defined (_DPT_MSDOS) && !defined (_DPT_WIN_3X) + #define _DPT_MULTI_THREADED +#endif + +#if !defined (_DPT_MSDOS) + #define _DPT_MULTI_TASKING +#endif + + /* These exist for platforms that */ + /* chunk when accessing mis-aligned */ + /* data */ +#if defined (SNI_MIPS) || defined (_DPT_SOLARIS) + #if defined (_DPT_BIG_ENDIAN) + #if !defined (_DPT_STRICT_ALIGN) + #define _DPT_STRICT_ALIGN + #endif + #endif +#endif + + /* Determine if in C or C++ mode */ +#ifdef __cplusplus + #define _DPT_CPP +#else + #define _DPT_C +#endif + +/*-------------------------------------------------------------------*/ +/* Under Solaris the compiler refuses to accept code like: */ +/* { {"DPT"}, 0, NULL .... }, */ +/* and complains about the {"DPT"} part by saying "cannot use { } */ +/* to initialize char*". */ +/* */ +/* By defining these ugly macros we can get around this and also */ +/* not have to copy and #ifdef large sections of code. I know that */ +/* these macros are *really* ugly, but they should help reduce */ +/* maintenance in the long run. */ +/* */ +/*-------------------------------------------------------------------*/ +#if !defined (DPTSQO) + #if defined (_DPT_SOLARIS) + #define DPTSQO + #define DPTSQC + #else + #define DPTSQO { + #define DPTSQC } + #endif /* solaris */ +#endif /* DPTSQO */ + + +/*---------------------- */ +/* OS dependent typedefs */ +/*---------------------- */ + +#if defined (_DPT_MSDOS) || defined (_DPT_SCO) + #define BYTE unsigned char + #define WORD unsigned short +#endif + +#ifndef _DPT_TYPEDEFS + #define _DPT_TYPEDEFS + typedef unsigned char uCHAR; + typedef unsigned short uSHORT; + typedef unsigned int uINT; + typedef unsigned long uLONG; + + typedef union { + uCHAR u8[4]; + uSHORT u16[2]; + uLONG u32; + } access_U; +#endif + +#if !defined (NULL) + #define NULL 0 +#endif + + +/*Prototypes - function ----------------------------------------------------- */ + +#ifdef __cplusplus + extern "C" { /* Declare all these functions as "C" functions */ +#endif + +/*------------------------ */ +/* Byte reversal functions */ +/*------------------------ */ + + /* Reverses the byte ordering of a 2 byte variable */ +#if (!defined(osdSwap2)) + uSHORT osdSwap2(DPT_UNALIGNED uSHORT *); +#endif // !osdSwap2 + + /* Reverses the byte ordering of a 4 byte variable and shifts left 8 bits */ +#if (!defined(osdSwap3)) + uLONG osdSwap3(DPT_UNALIGNED uLONG *); +#endif // !osdSwap3 + + +#ifdef _DPT_NETWARE + #include "novpass.h" /* For DPT_Bswapl() prototype */ + /* Inline the byte swap */ + #ifdef __cplusplus + inline uLONG osdSwap4(uLONG *inLong) { + return *inLong = DPT_Bswapl(*inLong); + } + #else + #define osdSwap4(inLong) DPT_Bswapl(inLong) + #endif // cplusplus +#else + /* Reverses the byte ordering of a 4 byte variable */ +# if (!defined(osdSwap4)) + uLONG osdSwap4(DPT_UNALIGNED uLONG *); +# endif // !osdSwap4 + + /* The following functions ALWAYS swap regardless of the * + * presence of DPT_BIG_ENDIAN */ + + uSHORT trueSwap2(DPT_UNALIGNED uSHORT *); + uLONG trueSwap4(DPT_UNALIGNED uLONG *); + +#endif // netware + + +/*-------------------------------------* + * Network order swap functions * + * * + * These functions/macros will be used * + * by the structure insert()/extract() * + * functions. * + * + * We will enclose all structure * + * portability modifications inside * + * #ifdefs. When we are ready, we * + * will #define DPT_PORTABLE to begin * + * using the modifications. * + *-------------------------------------*/ +uLONG netSwap4(uLONG val); + +#if defined (_DPT_BIG_ENDIAN) + +// for big-endian we need to swap + +#ifndef NET_SWAP_2 +#define NET_SWAP_2(x) (((x) >> 8) | ((x) << 8)) +#endif // NET_SWAP_2 + +#ifndef NET_SWAP_4 +#define NET_SWAP_4(x) netSwap4((x)) +#endif // NET_SWAP_4 + +#else + +// for little-endian we don't need to do anything + +#ifndef NET_SWAP_2 +#define NET_SWAP_2(x) (x) +#endif // NET_SWAP_2 + +#ifndef NET_SWAP_4 +#define NET_SWAP_4(x) (x) +#endif // NET_SWAP_4 + +#endif // big endian + + + +/*----------------------------------- */ +/* Run-time loadable module functions */ +/*----------------------------------- */ + + /* Loads the specified run-time loadable DLL */ +DLL_HANDLE_T osdLoadModule(uCHAR *); + /* Unloads the specified run-time loadable DLL */ +uSHORT osdUnloadModule(DLL_HANDLE_T); + /* Returns a pointer to a function inside a run-time loadable DLL */ +void * osdGetFnAddr(DLL_HANDLE_T,uCHAR *); + +/*--------------------------------------- */ +/* Mutually exclusive semaphore functions */ +/*--------------------------------------- */ + + /* Create a named semaphore */ +SEMAPHORE_T osdCreateNamedSemaphore(char *); + /* Create a mutually exlusive semaphore */ +SEMAPHORE_T osdCreateSemaphore(void); + /* create an event semaphore */ +SEMAPHORE_T osdCreateEventSemaphore(void); + /* create a named event semaphore */ +SEMAPHORE_T osdCreateNamedEventSemaphore(char *); + + /* Destroy the specified mutually exclusive semaphore object */ +uSHORT osdDestroySemaphore(SEMAPHORE_T); + /* Request access to the specified mutually exclusive semaphore */ +uLONG osdRequestSemaphore(SEMAPHORE_T,uLONG); + /* Release access to the specified mutually exclusive semaphore */ +uSHORT osdReleaseSemaphore(SEMAPHORE_T); + /* wait for a event to happen */ +uLONG osdWaitForEventSemaphore(SEMAPHORE_T, uLONG); + /* signal an event */ +uLONG osdSignalEventSemaphore(SEMAPHORE_T); + /* reset the event */ +uLONG osdResetEventSemaphore(SEMAPHORE_T); + +/*----------------- */ +/* Thread functions */ +/*----------------- */ + + /* Releases control to the task switcher in non-preemptive */ + /* multitasking operating systems. */ +void osdSwitchThreads(void); + + /* Starts a thread function */ +uLONG osdStartThread(void *,void *); + +/* what is my thread id */ +uLONG osdGetThreadID(void); + +/* wakes up the specifed thread */ +void osdWakeThread(uLONG); + +/* osd sleep for x miliseconds */ +void osdSleep(uLONG); + +#define DPT_THREAD_PRIORITY_LOWEST 0x00 +#define DPT_THREAD_PRIORITY_NORMAL 0x01 +#define DPT_THREAD_PRIORITY_HIGHEST 0x02 + +uCHAR osdSetThreadPriority(uLONG tid, uCHAR priority); + +#ifdef __cplusplus + } /* end the xtern "C" declaration */ +#endif + +#endif /* osd_util_h */ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpt/sys_info.h linux/drivers/scsi/dpt/sys_info.h --- v2.4.9/linux/drivers/scsi/dpt/sys_info.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpt/sys_info.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,417 @@ +/* BSDI sys_info.h,v 1.6 1998/06/03 19:14:59 karels Exp */ + +/* + * Copyright (c) 1996-1999 Distributed Processing Technology Corporation + * All rights reserved. + * + * Redistribution and use in source form, with or without modification, are + * permitted provided that redistributions of source code must retain the + * above copyright notice, this list of conditions and the following disclaimer. + * + * This software is provided `as is' by Distributed Processing Technology and + * any express or implied warranties, including, but not limited to, the + * implied warranties of merchantability and fitness for a particular purpose, + * are disclaimed. In no event shall Distributed Processing Technology be + * liable for any direct, indirect, incidental, special, exemplary or + * consequential damages (including, but not limited to, procurement of + * substitute goods or services; loss of use, data, or profits; or business + * interruptions) however caused and on any theory of liability, whether in + * contract, strict liability, or tort (including negligence or otherwise) + * arising in any way out of the use of this driver software, even if advised + * of the possibility of such damage. + * + */ + +#ifndef __SYS_INFO_H +#define __SYS_INFO_H + +/*File - SYS_INFO.H + **************************************************************************** + * + *Description: + * + * This file contains structure definitions for the OS dependent + *layer system information buffers. + * + *Copyright Distributed Processing Technology, Corp. + * 140 Candace Dr. + * Maitland, Fl. 32751 USA + * Phone: (407) 830-5522 Fax: (407) 260-5366 + * All Rights Reserved + * + *Author: Don Kemper + *Date: 5/10/94 + * + *Editors: + * + *Remarks: + * + * + *****************************************************************************/ + + +/*Include Files ------------------------------------------------------------- */ + +#include "osd_util.h" + +#ifndef NO_PACK +#if defined (_DPT_AIX) +#pragma options align=packed +#else +#pragma pack(1) +#endif /* aix */ +#endif // no unpack + + +/*struct - driveParam_S - start + *=========================================================================== + * + *Description: + * + * This structure defines the drive parameters seen during + *booting. + * + *---------------------------------------------------------------------------*/ + +#ifdef __cplusplus + struct driveParam_S { +#else + typedef struct { +#endif + + uSHORT cylinders; /* Upto 1024 */ + uCHAR heads; /* Upto 255 */ + uCHAR sectors; /* Upto 63 */ + +#ifdef __cplusplus + +//---------- Portability Additions ----------- in sp_sinfo.cpp +#ifdef DPT_PORTABLE + uSHORT netInsert(dptBuffer_S *buffer); + uSHORT netExtract(dptBuffer_S *buffer); +#endif // DPT PORTABLE +//-------------------------------------------- + + }; +#else + } driveParam_S; +#endif +/*driveParam_S - end */ + + +/*struct - sysInfo_S - start + *=========================================================================== + * + *Description: + * + * This structure defines the command system information that + *should be returned by every OS dependent layer. + * + *---------------------------------------------------------------------------*/ + +/*flags - bit definitions */ +#define SI_CMOS_Valid 0x0001 +#define SI_NumDrivesValid 0x0002 +#define SI_ProcessorValid 0x0004 +#define SI_MemorySizeValid 0x0008 +#define SI_DriveParamsValid 0x0010 +#define SI_SmartROMverValid 0x0020 +#define SI_OSversionValid 0x0040 +#define SI_OSspecificValid 0x0080 /* 1 if OS structure returned */ +#define SI_BusTypeValid 0x0100 + +#define SI_ALL_VALID 0x0FFF /* All Std SysInfo is valid */ +#define SI_NO_SmartROM 0x8000 + +/*busType - definitions */ +#define SI_ISA_BUS 0x00 +#define SI_MCA_BUS 0x01 +#define SI_EISA_BUS 0x02 +#define SI_PCI_BUS 0x04 + +#ifdef __cplusplus + struct sysInfo_S { +#else + typedef struct { +#endif + + uCHAR drive0CMOS; /* CMOS Drive 0 Type */ + uCHAR drive1CMOS; /* CMOS Drive 1 Type */ + uCHAR numDrives; /* 0040:0075 contents */ + uCHAR processorFamily; /* Same as DPTSIG's definition */ + uCHAR processorType; /* Same as DPTSIG's definition */ + uCHAR smartROMMajorVersion; + uCHAR smartROMMinorVersion; /* SmartROM version */ + uCHAR smartROMRevision; + uSHORT flags; /* See bit definitions above */ + uSHORT conventionalMemSize; /* in KB */ + uLONG extendedMemSize; /* in KB */ + uLONG osType; /* Same as DPTSIG's definition */ + uCHAR osMajorVersion; + uCHAR osMinorVersion; /* The OS version */ + uCHAR osRevision; +#ifdef _SINIX_ADDON + uCHAR busType; /* See defininitions above */ + uSHORT osSubRevision; + uCHAR pad[2]; /* For alignment */ +#else + uCHAR osSubRevision; + uCHAR busType; /* See defininitions above */ + uCHAR pad[3]; /* For alignment */ +#endif + driveParam_S drives[16]; /* SmartROM Logical Drives */ + +#ifdef __cplusplus + +//---------- Portability Additions ----------- in sp_sinfo.cpp +#ifdef DPT_PORTABLE + uSHORT netInsert(dptBuffer_S *buffer); + uSHORT netExtract(dptBuffer_S *buffer); +#endif // DPT PORTABLE +//-------------------------------------------- + + }; +#else + } sysInfo_S; +#endif +/*sysInfo_S - end */ + + +/*struct - DOS_Info_S - start + *=========================================================================== + * + *Description: + * + * This structure defines the system information specific to a + *DOS workstation. + * + *---------------------------------------------------------------------------*/ + +/*flags - bit definitions */ +#define DI_DOS_HIGH 0x01 /* DOS is loaded high */ +#define DI_DPMI_VALID 0x02 /* DPMI version is valid */ + +#ifdef __cplusplus + struct DOS_Info_S { +#else + typedef struct { +#endif + + uCHAR flags; /* See bit definitions above */ + uSHORT driverLocation; /* SmartROM BIOS address */ + uSHORT DOS_version; + uSHORT DPMI_version; + +#ifdef __cplusplus + +//---------- Portability Additions ----------- in sp_sinfo.cpp +#ifdef DPT_PORTABLE + uSHORT netInsert(dptBuffer_S *buffer); + uSHORT netExtract(dptBuffer_S *buffer); +#endif // DPT PORTABLE +//-------------------------------------------- + + }; +#else + } DOS_Info_S; +#endif +/*DOS_Info_S - end */ + + +/*struct - Netware_Info_S - start + *=========================================================================== + * + *Description: + * + * This structure defines the system information specific to a + *Netware machine. + * + *---------------------------------------------------------------------------*/ + +#ifdef __cplusplus + struct Netware_Info_S { +#else + typedef struct { +#endif + + uCHAR driverName[13]; /* ie PM12NW31.DSK */ + uCHAR serverName[48]; + uCHAR netwareVersion; /* The Netware OS version */ + uCHAR netwareSubVersion; + uCHAR netwareRevision; + uSHORT maxConnections; /* Probably 250 or 1000 */ + uSHORT connectionsInUse; + uSHORT maxVolumes; + uCHAR unused; + uCHAR SFTlevel; + uCHAR TTSlevel; + + uCHAR clibMajorVersion; /* The CLIB.NLM version */ + uCHAR clibMinorVersion; + uCHAR clibRevision; + +#ifdef __cplusplus + +//---------- Portability Additions ----------- in sp_sinfo.cpp +#ifdef DPT_PORTABLE + uSHORT netInsert(dptBuffer_S *buffer); + uSHORT netExtract(dptBuffer_S *buffer); +#endif // DPT PORTABLE +//-------------------------------------------- + + }; +#else + } Netware_Info_S; +#endif +/*Netware_Info_S - end */ + + +/*struct - OS2_Info_S - start + *=========================================================================== + * + *Description: + * + * This structure defines the system information specific to an + *OS/2 machine. + * + *---------------------------------------------------------------------------*/ + +#ifdef __cplusplus + struct OS2_Info_S { +#else + typedef struct { +#endif + + uCHAR something; + +#ifdef __cplusplus + +//---------- Portability Additions ----------- in sp_sinfo.cpp +#ifdef DPT_PORTABLE + uSHORT netInsert(dptBuffer_S *buffer); + uSHORT netExtract(dptBuffer_S *buffer); +#endif // DPT PORTABLE +//-------------------------------------------- + + }; +#else + } OS2_Info_S; +#endif +/*OS2_Info_S - end */ + + +/*struct - WinNT_Info_S - start + *=========================================================================== + * + *Description: + * + * This structure defines the system information specific to a + *Windows NT machine. + * + *---------------------------------------------------------------------------*/ + +#ifdef __cplusplus + struct WinNT_Info_S { +#else + typedef struct { +#endif + + uCHAR something; + +#ifdef __cplusplus + +//---------- Portability Additions ----------- in sp_sinfo.cpp +#ifdef DPT_PORTABLE + uSHORT netInsert(dptBuffer_S *buffer); + uSHORT netExtract(dptBuffer_S *buffer); +#endif // DPT PORTABLE +//-------------------------------------------- + + }; +#else + } WinNT_Info_S; +#endif +/*WinNT_Info_S - end */ + + +/*struct - SCO_Info_S - start + *=========================================================================== + * + *Description: + * + * This structure defines the system information specific to an + *SCO UNIX machine. + * + *---------------------------------------------------------------------------*/ + +#ifdef __cplusplus + struct SCO_Info_S { +#else + typedef struct { +#endif + + uCHAR something; + +#ifdef __cplusplus + +//---------- Portability Additions ----------- in sp_sinfo.cpp +#ifdef DPT_PORTABLE + uSHORT netInsert(dptBuffer_S *buffer); + uSHORT netExtract(dptBuffer_S *buffer); +#endif // DPT PORTABLE +//-------------------------------------------- + + }; +#else + } SCO_Info_S; +#endif +/*SCO_Info_S - end */ + + +/*struct - USL_Info_S - start + *=========================================================================== + * + *Description: + * + * This structure defines the system information specific to a + *USL UNIX machine. + * + *---------------------------------------------------------------------------*/ + +#ifdef __cplusplus + struct USL_Info_S { +#else + typedef struct { +#endif + + uCHAR something; + +#ifdef __cplusplus + +//---------- Portability Additions ----------- in sp_sinfo.cpp +#ifdef DPT_PORTABLE + uSHORT netInsert(dptBuffer_S *buffer); + uSHORT netExtract(dptBuffer_S *buffer); +#endif // DPT PORTABLE +//-------------------------------------------- + + }; +#else + } USL_Info_S; +#endif +/*USL_Info_S - end */ + + + /* Restore default structure packing */ +#ifndef NO_UNPACK +#if defined (_DPT_AIX) +#pragma options align=reset +#elif defined (UNPACK_FOUR) +#pragma pack(4) +#else +#pragma pack() +#endif /* aix */ +#endif // no unpack + +#endif // __SYS_INFO_H + diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpt_i2o.c linux/drivers/scsi/dpt_i2o.c --- v2.4.9/linux/drivers/scsi/dpt_i2o.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpt_i2o.c Fri Sep 7 09:28:38 2001 @@ -0,0 +1,3323 @@ +/*************************************************************************** + dpti.c - description + ------------------- + begin : Thu Sep 7 2000 + copyright : (C) 2000 by Adaptec + email : deanna_bonds@adaptec.com + + July 30, 2001 First version being submitted + for inclusion in the kernel. V2.4 + + See README.dpti for history, notes, license info, and credits + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +//#define DEBUG 1 +//#define UARTDELAY 1 + +// On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates +// high pages. Keep the macro around because of the broken unmerged ia64 tree + +#define ADDR32 (0) + +#include +#include + +MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn"); +MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); + +//////////////////////////////////////////////////////////////// + +#include /* For SCSI-Passthrough */ +#include + +#include +#include /* for kmalloc() */ +#include /* for CONFIG_PCI */ +#include /* for PCI support */ +#include +#include +#include /* for udelay */ +#include +#include +#include /* for printk */ +#include +#include +#include + +#include +#include +#include +#include + +#include /* for boot_cpu_data */ +#include +#include /* for virt_to_bus, etc. */ + +#include "scsi.h" +#include "hosts.h" +#include "sd.h" + +#include "dpt/dptsig.h" +#include "dpti.h" + +/*============================================================================ + * Create a binary signature - this is read by dptsig + * Needed for our management apps + *============================================================================ + */ +static dpt_sig_S DPTI_sig = { + {'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION, +#ifdef __i386__ + PROC_INTEL, PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM, +#elif defined __ia64__ + PROC_INTEL, PROC_IA64, +#elif define __sparc__ + PROC_ULTRASPARC, +#elif defined(__alpha__) + PROC_ALPHA , +#else + (-1), +#endif + FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL, + ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION, + DPT_MONTH, DPT_DAY, DPT_YEAR, "Adaptec Linux I2O RAID Driver" +}; + + + + +/*============================================================================ + * Globals + *============================================================================ + */ + +DECLARE_MUTEX(adpt_configuration_lock); + +static struct i2o_sys_tbl *sys_tbl = NULL; +static int sys_tbl_ind = 0; +static int sys_tbl_len = 0; + +static adpt_hba* hbas[DPTI_MAX_HBA]; +static adpt_hba* hba_chain = NULL; +static int hba_count = 0; + +// Debug flags to be put into the HBA flags field when initialized +// Make sure to enable DEBUG_PRINT for these flags to work +static unsigned long DebugFlags = HBA_FLAGS_DBG_SCAN_B | HBA_FLAGS_DBG_FLAGS_MASK; + +static struct file_operations adpt_fops = { + ioctl: adpt_ioctl, + open: adpt_open, + release: adpt_close +}; + +#ifdef REBOOT_NOTIFIER +static struct notifier_block adpt_reboot_notifier = +{ + adpt_reboot_event, + NULL, + 0 +}; +#endif + +/* Structures and definitions for synchronous message posting. + * See adpt_i2o_post_wait() for description + * */ +struct adpt_i2o_post_wait_data +{ + int status; + u32 id; + adpt_wait_queue_head_t *wq; + struct adpt_i2o_post_wait_data *next; +}; + +static struct adpt_i2o_post_wait_data *adpt_post_wait_queue = NULL; +static u32 adpt_post_wait_id = 0; +static spinlock_t adpt_post_wait_lock = SPIN_LOCK_UNLOCKED; + + +/*============================================================================ + * Functions + *============================================================================ + */ + +static u8 adpt_read_blink_led(adpt_hba* host) +{ + if(host->FwDebugBLEDflag_P != 0) { + if( readb(host->FwDebugBLEDflag_P) == 0xbc ){ + return readb(host->FwDebugBLEDvalue_P); + } + } + return 0; +} + +/*============================================================================ + * Scsi host template interface functions + *============================================================================ + */ + +static int adpt_detect(Scsi_Host_Template* sht) +{ + struct pci_dev *pDev = NULL; + adpt_hba* pHba; + + adpt_init(); + sht->use_new_eh_code = 1; + + PINFO("Detecting Adaptec I2O RAID controllers...\n"); + + /* search for all Adatpec I2O RAID cards */ + while ((pDev = pci_find_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) { + if(pDev->device == PCI_DPT_DEVICE_ID || + pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){ + if(adpt_install_hba(sht, pDev) ){ + PERROR("Could not Init an I2O RAID device\n"); + PERROR("Will not try to detect others.\n"); + return hba_count-1; + } + } + } + + /* In INIT state, Activate IOPs */ + for (pHba = hba_chain; pHba; pHba = pHba->next) { + // Activate does get status , init outbound, and get hrt + if (adpt_i2o_activate_hba(pHba) < 0) { + adpt_i2o_delete_hba(pHba); + } + } + + + /* Active IOPs in HOLD state */ + +rebuild_sys_tab: + if (hba_chain == NULL) + return 0; + + /* + * If build_sys_table fails, we kill everything and bail + * as we can't init the IOPs w/o a system table + */ + if (adpt_i2o_build_sys_table() < 0) { + adpt_i2o_sys_shutdown(); + return 0; + } + + PDEBUG("HBA's in HOLD state\n"); + + /* If IOP don't get online, we need to rebuild the System table */ + for (pHba = hba_chain; pHba; pHba = pHba->next) { + if (adpt_i2o_online_hba(pHba) < 0) { + adpt_i2o_delete_hba(pHba); + goto rebuild_sys_tab; + } + } + + /* Active IOPs now in OPERATIONAL state */ + PDEBUG("HBA's in OPERATIONAL state\n"); + + printk(KERN_INFO"dpti: If you have a lot of devices this could take a few minutes.\n"); + for (pHba = hba_chain; pHba; pHba = pHba->next) { + printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name); + if (adpt_i2o_lct_get(pHba) < 0){ + adpt_i2o_delete_hba(pHba); + continue; + } + + if (adpt_i2o_parse_lct(pHba) < 0){ + adpt_i2o_delete_hba(pHba); + continue; + } + adpt_inquiry(pHba); + } + + for (pHba = hba_chain; pHba; pHba = pHba->next) { + if( adpt_scsi_register(pHba,sht) < 0){ + adpt_i2o_delete_hba(pHba); + continue; + } + pHba->initialized = TRUE; + pHba->state &= ~DPTI_STATE_RESET; + } + + // Register our control device node + // nodes will need to be created in /dev to access this + // the nodes can not be created from within the driver + if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) { + adpt_i2o_sys_shutdown(); + return 0; + } + return hba_count; +} + + +/* + * scsi_unregister will be called AFTER we return. + */ +static int adpt_release(struct Scsi_Host *host) +{ + adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; +// adpt_i2o_quiesce_hba(pHba); + adpt_i2o_delete_hba(pHba); + return 0; +} + + +static void adpt_inquiry(adpt_hba* pHba) +{ + u32 msg[14]; + u32 *mptr; + u32 *lenptr; + int direction; + int scsidir; + u32 len; + u32 reqlen; + u8* buf; + u8 scb[16]; + s32 rcode; + + memset(msg, 0, sizeof(msg)); + buf = (u8*)kmalloc(80,GFP_KERNEL|ADDR32); + if(!buf){ + printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name); + return; + } + memset((void*)buf, 0, 36); + + len = 36; + direction = 0x00000000; + scsidir =0x40000000; // DATA IN (iop<--dev) + + reqlen = 14; // SINGLE SGE + /* Stick the headers on */ + msg[0] = reqlen<<16 | SGL_OFFSET_12; + msg[1] = (0xff<<24|HOST_TID<<12|ADAPTER_TID); + msg[2] = 0; + msg[3] = 0; + // Adaptec/DPT Private stuff + msg[4] = I2O_CMD_SCSI_EXEC|DPT_ORGANIZATION_ID<<16; + msg[5] = ADAPTER_TID | 1<<16 /* Interpret*/; + /* Direction, disconnect ok | sense data | simple queue , CDBLen */ + // I2O_SCB_FLAG_ENABLE_DISCONNECT | + // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG | + // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE; + msg[6] = scsidir|0x20a00000| 6 /* cmd len*/; + + mptr=msg+7; + + memset(scb, 0, sizeof(scb)); + // Write SCSI command into the message - always 16 byte block + scb[0] = INQUIRY; + scb[1] = 0; + scb[2] = 0; + scb[3] = 0; + scb[4] = 36; + scb[5] = 0; + // Don't care about the rest of scb + + memcpy(mptr, scb, sizeof(scb)); + mptr+=4; + lenptr=mptr++; /* Remember me - fill in when we know */ + + /* Now fill in the SGList and command */ + *lenptr = len; + *mptr++ = 0xD0000000|direction|len; + *mptr++ = virt_to_bus(buf); + + // Send it on it's way + rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120); + if (rcode != 0) { + sprintf(pHba->detail, "Adaptec I2O RAID"); + printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode); + } else { + memset(pHba->detail, 0, sizeof(pHba->detail)); + memcpy(&(pHba->detail), "Vendor: Adaptec ", 16); + memcpy(&(pHba->detail[16]), " Model: ", 8); + memcpy(&(pHba->detail[24]), (u8*) &buf[16], 16); + memcpy(&(pHba->detail[40]), " FW: ", 4); + memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4); + pHba->detail[48] = '\0'; /* precautionary */ + } + kfree(buf); + adpt_i2o_status_get(pHba); + return ; +} + + +static void adpt_select_queue_depths(struct Scsi_Host *host, Scsi_Device * devicelist) +{ + Scsi_Device *device; /* scsi layer per device information */ + adpt_hba* pHba; + + pHba = (adpt_hba *) host->hostdata[0]; + + for (device = devicelist; device != NULL; device = device->next) { + if (device->host != host) { + continue; + } + if (host->can_queue) { + device->queue_depth = host->can_queue - 1; + } else { + device->queue_depth = 1; + } + } +} + +static int adpt_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +{ + adpt_hba* pHba = NULL; + struct adpt_device* pDev = NULL; /* dpt per device information */ + ulong timeout = jiffies + (TMOUT_SCSI*HZ); + + cmd->scsi_done = done; + /* + * SCSI REQUEST_SENSE commands will be executed automatically by the + * Host Adapter for any errors, so they should not be executed + * explicitly unless the Sense Data is zero indicating that no error + * occurred. + */ + + if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) { + cmd->result = (DID_OK << 16); + cmd->scsi_done(cmd); + return 0; + } + + pHba = (adpt_hba*)cmd->host->hostdata[0]; + if (!pHba) { + return FAILED; + } + + rmb(); + /* + * TODO: I need to block here if I am processing ioctl cmds + * but if the outstanding cmds all finish before the ioctl, + * the scsi-core will not know to start sending cmds to me again. + * I need to a way to restart the scsi-cores queues or should I block + * calling scsi_done on the outstanding cmds instead + * for now we don't set the IOCTL state + */ + if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) { + pHba->host->last_reset = jiffies; + pHba->host->resetting = 1; + return 1; + } + + if(cmd->eh_state != SCSI_STATE_QUEUED){ + // If we are not doing error recovery + mod_timer(&cmd->eh_timeout, timeout); + } + + // TODO if the cmd->device if offline then I may need to issue a bus rescan + // followed by a get_lct to see if the device is there anymore + if((pDev = (struct adpt_device*) (cmd->device->hostdata)) == NULL) { + /* + * First command request for this device. Set up a pointer + * to the device structure. This should be a TEST_UNIT_READY + * command from scan_scsis_single. + */ + if ((pDev = adpt_find_device(pHba, (u32)cmd->channel, (u32)cmd->target, (u32)cmd-> lun)) == NULL) { + // TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response + // with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue. + cmd->result = (DID_NO_CONNECT << 16); + cmd->scsi_done(cmd); + return 0; + } + (struct adpt_device*)(cmd->device->hostdata) = pDev; + } + pDev->pScsi_dev = cmd->device; + + /* + * If we are being called from when the device is being reset, + * delay processing of the command until later. + */ + if (pDev->state & DPTI_DEV_RESET ) { + return FAILED; + } + return adpt_scsi_to_i2o(pHba, cmd, pDev); +} + +static int adpt_bios_param(Disk* disk, kdev_t dev, int geom[]) +{ + int heads=-1; + int sectors=-1; + int cylinders=-1; + + // *** First lets set the default geometry **** + + // If the capacity is less than ox2000 + if (disk->capacity < 0x2000 ) { // floppy + heads = 18; + sectors = 2; + } + // else if between 0x2000 and 0x20000 + else if (disk->capacity < 0x20000) { + heads = 64; + sectors = 32; + } + // else if between 0x20000 and 0x40000 + else if (disk->capacity < 0x40000) { + heads = 65; + sectors = 63; + } + // else if between 0x4000 and 0x80000 + else if (disk->capacity < 0x80000) { + heads = 128; + sectors = 63; + } + // else if greater than 0x80000 + else { + heads = 255; + sectors = 63; + } + cylinders = disk->capacity / (heads * sectors); + + // Special case if CDROM + if(disk->device->type == 5) { // CDROM + heads = 252; + sectors = 63; + cylinders = 1111; + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + PDEBUG("adpt_bios_param: exit\n"); + return 0; +} + + +static const char *adpt_info(struct Scsi_Host *host) +{ + adpt_hba* pHba; + + pHba = (adpt_hba *) host->hostdata[0]; + return (char *) (pHba->detail); +} + +static int adpt_proc_info(char *buffer, char **start, off_t offset, + int length, int hostno, int inout) +{ + struct adpt_device* d; + int id; + int chan; + int len = 0; + int begin = 0; + int pos = 0; + adpt_hba* pHba; + struct Scsi_Host *host; + int unit; + + *start = buffer; + if (inout == TRUE) { + /* + * The user has done a write and wants us to take the + * data in the buffer and do something with it. + * proc_scsiwrite calls us with inout = 1 + * + * Read data from buffer (writing to us) - NOT SUPPORTED + */ + return -EINVAL; + } + + /* + * inout = 0 means the user has done a read and wants information + * returned, so we write information about the cards into the buffer + * proc_scsiread() calls us with inout = 0 + */ + + // Find HBA (host bus adapter) we are looking for + down(&adpt_configuration_lock); + for (pHba = hba_chain; pHba; pHba = pHba->next) { + if (pHba->host->host_no == hostno) { + break; /* found adapter */ + } + } + up(&adpt_configuration_lock); + if (pHba == NULL) { + return 0; + } + host = pHba->host; + + len = sprintf(buffer , "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION); + len += sprintf(buffer+len, "%s\n", pHba->detail); + len += sprintf(buffer+len, "SCSI Host=scsi%d Control Node=/dev/%s irq=%d\n", + pHba->host->host_no, pHba->name, host->irq); + len += sprintf(buffer+len, "\tpost fifo size = %d\n\treply fifo size = %d\n\tsg table size = %d\n\n", + host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize); + + pos = begin + len; + + /* CHECKPOINT */ + if(pos > offset + length) { + goto stop_output; + } + if(pos <= offset) { + /* + * If we haven't even written to where we last left + * off (the last time we were called), reset the + * beginning pointer. + */ + len = 0; + begin = pos; + } + len += sprintf(buffer+len, "Devices:\n"); + for(chan = 0; chan < MAX_CHANNEL; chan++) { + for(id = 0; id < MAX_ID; id++) { + d = pHba->channel[chan].device[id]; + while(d){ + len += sprintf(buffer+len,"\t%-24.24s", d->pScsi_dev->vendor); + len += sprintf(buffer+len," Rev: %-8.8s\n", d->pScsi_dev->rev); + pos = begin + len; + + + /* CHECKPOINT */ + if(pos > offset + length) { + goto stop_output; + } + if(pos <= offset) { + len = 0; + begin = pos; + } + + unit = d->pI2o_dev->lct_data.tid; + len += sprintf(buffer+len, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d) (%s)\n\n", + unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun, + d->pScsi_dev->online? "online":"offline"); + pos = begin + len; + + /* CHECKPOINT */ + if(pos > offset + length) { + goto stop_output; + } + if(pos <= offset) { + len = 0; + begin = pos; + } + + d = d->next_lun; + } + } + } + + /* + * begin is where we last checked our position with regards to offset + * begin is always less than offset. len is relative to begin. It + * is the number of bytes written past begin + * + */ +stop_output: + /* stop the output and calculate the correct length */ + *(buffer + len) = '\0'; + + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); + if(len > length) { + len = length; + } else if(len < 0){ + len = 0; + **start = '\0'; + } + return len; +} + + +/*=========================================================================== + * Error Handling routines + *=========================================================================== + */ + +static int adpt_abort(Scsi_Cmnd * cmd) +{ + adpt_hba* pHba = NULL; /* host bus adapter structure */ + struct adpt_device* dptdevice; /* dpt per device information */ + u32 msg[5]; + int rcode; + + if(cmd->serial_number == 0){ + return FAILED; + } + pHba = (adpt_hba*) cmd->host->hostdata[0]; + printk(KERN_INFO"%s: Trying to Abort cmd=%ld\n",pHba->name, cmd->serial_number); + if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) { + printk(KERN_ERR "%s: Unable to abort: No device in cmnd\n",pHba->name); + return FAILED; + } + + memset(msg, 0, sizeof(msg)); + msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; + msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid; + msg[2] = 0; + msg[3]= 0; + msg[4] = (u32)cmd; + if( (rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER)) != 0){ + if(rcode == -EOPNOTSUPP ){ + printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name); + return FAILED; + } + printk(KERN_INFO"%s: Abort cmd=%ld failed.\n",pHba->name, cmd->serial_number); + return FAILED; + } + printk(KERN_INFO"%s: Abort cmd=%ld complete.\n",pHba->name, cmd->serial_number); + return SUCCESS; +} + + +#define I2O_DEVICE_RESET 0x27 +// This is the same for BLK and SCSI devices +// NOTE this is wrong in the i2o.h definitions +// This is not currently supported by our adapter but we issue it anyway +static int adpt_device_reset(Scsi_Cmnd* cmd) +{ + adpt_hba* pHba; + u32 msg[4]; + u32 rcode; + int old_state; + struct adpt_device* d = (void*) cmd->device->hostdata; + + pHba = (void*) cmd->host->hostdata[0]; + printk(KERN_INFO"%s: Trying to reset device\n",pHba->name); + if (!d) { + printk(KERN_INFO"%s: Reset Device: Device Not found\n",pHba->name); + return FAILED; + } + memset(msg, 0, sizeof(msg)); + msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; + msg[1] = (I2O_DEVICE_RESET<<24|HOST_TID<<12|d->tid); + msg[2] = 0; + msg[3] = 0; + + old_state = d->state; + d->state |= DPTI_DEV_RESET; + if( (rcode = adpt_i2o_post_wait(pHba, (void*)msg,sizeof(msg), FOREVER)) ){ + d->state = old_state; + if(rcode == -EOPNOTSUPP ){ + printk(KERN_INFO"%s: Device reset not supported\n",pHba->name); + return FAILED; + } + printk(KERN_INFO"%s: Device reset failed\n",pHba->name); + return FAILED; + } else { + d->state = old_state; + printk(KERN_INFO"%s: Device reset successful\n",pHba->name); + return SUCCESS; + } +} + + +#define I2O_HBA_BUS_RESET 0x87 +// This version of bus reset is called by the eh_error handler +static int adpt_bus_reset(Scsi_Cmnd* cmd) +{ + adpt_hba* pHba; + u32 msg[4]; + + pHba = (adpt_hba*)cmd->host->hostdata[0]; + memset(msg, 0, sizeof(msg)); + printk(KERN_WARNING"%s: Bus reset: SCSI Bus %d: tid: %d\n",pHba->name, cmd->channel,pHba->channel[cmd->channel].tid ); + msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; + msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->channel].tid); + msg[2] = 0; + msg[3] = 0; + if(adpt_i2o_post_wait(pHba, (void*)msg,sizeof(msg), FOREVER) ){ + printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name); + return FAILED; + } else { + printk(KERN_WARNING"%s: Bus reset success.\n",pHba->name); + return SUCCESS; + } +} + +// This version of reset is called by the eh_error_handler +static int adpt_reset(Scsi_Cmnd* cmd) +{ + adpt_hba* pHba; + int rcode; + pHba = (adpt_hba*)cmd->host->hostdata[0]; + printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n",pHba->name,cmd->channel,pHba->channel[cmd->channel].tid ); + rcode = adpt_hba_reset(pHba); + if(rcode == 0){ + printk(KERN_WARNING"%s: HBA reset complete\n",pHba->name); + return SUCCESS; + } else { + printk(KERN_WARNING"%s: HBA reset failed (%x)\n",pHba->name, rcode); + return FAILED; + } +} + +// This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_reset +static int adpt_hba_reset(adpt_hba* pHba) +{ + int rcode; + + pHba->state |= DPTI_STATE_RESET; + + // Activate does get status , init outbound, and get hrt + if ((rcode=adpt_i2o_activate_hba(pHba)) < 0) { + printk(KERN_ERR "%s: Could not activate\n", pHba->name); + adpt_i2o_delete_hba(pHba); + return rcode; + } + + if ((rcode=adpt_i2o_build_sys_table()) < 0) { + adpt_i2o_delete_hba(pHba); + return rcode; + } + PDEBUG("%s: in HOLD state\n",pHba->name); + + if ((rcode=adpt_i2o_online_hba(pHba)) < 0) { + adpt_i2o_delete_hba(pHba); + return rcode; + } + PDEBUG("%s: in OPERATIONAL state\n",pHba->name); + + if ((rcode=adpt_i2o_lct_get(pHba)) < 0){ + adpt_i2o_delete_hba(pHba); + return rcode; + } + + if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){ + adpt_i2o_delete_hba(pHba); + return rcode; + } + pHba->state &= ~DPTI_STATE_RESET; + + adpt_fail_posted_scbs(pHba); + return 0; /* return success */ +} + +/*=========================================================================== + * + *=========================================================================== + */ + + +static void adpt_i2o_sys_shutdown(void) +{ + adpt_hba *pHba, *pNext; + struct adpt_i2o_post_wait_data *p1, *p2; + + printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n"); + printk(KERN_INFO" This could take a few minutes if there are many devices attached\n"); + /* Delete all IOPs from the controller chain */ + /* They should have already been released by the + * scsi-core + */ + for (pHba = hba_chain; pHba; pHba = pNext) { + pNext = pHba->next; + adpt_i2o_delete_hba(pHba); + } + + /* Remove any timedout entries from the wait queue. */ + p2 = NULL; +// spin_lock_irqsave(&adpt_post_wait_lock, flags); + /* Nothing should be outstanding at this point so just + * free them + */ + for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p2->next) { + kfree(p1); + } +// spin_unlock_irqrestore(&adpt_post_wait_lock, flags); + adpt_post_wait_queue = 0; + + printk(KERN_INFO "Adaptec I2O controllers down.\n"); +} + +/* + * reboot/shutdown notification. + * + * - Quiesce each IOP in the system + * + */ + +#ifdef REBOOT_NOTIFIER +static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p) +{ + + if(code != SYS_RESTART && code != SYS_HALT && code != SYS_POWER_OFF) + return NOTIFY_DONE; + + adpt_i2o_sys_shutdown(); + + return NOTIFY_DONE; +} +#endif + + +static int adpt_install_hba(Scsi_Host_Template* sht, struct pci_dev* pDev) +{ + + adpt_hba* pHba = NULL; + adpt_hba* p = NULL; + ulong base_addr0_phys = 0; + ulong base_addr1_phys = 0; + u32 hba_map0_area_size = 0; + u32 hba_map1_area_size = 0; + ulong base_addr_virt = 0; + ulong msg_addr_virt = 0; + + int raptorFlag = FALSE; + int i; + + if(pci_enable_device(pDev)) { + return -EINVAL; + } + pci_set_master(pDev); + + base_addr0_phys = pci_resource_start(pDev,0); + hba_map0_area_size = pci_resource_len(pDev,0); + + // Check if standard PCI card or single BAR Raptor + if(pDev->device == PCI_DPT_DEVICE_ID){ + if(pDev->subsystem_device >=0xc032 && pDev->subsystem_device <= 0xc03b){ + // Raptor card with this device id needs 4M + hba_map0_area_size = 0x400000; + } else { // Not Raptor - it is a PCI card + if(hba_map0_area_size > 0x100000 ){ + hba_map0_area_size = 0x100000; + } + } + } else {// Raptor split BAR config + // Use BAR1 in this configuration + base_addr1_phys = pci_resource_start(pDev,1); + hba_map1_area_size = pci_resource_len(pDev,1); + raptorFlag = TRUE; + } + + + base_addr_virt = (ulong)ioremap(base_addr0_phys,hba_map0_area_size); + if(base_addr_virt == 0) { + PERROR("dpti: adpt_config_hba: io remap failed\n"); + return -EINVAL; + } + + if(raptorFlag == TRUE) { + msg_addr_virt = (ulong)ioremap(base_addr1_phys, hba_map1_area_size ); + if(msg_addr_virt == 0) { + PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); + iounmap((void*)base_addr_virt); + return -EINVAL; + } + } else { + msg_addr_virt = base_addr_virt; + } + + // Allocate and zero the data structure + pHba = kmalloc(sizeof(adpt_hba), GFP_KERNEL); + if( pHba == NULL) { + if(msg_addr_virt != base_addr_virt){ + iounmap((void*)msg_addr_virt); + } + iounmap((void*)base_addr_virt); + return -ENOMEM; + } + memset(pHba, 0, sizeof(adpt_hba)); + + down(&adpt_configuration_lock); + for(i=0;inext; p = p->next); + p->next = pHba; + } else { + hba_chain = pHba; + } + pHba->next = NULL; + pHba->unit = hba_count; + sprintf(pHba->name, "dpti%d", i); + hba_count++; + + up(&adpt_configuration_lock); + + pHba->pDev = pDev; + pHba->base_addr_phys = base_addr0_phys; + + // Set up the Virtual Base Address of the I2O Device + pHba->base_addr_virt = base_addr_virt; + pHba->msg_addr_virt = msg_addr_virt; + pHba->irq_mask = (ulong)(base_addr_virt+0x30); + pHba->post_port = (ulong)(base_addr_virt+0x40); + pHba->reply_port = (ulong)(base_addr_virt+0x44); + + pHba->hrt = NULL; + pHba->lct = NULL; + pHba->lct_size = 0; + pHba->status_block = NULL; + pHba->post_count = 0; + pHba->state = DPTI_STATE_RESET; + pHba->pDev = pDev; + pHba->devices = NULL; + + // Initializing the spinlocks + spin_lock_init(&pHba->state_lock); + + if(raptorFlag == 0){ + printk(KERN_INFO"Adaptec I2O RAID controller %d at %lx size=%x irq=%d\n", + hba_count-1, base_addr_virt, hba_map0_area_size, pDev->irq); + } else { + printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d\n",hba_count-1, pDev->irq); + printk(KERN_INFO" BAR0 %lx - size= %x\n",base_addr_virt,hba_map0_area_size); + printk(KERN_INFO" BAR1 %lx - size= %x\n",msg_addr_virt,hba_map1_area_size); + } + + if (request_irq (pDev->irq, adpt_isr, SA_SHIRQ, pHba->name, pHba)) { + printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq); + adpt_i2o_delete_hba(pHba); + return -EINVAL; + } + + return 0; +} + + +static void adpt_i2o_delete_hba(adpt_hba* pHba) +{ + adpt_hba* p1; + adpt_hba* p2; + struct i2o_device* d; + struct i2o_device* next; + int i; + int j; + struct adpt_device* pDev; + struct adpt_device* pNext; + + + down(&adpt_configuration_lock); + // scsi_unregister calls our adpt_release which + // does a quiese + if(pHba->host){ + free_irq(pHba->host->irq, pHba); + } + for(i=0;inext){ + if(p1 == pHba) { + if(p2) { + p2->next = p1->next; + } else { + hba_chain = p1->next; + } + break; + } + } + + hba_count--; + up(&adpt_configuration_lock); + + iounmap((void*)pHba->base_addr_virt); + if(pHba->msg_addr_virt != pHba->base_addr_virt){ + iounmap((void*)pHba->msg_addr_virt); + } + if(pHba->hrt) { + kfree(pHba->hrt); + } + if(pHba->lct){ + kfree(pHba->lct); + } + if(pHba->status_block) { + kfree(pHba->status_block); + } + if(pHba->reply_pool){ + kfree(pHba->reply_pool); + } + + for(d = pHba->devices; d ; d = next){ + next = d->next; + kfree(d); + } + for(i = 0 ; i < pHba->top_scsi_channel ; i++){ + for(j = 0; j < MAX_ID; j++){ + if(pHba->channel[i].device[j] != NULL){ + for(pDev = pHba->channel[i].device[j]; pDev; pDev = pNext){ + pNext = pDev->next_lun; + kfree(pDev); + } + } + } + } + kfree(pHba); + + if(hba_count <= 0){ + unregister_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER); + } +} + + +static int adpt_init(void) +{ + int i; + + printk(KERN_INFO"Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); + for (i = 0; i < DPTI_MAX_HBA; i++) { + hbas[i] = NULL; + } +#ifdef REBOOT_NOTIFIER + register_reboot_notifier(&adpt_reboot_notifier); +#endif + + return 0; +} + + +static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) +{ + struct adpt_device* d; + + if( pHba->channel[chan].device == NULL){ + printk(KERN_DEBUG"Adaptec I2O RAID: Trying to find device before they are allocated\n"); + return NULL; + } + + d = pHba->channel[chan].device[id]; + if(!d || d->tid == 0) { + return NULL; + } + + /* If it is the only lun at that address then this should match*/ + if(d->scsi_lun == lun){ + return d; + } + + /* else we need to look through all the luns */ + for(d=d->next_lun ; d ; d = d->next_lun){ + if(d->scsi_lun == lun){ + return d; + } + } + return NULL; +} + + +static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout) +{ + // I used my own version of the WAIT_QUEUE_HEAD + // to handle some version differences + // When embedded in the kernel this could go back to the vanilla one + ADPT_DECLARE_WAIT_QUEUE_HEAD(adpt_wq_i2o_post); + int status = 0; + ulong flags = 0; + struct adpt_i2o_post_wait_data *p1, *p2; + struct adpt_i2o_post_wait_data *wait_data = + kmalloc(sizeof(struct adpt_i2o_post_wait_data),GFP_KERNEL); + adpt_wait_queue_t wait; + + if(!wait_data){ + return -ENOMEM; + } + /* + * The spin locking is needed to keep anyone from playing + * with the queue pointers and id while we do the same + */ + spin_lock_irqsave(&adpt_post_wait_lock, flags); + // TODO we need a MORE unique way of getting ids + // to support async LCT get + wait_data->next = adpt_post_wait_queue; + adpt_post_wait_queue = wait_data; + adpt_post_wait_id = (++adpt_post_wait_id & 0x7fff); + wait_data->id = adpt_post_wait_id; + spin_unlock_irqrestore(&adpt_post_wait_lock, flags); + + wait_data->wq = &adpt_wq_i2o_post; + wait_data->status = -ETIMEDOUT; + + // this code is taken from kernel/sched.c:interruptible_sleep_on_timeout + wait.task = current; + init_waitqueue_entry(&wait, current); + wq_write_lock_irqsave(&adpt_wq_i2o_post.lock,flags); + __add_wait_queue(&adpt_wq_i2o_post, &wait); + wq_write_unlock(&adpt_wq_i2o_post.lock); + + msg[2] |= 0x80000000 | ((u32)wait_data->id); + timeout *= HZ; + if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){ + if(!timeout){ + current->state = TASK_INTERRUPTIBLE; + spin_unlock_irq(&io_request_lock); + schedule(); + spin_lock_irq(&io_request_lock); + } else { + current->state = TASK_INTERRUPTIBLE; + spin_unlock_irq(&io_request_lock); + schedule_timeout(timeout*HZ); + spin_lock_irq(&io_request_lock); + } + } + wq_write_lock_irq(&adpt_wq_i2o_post.lock); + __remove_wait_queue(&adpt_wq_i2o_post, &wait); + wq_write_unlock_irqrestore(&adpt_wq_i2o_post.lock,flags); + + if(status == -ETIMEDOUT){ + printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit); + // We will have to free the wait_data memory during shutdown + return status; + } + + /* Remove the entry from the queue. */ + p2 = NULL; + spin_lock_irqsave(&adpt_post_wait_lock, flags); + for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p1->next) { + if(p1 == wait_data) { + if(p1->status == I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION ) { + status = -EOPNOTSUPP; + } + if(p2) { + p2->next = p1->next; + } else { + adpt_post_wait_queue = p1->next; + } + break; + } + } + spin_unlock_irqrestore(&adpt_post_wait_lock, flags); + + kfree(wait_data); + + return status; +} + + +static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len) +{ + + u32 m = EMPTY_QUEUE; + u32 *msg; + ulong timeout = jiffies + 30*HZ; + do { + rmb(); + m = readl(pHba->post_port); + if (m != EMPTY_QUEUE) { + break; + } + if(time_after(jiffies,timeout)){ + printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit); + return -ETIMEDOUT; + } + } while(m == EMPTY_QUEUE); + + msg = (u32*) (pHba->msg_addr_virt + m); + memcpy_toio(msg, data, len); + wmb(); + + //post message + writel(m, pHba->post_port); + wmb(); + + return 0; +} + + +static void adpt_i2o_post_wait_complete(u32 context, int status) +{ + struct adpt_i2o_post_wait_data *p1 = NULL; + /* + * We need to search through the adpt_post_wait + * queue to see if the given message is still + * outstanding. If not, it means that the IOP + * took longer to respond to the message than we + * had allowed and timer has already expired. + * Not much we can do about that except log + * it for debug purposes, increase timeout, and recompile + * + * Lock needed to keep anyone from moving queue pointers + * around while we're looking through them. + */ + + context &= 0x7fff; + + spin_lock(&adpt_post_wait_lock); + for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) { + if(p1->id == context) { + p1->status = status; + spin_unlock(&adpt_post_wait_lock); + wake_up_interruptible(p1->wq); + return; + } + } + spin_unlock(&adpt_post_wait_lock); + // If this happens we loose commands that probably really completed + printk(KERN_DEBUG"dpti: Could Not find task %d in wait queue\n",context); + printk(KERN_DEBUG" Tasks in wait queue:\n"); + for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) { + printk(KERN_DEBUG" %d\n",p1->id); + } + return; +} + +static s32 adpt_i2o_reset_hba(adpt_hba* pHba) +{ + u32 msg[8]; + u8* status; + u32 m = EMPTY_QUEUE ; + ulong timeout = jiffies + (TMOUT_IOPRESET*HZ); + + if(pHba->initialized == FALSE) { // First time reset should be quick + timeout = jiffies + (25*HZ); + } else { + adpt_i2o_quiesce_hba(pHba); + } + + do { + rmb(); + m = readl(pHba->post_port); + if (m != EMPTY_QUEUE) { + break; + } + if(time_after(jiffies,timeout)){ + printk(KERN_WARNING"Timeout waiting for message!\n"); + return -ETIMEDOUT; + } + } while (m == EMPTY_QUEUE); + + status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32); + if(status == NULL) { + adpt_send_nop(pHba, m); + printk(KERN_ERR"IOP reset failed - no free memory.\n"); + return -ENOMEM; + } + memset(status,0,4); + + msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0; + msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID; + msg[2]=0; + msg[3]=0; + msg[4]=0; + msg[5]=0; + msg[6]=virt_to_bus(status); + msg[7]=0; + + memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg)); + wmb(); + writel(m, pHba->post_port); + wmb(); + + while(*status == 0){ + if(time_after(jiffies,timeout)){ + printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name); + kfree(status); + return -ETIMEDOUT; + } + rmb(); + } + + if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) { + PDEBUG("%s: Reset in progress...\n", pHba->name); + // Here we wait for message frame to become available + // indicated that reset has finished + do { + rmb(); + m = readl(pHba->post_port); + if (m != EMPTY_QUEUE) { + break; + } + if(time_after(jiffies,timeout)){ + printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name); + return -ETIMEDOUT; + } + } while (m == EMPTY_QUEUE); + // Flush the offset + adpt_send_nop(pHba, m); + } + adpt_i2o_status_get(pHba); + if(*status == 0x02 || + pHba->status_block->iop_state != ADAPTER_STATE_RESET) { + printk(KERN_WARNING"%s: Reset reject, trying to clear\n", + pHba->name); + } else { + PDEBUG("%s: Reset completed.\n", pHba->name); + } + + kfree(status); +#ifdef UARTDELAY + // This delay is to allow someone attached to the card through the debug UART to + // set up the dump levels that they want before the rest of the initialization sequence + adpt_delay(20000); +#endif + return 0; +} + + +static int adpt_i2o_parse_lct(adpt_hba* pHba) +{ + int i; + int max; + int tid; + struct i2o_device *d; + i2o_lct *lct = pHba->lct; + u8 bus_no = 0; + s16 scsi_id; + s16 scsi_lun; + u32 buf[10]; // larger than 7, or 8 ... + struct adpt_device* pDev; + + if (lct == NULL) { + printk(KERN_ERR "%s: LCT is empty???\n",pHba->name); + return -1; + } + + max = lct->table_size; + max -= 3; + max /= 9; + + for(i=0;ilct_entry[i].user_tid != 0xfff){ + /* + * If we have hidden devices, we need to inform the upper layers about + * the possible maximum id reference to handle device access when + * an array is disassembled. This code has no other purpose but to + * allow us future access to devices that are currently hidden + * behind arrays, hotspares or have not been configured (JBOD mode). + */ + if( lct->lct_entry[i].class_id != I2O_CLASS_RANDOM_BLOCK_STORAGE && + lct->lct_entry[i].class_id != I2O_CLASS_SCSI_PERIPHERAL && + lct->lct_entry[i].class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){ + continue; + } + tid = lct->lct_entry[i].tid; + // I2O_DPT_DEVICE_INFO_GROUP_NO; + if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) { + continue; + } + bus_no = buf[0]>>16; + scsi_id = buf[1]; + scsi_lun = (buf[2]>>8 )&0xff; + if(bus_no >= MAX_CHANNEL) { // Something wrong skip it + printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no); + continue; + } + if(scsi_id > MAX_ID){ + printk(KERN_WARNING"%s: SCSI ID %d out of range \n", pHba->name, bus_no); + continue; + } + if(bus_no > pHba->top_scsi_channel){ + pHba->top_scsi_channel = bus_no; + } + if(scsi_id > pHba->top_scsi_id){ + pHba->top_scsi_id = scsi_id; + } + if(scsi_lun > pHba->top_scsi_lun){ + pHba->top_scsi_lun = scsi_lun; + } + continue; + } + d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL); + if(d==NULL) + { + printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name); + return -ENOMEM; + } + + d->controller = (void*)pHba; + d->next = NULL; + + memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry)); + + d->flags = 0; + tid = d->lct_data.tid; + adpt_i2o_report_hba_unit(pHba, d); + adpt_i2o_install_device(pHba, d); + } + bus_no = 0; + for(d = pHba->devices; d ; d = d->next) { + if(d->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT || + d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PORT){ + tid = d->lct_data.tid; + // TODO get the bus_no from hrt-but for now they are in order + //bus_no = + if(bus_no > pHba->top_scsi_channel){ + pHba->top_scsi_channel = bus_no; + } + pHba->channel[bus_no].type = d->lct_data.class_id; + pHba->channel[bus_no].tid = tid; + if(adpt_i2o_query_scalar(pHba, tid, 0x0200, -1, buf, 28)>=0) + { + pHba->channel[bus_no].scsi_id = buf[1]; + PDEBUG("Bus %d - SCSI ID %d.\n", bus_no, buf[1]); + } + // TODO remove - this is just until we get from hrt + bus_no++; + if(bus_no >= MAX_CHANNEL) { // Something wrong skip it + printk(KERN_WARNING"%s: Channel number %d out of range - LCT\n", pHba->name, bus_no); + break; + } + } + } + + // Setup adpt_device table + for(d = pHba->devices; d ; d = d->next) { + if(d->lct_data.class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE || + d->lct_data.class_id == I2O_CLASS_SCSI_PERIPHERAL || + d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){ + + tid = d->lct_data.tid; + scsi_id = -1; + // I2O_DPT_DEVICE_INFO_GROUP_NO; + if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) { + bus_no = buf[0]>>16; + scsi_id = buf[1]; + scsi_lun = (buf[2]>>8 )&0xff; + if(bus_no >= MAX_CHANNEL) { // Something wrong skip it + continue; + } + if(scsi_id > MAX_ID){ + continue; + } + if( pHba->channel[bus_no].device[scsi_id] == NULL){ + pDev = kmalloc(sizeof(struct adpt_device),GFP_KERNEL); + if(pDev == NULL) { + return -ENOMEM; + } + pHba->channel[bus_no].device[scsi_id] = pDev; + memset(pDev,0,sizeof(struct adpt_device)); + } else { + for( pDev = pHba->channel[bus_no].device[scsi_id]; + pDev->next_lun; pDev = pDev->next_lun){ + } + pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL); + if(pDev == NULL) { + return -ENOMEM; + } + memset(pDev->next_lun,0,sizeof(struct adpt_device)); + pDev = pDev->next_lun; + } + pDev->tid = tid; + pDev->scsi_channel = bus_no; + pDev->scsi_id = scsi_id; + pDev->scsi_lun = scsi_lun; + pDev->pI2o_dev = d; + d->owner = pDev; + pDev->type = (buf[0])&0xff; + pDev->flags = (buf[0]>>8)&0xff; + if(scsi_id > pHba->top_scsi_id){ + pHba->top_scsi_id = scsi_id; + } + if(scsi_lun > pHba->top_scsi_lun){ + pHba->top_scsi_lun = scsi_lun; + } + } + if(scsi_id == -1){ + printk(KERN_WARNING"Could not find SCSI ID for %s\n", + d->lct_data.identity_tag); + } + } + } + return 0; +} + + +/* + * Each I2O controller has a chain of devices on it - these match + * the useful parts of the LCT of the board. + */ + +static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d) +{ + down(&adpt_configuration_lock); + d->controller=pHba; + d->owner=NULL; + d->next=pHba->devices; + d->prev=NULL; + if (pHba->devices != NULL){ + pHba->devices->prev=d; + } + pHba->devices=d; + *d->dev_name = 0; + + up(&adpt_configuration_lock); + return 0; +} + +static int adpt_open(struct inode *inode, struct file *file) +{ + int minor; + adpt_hba* pHba; + + //TODO check for root access + // + minor = MINOR(inode->i_rdev); + if (minor >= hba_count) { + return -ENXIO; + } + down(&adpt_configuration_lock); + for (pHba = hba_chain; pHba; pHba = pHba->next) { + if (pHba->unit == minor) { + break; /* found adapter */ + } + } + if (pHba == NULL) { + up(&adpt_configuration_lock); + return -ENXIO; + } + +// if(pHba->in_use){ + // up(&adpt_configuration_lock); +// return -EBUSY; +// } + + pHba->in_use = 1; + up(&adpt_configuration_lock); + + return 0; +} + +static int adpt_close(struct inode *inode, struct file *file) +{ + int minor; + adpt_hba* pHba; + + minor = MINOR(inode->i_rdev); + if (minor >= hba_count) { + return -ENXIO; + } + down(&adpt_configuration_lock); + for (pHba = hba_chain; pHba; pHba = pHba->next) { + if (pHba->unit == minor) { + break; /* found adapter */ + } + } + up(&adpt_configuration_lock); + if (pHba == NULL) { + return -ENXIO; + } + + pHba->in_use = 0; + + return 0; +} + + +static int adpt_i2o_passthru(adpt_hba* pHba, u32* arg) +{ + u32 msg[MAX_MESSAGE_SIZE]; + u32* reply = NULL; + u32 size = 0; + u32 reply_size = 0; + u32* user_msg = (u32*)arg; + u32* user_reply = NULL; + ulong sg_list[pHba->sg_tablesize]; + u32 sg_offset = 0; + u32 sg_count = 0; + int sg_index = 0; + u32 i = 0; + u32 rcode = 0; + ulong p = 0; + ulong flags = 0; + + memset(&msg, 0, MAX_MESSAGE_SIZE*4); + // get user msg size in u32s + if(get_user(size, &user_msg[0])){ + return -EFAULT; + } + size = size>>16; + + user_reply = &user_msg[size]; + if(size > MAX_MESSAGE_SIZE){ + return -EFAULT; + } + size *= 4; // Convert to bytes + + /* Copy in the user's I2O command */ + if(copy_from_user((void*)msg, (void*)user_msg, size)) { + return -EFAULT; + } + get_user(reply_size, &user_reply[0]); + reply_size = reply_size>>16; + if(reply_size > REPLY_FRAME_SIZE){ + reply_size = REPLY_FRAME_SIZE; + } + reply_size *= 4; + reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL); + if(reply == NULL) { + printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name); + return -ENOMEM; + } + memset(reply,0,REPLY_FRAME_SIZE*4); + sg_offset = (msg[0]>>4)&0xf; + msg[2] = 0x40000000; // IOCTL context + msg[3] = (u32)reply; + memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize); + if(sg_offset) { + // TODO 64bit fix + struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset); + sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); + if (sg_count > pHba->sg_tablesize){ + printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count); + kfree (reply); + return -EINVAL; + } + + for(i = 0; i < sg_count; i++) { + int sg_size; + + if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) { + printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",pHba->name,i, sg[i].flag_count); + rcode = -EINVAL; + goto cleanup; + } + sg_size = sg[i].flag_count & 0xffffff; + /* Allocate memory for the transfer */ + p = (ulong)kmalloc(sg_size, GFP_KERNEL|ADDR32); + if(p == 0) { + printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + pHba->name,sg_size,i,sg_count); + rcode = -ENOMEM; + goto cleanup; + } + sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. + /* Copy in the user's SG buffer if necessary */ + if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) { + // TODO 64bit fix + if (copy_from_user((void*)p,(void*)sg[i].addr_bus, sg_size)) { + printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i); + rcode = -EFAULT; + goto cleanup; + } + } + //TODO 64bit fix + sg[i].addr_bus = (u32)virt_to_bus((void*)p); + } + } + + do { + spin_lock_irqsave(&io_request_lock, flags); + // This state stops any new commands from enterring the + // controller while processing the ioctl +// pHba->state |= DPTI_STATE_IOCTL; +// We can't set this now - The scsi subsystem sets host_blocked and +// the queue empties and stops. We need a way to restart the queue + rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); +// pHba->state &= ~DPTI_STATE_IOCTL; + spin_unlock_irqrestore(&io_request_lock, flags); + } while(rcode == -ETIMEDOUT); + + if(rcode){ + goto cleanup; + } + + if(sg_offset) { + /* Copy back the Scatter Gather buffers back to user space */ + u32 j; + // TODO 64bit fix + struct sg_simple_element* sg; + int sg_size; + + // re-acquire the original message to handle correctly the sg copy operation + memset(&msg, 0, MAX_MESSAGE_SIZE*4); + // get user msg size in u32s + if(get_user(size, &user_msg[0])){ + rcode = -EFAULT; + goto cleanup; + } + size = size>>16; + size *= 4; + /* Copy in the user's I2O command */ + if (copy_from_user ((void*)msg, (void*)user_msg, size)) { + rcode = -EFAULT; + goto cleanup; + } + sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); + + // TODO 64bit fix + sg = (struct sg_simple_element*)(msg + sg_offset); + for (j = 0; j < sg_count; j++) { + /* Copy out the SG list to user's buffer if necessary */ + if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) { + sg_size = sg[j].flag_count & 0xffffff; + // TODO 64bit fix + if (copy_to_user((void*)sg[j].addr_bus,(void*)sg_list[j], sg_size)) { + printk(KERN_WARNING"%s: Could not copy %lx TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus); + rcode = -EFAULT; + goto cleanup; + } + } + } + } + + /* Copy back the reply to user space */ + if (reply_size) { + // we wrote our own values for context - now restore the user supplied ones + if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) { + printk(KERN_WARNING"%s: Could not copy message context FROM user\n",pHba->name); + rcode = -EFAULT; + } + if(copy_to_user(user_reply, reply, reply_size)) { + printk(KERN_WARNING"%s: Could not copy reply TO user\n",pHba->name); + rcode = -EFAULT; + } + } + + +cleanup: + kfree (reply); + while(sg_index) { + if(sg_list[--sg_index]) { + kfree((void*)(sg_list[sg_index])); + } + } + return rcode; +} + + +/* + * This routine returns information about the system. This does not effect + * any logic and if the info is wrong - it doesn't matter. + */ + +/* Get all the info we can not get from kernel services */ +static int adpt_system_info(void *buffer) +{ + sysInfo_S si; + + memset(&si, 0, sizeof(si)); + + si.osType = OS_LINUX; + si.osMajorVersion = (u8) (LINUX_VERSION_CODE >> 16); + si.osMinorVersion = (u8) (LINUX_VERSION_CODE >> 8 & 0x0ff); + si.osRevision = (u8) (LINUX_VERSION_CODE & 0x0ff); + si.busType = SI_PCI_BUS; + si.processorFamily = DPTI_sig.dsProcessorFamily; + +#if defined __i386__ + adpt_i386_info(&si); +#elif defined __ia64__ + adpt_ia64_info(&si); +#elif define __sparc__ + adpt_sparc_info(&si); +#elif defined __alpha__ + adpt_alpha_info(&si); +#else + si.processorType = 0xff ; +#endif + if(copy_to_user(buffer, &si, sizeof(si))){ + printk(KERN_WARNING"dpti: Could not copy buffer TO user\n"); + return -EFAULT; + } + + return 0; +} + +#if defined __ia64__ +static void adpt_ia64_info(sysInfo_S* si) +{ + // This is all the info we need for now + // We will add more info as our new + // managmenent utility requires it + si->processorType = PROC_IA64; +} +#endif + + +#if defined __sparc__ +static void adpt_sparc_info(sysInfo_S* si) +{ + // This is all the info we need for now + // We will add more info as our new + // managmenent utility requires it + si->processorType = PROC_ULTRASPARC; +} +#endif + +#if defined __alpha__ +static void adpt_sparc_info(sysInfo_S* si) +{ + // This is all the info we need for now + // We will add more info as our new + // managmenent utility requires it + si->processorType = PROC_ALPHA; +} +#endif + +#if defined __i386__ + +static void adpt_i386_info(sysInfo_S* si) +{ + // This is all the info we need for now + // We will add more info as our new + // managmenent utility requires it + switch (boot_cpu_data.x86) { + case CPU_386: + si->processorType = PROC_386; + break; + case CPU_486: + si->processorType = PROC_486; + break; + case CPU_586: + si->processorType = PROC_PENTIUM; + break; + default: // Just in case + si->processorType = PROC_PENTIUM; + break; + } +} + +#endif + + +static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, + ulong arg) +{ + int minor; + int error = 0; + adpt_hba* pHba; + ulong flags; + + minor = MINOR(inode->i_rdev); + if (minor >= DPTI_MAX_HBA){ + return -ENXIO; + } + down(&adpt_configuration_lock); + for (pHba = hba_chain; pHba; pHba = pHba->next) { + if (pHba->unit == minor) { + break; /* found adapter */ + } + } + up(&adpt_configuration_lock); + if(pHba == NULL){ + return -ENXIO; + } + + while((volatile u32) pHba->state & DPTI_STATE_RESET ) { + set_task_state(current,TASK_UNINTERRUPTIBLE); + schedule_timeout(2); + + } + + switch (cmd) { + // TODO: handle 3 cases + case DPT_SIGNATURE: + if (copy_to_user((char*)arg, &DPTI_sig, sizeof(DPTI_sig))) { + return -EFAULT; + } + break; + case I2OUSRCMD: + return adpt_i2o_passthru(pHba,(u32*)arg); + break; + + case DPT_CTRLINFO:{ + drvrHBAinfo_S HbaInfo; + +#define FLG_OSD_PCI_VALID 0x0001 +#define FLG_OSD_DMA 0x0002 +#define FLG_OSD_I2O 0x0004 + memset(&HbaInfo, 0, sizeof(HbaInfo)); + HbaInfo.drvrHBAnum = pHba->unit; + HbaInfo.baseAddr = (ulong) pHba->base_addr_phys; + HbaInfo.blinkState = adpt_read_blink_led(pHba); + HbaInfo.pciBusNum = pHba->pDev->bus->number; + HbaInfo.pciDeviceNum=PCI_SLOT(pHba->pDev->devfn); + HbaInfo.Interrupt = pHba->pDev->irq; + HbaInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O; + if(copy_to_user((void *) arg, &HbaInfo, sizeof(HbaInfo))){ + printk(KERN_WARNING"%s: Could not copy HbaInfo TO user\n",pHba->name); + return -EFAULT; + } + break; + } + case DPT_SYSINFO: + return adpt_system_info((void*)arg); + break; + case DPT_BLINKLED:{ + u32 value; + value = (u32)adpt_read_blink_led(pHba); + if (copy_to_user((char*)arg, &value, sizeof(value))) { + return -EFAULT; + } + break; + } + case I2ORESETCMD: + spin_lock_irqsave(&io_request_lock, flags); + adpt_hba_reset(pHba); + spin_unlock_irqrestore(&io_request_lock, flags); + break; + case I2ORESCANCMD: + adpt_rescan(pHba); + break; + case DPT_TARGET_BUSY & 0xFFFF: + case DPT_TARGET_BUSY: + { + TARGET_BUSY_T busy; + struct adpt_device* d; + + if (copy_from_user((void*)&busy, (void*)arg, sizeof(TARGET_BUSY_T))) { + return -EFAULT; + } + + d = adpt_find_device(pHba, busy.channel, busy.id, busy.lun); + if(d == NULL){ + return -ENODEV; + } + busy.isBusy = ((d->pScsi_dev) && (0 != d->pScsi_dev->access_count)) ? 1 : 0; + if (copy_to_user ((char*)arg, &busy, sizeof(busy))) { + return -EFAULT; + } + break; + } + default: + return -EINVAL; + } + + return error; +} + + +static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs) +{ + Scsi_Cmnd* cmd; + adpt_hba* pHba=NULL; + u32 m; + ulong reply; + u32 status=0; + u32 context; + ulong flags = 0; + + pHba = dev_id; + if (pHba == NULL ){ + printk(KERN_WARNING"adpt_isr: NULL dev_id\n"); + return; + } + spin_lock_irqsave(&io_request_lock, flags); + while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) { + m = readl(pHba->reply_port); + if(m == EMPTY_QUEUE){ + // Try twice then give up + rmb(); + m = readl(pHba->reply_port); + if(m == EMPTY_QUEUE){ + // This really should not happen + printk(KERN_ERR"dpti: Could not get reply frame\n"); + spin_unlock_irqrestore(&io_request_lock,flags); + return; + } + } + reply = (ulong)bus_to_virt(m); + + if (readl(reply) & MSG_FAIL) { + u32 old_m = readl(reply+28); + ulong msg; + u32 old_context; + PDEBUG("%s: Failed message\n",pHba->name); + if(old_m >= 0x100000){ + printk(KERN_ERR"%s: Bad preserved MFA (%x)- dropping frame\n",pHba->name,old_m); + writel(m,pHba->reply_port); + continue; + } + // Transaction context is 0 in failed reply frame + msg = (ulong)(pHba->msg_addr_virt + old_m); + old_context = readl(msg+12); + writel(old_context, reply+12); + adpt_send_nop(pHba, old_m); + } + context = readl(reply+8); + if(context & 0x40000000){ // IOCTL + ulong p = (ulong)(readl(reply+12)); + if( p != 0) { + memcpy((void*)p, (void*)reply, REPLY_FRAME_SIZE * 4); + } + // All IOCTLs will also be post wait + } + if(context & 0x80000000){ // Post wait message + status = readl(reply+16); + if(status >> 24){ + status &= 0xffff; /* Get detail status */ + } else { + status = I2O_POST_WAIT_OK; + } + if(!(context & 0x40000000)) { + cmd = (Scsi_Cmnd*) readl(reply+12); + if(cmd != NULL) { + printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context); + } + } + adpt_i2o_post_wait_complete(context, status); + } else { // SCSI message + cmd = (Scsi_Cmnd*) readl(reply+12); + if(cmd != NULL){ + if(cmd->serial_number != 0) { // If not timedout + adpt_i2o_to_scsi(reply, cmd); + } + } + } + writel(m, pHba->reply_port); + wmb(); + rmb(); + } + spin_unlock_irqrestore(&io_request_lock, flags); + return; + +} + +static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d) +{ + int i; + u32 msg[MAX_MESSAGE_SIZE]; + u32* mptr; + u32 *lenptr; + int direction; + int scsidir; + u32 len; + u32 reqlen; + s32 rcode; + + memset(msg, 0 , sizeof(msg)); + len = cmd->request_bufflen; + direction = 0x00000000; + + scsidir = 0x00000000; // DATA NO XFER + if(len) { + /* + * Set SCBFlags to indicate if data is being transferred + * in or out, or no data transfer + * Note: Do not have to verify index is less than 0 since + * cmd->cmnd[0] is an unsigned char + */ + switch(cmd->sc_data_direction){ + case SCSI_DATA_READ: + scsidir =0x40000000; // DATA IN (iop<--dev) + break; + case SCSI_DATA_WRITE: + direction=0x04000000; // SGL OUT + scsidir =0x80000000; // DATA OUT (iop-->dev) + break; + case SCSI_DATA_NONE: + break; + case SCSI_DATA_UNKNOWN: + scsidir =0x40000000; // DATA IN (iop<--dev) + // Assume In - and continue; + break; + default: + printk(KERN_WARNING"%s: scsi opcode 0x%x not supported.\n", + pHba->name, cmd->cmnd[0]); + cmd->result = (DID_OK <<16) | (INITIATOR_ERROR << 8); + cmd->scsi_done(cmd); + return 0; + } + } + // msg[0] is set later + // I2O_CMD_SCSI_EXEC + msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid); + msg[2] = 0; + msg[3] = (u32)cmd; /* We want the SCSI control block back */ + // Our cards use the transaction context as the tag for queueing + // Adaptec/DPT Private stuff + msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16); + msg[5] = d->tid; + /* Direction, disconnect ok | sense data | simple queue , CDBLen */ + // I2O_SCB_FLAG_ENABLE_DISCONNECT | + // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG | + // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE; + msg[6] = scsidir|0x20a00000|cmd->cmd_len; + + mptr=msg+7; + + // Write SCSI command into the message - always 16 byte block + memset(mptr, 0, 16); + memcpy(mptr, cmd->cmnd, cmd->cmd_len); + mptr+=4; + lenptr=mptr++; /* Remember me - fill in when we know */ + reqlen = 14; // SINGLE SGE + /* Now fill in the SGList and command */ + if(cmd->use_sg) { + struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; + len = 0; + for(i = 0 ; i < cmd->use_sg; i++) { + *mptr++ = direction|0x10000000|sg->length; + len+=sg->length; + *mptr++ = virt_to_bus(sg->address); + sg++; + } + /* Make this an end of list */ + mptr[-2] = direction|0xD0000000|(sg-1)->length; + reqlen = mptr - msg; + *lenptr = len; + + if(cmd->underflow && len != cmd->underflow){ + printk(KERN_WARNING"Cmd len %08X Cmd underflow %08X\n", + len, cmd->underflow); + } + } else { + *lenptr = len = cmd->request_bufflen; + if(len == 0) { + reqlen = 12; + } else { + *mptr++ = 0xD0000000|direction|cmd->request_bufflen; + *mptr++ = virt_to_bus(cmd->request_buffer); + } + } + + /* Stick the headers on */ + msg[0] = reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0); + + // Send it on it's way + rcode = adpt_i2o_post_this(pHba, msg, reqlen<<2); + if (rcode == 0) { + return 0; + } + return rcode; +} + + +static s32 adpt_scsi_register(adpt_hba* pHba,Scsi_Host_Template * sht) +{ + struct Scsi_Host *host = NULL; + + host = scsi_register(sht, sizeof(adpt_hba*)); + if (host == NULL) { + printk ("%s: scsi_register returned NULL\n",pHba->name); + return -1; + } + (adpt_hba*)(host->hostdata[0]) = pHba; + pHba->host = host; + + host->irq = pHba->pDev->irq;; + /* no IO ports, so don't have to set host->io_port and + * host->n_io_port + */ + host->io_port = 0; + host->n_io_port = 0; + /* see comments in hosts.h */ + host->max_id = 16; + host->max_lun = 256; + host->max_channel = pHba->top_scsi_channel + 1; + host->cmd_per_lun = 256; + host->unique_id = (uint) pHba; + host->sg_tablesize = pHba->sg_tablesize; + host->can_queue = pHba->post_fifo_size; + host->select_queue_depths = adpt_select_queue_depths; + + return 0; +} + + +static s32 adpt_i2o_to_scsi(ulong reply, Scsi_Cmnd* cmd) +{ + adpt_hba* pHba; + u32 hba_status; + u32 dev_status; + u32 reply_flags = readl(reply) & 0xff00; // Leave it shifted up 8 bits + // I know this would look cleaner if I just read bytes + // but the model I have been using for all the rest of the + // io is in 4 byte words - so I keep that model + u16 detailed_status = readl(reply+16) &0xffff; + dev_status = (detailed_status & 0xff); + hba_status = detailed_status >> 8; + + // calculate resid for sg + cmd->resid = cmd->request_bufflen - readl(reply+5); + + pHba = (adpt_hba*) cmd->host->hostdata[0]; + + cmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false + + if(!(reply_flags & MSG_FAIL)) { + switch(detailed_status & I2O_SCSI_DSC_MASK) { + case I2O_SCSI_DSC_SUCCESS: + cmd->result = (DID_OK << 16); + // handle underflow + if(readl(reply+5) < cmd->underflow ) { + cmd->result = (DID_ERROR <<16); + printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name); + } + break; + case I2O_SCSI_DSC_REQUEST_ABORTED: + cmd->result = (DID_ABORT << 16); + break; + case I2O_SCSI_DSC_PATH_INVALID: + case I2O_SCSI_DSC_DEVICE_NOT_PRESENT: + case I2O_SCSI_DSC_SELECTION_TIMEOUT: + case I2O_SCSI_DSC_COMMAND_TIMEOUT: + case I2O_SCSI_DSC_NO_ADAPTER: + case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE: + printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%d) hba status=0x%x, dev status=0x%x, cmd=0x%x\n", + pHba->name, (u32)cmd->channel, (u32)cmd->target, (u32)cmd->lun, hba_status, dev_status, cmd->cmnd[0]); + cmd->result = (DID_TIME_OUT << 16); + break; + case I2O_SCSI_DSC_ADAPTER_BUSY: + case I2O_SCSI_DSC_BUS_BUSY: + cmd->result = (DID_BUS_BUSY << 16); + break; + case I2O_SCSI_DSC_SCSI_BUS_RESET: + case I2O_SCSI_DSC_BDR_MESSAGE_SENT: + cmd->result = (DID_RESET << 16); + break; + case I2O_SCSI_DSC_PARITY_ERROR_FAILURE: + printk(KERN_WARNING"%s: SCSI CMD parity error\n",pHba->name); + cmd->result = (DID_PARITY << 16); + break; + case I2O_SCSI_DSC_UNABLE_TO_ABORT: + case I2O_SCSI_DSC_COMPLETE_WITH_ERROR: + case I2O_SCSI_DSC_UNABLE_TO_TERMINATE: + case I2O_SCSI_DSC_MR_MESSAGE_RECEIVED: + case I2O_SCSI_DSC_AUTOSENSE_FAILED: + case I2O_SCSI_DSC_DATA_OVERRUN: + case I2O_SCSI_DSC_UNEXPECTED_BUS_FREE: + case I2O_SCSI_DSC_SEQUENCE_FAILURE: + case I2O_SCSI_DSC_REQUEST_LENGTH_ERROR: + case I2O_SCSI_DSC_PROVIDE_FAILURE: + case I2O_SCSI_DSC_REQUEST_TERMINATED: + case I2O_SCSI_DSC_IDE_MESSAGE_SENT: + case I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT: + case I2O_SCSI_DSC_MESSAGE_RECEIVED: + case I2O_SCSI_DSC_INVALID_CDB: + case I2O_SCSI_DSC_LUN_INVALID: + case I2O_SCSI_DSC_SCSI_TID_INVALID: + case I2O_SCSI_DSC_FUNCTION_UNAVAILABLE: + case I2O_SCSI_DSC_NO_NEXUS: + case I2O_SCSI_DSC_CDB_RECEIVED: + case I2O_SCSI_DSC_LUN_ALREADY_ENABLED: + case I2O_SCSI_DSC_QUEUE_FROZEN: + case I2O_SCSI_DSC_REQUEST_INVALID: + default: + printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", + pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->channel, (u32)cmd->target, (u32)cmd-> lun, + hba_status, dev_status, cmd->cmnd[0]); + cmd->result = (DID_ERROR << 16); + break; + } + + // copy over the request sense data if it was a check + // condition status + if(dev_status == 0x02 /*CHECK_CONDITION*/) { + u32 len = sizeof(cmd->sense_buffer); + len = (len > 40) ? 40 : len; + // Copy over the sense data + memcpy(cmd->sense_buffer, (void*)(reply+28) , len); + if(cmd->sense_buffer[0] == 0x70 /* class 7 */ && + cmd->sense_buffer[2] == DATA_PROTECT ){ + /* This is to handle an array failed */ + cmd->result = (DID_TIME_OUT << 16); + printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", + pHba->name, (u32)cmd->channel, (u32)cmd->target, (u32)cmd->lun, + hba_status, dev_status, cmd->cmnd[0]); + + } + } + } else { + /* In this condtion we could not talk to the tid + * the card rejected it. We should signal a retry + * for a limitted number of retries. + */ + cmd->result = (DID_TIME_OUT << 16); + printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%d) tid=%d, cmd=0x%x\n", + pHba->name, (u32)cmd->channel, (u32)cmd->target, (u32)cmd-> lun, + ((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]); + } + + cmd->result |= (dev_status); + + if(cmd->scsi_done != NULL){ + cmd->scsi_done(cmd); + } + return cmd->result; +} + + +static s32 adpt_rescan(adpt_hba* pHba) +{ + s32 rcode; + ulong flags; + + spin_lock_irqsave(&io_request_lock, flags); + if ((rcode=adpt_i2o_lct_get(pHba)) < 0){ + spin_unlock_irqrestore(&io_request_lock, flags); + return rcode; + } + + if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){ + spin_unlock_irqrestore(&io_request_lock, flags); + return rcode; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return 0; +} + + +static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) +{ + int i; + int max; + int tid; + struct i2o_device *d; + i2o_lct *lct = pHba->lct; + u8 bus_no = 0; + s16 scsi_id; + s16 scsi_lun; + u32 buf[10]; // at least 8 u32's + struct adpt_device* pDev = NULL; + struct i2o_device* pI2o_dev = NULL; + + if (lct == NULL) { + printk(KERN_ERR "%s: LCT is empty???\n",pHba->name); + return -1; + } + + max = lct->table_size; + max -= 3; + max /= 9; + + // Mark each drive as unscanned + for (d = pHba->devices; d; d = d->next) { + pDev =(struct adpt_device*) d->owner; + if(!pDev){ + continue; + } + pDev->state |= DPTI_DEV_UNSCANNED; + } + + printk(KERN_INFO "%s: LCT has %d entries.\n", pHba->name,max); + + for(i=0;ilct_entry[i].user_tid != 0xfff){ + continue; + } + + if( lct->lct_entry[i].class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE || + lct->lct_entry[i].class_id == I2O_CLASS_SCSI_PERIPHERAL || + lct->lct_entry[i].class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){ + tid = lct->lct_entry[i].tid; + if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) { + printk(KERN_ERR"%s: Could not query device\n",pHba->name); + continue; + } + bus_no = buf[0]>>16; + scsi_id = buf[1]; + scsi_lun = (buf[2]>>8 )&0xff; + pDev = pHba->channel[bus_no].device[scsi_id]; + /* da lun */ + while(pDev) { + if(pDev->scsi_lun == scsi_lun) { + break; + } + pDev = pDev->next_lun; + } + if(!pDev ) { // Something new add it + d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL); + if(d==NULL) + { + printk(KERN_CRIT "Out of memory for I2O device data.\n"); + return -ENOMEM; + } + + d->controller = (void*)pHba; + d->next = NULL; + + memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry)); + + d->flags = 0; + adpt_i2o_report_hba_unit(pHba, d); + adpt_i2o_install_device(pHba, d); + + if(bus_no >= MAX_CHANNEL) { // Something wrong skip it + printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no); + continue; + } + pDev = pHba->channel[bus_no].device[scsi_id]; + if( pDev == NULL){ + pDev = kmalloc(sizeof(struct adpt_device),GFP_KERNEL); + if(pDev == NULL) { + return -ENOMEM; + } + pHba->channel[bus_no].device[scsi_id] = pDev; + } else { + while (pDev->next_lun) { + pDev = pDev->next_lun; + } + pDev = pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL); + if(pDev == NULL) { + return -ENOMEM; + } + } + memset(pDev,0,sizeof(struct adpt_device)); + pDev->tid = d->lct_data.tid; + pDev->scsi_channel = bus_no; + pDev->scsi_id = scsi_id; + pDev->scsi_lun = scsi_lun; + pDev->pI2o_dev = d; + d->owner = pDev; + pDev->type = (buf[0])&0xff; + pDev->flags = (buf[0]>>8)&0xff; + // Too late, SCSI system has made up it's mind, but what the hey ... + if(scsi_id > pHba->top_scsi_id){ + pHba->top_scsi_id = scsi_id; + } + if(scsi_lun > pHba->top_scsi_lun){ + pHba->top_scsi_lun = scsi_lun; + } + continue; + } // end of new i2o device + + // We found an old device - check it + while(pDev) { + if(pDev->scsi_lun == scsi_lun) { + if(pDev->pScsi_dev->online == FALSE) { + printk(KERN_WARNING"%s: Setting device (%d,%d,%d) back online\n", + pHba->name,bus_no,scsi_id,scsi_lun); + if (pDev->pScsi_dev) { + pDev->pScsi_dev->online = TRUE; + } + } + d = pDev->pI2o_dev; + if(d->lct_data.tid != tid) { // something changed + pDev->tid = tid; + memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry)); + if (pDev->pScsi_dev) { + pDev->pScsi_dev->changed = TRUE; + pDev->pScsi_dev->removable = TRUE; + } + } + // Found it - mark it scanned + pDev->state = DPTI_DEV_ONLINE; + break; + } + pDev = pDev->next_lun; + } + } + } + for (pI2o_dev = pHba->devices; pI2o_dev; pI2o_dev = pI2o_dev->next) { + pDev =(struct adpt_device*) pI2o_dev->owner; + if(!pDev){ + continue; + } + // Drive offline drives that previously existed but could not be found + // in the LCT table + if (pDev->state & DPTI_DEV_UNSCANNED){ + pDev->state = DPTI_DEV_OFFLINE; + printk(KERN_WARNING"%s: Device (%d,%d,%d) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun); + if (pDev->pScsi_dev) { + pDev->pScsi_dev->online = FALSE; + if (pDev->pScsi_dev->access_count) { + // A drive that was mounted is no longer there... bad! + SCSI_LOG_ERROR_RECOVERY(1, printk ("%s:Rescan: Previously " + "mounted drive not found!\n",pHba->name)); + printk(KERN_WARNING"%s:Mounted drive taken offline\n",pHba->name); + } + } + } + } + return 0; +} + +static void adpt_fail_posted_scbs(adpt_hba* pHba) +{ + Scsi_Cmnd* cmd = NULL; + Scsi_Device* d = NULL; + + if( pHba->host->host_queue != NULL ) { + d = pHba->host->host_queue; + if(!d){ + return; + } + while( d->next != NULL ){ + for(cmd = d->device_queue; cmd ; cmd = cmd->next){ + if(cmd->serial_number == 0){ + continue; + } + cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1); + cmd->scsi_done(cmd); + } + d = d->next; + } + } +} + + +/*============================================================================ + * Routines from i2o subsystem + *============================================================================ + */ + + + +/* + * Bring an I2O controller into HOLD state. See the spec. + */ +static int adpt_i2o_activate_hba(adpt_hba* pHba) +{ + int rcode; + + if(pHba->initialized ) { + if (adpt_i2o_status_get(pHba) < 0) { + if((rcode = adpt_i2o_reset_hba(pHba) != 0)){ + printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name); + return rcode; + } + if (adpt_i2o_status_get(pHba) < 0) { + printk(KERN_INFO "HBA not responding.\n"); + return -1; + } + } + + if(pHba->status_block->iop_state == ADAPTER_STATE_FAULTED) { + printk(KERN_CRIT "%s: hardware fault\n", pHba->name); + return -1; + } + + if (pHba->status_block->iop_state == ADAPTER_STATE_READY || + pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL || + pHba->status_block->iop_state == ADAPTER_STATE_HOLD || + pHba->status_block->iop_state == ADAPTER_STATE_FAILED) { + adpt_i2o_reset_hba(pHba); + if (adpt_i2o_status_get(pHba) < 0 || pHba->status_block->iop_state != ADAPTER_STATE_RESET) { + printk(KERN_ERR "%s: Failed to initialize.\n", pHba->name); + return -1; + } + } + } else { + if((rcode = adpt_i2o_reset_hba(pHba) != 0)){ + printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name); + return rcode; + } + + } + + if (adpt_i2o_init_outbound_q(pHba) < 0) { + return -1; + } + + /* In HOLD state */ + + if (adpt_i2o_hrt_get(pHba) < 0) { + return -1; + } + + return 0; +} + +/* + * Bring a controller online into OPERATIONAL state. + */ + +static int adpt_i2o_online_hba(adpt_hba* pHba) +{ + if (adpt_i2o_systab_send(pHba) < 0) { + adpt_i2o_delete_hba(pHba); + return -1; + } + /* In READY state */ + + if (adpt_i2o_enable_hba(pHba) < 0) { + adpt_i2o_delete_hba(pHba); + return -1; + } + + /* In OPERATIONAL state */ + return 0; +} + +static s32 adpt_send_nop(adpt_hba*pHba,u32 m) +{ + u32 *msg; + ulong timeout = jiffies + 5*HZ; + + while(m == EMPTY_QUEUE){ + rmb(); + m = readl(pHba->post_port); + if(m != EMPTY_QUEUE){ + break; + } + if(time_after(jiffies,timeout)){ + printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name); + return 2; + } + } + msg = (u32*)(pHba->msg_addr_virt + m); + writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]); + writel( I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0,&msg[1]); + writel( 0,&msg[2]); + wmb(); + + writel(m, pHba->post_port); + wmb(); + return 0; +} + +static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) +{ + u8 *status; + u32 *msg = NULL; + int i; + ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ; + u32* ptr; + u32 outbound_frame; // This had to be a 32 bit address + u32 m; + + do { + rmb(); + m = readl(pHba->post_port); + if (m != EMPTY_QUEUE) { + break; + } + + if(time_after(jiffies,timeout)){ + printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name); + return -ETIMEDOUT; + } + } while(m == EMPTY_QUEUE); + + msg=(u32 *)(pHba->msg_addr_virt+m); + + status = kmalloc(4,GFP_KERNEL|ADDR32); + if (status==NULL) { + adpt_send_nop(pHba, m); + printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n", + pHba->name); + return -ENOMEM; + } + memset(status, 0, 4); + + writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]); + writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]); + writel(0, &msg[2]); + writel(0x0106, &msg[3]); /* Transaction context */ + writel(4096, &msg[4]); /* Host page frame size */ + writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */ + writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */ + writel(virt_to_bus(status), &msg[7]); + + writel(m, pHba->post_port); + wmb(); + + // Wait for the reply status to come back + do { + if (*status) { + if (*status != 0x01 /*I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS*/) { + break; + } + } + rmb(); + if(time_after(jiffies,timeout)){ + printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name); + kfree((void*)status); + return -ETIMEDOUT; + } + } while (1); + + // If the command was successful, fill the fifo with our reply + // message packets + if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) { + kfree((void*)status); + return -2; + } + kfree((void*)status); + + if(pHba->reply_pool != NULL){ + kfree(pHba->reply_pool); + } + + pHba->reply_pool = (u32*)kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); + if(!pHba->reply_pool){ + printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name); + return -1; + } + memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4); + + ptr = pHba->reply_pool; + for(i = 0; i < pHba->reply_fifo_size; i++) { + outbound_frame = (u32)virt_to_bus(ptr); + writel(outbound_frame, pHba->reply_port); + wmb(); + ptr += REPLY_FRAME_SIZE; + } + adpt_i2o_status_get(pHba); + return 0; +} + + +/* + * I2O System Table. Contains information about + * all the IOPs in the system. Used to inform IOPs + * about each other's existence. + * + * sys_tbl_ver is the CurrentChangeIndicator that is + * used by IOPs to track changes. + */ + + + +static s32 adpt_i2o_status_get(adpt_hba* pHba) +{ + ulong timeout; + u32 m; + u32 *msg; + u8 *status_block=NULL; + ulong status_block_bus; + + if(pHba->status_block == NULL) { + pHba->status_block = (i2o_status_block*) + kmalloc(sizeof(i2o_status_block),GFP_KERNEL|ADDR32); + if(pHba->status_block == NULL) { + printk(KERN_ERR + "dpti%d: Get Status Block failed; Out of memory. \n", + pHba->unit); + return -ENOMEM; + } + } + memset(pHba->status_block, 0, sizeof(i2o_status_block)); + status_block = (u8*)(pHba->status_block); + status_block_bus = virt_to_bus(pHba->status_block); + timeout = jiffies+TMOUT_GETSTATUS*HZ; + do { + rmb(); + m = readl(pHba->post_port); + if (m != EMPTY_QUEUE) { + break; + } + if(time_after(jiffies,timeout)){ + printk(KERN_ERR "%s: Timeout waiting for message !\n", + pHba->name); + return -ETIMEDOUT; + } + } while(m==EMPTY_QUEUE); + + + msg=(u32*)(pHba->msg_addr_virt+m); + + writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]); + writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]); + writel(1, &msg[2]); + writel(0, &msg[3]); + writel(0, &msg[4]); + writel(0, &msg[5]); + writel(((u32)status_block_bus)&0xffffffff, &msg[6]); + writel(0, &msg[7]); + writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes + + //post message + writel(m, pHba->post_port); + wmb(); + + while(status_block[87]!=0xff){ + if(time_after(jiffies,timeout)){ + printk(KERN_ERR"dpti%d: Get status timeout.\n", + pHba->unit); + return -ETIMEDOUT; + } + rmb(); + } + + // Set up our number of outbound and inbound messages + pHba->post_fifo_size = pHba->status_block->max_inbound_frames; + if (pHba->post_fifo_size > MAX_TO_IOP_MESSAGES) { + pHba->post_fifo_size = MAX_TO_IOP_MESSAGES; + } + + pHba->reply_fifo_size = pHba->status_block->max_outbound_frames; + if (pHba->reply_fifo_size > MAX_FROM_IOP_MESSAGES) { + pHba->reply_fifo_size = MAX_FROM_IOP_MESSAGES; + } + + // Calculate the Scatter Gather list size + pHba->sg_tablesize = (pHba->status_block->inbound_frame_size * 4 -40)/ sizeof(struct sg_simple_element); + if (pHba->sg_tablesize > SG_LIST_ELEMENTS) { + pHba->sg_tablesize = SG_LIST_ELEMENTS; + } + + +#ifdef DEBUG + printk("dpti%d: State = ",pHba->unit); + switch(pHba->status_block->iop_state) { + case 0x01: + printk("INIT\n"); + break; + case 0x02: + printk("RESET\n"); + break; + case 0x04: + printk("HOLD\n"); + break; + case 0x05: + printk("READY\n"); + break; + case 0x08: + printk("OPERATIONAL\n"); + break; + case 0x10: + printk("FAILED\n"); + break; + case 0x11: + printk("FAULTED\n"); + break; + default: + printk("%x (unknown!!)\n",pHba->status_block->iop_state); + } +#endif + return 0; +} + +/* + * Get the IOP's Logical Configuration Table + */ +static int adpt_i2o_lct_get(adpt_hba* pHba) +{ + u32 msg[8]; + int ret; + u32 buf[16]; + + if ((pHba->lct_size == 0) || (pHba->lct == NULL)){ + pHba->lct_size = pHba->status_block->expected_lct_size; + } + do { + if (pHba->lct == NULL) { + pHba->lct = kmalloc(pHba->lct_size, GFP_KERNEL|ADDR32); + if(pHba->lct == NULL) { + printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n", + pHba->name); + return -ENOMEM; + } + } + memset(pHba->lct, 0, pHba->lct_size); + + msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6; + msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID; + msg[2] = 0; + msg[3] = 0; + msg[4] = 0xFFFFFFFF; /* All devices */ + msg[5] = 0x00000000; /* Report now */ + msg[6] = 0xD0000000|pHba->lct_size; + msg[7] = virt_to_bus(pHba->lct); + + if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) { + printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", + pHba->name, ret); + printk(KERN_ERR"Adaptec: Error Reading Hardware.\n"); + return ret; + } + + if ((pHba->lct->table_size << 2) > pHba->lct_size) { + pHba->lct_size = pHba->lct->table_size << 2; + kfree(pHba->lct); + pHba->lct = NULL; + } + } while (pHba->lct == NULL); + + PDEBUG("%s: Hardware resource table read.\n", pHba->name); + + + // I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO; + if(adpt_i2o_query_scalar(pHba, 0 , 0x8000, -1, buf, sizeof(buf))>=0) { + pHba->FwDebugBufferSize = buf[1]; + pHba->FwDebugBuffer_P = pHba->base_addr_virt + buf[0]; + pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P + FW_DEBUG_FLAGS_OFFSET; + pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P + FW_DEBUG_BLED_OFFSET; + pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1; + pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P + FW_DEBUG_STR_LENGTH_OFFSET; + pHba->FwDebugBuffer_P += buf[2]; + pHba->FwDebugFlags = 0; + } + + return 0; +} + +static int adpt_i2o_build_sys_table(void) +{ + adpt_hba* pHba = NULL; + int count = 0; + + sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs + (hba_count) * sizeof(struct i2o_sys_tbl_entry); + + if(sys_tbl) + kfree(sys_tbl); + + sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL|ADDR32); + if(!sys_tbl) { + printk(KERN_WARNING "SysTab Set failed. Out of memory.\n"); + return -ENOMEM; + } + memset(sys_tbl, 0, sys_tbl_len); + + sys_tbl->num_entries = hba_count; + sys_tbl->version = I2OVERSION; + sys_tbl->change_ind = sys_tbl_ind++; + + for(pHba = hba_chain; pHba; pHba = pHba->next) { + // Get updated Status Block so we have the latest information + if (adpt_i2o_status_get(pHba)) { + sys_tbl->num_entries--; + continue; // try next one + } + + sys_tbl->iops[count].org_id = pHba->status_block->org_id; + sys_tbl->iops[count].iop_id = pHba->unit + 2; + sys_tbl->iops[count].seg_num = 0; + sys_tbl->iops[count].i2o_version = pHba->status_block->i2o_version; + sys_tbl->iops[count].iop_state = pHba->status_block->iop_state; + sys_tbl->iops[count].msg_type = pHba->status_block->msg_type; + sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size; + sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ?? + sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities; + sys_tbl->iops[count].inbound_low = (u32)virt_to_bus((void*)pHba->post_port); + sys_tbl->iops[count].inbound_high = (u32)((u64)virt_to_bus((void*)pHba->post_port)>>32); + + count++; + } + +#ifdef DEBUG +{ + u32 *table = (u32*)sys_tbl; + printk(KERN_DEBUG"sys_tbl_len=%d in 32bit words\n",(sys_tbl_len >>2)); + for(count = 0; count < (sys_tbl_len >>2); count++) { + printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", + count, table[count]); + } +} +#endif + + return 0; +} + + +/* + * Dump the information block associated with a given unit (TID) + */ + +static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d) +{ + char buf[64]; + int unit = d->lct_data.tid; + + printk(KERN_INFO "TID %3.3d ", unit); + + if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 3, buf, 16)>=0) + { + buf[16]=0; + printk(" Vendor: %-12.12s", buf); + } + if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 4, buf, 16)>=0) + { + buf[16]=0; + printk(" Device: %-12.12s", buf); + } + if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 6, buf, 8)>=0) + { + buf[8]=0; + printk(" Rev: %-12.12s\n", buf); + } +#ifdef DEBUG + printk(KERN_INFO "\tClass: %.21s\n", adpt_i2o_get_class_name(d->lct_data.class_id)); + printk(KERN_INFO "\tSubclass: 0x%04X\n", d->lct_data.sub_class); + printk(KERN_INFO "\tFlags: "); + + if(d->lct_data.device_flags&(1<<0)) + printk("C"); // ConfigDialog requested + if(d->lct_data.device_flags&(1<<1)) + printk("U"); // Multi-user capable + if(!(d->lct_data.device_flags&(1<<4))) + printk("P"); // Peer service enabled! + if(!(d->lct_data.device_flags&(1<<5))) + printk("M"); // Mgmt service enabled! + printk("\n"); +#endif +} + +#ifdef DEBUG +/* + * Do i2o class name lookup + */ +static const char *adpt_i2o_get_class_name(int class) +{ + int idx = 16; + static char *i2o_class_name[] = { + "Executive", + "Device Driver Module", + "Block Device", + "Tape Device", + "LAN Interface", + "WAN Interface", + "Fibre Channel Port", + "Fibre Channel Device", + "SCSI Device", + "ATE Port", + "ATE Device", + "Floppy Controller", + "Floppy Device", + "Secondary Bus Port", + "Peer Transport Agent", + "Peer Transport", + "Unknown" + }; + + switch(class&0xFFF) { + case I2O_CLASS_EXECUTIVE: + idx = 0; break; + case I2O_CLASS_DDM: + idx = 1; break; + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + idx = 2; break; + case I2O_CLASS_SEQUENTIAL_STORAGE: + idx = 3; break; + case I2O_CLASS_LAN: + idx = 4; break; + case I2O_CLASS_WAN: + idx = 5; break; + case I2O_CLASS_FIBRE_CHANNEL_PORT: + idx = 6; break; + case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: + idx = 7; break; + case I2O_CLASS_SCSI_PERIPHERAL: + idx = 8; break; + case I2O_CLASS_ATE_PORT: + idx = 9; break; + case I2O_CLASS_ATE_PERIPHERAL: + idx = 10; break; + case I2O_CLASS_FLOPPY_CONTROLLER: + idx = 11; break; + case I2O_CLASS_FLOPPY_DEVICE: + idx = 12; break; + case I2O_CLASS_BUS_ADAPTER_PORT: + idx = 13; break; + case I2O_CLASS_PEER_TRANSPORT_AGENT: + idx = 14; break; + case I2O_CLASS_PEER_TRANSPORT: + idx = 15; break; + } + return i2o_class_name[idx]; +} +#endif + + +static s32 adpt_i2o_hrt_get(adpt_hba* pHba) +{ + u32 msg[6]; + int ret, size = sizeof(i2o_hrt); + + do { + if (pHba->hrt == NULL) { + pHba->hrt=kmalloc(size, GFP_KERNEL|ADDR32); + if (pHba->hrt == NULL) { + printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name); + return -ENOMEM; + } + } + + msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4; + msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID; + msg[2]= 0; + msg[3]= 0; + msg[4]= (0xD0000000 | size); /* Simple transaction */ + msg[5]= virt_to_bus(pHba->hrt); /* Dump it here */ + + if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) { + printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret); + return ret; + } + + if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) { + size = pHba->hrt->num_entries * pHba->hrt->entry_len << 2; + kfree(pHba->hrt); + pHba->hrt = NULL; + } + } while(pHba->hrt == NULL); + return 0; +} + +/* + * Query one scalar group value or a whole scalar group. + */ +static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, + int group, int field, void *buf, int buflen) +{ + u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; + u8 resblk[8+buflen]; /* 8 bytes for header */ + int size; + + if (field == -1) /* whole group */ + opblk[4] = -1; + + size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid, + opblk, sizeof(opblk), resblk, sizeof(resblk)); + + memcpy(buf, resblk+8, buflen); /* cut off header */ + + if (size < 0) + return size; + + return buflen; +} + + +/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET + * + * This function can be used for all UtilParamsGet/Set operations. + * The OperationBlock is given in opblk-buffer, + * and results are returned in resblk-buffer. + * Note that the minimum sized resblk is 8 bytes and contains + * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. + */ +static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, + void *opblk, int oplen, void *resblk, int reslen) +{ + u32 msg[9]; + u32 *res = (u32 *)resblk; + int wait_status; + + msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5; + msg[1] = cmd << 24 | HOST_TID << 12 | tid; + msg[2] = 0; + msg[3] = 0; + msg[4] = 0; + msg[5] = 0x54000000 | oplen; /* OperationBlock */ + msg[6] = virt_to_bus(opblk); + msg[7] = 0xD0000000 | reslen; /* ResultBlock */ + msg[8] = virt_to_bus(resblk); + + if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) { + return wait_status; /* -DetailedStatus */ + } + + if (res[1]&0x00FF0000) { /* BlockStatus != SUCCESS */ + printk(KERN_WARNING "%s: %s - Error:\n ErrorInfoSize = 0x%02x, " + "BlockStatus = 0x%02x, BlockSize = 0x%04x\n", + pHba->name, + (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" + : "PARAMS_GET", + res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF); + return -((res[1] >> 16) & 0xFF); /* -BlockStatus */ + } + + return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */ +} + + +static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba) +{ + u32 msg[4]; + int ret; + + adpt_i2o_status_get(pHba); + + /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */ + + if((pHba->status_block->iop_state != ADAPTER_STATE_READY) && + (pHba->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)){ + return 0; + } + + msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; + msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID; + msg[2] = 0; + msg[3] = 0; + + if((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) { + printk(KERN_INFO"dpti%d: Unable to quiesce (status=%#x).\n", + pHba->unit, -ret); + } else { + printk(KERN_INFO"dpti%d: Quiesced.\n",pHba->unit); + } + + adpt_i2o_status_get(pHba); + return ret; +} + + +/* + * Enable IOP. Allows the IOP to resume external operations. + */ +static int adpt_i2o_enable_hba(adpt_hba* pHba) +{ + u32 msg[4]; + int ret; + + adpt_i2o_status_get(pHba); + if(!pHba->status_block){ + return -ENOMEM; + } + /* Enable only allowed on READY state */ + if(pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL) + return 0; + + if(pHba->status_block->iop_state != ADAPTER_STATE_READY) + return -EINVAL; + + msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; + msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID; + msg[2]= 0; + msg[3]= 0; + + if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) { + printk(KERN_WARNING"%s: Could not enable (status=%#10x).\n", + pHba->name, ret); + } else { + PDEBUG("%s: Enabled.\n", pHba->name); + } + + adpt_i2o_status_get(pHba); + return ret; +} + + +static int adpt_i2o_systab_send(adpt_hba* pHba) +{ + u32 msg[12]; + int ret; + + msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6; + msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID; + msg[2] = 0; + msg[3] = 0; + msg[4] = (0<<16) | ((pHba->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */ + msg[5] = 0; /* Segment 0 */ + + /* + * Provide three SGL-elements: + * System table (SysTab), Private memory space declaration and + * Private i/o space declaration + */ + msg[6] = 0x54000000 | sys_tbl_len; + msg[7] = virt_to_phys(sys_tbl); + msg[8] = 0x54000000 | 0; + msg[9] = 0; + msg[10] = 0xD4000000 | 0; + msg[11] = 0; + + if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 120))) { + printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n", + pHba->name, ret); + } +#ifdef DEBUG + else { + PINFO("%s: SysTab set.\n", pHba->name); + } +#endif + + return ret; + } + + +/*============================================================================ + * + *============================================================================ + */ + + +#ifdef UARTDELAY + +static static void adpt_delay(int millisec) +{ + int i; + for (i = 0; i < millisec; i++) { + udelay(1000); /* delay for one millisecond */ + } +} + +#endif + +static Scsi_Host_Template driver_template = DPT_I2O; +#include "scsi_module.c" +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dpti.h linux/drivers/scsi/dpti.h --- v2.4.9/linux/drivers/scsi/dpti.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dpti.h Fri Sep 7 09:28:38 2001 @@ -0,0 +1,403 @@ +/*************************************************************************** + dpti.h - description + ------------------- + begin : Thu Sep 7 2000 + copyright : (C) 2001 by Adaptec + email : deanna_bonds@adaptec.com + + See README.dpti for history, notes, license info, and credits + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _DPT_H +#define _DPT_H + +#ifndef LINUX_VERSION_CODE +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,00) +#define MAX_TO_IOP_MESSAGES (210) +#else +#define MAX_TO_IOP_MESSAGES (255) +#endif +#define MAX_FROM_IOP_MESSAGES (255) + + +/* + * SCSI interface function Prototypes + */ + +static int adpt_proc_info(char *buffer, char **start, off_t offset, + int length, int inode, int inout); +static int adpt_detect(Scsi_Host_Template * sht); +static int adpt_queue(Scsi_Cmnd * cmd, void (*cmdcomplete) (Scsi_Cmnd *)); +static int adpt_abort(Scsi_Cmnd * cmd); +static int adpt_reset(Scsi_Cmnd* cmd); +static int adpt_release(struct Scsi_Host *host); + +static const char *adpt_info(struct Scsi_Host *pSHost); +static int adpt_bios_param(Disk * disk, kdev_t dev, int geom[]); + +static int adpt_bus_reset(Scsi_Cmnd* cmd); +static int adpt_device_reset(Scsi_Cmnd* cmd); + + +/* + * Scsi_Host_Template (see hosts.h) + */ + +#define DPT_DRIVER_NAME "Adaptec I2O RAID" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,00) +#define DPT_I2O { \ + proc_info: adpt_proc_info, \ + detect: adpt_detect, \ + release: adpt_release, \ + info: adpt_info, \ + queuecommand: adpt_queue, \ + eh_abort_handler: adpt_abort, \ + eh_device_reset_handler: adpt_device_reset, \ + eh_bus_reset_handler: adpt_bus_reset, \ + eh_host_reset_handler: adpt_reset, \ + bios_param: adpt_bios_param, \ + can_queue: MAX_TO_IOP_MESSAGES ,/* max simultaneous cmds */\ + this_id: 7, /* scsi id of host adapter */\ + sg_tablesize: 0, /* max scatter-gather cmds */\ + cmd_per_lun: 256, /* cmds per lun (linked cmds) */\ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 1 \ +} + +#else /* KERNEL_VERSION > 2.2.16 */ + +#define DPT_I2O { \ + proc_info: adpt_proc_info, \ + detect: adpt_detect, \ + release: adpt_release, \ + info: adpt_info, \ + queuecommand: adpt_queue, \ + eh_abort_handler: adpt_abort, \ + eh_device_reset_handler: adpt_device_reset, \ + eh_bus_reset_handler: adpt_bus_reset, \ + eh_host_reset_handler: adpt_reset, \ + bios_param: adpt_bios_param, \ + can_queue: MAX_TO_IOP_MESSAGES, /* max simultaneous cmds */\ + this_id: 7, /* scsi id of host adapter */\ + sg_tablesize: 0, /* max scatter-gather cmds */\ + cmd_per_lun: 256, /* cmds per lun (linked cmds) */\ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 1, \ + proc_name: "dpt_i2o" /* this is the name of our proc node*/ \ +} +#endif + +#ifndef HOSTS_C + +#include "dpt/sys_info.h" +#include +#include "dpt/dpti_i2o.h" +#include "dpt/dpti_ioctl.h" + +#define DPT_I2O_VERSION "2.4 Build 5" +#define DPT_VERSION 2 +#define DPT_REVISION '4' +#define DPT_SUBREVISION '5' +#define DPT_BETA "" +#define DPT_MONTH 8 +#define DPT_DAY 7 +#define DPT_YEAR (2001-1980) + +#define DPT_DRIVER "dpt_i2o" +#define DPTI_I2O_MAJOR (151) +#define DPT_ORGANIZATION_ID (0x1B) /* For Private Messages */ +#define DPTI_MAX_HBA (16) +#define MAX_CHANNEL (5) // Maximum Channel # Supported +#define MAX_ID (128) // Maximum Target ID Supported + +/* Sizes in 4 byte words */ +#define REPLY_FRAME_SIZE (17) +#define MAX_MESSAGE_SIZE (128) +#define SG_LIST_ELEMENTS (56) + +#define EMPTY_QUEUE 0xffffffff +#define I2O_INTERRUPT_PENDING_B (0x08) + +#define PCI_DPT_VENDOR_ID (0x1044) // DPT PCI Vendor ID +#define PCI_DPT_DEVICE_ID (0xA501) // DPT PCI I2O Device ID +#define PCI_DPT_RAPTOR_DEVICE_ID (0xA511) + +//#define REBOOT_NOTIFIER 1 +/* Debugging macro from Linux Device Drivers - Rubini */ +#undef PDEBUG +#ifdef DEBUG +//TODO add debug level switch +# define PDEBUG(fmt, args...) printk(KERN_DEBUG "dpti: " fmt, ##args) +# define PDEBUGV(fmt, args...) printk(KERN_DEBUG "dpti: " fmt, ##args) +#else +# define PDEBUG(fmt, args...) /* not debugging: nothing */ +# define PDEBUGV(fmt, args...) /* not debugging: nothing */ +#endif + +#define PERROR(fmt, args...) printk(KERN_ERR fmt, ##args) +#define PWARN(fmt, args...) printk(KERN_WARNING fmt, ##args) +#define PINFO(fmt, args...) printk(KERN_INFO fmt, ##args) +#define PCRIT(fmt, args...) printk(KERN_CRIT fmt, ##args) + +#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) + +// Command timeouts +#define FOREVER (0) +#define TMOUT_INQUIRY (20) +#define TMOUT_FLUSH (360/45) +#define TMOUT_ABORT (30) +#define TMOUT_SCSI (300) +#define TMOUT_IOPRESET (360) +#define TMOUT_GETSTATUS (15) +#define TMOUT_INITOUTBOUND (15) +#define TMOUT_LCT (360) + + +#define I2O_SCSI_DEVICE_DSC_MASK 0x00FF + +#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x000A + +#define I2O_SCSI_DSC_MASK 0xFF00 +#define I2O_SCSI_DSC_SUCCESS 0x0000 +#define I2O_SCSI_DSC_REQUEST_ABORTED 0x0200 +#define I2O_SCSI_DSC_UNABLE_TO_ABORT 0x0300 +#define I2O_SCSI_DSC_COMPLETE_WITH_ERROR 0x0400 +#define I2O_SCSI_DSC_ADAPTER_BUSY 0x0500 +#define I2O_SCSI_DSC_REQUEST_INVALID 0x0600 +#define I2O_SCSI_DSC_PATH_INVALID 0x0700 +#define I2O_SCSI_DSC_DEVICE_NOT_PRESENT 0x0800 +#define I2O_SCSI_DSC_UNABLE_TO_TERMINATE 0x0900 +#define I2O_SCSI_DSC_SELECTION_TIMEOUT 0x0A00 +#define I2O_SCSI_DSC_COMMAND_TIMEOUT 0x0B00 +#define I2O_SCSI_DSC_MR_MESSAGE_RECEIVED 0x0D00 +#define I2O_SCSI_DSC_SCSI_BUS_RESET 0x0E00 +#define I2O_SCSI_DSC_PARITY_ERROR_FAILURE 0x0F00 +#define I2O_SCSI_DSC_AUTOSENSE_FAILED 0x1000 +#define I2O_SCSI_DSC_NO_ADAPTER 0x1100 +#define I2O_SCSI_DSC_DATA_OVERRUN 0x1200 +#define I2O_SCSI_DSC_UNEXPECTED_BUS_FREE 0x1300 +#define I2O_SCSI_DSC_SEQUENCE_FAILURE 0x1400 +#define I2O_SCSI_DSC_REQUEST_LENGTH_ERROR 0x1500 +#define I2O_SCSI_DSC_PROVIDE_FAILURE 0x1600 +#define I2O_SCSI_DSC_BDR_MESSAGE_SENT 0x1700 +#define I2O_SCSI_DSC_REQUEST_TERMINATED 0x1800 +#define I2O_SCSI_DSC_IDE_MESSAGE_SENT 0x3300 +#define I2O_SCSI_DSC_RESOURCE_UNAVAILABLE 0x3400 +#define I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT 0x3500 +#define I2O_SCSI_DSC_MESSAGE_RECEIVED 0x3600 +#define I2O_SCSI_DSC_INVALID_CDB 0x3700 +#define I2O_SCSI_DSC_LUN_INVALID 0x3800 +#define I2O_SCSI_DSC_SCSI_TID_INVALID 0x3900 +#define I2O_SCSI_DSC_FUNCTION_UNAVAILABLE 0x3A00 +#define I2O_SCSI_DSC_NO_NEXUS 0x3B00 +#define I2O_SCSI_DSC_SCSI_IID_INVALID 0x3C00 +#define I2O_SCSI_DSC_CDB_RECEIVED 0x3D00 +#define I2O_SCSI_DSC_LUN_ALREADY_ENABLED 0x3E00 +#define I2O_SCSI_DSC_BUS_BUSY 0x3F00 +#define I2O_SCSI_DSC_QUEUE_FROZEN 0x4000 + + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#define HBA_FLAGS_INSTALLED_B 0x00000001 // Adapter Was Installed +#define HBA_FLAGS_BLINKLED_B 0x00000002 // Adapter In Blink LED State +#define HBA_FLAGS_IN_RESET 0x00000040 /* in reset */ +#define HBA_HOSTRESET_FAILED 0x00000080 /* adpt_resethost failed */ + + +// Device state flags +#define DPTI_DEV_ONLINE 0x00 +#define DPTI_DEV_UNSCANNED 0x01 +#define DPTI_DEV_RESET 0x02 +#define DPTI_DEV_OFFLINE 0x04 + + +struct adpt_device { + struct adpt_device* next_lun; + u32 flags; + u32 type; + u32 capacity; + u32 block_size; + u8 scsi_channel; + u8 scsi_id; + u8 scsi_lun; + u8 state; + u16 tid; + struct i2o_device* pI2o_dev; + Scsi_Device *pScsi_dev; +}; + +struct adpt_channel { + struct adpt_device* device[MAX_ID]; /* used as an array of 128 scsi ids */ + u8 scsi_id; + u8 type; + u16 tid; + u32 state; + struct i2o_device* pI2o_dev; +}; + +// HBA state flags +#define DPTI_STATE_RESET (0x01) +#define DPTI_STATE_IOCTL (0x02) + +typedef struct _adpt_hba { + struct _adpt_hba *next; + struct pci_dev *pDev; + struct Scsi_Host *host; + u32 state; + spinlock_t state_lock; + int unit; + int host_no; /* SCSI host number */ + u8 initialized; + u8 in_use; /* is the management node open*/ + + char name[32]; + char detail[55]; + + ulong base_addr_virt; + ulong msg_addr_virt; + ulong base_addr_phys; + ulong post_port; + ulong reply_port; + ulong irq_mask; + u16 post_count; + u32 post_fifo_size; + u32 reply_fifo_size; + u32* reply_pool; + u32 sg_tablesize; // Scatter/Gather List Size. + u8 top_scsi_channel; + u8 top_scsi_id; + u8 top_scsi_lun; + + i2o_status_block* status_block; + i2o_hrt* hrt; + i2o_lct* lct; + uint lct_size; + struct i2o_device* devices; + struct adpt_channel channel[MAX_CHANNEL]; + struct proc_dir_entry* proc_entry; /* /proc dir */ + + ulong FwDebugBuffer_P; // Virtual Address Of FW Debug Buffer + u32 FwDebugBufferSize; // FW Debug Buffer Size In Bytes + ulong FwDebugStrLength_P; // Virtual Addr Of FW Debug String Len + ulong FwDebugFlags_P; // Virtual Address Of FW Debug Flags + ulong FwDebugBLEDflag_P; // Virtual Addr Of FW Debug BLED + ulong FwDebugBLEDvalue_P; // Virtual Addr Of FW Debug BLED + u32 FwDebugFlags; +} adpt_hba; + +struct sg_simple_element { + u32 flag_count; + u32 addr_bus; +}; + +/* + * Function Prototypes + */ + +static void adpt_i2o_sys_shutdown(void); +static int adpt_init(void); +static int adpt_i2o_build_sys_table(void); +static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs); +#ifdef REBOOT_NOTIFIER +static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p); +#endif + +static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d); +static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, + int group, int field, void *buf, int buflen); +#ifdef DEBUG +static const char *adpt_i2o_get_class_name(int class); +#endif +static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, + void *opblk, int oplen, void *resblk, int reslen); +static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout); +static int adpt_i2o_lct_get(adpt_hba* pHba); +static int adpt_i2o_parse_lct(adpt_hba* pHba); +static int adpt_i2o_activate_hba(adpt_hba* pHba); +static int adpt_i2o_enable_hba(adpt_hba* pHba); +static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d); +static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len); +static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba); +static s32 adpt_i2o_status_get(adpt_hba* pHba); +static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba); +static s32 adpt_i2o_hrt_get(adpt_hba* pHba); +static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* dptdevice); +static s32 adpt_i2o_to_scsi(ulong reply, Scsi_Cmnd* cmd); +static s32 adpt_scsi_register(adpt_hba* pHba,Scsi_Host_Template * sht); +static s32 adpt_hba_reset(adpt_hba* pHba); +static s32 adpt_i2o_reset_hba(adpt_hba* pHba); +static s32 adpt_rescan(adpt_hba* pHba); +static s32 adpt_i2o_reparse_lct(adpt_hba* pHba); +static s32 adpt_send_nop(adpt_hba*pHba,u32 m); +static void adpt_i2o_delete_hba(adpt_hba* pHba); +static void adpt_select_queue_depths(struct Scsi_Host *host, Scsi_Device * devicelist); +static void adpt_inquiry(adpt_hba* pHba); +static void adpt_fail_posted_scbs(adpt_hba* pHba); +static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun); +static int adpt_install_hba(Scsi_Host_Template* sht, struct pci_dev* pDev) ; +static int adpt_i2o_online_hba(adpt_hba* pHba); +static void adpt_i2o_post_wait_complete(u32, int); +static int adpt_i2o_systab_send(adpt_hba* pHba); + +static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg); +static int adpt_open(struct inode *inode, struct file *file); +static int adpt_close(struct inode *inode, struct file *file); + + +#ifdef UARTDELAY +static void adpt_delay(int millisec); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +static struct pci_dev* adpt_pci_find_device(uint vendor, struct pci_dev* from); +#endif + +#if defined __ia64__ +static void adpt_ia64_info(sysInfo_S* si); +#endif +#if defined __sparc__ +static void adpt_sparc_info(sysInfo_S* si); +#endif +#if defined __alpha__ +static void adpt_sparc_info(sysInfo_S* si); +#endif +#if defined __i386__ +static void adpt_i386_info(sysInfo_S* si); +#endif + +#define PRINT_BUFFER_SIZE 512 + +#define HBA_FLAGS_DBG_FLAGS_MASK 0xffff0000 // Mask for debug flags +#define HBA_FLAGS_DBG_KERNEL_PRINT_B 0x00010000 // Kernel Debugger Print +#define HBA_FLAGS_DBG_FW_PRINT_B 0x00020000 // Firmware Debugger Print +#define HBA_FLAGS_DBG_FUNCTION_ENTRY_B 0x00040000 // Function Entry Point +#define HBA_FLAGS_DBG_FUNCTION_EXIT_B 0x00080000 // Function Exit +#define HBA_FLAGS_DBG_ERROR_B 0x00100000 // Error Conditions +#define HBA_FLAGS_DBG_INIT_B 0x00200000 // Init Prints +#define HBA_FLAGS_DBG_OS_COMMANDS_B 0x00400000 // OS Command Info +#define HBA_FLAGS_DBG_SCAN_B 0x00800000 // Device Scan + +#define FW_DEBUG_STR_LENGTH_OFFSET 0 +#define FW_DEBUG_FLAGS_OFFSET 4 +#define FW_DEBUG_BLED_OFFSET 8 + +#define FW_DEBUG_FLAGS_NO_HEADERS_B 0x01 +#endif /* !HOSTS_C */ +#endif /* _DPT_H */ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c --- v2.4.9/linux/drivers/scsi/gdth.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/scsi/gdth.c Fri Sep 7 09:28:37 2001 @@ -1,8 +1,10 @@ /************************************************************************ - * GDT ISA/EISA/PCI Disk Array Controller driver for Linux * + * Linux driver for * + * ICP vortex GmbH: GDT ISA/EISA/PCI Disk Array Controllers * + * Intel Corporation: Storage RAID Controllers * * * * gdth.c * - * Copyright (C) 1995-01 ICP vortex Computersysteme GmbH, Achim Leubner * + * Copyright (C) 1995-01 ICP vortex, an Intel company, Achim Leubner * * * * * * * @@ -20,9 +22,36 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Tested with Linux 1.2.13, ..., 2.2.18, ..., 2.4.2 * + * Tested with Linux 1.2.13, ..., 2.2.19, ..., 2.4.7 * * * * $Log: gdth.c,v $ + * Revision 1.57 2001/08/21 11:16:35 achim + * Bugfix free_irq() + * + * Revision 1.56 2001/08/09 11:19:39 achim + * Scsi_Host_Template changes + * + * Revision 1.55 2001/08/09 10:11:28 achim + * Command HOST_UNFREEZE_IO before cache service init. + * + * Revision 1.54 2001/07/20 13:48:12 achim + * Expand: gdth_analyse_hdrive() removed + * + * Revision 1.53 2001/07/17 09:52:49 achim + * Small OEM related change + * + * Revision 1.52 2001/06/19 15:06:20 achim + * New host command GDT_UNFREEZE_IO added + * + * Revision 1.51 2001/05/22 06:42:37 achim + * PCI: Subdevice ID added + * + * Revision 1.50 2001/05/17 13:42:16 achim + * Support for Intel Storage RAID Controllers added + * + * Revision 1.50 2001/05/17 12:12:34 achim + * Support for Intel Storage RAID Controllers added + * * Revision 1.49 2001/03/15 15:07:17 achim * New __setup interface for boot command line options added * @@ -203,7 +232,7 @@ * Initial revision * ************************************************************************/ -#ident "$Id: gdth.c,v 1.49 2001/03/15 15:07:17 achim Exp $" +#ident "$Id: gdth.c,v 1.57 2001/08/21 11:16:35 achim Exp $" /* All GDT Disk Array Controllers are fully supported by this driver. * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the @@ -291,9 +320,6 @@ #else #include #endif -#if LINUX_VERSION_CODE >= 0x020126 -#include -#endif #include #include @@ -344,6 +370,8 @@ static int gdth_search_eisa(ushort eisa_adr); static int gdth_search_isa(ulong32 bios_adr); static int gdth_search_pci(gdth_pci_str *pcistr); +static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, + ushort vendor, ushort dev); static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt); static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha); static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha); @@ -588,8 +616,10 @@ /* __initfunc, __initdata macros */ #if LINUX_VERSION_CODE >= 0x020322 #define GDTH_INITFUNC(type, func) type __init func +#include #elif LINUX_VERSION_CODE >= 0x020126 #define GDTH_INITFUNC(type, func) __initfunc(type func) +#include #else #define GDTH_INITFUNC(type, func) type func #define __initdata @@ -753,8 +783,28 @@ GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr)) { + ushort device, cnt; + + TRACE(("gdth_search_pci()\n")); + + cnt = 0; + for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device) + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device); + for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP; + device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device) + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device); + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, + PCI_DEVICE_ID_VORTEX_GDTNEWRX); + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_SRC); + return cnt; +} + + +GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, + ushort vendor, ushort device)) +{ ulong base0, base1, base2; - ushort device_id, cnt; #if LINUX_VERSION_CODE >= 0x2015C struct pci_dev *pdev; #else @@ -762,147 +812,150 @@ ushort idx; #endif - TRACE(("gdth_search_pci()\n")); + TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n", + *cnt, vendor, device)); - cnt = 0; - for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; - ++device_id) { - if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 && - device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP) - continue; #if LINUX_VERSION_CODE >= 0x20363 - pdev = NULL; - while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) - != NULL) { - if (pci_enable_device(pdev)) + pdev = NULL; + while ((pdev = pci_find_device(vendor, device, pdev)) + != NULL) { + if (pci_enable_device(pdev)) + continue; + if (*cnt >= MAXHA) + return; + /* GDT PCI controller found, resources are already in pdev */ + pcistr[*cnt].pdev = pdev; + pcistr[*cnt].vendor_id = vendor; + pcistr[*cnt].device_id = device; + pcistr[*cnt].subdevice_id = pdev->subsystem_device; + pcistr[*cnt].bus = pdev->bus->number; + pcistr[*cnt].device_fn = pdev->devfn; + pcistr[*cnt].irq = pdev->irq; + base0 = pci_resource_flags(pdev, 0); + base1 = pci_resource_flags(pdev, 1); + base2 = pci_resource_flags(pdev, 2); + if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ + device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ + if (!(base0 & IORESOURCE_MEM)) continue; - if (cnt >= MAXHA) - return cnt; - /* GDT PCI controller found, resources are already in pdev */ - pcistr[cnt].pdev = pdev; - pcistr[cnt].device_id = device_id; - pcistr[cnt].bus = pdev->bus->number; - pcistr[cnt].device_fn = pdev->devfn; - pcistr[cnt].irq = pdev->irq; - base0 = pci_resource_flags(pdev, 0); - base1 = pci_resource_flags(pdev, 1); - base2 = pci_resource_flags(pdev, 2); - if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ - device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if (!(base0 & IORESOURCE_MEM)) - continue; - pcistr[cnt].dpmem = pci_resource_start(pdev, 0); - } else { /* GDT6110, GDT6120, .. */ - if (!(base0 & IORESOURCE_MEM) || - !(base2 & IORESOURCE_MEM) || - !(base1 & IORESOURCE_IO)) - continue; - pcistr[cnt].dpmem = pci_resource_start(pdev, 2); - pcistr[cnt].io_mm = pci_resource_start(pdev, 0); - pcistr[cnt].io = pci_resource_start(pdev, 1); - } - TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), - pcistr[cnt].irq, pcistr[cnt].dpmem)); - cnt++; - } + pcistr[*cnt].dpmem = pci_resource_start(pdev, 0); + } else { /* GDT6110, GDT6120, .. */ + if (!(base0 & IORESOURCE_MEM) || + !(base2 & IORESOURCE_MEM) || + !(base1 & IORESOURCE_IO)) + continue; + pcistr[*cnt].dpmem = pci_resource_start(pdev, 2); + pcistr[*cnt].io_mm = pci_resource_start(pdev, 0); + pcistr[*cnt].io = pci_resource_start(pdev, 1); + } + TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", + pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), + pcistr[*cnt].irq, pcistr[*cnt].dpmem)); + (*cnt)++; + } #elif LINUX_VERSION_CODE >= 0x2015C - pdev = NULL; - while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) - != NULL) { - if (cnt >= MAXHA) - return cnt; - /* GDT PCI controller found, resources are already in pdev */ - pcistr[cnt].pdev = pdev; - pcistr[cnt].device_id = device_id; - pcistr[cnt].bus = pdev->bus->number; - pcistr[cnt].device_fn = pdev->devfn; - pcistr[cnt].irq = pdev->irq; - base0 = pdev->base_address[0]; - base1 = pdev->base_address[1]; - base2 = pdev->base_address[2]; - if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ - device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY) - continue; - pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; - } else { /* GDT6110, GDT6120, .. */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base2 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base1 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_IO) - continue; - pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; - } - TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), - pcistr[cnt].irq, pcistr[cnt].dpmem)); - cnt++; - } + pdev = NULL; + while ((pdev = pci_find_device(vendor, device, pdev)) + != NULL) { + if (*cnt >= MAXHA) + return; + /* GDT PCI controller found, resources are already in pdev */ + pcistr[*cnt].pdev = pdev; + pcistr[*cnt].vendor_id = vendor; + pcistr[*cnt].device_id = device; + pcistr[*cnt].bus = pdev->bus->number; + pcistr[*cnt].device_fn = pdev->devfn; + pcibios_read_config_word(pcistr[*cnt].bus, pcistr[*cnt].device_fn, + PCI_SUBSYSTEM_ID, &pcistr[*cnt].subdevice_id); + pcistr[*cnt].irq = pdev->irq; + base0 = pdev->base_address[0]; + base1 = pdev->base_address[1]; + base2 = pdev->base_address[2]; + if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ + device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ + if ((base0 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY) + continue; + pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; + } else { /* GDT6110, GDT6120, .. */ + if ((base0 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (base2 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (base1 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_IO) + continue; + pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; + } + TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", + pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), + pcistr[*cnt].irq, pcistr[*cnt].dpmem)); + (*cnt)++; + } #else - idx = 0; - while (!pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,idx++, - &pcistr[cnt].bus,&pcistr[cnt].device_fn)) { - if (cnt >= MAXHA) - return cnt; - /* GDT PCI ctr. found, now read resources from config space */ + idx = 0; + while (!pcibios_find_device(vendor, device, idx++, + &pcistr[*cnt].bus,&pcistr[*cnt].device_fn)) { + if (*cnt >= MAXHA) + return; + /* GDT PCI ctr. found, now read resources from config space */ #if LINUX_VERSION_CODE >= 0x010300 #define GDTH_BASEP (int *) #else #define GDTH_BASEP #endif - if ((error = pcibios_read_config_dword(pcistr[cnt].bus, - pcistr[cnt].device_fn, - PCI_BASE_ADDRESS_0, - GDTH_BASEP&base0)) || - (error = pcibios_read_config_dword(pcistr[cnt].bus, - pcistr[cnt].device_fn, - PCI_BASE_ADDRESS_1, - GDTH_BASEP&base1)) || - (error = pcibios_read_config_dword(pcistr[cnt].bus, - pcistr[cnt].device_fn, - PCI_BASE_ADDRESS_2, - GDTH_BASEP&base2)) || - (error = pcibios_read_config_byte(pcistr[cnt].bus, - pcistr[cnt].device_fn, - PCI_INTERRUPT_LINE, - &pcistr[cnt].irq))) { - printk("GDT-PCI: error %d reading configuration space", error); + if ((error = pcibios_read_config_dword(pcistr[*cnt].bus, + pcistr[*cnt].device_fn, + PCI_BASE_ADDRESS_0, + GDTH_BASEP&base0)) || + (error = pcibios_read_config_dword(pcistr[*cnt].bus, + pcistr[*cnt].device_fn, + PCI_BASE_ADDRESS_1, + GDTH_BASEP&base1)) || + (error = pcibios_read_config_dword(pcistr[*cnt].bus, + pcistr[*cnt].device_fn, + PCI_BASE_ADDRESS_2, + GDTH_BASEP&base2)) || + (error = pcibios_read_config_word(pcistr[*cnt].bus, + pcistr[*cnt].device_fn, + PCI_SUBSYSTEM_ID, + &pcistr[*cnt].subdevice_id)) || + (error = pcibios_read_config_byte(pcistr[*cnt].bus, + pcistr[*cnt].device_fn, + PCI_INTERRUPT_LINE, + &pcistr[*cnt].irq))) { + printk("GDT-PCI: error %d reading configuration space", error); + continue; + } + pcistr[*cnt].vendor_id = vendor; + pcistr[*cnt].device_id = device; + if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ + device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ + if ((base0 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY) continue; - } - pcistr[cnt].device_id = device_id; - if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ - device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY) - continue; - pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; - } else { /* GDT6110, GDT6120, .. */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base2 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base1 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_IO) - continue; - pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; - } - TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), - pcistr[cnt].irq, pcistr[cnt].dpmem)); - cnt++; + pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; + } else { /* GDT6110, GDT6120, .. */ + if ((base0 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (base2 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY || + (base1 & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_IO) + continue; + pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; } + TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", + pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), + pcistr[*cnt].irq, pcistr[*cnt].dpmem)); + (*cnt)++; + } #endif - } - return cnt; -} +} GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt)) @@ -982,6 +1035,7 @@ /* detect IRQ */ if ((id = inl(eisa_adr+ID0REG)) == GDT3_ID) { + ha->oem_id = OEM_ID_ICP; ha->type = GDT_EISA; ha->stype = id; outl(1,eisa_adr+MAILBOXREG+8); @@ -1025,6 +1079,7 @@ if (eisacf > 4) /* level triggered */ eisacf -= 4; ha->irq = gdth_irq_tab[eisacf]; + ha->oem_id = OEM_ID_ICP; ha->type = GDT_EISA; ha->stype = id; } @@ -1101,6 +1156,7 @@ return 0; } + ha->oem_id = OEM_ID_ICP; ha->type = GDT_ISA; ha->ic_all_size = sizeof(dp2_ptr->u); ha->stype= GDT2_ID; @@ -1144,9 +1200,14 @@ TRACE(("gdth_init_pci()\n")); + if (pcistr->vendor_id == PCI_VENDOR_ID_INTEL) + ha->oem_id = OEM_ID_INTEL; + else + ha->oem_id = OEM_ID_ICP; ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8); - ha->stype = (ulong32)pcistr->device_id; - ha->irq = pcistr->irq; + ha->stype = (ulong32)pcistr->device_id; + ha->subdevice_id = pcistr->subdevice_id; + ha->irq = pcistr->irq; if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); @@ -1914,7 +1975,10 @@ /* 3. send to controller firmware */ gdth_internal_cmd(hanum,SCREENSERVICE,GDT_REALTIME, *(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]); -#endif +#endif + + /* unfreeze all IOs */ + gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0); /* initialize cache service */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) { @@ -2599,7 +2663,10 @@ inq.version = 2; inq.resp_aenc = 2; inq.add_length= 32; - strcpy(inq.vendor,"ICP "); + if (ha->oem_id == OEM_ID_INTEL) + strcpy(inq.vendor,"Intel "); + else + strcpy(inq.vendor,"ICP "); sprintf(inq.product,"Host Drive #%02d",t); strcpy(inq.revision," "); gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data)); @@ -3690,7 +3757,7 @@ if (ha->service == CACHESERVICE && ha->status == 56) { TRACE2(("gdth_async_event(): new host drive %d created\n", (ushort)ha->info)); - gdth_analyse_hdrive(hanum, (ushort)ha->info); + /* gdth_analyse_hdrive(hanum, (ushort)ha->info); */ } } return 1; @@ -3938,7 +4005,7 @@ if (request_dma(ha->drq,"gdth")) { printk("GDT-ISA: Unable to allocate DMA channel\n"); #if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,NULL); + free_irq(ha->irq,ha); #else free_irq(ha->irq); #endif @@ -3984,7 +4051,7 @@ scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif #if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,NULL); + free_irq(ha->irq,ha); #else free_irq(ha->irq); #endif @@ -4085,7 +4152,7 @@ scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif #if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,NULL); + free_irq(ha->irq,ha); #else free_irq(ha->irq); #endif @@ -4194,7 +4261,7 @@ scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif #if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,NULL); + free_irq(ha->irq,ha); #else free_irq(ha->irq); #endif @@ -4264,7 +4331,7 @@ if (shp->irq) { #if LINUX_VERSION_CODE >= 0x010346 - free_irq(shp->irq,NULL); + free_irq(shp->irq,ha); #else free_irq(shp->irq); #endif diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/gdth.h linux/drivers/scsi/gdth.h --- v2.4.9/linux/drivers/scsi/gdth.h Sat May 19 17:43:06 2001 +++ linux/drivers/scsi/gdth.h Fri Sep 7 09:28:37 2001 @@ -10,7 +10,7 @@ * * * - * $Id: gdth.h,v 1.38 2001/03/15 15:06:23 achim Exp $ + * $Id: gdth.h,v 1.44 2001/08/21 11:19:05 achim Exp $ */ #include @@ -29,13 +29,17 @@ /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "1.28" -#define GDTH_VERSION 1 -#define GDTH_SUBVERSION 28 +#define GDTH_VERSION_STR "2.03" +#define GDTH_VERSION 2 +#define GDTH_SUBVERSION 3 /* protocol version */ #define PROTOCOL_VERSION 1 +/* OEM IDs */ +#define OEM_ID_ICP 0x941c +#define OEM_ID_INTEL 0x8000 + /* controller classes */ #define GDT_ISA 0x01 /* ISA controller */ #define GDT_EISA 0x02 /* EISA controller */ @@ -54,6 +58,9 @@ #ifndef PCI_VENDOR_ID_VORTEX #define PCI_VENDOR_ID_VORTEX 0x1119 /* PCI controller vendor ID */ #endif +#ifndef PCI_VENDOR_ID_INTEL +#define PCI_VENDOR_ID_INTEL 0x8086 +#endif #ifndef PCI_DEVICE_ID_VORTEX_GDT60x0 /* GDT_PCI */ @@ -125,6 +132,16 @@ #define PCI_DEVICE_ID_VORTEX_GDTMAXRP 0x2ff #endif +#ifndef PCI_DEVICE_ID_VORTEX_GDTNEWRX +/* new GDT Rx Controller */ +#define PCI_DEVICE_ID_VORTEX_GDTNEWRX 0x300 +#endif + +#ifndef PCI_DEVICE_ID_INTEL_SRC +/* Intel Storage RAID Controller */ +#define PCI_DEVICE_ID_INTEL_SRC 0x600 +#endif + /* limits */ #define GDTH_SCRATCH PAGE_SIZE /* 4KB scratch buffer */ #define GDTH_SCRATCH_ORD 0 /* order 0 means 1 page */ @@ -202,6 +219,8 @@ #define GDT_CLUST_INFO 22 /* cluster info */ #define GDT_RW_ATTRIBS 23 /* R/W attribs (write thru,..)*/ #define GDT_CLUST_RESET 24 /* releases the cluster drives*/ +#define GDT_FREEZE_IO 25 /* freezes all IOs */ +#define GDT_UNFREEZE_IO 26 /* unfreezes all IOs */ /* raw service commands */ #define GDT_RESERVE 14 /* reserve dev. to raw serv. */ @@ -843,7 +862,9 @@ #if LINUX_VERSION_CODE >= 0x02015C struct pci_dev *pdev; #endif + ushort vendor_id; /* vendor (ICP, Intel, ..) */ ushort device_id; /* device ID (0,..,9) */ + ushort subdevice_id; /* sub device ID */ unchar bus; /* PCI bus */ unchar device_fn; /* PCI device/function no. */ ulong dpmem; /* DPRAM address */ @@ -855,9 +876,11 @@ /* controller information structure */ typedef struct { + ushort oem_id; /* OEM */ ushort type; /* controller class */ ushort raw_feat; /* feat. raw service (s/g,..) */ - ulong32 stype; /* controller subtype */ + ulong32 stype; /* subtype (PCI: device ID) */ + ushort subdevice_id; /* sub device ID (PCI) */ ushort fw_vers; /* firmware version */ ushort cache_feat; /* feat. cache serv. (s/g,..) */ ushort bmic; /* BMIC address (EISA) */ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/gdth_ioctl.h linux/drivers/scsi/gdth_ioctl.h --- v2.4.9/linux/drivers/scsi/gdth_ioctl.h Sat May 19 17:43:06 2001 +++ linux/drivers/scsi/gdth_ioctl.h Fri Sep 7 09:28:37 2001 @@ -2,7 +2,7 @@ #define _GDTH_IOCTL_H /* gdth_ioctl.h - * $Id: gdth_ioctl.h,v 1.9 2001/01/10 14:39:37 achim Exp $ + * $Id: gdth_ioctl.h,v 1.10 2001/05/22 06:28:59 achim Exp $ */ /* IOCTLs */ @@ -83,6 +83,8 @@ ushort bios_ver; /* not used */ ushort access; /* not used */ ushort ext_type; /* extended type */ + ushort device_id; /* device ID */ + ushort sub_device_id; /* sub device ID */ } ctrtype; struct { unchar version; /* OS version */ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c --- v2.4.9/linux/drivers/scsi/gdth_proc.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/scsi/gdth_proc.c Fri Sep 7 09:28:37 2001 @@ -1,9 +1,11 @@ /* gdth_proc.c - * $Id: gdth_proc.c,v 1.27 2001/03/14 10:47:00 achim Exp $ + * $Id: gdth_proc.c,v 1.33 2001/08/10 07:54:39 achim Exp $ */ #include "gdth_ioctl.h" +#if LINUX_VERSION_CODE >= 0x020407 #include +#endif int gdth_proc_info(char *buffer,char **start,off_t offset,int length, int hostno,int inout) @@ -48,7 +50,7 @@ sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) - return -ENOMEM; + return -ENOMEM; scp->cmd_len = 12; scp->use_sg = 0; #else @@ -176,7 +178,7 @@ } if (wb_mode) { - if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str))) + if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE)) return(-EBUSY); pcpar = (gdth_cpar_str *)ha->pscratch; memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) ); @@ -192,7 +194,7 @@ #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); #endif - gdth_ioctl_free(hanum); + gdth_ioctl_free(hanum, ha->pscratch); printk("Done.\n"); return(orig_length); } @@ -270,7 +272,8 @@ } else { return(-EINVAL); } - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2 )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2, + TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; @@ -294,7 +297,7 @@ break; case GDTIOCTL_DRVERS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -303,25 +306,33 @@ break; case GDTIOCTL_CTRTYPE: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; if (ha->type == GDT_ISA || ha->type == GDT_EISA) { piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10); - } else if (ha->type != GDT_PCIMPR) { - piord->iu.ctrtype.type = (unchar)((ha->stype<<8) + 6); } else { - piord->iu.ctrtype.type = 0xfe; - piord->iu.ctrtype.ext_type = 0x6000 | ha->stype; + if (ha->type != GDT_PCIMPR) { + piord->iu.ctrtype.type = (unchar)((ha->stype<<4) + 6); + } else { + piord->iu.ctrtype.type = + (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe); + if (ha->stype >= 0x300) + piord->iu.ctrtype.ext_type = 0x6000 | ha->subdevice_id; + else + piord->iu.ctrtype.ext_type = 0x6000 | ha->stype; + } + piord->iu.ctrtype.device_id = ha->stype; + piord->iu.ctrtype.sub_device_id = ha->subdevice_id; } piord->iu.ctrtype.info = ha->brd_phys; - piord->iu.ctrtype.oem_id = (ushort)GDT3_ID; + piord->iu.ctrtype.oem_id = ha->oem_id; break; case GDTIOCTL_CTRCNT: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -330,7 +341,7 @@ break; case GDTIOCTL_OSVERS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -341,7 +352,7 @@ break; case GDTIOCTL_LOCKDRV: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) { @@ -367,7 +378,7 @@ break; case GDTIOCTL_LOCKCHN: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); i = piowr->iu.lockchn.channel; if (i < ha->bus_cnt) { @@ -395,7 +406,7 @@ break; case GDTIOCTL_EVENT: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; if (piowr->iu.event.erase == 0xff) { @@ -430,7 +441,7 @@ break; case GDTIOCTL_SCSI: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -451,7 +462,7 @@ break; case GDTIOCTL_RESET_BUS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -475,7 +486,7 @@ break; case GDTIOCTL_HDRLIST: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -509,7 +520,7 @@ break; case GDTIOCTL_RESCAN: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -635,7 +646,7 @@ break; case GDTIOCTL_RESET_DRV: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -684,6 +695,7 @@ char hrec[161]; struct timeval tv; + char *buf; gdth_dskstat_str *pds; gdth_diskinfo_str *pdi; gdth_arrayinf_str *pai; @@ -701,6 +713,8 @@ #if LINUX_VERSION_CODE >= 0x020322 sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]); scp = scsi_allocate_device(sdev, 1, FALSE); + if (!scp) + return -ENOMEM; scp->cmd_len = 12; scp->use_sg = 0; #else @@ -784,12 +798,13 @@ len += size; pos = begin + len; flag = FALSE; - if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH)) + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE); + if (!buf) goto stop_output; for (i = 0; i < ha->bus_cnt; ++i) { /* 2.a statistics (and retries/reassigns) */ TRACE2(("pdr_statistics() chn %d\n",i)); - pds = (gdth_dskstat_str *)(ha->pscratch + GDTH_SCRATCH/4); + pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = virt_to_bus(pds); @@ -819,7 +834,7 @@ /* 2.b drive info */ TRACE2(("scsi_drv_info() chn %d dev %d\n", i, ha->raw[i].id_list[j])); - pdi = (gdth_diskinfo_str *)ha->pscratch; + pdi = (gdth_diskinfo_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = virt_to_bus(pdi); @@ -874,7 +889,7 @@ /* 2.c grown defects */ TRACE2(("scsi_drv_defcnt() chn %d dev %d\n", i, ha->raw[i].id_list[j])); - pdef = (gdth_defcnt_str *)ha->pscratch; + pdef = (gdth_defcnt_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = virt_to_bus(pdef); @@ -905,7 +920,7 @@ goto stop_output; } } - gdth_ioctl_free(hanum); + gdth_ioctl_free(hanum, buf); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -917,7 +932,8 @@ len += size; pos = begin + len; flag = FALSE; - if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH)) + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE); + if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { if (!ha->hdr[i].is_logdrv) @@ -928,7 +944,7 @@ do { /* 3.a log. drive info */ TRACE2(("cache_drv_info() drive no %d\n",drv_no)); - pcdi = (gdth_cdrinfo_str *)ha->pscratch; + pcdi = (gdth_cdrinfo_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi); @@ -1018,7 +1034,7 @@ if (pos > offset + length) goto stop_output; } - gdth_ioctl_free(hanum); + gdth_ioctl_free(hanum, buf); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -1030,14 +1046,15 @@ len += size; pos = begin + len; flag = FALSE; - if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH)) + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE); + if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master)) continue; /* 4.a array drive info */ TRACE2(("array_info() drive no %d\n",i)); - pai = (gdth_arrayinf_str *)ha->pscratch; + pai = (gdth_arrayinf_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = virt_to_bus(pai); @@ -1095,7 +1112,7 @@ goto stop_output; } } - gdth_ioctl_free(hanum); + gdth_ioctl_free(hanum, buf); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -1107,7 +1124,8 @@ len += size; pos = begin + len; flag = FALSE; - if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH)) + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE); + if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { if (!ha->hdr[i].is_logdrv || @@ -1115,7 +1133,7 @@ continue; /* 5.a get host drive list */ TRACE2(("host_get() drv_no %d\n",i)); - phg = (gdth_hget_str *)ha->pscratch; + phg = (gdth_hget_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = virt_to_bus(phg); @@ -1146,7 +1164,7 @@ } } } - gdth_ioctl_free(hanum); + gdth_ioctl_free(hanum, buf); for (i = 0; i < MAX_HDRIVES; ++i) { if (!(ha->hdr[i].present)) @@ -1210,7 +1228,7 @@ goto stop_output; length = piord->size; memcpy(buffer+len, (char *)piord, length); - gdth_ioctl_free(hanum); + gdth_ioctl_free(hanum, ha->pscratch); len = length; } @@ -1232,7 +1250,13 @@ char *cmnd, int timeout) { unsigned bufflen; +#if LINUX_VERSION_CODE >= 0x020407 DECLARE_COMPLETION(wait); +#elif LINUX_VERSION_CODE >= 0x020322 + DECLARE_MUTEX_LOCKED(sem); +#else + struct semaphore sem = MUTEX_LOCKED; +#endif TRACE2(("gdth_do_cmd()\n")); if (gdtcmd != NULL) { @@ -1243,7 +1267,12 @@ bufflen = 0; } scp->request.rq_status = RQ_SCSI_BUSY; +#if LINUX_VERSION_CODE >= 0x020407 scp->request.waiting = &wait; + scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); + wait_for_completion(&wait); +#else + scp->request.sem = &sem; #if LINUX_VERSION_CODE >= 0x020322 scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); #else @@ -1251,7 +1280,8 @@ scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); GDTH_UNLOCK_SCSI_DOCMD(); #endif - wait_for_completion(&wait); + down(&sem); +#endif } void gdth_scsi_done(Scsi_Cmnd *scp) @@ -1260,15 +1290,20 @@ scp->request.rq_status = RQ_SCSI_DONE; +#if LINUX_VERSION_CODE >= 0x020407 if (scp->request.waiting != NULL) complete(scp->request.waiting); +#else + if (scp->request.sem != NULL) + up(scp->request.sem); +#endif } -static int gdth_ioctl_alloc(int hanum, ushort size) +static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch) { gdth_ha_str *ha; ulong flags; - int ret_val; + char *ret_val; if (size == 0 || size > GDTH_SCRATCH) return FALSE; @@ -1276,17 +1311,26 @@ ha = HADATA(gdth_ctr_tab[hanum]); GDTH_LOCK_HA(ha, flags); - if (!ha->scratch_busy) { - ha->scratch_busy = TRUE; - ret_val = TRUE; - } else - ret_val = FALSE; + if (scratch) { + if (!ha->scratch_busy) { + ha->scratch_busy = TRUE; + ret_val = ha->pscratch; + } else + ret_val = NULL; + } else { +#if LINUX_VERSION_CODE >= 0x020322 + ret_val = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, + GDTH_SCRATCH_ORD); +#else + ret_val = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); +#endif + } GDTH_UNLOCK_HA(ha, flags); return ret_val; } -static void gdth_ioctl_free(int hanum) +static void gdth_ioctl_free(int hanum, char *buf) { gdth_ha_str *ha; ulong flags; @@ -1294,7 +1338,15 @@ ha = HADATA(gdth_ctr_tab[hanum]); GDTH_LOCK_HA(ha, flags); - ha->scratch_busy = FALSE; + if (buf == ha->pscratch) { + ha->scratch_busy = FALSE; + } else { +#if LINUX_VERSION_CODE >= 0x020322 + free_pages((unsigned long)buf, GDTH_SCRATCH_ORD); +#else + scsi_init_free((void *)buf, GDTH_SCRATCH); +#endif + } GDTH_UNLOCK_HA(ha, flags); } diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/gdth_proc.h linux/drivers/scsi/gdth_proc.h --- v2.4.9/linux/drivers/scsi/gdth_proc.h Sat May 19 17:43:06 2001 +++ linux/drivers/scsi/gdth_proc.h Fri Sep 7 09:28:37 2001 @@ -2,7 +2,7 @@ #define _GDTH_PROC_H /* gdth_proc.h - * $Id: gdth_proc.h,v 1.10 2000/07/24 09:30:01 achim Exp $ + * $Id: gdth_proc.h,v 1.11 2001/07/25 15:37:40 achim Exp $ */ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum); @@ -19,8 +19,8 @@ static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, char *cmnd, int timeout); -static int gdth_ioctl_alloc(int hanum, ushort size); -static void gdth_ioctl_free(int hanum); +static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch); +static void gdth_ioctl_free(int hanum, char *buf); static int gdth_ioctl_check_bin(int hanum, ushort size); static void gdth_wait_completion(int hanum, int busnum, int id); static void gdth_stop_timeout(int hanum, int busnum, int id); diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/pcmcia/nsp_cs.c linux/drivers/scsi/pcmcia/nsp_cs.c --- v2.4.9/linux/drivers/scsi/pcmcia/nsp_cs.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/scsi/pcmcia/nsp_cs.c Fri Sep 7 09:28:37 2001 @@ -9,7 +9,7 @@ Ver.0.1 Initial version This software may be used and distributed according to the terms of - the GNU Public License. + the GNU General Public License. ======================================================================*/ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/pcmcia/nsp_debug.c linux/drivers/scsi/pcmcia/nsp_debug.c --- v2.4.9/linux/drivers/scsi/pcmcia/nsp_debug.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/scsi/pcmcia/nsp_debug.c Fri Sep 7 09:28:37 2001 @@ -3,7 +3,7 @@ By: YOKOTA Hiroshi This software may be used and distributed according to the terms of - the GNU Public License. + the GNU General Public License. =========================================================================*/ /* $Id: nsp_debug.c,v 1.6 2001/07/04 14:43:53 elca Exp $ */ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/pcmcia/nsp_message.c linux/drivers/scsi/pcmcia/nsp_message.c --- v2.4.9/linux/drivers/scsi/pcmcia/nsp_message.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/scsi/pcmcia/nsp_message.c Fri Sep 7 09:28:37 2001 @@ -3,7 +3,7 @@ By: YOKOTA Hiroshi This software may be used and distributed according to the terms of - the GNU Public License. + the GNU General Public License. */ /* $Id: nsp_message.c,v 1.6 2001/07/05 10:56:37 elca Exp $ */ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/qlogicfc.c linux/drivers/scsi/qlogicfc.c --- v2.4.9/linux/drivers/scsi/qlogicfc.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/scsi/qlogicfc.c Fri Sep 7 09:28:37 2001 @@ -98,8 +98,6 @@ isp2200's firmware. */ -#define RELOAD_FIRMWARE 0 - #define USE_NVRAM_DEFAULTS 1 #define ISP2x00_PORTDB 1 @@ -440,7 +438,16 @@ #define MBOX_SEND_CHANGE_REQUEST 0x0070 #define MBOX_PORT_LOGOUT 0x0071 -//#include "qlogicfc_asm.c" +/* + * Firmware if needed (note this is a hack, it belongs in a seperate + * module. + */ + +#ifdef CONFIG_SCSI_QLOGIC_FC_FIRMWARE +#include "qlogicfc_asm.c" +#else +static unsigned short risc_code_addr01 = 0x1000 ; +#endif /* Each element in mbox_param is an 8 bit bitmap where each bit indicates if that mbox should be copied as input. For example 0x2 would mean @@ -1853,7 +1860,6 @@ struct isp2x00_hostdata *hostdata; int loop_count; dma64_addr_t busaddr; - unsigned short risc_code_addr01 = 0x1000 ; ENTER("isp2x00_reset_hardware"); @@ -1892,7 +1898,7 @@ DEBUG(printk("qlogicfc%d : verifying checksum\n", hostdata->host_id)); -#if RELOAD_FIRMWARE +#if defined(CONFIG_SCSI_QLOGIC_FC_FIRMWARE) { int i; unsigned short * risc_code = NULL; diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/qlogicfc_asm.c linux/drivers/scsi/qlogicfc_asm.c --- v2.4.9/linux/drivers/scsi/qlogicfc_asm.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/qlogicfc_asm.c Fri Sep 7 09:28:37 2001 @@ -0,0 +1,9751 @@ +/************************************************************************ + * * + * --- ISP2100 Fabric Initiator/Target Firmware --- * + * with expanded LUN addressing * + * and FcTape (FCP-2) support * + * * + * * + ************************************************************************ + Copyright (C) 2000 and 2001 Qlogic Corporation + (www.qlogic.com) + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. +************************************************************************/ + +/* + * Firmware Version 1.19.16 (10:36 Nov 02, 2000) + */ + +unsigned short risc_code_addr01 = 0x1000 ; + +unsigned short risc_code_length2100 = 0x9260; +unsigned short risc_code2100[] = { + 0x0078, 0x102d, 0x0000, 0x9260, 0x0000, 0x0001, 0x0013, 0x0010, + 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, + 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1, + 0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff, + 0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04, + 0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c, + 0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020, + 0x2039, 0x8fff, 0x20a1, 0xaa00, 0x2708, 0x810d, 0x810d, 0x810d, + 0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8, + 0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102, + 0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1, + 0xa260, 0x2009, 0x0000, 0x20a9, 0x07a0, 0x41a4, 0x3400, 0x20c9, + 0xa7ff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x255d, + 0x2051, 0xa300, 0x2a70, 0x775e, 0xa786, 0x8fff, 0x0040, 0x1092, + 0x705b, 0xca00, 0x7057, 0xc9f1, 0x7063, 0x0200, 0x7067, 0x0200, + 0x0078, 0x109a, 0x7057, 0xba01, 0x7063, 0x0100, 0x7067, 0x0100, + 0x705b, 0xba00, 0x1078, 0x12df, 0x1078, 0x13c0, 0x1078, 0x1569, + 0x1078, 0x1ca4, 0x1078, 0x4229, 0x1078, 0x74cf, 0x1078, 0x134b, + 0x1078, 0x2a3f, 0x1078, 0x4da2, 0x1078, 0x48b2, 0x1078, 0x57df, + 0x1078, 0x21f7, 0x1078, 0x5abf, 0x1078, 0x5369, 0x1078, 0x210d, + 0x1078, 0x21d4, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf, + 0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068, + 0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, + 0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, + 0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x35bc, 0x1078, 0x2a67, + 0x1078, 0x4df2, 0x1078, 0x4a75, 0x2009, 0x0100, 0x2104, 0xa082, + 0x0002, 0x0048, 0x10f3, 0x1078, 0x57fb, 0x0078, 0x10d6, 0x1079, + 0x10f7, 0x0078, 0x10dc, 0x1078, 0x6fa9, 0x0078, 0x10eb, 0x1101, + 0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078, + 0x1328, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086, + 0x0001, 0x00c0, 0x1198, 0x1078, 0x3a43, 0x2079, 0x0100, 0x7844, + 0xa005, 0x00c0, 0x1198, 0x2011, 0x4129, 0x1078, 0x58d4, 0x1078, + 0x1ab1, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, + 0x8010, 0x73c0, 0x1078, 0x3579, 0x2001, 0xffff, 0x1078, 0x5975, + 0x7238, 0xc284, 0x723a, 0x2001, 0xa30c, 0x2014, 0xc2ac, 0x2202, + 0x1078, 0x6db5, 0x2011, 0x0004, 0x1078, 0x8a59, 0x1078, 0x47ce, + 0x1078, 0x4211, 0x0040, 0x1144, 0x7083, 0x0001, 0x70bb, 0x0000, + 0x1078, 0x3bf5, 0x0078, 0x1198, 0x1078, 0x4897, 0x0040, 0x114d, + 0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x8ddf, 0x70c8, + 0xd09c, 0x00c0, 0x1159, 0x7094, 0xa005, 0x0040, 0x1159, 0x1078, + 0x41f5, 0x70d3, 0x0000, 0x70cf, 0x0000, 0x72c8, 0x2079, 0xa351, + 0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ca, 0xa296, 0x0004, + 0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8a59, 0x708f, 0x0000, + 0x7093, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x260d, 0x2011, + 0x0005, 0x1078, 0x6ef2, 0x1078, 0x6109, 0x0c7e, 0x2061, 0x0100, + 0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x708f, 0x0000, + 0x7093, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x6ef2, + 0x1078, 0x6109, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, + 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e, + 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078, + 0x71e0, 0x027f, 0x1078, 0xa190, 0x037f, 0x027f, 0x017f, 0x1078, + 0x2921, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706b, 0x0000, 0x706c, + 0xa084, 0x00ff, 0x706e, 0x7097, 0x0000, 0x007c, 0x127e, 0x2091, + 0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7090, 0xa086, + 0xffff, 0x0040, 0x11d1, 0x1078, 0x260d, 0x1078, 0x6109, 0x0078, + 0x1244, 0x70c8, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd, + 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, + 0x0040, 0x11fd, 0x70cc, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078, + 0x278a, 0x1078, 0x6109, 0x70c8, 0xd094, 0x00c0, 0x1244, 0x2011, + 0x0001, 0x2019, 0x0000, 0x1078, 0x27c2, 0x1078, 0x6109, 0x0078, + 0x1244, 0x70d0, 0xa005, 0x00c0, 0x1244, 0x708c, 0xa005, 0x00c0, + 0x1244, 0x1078, 0x4897, 0x00c0, 0x1244, 0x2001, 0xa352, 0x2004, + 0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, 0x121a, 0x6000, 0xd0ec, + 0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f, + 0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003, + 0x0003, 0x7093, 0xffff, 0x2001, 0x0000, 0x1078, 0x2480, 0x1078, + 0x35f7, 0x2001, 0xa5ac, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c, + 0x2011, 0x0000, 0x1078, 0x6ef2, 0x2011, 0x0000, 0x1078, 0x6efc, + 0x1078, 0x6109, 0x1078, 0x61d3, 0x127f, 0x007c, 0x017e, 0x0f7e, + 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078, + 0x41de, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040, + 0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008, + 0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5975, 0x7900, 0xa18a, + 0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009, + 0x00f8, 0x1078, 0x41de, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, + 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0, + 0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x2480, 0x0078, + 0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0, + 0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f, + 0x0000, 0x2009, 0x00f8, 0x1078, 0x41de, 0x20a9, 0x000e, 0x0005, + 0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010, + 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4, + 0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009, + 0xa331, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4, + 0x200b, 0x0000, 0x1078, 0x251e, 0x2001, 0x0001, 0x1078, 0x2480, + 0x0078, 0x12d3, 0x2001, 0xa331, 0x2003, 0x0000, 0x7828, 0xc09d, + 0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f, + 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70, + 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, 0x12eb, 0x704f, + 0xffff, 0x0078, 0x12ed, 0x704f, 0x0000, 0x7053, 0xffff, 0x706b, + 0x0000, 0x706f, 0x0000, 0x1078, 0x8ddf, 0x2061, 0xa58c, 0x6003, + 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, + 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, + 0xa594, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, + 0x0000, 0x2061, 0xa5a3, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, + 0x4943, 0x600f, 0x2020, 0x2001, 0xa325, 0x2003, 0x0000, 0x007c, + 0x2091, 0x8000, 0x0068, 0x132a, 0x007e, 0x017e, 0x2079, 0x0000, + 0x7818, 0xd084, 0x00c0, 0x1330, 0x017f, 0x792e, 0x007f, 0x782a, + 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, + 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa300, 0x7803, 0x0005, + 0x0078, 0x1348, 0x007c, 0x2071, 0xa300, 0x7158, 0x712e, 0x2021, + 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048, 0x1361, 0x705c, + 0xa302, 0x00c8, 0x1361, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, + 0x1353, 0x200b, 0x0000, 0x74a6, 0x74aa, 0x007c, 0x0e7e, 0x127e, + 0x2091, 0x8000, 0x2071, 0xa300, 0x70a8, 0xa0ea, 0x0010, 0x00c8, + 0x1374, 0xa06e, 0x0078, 0x137e, 0x8001, 0x70aa, 0x702c, 0x2068, + 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, + 0x007c, 0x0e7e, 0x2071, 0xa300, 0x127e, 0x2091, 0x8000, 0x70a8, + 0x8001, 0x00c8, 0x138e, 0xa06e, 0x0078, 0x1397, 0x70aa, 0x702c, + 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, + 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa300, + 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a8, 0x8000, 0x70aa, 0x127f, + 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13b6, 0x6804, 0x6807, 0x0000, + 0x007e, 0x1078, 0x139a, 0x0d7f, 0x0078, 0x13aa, 0x007c, 0x0e7e, + 0x2071, 0xa300, 0x70a8, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c, + 0x0e7e, 0x2071, 0xa5d0, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, + 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f, + 0x007c, 0x0e7e, 0x2270, 0x700b, 0x0000, 0x2071, 0xa5d0, 0x7018, + 0xa088, 0xa5d9, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, + 0xa005, 0x00c0, 0x13e9, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13fa, + 0x0f7f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa5d0, 0x7004, 0xa005, + 0x00c0, 0x13f8, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13fa, 0x0f7f, + 0x0e7f, 0x007c, 0x7000, 0x0079, 0x13fd, 0x1401, 0x146b, 0x1488, + 0x1488, 0x7018, 0x711c, 0xa106, 0x00c0, 0x1409, 0x7007, 0x0000, + 0x007c, 0x0d7e, 0xa180, 0xa5d9, 0x2004, 0x700a, 0x2068, 0x8108, + 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, + 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, + 0x7016, 0x6804, 0x0d7f, 0xd084, 0x0040, 0x142b, 0x7007, 0x0001, + 0x1078, 0x1430, 0x007c, 0x7007, 0x0002, 0x1078, 0x1446, 0x007c, + 0x017e, 0x027e, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, + 0x143b, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, + 0x0020, 0x7803, 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, + 0x137e, 0x147e, 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, + 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x145a, + 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, + 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f, + 0x027f, 0x017f, 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa3f9, + 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, + 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, + 0x7002, 0x700b, 0xa3f4, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, + 0x137e, 0x147e, 0x157e, 0x2001, 0xa428, 0x209c, 0x20a1, 0x0014, + 0x7803, 0x0026, 0x2001, 0xa429, 0x20ac, 0x53a6, 0x2099, 0xa42a, + 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, + 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, + 0x7002, 0x700b, 0xa425, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, + 0x017e, 0x0e7e, 0x2071, 0xa5d0, 0x0f7e, 0x2079, 0x0010, 0x7904, + 0x7803, 0x0002, 0xd1fc, 0x0040, 0x14c2, 0xa18c, 0x0700, 0x7004, + 0x1079, 0x14c6, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13fa, 0x14ce, + 0x14fb, 0x1523, 0x1556, 0x14cc, 0x0078, 0x14cc, 0xa18c, 0x0700, + 0x00c0, 0x14f4, 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099, + 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, + 0x157f, 0x147f, 0x137f, 0x700c, 0xa005, 0x0040, 0x1510, 0x1078, + 0x1430, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, + 0x0000, 0x1078, 0x13fa, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, + 0x0200, 0x0078, 0x14ef, 0xa18c, 0x0700, 0x00c0, 0x1506, 0x700c, + 0xa005, 0x0040, 0x1510, 0x1078, 0x1446, 0x007c, 0x7008, 0xa080, + 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x1078, 0x13fa, 0x007c, + 0x0d7e, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, + 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, + 0x1078, 0x13fa, 0x007c, 0xa18c, 0x0700, 0x00c0, 0x1550, 0x137e, + 0x147e, 0x157e, 0x2001, 0xa3f7, 0x2004, 0xa080, 0x000d, 0x20a0, + 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, + 0xa3f9, 0x2004, 0xd0bc, 0x0040, 0x1546, 0x2001, 0xa402, 0x2004, + 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f, + 0x137f, 0x7007, 0x0000, 0x1078, 0x4e9b, 0x1078, 0x13fa, 0x007c, + 0x2011, 0x8003, 0x1078, 0x3579, 0x0078, 0x1554, 0xa18c, 0x0700, + 0x00c0, 0x1563, 0x2001, 0xa427, 0x2003, 0x0100, 0x7007, 0x0000, + 0x1078, 0x13fa, 0x007c, 0x2011, 0x8004, 0x1078, 0x3579, 0x0078, + 0x1567, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa5e1, + 0x7803, 0x0004, 0x7003, 0x0000, 0x700f, 0xa5e7, 0x7013, 0xa5e7, + 0x780f, 0x0076, 0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184, + 0x0007, 0x0079, 0x1583, 0x158b, 0x15d1, 0x158b, 0x158b, 0x158b, + 0x15b6, 0x159a, 0x158f, 0xa085, 0x0001, 0x0078, 0x15eb, 0x684c, + 0xd0bc, 0x0040, 0x158b, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, + 0x0078, 0x15d9, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x158b, + 0x684c, 0xd0bc, 0x0040, 0x158b, 0x6860, 0x682e, 0x685c, 0x682a, + 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, + 0x2015, 0x2004, 0x6832, 0x6858, 0x0078, 0x15e1, 0xa18c, 0x00ff, + 0xa186, 0x0015, 0x00c0, 0x158b, 0x684c, 0xd0ac, 0x0040, 0x158b, + 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, + 0x2015, 0x2004, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, + 0x15e1, 0x684c, 0xd0ac, 0x0040, 0x158b, 0xa006, 0x682e, 0x682a, + 0x6858, 0xa18c, 0x000f, 0xa188, 0x2015, 0x210c, 0x6932, 0x2d08, + 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, + 0x6912, 0x6980, 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, + 0x2001, 0x020a, 0x2004, 0x82ff, 0x0040, 0x160e, 0xa280, 0x0004, + 0x0d7e, 0x206c, 0x684c, 0xd0dc, 0x00c0, 0x160a, 0x1078, 0x157e, + 0x0040, 0x160a, 0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, + 0x0078, 0x160e, 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, + 0x037e, 0x027e, 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, + 0xa005, 0x00c0, 0x1622, 0x7206, 0x2001, 0x1643, 0x007e, 0x2260, + 0x0078, 0x17be, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, + 0x8108, 0xa182, 0xa602, 0x0048, 0x162f, 0x2009, 0xa5e7, 0x710e, + 0x7010, 0xa102, 0xa082, 0x0009, 0x0040, 0x163a, 0xa080, 0x001b, + 0x00c0, 0x163d, 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0, + 0x1643, 0x1078, 0x179f, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e, + 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f, + 0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005, + 0x0040, 0x16cf, 0x6808, 0xa005, 0x0040, 0x173c, 0x7000, 0xa005, + 0x00c0, 0x1664, 0x0078, 0x16c4, 0x700c, 0x7110, 0xa106, 0x00c0, + 0x1745, 0x7004, 0xa406, 0x00c0, 0x16c4, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0040, 0x1681, 0x047e, 0x1078, 0x18e2, 0x047f, 0x2460, + 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x0040, 0x173c, 0x0078, + 0x165e, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x166d, 0x7804, + 0xa084, 0x6000, 0x0040, 0x1692, 0xa086, 0x6000, 0x0040, 0x1692, + 0x0078, 0x166d, 0x7100, 0xa186, 0x0002, 0x00c0, 0x16b2, 0x0e7e, + 0x2b68, 0x6818, 0x2060, 0x1078, 0x1fea, 0x2804, 0xac70, 0x6034, + 0xd09c, 0x00c0, 0x16a7, 0x7108, 0x720c, 0x0078, 0x16a9, 0x7110, + 0x7214, 0x6810, 0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f, + 0x0078, 0x16b6, 0xa186, 0x0001, 0x00c0, 0x16be, 0x7820, 0x6910, + 0xa100, 0x6812, 0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004, + 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0, + 0x1745, 0x2009, 0x0048, 0x1078, 0x756c, 0x0078, 0x1745, 0x6808, + 0xa005, 0x0040, 0x173c, 0x7000, 0xa005, 0x00c0, 0x16d9, 0x0078, + 0x173c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x16e2, 0x7004, 0xa406, + 0x00c0, 0x173c, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x16f6, + 0x047e, 0x1078, 0x18e2, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002, + 0x2004, 0xa005, 0x0040, 0x173c, 0x0078, 0x16d3, 0x2001, 0x0207, + 0x2004, 0xd09c, 0x00c0, 0x16e2, 0x2001, 0x0005, 0x2004, 0xd08c, + 0x00c0, 0x16e8, 0x7804, 0xa084, 0x6000, 0x0040, 0x170d, 0xa086, + 0x6000, 0x0040, 0x170d, 0x0078, 0x16e2, 0x7007, 0x0000, 0xa016, + 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x172e, 0xa08e, 0x0002, + 0x00c0, 0x173c, 0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x1fea, + 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x172a, 0x7308, 0x720c, + 0x0078, 0x172c, 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318, + 0x7824, 0xa211, 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816, + 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0, + 0x1745, 0x2009, 0x0048, 0x1078, 0x756c, 0x0c7f, 0x0d7f, 0x127f, + 0x007c, 0x0f7e, 0x0e7e, 0x027e, 0x037e, 0x047e, 0x1078, 0x1af7, + 0x027e, 0x2071, 0xa5e1, 0x7000, 0xa086, 0x0000, 0x0040, 0x1790, + 0x7004, 0xac06, 0x00c0, 0x1781, 0x2079, 0x0030, 0x7000, 0xa086, + 0x0003, 0x0040, 0x1781, 0x7804, 0xd0fc, 0x00c0, 0x177d, 0x2001, + 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1763, 0x7803, 0x0004, 0x7804, + 0xd0ac, 0x00c0, 0x176f, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, + 0x0003, 0x7007, 0x0000, 0x0078, 0x1781, 0x1078, 0x18e2, 0x0078, + 0x1753, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa5e7, 0x2104, 0xac06, + 0x00c0, 0x178b, 0x200a, 0xa188, 0x0003, 0x00f0, 0x1786, 0x157f, + 0x027f, 0x2001, 0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0138, + 0x2202, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f, 0x007c, 0x700c, + 0x7110, 0xa106, 0x00c0, 0x17a7, 0x7003, 0x0000, 0x007c, 0x2104, + 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, + 0xa602, 0x0048, 0x17b5, 0x2009, 0xa5e7, 0x7112, 0x700c, 0xa106, + 0x00c0, 0x17be, 0x2001, 0x0138, 0x2003, 0x0008, 0x8cff, 0x00c0, + 0x17c5, 0x1078, 0x1b22, 0x0078, 0x1823, 0x6010, 0x2068, 0x2d58, + 0x6828, 0xa406, 0x00c0, 0x17d0, 0x682c, 0xa306, 0x0040, 0x17fe, + 0x601c, 0xa086, 0x0008, 0x0040, 0x17fe, 0x6024, 0xd0f4, 0x00c0, + 0x17fa, 0xd0d4, 0x0040, 0x17f6, 0x6038, 0xa402, 0x6034, 0xa303, + 0x0040, 0x17e4, 0x00c8, 0x17f6, 0x643a, 0x6336, 0x6c2a, 0x6b2e, + 0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, + 0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x17fa, 0x1078, 0x8d8e, + 0x0040, 0x17c1, 0x1078, 0x2035, 0x00c0, 0x17c1, 0x0c7e, 0x7004, + 0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4, 0x0040, + 0x180f, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17c1, 0x6824, + 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, + 0x2009, 0x0011, 0x1078, 0x1824, 0x0040, 0x1822, 0x2009, 0x0001, + 0x1078, 0x1824, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18bb, 0xa03e, + 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1846, 0xd0f4, 0x00c0, 0x1856, + 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1836, 0x189d, 0x185d, + 0x185d, 0x189d, 0x189d, 0x1895, 0x189d, 0x185d, 0x189d, 0x1863, + 0x1863, 0x189d, 0x189d, 0x189d, 0x188c, 0x1863, 0xc0fc, 0x6852, + 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040, 0x18a0, + 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18a0, 0xc0f4, 0x6852, + 0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18a7, 0x6b08, 0x6a0c, 0x6d00, + 0x6c04, 0x0078, 0x18a0, 0x7b0c, 0xd3bc, 0x0040, 0x1884, 0x7004, + 0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1884, + 0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff, + 0x00c0, 0x187f, 0x6810, 0xa302, 0x0048, 0x187f, 0x6b10, 0x2011, + 0x0000, 0x2468, 0x0078, 0x1886, 0x6b10, 0x6a14, 0x6d00, 0x6c04, + 0x6f08, 0x6e0c, 0x0078, 0x18a0, 0x0d7f, 0x0d7e, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001e, 0x00c0, 0x189d, 0x0d7f, 0x1078, 0x1fd1, + 0x00c0, 0x1824, 0xa00e, 0x0078, 0x18bb, 0x0d7f, 0x1078, 0x1328, + 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, + 0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, + 0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14, 0xa203, + 0x6816, 0x1078, 0x1fd1, 0x007c, 0x1078, 0x1328, 0x1078, 0x1c52, + 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000, 0x1078, + 0x1ac6, 0x1078, 0x8a44, 0x0040, 0x18db, 0x6808, 0x8001, 0x680a, + 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff, + 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8758, 0x0078, 0x1aad, + 0x1078, 0x1328, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, 0x2b68, + 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, + 0x18be, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x18e0, 0x7000, + 0x0079, 0x18fa, 0x1902, 0x1904, 0x1a06, 0x1a84, 0x1a9b, 0x1902, + 0x1902, 0x1902, 0x1078, 0x1328, 0x8001, 0x7002, 0xa184, 0x0880, + 0x00c0, 0x1919, 0x8aff, 0x0040, 0x199b, 0x2009, 0x0001, 0x1078, + 0x1824, 0x0040, 0x1aad, 0x2009, 0x0001, 0x1078, 0x1824, 0x0078, + 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0, 0x1979, + 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1930, 0x7c20, 0x7d24, + 0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1932, + 0x1078, 0x1b9f, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, + 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060, 0x6024, + 0xd0f4, 0x00c0, 0x1945, 0x633a, 0x6236, 0x0c7f, 0x2400, 0x6910, + 0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f, 0x027f, + 0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x1fea, 0x2a00, 0x6826, + 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, 0x6808, + 0x8001, 0x680a, 0x00c0, 0x196e, 0x684c, 0xd0e4, 0x0040, 0x196e, + 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x756c, 0x7000, 0xa086, + 0x0004, 0x0040, 0x1aad, 0x7003, 0x0000, 0x1078, 0x179f, 0x0078, + 0x1aad, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x1980, 0x1078, 0xa20c, + 0x057f, 0x1078, 0x1ac6, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4893, + 0x0040, 0x198d, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff, + 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, + 0x6916, 0x0078, 0x1aad, 0x7004, 0x0c7e, 0x2060, 0x6024, 0x0c7f, + 0xd0f4, 0x0040, 0x19a8, 0x6808, 0x8001, 0x680a, 0x0078, 0x1aad, + 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19c0, 0x7003, + 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19bc, 0x7004, 0x2060, + 0x2009, 0x0048, 0x1078, 0x756c, 0x1078, 0x179f, 0x0078, 0x1aad, + 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816, + 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214, + 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, + 0x810b, 0x1078, 0x1b4d, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, + 0x0001, 0x7804, 0xd0fc, 0x0040, 0x19e1, 0x7803, 0x0002, 0x7803, + 0x0004, 0x780f, 0x0076, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, + 0x0048, 0x1078, 0x756c, 0x1078, 0x1b81, 0x0040, 0x19bc, 0x7908, + 0xd1ec, 0x00c0, 0x19ff, 0x2009, 0x0009, 0x0078, 0x1a01, 0x2009, + 0x0019, 0x7902, 0x7003, 0x0003, 0x0078, 0x1aad, 0x8001, 0x7002, + 0xd194, 0x0040, 0x1a18, 0x7804, 0xd0fc, 0x00c0, 0x18ea, 0x8aff, + 0x0040, 0x1aad, 0x2009, 0x0001, 0x1078, 0x1824, 0x0078, 0x1aad, + 0xa184, 0x0880, 0x00c0, 0x1a25, 0x8aff, 0x0040, 0x1aad, 0x2009, + 0x0001, 0x1078, 0x1824, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, + 0x0000, 0xd1bc, 0x00c0, 0x1a65, 0x027e, 0x037e, 0x7808, 0xd0ec, + 0x00c0, 0x1a38, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a3a, + 0x1078, 0x1b9f, 0x6b28, 0x6a2c, 0x1078, 0x1fea, 0x0d7e, 0x0f7e, + 0x2d78, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a55, 0x6808, + 0x2008, 0xa31a, 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, + 0x7814, 0xa101, 0x7816, 0x0078, 0x1a61, 0x6810, 0x2008, 0xa31a, + 0x6814, 0xa213, 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, + 0x7816, 0x0f7f, 0x0d7f, 0x0078, 0x1934, 0x057e, 0x7d0c, 0x1078, + 0xa20c, 0x057f, 0x1078, 0x1ac6, 0x0f7e, 0x7004, 0x2078, 0x1078, + 0x4893, 0x0040, 0x1a76, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, + 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, + 0x6980, 0x6916, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, + 0x7004, 0xa00d, 0x0040, 0x1a97, 0x6808, 0x8001, 0x680a, 0x00c0, + 0x1a97, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x756c, 0x1078, + 0x179f, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, + 0x2060, 0x6010, 0xa005, 0x0040, 0x1a97, 0x2068, 0x6808, 0x8000, + 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x17be, 0x017f, 0x007f, 0x127f, + 0x007c, 0x127e, 0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0, + 0x1ac4, 0x700c, 0x7110, 0xa106, 0x0040, 0x1ac4, 0x20e1, 0x9028, + 0x700f, 0xa5e7, 0x7013, 0xa5e7, 0x127f, 0x007c, 0x0c7e, 0x1078, + 0x1af7, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1aed, + 0x2104, 0xa005, 0x0040, 0x1ada, 0x2060, 0x6010, 0x2060, 0x6008, + 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xa602, 0x0048, 0x1ae2, + 0x2009, 0xa5e7, 0x7112, 0x700c, 0xa106, 0x00c0, 0x1acb, 0x2001, + 0x0138, 0x2003, 0x0008, 0x0078, 0x1acb, 0x2001, 0x015d, 0x200c, + 0x810a, 0x2102, 0x2001, 0x0138, 0x2202, 0x0c7f, 0x007c, 0x2001, + 0x0138, 0x2014, 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141, + 0x201c, 0xd3dc, 0x00c0, 0x1b14, 0x2001, 0x0109, 0x201c, 0xa39c, + 0x0048, 0x00c0, 0x1b14, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0, + 0x1b14, 0x8421, 0x00c0, 0x1afe, 0x007c, 0x2011, 0x0201, 0x2009, + 0x003c, 0x2204, 0xa005, 0x00c0, 0x1b21, 0x8109, 0x00c0, 0x1b19, + 0x007c, 0x007c, 0x1078, 0x1b15, 0x0040, 0x1b4a, 0x7908, 0xd1ec, + 0x00c0, 0x1b3a, 0x1078, 0x1b81, 0x0040, 0x1b3a, 0x7803, 0x0009, + 0x7904, 0xd1fc, 0x0040, 0x1b30, 0x7803, 0x0006, 0x1078, 0x1b15, + 0x0040, 0x1b4a, 0x780c, 0xd0a4, 0x00c0, 0x1b4a, 0x7007, 0x0000, + 0x1078, 0x1b81, 0x0040, 0x1b4c, 0x7803, 0x0019, 0x7003, 0x0003, + 0x0078, 0x1b4c, 0x1078, 0x1ac6, 0x007c, 0x0e7e, 0x2071, 0x0200, + 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1af7, 0x2019, 0x5000, + 0x8319, 0x0040, 0x1b6b, 0x2001, 0xa602, 0x2004, 0xa086, 0x0000, + 0x0040, 0x1b6b, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b58, 0x1078, + 0x1e5d, 0x0078, 0x1b56, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028, + 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100, + 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, 0x0e7f, + 0x007c, 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x1b8c, + 0xa085, 0x0001, 0x0078, 0x1b9e, 0x2001, 0x020a, 0x81ff, 0x0040, + 0x1b97, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1, + 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x007c, 0x7c20, + 0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c24, + 0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c24, 0x0d7e, + 0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c22, 0x6824, 0xd0d4, + 0x00c0, 0x1c22, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x0040, 0x1bec, + 0x8108, 0x2104, 0x6b2c, 0xa306, 0x00c0, 0x1c22, 0x8108, 0x2104, + 0x6a28, 0xa206, 0x00c0, 0x1c22, 0x6850, 0xc0fc, 0xc0f5, 0x6852, + 0x686c, 0x7822, 0x6870, 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, + 0x6818, 0x2060, 0x6034, 0xd09c, 0x0040, 0x1be7, 0x6830, 0x2004, + 0xac68, 0x6808, 0x783a, 0x680c, 0x783e, 0x0078, 0x1c20, 0xa006, + 0x783a, 0x783e, 0x0078, 0x1c20, 0x8108, 0x2104, 0xa005, 0x00c0, + 0x1c22, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c22, 0x6850, 0xc0f5, + 0x6852, 0x6830, 0x2004, 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, + 0xd09c, 0x00c0, 0x1c12, 0x6008, 0x7822, 0x686e, 0x600c, 0x7826, + 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0xa006, 0x783a, 0x783e, + 0x0078, 0x1c20, 0x6010, 0x7822, 0x686e, 0x6014, 0x7826, 0x6872, + 0x6000, 0x7832, 0x6004, 0x7836, 0x6008, 0x783a, 0x600c, 0x783e, + 0x7803, 0x0011, 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e, + 0x027e, 0x2071, 0xa5e1, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, + 0xa086, 0x0000, 0x0040, 0x1c4d, 0x8211, 0x0040, 0x1c4b, 0x2001, + 0x0005, 0x2004, 0xd08c, 0x0040, 0x1c34, 0x7904, 0xa18c, 0x0780, + 0x017e, 0x1078, 0x18e2, 0x017f, 0x81ff, 0x00c0, 0x1c4b, 0x2011, + 0x0050, 0x0078, 0x1c2f, 0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f, + 0x0f7f, 0x007c, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, + 0x0040, 0x1ca3, 0x8109, 0x00c0, 0x1c56, 0x2009, 0x0100, 0x210c, + 0xa18a, 0x0003, 0x1048, 0x1328, 0x1078, 0x1f75, 0x0e7e, 0x0f7e, + 0x2071, 0xa5d0, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0040, + 0x1c9b, 0x7800, 0x007e, 0x7820, 0x007e, 0x7830, 0x007e, 0x7834, + 0x007e, 0x7838, 0x007e, 0x783c, 0x007e, 0x7803, 0x0004, 0x7823, + 0x0000, 0x0005, 0x0005, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0, + 0x1328, 0x2079, 0x0010, 0x007f, 0x783e, 0x007f, 0x783a, 0x007f, + 0x7836, 0x007f, 0x7832, 0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f, + 0x0e7f, 0x0078, 0x1ca1, 0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0, + 0x1328, 0x1078, 0x61d3, 0x007c, 0x0e7e, 0x2071, 0xa602, 0x7003, + 0x0000, 0x0e7f, 0x007c, 0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c, + 0xd1dc, 0x00c0, 0x1d26, 0x6934, 0xa184, 0x0007, 0x0079, 0x1cb8, + 0x1cc0, 0x1d11, 0x1cc0, 0x1cc0, 0x1cc0, 0x1cf6, 0x1cd3, 0x1cc2, + 0x1078, 0x1328, 0x684c, 0xd0b4, 0x0040, 0x1e34, 0x6860, 0x682e, + 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, + 0x6958, 0x0078, 0x1d19, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, + 0x00c0, 0x1cc0, 0x684c, 0xd0b4, 0x0040, 0x1e34, 0x6860, 0x682e, + 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, + 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, + 0x2015, 0x2004, 0x6832, 0x6958, 0x0078, 0x1d22, 0xa18c, 0x00ff, + 0xa186, 0x0015, 0x00c0, 0x1d26, 0x684c, 0xd0b4, 0x0040, 0x1e34, + 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, + 0x2015, 0x2004, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0078, + 0x1d22, 0x684c, 0xd0b4, 0x0040, 0x18bc, 0x6958, 0xa006, 0x682e, + 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2015, + 0x2004, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c, + 0x0f7e, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x10c0, 0x1e5d, 0x0e7e, + 0x0d7e, 0x2071, 0xa602, 0x7000, 0xa005, 0x00c0, 0x1dab, 0x0c7e, + 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, + 0x6818, 0x0d7e, 0x2068, 0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1, + 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, + 0x0f7f, 0x0d7f, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, + 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x2001, 0x04fd, 0x2004, + 0xa086, 0x0007, 0x0040, 0x1d6d, 0xa184, 0x0007, 0x0040, 0x1d6d, + 0x017e, 0x2009, 0x0008, 0xa102, 0x017f, 0xa108, 0x791a, 0x7116, + 0x701e, 0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, + 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x00c0, 0x1d84, 0x6928, + 0x6810, 0xa106, 0x0040, 0x1d91, 0x037e, 0x047e, 0x6b14, 0x6c10, + 0x1078, 0x2035, 0x047f, 0x037f, 0x0040, 0x1d91, 0x0c7f, 0x0078, + 0x1dab, 0x8aff, 0x00c0, 0x1d99, 0x0c7f, 0xa085, 0x0001, 0x0078, + 0x1dab, 0x127e, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, + 0x1078, 0x1daf, 0x0040, 0x1da8, 0x2009, 0x0001, 0x1078, 0x1daf, + 0x127f, 0x0c7f, 0xa006, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, + 0x067e, 0x057e, 0x047e, 0x037e, 0x027e, 0x8aff, 0x0040, 0x1e2d, + 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0048, 0x1e2c, + 0xa705, 0x0040, 0x1e2c, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, + 0x1ddf, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1dcf, 0x1e0e, + 0x1def, 0x1def, 0x1e0e, 0x1e0e, 0x1e06, 0x1e0e, 0x1def, 0x1e0e, + 0x1df5, 0x1df5, 0x1e0e, 0x1e0e, 0x1e0e, 0x1dfd, 0x1df5, 0xc0fc, + 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e12, + 0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x1e11, 0x6b08, + 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1e11, 0x6b10, 0x6a14, 0x6d00, + 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1e11, 0x0d7f, 0x0d7e, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1e0e, 0x0d7f, 0x1078, + 0x1fd1, 0x00c0, 0x1db5, 0xa00e, 0x0078, 0x1e2d, 0x0d7f, 0x1078, + 0x1328, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, + 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, + 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, + 0x1078, 0x1fd1, 0x0078, 0x1e2d, 0xa006, 0x027f, 0x037f, 0x047f, + 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x1328, 0x027e, 0x2001, + 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, + 0x0000, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, + 0x0040, 0x1e4d, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8758, + 0x20e1, 0x9040, 0x1078, 0x719a, 0x2011, 0x0000, 0x1078, 0x6efc, + 0x1078, 0x61d3, 0x027f, 0x0078, 0x1f29, 0x127e, 0x2091, 0x2200, + 0x007e, 0x017e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, + 0x2071, 0xa602, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, + 0xa184, 0x0700, 0x00c0, 0x1e36, 0x7000, 0x0079, 0x1e77, 0x1f29, + 0x1e7b, 0x1ef6, 0x1f27, 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1e8f, + 0x8aff, 0x0040, 0x1eae, 0x2009, 0x0001, 0x1078, 0x1daf, 0x0040, + 0x1f29, 0x2009, 0x0001, 0x1078, 0x1daf, 0x0078, 0x1f29, 0x7803, + 0x0004, 0xd194, 0x0040, 0x1e9f, 0x6850, 0xc0fc, 0x6852, 0x8aff, + 0x00c0, 0x1ea4, 0x684c, 0xc0f5, 0x684e, 0x0078, 0x1ea4, 0x1078, + 0x1fea, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, + 0x2800, 0x6832, 0x7003, 0x0000, 0x0078, 0x1f29, 0x711c, 0x81ff, + 0x0040, 0x1ec4, 0x7918, 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, + 0x7000, 0x8000, 0x7002, 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, + 0x0000, 0x7012, 0x0078, 0x1f29, 0x0f7e, 0x027e, 0x781c, 0x007e, + 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, + 0x0012, 0x7816, 0x037e, 0x2019, 0x1000, 0x8319, 0x1040, 0x1328, + 0x7820, 0xd0bc, 0x00c0, 0x1ed5, 0x037f, 0x79c8, 0x007f, 0xa102, + 0x017f, 0x007e, 0x017e, 0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f, + 0x78ca, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f, + 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1f29, 0x8001, 0x7002, + 0xd194, 0x0040, 0x1f0b, 0x7804, 0xd0fc, 0x00c0, 0x1e6d, 0xd19c, + 0x00c0, 0x1f25, 0x8aff, 0x0040, 0x1f29, 0x2009, 0x0001, 0x1078, + 0x1daf, 0x0078, 0x1f29, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078, + 0x1fea, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f1e, + 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1f22, 0x6810, 0xa31a, + 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1e9f, 0x0078, 0x1e9f, 0x1078, + 0x1328, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f, + 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0xa602, 0x7000, 0xa086, 0x0000, + 0x0040, 0x1f72, 0x2079, 0x0020, 0x017e, 0x2009, 0x0207, 0x210c, + 0xd194, 0x0040, 0x1f4f, 0x2009, 0x020c, 0x210c, 0xa184, 0x0003, + 0x0040, 0x1f4f, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, 0x2009, + 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x00c0, 0x1f5a, + 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0040, 0x1f3d, 0x1078, 0x1e5d, + 0x7000, 0xa086, 0x0000, 0x00c0, 0x1f3d, 0x017f, 0x7803, 0x0004, + 0x7804, 0xd0ac, 0x00c0, 0x1f68, 0x20e1, 0x9040, 0x7803, 0x0002, + 0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e, + 0x0e7e, 0x0f7e, 0x2071, 0xa602, 0x2079, 0x0020, 0x7000, 0xa086, + 0x0000, 0x0040, 0x1fae, 0x7004, 0x2060, 0x6010, 0x2068, 0x1078, + 0x8a44, 0x0040, 0x1f98, 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, + 0xa206, 0x00c0, 0x1f98, 0x6808, 0x7a18, 0xa206, 0x0040, 0x1fb4, + 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, + 0x7003, 0x0000, 0x7004, 0x2060, 0x1078, 0x8758, 0x20e1, 0x9040, + 0x1078, 0x719a, 0x2011, 0x0000, 0x1078, 0x6efc, 0x0f7f, 0x0e7f, + 0x0d7f, 0x0c7f, 0x027f, 0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0, + 0x1f98, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x1078, 0x1cab, 0x2001, + 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, + 0x0000, 0x2069, 0xa5ab, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, + 0x1fae, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1fe5, 0x6004, 0xa005, + 0x0040, 0x1fe7, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, + 0x2015, 0x2044, 0x88ff, 0x1040, 0x1328, 0x8a51, 0x007c, 0x2051, + 0x0000, 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x2004, + 0x2c00, 0xad06, 0x0040, 0x1ff9, 0x6000, 0xa005, 0x00c0, 0x1ff9, + 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x2025, + 0x2044, 0x88ff, 0x1040, 0x1328, 0x007c, 0x0000, 0x0011, 0x0015, + 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, + 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x200a, 0x2006, + 0x0000, 0x0000, 0x2014, 0x0000, 0x200a, 0x0000, 0x2011, 0x200e, + 0x0000, 0x0000, 0x0000, 0x2014, 0x2011, 0x0000, 0x200c, 0x200c, + 0x0000, 0x0000, 0x2014, 0x0000, 0x200c, 0x0000, 0x2012, 0x2012, + 0x0000, 0x0000, 0x0000, 0x2014, 0x2012, 0x0a7e, 0x097e, 0x087e, + 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0040, 0x20d8, 0x2d60, 0x6034, + 0xa0cc, 0x000f, 0xa9c0, 0x2015, 0xa986, 0x0007, 0x0040, 0x2050, + 0xa986, 0x000e, 0x0040, 0x2050, 0xa986, 0x000f, 0x00c0, 0x2054, + 0x605c, 0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x2062, + 0x0050, 0x205c, 0x0078, 0x20d8, 0x6004, 0xa065, 0x0040, 0x20d8, + 0x0078, 0x203f, 0x2804, 0xa005, 0x0040, 0x2080, 0xac68, 0xd99c, + 0x00c0, 0x2070, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x2074, + 0x6810, 0xa422, 0x6814, 0xa31b, 0x0048, 0x209f, 0x2300, 0xa405, + 0x0040, 0x2086, 0x8a51, 0x0040, 0x20d8, 0x8840, 0x0078, 0x2062, + 0x6004, 0xa065, 0x0040, 0x20d8, 0x0078, 0x203f, 0x8a51, 0x0040, + 0x20d8, 0x8840, 0x2804, 0xa005, 0x00c0, 0x2099, 0x6004, 0xa065, + 0x0040, 0x20d8, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2015, 0x2804, + 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0078, 0x20cc, 0x8422, + 0x8420, 0x831a, 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, + 0x0d7f, 0xd99c, 0x00c0, 0x20ba, 0x6908, 0x2400, 0xa122, 0x690c, + 0x2300, 0xa11b, 0x1048, 0x1328, 0x6800, 0xa420, 0x6804, 0xa319, + 0x0078, 0x20c6, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, + 0x1048, 0x1328, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, + 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, + 0x2a00, 0x6826, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x20dd, + 0x087f, 0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, + 0x2004, 0xa084, 0x0007, 0x0079, 0x20e5, 0x20ed, 0x20ee, 0x20f1, + 0x20f4, 0x20f9, 0x20fc, 0x2101, 0x2106, 0x007c, 0x1078, 0x1e5d, + 0x007c, 0x1078, 0x18e2, 0x007c, 0x1078, 0x18e2, 0x1078, 0x1e5d, + 0x007c, 0x1078, 0x14b0, 0x007c, 0x1078, 0x1e5d, 0x1078, 0x14b0, + 0x007c, 0x1078, 0x18e2, 0x1078, 0x14b0, 0x007c, 0x1078, 0x18e2, + 0x1078, 0x1e5d, 0x1078, 0x14b0, 0x007c, 0x127e, 0x2091, 0x2300, + 0x2079, 0x0200, 0x2071, 0xa880, 0x2069, 0xa300, 0x2009, 0x0004, + 0x7912, 0x7817, 0x0004, 0x1078, 0x24b5, 0x781b, 0x0002, 0x20e1, + 0x8700, 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, + 0x0007, 0x0079, 0x212b, 0x214f, 0x2133, 0x2137, 0x213b, 0x2141, + 0x2145, 0x2149, 0x214d, 0x1078, 0x5372, 0x0078, 0x214f, 0x1078, + 0x53b3, 0x0078, 0x214f, 0x1078, 0x5372, 0x1078, 0x53b3, 0x0078, + 0x214f, 0x1078, 0x2151, 0x0078, 0x214f, 0x1078, 0x2151, 0x0078, + 0x214f, 0x1078, 0x2151, 0x0078, 0x214f, 0x1078, 0x2151, 0x127f, + 0x007c, 0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040, + 0x215d, 0x20e1, 0x9040, 0x0078, 0x2186, 0xa184, 0x0030, 0x0040, + 0x216e, 0x6a00, 0xa286, 0x0003, 0x00c0, 0x2168, 0x0078, 0x216a, + 0x1078, 0x4171, 0x20e1, 0x9010, 0x0078, 0x2186, 0xa184, 0x00c0, + 0x0040, 0x2180, 0x0e7e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa5e1, + 0x1078, 0x1ac6, 0x057f, 0x047f, 0x037f, 0x0e7f, 0x0078, 0x2186, + 0xa184, 0x0300, 0x0040, 0x2186, 0x20e1, 0x9020, 0x7932, 0x027f, + 0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, 0xa300, + 0x7128, 0x2001, 0xa58f, 0x2102, 0x2001, 0xa597, 0x2102, 0xa182, + 0x0211, 0x00c8, 0x219f, 0x2009, 0x0008, 0x0078, 0x21c9, 0xa182, + 0x0259, 0x00c8, 0x21a7, 0x2009, 0x0007, 0x0078, 0x21c9, 0xa182, + 0x02c1, 0x00c8, 0x21af, 0x2009, 0x0006, 0x0078, 0x21c9, 0xa182, + 0x0349, 0x00c8, 0x21b7, 0x2009, 0x0005, 0x0078, 0x21c9, 0xa182, + 0x0421, 0x00c8, 0x21bf, 0x2009, 0x0004, 0x0078, 0x21c9, 0xa182, + 0x0581, 0x00c8, 0x21c7, 0x2009, 0x0003, 0x0078, 0x21c9, 0x2009, + 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x1078, 0x24b5, + 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061, + 0x0100, 0x2071, 0xa300, 0x6024, 0x6026, 0x6053, 0x0030, 0x6033, + 0x00ef, 0x60e7, 0x0000, 0x60eb, 0x00ef, 0x60e3, 0x0008, 0x604b, + 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, + 0x0eaf, 0x600f, 0x00ff, 0x602b, 0x002f, 0x127f, 0x007c, 0x2001, + 0xa32f, 0x2003, 0x0000, 0x2001, 0xa32e, 0x2003, 0x0001, 0x007c, + 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184, + 0x002c, 0x00c0, 0x220f, 0xa184, 0x0007, 0x0079, 0x2215, 0xa195, + 0x0004, 0xa284, 0x0007, 0x0079, 0x2215, 0x2241, 0x221d, 0x2221, + 0x2225, 0x222b, 0x222f, 0x2235, 0x223b, 0x1078, 0x5ad2, 0x0078, + 0x2241, 0x1078, 0x5bc1, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078, + 0x5ad2, 0x0078, 0x2241, 0x1078, 0x2246, 0x0078, 0x2241, 0x1078, + 0x5ad2, 0x1078, 0x2246, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078, + 0x2246, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078, 0x5ad2, 0x1078, + 0x2246, 0x027f, 0x017f, 0x007f, 0x127f, 0x007c, 0x6124, 0xd1ac, + 0x0040, 0x2342, 0x017e, 0x047e, 0x0c7e, 0x644c, 0xa486, 0xf0f0, + 0x00c0, 0x2259, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, + 0x0010, 0x74c2, 0xa48c, 0xff00, 0x7034, 0xd084, 0x0040, 0x2271, + 0xa186, 0xf800, 0x00c0, 0x2271, 0x7038, 0xd084, 0x00c0, 0x2271, + 0xc085, 0x703a, 0x037e, 0x2418, 0x2011, 0x8016, 0x1078, 0x3579, + 0x037f, 0xa196, 0xff00, 0x0040, 0x22b3, 0x6030, 0xa084, 0x00ff, + 0x810f, 0xa116, 0x0040, 0x22b3, 0x7130, 0xd184, 0x00c0, 0x22b3, + 0x2011, 0xa352, 0x2214, 0xd2ec, 0x0040, 0x228e, 0xc18d, 0x7132, + 0x2011, 0xa352, 0x2214, 0xd2ac, 0x00c0, 0x22b3, 0x6240, 0xa294, + 0x0010, 0x0040, 0x229a, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, + 0x0040, 0x22b3, 0x7030, 0xd08c, 0x0040, 0x2305, 0x7034, 0xd08c, + 0x00c0, 0x22aa, 0x2001, 0xa30c, 0x200c, 0xd1ac, 0x00c0, 0x2305, + 0xc1ad, 0x2102, 0x037e, 0x73c0, 0x2011, 0x8013, 0x1078, 0x3579, + 0x037f, 0x0078, 0x2305, 0x7034, 0xd08c, 0x00c0, 0x22bf, 0x2001, + 0xa30c, 0x200c, 0xd1ac, 0x00c0, 0x2305, 0xc1ad, 0x2102, 0x037e, + 0x73c0, 0x2011, 0x8013, 0x1078, 0x3579, 0x037f, 0x7130, 0xc185, + 0x7132, 0x2011, 0xa352, 0x220c, 0xd1a4, 0x0040, 0x22e9, 0x017e, + 0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x5a6d, 0x2019, 0x000e, + 0x1078, 0x9e3b, 0xa484, 0x00ff, 0xa080, 0x293f, 0x200c, 0xa18c, + 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x1078, 0x9ec0, + 0x017f, 0xd1ac, 0x00c0, 0x22f6, 0x017e, 0x2009, 0x0000, 0x2019, + 0x0004, 0x1078, 0x27e2, 0x017f, 0x0078, 0x2305, 0x157e, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x1078, 0x4501, 0x00c0, 0x2301, 0x1078, + 0x4235, 0x8108, 0x00f0, 0x22fb, 0x157f, 0x0c7f, 0x047f, 0x0f7e, + 0x2079, 0xa5be, 0x783c, 0xa086, 0x0000, 0x0040, 0x2317, 0x6027, + 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x0000, 0x0f7f, + 0x2011, 0x0003, 0x1078, 0x6ef2, 0x2011, 0x0002, 0x1078, 0x6efc, + 0x1078, 0x6dda, 0x1078, 0x595a, 0x037e, 0x2019, 0x0000, 0x1078, + 0x6e6c, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, 0xa300, 0x2014, + 0xa296, 0x0004, 0x00c0, 0x233a, 0xd19c, 0x00c0, 0x233a, 0x6228, + 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa321, 0x2003, 0x0000, + 0x6027, 0x0020, 0xd194, 0x0040, 0x2426, 0x0f7e, 0x2079, 0xa5be, + 0x783c, 0xa086, 0x0001, 0x00c0, 0x2366, 0x017e, 0x6027, 0x0004, + 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000, 0x7803, 0x0000, + 0x2079, 0xa5ab, 0x7807, 0x0000, 0x7833, 0x0000, 0x1078, 0x6109, + 0x1078, 0x61d3, 0x017f, 0x0f7f, 0x0078, 0x2426, 0x0f7f, 0x017e, + 0x3900, 0xa082, 0xa6cd, 0x00c8, 0x2371, 0x017e, 0x1078, 0x728a, + 0x017f, 0x6220, 0xd2b4, 0x0040, 0x23dc, 0x1078, 0x595a, 0x1078, + 0x6c41, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa5b4, 0x2304, 0xa07d, + 0x0040, 0x23b2, 0x7804, 0xa086, 0x0032, 0x00c0, 0x23b2, 0x0d7e, + 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, + 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x00c0, + 0x2396, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, + 0x628a, 0x1078, 0x6010, 0x1078, 0x6109, 0x7810, 0x2070, 0x7037, + 0x0103, 0x2f60, 0x1078, 0x753d, 0x0e7f, 0x0c7f, 0x0d7f, 0x0f7f, + 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, + 0x4000, 0x0040, 0x23bf, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, + 0x0c7e, 0x2061, 0xa5ab, 0x6028, 0xa09a, 0x00c8, 0x00c8, 0x23cf, + 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6c33, 0x0078, 0x2425, 0x2019, + 0xa5b4, 0x2304, 0xa065, 0x0040, 0x23d9, 0x2009, 0x0027, 0x1078, + 0x756c, 0x0c7f, 0x0078, 0x2425, 0xd2bc, 0x0040, 0x2425, 0x1078, + 0x5967, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140, + 0x6804, 0xa084, 0x4000, 0x0040, 0x23f1, 0x6803, 0x1000, 0x6803, + 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa5ab, 0x6044, 0xa09a, 0x00c8, + 0x00c8, 0x2414, 0x8000, 0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040, + 0x2425, 0x2009, 0x07d0, 0x1078, 0x595f, 0xa080, 0x0007, 0x2004, + 0xa086, 0x0006, 0x00c0, 0x2410, 0x6017, 0x0012, 0x0078, 0x2425, + 0x6017, 0x0016, 0x0078, 0x2425, 0x037e, 0x2019, 0x0001, 0x1078, + 0x6e6c, 0x037f, 0x2019, 0xa5ba, 0x2304, 0xa065, 0x0040, 0x2424, + 0x2009, 0x004f, 0x1078, 0x756c, 0x0c7f, 0x017f, 0xd19c, 0x0040, + 0x247c, 0x7034, 0xd0ac, 0x00c0, 0x2457, 0x017e, 0x157e, 0x6027, + 0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0, 0x2435, 0x602f, + 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0320, 0x00e0, + 0x243f, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0, 0x244e, 0x157f, + 0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x247c, 0x1078, 0x250d, + 0x00f0, 0x243f, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x017e, + 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, 0x6ef2, 0x2011, + 0x0002, 0x1078, 0x6efc, 0x1078, 0x6dda, 0x1078, 0x595a, 0x037e, + 0x2019, 0x0000, 0x1078, 0x6e6c, 0x037f, 0x60e3, 0x0000, 0x1078, + 0xa22a, 0x1078, 0xa248, 0x2001, 0xa300, 0x2003, 0x0004, 0x6027, + 0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c, + 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000, + 0x2071, 0xa300, 0x71b8, 0x70ba, 0xa116, 0x0040, 0x24ae, 0x81ff, + 0x0040, 0x2498, 0x2011, 0x8011, 0x1078, 0x3579, 0x0078, 0x24ae, + 0x2011, 0x8012, 0x1078, 0x3579, 0x2001, 0xa371, 0x2004, 0xd0fc, + 0x00c0, 0x24ae, 0x037e, 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028, + 0x2009, 0x0000, 0x1078, 0x27e2, 0x0c7f, 0x037f, 0x127f, 0x0f7f, + 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x0f7e, 0x007e, + 0x027e, 0x2061, 0x0100, 0xa190, 0x24d1, 0x2204, 0x60f2, 0x2011, + 0x24de, 0x6000, 0xa082, 0x0003, 0x00c8, 0x24ca, 0x2001, 0x00ff, + 0x0078, 0x24cb, 0x2204, 0x60ee, 0x027f, 0x007f, 0x0f7f, 0x0c7f, + 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0, + 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8, + 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094, + 0xff00, 0x00c0, 0x24ee, 0x81ff, 0x0040, 0x24f2, 0x1078, 0x5623, + 0x0078, 0x24f9, 0xa080, 0x293f, 0x200c, 0xa18c, 0xff00, 0x810f, + 0xa006, 0x007c, 0xa080, 0x293f, 0x200c, 0xa18c, 0x00ff, 0x007c, + 0x0c7e, 0x2061, 0xa300, 0x6030, 0x0040, 0x2509, 0xc09d, 0x0078, + 0x250a, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e, 0x157e, 0x0f7e, + 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x00c0, 0x251a, + 0x00f0, 0x2514, 0x0f7f, 0x157f, 0x007f, 0x007c, 0x0c7e, 0x007e, + 0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e, 0x60e4, 0x007e, + 0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e, 0x60ec, 0x007e, + 0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e, 0x60e0, 0x007e, + 0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005, 0x0005, 0x0005, + 0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2, 0x007f, 0x602a, + 0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee, 0x007f, 0x60f2, + 0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6, 0x007f, 0x604a, + 0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x257d, 0x2581, 0x2585, + 0x258b, 0x2591, 0x2597, 0x259d, 0x25a5, 0x25ad, 0x25b3, 0x25b9, + 0x25c1, 0x25c9, 0x25d1, 0x25d9, 0x25e3, 0x25ed, 0x25ed, 0x25ed, + 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, + 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x107e, 0x007e, 0x0078, + 0x2606, 0x107e, 0x007e, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, + 0x2200, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x0078, + 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, + 0x007e, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, + 0x2200, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, + 0x2200, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, + 0x2123, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2123, 0x0078, + 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x2123, 0x0078, + 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x2123, 0x0078, + 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x1078, 0x2123, 0x0078, + 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x1078, 0x2123, 0x0078, + 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x20de, 0x1078, + 0x2123, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, + 0x20de, 0x1078, 0x2123, 0x0078, 0x2606, 0x0005, 0x0078, 0x25ed, + 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x25f6, 0x2606, 0x2583, + 0x2587, 0x258d, 0x2593, 0x2599, 0x259f, 0x25a7, 0x25af, 0x25b5, + 0x25bb, 0x25c3, 0x25cb, 0x25d3, 0x25db, 0x25e5, 0x0008, 0x25f0, + 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, 0x027e, 0x047e, + 0x2021, 0x0000, 0x1078, 0x4897, 0x00c0, 0x2705, 0x70c8, 0xd09c, + 0x0040, 0x2624, 0xd084, 0x00c0, 0x2624, 0xd0bc, 0x00c0, 0x2705, + 0x1078, 0x2709, 0x0078, 0x2705, 0xd094, 0x0040, 0x262b, 0x7093, + 0xffff, 0x0078, 0x2705, 0x2001, 0x010c, 0x203c, 0x7280, 0xd284, + 0x0040, 0x2694, 0xd28c, 0x00c0, 0x2694, 0x037e, 0x7390, 0xa38e, + 0xffff, 0x0040, 0x263e, 0x83ff, 0x00c0, 0x2640, 0x2019, 0x0001, + 0x8314, 0xa2e0, 0xa9c0, 0x2c04, 0xa38c, 0x0001, 0x0040, 0x264d, + 0xa084, 0xff00, 0x8007, 0x0078, 0x264f, 0xa084, 0x00ff, 0xa70e, + 0x0040, 0x2689, 0xa08e, 0x0000, 0x0040, 0x2689, 0xa08e, 0x00ff, + 0x00c0, 0x2666, 0x7230, 0xd284, 0x00c0, 0x268f, 0x7280, 0xc28d, + 0x7282, 0x7093, 0xffff, 0x037f, 0x0078, 0x2694, 0x2009, 0x0000, + 0x1078, 0x24e3, 0x1078, 0x4499, 0x00c0, 0x268c, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2683, 0x7030, 0xd08c, 0x0040, + 0x267d, 0x6000, 0xd0bc, 0x0040, 0x2683, 0x1078, 0x271f, 0x0040, + 0x268c, 0x0078, 0x2689, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040, + 0x268c, 0x8318, 0x0078, 0x2640, 0x7392, 0x0078, 0x2691, 0x7093, + 0xffff, 0x037f, 0x0078, 0x2705, 0xa780, 0x293f, 0x203c, 0xa7bc, + 0xff00, 0x873f, 0x2041, 0x007e, 0x7090, 0xa096, 0xffff, 0x00c0, + 0x26a6, 0x2009, 0x0000, 0x28a8, 0x0078, 0x26b2, 0xa812, 0x0048, + 0x26ae, 0x2008, 0xa802, 0x20a8, 0x0078, 0x26b2, 0x7093, 0xffff, + 0x0078, 0x2705, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040, 0x26f9, + 0xc484, 0x1078, 0x4501, 0x0040, 0x26c3, 0x1078, 0x4499, 0x00c0, + 0x2702, 0x0078, 0x26c4, 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x00c0, 0x26d3, 0x7030, 0xd08c, 0x0040, 0x26f1, 0x6000, + 0xd0bc, 0x00c0, 0x26f1, 0x7280, 0xd28c, 0x0040, 0x26e9, 0x6004, + 0xa084, 0x00ff, 0xa082, 0x0006, 0x0048, 0x26f9, 0xd484, 0x00c0, + 0x26e5, 0x1078, 0x44bc, 0x0078, 0x26e7, 0x1078, 0x2921, 0x0078, + 0x26f9, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040, 0x2702, 0x0078, + 0x26f9, 0x1078, 0x28ec, 0x0040, 0x26f9, 0x1078, 0x271f, 0x0040, + 0x2702, 0x017f, 0x8108, 0x157f, 0x00f0, 0x26b2, 0x7093, 0xffff, + 0x0078, 0x2705, 0x017f, 0x157f, 0x7192, 0x047f, 0x027f, 0x0c7f, + 0x007c, 0x0c7e, 0x017e, 0x7093, 0x0000, 0x2009, 0x007e, 0x1078, + 0x4499, 0x00c0, 0x271c, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040, + 0x271c, 0x70c8, 0xc0bd, 0x70ca, 0x017f, 0x0c7f, 0x007c, 0x017e, + 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa356, 0x2004, 0xa084, + 0x00ff, 0x6842, 0x1078, 0x74d7, 0x0040, 0x2747, 0x2d00, 0x601a, + 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0000, + 0x1078, 0x443f, 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e, + 0x127f, 0x2009, 0x0004, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, + 0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, + 0x2c68, 0x2001, 0xa356, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, + 0x74d7, 0x0040, 0x2785, 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, + 0x68a0, 0xa086, 0x007e, 0x0040, 0x276e, 0x6804, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x00c0, 0x276e, 0x1078, 0x2813, 0x601f, 0x0001, + 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f, + 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e, 0x127f, 0x2009, + 0x0002, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, + 0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009, 0x0080, 0x1078, 0x4499, + 0x00c0, 0x2798, 0x1078, 0x279b, 0x0040, 0x2798, 0x70cf, 0xffff, + 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, + 0x1078, 0x74d7, 0x0040, 0x27bd, 0x2d00, 0x601a, 0x601f, 0x0001, + 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f, + 0x127e, 0x2091, 0x8000, 0x70d0, 0x8000, 0x70d2, 0x127f, 0x2009, + 0x0002, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, + 0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009, + 0x007f, 0x1078, 0x4499, 0x00c0, 0x27de, 0x2c68, 0x1078, 0x74d7, + 0x0040, 0x27de, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, + 0x2009, 0x0022, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0d7f, + 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, + 0x5d60, 0x1078, 0x5d02, 0x1078, 0x7ddf, 0x2130, 0x81ff, 0x0040, + 0x27f7, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0078, 0x27fb, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, 0x2804, + 0x1078, 0x471b, 0x1078, 0x4235, 0x017f, 0x8108, 0x00f0, 0x27fb, + 0x86ff, 0x00c0, 0x280d, 0x1078, 0x119b, 0x027f, 0x037f, 0x067f, + 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, + 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x5d53, + 0x077e, 0x2039, 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, + 0x077f, 0x017f, 0x2e60, 0x1078, 0x471b, 0x6210, 0x6314, 0x1078, + 0x4235, 0x6212, 0x6316, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, + 0x007c, 0x0e7e, 0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, + 0x00c0, 0x284d, 0x2071, 0xa300, 0x708c, 0xa005, 0x0040, 0x284a, + 0x8001, 0x708e, 0x007f, 0x0e7f, 0x007c, 0x2071, 0xa300, 0x70d0, + 0xa005, 0x0040, 0x284a, 0x8001, 0x70d2, 0x0078, 0x284a, 0x6000, + 0xc08c, 0x6002, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e, + 0x017e, 0x157e, 0x2178, 0x81ff, 0x00c0, 0x286a, 0x20a9, 0x0001, + 0x0078, 0x2885, 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x2881, + 0xd0a4, 0x0040, 0x2881, 0x047e, 0x6018, 0xa080, 0x0028, 0x2024, + 0xa4a4, 0x00ff, 0x8427, 0xa006, 0x2009, 0x002d, 0x1078, 0x9ec0, + 0x047f, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x027e, 0xa28e, 0x007e, + 0x0040, 0x28c9, 0xa28e, 0x007f, 0x0040, 0x28c9, 0xa28e, 0x0080, + 0x0040, 0x28c9, 0xa288, 0xa434, 0x210c, 0x81ff, 0x0040, 0x28c9, + 0x8fff, 0x1040, 0x28d5, 0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078, + 0x48a2, 0x0c7f, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, + 0x0000, 0x1078, 0x5c78, 0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294, + 0x00ff, 0xa286, 0x0006, 0x00c0, 0x28b9, 0x6007, 0x0404, 0x0078, + 0x28be, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f, + 0x017e, 0x2c08, 0x1078, 0x9c38, 0x017f, 0x077f, 0x2160, 0x1078, + 0x471b, 0x027f, 0x8210, 0x00f0, 0x2885, 0x157f, 0x017f, 0x027f, + 0x037f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e, + 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x28e8, 0xd0a4, 0x0040, + 0x28e8, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x1078, 0x9ec0, + 0x017f, 0x027f, 0x047f, 0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e, + 0x7280, 0x82ff, 0x0040, 0x291a, 0xa290, 0xa352, 0x2214, 0xd2ac, + 0x00c0, 0x291a, 0x2100, 0x1078, 0x24fa, 0x81ff, 0x0040, 0x291c, + 0x2019, 0x0001, 0x8314, 0xa2e0, 0xa9c0, 0x2c04, 0xd384, 0x0040, + 0x290e, 0xa084, 0xff00, 0x8007, 0x0078, 0x2910, 0xa084, 0x00ff, + 0xa116, 0x0040, 0x291c, 0xa096, 0x00ff, 0x0040, 0x291a, 0x8318, + 0x0078, 0x2902, 0xa085, 0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f, + 0x007c, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0xa180, 0xa434, + 0x2004, 0xa065, 0x0040, 0x293b, 0x017e, 0x0c7e, 0x1078, 0x8ec0, + 0x017f, 0x1040, 0x1328, 0x611a, 0x1078, 0x2813, 0x1078, 0x753d, + 0x017f, 0x1078, 0x44bc, 0x127f, 0x0c7f, 0x017f, 0x007c, 0x7eef, + 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, + 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, + 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, + 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, + 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, + 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, + 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, + 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, + 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, + 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, + 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, + 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, + 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, + 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, + 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, + 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, + 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, + 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, + 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, + 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, + 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, + 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, + 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, + 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, + 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, + 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, + 0xa381, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, + 0x7033, 0xa391, 0x7037, 0xa391, 0x7007, 0x0001, 0x2061, 0xa3d1, + 0x6003, 0x0002, 0x007c, 0x0090, 0x2a66, 0x0068, 0x2a66, 0x2071, + 0xa381, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2a66, 0x2a60, 0x7820, + 0xa08e, 0x0069, 0x00c0, 0x2b56, 0x0079, 0x2aea, 0x007c, 0x2071, + 0xa381, 0x7004, 0x0079, 0x2a6c, 0x2a70, 0x2a71, 0x2a7b, 0x2a8d, + 0x007c, 0x0090, 0x2a7a, 0x0068, 0x2a7a, 0x2b78, 0x7818, 0xd084, + 0x0040, 0x2a99, 0x007c, 0x2b78, 0x2061, 0xa3d1, 0x6008, 0xa08e, + 0x0100, 0x0040, 0x2a88, 0xa086, 0x0200, 0x0040, 0x2b4e, 0x007c, + 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, 0x6834, + 0xa086, 0x0103, 0x0040, 0x2a95, 0x007c, 0x2a60, 0x2b78, 0x7018, + 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2aa2, 0x61b8, + 0x0079, 0x2aaa, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2b4a, 0x61b8, + 0x0079, 0x2aea, 0x2b2c, 0x2b5e, 0x2b66, 0x2b6a, 0x2b72, 0x2b78, + 0x2b7c, 0x2b88, 0x2b8c, 0x2b96, 0x2b9a, 0x2b4a, 0x2b4a, 0x2b4a, + 0x2b9e, 0x2b4a, 0x2bae, 0x2bc5, 0x2bdc, 0x2c58, 0x2c5d, 0x2c8a, + 0x2ce4, 0x2cf5, 0x2d13, 0x2d54, 0x2d5e, 0x2d6b, 0x2d7e, 0x2d9d, + 0x2da6, 0x2de3, 0x2de9, 0x2b4a, 0x2e05, 0x2b4a, 0x2b4a, 0x2b4a, + 0x2b4a, 0x2b4a, 0x2e0c, 0x2e16, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, + 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2e1e, 0x2b4a, 0x2b4a, 0x2b4a, + 0x2b4a, 0x2b4a, 0x2e30, 0x2e47, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, + 0x2b4a, 0x2b4a, 0x2e59, 0x2eb0, 0x2f0e, 0x2f1f, 0x2b4a, 0x2b4a, + 0x2b4a, 0x38f1, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, + 0x2b4a, 0x2b4a, 0x2b96, 0x2b9a, 0x2f36, 0x2b4a, 0x2f43, 0x397d, + 0x39da, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, + 0x2b4a, 0x2b4a, 0x2f90, 0x30c5, 0x30e1, 0x30ed, 0x3150, 0x31a9, + 0x31b4, 0x31f3, 0x3202, 0x3211, 0x3214, 0x2f47, 0x3238, 0x3284, + 0x3291, 0x33a2, 0x34cd, 0x34f7, 0x3604, 0x3614, 0x3621, 0x365b, + 0x372a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x3792, 0x37ae, 0x3828, + 0x38e2, 0x713c, 0x0078, 0x2b2c, 0x2021, 0x4000, 0x1078, 0x3553, + 0x127e, 0x2091, 0x8000, 0x0068, 0x2b39, 0x7818, 0xd084, 0x0040, + 0x2b3c, 0x127f, 0x0078, 0x2b30, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, + 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, + 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2b2e, 0x2021, 0x4002, + 0x0078, 0x2b2e, 0x2021, 0x4003, 0x0078, 0x2b2e, 0x2021, 0x4005, + 0x0078, 0x2b2e, 0x2021, 0x4006, 0x0078, 0x2b2e, 0xa02e, 0x2520, + 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3562, 0x7823, 0x0004, + 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, + 0x0078, 0x3566, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2b2c, + 0x7924, 0x2114, 0x0078, 0x2b2c, 0x2099, 0x0009, 0x20a1, 0x0009, + 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078, 0x2b2c, + 0x7824, 0x2060, 0x0078, 0x2ba0, 0x2009, 0x0001, 0x2011, 0x0013, + 0x2019, 0x0010, 0x783b, 0x0017, 0x0078, 0x2b2c, 0x7d38, 0x7c3c, + 0x0078, 0x2b60, 0x7d38, 0x7c3c, 0x0078, 0x2b6c, 0x2061, 0x1000, + 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, 0x2ba2, + 0x2010, 0xa005, 0x0040, 0x2b2c, 0x0078, 0x2b52, 0x2069, 0xa351, + 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2b5a, 0x8019, 0x0040, 0x2b5a, + 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, + 0x685e, 0x1078, 0x4dbd, 0x0078, 0x2b2c, 0x2069, 0xa351, 0x7824, + 0x7934, 0xa11a, 0x00c8, 0x2b5a, 0x8019, 0x0040, 0x2b5a, 0x684e, + 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, + 0x1078, 0x494d, 0x0078, 0x2b2c, 0xa02e, 0x2520, 0x81ff, 0x00c0, + 0x2b56, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xa388, + 0x41a1, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, 0x0020, 0x1078, + 0x3562, 0x701b, 0x2bf4, 0x007c, 0x6834, 0x2008, 0xa084, 0x00ff, + 0xa096, 0x0011, 0x0040, 0x2c00, 0xa096, 0x0019, 0x00c0, 0x2b56, + 0x810f, 0xa18c, 0x00ff, 0x0040, 0x2b56, 0x710e, 0x700c, 0x8001, + 0x0040, 0x2c31, 0x700e, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, + 0x0020, 0x2061, 0xa3d1, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, + 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078, + 0x3562, 0x701b, 0x2c24, 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096, + 0x0002, 0x0040, 0x2c2f, 0xa096, 0x000a, 0x00c0, 0x2b56, 0x0078, + 0x2c06, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x436e, + 0x00c0, 0x2c3f, 0x7007, 0x0003, 0x701b, 0x2c41, 0x007c, 0x1078, + 0x4a60, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xa388, + 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, + 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f, 0x0078, 0x3566, + 0x61a0, 0x7824, 0x60a2, 0x0078, 0x2b2c, 0x2091, 0x8000, 0x7823, + 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, + 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, + 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, + 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, + 0x2071, 0x0010, 0x20c1, 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427, + 0x0078, 0x0423, 0x81ff, 0x00c0, 0x2b56, 0x7924, 0x810f, 0xa18c, + 0x00ff, 0x1078, 0x4501, 0x00c0, 0x2b5a, 0x7e38, 0xa684, 0x3fff, + 0xa082, 0x4000, 0x0048, 0x2c9e, 0x0078, 0x2b5a, 0x7c28, 0x7d2c, + 0x1078, 0x46d6, 0xd28c, 0x00c0, 0x2ca9, 0x1078, 0x466a, 0x0078, + 0x2cab, 0x1078, 0x46a4, 0x00c0, 0x2cd5, 0x2061, 0xaa00, 0x127e, + 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0040, 0x2cc3, 0x6010, + 0xa06d, 0x0040, 0x2cc3, 0x683c, 0xa406, 0x00c0, 0x2cc3, 0x6840, + 0xa506, 0x0040, 0x2cce, 0x127f, 0xace0, 0x0010, 0x2001, 0xa315, + 0x2004, 0xac02, 0x00c8, 0x2b56, 0x0078, 0x2caf, 0x1078, 0x8758, + 0x127f, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0xa00e, 0x2001, 0x0005, + 0x1078, 0x4a60, 0x127e, 0x2091, 0x8000, 0x1078, 0x8cc0, 0x1078, + 0x4982, 0x127f, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, + 0x3530, 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, + 0x46e4, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, + 0x1078, 0x3542, 0x0040, 0x2b5a, 0x1078, 0x475f, 0x0040, 0x2b56, + 0x2019, 0x0005, 0x1078, 0x4705, 0x0040, 0x2b56, 0x7828, 0xa08a, + 0x1000, 0x00c8, 0x2b5a, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, + 0x58e1, 0x0078, 0x2b2c, 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040, + 0x2d1d, 0x2009, 0x0001, 0x0078, 0x2d4e, 0x2029, 0x00ff, 0x644c, + 0x2400, 0xa506, 0x0040, 0x2d48, 0x2508, 0x1078, 0x4501, 0x00c0, + 0x2d48, 0x1078, 0x475f, 0x00c0, 0x2d33, 0x2009, 0x0002, 0x62a8, + 0x2518, 0x0078, 0x2d4e, 0x2019, 0x0004, 0x1078, 0x4705, 0x00c0, + 0x2d3d, 0x2009, 0x0006, 0x0078, 0x2d4e, 0x7824, 0xa08a, 0x1000, + 0x00c8, 0x2d51, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x58e1, + 0x8529, 0x00c8, 0x2d20, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, + 0x2b56, 0x127f, 0x0078, 0x2b5a, 0x1078, 0x3530, 0x0040, 0x2b5a, + 0x1078, 0x461b, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x81ff, 0x00c0, + 0x2b56, 0x1078, 0x3530, 0x0040, 0x2b5a, 0x1078, 0x460a, 0x1078, + 0x46d6, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, + 0x0040, 0x2b5a, 0x1078, 0x46a7, 0x0040, 0x2b56, 0x1078, 0x43c1, + 0x1078, 0x4663, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x1078, 0x3530, + 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x62a0, 0x2019, + 0x0005, 0x0c7e, 0x1078, 0x471b, 0x0c7f, 0x1078, 0x5d53, 0x077e, + 0x2039, 0x0000, 0x1078, 0x5c78, 0x2009, 0x0000, 0x1078, 0x9c38, + 0x077f, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x1078, 0x3530, 0x0040, + 0x2b5a, 0x1078, 0x46d6, 0x2208, 0x0078, 0x2b2c, 0x157e, 0x0d7e, + 0x0e7e, 0x2069, 0xa413, 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2db2, + 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, + 0x00ff, 0x2069, 0xa434, 0x2d04, 0xa075, 0x0040, 0x2dc7, 0x704c, + 0x1078, 0x2dd1, 0xa210, 0x7080, 0x1078, 0x2dd1, 0xa318, 0x8d68, + 0x00f0, 0x2dbb, 0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, + 0x2b2c, 0x0f7e, 0x017e, 0xa07d, 0x0040, 0x2de0, 0x2001, 0x0000, + 0x8000, 0x2f0c, 0x81ff, 0x0040, 0x2de0, 0x2178, 0x0078, 0x2dd8, + 0x017f, 0x0f7f, 0x007c, 0x2069, 0xa413, 0x6910, 0x62a4, 0x0078, + 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x614c, 0xa190, 0x293f, 0x2214, + 0xa294, 0x00ff, 0x606c, 0xa084, 0xff00, 0xa215, 0x6368, 0x67c8, + 0xd79c, 0x0040, 0x2dff, 0x2031, 0x0001, 0x0078, 0x2e01, 0x2031, + 0x0000, 0x7e3a, 0x7f3e, 0x0078, 0x2b2c, 0x613c, 0x6240, 0x2019, + 0xa5a0, 0x231c, 0x0078, 0x2b2c, 0x127e, 0x2091, 0x8000, 0x6134, + 0xa006, 0x2010, 0x2018, 0x127f, 0x0078, 0x2b2c, 0x1078, 0x3542, + 0x0040, 0x2b5a, 0x6244, 0x6338, 0x0078, 0x2b2c, 0x613c, 0x6240, + 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0xa351, 0x831f, 0xa305, + 0x6816, 0x782c, 0x2069, 0xa5a0, 0x2d1c, 0x206a, 0x0078, 0x2b2c, + 0x017e, 0x127e, 0x2091, 0x8000, 0x7824, 0x6036, 0xd094, 0x0040, + 0x2e43, 0x7828, 0xa085, 0x0001, 0x2009, 0xa5a9, 0x200a, 0x2001, + 0xffff, 0x1078, 0x5975, 0x127f, 0x017f, 0x0078, 0x2b2c, 0x1078, + 0x3542, 0x0040, 0x2b5a, 0x7828, 0xa00d, 0x0040, 0x2b5a, 0x782c, + 0xa005, 0x0040, 0x2b5a, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078, + 0x2b2c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, + 0x0c7e, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, + 0x00ff, 0x00c0, 0x2e70, 0x6030, 0xa085, 0xff00, 0x0078, 0x2e7f, + 0xa182, 0x007f, 0x00c8, 0x2ea9, 0xa188, 0x293f, 0x210c, 0xa18c, + 0x00ff, 0x6030, 0xa116, 0x0040, 0x2ea9, 0x810f, 0xa105, 0x127e, + 0x2091, 0x8000, 0x007e, 0x1078, 0x74d7, 0x007f, 0x0040, 0x2ea5, + 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x3518, 0x0040, + 0x2eac, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x701b, 0x2f07, 0x2d00, 0x6012, 0x2009, 0x0032, + 0x1078, 0x756c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, + 0x2b56, 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x753d, 0x0078, 0x2ea5, + 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x0c7e, + 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, + 0x00c0, 0x2ec7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2ed6, 0xa182, + 0x007f, 0x00c8, 0x2f00, 0xa188, 0x293f, 0x210c, 0xa18c, 0x00ff, + 0x6030, 0xa116, 0x0040, 0x2f00, 0x810f, 0xa105, 0x127e, 0x2091, + 0x8000, 0x007e, 0x1078, 0x74d7, 0x007f, 0x0040, 0x2efc, 0x601a, + 0x600b, 0xbc05, 0x601f, 0x0001, 0x1078, 0x3518, 0x0040, 0x2f03, + 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x701b, 0x2f07, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, + 0x756c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2b56, + 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x753d, 0x0078, 0x2efc, 0x6830, + 0xa086, 0x0100, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x2061, 0xa62d, + 0x127e, 0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2f1c, 0x6104, + 0x6208, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b5a, 0x81ff, + 0x00c0, 0x2b56, 0x127e, 0x2091, 0x8000, 0x6244, 0x6060, 0xa202, + 0x0048, 0x2f33, 0xa085, 0x0001, 0x1078, 0x2500, 0x1078, 0x3bf5, + 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b5a, 0x127e, 0x2091, + 0x8000, 0x20a9, 0x0011, 0x2001, 0xa340, 0x20a0, 0xa006, 0x40a4, + 0x127f, 0x0078, 0x2b2c, 0x7d38, 0x7c3c, 0x0078, 0x2bde, 0x7824, + 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2b56, 0x624c, 0xa084, + 0xff00, 0x8007, 0xa206, 0x00c0, 0x2f5f, 0x2001, 0xa340, 0x2009, + 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3566, 0x81ff, + 0x00c0, 0x2b56, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2b56, 0x0c7e, 0x1078, 0x3518, + 0x0c7f, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x1078, 0x8b85, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x2f81, + 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2b56, 0xad80, 0x000e, + 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3566, + 0x1078, 0x3518, 0x0040, 0x2b56, 0x1078, 0x421a, 0x2009, 0x001c, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, 0x2fa1, + 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x2b5a, 0x6804, + 0xd0ac, 0x0040, 0x2fae, 0xd0a4, 0x0040, 0x2b5a, 0xd094, 0x0040, + 0x2fb9, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf, 0x6106, + 0x0c7f, 0xd08c, 0x0040, 0x2fc4, 0x0c7e, 0x2061, 0x0100, 0x6104, + 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c, 0xa18a, + 0x0002, 0x0048, 0x2fd9, 0xd084, 0x0040, 0x2fd9, 0x6a28, 0xa28a, + 0x007f, 0x00c8, 0x2b5a, 0xa288, 0x293f, 0x210c, 0xa18c, 0x00ff, + 0x6152, 0xd0dc, 0x0040, 0x2fe2, 0x6828, 0xa08a, 0x007f, 0x00c8, + 0x2b5a, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x2b5a, 0xa08a, + 0x0841, 0x00c8, 0x2b5a, 0xa084, 0x0007, 0x00c0, 0x2b5a, 0x680c, + 0xa005, 0x0040, 0x2b5a, 0x6810, 0xa005, 0x0040, 0x2b5a, 0x6848, + 0x6940, 0xa10a, 0x00c8, 0x2b5a, 0x8001, 0x0040, 0x2b5a, 0x684c, + 0x6944, 0xa10a, 0x00c8, 0x2b5a, 0x8001, 0x0040, 0x2b5a, 0x6804, + 0xd0fc, 0x0040, 0x3038, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, + 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399, + 0x0000, 0x1078, 0x3562, 0x701b, 0x301e, 0x007c, 0xade8, 0x000d, + 0x20a9, 0x0014, 0x2d98, 0x2069, 0xa36d, 0x2da0, 0x53a3, 0x7010, + 0xa0e8, 0x000d, 0x2001, 0xa371, 0x200c, 0xd1e4, 0x0040, 0x3038, + 0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, 0x6006, 0x0c7f, + 0x20a9, 0x001c, 0x2d98, 0x2069, 0xa351, 0x2da0, 0x53a3, 0x6814, + 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078, + 0x4dbd, 0x1078, 0x48dd, 0x1078, 0x494d, 0x6000, 0xa086, 0x0000, + 0x00c0, 0x30c3, 0x6808, 0x602a, 0x1078, 0x218b, 0x6818, 0x691c, + 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, + 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x3070, 0x6830, 0x6934, + 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0078, 0x3072, + 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x1078, 0x59a8, + 0x6904, 0xd1fc, 0x0040, 0x30a5, 0x0c7e, 0x2009, 0x0000, 0x20a9, + 0x0001, 0x6b70, 0xd384, 0x0040, 0x30a2, 0x0078, 0x308c, 0x839d, + 0x00c8, 0x30a2, 0x3508, 0x8109, 0x1078, 0x5364, 0x6878, 0x6016, + 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, + 0x6006, 0x8108, 0x00c0, 0x30a0, 0x6003, 0x0003, 0x0078, 0x30a2, + 0x6003, 0x0001, 0x00f0, 0x3087, 0x0c7f, 0x0c7e, 0x2061, 0x0100, + 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078, 0x3784, 0x0040, + 0x30b3, 0x1078, 0x2500, 0x60bc, 0xa005, 0x0040, 0x30bf, 0x6003, + 0x0001, 0x2091, 0x301d, 0x1078, 0x4171, 0x0078, 0x30c3, 0x6003, + 0x0004, 0x2091, 0x301d, 0x0078, 0x2b2c, 0x6000, 0xa086, 0x0000, + 0x0040, 0x2b56, 0x2069, 0xa351, 0x7830, 0x6842, 0x7834, 0x6846, + 0x6804, 0xd0fc, 0x0040, 0x30d8, 0x2009, 0x0030, 0x0078, 0x30da, + 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, + 0x3566, 0xa006, 0x1078, 0x2500, 0x81ff, 0x00c0, 0x2b56, 0x1078, + 0x421a, 0x1078, 0x4171, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, + 0x6180, 0x81ff, 0x0040, 0x3107, 0x703f, 0x0000, 0x2001, 0xa9c0, + 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x127e, 0x2091, + 0x8000, 0x1078, 0x3566, 0x701b, 0x2b29, 0x127f, 0x007c, 0x703f, + 0x0001, 0x0d7e, 0x2069, 0xa9c0, 0x20a9, 0x0040, 0x20a1, 0xa9c0, + 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x293f, 0x210c, 0xa18c, + 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x0040, + 0x3139, 0x1078, 0x4501, 0x00c0, 0x3139, 0x6014, 0x821c, 0x0048, + 0x3131, 0xa398, 0xa9c0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0078, + 0x3138, 0xa398, 0xa9c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, + 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x3140, 0x0078, 0x311d, + 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, 0x20a9, 0x0040, + 0x20a1, 0xa9c0, 0x2099, 0xa9c0, 0x1078, 0x41be, 0x0078, 0x30f6, + 0x1078, 0x3542, 0x0040, 0x2b5a, 0x0c7e, 0x1078, 0x3518, 0x0c7f, + 0x00c0, 0x315e, 0x2009, 0x0002, 0x0078, 0x2b56, 0x2001, 0xa352, + 0x2004, 0xd0b4, 0x0040, 0x3185, 0x6000, 0xd08c, 0x00c0, 0x3185, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x3185, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8bd9, 0x00c0, 0x317c, + 0x2009, 0x0003, 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3181, + 0x007c, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x20a9, 0x002b, 0x2c98, + 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, + 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x41be, 0x20a9, 0x0004, + 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x41be, + 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, + 0x3566, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040, 0x2b5a, + 0x1078, 0x46ef, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x7828, + 0xa08a, 0x1000, 0x00c8, 0x2b5a, 0x1078, 0x3542, 0x0040, 0x2b5a, + 0x1078, 0x475f, 0x0040, 0x2b56, 0x2019, 0x0004, 0x1078, 0x4705, + 0x7924, 0x810f, 0x7a28, 0x1078, 0x31cf, 0x0078, 0x2b2c, 0xa186, + 0x00ff, 0x0040, 0x31d7, 0x1078, 0x31e7, 0x0078, 0x31e6, 0x2029, + 0x007e, 0x2061, 0xa300, 0x644c, 0x2400, 0xa506, 0x0040, 0x31e3, + 0x2508, 0x1078, 0x31e7, 0x8529, 0x00c8, 0x31dc, 0x007c, 0x1078, + 0x4501, 0x00c0, 0x31f2, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, + 0x1078, 0x58e1, 0x007c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, + 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x46fa, + 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040, + 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x46e4, 0x0078, + 0x2b2c, 0x6100, 0x0078, 0x2b2c, 0x1078, 0x3542, 0x0040, 0x2b5a, + 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x0d7e, + 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x3228, 0xace8, 0x0006, + 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, + 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, 0x0078, 0x2b2c, + 0xa006, 0x1078, 0x2500, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, + 0x0040, 0x3245, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x421a, 0x7828, + 0xa08a, 0x1000, 0x00c8, 0x2b5a, 0x7924, 0xa18c, 0xff00, 0x810f, + 0xa186, 0x00ff, 0x0040, 0x325b, 0xa182, 0x007f, 0x00c8, 0x2b5a, + 0x2100, 0x1078, 0x24fa, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, + 0x2061, 0xa5be, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x0100, + 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, + 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4196, 0x1078, 0x596c, + 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, 0x31cf, 0x127f, + 0x0c7f, 0x027f, 0x0078, 0x2b2c, 0x7924, 0xa18c, 0xff00, 0x810f, + 0x0c7e, 0x1078, 0x4499, 0x2c08, 0x0c7f, 0x00c0, 0x2b5a, 0x0078, + 0x2b2c, 0x81ff, 0x0040, 0x3298, 0x2009, 0x0001, 0x0078, 0x2b56, + 0x60c8, 0xd09c, 0x00c0, 0x32a0, 0x2009, 0x0005, 0x0078, 0x2b56, + 0x1078, 0x3518, 0x00c0, 0x32a8, 0x2009, 0x0002, 0x0078, 0x2b56, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, + 0x32b2, 0x007c, 0x2009, 0x0080, 0x1078, 0x4501, 0x00c0, 0x32bf, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x32c3, 0x2021, + 0x400a, 0x0078, 0x2b2e, 0x0d7e, 0xade8, 0x000d, 0x6900, 0x6a08, + 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0040, + 0x3336, 0xa0be, 0x0112, 0x0040, 0x3336, 0xa0be, 0x0113, 0x0040, + 0x3336, 0xa0be, 0x0114, 0x0040, 0x3336, 0xa0be, 0x0117, 0x0040, + 0x3336, 0xa0be, 0x011a, 0x0040, 0x3336, 0xa0be, 0x0121, 0x0040, + 0x332c, 0xa0be, 0x0131, 0x0040, 0x332c, 0xa0be, 0x0171, 0x0040, + 0x3336, 0xa0be, 0x0173, 0x0040, 0x3336, 0xa0be, 0x01a1, 0x00c0, + 0x32fe, 0x6830, 0x8007, 0x6832, 0x0078, 0x333c, 0xa0be, 0x0212, + 0x0040, 0x3332, 0xa0be, 0x0213, 0x0040, 0x3332, 0xa0be, 0x0214, + 0x0040, 0x3324, 0xa0be, 0x0217, 0x0040, 0x331e, 0xa0be, 0x021a, + 0x00c0, 0x3317, 0x6838, 0x8007, 0x683a, 0x0078, 0x3336, 0xa0be, + 0x0300, 0x0040, 0x3336, 0x0d7f, 0x0078, 0x2b5a, 0xad80, 0x0010, + 0x20a9, 0x0007, 0x1078, 0x337e, 0xad80, 0x000e, 0x20a9, 0x0001, + 0x1078, 0x337e, 0x0078, 0x3336, 0xad80, 0x000c, 0x1078, 0x338c, + 0x0078, 0x333c, 0xad80, 0x000e, 0x1078, 0x338c, 0xad80, 0x000c, + 0x20a9, 0x0001, 0x1078, 0x337e, 0x0c7e, 0x1078, 0x3518, 0x0040, + 0x336f, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, 0x0000, + 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000, + 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x0c7f, + 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, + 0x6804, 0x2068, 0x1078, 0x8ba1, 0x00c0, 0x336a, 0x2009, 0x0003, + 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3375, 0x007c, 0x0c7f, + 0x0d7f, 0x2009, 0x0002, 0x0078, 0x2b56, 0x6820, 0xa086, 0x8001, + 0x00c0, 0x2b2c, 0x2009, 0x0004, 0x0078, 0x2b56, 0x017e, 0x2008, + 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, + 0x00f0, 0x3380, 0x017f, 0x007c, 0x017e, 0x0a7e, 0x0b7e, 0x2008, + 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, + 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x0b7f, 0x0a7f, + 0x017f, 0x007c, 0x81ff, 0x0040, 0x33a9, 0x2009, 0x0001, 0x0078, + 0x2b56, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, + 0x0048, 0x2b5a, 0xa182, 0x00ff, 0x00c8, 0x2b5a, 0x7a2c, 0x7b28, + 0x6068, 0xa306, 0x00c0, 0x33c4, 0x606c, 0xa24e, 0x0040, 0x2b5a, + 0xa9cc, 0xff00, 0x0040, 0x2b5a, 0x0c7e, 0x1078, 0x346d, 0x2c68, + 0x0c7f, 0x0040, 0x33fc, 0xa0c6, 0x4000, 0x00c0, 0x33e2, 0x0c7e, + 0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x47cb, 0x00c0, 0x33d9, + 0xc185, 0x6000, 0xd0bc, 0x0040, 0x33de, 0xc18d, 0x007f, 0x0c7f, + 0x0078, 0x33f9, 0xa0c6, 0x4007, 0x00c0, 0x33e9, 0x2408, 0x0078, + 0x33f9, 0xa0c6, 0x4008, 0x00c0, 0x33f1, 0x2708, 0x2610, 0x0078, + 0x33f9, 0xa0c6, 0x4009, 0x00c0, 0x33f7, 0x0078, 0x33f9, 0x2001, + 0x4006, 0x2020, 0x0078, 0x2b2e, 0x2d00, 0x7022, 0x017e, 0x0b7e, + 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x74d7, 0x0040, 0x3442, 0x2d00, + 0x601a, 0x2001, 0xa356, 0x2004, 0xa084, 0x00ff, 0x6842, 0x2e58, + 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x2b70, 0x00c0, + 0x3423, 0x1078, 0x753d, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x2009, + 0x0002, 0x0078, 0x2b56, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, + 0x2813, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x442b, + 0x2001, 0x0002, 0x1078, 0x443f, 0x2009, 0x0002, 0x1078, 0x756c, + 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x00c0, 0x344c, + 0x2009, 0x0003, 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3451, + 0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, 0x00c0, 0x345f, + 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078, 0x2b56, 0x2009, + 0x0000, 0x1078, 0x47cb, 0x00c0, 0x3466, 0xc185, 0x6000, 0xd0bc, + 0x0040, 0x346b, 0xc18d, 0x0078, 0x2b2c, 0x0e7e, 0x0d7e, 0x2029, + 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xa4b4, 0x2e04, + 0xa005, 0x00c0, 0x3482, 0x2100, 0xa406, 0x00c0, 0x34b3, 0x2428, + 0x0078, 0x34b3, 0x2068, 0x6f10, 0x2700, 0xa306, 0x00c0, 0x34a4, + 0x6e14, 0x2600, 0xa206, 0x00c0, 0x34a4, 0x2400, 0xa106, 0x00c0, + 0x34a0, 0x2d60, 0xd884, 0x0040, 0x34c8, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x00c0, 0x34c8, 0x2001, 0x4000, 0x0078, 0x34c9, + 0x2001, 0x4007, 0x0078, 0x34c9, 0x2400, 0xa106, 0x00c0, 0x34b3, + 0x6e14, 0x87ff, 0x00c0, 0x34af, 0x86ff, 0x0040, 0x347f, 0x2001, + 0x4008, 0x0078, 0x34c9, 0x8420, 0x8e70, 0x00f0, 0x3477, 0x85ff, + 0x00c0, 0x34c2, 0x2001, 0x4009, 0x0078, 0x34c9, 0x2001, 0x0001, + 0x0078, 0x34c9, 0x1078, 0x4499, 0x00c0, 0x34be, 0x6312, 0x6216, + 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0, 0x2b56, + 0x1078, 0x3518, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x7824, 0xa005, 0x0040, 0x2b5a, 0xa096, 0x00ff, 0x0040, + 0x34e5, 0xa092, 0x0004, 0x00c8, 0x2b5a, 0x2010, 0x2d18, 0x1078, + 0x27c2, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x34f0, 0x007c, + 0x6830, 0xa086, 0x0100, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x7924, + 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, 0x2b5a, 0xa182, + 0x00ff, 0x00c8, 0x2b5a, 0x127e, 0x2091, 0x8000, 0x1078, 0x8a89, + 0x00c0, 0x3515, 0xa190, 0xa434, 0x2204, 0xa065, 0x0040, 0x3515, + 0x1078, 0x4235, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b56, + 0x1078, 0x1381, 0x0040, 0x352f, 0xa006, 0x6802, 0x7010, 0xa005, + 0x00c0, 0x3527, 0x2d00, 0x7012, 0x7016, 0x0078, 0x352d, 0x7014, + 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x007c, + 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x4501, 0x00c0, 0x353f, + 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, 0x3540, 0xa066, + 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078, 0x4501, + 0x00c0, 0x3550, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0048, 0x3551, + 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040, 0x355e, + 0x2168, 0x6904, 0x1078, 0x139a, 0x0078, 0x3555, 0x7112, 0x7116, + 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x3568, 0x2031, 0x0000, + 0x2061, 0xa3d1, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e, + 0x6532, 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, 0x701b, 0x2b2c, + 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, + 0xa38f, 0x2004, 0xa005, 0x00c0, 0x3594, 0x0068, 0x3594, 0x7818, + 0xd084, 0x00c0, 0x3594, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, + 0x2091, 0x4080, 0x0078, 0x35b9, 0x017e, 0x0c7e, 0x0e7e, 0x2071, + 0xa381, 0x7138, 0xa182, 0x0008, 0x0048, 0x35a2, 0x7030, 0x2060, + 0x0078, 0x35b3, 0x7030, 0xa0e0, 0x0008, 0xac82, 0xa3d1, 0x0048, + 0x35ab, 0x2061, 0xa391, 0x2c00, 0x7032, 0x81ff, 0x00c0, 0x35b1, + 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f, 0x0c7f, + 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0xa381, 0x7038, + 0xa005, 0x0040, 0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x35f4, + 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x35f3, 0x0c7e, + 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005, + 0x00c0, 0x35e9, 0x7033, 0xa391, 0x7037, 0xa391, 0x0c7f, 0x0078, + 0x35f3, 0xac80, 0x0008, 0xa0fa, 0xa3d1, 0x0048, 0x35f1, 0x2001, + 0xa391, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c, 0x027e, + 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x3602, 0x2011, 0x8014, + 0x1078, 0x3579, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x2b56, 0x127e, + 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x1078, + 0x4171, 0x127f, 0x0078, 0x2b2c, 0x7824, 0x2008, 0xa18c, 0xfffd, + 0x00c0, 0x361f, 0x61d4, 0xa10d, 0x61d6, 0x0078, 0x2b2c, 0x0078, + 0x2b5a, 0x81ff, 0x00c0, 0x2b56, 0x6000, 0xa086, 0x0003, 0x00c0, + 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x2b56, 0x1078, + 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x00c0, 0x363e, 0x7828, 0xa005, 0x0040, 0x2b2c, 0x0c7e, 0x1078, + 0x3518, 0x0c7f, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8c4d, 0x0040, 0x2b56, 0x7007, + 0x0003, 0x701b, 0x3654, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, + 0x2b56, 0x0078, 0x2b2c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, + 0x00c0, 0x2b56, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, + 0x3518, 0x0040, 0x2b56, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, + 0x0000, 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, + 0x4501, 0x00c0, 0x36d8, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, + 0x0040, 0x3688, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x36d8, + 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x3695, 0x1078, 0x47cb, + 0x00c0, 0x3695, 0xd79c, 0x0040, 0x36d8, 0xd794, 0x00c0, 0x369b, + 0xd784, 0x0040, 0x36a7, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, + 0x0004, 0x53a3, 0x1078, 0x338c, 0xd794, 0x0040, 0x36b0, 0xac80, + 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, 0x338c, + 0x21a2, 0xd794, 0x0040, 0x36d0, 0xac80, 0x0000, 0x2098, 0x94a0, + 0x20a9, 0x0002, 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, + 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x53a3, 0x1078, 0x337e, + 0xac80, 0x0026, 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0078, 0x36d1, + 0x94a0, 0xd794, 0x0040, 0x36d6, 0xa6b0, 0x000b, 0xa6b0, 0x0005, + 0x8108, 0xd78c, 0x0040, 0x36e2, 0xa186, 0x0100, 0x0040, 0x36f3, + 0x0078, 0x36e6, 0xa186, 0x007e, 0x0040, 0x36f3, 0xd794, 0x0040, + 0x36ed, 0xa686, 0x0020, 0x0078, 0x36ef, 0xa686, 0x0028, 0x0040, + 0x36fc, 0x0078, 0x3677, 0x86ff, 0x00c0, 0x36fa, 0x7120, 0x810b, + 0x0078, 0x2b2c, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, + 0x772a, 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, + 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13d1, 0x7007, + 0x0002, 0x701b, 0x3714, 0x007c, 0x702c, 0xa005, 0x00c0, 0x3726, + 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0xa3d1, + 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3677, 0x7120, 0x810b, + 0x0078, 0x2b2c, 0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, + 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, + 0x0048, 0x2b5a, 0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2b5a, + 0xa502, 0x0048, 0x2b5a, 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, + 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0xa284, 0x00ff, 0xa0e2, + 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0xa384, 0xff00, + 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, + 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, + 0x2b5a, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, + 0xa502, 0x0048, 0x2b5a, 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048, + 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0x2061, 0xa5a3, 0x6102, 0x6206, + 0x630a, 0x640e, 0x0078, 0x2b2c, 0x007e, 0x2001, 0xa352, 0x2004, + 0xd0cc, 0x007f, 0x007c, 0x007e, 0x2001, 0xa371, 0x2004, 0xd0bc, + 0x007f, 0x007c, 0x6160, 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x379b, + 0x7926, 0x0078, 0x2b2c, 0x83ff, 0x00c0, 0x2b5a, 0x2001, 0xfff0, + 0xa200, 0x00c8, 0x2b5a, 0x2019, 0xffff, 0x6064, 0xa302, 0xa200, + 0x0048, 0x2b5a, 0x7926, 0x6262, 0x0078, 0x2b2c, 0x2001, 0xa300, + 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x7c28, 0x7d24, 0x7e38, + 0x7f2c, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, 0x0000, 0x2019, + 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, + 0x20a0, 0xa1e0, 0xa434, 0x2c64, 0x8cff, 0x0040, 0x37e8, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x37dd, 0x6004, 0xa084, + 0xff00, 0xa086, 0x0600, 0x00c0, 0x37e8, 0x6014, 0x20a2, 0x94a0, + 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, + 0x8108, 0xa182, 0x00ff, 0x0040, 0x37f3, 0xa386, 0x002a, 0x0040, + 0x37fc, 0x0078, 0x37c9, 0x83ff, 0x00c0, 0x37fa, 0x7120, 0x810c, + 0x0078, 0x2b2c, 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, + 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, + 0x652a, 0x662e, 0x6732, 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, + 0x701b, 0x3813, 0x007c, 0x702c, 0xa005, 0x00c0, 0x3824, 0x711c, + 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xa3d1, 0x6424, 0x6528, + 0x662c, 0x6730, 0x0078, 0x37c9, 0x7120, 0x810c, 0x0078, 0x2b2c, + 0x81ff, 0x00c0, 0x2b56, 0x60c8, 0xd09c, 0x0040, 0x2b56, 0x1078, + 0x3518, 0x0040, 0x2b56, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x1078, 0x3562, 0x701b, 0x383d, 0x007c, 0x0d7e, 0xade8, 0x000d, + 0x6828, 0xa0be, 0x7000, 0x0040, 0x3850, 0xa0be, 0x7100, 0x0040, + 0x3850, 0xa0be, 0x7200, 0x0040, 0x3850, 0x0d7f, 0x0078, 0x2b5a, + 0x6820, 0x6924, 0x1078, 0x24e3, 0x00c0, 0x387b, 0x1078, 0x4499, + 0x00c0, 0x387b, 0x7122, 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078, + 0x3518, 0x0040, 0x387b, 0x1078, 0x3518, 0x0040, 0x387b, 0x0c7f, + 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, + 0x6804, 0x2068, 0x1078, 0x8bbd, 0x0040, 0x2b56, 0x7007, 0x0003, + 0x701b, 0x387e, 0x007c, 0x0d7f, 0x0078, 0x2b56, 0x7120, 0x1078, + 0x2921, 0x6820, 0xa086, 0x8001, 0x0040, 0x2b56, 0x2d00, 0x701e, + 0x6804, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, + 0x1078, 0x41be, 0x007f, 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, + 0x6d14, 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, + 0x7000, 0x00c0, 0x38a5, 0x0078, 0x38a9, 0xa7c6, 0x7100, 0x00c0, + 0x38b1, 0xa6c2, 0x0004, 0x0048, 0x2b5a, 0x2009, 0x0004, 0x0078, + 0x3566, 0xa7c6, 0x7200, 0x00c0, 0x2b5a, 0xa6c2, 0x0054, 0x0048, + 0x2b5a, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, + 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, 0x701b, 0x38c8, 0x007c, + 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, + 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x41be, 0x007f, + 0x2009, 0x002a, 0x2061, 0xa3d1, 0x6224, 0x6328, 0x642c, 0x6530, + 0x0078, 0x3566, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040, + 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x4710, 0x0078, + 0x2b2c, 0x7824, 0xd084, 0x0040, 0x3150, 0x1078, 0x3542, 0x0040, + 0x2b5a, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x00c0, 0x3903, 0x2009, + 0x0002, 0x0078, 0x2b56, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x0040, 0x3910, 0xa08e, 0x0004, 0x0040, 0x3910, 0xa08e, 0x0005, + 0x00c0, 0x3934, 0x2001, 0xa352, 0x2004, 0xd0b4, 0x0040, 0x3185, + 0x6000, 0xd08c, 0x00c0, 0x3185, 0x6837, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x1078, 0x8bd9, 0x00c0, 0x3929, 0x2009, 0x0003, 0x0078, + 0x2b56, 0x7007, 0x0003, 0x701b, 0x392e, 0x007c, 0x1078, 0x3542, + 0x0040, 0x2b5a, 0x0078, 0x3185, 0x2009, 0xa32e, 0x210c, 0x81ff, + 0x0040, 0x393e, 0x2009, 0x0001, 0x0078, 0x2b56, 0x2001, 0xa300, + 0x2004, 0xa086, 0x0003, 0x0040, 0x3949, 0x2009, 0x0007, 0x0078, + 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x0040, 0x3953, 0x2009, + 0x0008, 0x0078, 0x2b56, 0x609c, 0xd0a4, 0x00c0, 0x395a, 0xd0ac, + 0x00c0, 0x3185, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x1078, 0x8c4d, 0x00c0, 0x3969, 0x2009, 0x0003, 0x0078, + 0x2b56, 0x7007, 0x0003, 0x701b, 0x396e, 0x007c, 0x6830, 0xa086, + 0x0100, 0x00c0, 0x3977, 0x2009, 0x0004, 0x0078, 0x2b56, 0x1078, + 0x3542, 0x0040, 0x2b5a, 0x0078, 0x3912, 0x81ff, 0x2009, 0x0001, + 0x00c0, 0x2b56, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, + 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x00c0, + 0x2b56, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2b56, 0x0c7e, 0x1078, + 0x3518, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2b56, 0x6837, 0x0000, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, + 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x39bc, 0xc0ed, 0x6952, + 0x792c, 0x6956, 0x0078, 0x39c5, 0xa28e, 0x0100, 0x00c0, 0x2b5a, + 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078, 0x8df6, + 0x2009, 0x0003, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x39d1, + 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, 0x2b56, + 0x0078, 0x2b2c, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2b56, 0x6000, + 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2b56, 0x1078, 0x3542, + 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, + 0x0009, 0x00c0, 0x2b56, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x2009, + 0x0002, 0x0040, 0x2b56, 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, 0x3a08, 0x007c, + 0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0, 0x3a1b, + 0x6804, 0xa005, 0x00c0, 0x3a1b, 0x6808, 0xa084, 0xff00, 0x00c0, + 0x3a1b, 0x0078, 0x3a1e, 0x0d7f, 0x00c0, 0x2b5a, 0x0d7f, 0x6837, + 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e, 0x1078, + 0x3542, 0x00c0, 0x3a2e, 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x8e52, + 0x2009, 0x0003, 0x0c7f, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, + 0x3a3a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, + 0x2b56, 0x0078, 0x2b2c, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100, + 0x2071, 0xa300, 0x6044, 0xd0a4, 0x00c0, 0x3a6c, 0xd084, 0x0040, + 0x3a55, 0x1078, 0x3bcc, 0x0078, 0x3a68, 0xd08c, 0x0040, 0x3a5c, + 0x1078, 0x3ae3, 0x0078, 0x3a68, 0xd094, 0x0040, 0x3a63, 0x1078, + 0x3ab7, 0x0078, 0x3a68, 0xd09c, 0x0040, 0x3a68, 0x1078, 0x3a76, + 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0, + 0x3a73, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3a68, 0x624c, 0xa286, + 0xf0f0, 0x00c0, 0x3a87, 0x6048, 0xa086, 0xf0f0, 0x0040, 0x3a87, + 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3ab6, 0xa294, + 0xff00, 0xa296, 0xf700, 0x0040, 0x3a9c, 0x7134, 0xd1a4, 0x00c0, + 0x3a9c, 0x6240, 0xa294, 0x0010, 0x0040, 0x3a9c, 0x2009, 0x00f7, + 0x1078, 0x41de, 0x0078, 0x3ab6, 0x6043, 0x0040, 0x6043, 0x0000, + 0x7073, 0x0000, 0x708b, 0x0001, 0x70af, 0x0000, 0x70cb, 0x0000, + 0x2009, 0xa9c0, 0x200b, 0x0000, 0x7083, 0x0000, 0x7077, 0x000f, + 0x2009, 0x000f, 0x2011, 0x4122, 0x1078, 0x596c, 0x007c, 0x157e, + 0x7074, 0xa005, 0x00c0, 0x3ae1, 0x2011, 0x4122, 0x1078, 0x58d4, + 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8, + 0x6044, 0xd08c, 0x00c0, 0x3ada, 0x00f0, 0x3ac8, 0x6242, 0x7087, + 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, + 0x0078, 0x3ae1, 0x6242, 0x7087, 0x0000, 0x707b, 0x0000, 0x0078, + 0x3ae1, 0x157f, 0x007c, 0x7078, 0xa08a, 0x0003, 0x00c8, 0x3aec, + 0x1079, 0x3aef, 0x0078, 0x3aee, 0x1078, 0x1328, 0x007c, 0x3af2, + 0x3b41, 0x3bcb, 0x0f7e, 0x707b, 0x0001, 0x20e1, 0xa000, 0x20e1, + 0x8700, 0x1078, 0x218b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079, + 0xa800, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f, + 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f, + 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f, + 0x0000, 0x2079, 0xa80c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099, + 0xa305, 0x20a1, 0xa80e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0xa812, + 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xa800, 0x20a1, 0x020b, + 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078, + 0x4158, 0x0f7f, 0x707f, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000, + 0x007c, 0x0d7e, 0x707c, 0x707f, 0x0000, 0xa025, 0x0040, 0x3bb5, + 0x6020, 0xd0b4, 0x00c0, 0x3bb3, 0x7188, 0x81ff, 0x0040, 0x3ba2, + 0xa486, 0x000c, 0x00c0, 0x3bad, 0xa480, 0x0018, 0x8004, 0x20a8, + 0x2011, 0xa880, 0x2019, 0xa800, 0x220c, 0x2304, 0xa106, 0x00c0, + 0x3b79, 0x8210, 0x8318, 0x00f0, 0x3b5c, 0x6043, 0x0004, 0x608b, + 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707b, 0x0002, 0x7087, + 0x0002, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c, 0x0078, + 0x3bb3, 0x2069, 0xa880, 0x6930, 0xa18e, 0x1101, 0x00c0, 0x3bad, + 0x6834, 0xa005, 0x00c0, 0x3bad, 0x6900, 0xa18c, 0x00ff, 0x00c0, + 0x3b8d, 0x6804, 0xa005, 0x0040, 0x3ba2, 0x2011, 0xa88e, 0x2019, + 0xa305, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048, 0x3ba0, + 0x00c0, 0x3bad, 0x8210, 0x8318, 0x00f0, 0x3b93, 0x0078, 0x3bad, + 0x708b, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, + 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, + 0x0000, 0x0078, 0x3bb5, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0, + 0x3bb3, 0x60c3, 0x000c, 0x2011, 0xa5b5, 0x2013, 0x0000, 0x707f, + 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, + 0x6c38, 0x0078, 0x3bb3, 0x007c, 0x7084, 0xa08a, 0x001d, 0x00c8, + 0x3bd5, 0x1079, 0x3bd8, 0x0078, 0x3bd7, 0x1078, 0x1328, 0x007c, + 0x3c02, 0x3c11, 0x3c40, 0x3c59, 0x3c85, 0x3cb1, 0x3cdd, 0x3d13, + 0x3d3f, 0x3d67, 0x3daa, 0x3dd4, 0x3df6, 0x3e0c, 0x3e32, 0x3e45, + 0x3e4e, 0x3e7e, 0x3eaa, 0x3ed6, 0x3f02, 0x3f38, 0x3f7d, 0x3fac, + 0x3fce, 0x4010, 0x4036, 0x404f, 0x4050, 0x0c7e, 0x2061, 0xa300, + 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006, + 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, + 0x7087, 0x0001, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c, + 0x007c, 0x0f7e, 0x707c, 0xa086, 0x0014, 0x00c0, 0x3c3e, 0x6043, + 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3c3e, 0x2079, 0xa880, 0x7a30, + 0xa296, 0x1102, 0x00c0, 0x3c3c, 0x7834, 0xa005, 0x00c0, 0x3c3c, + 0x7a38, 0xd2fc, 0x0040, 0x3c32, 0x70ac, 0xa005, 0x00c0, 0x3c32, + 0x70af, 0x0001, 0x2011, 0x4129, 0x1078, 0x58d4, 0x7087, 0x0010, + 0x1078, 0x3e4e, 0x0078, 0x3c3e, 0x1078, 0x4171, 0x0f7f, 0x007c, + 0x7087, 0x0003, 0x6043, 0x0004, 0x2011, 0x4129, 0x1078, 0x58d4, + 0x1078, 0x41c6, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, + 0x20a3, 0x0000, 0x00f0, 0x3c50, 0x60c3, 0x0014, 0x1078, 0x4158, + 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3c83, 0x2011, 0x4129, + 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3c81, 0x2079, 0xa880, + 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3c81, 0x7834, 0xa005, 0x00c0, + 0x3c81, 0x7a38, 0xd2fc, 0x0040, 0x3c7b, 0x70ac, 0xa005, 0x00c0, + 0x3c7b, 0x70af, 0x0001, 0x7087, 0x0004, 0x1078, 0x3c85, 0x0078, + 0x3c83, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0005, 0x1078, + 0x41c6, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, + 0x1078, 0x4211, 0x00c0, 0x3ca3, 0x7070, 0xa005, 0x00c0, 0x3ca3, + 0x714c, 0xa186, 0xffff, 0x0040, 0x3ca3, 0x1078, 0x40ea, 0x0040, + 0x3ca3, 0x1078, 0x41f5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, + 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3cdb, 0x2011, 0x4129, + 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3cd9, 0x2079, 0xa880, + 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3cd9, 0x7834, 0xa005, 0x00c0, + 0x3cd9, 0x7a38, 0xd2fc, 0x0040, 0x3cd3, 0x70ac, 0xa005, 0x00c0, + 0x3cd3, 0x70af, 0x0001, 0x7087, 0x0006, 0x1078, 0x3cdd, 0x0078, + 0x3cdb, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0007, 0x1078, + 0x41c6, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, + 0x1078, 0x4211, 0x00c0, 0x3d05, 0x7070, 0xa005, 0x00c0, 0x3d05, + 0x7150, 0xa186, 0xffff, 0x0040, 0x3d05, 0xa180, 0x293f, 0x200c, + 0xa18c, 0xff00, 0x810f, 0x1078, 0x40ea, 0x0040, 0x3d05, 0x1078, + 0x378b, 0x0040, 0x3d05, 0x1078, 0x2500, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3d3d, + 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3d3b, + 0x2079, 0xa880, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3d3b, 0x7834, + 0xa005, 0x00c0, 0x3d3b, 0x7a38, 0xd2fc, 0x0040, 0x3d35, 0x70ac, + 0xa005, 0x00c0, 0x3d35, 0x70af, 0x0001, 0x7087, 0x0008, 0x1078, + 0x3d3f, 0x0078, 0x3d3d, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, + 0x0009, 0x1078, 0x41c6, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, + 0x1078, 0x4211, 0x00c0, 0x3d58, 0x7070, 0xa005, 0x00c0, 0x3d58, + 0x1078, 0x4051, 0x00c0, 0x3d62, 0xa085, 0x0001, 0x1078, 0x2500, + 0x20a9, 0x0008, 0x2099, 0xa88e, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, + 0x707c, 0xa005, 0x0040, 0x3da8, 0x2011, 0x4129, 0x1078, 0x58d4, + 0xa086, 0x0014, 0x00c0, 0x3da6, 0x2079, 0xa880, 0x7a30, 0xa296, + 0x1105, 0x00c0, 0x3da6, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, + 0x3d91, 0x7a38, 0xd2fc, 0x0040, 0x3d8b, 0x70ac, 0xa005, 0x00c0, + 0x3d8b, 0x70af, 0x0001, 0x7087, 0x000a, 0x1078, 0x3daa, 0x0078, + 0x3da8, 0xa005, 0x00c0, 0x3da6, 0x7a38, 0xd2fc, 0x0040, 0x3d9e, + 0x70ac, 0xa005, 0x00c0, 0x3d9e, 0x70af, 0x0001, 0x7083, 0x0000, + 0x7087, 0x000e, 0x1078, 0x3e32, 0x0078, 0x3da8, 0x1078, 0x4171, + 0x0f7f, 0x007c, 0x7087, 0x000b, 0x2011, 0xa80e, 0x22a0, 0x20a9, + 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, + 0x41a4, 0x1078, 0x41c6, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x1078, + 0x4211, 0x0040, 0x3dc7, 0x2013, 0x0000, 0x0078, 0x3dcb, 0x6030, + 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, + 0x0084, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, + 0x3df4, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0, + 0x3df2, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3df2, + 0x7834, 0xa005, 0x00c0, 0x3df2, 0x7087, 0x000c, 0x1078, 0x3df6, + 0x0078, 0x3df4, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x000d, + 0x1078, 0x41c6, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, 0xa88e, + 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0084, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, + 0x3e30, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0, + 0x3e2e, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x3e2e, + 0x7834, 0xa005, 0x00c0, 0x3e2e, 0x7083, 0x0001, 0x1078, 0x41b8, + 0x7087, 0x000e, 0x1078, 0x3e32, 0x0078, 0x3e30, 0x1078, 0x4171, + 0x0f7f, 0x007c, 0x7087, 0x000f, 0x707f, 0x0000, 0x608b, 0xbc85, + 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, + 0x2011, 0x4129, 0x1078, 0x58c7, 0x007c, 0x707c, 0xa005, 0x0040, + 0x3e4d, 0x2011, 0x4129, 0x1078, 0x58d4, 0x007c, 0x7087, 0x0011, + 0x1078, 0x4211, 0x00c0, 0x3e67, 0x7168, 0x81ff, 0x0040, 0x3e67, + 0x2009, 0x0000, 0x706c, 0xa084, 0x00ff, 0x1078, 0x24e3, 0xa186, + 0x0080, 0x0040, 0x3e67, 0x2011, 0xa88e, 0x1078, 0x40ea, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, 0x747c, + 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, + 0x53a6, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, + 0xa005, 0x0040, 0x3ea8, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, + 0x0014, 0x00c0, 0x3ea6, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1103, + 0x00c0, 0x3ea6, 0x7834, 0xa005, 0x00c0, 0x3ea6, 0x7a38, 0xd2fc, + 0x0040, 0x3ea0, 0x70ac, 0xa005, 0x00c0, 0x3ea0, 0x70af, 0x0001, + 0x7087, 0x0012, 0x1078, 0x3eaa, 0x0078, 0x3ea8, 0x1078, 0x4171, + 0x0f7f, 0x007c, 0x7087, 0x0013, 0x1078, 0x41d2, 0x20a3, 0x1103, + 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, 0x1078, 0x4211, 0x00c0, + 0x3ec8, 0x7070, 0xa005, 0x00c0, 0x3ec8, 0x714c, 0xa186, 0xffff, + 0x0040, 0x3ec8, 0x1078, 0x40ea, 0x0040, 0x3ec8, 0x1078, 0x41f5, + 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, + 0xa005, 0x0040, 0x3f00, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, + 0x0014, 0x00c0, 0x3efe, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1104, + 0x00c0, 0x3efe, 0x7834, 0xa005, 0x00c0, 0x3efe, 0x7a38, 0xd2fc, + 0x0040, 0x3ef8, 0x70ac, 0xa005, 0x00c0, 0x3ef8, 0x70af, 0x0001, + 0x7087, 0x0014, 0x1078, 0x3f02, 0x0078, 0x3f00, 0x1078, 0x4171, + 0x0f7f, 0x007c, 0x7087, 0x0015, 0x1078, 0x41d2, 0x20a3, 0x1104, + 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, 0x1078, 0x4211, 0x00c0, + 0x3f2a, 0x7070, 0xa005, 0x00c0, 0x3f2a, 0x7150, 0xa186, 0xffff, + 0x0040, 0x3f2a, 0xa180, 0x293f, 0x200c, 0xa18c, 0xff00, 0x810f, + 0x1078, 0x40ea, 0x0040, 0x3f2a, 0x1078, 0x378b, 0x0040, 0x3f2a, + 0x1078, 0x2500, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, + 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3f7b, 0x2011, 0x4129, 0x1078, + 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3f79, 0x2079, 0xa880, 0x7a30, + 0xa296, 0x1105, 0x00c0, 0x3f79, 0x7834, 0x2011, 0x0100, 0xa21e, + 0x00c0, 0x3f5e, 0x7a38, 0xd2fc, 0x0040, 0x3f5c, 0x70ac, 0xa005, + 0x00c0, 0x3f5c, 0x70af, 0x0001, 0x0078, 0x3f6d, 0xa005, 0x00c0, + 0x3f79, 0x7a38, 0xd2fc, 0x0040, 0x3f6b, 0x70ac, 0xa005, 0x00c0, + 0x3f6b, 0x70af, 0x0001, 0x7083, 0x0000, 0x7a38, 0xd2f4, 0x0040, + 0x3f73, 0x70cb, 0x0008, 0x7087, 0x0016, 0x1078, 0x3f7d, 0x0078, + 0x3f7b, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, + 0x3430, 0x2011, 0xa88e, 0x7087, 0x0017, 0x1078, 0x4211, 0x00c0, + 0x3f9d, 0x7070, 0xa005, 0x00c0, 0x3f9d, 0x1078, 0x4051, 0x00c0, + 0x3fa7, 0xa085, 0x0001, 0x1078, 0x2500, 0x20a9, 0x0008, 0x2099, + 0xa88e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, + 0x3fcc, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0, + 0x3fca, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3fca, + 0x7834, 0xa005, 0x00c0, 0x3fca, 0x7087, 0x0018, 0x1078, 0x3fce, + 0x0078, 0x3fcc, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0019, + 0x1078, 0x41d2, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, + 0xa88e, 0x2039, 0xa80e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x1078, + 0x4211, 0x00c0, 0x4002, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, + 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x6030, + 0x2310, 0x8214, 0xa2a0, 0xa80e, 0x2414, 0xa38c, 0x0001, 0x0040, + 0x3ffd, 0xa294, 0xff00, 0x0078, 0x4000, 0xa294, 0x00ff, 0x8007, + 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078, 0x4158, 0x007c, + 0x0f7e, 0x707c, 0xa005, 0x0040, 0x4034, 0x2011, 0x4129, 0x1078, + 0x58d4, 0xa086, 0x0084, 0x00c0, 0x4032, 0x2079, 0xa880, 0x7a30, + 0xa296, 0x1107, 0x00c0, 0x4032, 0x7834, 0xa005, 0x00c0, 0x4032, + 0x7083, 0x0001, 0x1078, 0x41b8, 0x7087, 0x001a, 0x1078, 0x4036, + 0x0078, 0x4034, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x001b, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, + 0x747c, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, + 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x4158, 0x007c, 0x007c, + 0x007c, 0x087e, 0x097e, 0x2029, 0xa352, 0x252c, 0x20a9, 0x0008, + 0x2041, 0xa80e, 0x28a0, 0x2099, 0xa88e, 0x53a3, 0x20a9, 0x0008, + 0x2011, 0x0007, 0xd5d4, 0x0040, 0x4067, 0x2011, 0x0000, 0x2800, + 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, 0x4079, 0xd5d4, 0x0040, + 0x4074, 0x8210, 0x0078, 0x4075, 0x8211, 0x00f0, 0x4067, 0x0078, + 0x40e1, 0x82ff, 0x00c0, 0x408b, 0xd5d4, 0x0040, 0x4085, 0xa1a6, + 0x3fff, 0x0040, 0x4071, 0x0078, 0x4089, 0xa1a6, 0x3fff, 0x0040, + 0x40e1, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, + 0x0040, 0x4094, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x409b, + 0x8423, 0x0078, 0x409c, 0x8424, 0x00c8, 0x40a9, 0xd5d4, 0x0040, + 0x40a4, 0x8319, 0x0078, 0x40a5, 0x8318, 0x00f0, 0x4095, 0x0078, + 0x40e1, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x40ad, + 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, 0x40c1, 0x007e, 0x2039, + 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0, + 0x40bd, 0x754e, 0xa5c8, 0x293f, 0x292c, 0xa5ac, 0x00ff, 0x6532, + 0x60e7, 0x0000, 0x65ea, 0x706b, 0x0000, 0x756e, 0x2018, 0x2304, + 0xa405, 0x201a, 0x7073, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, + 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0078, + 0x40e7, 0xa006, 0x0078, 0x40e7, 0xa006, 0x1078, 0x1328, 0x097f, + 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, + 0x0010, 0x0048, 0x40f7, 0x8420, 0x8001, 0x0078, 0x40ef, 0x2118, + 0x84ff, 0x0040, 0x4100, 0xa39a, 0x0010, 0x8421, 0x00c0, 0x40fb, + 0x2021, 0x0001, 0x83ff, 0x0040, 0x4109, 0x8423, 0x8319, 0x00c0, + 0x4105, 0xa238, 0x2704, 0xa42c, 0x00c0, 0x4121, 0xa405, 0x203a, + 0x714e, 0xa1a0, 0x293f, 0x242c, 0xa5ac, 0x00ff, 0x6532, 0x60e7, + 0x0000, 0x65ea, 0x706b, 0x0000, 0x756e, 0x7073, 0x0001, 0xa084, + 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa300, 0x7077, 0x0000, 0x0e7f, + 0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002, 0x1078, 0x5975, 0x2079, + 0x0100, 0x2071, 0x0140, 0x1078, 0x6c41, 0x7004, 0xa084, 0x4000, + 0x0040, 0x413e, 0x7003, 0x1000, 0x7003, 0x0000, 0x127e, 0x2091, + 0x8000, 0x2071, 0xa321, 0x2073, 0x0000, 0x7840, 0x027e, 0x017e, + 0x2009, 0x00f7, 0x1078, 0x41de, 0x017f, 0xa094, 0x0010, 0xa285, + 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, 0x0f7f, 0x0e7f, 0x007c, + 0x127e, 0x2091, 0x8000, 0x2011, 0xa5b5, 0x2013, 0x0000, 0x707f, + 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x1078, 0x6c38, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c, + 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x2009, + 0x00f7, 0x1078, 0x41de, 0x2061, 0xa5be, 0x601b, 0x0000, 0x601f, + 0x0000, 0x2061, 0xa300, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, + 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4196, 0x1078, + 0x58c7, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c, 0x0e7e, 0x007e, + 0x127e, 0x2091, 0x8000, 0x2001, 0x0001, 0x1078, 0x5975, 0x2071, + 0x0100, 0x1078, 0x6c41, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, + 0x0040, 0x41ae, 0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001, + 0x1078, 0x2480, 0x1078, 0x4171, 0x127f, 0x007f, 0x0e7f, 0x007c, + 0x20a9, 0x0040, 0x20a1, 0xa9c0, 0x2099, 0xa88e, 0x3304, 0x8007, + 0x20a2, 0x9398, 0x94a0, 0x00f0, 0x41be, 0x007c, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2099, 0xa800, 0x20a1, 0x020b, 0x20a9, 0x000c, + 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, + 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e, + 0x2061, 0x0100, 0x810f, 0x2001, 0xa32e, 0x2004, 0xa005, 0x00c0, + 0x41ef, 0x6030, 0xa084, 0x00ff, 0xa105, 0x0078, 0x41f1, 0xa185, + 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, 0x017e, 0x047e, 0x2001, + 0xa352, 0x2004, 0xd0a4, 0x0040, 0x4208, 0xa006, 0x2020, 0x2009, + 0x002a, 0x1078, 0x9ec0, 0x2001, 0xa30c, 0x200c, 0xc195, 0x2102, + 0x2019, 0x002a, 0x2009, 0x0000, 0x1078, 0x27e2, 0x047f, 0x017f, + 0x007c, 0x007e, 0x2001, 0xa30c, 0x2004, 0xd09c, 0x0040, 0x4218, + 0x007f, 0x007c, 0x007e, 0x017e, 0x127e, 0x2091, 0x8000, 0x2001, + 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x127f, 0x017f, 0x007f, + 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, 0xa434, 0xa006, 0x200a, + 0x8108, 0x00f0, 0x422f, 0x157f, 0x007c, 0x0d7e, 0x037e, 0x157e, + 0x137e, 0x147e, 0x2069, 0xa351, 0xa006, 0x6002, 0x6007, 0x0707, + 0x600a, 0x600e, 0x6012, 0xa198, 0x293f, 0x231c, 0xa39c, 0x00ff, + 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, + 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, + 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, + 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, 0x608e, + 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x0d7e, 0x60a4, + 0xa06d, 0x0040, 0x4275, 0x1078, 0x139a, 0x60a7, 0x0000, 0x60a8, + 0xa06d, 0x0040, 0x427d, 0x1078, 0x139a, 0x60ab, 0x0000, 0x0d7f, + 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, + 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f, 0x007c, + 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, + 0x4000, 0x00c8, 0x4361, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, + 0x00c8, 0x4367, 0x2001, 0xa30c, 0x2004, 0xa084, 0x0003, 0x0040, + 0x42c2, 0x2001, 0xa30c, 0x2004, 0xd084, 0x00c0, 0x4342, 0xa188, + 0xa434, 0x2104, 0xa065, 0x0040, 0x4342, 0x6004, 0xa084, 0x00ff, + 0xa08e, 0x0006, 0x00c0, 0x4342, 0x6000, 0xd0c4, 0x0040, 0x4342, + 0x0078, 0x42cf, 0xa188, 0xa434, 0x2104, 0xa065, 0x0040, 0x4326, + 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x432c, 0x60a4, + 0xa00d, 0x0040, 0x42d7, 0x1078, 0x4749, 0x0040, 0x4320, 0x60a8, + 0xa00d, 0x0040, 0x42f1, 0x1078, 0x479a, 0x00c0, 0x42f1, 0x694c, + 0xd1fc, 0x00c0, 0x42e7, 0x1078, 0x441c, 0x0078, 0x431b, 0x1078, + 0x43d6, 0x694c, 0xd1ec, 0x00c0, 0x431b, 0x1078, 0x460a, 0x0078, + 0x431b, 0x694c, 0xa184, 0xa000, 0x0040, 0x430b, 0xd1ec, 0x0040, + 0x4304, 0xd1fc, 0x0040, 0x4300, 0x1078, 0x461b, 0x0078, 0x4307, + 0x1078, 0x461b, 0x0078, 0x430b, 0xd1fc, 0x0040, 0x430b, 0x1078, + 0x43d6, 0x0078, 0x431b, 0x6050, 0xa00d, 0x0040, 0x4316, 0x2d00, + 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, 0x431b, 0x2d00, 0x6052, + 0x604e, 0x6803, 0x0000, 0x1078, 0x5c17, 0xa006, 0x127f, 0x007c, + 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, 0x436b, 0x2001, 0x0028, + 0x2009, 0x0000, 0x0078, 0x436b, 0xa082, 0x0006, 0x00c8, 0x4342, + 0x60a0, 0xd0bc, 0x00c0, 0x433e, 0x6100, 0xd1fc, 0x0040, 0x42cf, + 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x436b, 0x2001, 0x0028, + 0x0078, 0x435d, 0x2009, 0xa30c, 0x210c, 0xd18c, 0x0040, 0x434c, + 0x2001, 0x0004, 0x0078, 0x435d, 0xd184, 0x0040, 0x4353, 0x2001, + 0x0004, 0x0078, 0x435d, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0040, + 0x435d, 0x2009, 0x1000, 0x0078, 0x436b, 0x2009, 0x0000, 0x0078, + 0x436b, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x436b, 0x2001, + 0x0029, 0x2009, 0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0x6e48, + 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x43bb, 0xa18c, 0xff00, + 0x810f, 0xa182, 0x00ff, 0x00c8, 0x43a1, 0xa188, 0xa434, 0x2104, + 0xa065, 0x0040, 0x43a1, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, + 0x00c0, 0x43a7, 0x684c, 0xd0ec, 0x0040, 0x4394, 0x1078, 0x461b, + 0x1078, 0x43d6, 0x0078, 0x439c, 0x1078, 0x43d6, 0x684c, 0xd0fc, + 0x0040, 0x439c, 0x1078, 0x460a, 0x1078, 0x4663, 0xa006, 0x0078, + 0x43bf, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x43bf, 0xa082, + 0x0006, 0x00c8, 0x43b5, 0x6100, 0xd1fc, 0x0040, 0x438a, 0x2001, + 0x0029, 0x2009, 0x1000, 0x0078, 0x43bf, 0x2001, 0x0029, 0x2009, + 0x0000, 0x0078, 0x43bf, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, + 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0040, 0x43cf, + 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c, 0x2d00, + 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x43cd, 0x127e, 0x2091, + 0x8000, 0x604c, 0xa005, 0x0040, 0x43ec, 0x0e7e, 0x2071, 0xa5ab, + 0x7004, 0xa086, 0x0002, 0x0040, 0x43f3, 0x0e7f, 0x604c, 0x6802, + 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, + 0x0000, 0x0078, 0x43ea, 0x701c, 0xac06, 0x00c0, 0x43e5, 0x604c, + 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x0e7f, 0x127f, 0x007c, + 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040, 0x440e, 0x6800, + 0xa005, 0x00c0, 0x440c, 0x6052, 0x604e, 0xad05, 0x127f, 0x007c, + 0x604c, 0xa06d, 0x0040, 0x441b, 0x6800, 0xa005, 0x00c0, 0x4419, + 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000, 0x6084, 0xa00d, + 0x0040, 0x4426, 0x2d00, 0x200a, 0x6086, 0x007c, 0x2d00, 0x6086, + 0x6082, 0x0078, 0x4425, 0x127e, 0x0c7e, 0x027e, 0x2091, 0x8000, + 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x4439, 0xc285, 0x0078, + 0x443a, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f, 0x007c, 0x127e, + 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086, + 0x0006, 0x00c0, 0x445e, 0x609c, 0xd0ac, 0x0040, 0x445e, 0x2001, + 0xa352, 0x2004, 0xd0a4, 0x0040, 0x445e, 0xa284, 0xff00, 0x8007, + 0xa086, 0x0007, 0x00c0, 0x445e, 0x2011, 0x0600, 0x007f, 0xa294, + 0xff00, 0xa215, 0x6206, 0x007e, 0xa086, 0x0006, 0x00c0, 0x446e, + 0x6290, 0x82ff, 0x00c0, 0x446e, 0x1078, 0x1328, 0x007f, 0x0c7f, + 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, + 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4490, 0x609c, 0xd0a4, + 0x0040, 0x4490, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x4490, + 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, 0x4490, 0x2011, 0x0006, + 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x0c7f, 0x127f, + 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, 0x44a2, 0xa085, 0x0001, + 0x0078, 0x44ba, 0xa190, 0xa434, 0x2204, 0xa065, 0x00c0, 0x44b9, + 0x017e, 0x0d7e, 0x1078, 0x1366, 0x2d60, 0x0d7f, 0x017f, 0x0040, + 0x449e, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000, 0x1078, + 0x4235, 0xa006, 0x027f, 0x007c, 0x127e, 0x2091, 0x8000, 0x027e, + 0xa182, 0x00ff, 0x0048, 0x44c8, 0xa085, 0x0001, 0x0078, 0x44fe, + 0x0d7e, 0xa190, 0xa434, 0x2204, 0xa06d, 0x0040, 0x44fc, 0x2013, + 0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4, 0xa06d, 0x0040, 0x44da, + 0x1078, 0x139a, 0x60a8, 0xa06d, 0x0040, 0x44e0, 0x1078, 0x139a, + 0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac, 0x2060, 0x8cff, 0x0040, + 0x44f8, 0x600c, 0x007e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, + 0x44f3, 0x1078, 0x13aa, 0x1078, 0x753d, 0x0c7f, 0x0078, 0x44e6, + 0x0c7f, 0x0d7f, 0x1078, 0x139a, 0x0d7f, 0xa006, 0x027f, 0x127f, + 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048, 0x450a, 0xa085, 0x0001, + 0x0078, 0x4511, 0xa188, 0xa434, 0x2104, 0xa065, 0x0040, 0x4506, + 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x600b, + 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x2069, 0xa88e, + 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0048, 0x4529, + 0x603a, 0x6814, 0x6066, 0x2099, 0xa896, 0xac88, 0x000a, 0x21a0, + 0x20a9, 0x0004, 0x53a3, 0x2099, 0xa89a, 0xac88, 0x0006, 0x21a0, + 0x20a9, 0x0004, 0x53a3, 0x2069, 0xa8ae, 0x6808, 0x606a, 0x690c, + 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211, 0x00c8, + 0x454d, 0x2009, 0x0008, 0x0078, 0x4577, 0xa182, 0x0259, 0x00c8, + 0x4555, 0x2009, 0x0007, 0x0078, 0x4577, 0xa182, 0x02c1, 0x00c8, + 0x455d, 0x2009, 0x0006, 0x0078, 0x4577, 0xa182, 0x0349, 0x00c8, + 0x4565, 0x2009, 0x0005, 0x0078, 0x4577, 0xa182, 0x0421, 0x00c8, + 0x456d, 0x2009, 0x0004, 0x0078, 0x4577, 0xa182, 0x0581, 0x00c8, + 0x4575, 0x2009, 0x0003, 0x0078, 0x4577, 0x2009, 0x0002, 0x6192, + 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x017e, 0x027e, 0x0e7e, + 0x2071, 0xa88d, 0x2e04, 0x6896, 0x2071, 0xa88e, 0x7004, 0x689a, + 0x701c, 0x689e, 0x6a00, 0x2009, 0xa371, 0x210c, 0xd0bc, 0x0040, + 0x4597, 0xd1ec, 0x0040, 0x4597, 0xc2ad, 0x0078, 0x4598, 0xc2ac, + 0xd0c4, 0x0040, 0x45a1, 0xd1e4, 0x0040, 0x45a1, 0xc2bd, 0x0078, + 0x45a2, 0xc2bc, 0x6a02, 0x0e7f, 0x027f, 0x017f, 0x007c, 0x0d7e, + 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x0040, 0x45cb, 0x6900, + 0x81ff, 0x00c0, 0x45df, 0x6a04, 0xa282, 0x0010, 0x00c8, 0x45e4, + 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040, + 0x45c6, 0x8108, 0x00f0, 0x45bc, 0x1078, 0x1328, 0x260a, 0x8210, + 0x6a06, 0x0078, 0x45df, 0x1078, 0x1381, 0x0040, 0x45e4, 0x2d00, + 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, + 0xffff, 0x8108, 0x00f0, 0x45d7, 0x6807, 0x0001, 0x6e12, 0xa085, + 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x45e1, 0x127e, + 0x2091, 0x8000, 0x0d7e, 0x60a4, 0xa00d, 0x0040, 0x4607, 0x2168, + 0x6800, 0xa005, 0x00c0, 0x4603, 0x1078, 0x4749, 0x00c0, 0x4607, + 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0048, 0x4603, 0x8001, + 0x6806, 0x0078, 0x4607, 0x1078, 0x139a, 0x60a7, 0x0000, 0x0d7f, + 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x47af, 0x0078, + 0x4613, 0x1078, 0x43c1, 0x1078, 0x46a7, 0x00c0, 0x4611, 0x1078, + 0x4663, 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a8, + 0xa06d, 0x0040, 0x463f, 0x6950, 0x81ff, 0x00c0, 0x4653, 0x6a54, + 0xa282, 0x0010, 0x00c8, 0x4660, 0xad88, 0x0018, 0x20a9, 0x0010, + 0x2104, 0xa086, 0xffff, 0x0040, 0x463a, 0x8108, 0x00f0, 0x4630, + 0x1078, 0x1328, 0x260a, 0x8210, 0x6a56, 0x0078, 0x4653, 0x1078, + 0x1381, 0x0040, 0x4660, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, + 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x464b, + 0x6857, 0x0001, 0x6e62, 0x0078, 0x4657, 0x1078, 0x441c, 0x1078, + 0x466d, 0x00c0, 0x4655, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, + 0xa006, 0x0078, 0x465d, 0x127e, 0x2091, 0x8000, 0x1078, 0x5c17, + 0x127f, 0x007c, 0xa01e, 0x0078, 0x466f, 0x2019, 0x0001, 0xa00e, + 0x127e, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0, + 0x468d, 0x8dff, 0x0040, 0x46a2, 0x83ff, 0x0040, 0x4685, 0x6848, + 0xa606, 0x0040, 0x4692, 0x0078, 0x468d, 0x683c, 0xa406, 0x00c0, + 0x468d, 0x6840, 0xa506, 0x0040, 0x4692, 0x2d08, 0x6800, 0x2068, + 0x0078, 0x4679, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x469a, 0x624e, + 0x0078, 0x469d, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x46a2, + 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x46a9, 0x2019, + 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x46d5, 0x83ff, + 0x0040, 0x46b8, 0x6848, 0xa606, 0x0040, 0x46c5, 0x0078, 0x46c0, + 0x683c, 0xa406, 0x00c0, 0x46c0, 0x6840, 0xa506, 0x0040, 0x46c5, + 0x2d08, 0x6800, 0x2068, 0x0078, 0x46ac, 0x6a00, 0x6080, 0xad06, + 0x00c0, 0x46cd, 0x6282, 0x0078, 0x46d0, 0xa180, 0x0000, 0x2202, + 0x82ff, 0x00c0, 0x46d5, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078, + 0x4742, 0x00c0, 0x46dd, 0x2011, 0x0001, 0x1078, 0x4793, 0x00c0, + 0x46e3, 0xa295, 0x0002, 0x007c, 0x1078, 0x47cb, 0x0040, 0x46ec, + 0x1078, 0x8b12, 0x0078, 0x46ee, 0xa085, 0x0001, 0x007c, 0x1078, + 0x47cb, 0x0040, 0x46f7, 0x1078, 0x8aaa, 0x0078, 0x46f9, 0xa085, + 0x0001, 0x007c, 0x1078, 0x47cb, 0x0040, 0x4702, 0x1078, 0x8af4, + 0x0078, 0x4704, 0xa085, 0x0001, 0x007c, 0x1078, 0x47cb, 0x0040, + 0x470d, 0x1078, 0x8ac6, 0x0078, 0x470f, 0xa085, 0x0001, 0x007c, + 0x1078, 0x47cb, 0x0040, 0x4718, 0x1078, 0x8b30, 0x0078, 0x471a, + 0xa085, 0x0001, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000, + 0x6080, 0xa06d, 0x0040, 0x473a, 0x6800, 0x007e, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x007e, 0x6000, 0xd0fc, + 0x0040, 0x4734, 0x1078, 0xa18c, 0x007f, 0x1078, 0x4982, 0x007f, + 0x0078, 0x4721, 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f, + 0x127f, 0x007c, 0x60a4, 0xa00d, 0x00c0, 0x4749, 0xa085, 0x0001, + 0x007c, 0x0e7e, 0x2170, 0x7000, 0xa005, 0x00c0, 0x475c, 0x20a9, + 0x0010, 0xae88, 0x0004, 0x2104, 0xa606, 0x0040, 0x475c, 0x8108, + 0x00f0, 0x4753, 0xa085, 0x0001, 0xa006, 0x0e7f, 0x007c, 0x0d7e, + 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x476d, 0x1078, + 0x1381, 0x0040, 0x477f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, + 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, + 0x00f0, 0x4775, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, + 0x0078, 0x477c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, + 0x0040, 0x4790, 0x60a7, 0x0000, 0x1078, 0x139a, 0xa085, 0x0001, + 0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x479a, 0xa085, + 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x47ad, + 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x47ad, + 0x8108, 0x00f0, 0x47a4, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e, + 0x2091, 0x8000, 0x1078, 0x4793, 0x00c0, 0x47c9, 0x200b, 0xffff, + 0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x47c4, + 0x8001, 0x6856, 0x0078, 0x47c8, 0x1078, 0x139a, 0x60ab, 0x0000, + 0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71ac, + 0x81ff, 0x00c0, 0x47e9, 0x71c8, 0xd19c, 0x0040, 0x47e9, 0x2001, + 0x007e, 0xa080, 0xa434, 0x2004, 0xa07d, 0x0040, 0x47e9, 0x7804, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x47e9, 0x7800, 0xc0ed, + 0x7802, 0x2079, 0xa351, 0x7804, 0xd0a4, 0x0040, 0x480f, 0x157e, + 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, + 0x00c0, 0x4809, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, + 0x0040, 0x4806, 0xa086, 0x0006, 0x00c0, 0x4809, 0x6000, 0xc0ed, + 0x6002, 0x017f, 0x8108, 0x00f0, 0x47f5, 0x0c7f, 0x157f, 0x1078, + 0x4897, 0x0040, 0x4818, 0x2001, 0xa59f, 0x200c, 0x0078, 0x4820, + 0x2079, 0xa351, 0x7804, 0xd0a4, 0x0040, 0x4824, 0x2009, 0x07d0, + 0x2011, 0x4826, 0x1078, 0x596c, 0x0f7f, 0x007c, 0x2011, 0x4826, + 0x1078, 0x58d4, 0x1078, 0x4897, 0x0040, 0x484e, 0x2001, 0xa4b2, + 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa352, + 0x2004, 0xd0a4, 0x0040, 0x4842, 0x2009, 0x07d0, 0x2011, 0x4826, + 0x1078, 0x596c, 0x0e7e, 0x2071, 0xa300, 0x706b, 0x0000, 0x706f, + 0x0000, 0x1078, 0x260d, 0x0e7f, 0x0078, 0x4886, 0x157e, 0x0c7e, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, + 0x4880, 0x6000, 0xd0ec, 0x0040, 0x4880, 0x047e, 0x62a0, 0xa294, + 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x9ec0, 0x6000, + 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, + 0x6006, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, + 0x1078, 0x5c78, 0x2009, 0x0000, 0x1078, 0x9c38, 0x077f, 0x047f, + 0x017f, 0x8108, 0x00f0, 0x4854, 0x0c7f, 0x157f, 0x007c, 0x0c7e, + 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818, + 0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e, + 0x2001, 0xa4b2, 0x2004, 0xa07d, 0x0040, 0x48a0, 0x7800, 0xd0ec, + 0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x6200, 0xa005, + 0x0040, 0x48ad, 0xc2fd, 0x0078, 0x48ae, 0xc2fc, 0x6202, 0x027f, + 0x127f, 0x007c, 0x2071, 0xa413, 0x7003, 0x0001, 0x7007, 0x0000, + 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, + 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020, + 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa57c, 0x7003, 0xa413, + 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa55c, 0x7013, 0x0020, + 0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, 0x2071, + 0xa534, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xa352, + 0x2004, 0xd0fc, 0x00c0, 0x48f7, 0x2001, 0xa352, 0x2004, 0xa00e, + 0xd09c, 0x0040, 0x48f4, 0x8108, 0x7102, 0x0078, 0x494a, 0x2001, + 0xa371, 0x200c, 0xa184, 0x000f, 0x2009, 0xa372, 0x210c, 0x0079, + 0x4901, 0x48ec, 0x4922, 0x492a, 0x4935, 0x493b, 0x48ec, 0x48ec, + 0x48ec, 0x4911, 0x48ec, 0x48ec, 0x48ec, 0x48ec, 0x48ec, 0x48ec, + 0x48ec, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099, 0xa375, + 0x20a1, 0xa585, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f, + 0x0078, 0x494a, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, + 0x0078, 0x4930, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003, + 0x7002, 0x7097, 0x0001, 0x0078, 0x4947, 0x7007, 0x0122, 0x2001, + 0x0002, 0x0078, 0x493f, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, + 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, 0xa184, + 0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, 0xa413, + 0x684c, 0xa005, 0x00c0, 0x495b, 0x7028, 0xc085, 0x702a, 0xa085, + 0x0001, 0x0078, 0x4980, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, + 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, + 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006, + 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, + 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, + 0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0, 0x49d8, + 0x6804, 0xa00d, 0x0040, 0x499e, 0x0d7e, 0x2071, 0xa300, 0xa016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x00c0, + 0x4991, 0x702e, 0x70a8, 0xa200, 0x70aa, 0x0d7f, 0x2071, 0xa413, + 0x701c, 0xa005, 0x00c0, 0x49ea, 0x0068, 0x49e8, 0x2071, 0xa534, + 0x7200, 0x82ff, 0x0040, 0x49e8, 0x6934, 0xa186, 0x0103, 0x00c0, + 0x49fb, 0x6948, 0x6844, 0xa105, 0x00c0, 0x49db, 0x2009, 0x8020, + 0x2200, 0x0079, 0x49bb, 0x49e8, 0x49c0, 0x4a18, 0x4a26, 0x49e8, + 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x49e8, 0x7122, 0x683c, + 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x2071, + 0xa300, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a8, 0x8000, 0x70aa, + 0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, 0x49e8, + 0x6868, 0xa005, 0x00c0, 0x49e8, 0x2009, 0x8020, 0x0078, 0x49b8, + 0x2071, 0xa413, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012, + 0x7018, 0xa06d, 0x711a, 0x0040, 0x49f8, 0x6902, 0x0078, 0x49f9, + 0x711e, 0x0078, 0x49d8, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040, + 0x4a09, 0xa186, 0x001e, 0x0040, 0x4a09, 0xa18e, 0x001f, 0x00c0, + 0x49e8, 0x684c, 0xd0cc, 0x0040, 0x49e8, 0x6850, 0xa084, 0x00ff, + 0xa086, 0x0001, 0x00c0, 0x49e8, 0x2009, 0x8021, 0x0078, 0x49b8, + 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x49e8, 0x7186, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4a36, 0x7084, 0x8008, + 0xa092, 0x000f, 0x00c8, 0x49e8, 0x7186, 0xae90, 0x0003, 0x8003, + 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, + 0x0048, 0x49cf, 0x718c, 0x7084, 0xa10a, 0x0048, 0x49cf, 0x2071, + 0x0000, 0x7018, 0xd084, 0x00c0, 0x49cf, 0x2071, 0xa534, 0x7000, + 0xa086, 0x0002, 0x00c0, 0x4a56, 0x1078, 0x4cd2, 0x2071, 0x0000, + 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x49cf, 0x1078, 0x4cfd, + 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x49cf, + 0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, + 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084, 0x00ff, + 0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa413, 0x7004, + 0x0079, 0x4a7a, 0x4a84, 0x4a95, 0x4ca3, 0x4ca4, 0x4ccb, 0x4cd1, + 0x4a85, 0x4c91, 0x4c32, 0x4cb4, 0x007c, 0x127e, 0x2091, 0x8000, + 0x0068, 0x4a94, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, + 0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa5be, 0x6844, + 0xa005, 0x0050, 0x4abd, 0x00c0, 0x4abd, 0x127e, 0x2091, 0x8000, + 0x2069, 0x0000, 0x6934, 0x2001, 0xa41f, 0x2004, 0xa10a, 0x0040, + 0x4ab8, 0x0068, 0x4abc, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, + 0x4abc, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, + 0x2069, 0xa5be, 0x6847, 0xffff, 0x127f, 0x2069, 0xa300, 0x6844, + 0x6960, 0xa102, 0x2069, 0xa534, 0x688a, 0x6984, 0x701c, 0xa06d, + 0x0040, 0x4acf, 0x81ff, 0x0040, 0x4b17, 0x0078, 0x4ae5, 0x81ff, + 0x0040, 0x4be9, 0x2071, 0xa534, 0x7184, 0x7088, 0xa10a, 0x00c8, + 0x4ae5, 0x7190, 0x2071, 0xa5be, 0x7040, 0xa005, 0x0040, 0x4ae5, + 0x00d0, 0x4be9, 0x7142, 0x0078, 0x4be9, 0x2071, 0xa534, 0x718c, + 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4c06, 0x0068, + 0x4b9b, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4b9b, 0x2001, + 0xffff, 0x2071, 0xa5be, 0x7042, 0x2071, 0xa534, 0x7000, 0xa086, + 0x0002, 0x00c0, 0x4b0d, 0x1078, 0x4cd2, 0x2071, 0x0000, 0x701b, + 0x0001, 0x2091, 0x4080, 0x0078, 0x4b9b, 0x1078, 0x4cfd, 0x2071, + 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4b9b, 0x2071, + 0xa534, 0x7000, 0xa005, 0x0040, 0x4bc8, 0x6934, 0xa186, 0x0103, + 0x00c0, 0x4b9e, 0x684c, 0xd0bc, 0x00c0, 0x4bc8, 0x6948, 0x6844, + 0xa105, 0x00c0, 0x4bbb, 0x2009, 0x8020, 0x2071, 0xa534, 0x7000, + 0x0079, 0x4b32, 0x4bc8, 0x4b80, 0x4b58, 0x4b6a, 0x4b37, 0x137e, + 0x147e, 0x157e, 0x2099, 0xa375, 0x20a1, 0xa585, 0x20a9, 0x0004, + 0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa57c, 0xad80, 0x000f, + 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, 0x2e10, + 0x1078, 0x13d1, 0x2071, 0xa413, 0x7007, 0x0009, 0x0078, 0x4be9, + 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4be9, 0xae90, 0x0003, + 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa413, 0x1078, 0x4d5b, + 0x0078, 0x4be9, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, 0x4be9, + 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, + 0x2012, 0x7186, 0x2071, 0xa413, 0x1078, 0x4d5b, 0x0078, 0x4be9, + 0x127e, 0x2091, 0x8000, 0x0068, 0x4b9b, 0x2071, 0x0000, 0x7018, + 0xd084, 0x00c0, 0x4b9b, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, + 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa413, 0x1078, + 0x4d5b, 0x0078, 0x4be9, 0x127f, 0x0078, 0x4be9, 0xa18c, 0x00ff, + 0xa186, 0x0017, 0x0040, 0x4bac, 0xa186, 0x001e, 0x0040, 0x4bac, + 0xa18e, 0x001f, 0x00c0, 0x4bc8, 0x684c, 0xd0cc, 0x0040, 0x4bc8, + 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4bc8, 0x2009, + 0x8021, 0x0078, 0x4b2d, 0x6844, 0xa086, 0x0100, 0x00c0, 0x4bc8, + 0x6868, 0xa005, 0x00c0, 0x4bc8, 0x2009, 0x8020, 0x0078, 0x4b2d, + 0x2071, 0xa413, 0x1078, 0x4d6f, 0x0040, 0x4be9, 0x2071, 0xa413, + 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x00c0, + 0x4be0, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4be0, 0x710e, + 0x7007, 0x0003, 0x1078, 0x4d8f, 0x7050, 0xa086, 0x0100, 0x0040, + 0x4ca4, 0x127e, 0x2091, 0x8000, 0x2071, 0xa413, 0x7008, 0xa086, + 0x0001, 0x00c0, 0x4c04, 0x0068, 0x4c04, 0x2009, 0x000d, 0x7030, + 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, + 0x00c0, 0x4c04, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071, 0xa413, + 0x1078, 0x4d6f, 0x0040, 0x4c2f, 0x2071, 0xa534, 0x7084, 0x700a, + 0x20a9, 0x0020, 0x2099, 0xa535, 0x20a1, 0xa55c, 0x53a3, 0x7087, + 0x0000, 0x2071, 0xa413, 0x2069, 0xa57c, 0x706c, 0x6826, 0x7070, + 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, 0x13d1, + 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa5be, 0x7042, 0x127f, + 0x0078, 0x4be9, 0x2069, 0xa57c, 0x6808, 0xa08e, 0x0000, 0x0040, + 0x4c90, 0xa08e, 0x0200, 0x0040, 0x4c8e, 0xa08e, 0x0100, 0x00c0, + 0x4c90, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8b, 0x2069, 0x0000, + 0x6818, 0xd084, 0x00c0, 0x4c8b, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0048, 0x4c59, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0078, + 0x4c63, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4c63, 0x7070, + 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001, + 0xa559, 0x2004, 0xa005, 0x00c0, 0x4c82, 0x6934, 0x2069, 0xa534, + 0x689c, 0x699e, 0x2069, 0xa5be, 0xa102, 0x00c0, 0x4c7b, 0x6844, + 0xa005, 0x00d0, 0x4c89, 0x2001, 0xa55a, 0x200c, 0x810d, 0x6946, + 0x0078, 0x4c89, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, + 0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4c90, 0x7007, 0x0005, + 0x007c, 0x701c, 0xa06d, 0x0040, 0x4ca2, 0x1078, 0x4d6f, 0x0040, + 0x4ca2, 0x7007, 0x0003, 0x1078, 0x4d8f, 0x7050, 0xa086, 0x0100, + 0x0040, 0x4ca4, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, 0x00c0, + 0x4cad, 0x7007, 0x0004, 0x0078, 0x4ccb, 0xa086, 0x0200, 0x00c0, + 0x4cb3, 0x7007, 0x0005, 0x007c, 0x2001, 0xa57e, 0x2004, 0xa08e, + 0x0100, 0x00c0, 0x4cc0, 0x7007, 0x0001, 0x1078, 0x4d5b, 0x007c, + 0xa08e, 0x0000, 0x0040, 0x4cbf, 0xa08e, 0x0200, 0x00c0, 0x4cbf, + 0x7007, 0x0005, 0x007c, 0x1078, 0x4d25, 0x7006, 0x1078, 0x4d5b, + 0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa534, 0x7184, 0x81ff, + 0x0040, 0x4cfa, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, + 0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4cf7, 0x2014, 0x722a, + 0x8000, 0x0070, 0x4cf7, 0x2014, 0x722e, 0x8000, 0x0070, 0x4cf7, + 0x2014, 0x723a, 0x8000, 0x0070, 0x4cf7, 0x2014, 0x723e, 0xa180, + 0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e, 0x2071, + 0xa534, 0x7184, 0x81ff, 0x0040, 0x4d22, 0xa006, 0x7086, 0xae80, + 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, + 0x722a, 0x8000, 0x0070, 0x4d1b, 0x2014, 0x723a, 0x8000, 0x2014, + 0x723e, 0x0078, 0x4d1f, 0x2001, 0x8020, 0x0078, 0x4d21, 0x2001, + 0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130, 0x8108, + 0xa102, 0x0048, 0x4d32, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, + 0x0078, 0x4d3c, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d3c, + 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, + 0x00c0, 0x4d52, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d55, 0x2001, + 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, 0x0000, + 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x700b, + 0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d6e, 0x127e, + 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005, + 0x00c0, 0x4d6b, 0x701a, 0x127f, 0x1078, 0x139a, 0x007c, 0x2019, + 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4d7e, 0x2304, 0x230c, + 0xa10e, 0x0040, 0x4d7e, 0xa006, 0x0078, 0x4d8e, 0x732c, 0x8319, + 0x7130, 0xa102, 0x00c0, 0x4d88, 0x2300, 0xa005, 0x0078, 0x4d8e, + 0x0048, 0x4d8d, 0xa302, 0x0078, 0x4d8e, 0x8002, 0x007c, 0x2d00, + 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, 0x2091, + 0x8000, 0x2009, 0xa5d0, 0x2104, 0xc08d, 0x200a, 0x127f, 0x1078, + 0x13eb, 0x007c, 0x2071, 0xa3e1, 0x7003, 0x0000, 0x7007, 0x0000, + 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001, + 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000, + 0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa3e1, + 0x6848, 0xa005, 0x00c0, 0x4dcb, 0x7028, 0xc085, 0x702a, 0xa085, + 0x0001, 0x0078, 0x4df0, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, + 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, + 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, + 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, + 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, + 0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa3e1, 0x7004, 0x1079, 0x4e50, + 0x700c, 0x0079, 0x4dfb, 0x4e00, 0x4df5, 0x4df5, 0x4df5, 0x4df5, + 0x007c, 0x700c, 0x0079, 0x4e04, 0x4e09, 0x4e4e, 0x4e4e, 0x4e4f, + 0x4e4f, 0x7830, 0x7930, 0xa106, 0x0040, 0x4e13, 0x7830, 0x7930, + 0xa106, 0x00c0, 0x4e39, 0x7030, 0xa10a, 0x0040, 0x4e39, 0x00c8, + 0x4e1b, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4e3a, 0x1078, + 0x1366, 0x0040, 0x4e39, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, + 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, 0x2009, + 0xa5d0, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f, 0x1078, + 0x13eb, 0x007c, 0x1078, 0x1366, 0x0040, 0x4e39, 0x2d00, 0x705a, + 0x1078, 0x1366, 0x00c0, 0x4e46, 0x0078, 0x4e25, 0x2d00, 0x7086, + 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4e29, 0x007c, 0x007c, + 0x4e61, 0x4e62, 0x4e99, 0x4e9a, 0x4e4e, 0x4ed0, 0x4ed5, 0x4f0c, + 0x4f0d, 0x4f28, 0x4f29, 0x4f2a, 0x4f2b, 0x4f2c, 0x4f2d, 0x4fad, + 0x4fd7, 0x007c, 0x700c, 0x0079, 0x4e65, 0x4e6a, 0x4e6d, 0x4e7d, + 0x4e98, 0x4e98, 0x1078, 0x4e01, 0x007c, 0x127e, 0x8001, 0x700e, + 0x7058, 0x007e, 0x1078, 0x5348, 0x0040, 0x4e7a, 0x2091, 0x8000, + 0x1078, 0x4e01, 0x0d7f, 0x0078, 0x4e86, 0x127e, 0x8001, 0x700e, + 0x1078, 0x5348, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, + 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, 0x00c8, + 0x4e95, 0x1079, 0x4eb0, 0x127f, 0x007c, 0x127f, 0x1078, 0x4f2e, + 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa3e1, 0x700c, 0x0079, + 0x4ea1, 0x4ea6, 0x4ea6, 0x4ea6, 0x4ea8, 0x4eac, 0x0e7f, 0x007c, + 0x700f, 0x0001, 0x0078, 0x4eae, 0x700f, 0x0002, 0x0e7f, 0x007c, + 0x4f2e, 0x4f2e, 0x4f4a, 0x4f2e, 0x5080, 0x4f2e, 0x4f2e, 0x4f2e, + 0x4f2e, 0x4f2e, 0x4f4a, 0x50ca, 0x5117, 0x5170, 0x5186, 0x4f2e, + 0x4f2e, 0x4f66, 0x4f4a, 0x4f2e, 0x4f2e, 0x4f87, 0x5245, 0x5263, + 0x4f2e, 0x4f66, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f7c, 0x5263, + 0x7020, 0x2068, 0x1078, 0x139a, 0x007c, 0x700c, 0x0079, 0x4ed8, + 0x4edd, 0x4ee0, 0x4ef0, 0x4f0b, 0x4f0b, 0x1078, 0x4e01, 0x007c, + 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5348, 0x0040, + 0x4eed, 0x2091, 0x8000, 0x1078, 0x4e01, 0x0d7f, 0x0078, 0x4ef9, + 0x127e, 0x8001, 0x700e, 0x1078, 0x5348, 0x7058, 0x2068, 0x7084, + 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, + 0xa08a, 0x001a, 0x00c8, 0x4f08, 0x1079, 0x4f0e, 0x127f, 0x007c, + 0x127f, 0x1078, 0x4f2e, 0x007c, 0x007c, 0x007c, 0x4f2e, 0x4f4a, + 0x506a, 0x4f2e, 0x4f4a, 0x4f2e, 0x4f4a, 0x4f4a, 0x4f2e, 0x4f4a, + 0x506a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f2e, 0x4f4a, + 0x506a, 0x4f2e, 0x4f2e, 0x4f4a, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f4a, + 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, 0x0001, + 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, 0x8000, + 0x1078, 0x4982, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, + 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982, + 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, + 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982, 0x127f, 0x007c, + 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x127e, + 0x2091, 0x8000, 0x1078, 0x4982, 0x127f, 0x007c, 0x6834, 0x8007, + 0xa084, 0x00ff, 0x0040, 0x4f3c, 0x8001, 0x00c0, 0x4f73, 0x7007, + 0x0001, 0x0078, 0x5049, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, + 0x701a, 0x704b, 0x5049, 0x007c, 0x684c, 0xa084, 0x00c0, 0xa086, + 0x00c0, 0x00c0, 0x4f87, 0x7007, 0x0001, 0x0078, 0x5280, 0x2d00, + 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, + 0xa40c, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, 0x4f58, + 0x6884, 0xa08a, 0x0002, 0x00c8, 0x4f58, 0x82ff, 0x00c0, 0x4fa9, + 0x6888, 0x698c, 0xa105, 0x0040, 0x4fa9, 0x2001, 0x5019, 0x0078, + 0x4fac, 0xa280, 0x500f, 0x2004, 0x70c6, 0x7010, 0xa015, 0x0040, + 0x4ff7, 0x1078, 0x1366, 0x00c0, 0x4fb8, 0x7007, 0x000f, 0x007c, + 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, 0xad00, + 0x7096, 0x6008, 0xa20a, 0x00c8, 0x4fc7, 0xa00e, 0x2200, 0x7112, + 0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x4fd0, 0xa108, + 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13d1, 0x7090, + 0xa08e, 0x0100, 0x0040, 0x4feb, 0xa086, 0x0200, 0x0040, 0x4fe3, + 0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x139a, 0x7014, + 0x2068, 0x0078, 0x4f58, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, + 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x4fad, 0x7014, + 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x5006, 0x6888, + 0x698c, 0xa105, 0x0040, 0x5006, 0x1078, 0x501d, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001e, 0x0040, 0x5280, 0x0078, 0x5049, 0x5011, + 0x5015, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005, + 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e, 0x0c7e, + 0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021, + 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812, + 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0040, + 0x503f, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x502c, 0x6004, + 0xa065, 0x00c0, 0x5026, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x0f7f, + 0x007c, 0x2009, 0xa32e, 0x210c, 0x81ff, 0x00c0, 0x5064, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x1078, 0x4290, 0x00c0, 0x5058, 0x007c, + 0x1078, 0x4a60, 0x127e, 0x2091, 0x8000, 0x1078, 0x8cb8, 0x1078, + 0x4982, 0x127f, 0x0078, 0x5057, 0x2001, 0x0028, 0x2009, 0x0000, + 0x0078, 0x5058, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, + 0x7010, 0x8001, 0x7012, 0x0040, 0x5079, 0x7007, 0x0006, 0x0078, + 0x507f, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, 0x007c, + 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, + 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x50a9, 0x2009, + 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x50a9, 0xa005, + 0x00c0, 0x50bc, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x4501, + 0x00c0, 0x50bc, 0x067e, 0x6e50, 0x1078, 0x45e7, 0x067f, 0x0078, + 0x50bc, 0x047e, 0x2011, 0xa30c, 0x2224, 0xc484, 0xc48c, 0x2412, + 0x047f, 0x0c7e, 0x1078, 0x4501, 0x00c0, 0x50b8, 0x1078, 0x4782, + 0x8108, 0x00f0, 0x50b2, 0x0c7f, 0x684c, 0xd084, 0x00c0, 0x50c3, + 0x1078, 0x139a, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982, + 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, + 0xa352, 0x2004, 0xd0a4, 0x0040, 0x510e, 0x2061, 0xa62d, 0x6100, + 0xd184, 0x0040, 0x50ee, 0x6858, 0xa084, 0x00ff, 0x00c0, 0x5111, + 0x6000, 0xd084, 0x0040, 0x510e, 0x6004, 0xa005, 0x00c0, 0x5114, + 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x510b, 0x2011, 0x0001, + 0x6860, 0xa005, 0x00c0, 0x50f6, 0x2001, 0x001e, 0x8000, 0x6016, + 0x6858, 0xa084, 0x00ff, 0x0040, 0x510e, 0x6006, 0x6858, 0x8007, + 0xa084, 0x00ff, 0x0040, 0x510e, 0x600a, 0x6858, 0x8000, 0x00c0, + 0x510a, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5337, 0x127f, 0x0078, + 0x532f, 0x127f, 0x0078, 0x5327, 0x127f, 0x0078, 0x532b, 0x127e, + 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa352, 0x2004, 0xd0a4, + 0x0040, 0x516d, 0x2061, 0xa62d, 0x6000, 0xd084, 0x0040, 0x516d, + 0x6204, 0x6308, 0xd08c, 0x00c0, 0x515f, 0x6c48, 0xa484, 0x0003, + 0x0040, 0x5145, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x513e, + 0x2100, 0xa210, 0x0048, 0x516a, 0x0078, 0x5145, 0x8001, 0x00c0, + 0x516a, 0x2100, 0xa212, 0x0048, 0x516a, 0xa484, 0x000c, 0x0040, + 0x515f, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0, + 0x5157, 0x2100, 0xa318, 0x0048, 0x516a, 0x0078, 0x515f, 0xa082, + 0x0004, 0x00c0, 0x516a, 0x2100, 0xa31a, 0x0048, 0x516a, 0x6860, + 0xa005, 0x0040, 0x5165, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f, + 0x0078, 0x5337, 0x127f, 0x0078, 0x5333, 0x127f, 0x0078, 0x532f, + 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xa62d, 0x6300, + 0xd38c, 0x00c0, 0x5180, 0x6308, 0x8318, 0x0048, 0x5183, 0x630a, + 0x127f, 0x0078, 0x5345, 0x127f, 0x0078, 0x5333, 0x127e, 0x0c7e, + 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040, 0x519a, + 0x0c7e, 0x2061, 0xa62d, 0x6000, 0xa084, 0xfcff, 0x6002, 0x0c7f, + 0x0078, 0x51c9, 0x6858, 0xa005, 0x0040, 0x51e0, 0x685c, 0xa065, + 0x0040, 0x51dc, 0x2001, 0xa32e, 0x2004, 0xa005, 0x0040, 0x51ac, + 0x1078, 0x8c01, 0x0078, 0x51ba, 0x6013, 0x0400, 0x6037, 0x0000, + 0x694c, 0xd1a4, 0x0040, 0x51b6, 0x6950, 0x6136, 0x2009, 0x0041, + 0x1078, 0x756c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x00c0, + 0x51c9, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, 0x5a6d, + 0x027f, 0x684c, 0xd0c4, 0x0040, 0x51d8, 0x2061, 0xa62d, 0x6000, + 0xd08c, 0x00c0, 0x51d8, 0x6008, 0x8000, 0x0048, 0x51dc, 0x600a, + 0x0c7f, 0x127f, 0x0078, 0x5337, 0x0c7f, 0x127f, 0x0078, 0x532f, + 0x6954, 0xa186, 0x0045, 0x0040, 0x5213, 0xa186, 0x002a, 0x00c0, + 0x51f0, 0x2001, 0xa30c, 0x200c, 0xc194, 0x2102, 0x0078, 0x51c9, + 0xa186, 0x0020, 0x0040, 0x5209, 0xa186, 0x0029, 0x0040, 0x51fc, + 0xa186, 0x002d, 0x00c0, 0x51dc, 0x6944, 0xa18c, 0xff00, 0x810f, + 0x1078, 0x4501, 0x00c0, 0x51c9, 0x6000, 0xc0e4, 0x6002, 0x0078, + 0x51c9, 0x685c, 0xa065, 0x0040, 0x51dc, 0x2001, 0xa5a1, 0x2004, + 0x6016, 0x0078, 0x51c9, 0x685c, 0xa065, 0x0040, 0x51dc, 0x0e7e, + 0x6860, 0xa075, 0x2001, 0xa32e, 0x2004, 0xa005, 0x0040, 0x522b, + 0x1078, 0x8c01, 0x8eff, 0x0040, 0x5228, 0x2e60, 0x1078, 0x8c01, + 0x0e7f, 0x0078, 0x51c9, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, + 0x6007, 0x003a, 0x6870, 0xa005, 0x0040, 0x523c, 0x6007, 0x003b, + 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x1078, 0x5bf8, + 0x1078, 0x6109, 0x0e7f, 0x0078, 0x51c9, 0x2061, 0xa62d, 0x6000, + 0xd084, 0x0040, 0x525f, 0xd08c, 0x00c0, 0x5345, 0x2091, 0x8000, + 0x6204, 0x8210, 0x0048, 0x5259, 0x6206, 0x2091, 0x8001, 0x0078, + 0x5345, 0x2091, 0x8001, 0x6853, 0x0016, 0x0078, 0x533e, 0x6853, + 0x0007, 0x0078, 0x533e, 0x6834, 0x8007, 0xa084, 0x00ff, 0x00c0, + 0x526d, 0x1078, 0x4f3c, 0x0078, 0x527f, 0x2030, 0x8001, 0x00c0, + 0x5277, 0x7007, 0x0001, 0x1078, 0x5280, 0x0078, 0x527f, 0x7007, + 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5280, 0x007c, + 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2009, 0xa32e, 0x210c, 0x81ff, + 0x00c0, 0x530b, 0x2009, 0xa30c, 0x210c, 0xd194, 0x00c0, 0x5315, + 0x6848, 0x2070, 0xae82, 0xaa00, 0x0048, 0x52fb, 0x2001, 0xa315, + 0x2004, 0xae02, 0x00c8, 0x52fb, 0x2061, 0xa62d, 0x6100, 0xa184, + 0x0301, 0xa086, 0x0001, 0x00c0, 0x52de, 0x711c, 0xa186, 0x0006, + 0x00c0, 0x52e6, 0x7018, 0xa005, 0x0040, 0x530b, 0x2004, 0xd0e4, + 0x00c0, 0x530f, 0x7024, 0xd0dc, 0x00c0, 0x5319, 0x6853, 0x0000, + 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x00c0, 0x52ca, 0x7112, + 0x684c, 0xd0f4, 0x00c0, 0x531d, 0x2e60, 0x1078, 0x59b6, 0x127f, + 0x0e7f, 0x007c, 0x2068, 0x6800, 0xa005, 0x00c0, 0x52ca, 0x6902, + 0x2168, 0x684c, 0xd0f4, 0x00c0, 0x531d, 0x127f, 0x0e7f, 0x007c, + 0x127f, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x533e, 0xd184, 0x0040, + 0x52d8, 0xd1c4, 0x00c0, 0x52ff, 0x0078, 0x5303, 0x6944, 0xa18c, + 0xff00, 0x810f, 0x1078, 0x4501, 0x00c0, 0x530f, 0x6000, 0xd0e4, + 0x00c0, 0x530f, 0x711c, 0xa186, 0x0007, 0x00c0, 0x52fb, 0x6853, + 0x0002, 0x0078, 0x5311, 0x6853, 0x0008, 0x0078, 0x5311, 0x6853, + 0x000e, 0x0078, 0x5311, 0x6853, 0x0017, 0x0078, 0x5311, 0x6853, + 0x0035, 0x0078, 0x5311, 0x6853, 0x0028, 0x0078, 0x5311, 0x6853, + 0x0029, 0x127f, 0x0e7f, 0x0078, 0x533e, 0x6853, 0x002a, 0x0078, + 0x5311, 0x6853, 0x0045, 0x0078, 0x5311, 0x2e60, 0x2019, 0x0002, + 0x6017, 0x0014, 0x1078, 0x9a6a, 0x127f, 0x0e7f, 0x007c, 0x2009, + 0x003e, 0x0078, 0x5339, 0x2009, 0x0004, 0x0078, 0x5339, 0x2009, + 0x0006, 0x0078, 0x5339, 0x2009, 0x0016, 0x0078, 0x5339, 0x2009, + 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x2091, 0x8000, + 0x1078, 0x4982, 0x2091, 0x8001, 0x007c, 0x1078, 0x139a, 0x007c, + 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, 0x5355, 0xa00e, 0x7034, + 0x7072, 0x7038, 0x7076, 0x0078, 0x5361, 0x7070, 0xa080, 0x0040, + 0x7072, 0x00c8, 0x5361, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, + 0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e, 0x1078, 0x59ad, 0x0d7f, + 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, + 0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, + 0xa084, 0x7000, 0x0040, 0x5380, 0xa086, 0x1000, 0x00c0, 0x53ac, + 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, 0xa084, 0xf000, + 0xa086, 0x3000, 0x00c0, 0x5390, 0x1078, 0x5570, 0x0078, 0x53a7, + 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x5397, 0x3e60, 0xac84, + 0x000f, 0x00c0, 0x53ac, 0xac82, 0xaa00, 0x0048, 0x53ac, 0x6854, + 0xac02, 0x00c8, 0x53ac, 0x2009, 0x0047, 0x1078, 0x756c, 0x7a1c, + 0xd284, 0x00c0, 0x5372, 0x007c, 0xa016, 0x1078, 0x15ec, 0x0078, + 0x53a7, 0x0078, 0x53ac, 0x781c, 0xd08c, 0x0040, 0x53db, 0x157e, + 0x137e, 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, + 0x00c0, 0x53f1, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x53e0, + 0x1078, 0x540c, 0x0040, 0x53f1, 0x20e1, 0x3000, 0x7828, 0x7828, + 0x1078, 0x542a, 0x147f, 0x137f, 0x157f, 0x2009, 0xa5b3, 0x2104, + 0xa005, 0x00c0, 0x53dc, 0x007c, 0x1078, 0x6109, 0x0078, 0x53db, + 0xa484, 0x7000, 0x00c0, 0x53f1, 0x1078, 0x540c, 0x0040, 0x5403, + 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x53cc, 0x0078, + 0x5403, 0x1078, 0xa1ee, 0xd5a4, 0x0040, 0x53ff, 0x1078, 0x1af7, + 0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5407, 0x1078, + 0x540c, 0x687f, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f, + 0x137f, 0x157f, 0x0078, 0x53db, 0xa484, 0x01ff, 0x687e, 0xa005, + 0x0040, 0x541e, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1, + 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9, 0x000c, + 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, + 0x0078, 0x541d, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007, + 0xa196, 0x0000, 0x00c0, 0x5437, 0x0078, 0x567c, 0x007c, 0xa196, + 0x2000, 0x00c0, 0x5448, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x5444, + 0x1078, 0x3a43, 0x0078, 0x5436, 0x1078, 0x5450, 0x0078, 0x5436, + 0xa196, 0x8000, 0x00c0, 0x5436, 0x1078, 0x570c, 0x0078, 0x5436, + 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040, + 0x545d, 0xa196, 0x0023, 0x00c0, 0x5568, 0xa08e, 0x0023, 0x00c0, + 0x5492, 0x1078, 0x57b2, 0x0040, 0x5568, 0x7124, 0x610a, 0x7030, + 0xa08e, 0x0200, 0x00c0, 0x5476, 0x7034, 0xa005, 0x00c0, 0x5568, + 0x2009, 0x0015, 0x1078, 0x756c, 0x0078, 0x5568, 0xa08e, 0x0214, + 0x0040, 0x547e, 0xa08e, 0x0210, 0x00c0, 0x5484, 0x2009, 0x0015, + 0x1078, 0x756c, 0x0078, 0x5568, 0xa08e, 0x0100, 0x00c0, 0x5568, + 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009, 0x0016, 0x1078, 0x756c, + 0x0078, 0x5568, 0xa08e, 0x0022, 0x00c0, 0x5568, 0x7030, 0xa08e, + 0x0300, 0x00c0, 0x54a3, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009, + 0x0017, 0x0078, 0x5534, 0xa08e, 0x0500, 0x00c0, 0x54af, 0x7034, + 0xa005, 0x00c0, 0x5568, 0x2009, 0x0018, 0x0078, 0x5534, 0xa08e, + 0x2010, 0x00c0, 0x54b7, 0x2009, 0x0019, 0x0078, 0x5534, 0xa08e, + 0x2110, 0x00c0, 0x54bf, 0x2009, 0x001a, 0x0078, 0x5534, 0xa08e, + 0x5200, 0x00c0, 0x54cb, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009, + 0x001b, 0x0078, 0x5534, 0xa08e, 0x5000, 0x00c0, 0x54d7, 0x7034, + 0xa005, 0x00c0, 0x5568, 0x2009, 0x001c, 0x0078, 0x5534, 0xa08e, + 0x1300, 0x00c0, 0x54df, 0x2009, 0x0034, 0x0078, 0x5534, 0xa08e, + 0x1200, 0x00c0, 0x54eb, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009, + 0x0024, 0x0078, 0x5534, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x00c0, + 0x54f5, 0x2009, 0x002d, 0x0078, 0x5534, 0xa08c, 0xff00, 0xa18e, + 0x5300, 0x00c0, 0x54ff, 0x2009, 0x002a, 0x0078, 0x5534, 0xa08e, + 0x0f00, 0x00c0, 0x5507, 0x2009, 0x0020, 0x0078, 0x5534, 0xa08e, + 0x5300, 0x00c0, 0x550d, 0x0078, 0x552a, 0xa08e, 0x6104, 0x00c0, + 0x552a, 0x2011, 0xa88d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, + 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, 0x047e, 0x2124, + 0x1078, 0x3579, 0x047f, 0x8108, 0x00f0, 0x551a, 0x2009, 0x0023, + 0x0078, 0x5534, 0xa08e, 0x6000, 0x00c0, 0x5532, 0x2009, 0x003f, + 0x0078, 0x5534, 0x2009, 0x001d, 0x017e, 0x2011, 0xa883, 0x2204, + 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x556a, 0x1078, 0x4499, + 0x00c0, 0x556a, 0x6612, 0x6516, 0x86ff, 0x0040, 0x555a, 0x017f, + 0x017e, 0xa186, 0x0017, 0x00c0, 0x555a, 0x6868, 0xa606, 0x00c0, + 0x555a, 0x686c, 0xa506, 0xa084, 0xff00, 0x00c0, 0x555a, 0x6000, + 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x74d7, 0x0040, 0x556d, 0x017f, + 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x756c, + 0x0c7f, 0x007c, 0x017f, 0x0078, 0x5568, 0x0c7f, 0x0078, 0x556a, + 0x0c7e, 0x1078, 0x55d4, 0x00c0, 0x55d2, 0xa184, 0xff00, 0x8007, + 0xa086, 0x0008, 0x00c0, 0x55d2, 0xa28e, 0x0033, 0x00c0, 0x55a3, + 0x1078, 0x57b2, 0x0040, 0x55d2, 0x7124, 0x610a, 0x7030, 0xa08e, + 0x0200, 0x00c0, 0x5595, 0x7034, 0xa005, 0x00c0, 0x55d2, 0x2009, + 0x0015, 0x1078, 0x756c, 0x0078, 0x55d2, 0xa08e, 0x0100, 0x00c0, + 0x55d2, 0x7034, 0xa005, 0x00c0, 0x55d2, 0x2009, 0x0016, 0x1078, + 0x756c, 0x0078, 0x55d2, 0xa28e, 0x0032, 0x00c0, 0x55d2, 0x7030, + 0xa08e, 0x1400, 0x00c0, 0x55d2, 0x2009, 0x0038, 0x017e, 0x2011, + 0xa883, 0x2204, 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x55d1, + 0x1078, 0x4499, 0x00c0, 0x55d1, 0x6612, 0x6516, 0x0c7e, 0x1078, + 0x74d7, 0x0040, 0x55d0, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120, + 0x610a, 0x017f, 0x1078, 0x756c, 0x1078, 0x6109, 0x0078, 0x55d2, + 0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0d7e, 0x027e, 0x017e, + 0x137e, 0x147e, 0x157e, 0x3c00, 0x007e, 0x2079, 0x0030, 0x2069, + 0x0200, 0x1078, 0x1c25, 0x00c0, 0x5615, 0x1078, 0x1b15, 0x0040, + 0x561f, 0x7908, 0xa18c, 0x1fff, 0xa182, 0x0011, 0x00c8, 0x561f, + 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, 0x2099, 0x020a, 0x53a5, + 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x7a0c, 0x7808, 0xa080, + 0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140, 0x10c8, 0x1328, 0x80ac, + 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, + 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, 0x007f, 0x20e0, 0x157f, + 0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f, 0x0f7f, 0x007c, 0xa085, + 0x0001, 0x0078, 0x5615, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130, + 0xa696, 0x00ff, 0x00c0, 0x5644, 0xa596, 0xfffd, 0x00c0, 0x5634, + 0x2009, 0x007f, 0x0078, 0x5677, 0xa596, 0xfffe, 0x00c0, 0x563c, + 0x2009, 0x007e, 0x0078, 0x5677, 0xa596, 0xfffc, 0x00c0, 0x5644, + 0x2009, 0x0080, 0x0078, 0x5677, 0x2011, 0x0000, 0x2021, 0x0081, + 0x20a9, 0x007e, 0x2071, 0xa4b5, 0x2e1c, 0x83ff, 0x00c0, 0x5656, + 0x82ff, 0x00c0, 0x566b, 0x2410, 0x0078, 0x566b, 0x2368, 0x6f10, + 0x007e, 0x2100, 0xa706, 0x007f, 0x6b14, 0x00c0, 0x5665, 0xa346, + 0x00c0, 0x5665, 0x2408, 0x0078, 0x5677, 0x87ff, 0x00c0, 0x566b, + 0x83ff, 0x0040, 0x5650, 0x8420, 0x8e70, 0x00f0, 0x564c, 0x82ff, + 0x00c0, 0x5676, 0xa085, 0x0001, 0x0078, 0x5678, 0x2208, 0xa006, + 0x0d7f, 0x0e7f, 0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x5681, + 0x007c, 0x5689, 0x5689, 0x5689, 0x57c8, 0x5689, 0x568a, 0x56a3, + 0x56f3, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x56a2, 0x7120, 0x2160, + 0xac8c, 0x000f, 0x00c0, 0x56a2, 0xac8a, 0xaa00, 0x0048, 0x56a2, + 0x6854, 0xac02, 0x00c8, 0x56a2, 0x7124, 0x610a, 0x2009, 0x0046, + 0x1078, 0x756c, 0x007c, 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x56f1, + 0x2011, 0xa883, 0x2204, 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, + 0x56f1, 0x1078, 0x4499, 0x00c0, 0x56f1, 0x6612, 0x6516, 0x6000, + 0xd0ec, 0x00c0, 0x56f1, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, + 0x0006, 0x00c0, 0x56d6, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, + 0x56f1, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6122, + 0x2009, 0x0044, 0x1078, 0x756c, 0x0078, 0x56f1, 0x0c7e, 0x1078, + 0x74d7, 0x017f, 0x0040, 0x56f1, 0x611a, 0x601f, 0x0004, 0x7120, + 0x610a, 0xa286, 0x0004, 0x00c0, 0x56e9, 0x6007, 0x0005, 0x0078, + 0x56eb, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5c45, 0x1078, + 0x6109, 0x0c7f, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x570b, 0x7020, + 0x2060, 0xac84, 0x000f, 0x00c0, 0x570b, 0xac82, 0xaa00, 0x0048, + 0x570b, 0x6854, 0xac02, 0x00c8, 0x570b, 0x7124, 0x610a, 0x2009, + 0x0045, 0x1078, 0x756c, 0x007c, 0x7110, 0xa18c, 0xff00, 0x810f, + 0xa18e, 0x0000, 0x00c0, 0x571c, 0xa084, 0x000f, 0xa08a, 0x0006, + 0x00c8, 0x571c, 0x1079, 0x571d, 0x007c, 0x5723, 0x5724, 0x5723, + 0x5723, 0x5794, 0x57a3, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x572c, + 0x702c, 0xd084, 0x0040, 0x5793, 0x700c, 0x7108, 0x1078, 0x24e3, + 0x00c0, 0x5793, 0x1078, 0x4499, 0x00c0, 0x5793, 0x6612, 0x6516, + 0x6204, 0x7110, 0xd1bc, 0x0040, 0x575e, 0xa28c, 0x00ff, 0xa186, + 0x0004, 0x0040, 0x5747, 0xa186, 0x0006, 0x00c0, 0x5784, 0x0c7e, + 0x1078, 0x57b2, 0x0c7f, 0x0040, 0x5793, 0x0c7e, 0x1078, 0x74d7, + 0x017f, 0x0040, 0x5793, 0x611a, 0x601f, 0x0002, 0x7120, 0x610a, + 0x2009, 0x0088, 0x1078, 0x756c, 0x0078, 0x5793, 0xa28c, 0x00ff, + 0xa186, 0x0006, 0x0040, 0x5773, 0xa186, 0x0004, 0x0040, 0x5773, + 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, 0x0040, 0x5773, 0xa286, + 0x0006, 0x00c0, 0x5784, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, + 0x5793, 0x611a, 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, + 0x1078, 0x756c, 0x0078, 0x5793, 0x0c7e, 0x1078, 0x74d7, 0x017f, + 0x0040, 0x5793, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009, + 0x0001, 0x1078, 0x756c, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x57a2, + 0x1078, 0x57b2, 0x0040, 0x57a2, 0x7124, 0x610a, 0x2009, 0x0089, + 0x1078, 0x756c, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x57b1, 0x1078, + 0x57b2, 0x0040, 0x57b1, 0x7124, 0x610a, 0x2009, 0x008a, 0x1078, + 0x756c, 0x007c, 0x7020, 0x2060, 0xac84, 0x000f, 0x00c0, 0x57c5, + 0xac82, 0xaa00, 0x0048, 0x57c5, 0x2001, 0xa315, 0x2004, 0xac02, + 0x00c8, 0x57c5, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x57c4, + 0x7110, 0xd1bc, 0x00c0, 0x57de, 0x7024, 0x2060, 0xac84, 0x000f, + 0x00c0, 0x57de, 0xac82, 0xaa00, 0x0048, 0x57de, 0x6854, 0xac02, + 0x00c8, 0x57de, 0x2009, 0x0051, 0x1078, 0x756c, 0x007c, 0x2071, + 0xa5be, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012, + 0x7017, 0xaa00, 0x7007, 0x0000, 0x7026, 0x702b, 0x6c4e, 0x7032, + 0x7037, 0x6ca0, 0x703b, 0x0002, 0x703f, 0x0000, 0x7043, 0xffff, + 0x7047, 0xffff, 0x007c, 0x2071, 0xa5be, 0x00e0, 0x58c1, 0x2091, + 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x5873, 0x700f, 0x0361, + 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, 0x7138, 0x8109, 0x713a, + 0x00c0, 0x5871, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104, 0xa082, + 0x0003, 0x00c8, 0x5871, 0x703c, 0xa086, 0x0001, 0x00c0, 0x584e, + 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x582c, + 0x6803, 0x1000, 0x0078, 0x5833, 0x6804, 0xa084, 0x1000, 0x0040, + 0x5833, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000, 0x2069, + 0xa5ab, 0x6804, 0xa082, 0x0006, 0x00c0, 0x5840, 0x6807, 0x0000, + 0x6830, 0xa082, 0x0003, 0x00c0, 0x5847, 0x6833, 0x0000, 0x1078, + 0x6109, 0x1078, 0x61d3, 0x0d7f, 0x0078, 0x5871, 0x0d7e, 0x2069, + 0xa300, 0x6944, 0x6860, 0xa102, 0x00c8, 0x5870, 0x2069, 0xa5ab, + 0x6804, 0xa086, 0x0000, 0x00c0, 0x5870, 0x6830, 0xa086, 0x0000, + 0x00c0, 0x5870, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833, 0x0003, + 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, 0x0140, 0x6803, 0x0600, + 0x0d7f, 0x0078, 0x5876, 0x127e, 0x2091, 0x8000, 0x7024, 0xa00d, + 0x0040, 0x588e, 0x7020, 0x8001, 0x7022, 0x00c0, 0x588e, 0x7023, + 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, 0x00c0, 0x5889, 0x7028, + 0x107a, 0x81ff, 0x00c0, 0x588e, 0x7028, 0x107a, 0x7030, 0xa00d, + 0x0040, 0x589f, 0x702c, 0x8001, 0x702e, 0x00c0, 0x589f, 0x702f, + 0x0009, 0x8109, 0x7132, 0x00c0, 0x589f, 0x7034, 0x107a, 0x7040, + 0xa005, 0x0040, 0x58a7, 0x0050, 0x58a7, 0x8001, 0x7042, 0x7044, + 0xa005, 0x0040, 0x58af, 0x0050, 0x58af, 0x8001, 0x7046, 0x7018, + 0xa00d, 0x0040, 0x58c0, 0x7008, 0x8001, 0x700a, 0x00c0, 0x58c0, + 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x58c0, 0x701c, 0x107a, + 0x127f, 0x7004, 0x0079, 0x58c4, 0x58eb, 0x58ec, 0x5908, 0x0e7e, + 0x2071, 0xa5be, 0x7018, 0xa005, 0x00c0, 0x58d2, 0x711a, 0x721e, + 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, 0xa5be, + 0x701c, 0xa206, 0x00c0, 0x58de, 0x701a, 0x701e, 0x007f, 0x0e7f, + 0x007c, 0x0e7e, 0x2071, 0xa5be, 0x6088, 0xa102, 0x0048, 0x58e9, + 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x4501, 0x00c0, + 0x58fe, 0x6088, 0x8001, 0x0048, 0x58fe, 0x608a, 0x00c0, 0x58fe, + 0x127e, 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x8108, 0xa182, + 0x00ff, 0x0048, 0x5906, 0xa00e, 0x7007, 0x0002, 0x7112, 0x007c, + 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005, 0x0040, + 0x5917, 0x8001, 0x603e, 0x00c0, 0x5917, 0x1078, 0x8cd7, 0x6014, + 0xa005, 0x0040, 0x5941, 0x8001, 0x6016, 0x00c0, 0x5941, 0x611c, + 0xa186, 0x0003, 0x0040, 0x5928, 0xa186, 0x0006, 0x00c0, 0x593f, + 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x593f, 0xa082, + 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5938, 0x2001, 0x1999, + 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5941, 0x1078, + 0x8810, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xca00, 0xa102, + 0x0048, 0x594e, 0x7017, 0xaa00, 0x7007, 0x0000, 0x007c, 0x0e7e, + 0x2071, 0xa5be, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, 0x0002, + 0x0e7f, 0x007c, 0x2001, 0xa5c7, 0x2003, 0x0000, 0x007c, 0x0e7e, + 0x2071, 0xa5be, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c, 0x2011, + 0xa5ca, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa5be, 0x711a, + 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e, 0x0f7e, + 0x2079, 0xa300, 0x7a34, 0xd294, 0x0040, 0x59a4, 0x2071, 0xa5aa, + 0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5991, 0xa0fe, 0x0001, 0x0040, + 0x5995, 0xa0fe, 0x0002, 0x00c0, 0x59a0, 0xa292, 0x0085, 0x0078, + 0x5997, 0xa292, 0x0005, 0x0078, 0x5997, 0xa292, 0x0002, 0x2272, + 0x0040, 0x599c, 0x00c8, 0x59a4, 0x2011, 0x8037, 0x1078, 0x3579, + 0x2011, 0xa5a9, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f, 0x007c, + 0x0c7e, 0x2061, 0xa62d, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003, + 0x8003, 0x8003, 0xa080, 0xa62d, 0x2060, 0x007c, 0x6854, 0xa08a, + 0x199a, 0x0048, 0x59bd, 0x2001, 0x1999, 0xa005, 0x00c0, 0x59cc, + 0x0c7e, 0x2061, 0xa62d, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x59d1, + 0x2001, 0x001e, 0x0078, 0x59d1, 0xa08e, 0xffff, 0x00c0, 0x59d1, + 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, + 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5a24, 0xd0b4, 0x00c0, 0x59e8, + 0xd0bc, 0x00c0, 0x5a14, 0x2009, 0x0006, 0x1078, 0x5a43, 0x007c, + 0xd0fc, 0x0040, 0x59f3, 0xa084, 0x0003, 0x0040, 0x59f3, 0xa086, + 0x0003, 0x00c0, 0x5a3c, 0x6024, 0xd0d4, 0x0040, 0x59fd, 0xc0d4, + 0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa373, 0x2104, + 0xd084, 0x0040, 0x5a0f, 0x6118, 0xa188, 0x0027, 0x2104, 0xd08c, + 0x00c0, 0x5a0f, 0x2009, 0x0042, 0x1078, 0x756c, 0x007c, 0x2009, + 0x0043, 0x1078, 0x756c, 0x007c, 0xd0fc, 0x0040, 0x5a1f, 0xa084, + 0x0003, 0x0040, 0x5a1f, 0xa086, 0x0003, 0x00c0, 0x5a3c, 0x2009, + 0x0042, 0x1078, 0x756c, 0x007c, 0xd0fc, 0x0040, 0x5a32, 0xa084, + 0x0003, 0xa08e, 0x0002, 0x0040, 0x5a36, 0x2009, 0x0041, 0x1078, + 0x756c, 0x007c, 0x1078, 0x5a41, 0x0078, 0x5a31, 0x2009, 0x0043, + 0x1078, 0x756c, 0x0078, 0x5a31, 0x2009, 0x0004, 0x1078, 0x5a43, + 0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040, + 0x5a6b, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0, + 0x5a65, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5a65, + 0x0c7e, 0x2061, 0xa62d, 0x6200, 0xd28c, 0x00c0, 0x5a64, 0x6204, + 0x8210, 0x0048, 0x5a64, 0x6206, 0x0c7f, 0x1078, 0x4982, 0x6010, + 0xa06d, 0x10c0, 0x59b6, 0x0d7f, 0x007c, 0x157e, 0x0c7e, 0x2061, + 0xa62d, 0x6000, 0x81ff, 0x0040, 0x5a78, 0xa205, 0x0078, 0x5a79, + 0xa204, 0x6002, 0x0c7f, 0x157f, 0x007c, 0x6800, 0xd08c, 0x00c0, + 0x5a89, 0x6808, 0xa005, 0x0040, 0x5a89, 0x8001, 0x680a, 0xa085, + 0x0001, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, + 0x00c8, 0x5a93, 0xa200, 0x00f0, 0x5a8e, 0x8086, 0x818e, 0x007c, + 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x5ab9, 0xa11a, 0x00c8, + 0x5ab9, 0x8213, 0x818d, 0x0048, 0x5aac, 0xa11a, 0x00c8, 0x5aad, + 0x00f0, 0x5aa1, 0x0078, 0x5ab1, 0xa11a, 0x2308, 0x8210, 0x00f0, + 0x5aa1, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f, + 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x5ab5, 0x127e, + 0x2091, 0x2200, 0x2079, 0xa5ab, 0x127f, 0x0d7e, 0x2069, 0xa5ab, + 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, + 0x0d7f, 0x007c, 0x0c7e, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, + 0x0079, 0x5ada, 0x5ae4, 0x5b09, 0x5b64, 0x5aea, 0x5b09, 0x5ae4, + 0x5ae2, 0x5ae2, 0x1078, 0x1328, 0x1078, 0x595a, 0x1078, 0x6109, + 0x0c7f, 0x007c, 0x62c0, 0x82ff, 0x00c0, 0x5af0, 0x0c7f, 0x007c, + 0x2011, 0x4129, 0x1078, 0x58d4, 0x7828, 0xa092, 0x00c8, 0x00c8, + 0x5aff, 0x8000, 0x782a, 0x1078, 0x4168, 0x0078, 0x5aee, 0x1078, + 0x4129, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0078, + 0x5aee, 0x1078, 0x595a, 0x3c00, 0x007e, 0x2011, 0x0209, 0x20e1, + 0x4000, 0x2214, 0x007f, 0x20e0, 0x82ff, 0x0040, 0x5b27, 0x62c0, + 0x82ff, 0x00c0, 0x5b27, 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, + 0x1328, 0x2009, 0x0013, 0x1078, 0x756c, 0x0c7f, 0x007c, 0x3900, + 0xa082, 0xa6cd, 0x00c8, 0x5b2e, 0x1078, 0x728a, 0x0c7e, 0x7824, + 0xa065, 0x1040, 0x1328, 0x7804, 0xa086, 0x0004, 0x0040, 0x5ba9, + 0x7828, 0xa092, 0x2710, 0x00c8, 0x5b44, 0x8000, 0x782a, 0x0c7f, + 0x1078, 0x6c33, 0x0078, 0x5b25, 0x6104, 0xa186, 0x0003, 0x00c0, + 0x5b5b, 0x0e7e, 0x2071, 0xa300, 0x70d4, 0x0e7f, 0xd08c, 0x0040, + 0x5b5b, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, 0xa300, 0x1078, + 0x4171, 0x0e7f, 0x0c7f, 0x1078, 0xa241, 0x2009, 0x0014, 0x1078, + 0x756c, 0x0c7f, 0x0078, 0x5b25, 0x2001, 0xa5c7, 0x2003, 0x0000, + 0x62c0, 0x82ff, 0x00c0, 0x5b78, 0x782b, 0x0000, 0x7824, 0xa065, + 0x1040, 0x1328, 0x2009, 0x0013, 0x1078, 0x75c3, 0x0c7f, 0x007c, + 0x0c7e, 0x0d7e, 0x3900, 0xa082, 0xa6cd, 0x00c8, 0x5b81, 0x1078, + 0x728a, 0x7824, 0xa005, 0x1040, 0x1328, 0x781c, 0xa06d, 0x1040, + 0x1328, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x1078, 0x753d, + 0x693c, 0x81ff, 0x1040, 0x1328, 0x8109, 0x693e, 0x6854, 0xa015, + 0x0040, 0x5b9d, 0x7a1e, 0x0078, 0x5b9f, 0x7918, 0x791e, 0x7807, + 0x0000, 0x7827, 0x0000, 0x0d7f, 0x0c7f, 0x1078, 0x6109, 0x0078, + 0x5b76, 0x6104, 0xa186, 0x0002, 0x0040, 0x5bb4, 0xa186, 0x0004, + 0x0040, 0x5bb4, 0x0078, 0x5b38, 0x7808, 0xac06, 0x0040, 0x5b38, + 0x1078, 0x6010, 0x1078, 0x5c45, 0x0c7f, 0x1078, 0x6109, 0x0078, + 0x5b25, 0x0c7e, 0x6027, 0x0002, 0x62c8, 0x82ff, 0x00c0, 0x5bdb, + 0x62c4, 0x82ff, 0x00c0, 0x5bdb, 0x793c, 0xa1e5, 0x0000, 0x0040, + 0x5bd5, 0x2009, 0x0049, 0x1078, 0x756c, 0x2011, 0xa5ca, 0x2013, + 0x0000, 0x0c7f, 0x007c, 0x3908, 0xa192, 0xa6cd, 0x00c8, 0x5be2, + 0x1078, 0x728a, 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5bd5, + 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5bf4, + 0x6017, 0x0012, 0x0078, 0x5bd9, 0x6017, 0x0016, 0x0078, 0x5bd9, + 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0xa5ab, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, + 0x0040, 0x5c13, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f, + 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, 0x5c0e, 0x0d7e, + 0x2069, 0xa5ab, 0x6000, 0xd0d4, 0x0040, 0x5c2c, 0x6820, 0x8000, + 0x6822, 0xa086, 0x0001, 0x00c0, 0x5c27, 0x2c00, 0x681e, 0x6804, + 0xa084, 0x0007, 0x0079, 0x6111, 0xc0d5, 0x6002, 0x6818, 0xa005, + 0x0040, 0x5c3e, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00, 0x681a, + 0x0d7f, 0x685a, 0x2069, 0xa5ab, 0x0078, 0x5c1e, 0x6056, 0x605a, + 0x2c00, 0x681a, 0x681e, 0x0078, 0x5c1e, 0x007e, 0x017e, 0x0c7e, + 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xa5ab, + 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, 0x5c60, 0xa080, + 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, + 0x610e, 0x610a, 0x0078, 0x5c5b, 0x0c7e, 0x600f, 0x0000, 0x2c08, + 0x2061, 0xa5ab, 0x6034, 0xa005, 0x0040, 0x5c74, 0xa080, 0x0003, + 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, 0x0078, 0x5c72, + 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x017e, 0x007e, + 0x127e, 0x2071, 0xa5ab, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, + 0x8cff, 0x0040, 0x5ced, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, + 0x00c0, 0x5ce8, 0x87ff, 0x0040, 0x5c99, 0x6020, 0xa106, 0x00c0, + 0x5ce8, 0x703c, 0xac06, 0x00c0, 0x5cab, 0x037e, 0x2019, 0x0001, + 0x1078, 0x6e6c, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, + 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x5cb1, 0x660c, + 0x763a, 0x7034, 0xac36, 0x00c0, 0x5cbf, 0x2c00, 0xaf36, 0x0040, + 0x5cbd, 0x2f00, 0x7036, 0x0078, 0x5cbf, 0x7037, 0x0000, 0x660c, + 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5cc8, 0x7e0e, 0x0078, 0x5cc9, + 0x2678, 0x600f, 0x0000, 0x1078, 0x8a44, 0x0040, 0x5ce3, 0x6010, + 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5cf7, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, 0xa181, 0x1078, + 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x5c88, + 0x2c78, 0x600c, 0x2060, 0x0078, 0x5c88, 0x127f, 0x007f, 0x017f, + 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, + 0xa086, 0x0006, 0x00c0, 0x5cd6, 0x1078, 0xa181, 0x1078, 0x9e70, + 0x0078, 0x5ce3, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, + 0x0000, 0x127e, 0x2091, 0x8000, 0x2079, 0xa5ab, 0x7838, 0xa065, + 0x0040, 0x5d41, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06, + 0x00c0, 0x5d28, 0x037e, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x7833, + 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, 0x037f, + 0x1078, 0x8a44, 0x0040, 0x5d3c, 0x6010, 0x2068, 0x601c, 0xa086, + 0x0003, 0x00c0, 0x5d4a, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x007f, 0x0078, + 0x5d0f, 0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, + 0x007f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5d33, 0x1078, + 0x9e70, 0x0078, 0x5d3c, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000, + 0x1078, 0x5d6d, 0x1078, 0x5e21, 0x087f, 0x027f, 0x017f, 0x007c, + 0x0f7e, 0x127e, 0x2079, 0xa5ab, 0x2091, 0x8000, 0x1078, 0x5ebc, + 0x1078, 0x5f32, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, + 0x0c7e, 0x067e, 0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, + 0xa5ab, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5e01, 0x6018, + 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5dfc, 0x88ff, 0x0040, + 0x5d8d, 0x6020, 0xa106, 0x00c0, 0x5dfc, 0x7024, 0xac06, 0x00c0, + 0x5dbd, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x5db8, 0x1078, + 0x595a, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, + 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, + 0x5dad, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, + 0xd084, 0x0040, 0x5db5, 0x6827, 0x0001, 0x037f, 0x0078, 0x5dbd, + 0x6003, 0x0009, 0x630a, 0x0078, 0x5dfc, 0x7014, 0xac36, 0x00c0, + 0x5dc3, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x5dd1, 0x2c00, + 0xaf36, 0x0040, 0x5dcf, 0x2f00, 0x7012, 0x0078, 0x5dd1, 0x7013, + 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5dda, 0x7e0e, + 0x0078, 0x5ddb, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, + 0x8a44, 0x0040, 0x5df5, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e0a, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, + 0xa181, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x1078, + 0x7045, 0x0c7f, 0x0078, 0x5d7c, 0x2c78, 0x600c, 0x2060, 0x0078, + 0x5d7c, 0x127f, 0x007f, 0x017f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, + 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5e15, 0x1078, + 0xa181, 0x1078, 0x9e70, 0x0078, 0x5df5, 0x601c, 0xa086, 0x0002, + 0x00c0, 0x5df5, 0x6004, 0xa086, 0x0085, 0x0040, 0x5de8, 0x0078, + 0x5df5, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0xa434, + 0x2004, 0xa065, 0x0040, 0x5eb8, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, + 0x2071, 0xa5ab, 0x6654, 0x7018, 0xac06, 0x00c0, 0x5e38, 0x761a, + 0x701c, 0xac06, 0x00c0, 0x5e44, 0x86ff, 0x00c0, 0x5e43, 0x7018, + 0x701e, 0x0078, 0x5e44, 0x761e, 0x6058, 0xa07d, 0x0040, 0x5e49, + 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x5e4f, 0x2f00, 0x685a, 0x6057, + 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, + 0x4410, 0x0040, 0x5eb4, 0x7624, 0x86ff, 0x0040, 0x5ea2, 0xa680, + 0x0004, 0x2004, 0xad06, 0x00c0, 0x5ea2, 0x0d7e, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0040, 0x5e99, 0x1078, 0x595a, 0x1078, 0x6c41, + 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, 0x2069, + 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5e82, 0x6803, 0x0100, + 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5e8a, + 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, + 0x5e93, 0x8001, 0x603e, 0x2660, 0x1078, 0x8c01, 0x0c7f, 0x0078, + 0x5ea2, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, + 0x0078, 0x5e57, 0x8dff, 0x0040, 0x5eb0, 0x6837, 0x0103, 0x6b4a, + 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, 0xa181, 0x1078, 0x4982, + 0x1078, 0x7045, 0x0078, 0x5e57, 0x067f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, 0x0c7e, 0x0d7e, + 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x5f16, 0x600c, 0x007e, + 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x5efb, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0040, 0x5ef5, 0x1078, 0x595a, 0x1078, 0x6c41, + 0x68c3, 0x0000, 0x1078, 0x7188, 0x7827, 0x0000, 0x037e, 0x2069, + 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5eea, 0x6803, 0x0100, + 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ef2, + 0x6827, 0x0001, 0x037f, 0x0078, 0x5efb, 0x6003, 0x0009, 0x630a, + 0x2c30, 0x0078, 0x5f13, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, + 0x5f0f, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5f1d, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, + 0x8c01, 0x1078, 0x7045, 0x007f, 0x0078, 0x5ec3, 0x7e16, 0x7e12, + 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006, + 0x00c0, 0x5f26, 0x1078, 0x9e70, 0x0078, 0x5f0f, 0x601c, 0xa086, + 0x0002, 0x00c0, 0x5f0f, 0x6004, 0xa086, 0x0085, 0x0040, 0x5f06, + 0x0078, 0x5f0f, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x7818, 0xa065, + 0x0040, 0x5fa0, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x4410, 0x0040, 0x5f9d, + 0x7e24, 0x86ff, 0x0040, 0x5f8f, 0xa680, 0x0004, 0x2004, 0xad06, + 0x00c0, 0x5f8f, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, + 0x5f86, 0x1078, 0x595a, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, + 0x7188, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, + 0x1000, 0x0040, 0x5f6f, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0040, 0x5f77, 0x6827, 0x0001, 0x037f, + 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x5f80, 0x8001, 0x603e, + 0x2660, 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x5f8f, 0x0d7f, 0x0c7e, + 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x5f44, 0x8dff, + 0x0040, 0x5f99, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, + 0x4982, 0x1078, 0x7045, 0x0078, 0x5f44, 0x007f, 0x0078, 0x5f37, + 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x0e7e, + 0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x5fc4, 0x604c, 0xa06d, + 0x0040, 0x5fc4, 0x6848, 0xa606, 0x00c0, 0x5fc4, 0x2071, 0xa5ab, + 0x7024, 0xa035, 0x0040, 0x5fc4, 0xa080, 0x0004, 0x2004, 0xad06, + 0x00c0, 0x5fc4, 0x1078, 0x5fc8, 0x067f, 0x0d7f, 0x0e7f, 0x007c, + 0x0f7e, 0x2079, 0x0100, 0x78c0, 0xa005, 0x00c0, 0x5fd7, 0x0c7e, + 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x600e, 0x1078, + 0x6c41, 0x78c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, + 0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0040, 0x5feb, 0x7803, + 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0040, + 0x5ff3, 0x7827, 0x0001, 0x1078, 0x7188, 0x037f, 0x1078, 0x4410, + 0x0c7e, 0x603c, 0xa005, 0x0040, 0x5fff, 0x8001, 0x603e, 0x2660, + 0x1078, 0x753d, 0x0c7f, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x1078, 0x8cb8, 0x1078, 0x4982, 0x1078, 0x7045, 0x0f7f, 0x007c, + 0x0e7e, 0x0c7e, 0x2071, 0xa5ab, 0x7004, 0xa084, 0x0007, 0x0079, + 0x6019, 0x6023, 0x6026, 0x603f, 0x605b, 0x60a0, 0x6023, 0x6023, + 0x6021, 0x1078, 0x1328, 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, + 0x0040, 0x6034, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0040, + 0x603b, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, + 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x6034, 0x6018, + 0x2060, 0x1078, 0x4410, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, + 0x7022, 0x0040, 0x6050, 0x6054, 0xa015, 0x0040, 0x6057, 0x721e, + 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218, + 0x721e, 0x0078, 0x6050, 0x7024, 0xa065, 0x0040, 0x609d, 0x700c, + 0xac06, 0x00c0, 0x6072, 0x1078, 0x7045, 0x600c, 0xa015, 0x0040, + 0x606e, 0x720e, 0x600f, 0x0000, 0x0078, 0x609b, 0x720e, 0x720a, + 0x0078, 0x609b, 0x7014, 0xac06, 0x00c0, 0x6085, 0x1078, 0x7045, + 0x600c, 0xa015, 0x0040, 0x6081, 0x7216, 0x600f, 0x0000, 0x0078, + 0x609b, 0x7216, 0x7212, 0x0078, 0x609b, 0x6018, 0x2060, 0x1078, + 0x4410, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7045, 0x701c, 0xa065, + 0x0040, 0x609b, 0x6054, 0xa015, 0x0040, 0x6099, 0x721e, 0x0078, + 0x609b, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, + 0x7024, 0xa065, 0x0040, 0x60ad, 0x1078, 0x7045, 0x600c, 0xa015, + 0x0040, 0x60b4, 0x720e, 0x600f, 0x0000, 0x1078, 0x7188, 0x7027, + 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078, 0x60ad, + 0x0d7e, 0x2069, 0xa5ab, 0x6830, 0xa084, 0x0003, 0x0079, 0x60c0, + 0x60c6, 0x60c8, 0x60ee, 0x60c6, 0x1078, 0x1328, 0x0d7f, 0x007c, + 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x60e4, 0x683c, 0xa065, + 0x0040, 0x60d9, 0x600c, 0xa015, 0x0040, 0x60e0, 0x6a3a, 0x600f, + 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f, 0x007c, + 0x683a, 0x6836, 0x0078, 0x60d9, 0x6843, 0x0000, 0x6838, 0xa065, + 0x0040, 0x60d9, 0x6003, 0x0003, 0x0078, 0x60d9, 0x0c7e, 0x6843, + 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x6106, 0x600c, + 0xa015, 0x0040, 0x6102, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, + 0x0078, 0x6106, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f, + 0x007c, 0x0d7e, 0x2069, 0xa5ab, 0x6804, 0xa084, 0x0007, 0x0079, + 0x6111, 0x611b, 0x61c2, 0x61c2, 0x61c2, 0x61c2, 0x61c4, 0x61c2, + 0x6119, 0x1078, 0x1328, 0x6820, 0xa005, 0x00c0, 0x6121, 0x0d7f, + 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x6130, 0x6807, 0x0004, + 0x6826, 0x682b, 0x0000, 0x1078, 0x620a, 0x0c7f, 0x0d7f, 0x007c, + 0x6814, 0xa065, 0x0040, 0x613e, 0x6807, 0x0001, 0x6826, 0x682b, + 0x0000, 0x1078, 0x620a, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e, + 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x61bd, 0x704c, 0xa00d, 0x0040, + 0x614d, 0x7088, 0xa005, 0x0040, 0x6165, 0x7054, 0xa075, 0x0040, + 0x6156, 0xa20e, 0x0040, 0x61bd, 0x0078, 0x615b, 0x6818, 0xa20e, + 0x0040, 0x61bd, 0x2070, 0x704c, 0xa00d, 0x0040, 0x614d, 0x7088, + 0xa005, 0x00c0, 0x614d, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, + 0x00c8, 0x614d, 0x1078, 0x750c, 0x0040, 0x61bd, 0x8318, 0x733e, + 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, + 0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, + 0xa08a, 0x199a, 0x0048, 0x6186, 0x2001, 0x1999, 0x8003, 0x801b, + 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, + 0x0040, 0x619f, 0x7100, 0xd1f4, 0x0040, 0x619b, 0x7114, 0xa18c, + 0x00ff, 0x0078, 0x61a4, 0x2009, 0x0000, 0x0078, 0x61a4, 0xa1e0, + 0x293f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, + 0x679b, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, + 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, + 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, + 0x0078, 0x61bb, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, + 0x61d0, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x620a, + 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa5ab, 0x6830, + 0xa086, 0x0000, 0x00c0, 0x61f1, 0x6838, 0xa07d, 0x0040, 0x61f1, + 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091, + 0x2200, 0x027f, 0x1078, 0x1d28, 0x00c0, 0x61f4, 0x127f, 0x1078, + 0x6ae5, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803, + 0x0002, 0x780c, 0xa015, 0x0040, 0x6206, 0x6a3a, 0x780f, 0x0000, + 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x61f1, 0x683a, 0x6836, + 0x0078, 0x6200, 0x601c, 0xa084, 0x000f, 0x1079, 0x6210, 0x007c, + 0x6219, 0x621e, 0x663f, 0x6758, 0x621e, 0x663f, 0x6758, 0x6219, + 0x621e, 0x1078, 0x6010, 0x1078, 0x6109, 0x007c, 0x157e, 0x137e, + 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044, 0x10c8, 0x1328, + 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x623b, 0x7900, 0xd1f4, + 0x0040, 0x6237, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x6240, 0x2009, + 0x0000, 0x0078, 0x6240, 0xa1f8, 0x293f, 0x2f0c, 0xa18c, 0x00ff, + 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x00c8, 0x6292, + 0x1079, 0x6250, 0x0f7f, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, + 0x62f8, 0x6340, 0x6368, 0x6403, 0x6433, 0x643b, 0x6462, 0x6473, + 0x6484, 0x648c, 0x64a4, 0x648c, 0x650f, 0x6473, 0x6530, 0x6538, + 0x6484, 0x6538, 0x6549, 0x6290, 0x6290, 0x6290, 0x6290, 0x6290, + 0x6290, 0x6290, 0x6290, 0x6290, 0x6290, 0x6290, 0x6d05, 0x6d2a, + 0x6d3f, 0x6d62, 0x6d83, 0x6462, 0x6290, 0x6462, 0x648c, 0x6290, + 0x6368, 0x6403, 0x6290, 0x72ac, 0x648c, 0x6290, 0x72cc, 0x648c, + 0x6290, 0x6290, 0x62f3, 0x62a1, 0x6290, 0x72f1, 0x7368, 0x7450, + 0x6290, 0x7461, 0x645c, 0x747d, 0x6290, 0x6d98, 0x6290, 0x6290, + 0x1078, 0x1328, 0x2100, 0x1079, 0x629b, 0x0f7f, 0x0c7f, 0x147f, + 0x137f, 0x157f, 0x007c, 0x629f, 0x629f, 0x629f, 0x62d5, 0x1078, + 0x1328, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6567, 0x7810, 0x2068, + 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0018, 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x0d7e, 0x7818, + 0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x62d2, 0xa085, 0x0001, + 0x0d7f, 0x007c, 0xa006, 0x0078, 0x62d0, 0x0d7e, 0x20a1, 0x020b, + 0x1078, 0x6567, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, + 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, + 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, 0x1078, + 0x6c2d, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078, 0x6c2d, 0x007c, + 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x5200, 0x20a3, 0x0000, + 0x0d7e, 0x2069, 0xa351, 0x6804, 0xd084, 0x0040, 0x6312, 0x6828, + 0x20a3, 0x0000, 0x017e, 0x1078, 0x24fa, 0x21a2, 0x017f, 0x0d7f, + 0x0078, 0x6317, 0x0d7f, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, + 0x0004, 0x2099, 0xa305, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa301, + 0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0048, + 0x6331, 0x2001, 0xa31a, 0x20a6, 0x2001, 0xa31b, 0x20a6, 0x0078, + 0x6337, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x6c2d, 0x007c, + 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x0500, 0x20a3, 0x0000, + 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0048, 0x6358, + 0x2001, 0xa31a, 0x20a6, 0x2001, 0xa31b, 0x20a6, 0x0078, 0x635e, + 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004, + 0x2099, 0xa305, 0x53a6, 0x60c3, 0x0010, 0x1078, 0x6c2d, 0x007c, + 0x20a1, 0x020b, 0x1078, 0x6567, 0x0c7e, 0x7818, 0x2060, 0x2001, + 0x0000, 0x1078, 0x48a2, 0x0c7f, 0x7818, 0xa080, 0x0028, 0x2004, + 0xa086, 0x007e, 0x00c0, 0x6383, 0x20a3, 0x0400, 0x620c, 0xc2b4, + 0x620e, 0x0078, 0x6385, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, + 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x63d2, 0x2099, + 0xa58c, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0xa084, 0x3fff, + 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xa305, 0x53a6, + 0x20a9, 0x0004, 0x2099, 0xa301, 0x53a6, 0x20a9, 0x0010, 0x20a3, + 0x0000, 0x00f0, 0x63af, 0x2099, 0xa594, 0x3304, 0xc0dd, 0x20a2, + 0x2001, 0xa371, 0x2004, 0xd0e4, 0x0040, 0x63ca, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004, + 0x0078, 0x63cc, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x00f0, 0x63cc, + 0x0078, 0x63f2, 0x2099, 0xa58c, 0x20a9, 0x0008, 0x53a6, 0x20a9, + 0x0004, 0x2099, 0xa305, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa301, + 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63e3, 0x20a9, + 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63e9, 0x2099, 0xa594, 0x20a9, + 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63f4, + 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x63fa, 0x60c3, 0x0074, + 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, + 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa351, + 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x641f, 0xa085, 0x0020, 0xd1a4, + 0x0040, 0x6424, 0xa085, 0x0010, 0xa085, 0x0002, 0x0d7e, 0x0078, + 0x64ed, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, + 0x5000, 0x0078, 0x6385, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, + 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65ef, + 0x0078, 0x6466, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, + 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, + 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, + 0x0008, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8, + 0x20a3, 0x0200, 0x0078, 0x6385, 0x20a1, 0x020b, 0x1078, 0x65f8, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0040, 0x649b, + 0x20a2, 0x0078, 0x649d, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, + 0x0008, 0x1078, 0x6c2d, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, + 0x65f8, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, + 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x64ca, 0x6998, 0xa184, + 0xc000, 0x00c0, 0x64c6, 0xd1ec, 0x0040, 0x64c2, 0x20a3, 0x2100, + 0x0078, 0x64cc, 0x20a3, 0x0100, 0x0078, 0x64cc, 0x20a3, 0x0400, + 0x0078, 0x64cc, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa351, 0x7904, 0x0f7f, 0xd1ac, + 0x00c0, 0x64dc, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x64e1, 0xa085, + 0x0010, 0x2009, 0xa373, 0x210c, 0xd184, 0x0040, 0x64eb, 0x699c, + 0xd18c, 0x0040, 0x64ed, 0xa085, 0x0002, 0x027e, 0x2009, 0xa371, + 0x210c, 0xd1e4, 0x0040, 0x64fb, 0xc0c5, 0xa094, 0x0030, 0xa296, + 0x0010, 0x0040, 0x6505, 0xd1ec, 0x0040, 0x6505, 0xa094, 0x0030, + 0xa296, 0x0010, 0x0040, 0x6505, 0xc0bd, 0x027f, 0x20a2, 0x20a2, + 0x20a2, 0x60c3, 0x0014, 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x20a1, + 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, + 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x6c2d, 0x007c, + 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, 0x0078, 0x62fe, + 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x6c2d, + 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078, + 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, + 0x0000, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x007c, 0x027e, 0x037e, + 0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078, 0x656e, 0x027e, + 0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, + 0x00c0, 0x6581, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x0078, + 0x65b6, 0xa286, 0x007f, 0x00c0, 0x658d, 0x0d7e, 0xa385, 0x00ff, + 0x20a2, 0x20a3, 0xfffd, 0x0078, 0x65a4, 0xd2bc, 0x0040, 0x65ac, + 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x659c, 0xa385, 0x00ff, 0x20a2, + 0x20a3, 0xfffc, 0x0078, 0x65a4, 0xa2e8, 0xa434, 0x2d6c, 0x6810, + 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, + 0x2da6, 0x0d7f, 0x0078, 0x65ba, 0x0d7e, 0xa2e8, 0xa434, 0x2d6c, + 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, + 0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f, 0x037f, 0x20a3, + 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, + 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc, + 0x22a2, 0x0d7e, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, + 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x65c1, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x007c, 0x027e, + 0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800, 0x0078, 0x65ff, + 0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, + 0x007e, 0x0048, 0x661c, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, + 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, + 0x2da6, 0x0d7f, 0x0078, 0x662a, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, + 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, + 0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x047f, + 0x037f, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0c7e, + 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1328, 0xa08a, 0x008c, + 0x10c8, 0x1328, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x665d, + 0x7900, 0xd1f4, 0x0040, 0x6659, 0x7914, 0xa18c, 0x00ff, 0x0078, + 0x6662, 0x2009, 0x0000, 0x0078, 0x6662, 0xa1f8, 0x293f, 0x2f0c, + 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, + 0x1079, 0x666d, 0x0f7f, 0x0c7f, 0x007c, 0x6676, 0x6681, 0x669c, + 0x6674, 0x6674, 0x6674, 0x6676, 0x1078, 0x1328, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x66af, 0x60c3, 0x0000, 0x1078, 0x6c2d, 0x147f, + 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x66e3, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, + 0x1078, 0x6c2d, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, + 0x6724, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0004, 0x1078, 0x6c2d, 0x147f, 0x007c, 0x027e, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, + 0xa092, 0x007e, 0x0048, 0x66ce, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, + 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x66dd, 0x0d7e, 0xa0e8, + 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, + 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3, + 0x0000, 0x0078, 0x65c1, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6702, + 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, + 0x0078, 0x6711, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, + 0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, + 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, + 0x6743, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8500, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, + 0x0d7f, 0x0078, 0x6752, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, + 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, + 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x0078, 0x6715, + 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x1048, 0x1328, + 0xa08a, 0x0053, 0x10c8, 0x1328, 0x7918, 0x2160, 0x61a0, 0xd1bc, + 0x0040, 0x6777, 0x6100, 0xd1f4, 0x0040, 0x6773, 0x6114, 0xa18c, + 0x00ff, 0x0078, 0x677c, 0x2009, 0x0000, 0x0078, 0x677c, 0xa1e0, + 0x293f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, + 0x0040, 0x1079, 0x6786, 0x0f7f, 0x0c7f, 0x007c, 0x679b, 0x68a9, + 0x684a, 0x6a59, 0x6799, 0x6799, 0x6799, 0x6799, 0x6799, 0x6799, + 0x6799, 0x6f5e, 0x6f6f, 0x6f80, 0x6f91, 0x6799, 0x748e, 0x6799, + 0x6f4d, 0x1078, 0x1328, 0x0d7e, 0x157e, 0x147e, 0x780b, 0xffff, + 0x20a1, 0x020b, 0x1078, 0x6806, 0x7910, 0x2168, 0x6948, 0x7922, + 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f, + 0x00c0, 0x67b6, 0x2001, 0x0005, 0x0078, 0x67c0, 0xd184, 0x0040, + 0x67bd, 0x2001, 0x0004, 0x0078, 0x67c0, 0xa084, 0x0006, 0x8004, + 0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007, 0xa105, 0x017f, + 0x20a2, 0xd1ac, 0x0040, 0x67d0, 0x20a3, 0x0002, 0x0078, 0x67dc, + 0xd1b4, 0x0040, 0x67d7, 0x20a3, 0x0001, 0x0078, 0x67dc, 0x20a3, + 0x0000, 0x2230, 0x0078, 0x67de, 0x6a80, 0x6e7c, 0x20a9, 0x0008, + 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x67e2, + 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, + 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa5c7, 0x2003, 0x07d0, + 0x2001, 0xa5c6, 0x2003, 0x0009, 0x2001, 0xa5cc, 0x2003, 0x0002, + 0x1078, 0x157e, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, + 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, + 0x0040, 0x682c, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, + 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, + 0x2da6, 0x0d7f, 0x0078, 0x683b, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, + 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, + 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, + 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b, + 0x1078, 0x686a, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, + 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, + 0x20a2, 0x60c3, 0x000c, 0x1078, 0x6c2d, 0x147f, 0x137f, 0x157f, + 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6888, 0x0d7e, 0xa0e8, + 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6897, + 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, + 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, + 0x0889, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, + 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810, 0xa06d, 0x1078, + 0x488f, 0x0040, 0x68bd, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, + 0x00c0, 0x68bd, 0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078, + 0x6a12, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, + 0xa084, 0xf000, 0x00c0, 0x68d4, 0x7810, 0xa084, 0x0700, 0x8007, + 0x1079, 0x68dc, 0x0078, 0x68d7, 0xa006, 0x1079, 0x68dc, 0x147f, + 0x137f, 0x157f, 0x0d7f, 0x007c, 0x68e6, 0x697e, 0x6989, 0x69b3, + 0x69c7, 0x69e3, 0x69ee, 0x68e4, 0x1078, 0x1328, 0x017e, 0x037e, + 0x694c, 0xa18c, 0x0003, 0x0040, 0x68f1, 0xa186, 0x0003, 0x00c0, + 0x6900, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x68f7, 0xc3e5, 0x23a2, + 0x6868, 0x20a2, 0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x69be, + 0xa186, 0x0001, 0x10c0, 0x1328, 0x6b78, 0x7824, 0xd0cc, 0x0040, + 0x690a, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, + 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, + 0x0300, 0x0040, 0x6978, 0xd3c4, 0x0040, 0x6920, 0x687c, 0xa108, + 0xd3cc, 0x0040, 0x6925, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, + 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x692a, + 0x157f, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6978, + 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818, + 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6958, 0x0d7e, 0xa0e8, + 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6967, + 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f, + 0x7b24, 0xd3cc, 0x0040, 0x6970, 0x20a3, 0x0889, 0x0078, 0x6972, + 0x20a3, 0x0898, 0x20a2, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, + 0x61c2, 0x037f, 0x017f, 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0008, + 0x7824, 0xd0cc, 0x0040, 0x6985, 0xc2e5, 0x22a2, 0xa016, 0x0078, + 0x69bc, 0x2011, 0x0302, 0x7824, 0xd0cc, 0x0040, 0x6990, 0xc2e5, + 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, + 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, + 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, + 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, + 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040, + 0x69ba, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x6c2d, 0x007c, 0x2011, + 0x0100, 0x7824, 0xd0cc, 0x0040, 0x69ce, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, + 0x7834, 0xa084, 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, + 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040, + 0x69ea, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x69bc, 0x037e, 0x7b10, + 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6a01, + 0x7824, 0xd0cc, 0x0040, 0x69fd, 0xc2e5, 0x22a2, 0x037f, 0x0078, + 0x69bc, 0x047e, 0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f, + 0x0040, 0x6a0b, 0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f, + 0x0078, 0x69be, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a30, 0x0d7e, 0xa0e8, + 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a3f, + 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824, + 0xd0cc, 0x0040, 0x6a47, 0x20a3, 0x0889, 0x0078, 0x6a49, 0x20a3, + 0x0898, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, + 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, + 0xa084, 0x0700, 0x8007, 0x1079, 0x6a6c, 0x037f, 0x017f, 0x147f, + 0x137f, 0x157f, 0x0d7f, 0x007c, 0x6a74, 0x6a74, 0x6a76, 0x6a74, + 0x6a74, 0x6a74, 0x6a9b, 0x6a74, 0x1078, 0x1328, 0x7910, 0xa18c, + 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, + 0x1078, 0x6aa5, 0x0d7e, 0x2069, 0xa351, 0x6804, 0xd0bc, 0x0040, + 0x6a90, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6a92, + 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, + 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, + 0x6aa5, 0x20a3, 0x7f00, 0x0078, 0x6a93, 0x027e, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, + 0x6ac3, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0100, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, + 0x0d7f, 0x0078, 0x6ad2, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, + 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, + 0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078, + 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, + 0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071, 0xa300, 0x6130, + 0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6afc, 0x6910, + 0x6a14, 0x6430, 0x0078, 0x6b00, 0x6910, 0x6a14, 0x7368, 0x746c, + 0x781c, 0xa086, 0x0006, 0x0040, 0x6b5f, 0xd5bc, 0x0040, 0x6b10, + 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6b17, + 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, + 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, + 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, + 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, + 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x6b49, 0x6a00, 0xd2f4, + 0x0040, 0x6b47, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6b49, 0x2011, + 0x0000, 0x629e, 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, + 0xfff0, 0xa005, 0x0040, 0x6b56, 0x2009, 0x1b58, 0x1078, 0x595f, + 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, + 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6bb7, + 0xd5bc, 0x0040, 0x6b73, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0078, 0x6b7a, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, + 0x0000, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, + 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, + 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, + 0x60c6, 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, + 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, + 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x6bb2, 0x6a00, + 0xd2f4, 0x0040, 0x6bb0, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6bb2, + 0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x6b4c, 0xd5bc, + 0x0040, 0x6bc2, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, + 0x0078, 0x6bc9, 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, + 0x646e, 0x1078, 0x488f, 0x0040, 0x6bdf, 0x0d7e, 0x7810, 0xa06d, + 0x684c, 0x0d7f, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6bdf, + 0x7824, 0xc0cd, 0x7826, 0x6073, 0x0889, 0x0078, 0x6be1, 0x6073, + 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, + 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, + 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, + 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0xa582, 0x0080, 0x0048, 0x6c0f, 0x6a00, 0xd2f4, 0x0040, 0x6c0d, + 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6c0f, 0x2011, 0x0000, 0x629e, + 0x7824, 0xd0cc, 0x0040, 0x6c18, 0x6017, 0x0016, 0x0078, 0x6b4c, + 0x6017, 0x0012, 0x0078, 0x6b4c, 0x7a18, 0xa280, 0x0023, 0x2014, + 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069, + 0xa5ab, 0x6843, 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x1078, 0x6c38, 0x1078, 0x594f, 0x007c, + 0x007e, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f, + 0x007c, 0x007e, 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004, + 0xa085, 0x0008, 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e, + 0x017e, 0x027e, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, + 0x4000, 0x0040, 0x6c89, 0x1078, 0x6c41, 0x6803, 0x1000, 0x6803, + 0x0000, 0x0c7e, 0x2061, 0xa5ab, 0x6128, 0xa192, 0x00c8, 0x00c8, + 0x6c76, 0x8108, 0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6c84, + 0x1078, 0x594f, 0x1078, 0x6c38, 0x0078, 0x6c84, 0x6124, 0xa1e5, + 0x0000, 0x0040, 0x6c81, 0x1078, 0xa241, 0x2009, 0x0014, 0x1078, + 0x756c, 0x0c7f, 0x0078, 0x6c84, 0x027f, 0x017f, 0x0d7f, 0x0c7f, + 0x007c, 0x2001, 0xa5c7, 0x2004, 0xa005, 0x00c0, 0x6c84, 0x0c7e, + 0x2061, 0xa5ab, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6c76, 0x8108, + 0x612a, 0x0c7f, 0x1078, 0x594f, 0x1078, 0x4171, 0x0078, 0x6c84, + 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5967, 0x2071, + 0xa5ab, 0x713c, 0x81ff, 0x0040, 0x6cca, 0x2061, 0x0100, 0x2069, + 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6cd0, 0x6803, 0x1000, + 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x037f, + 0x713c, 0x2160, 0x1078, 0xa241, 0x2009, 0x004a, 0x1078, 0x756c, + 0x0078, 0x6cca, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, + 0x0078, 0x6cba, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, 0x047e, + 0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071, + 0xa5ab, 0x7018, 0x2068, 0x8dff, 0x0040, 0x6cfc, 0x68a0, 0xa406, + 0x0040, 0x6cee, 0x6854, 0x2068, 0x0078, 0x6ce3, 0x6010, 0x2060, + 0x643c, 0x6540, 0x6e48, 0x2d60, 0x1078, 0x466a, 0x0040, 0x6cfc, + 0x1078, 0x7045, 0xa085, 0x0001, 0x127f, 0x007f, 0x047f, 0x057f, + 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x6567, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c, + 0xa086, 0x0004, 0x00c0, 0x6d17, 0x6098, 0x0078, 0x6d18, 0x6030, + 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006, + 0x20a2, 0x00f0, 0x6d20, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x1078, + 0x6c2d, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6567, + 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, + 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x147f, 0x157f, 0x007c, 0x157e, + 0x147e, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, 0x20a3, + 0x0000, 0x20a9, 0x0006, 0x2011, 0xa340, 0x2019, 0xa341, 0x23a6, + 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0, 0x6d4f, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x6c2d, 0x147f, + 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, + 0x1078, 0x65cf, 0x1078, 0x65e6, 0x7810, 0xa080, 0x0000, 0x2004, + 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, + 0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6c2d, 0x027f, 0x017f, + 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, + 0x6567, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, + 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x147f, 0x157f, 0x007c, + 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x6567, + 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, + 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x1078, 0x6c2d, + 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, 0x0c7e, 0x007e, + 0x127e, 0x2091, 0x8000, 0x2071, 0xa5ab, 0x700c, 0x2060, 0x8cff, + 0x0040, 0x6dd1, 0x1078, 0x8c3b, 0x00c0, 0x6dc8, 0x1078, 0x7a05, + 0x600c, 0x007e, 0x1078, 0x753d, 0x1078, 0x7045, 0x0c7f, 0x0078, + 0x6dbf, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, 0x007f, 0x0c7f, + 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, + 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, + 0x0140, 0x2071, 0xa5ab, 0x7024, 0x2060, 0x8cff, 0x0040, 0x6e2a, + 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x595a, 0x2009, 0x0013, + 0x1078, 0x756c, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x6e0d, + 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x6e1f, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0x6e1f, 0xd084, 0x0040, 0x6e14, + 0x6827, 0x0001, 0x0078, 0x6e16, 0x00f0, 0x6dfc, 0x7804, 0xa084, + 0x1000, 0x0040, 0x6e1f, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, + 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, + 0x127f, 0x007c, 0x2001, 0xa300, 0x2004, 0xa096, 0x0001, 0x0040, + 0x6e62, 0xa096, 0x0004, 0x0040, 0x6e62, 0x6817, 0x0008, 0x68c3, + 0x0000, 0x2011, 0x4129, 0x1078, 0x58d4, 0x20a9, 0x01f4, 0x6824, + 0xd094, 0x0040, 0x6e50, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, + 0x0040, 0x6e62, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x6e62, + 0xd084, 0x0040, 0x6e57, 0x6827, 0x0001, 0x0078, 0x6e59, 0x00f0, + 0x6e3f, 0x7804, 0xa084, 0x1000, 0x0040, 0x6e62, 0x7803, 0x0100, + 0x7803, 0x0000, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, + 0x0f7f, 0x157f, 0x127f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, + 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, + 0x0100, 0x2079, 0x0140, 0x2071, 0xa5ab, 0x703c, 0x2060, 0x8cff, + 0x0040, 0x6ee8, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0, + 0x6e86, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x1078, 0x5967, 0x1078, + 0x1f31, 0x047e, 0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, + 0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, + 0x6eb7, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079, + 0x0020, 0x2071, 0xa602, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, + 0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a, + 0x057f, 0x047f, 0xa39d, 0x0000, 0x00c0, 0x6ec2, 0x2009, 0x0049, + 0x1078, 0x756c, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x6ed5, + 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x6ee7, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0x6ee7, 0xd08c, 0x0040, 0x6edc, + 0x6827, 0x0002, 0x0078, 0x6ede, 0x00f0, 0x6ec4, 0x7804, 0xa084, + 0x1000, 0x0040, 0x6ee7, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, + 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, + 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa5ab, + 0x6a06, 0x127f, 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, + 0x2069, 0xa5ab, 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, + 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2071, 0xa5ab, 0x7614, 0x2660, + 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x6f46, 0x601c, 0xa206, + 0x00c0, 0x6f41, 0x7014, 0xac36, 0x00c0, 0x6f20, 0x660c, 0x7616, + 0x7010, 0xac36, 0x00c0, 0x6f2e, 0x2c00, 0xaf36, 0x0040, 0x6f2c, + 0x2f00, 0x7012, 0x0078, 0x6f2e, 0x7013, 0x0000, 0x660c, 0x067e, + 0x2c00, 0xaf06, 0x0040, 0x6f37, 0x7e0e, 0x0078, 0x6f38, 0x2678, + 0x600f, 0x0000, 0x1078, 0x8c01, 0x1078, 0x7045, 0x0c7f, 0x0078, + 0x6f13, 0x2c78, 0x600c, 0x2060, 0x0078, 0x6f13, 0x127f, 0x007f, + 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0078, 0x6fa0, 0x157e, 0x147e, + 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0078, 0x6fa0, 0x157e, + 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x6fa0, + 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, + 0x6fa0, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, + 0x1078, 0x7050, 0x60c3, 0x0020, 0x1078, 0x6c2d, 0x147f, 0x157f, + 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, + 0xd1b4, 0x00c0, 0x6fb8, 0xd1bc, 0x00c0, 0x7002, 0x0078, 0x7042, + 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, + 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, + 0x0040, 0x6ff9, 0x6020, 0xd0b4, 0x0040, 0x6ff9, 0x6024, 0xd094, + 0x00c0, 0x6ff9, 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, + 0x6ff9, 0x00f0, 0x6fc5, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, + 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, + 0xbc91, 0x6043, 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, + 0xd094, 0x00c0, 0x6ff8, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x6fef, + 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, + 0x0078, 0x7042, 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, + 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, + 0xa084, 0x4000, 0x0040, 0x703b, 0x6020, 0xd0bc, 0x0040, 0x703b, + 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x703b, 0x00f0, + 0x700f, 0x027e, 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, + 0x00ff, 0xa10d, 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, + 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, + 0x00c0, 0x7035, 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, + 0x200b, 0x0000, 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa5ab, + 0x7020, 0xa005, 0x0040, 0x704e, 0x8001, 0x7022, 0x0e7f, 0x007c, + 0x20a9, 0x0008, 0x20a2, 0x00f0, 0x7052, 0x20a2, 0x20a2, 0x007c, + 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, + 0x2091, 0x8000, 0x2071, 0xa5ab, 0x7614, 0x2660, 0x2678, 0x2039, + 0x0001, 0x87ff, 0x0040, 0x70f4, 0x8cff, 0x0040, 0x70f4, 0x601c, + 0xa086, 0x0006, 0x00c0, 0x70ef, 0x88ff, 0x0040, 0x707f, 0x2800, + 0xac06, 0x00c0, 0x70ef, 0x2039, 0x0000, 0x0078, 0x708a, 0x6018, + 0xa206, 0x00c0, 0x70ef, 0x85ff, 0x0040, 0x708a, 0x6020, 0xa106, + 0x00c0, 0x70ef, 0x7024, 0xac06, 0x00c0, 0x70ba, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0040, 0x70b5, 0x1078, 0x595a, 0x6817, 0x0008, + 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, 0x2069, + 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x70aa, 0x6803, 0x0100, + 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x70b2, + 0x6827, 0x0001, 0x037f, 0x0078, 0x70ba, 0x6003, 0x0009, 0x630a, + 0x0078, 0x70ef, 0x7014, 0xac36, 0x00c0, 0x70c0, 0x660c, 0x7616, + 0x7010, 0xac36, 0x00c0, 0x70ce, 0x2c00, 0xaf36, 0x0040, 0x70cc, + 0x2f00, 0x7012, 0x0078, 0x70ce, 0x7013, 0x0000, 0x660c, 0x067e, + 0x2c00, 0xaf06, 0x0040, 0x70d7, 0x7e0e, 0x0078, 0x70d8, 0x2678, + 0x89ff, 0x00c0, 0x70e7, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, + 0x8a44, 0x0040, 0x70e5, 0x1078, 0x9e70, 0x1078, 0x8c01, 0x1078, + 0x7045, 0x88ff, 0x00c0, 0x70fe, 0x0c7f, 0x0078, 0x7069, 0x2c78, + 0x600c, 0x2060, 0x0078, 0x7069, 0xa006, 0x127f, 0x007f, 0x067f, + 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, + 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x70f5, 0x0f7e, 0x0e7e, 0x0d7e, + 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, + 0xa5ab, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x7177, 0x601c, + 0xa086, 0x0006, 0x00c0, 0x7172, 0x87ff, 0x0040, 0x7125, 0x2700, + 0xac06, 0x00c0, 0x7172, 0x0078, 0x7130, 0x6018, 0xa206, 0x00c0, + 0x7172, 0x85ff, 0x0040, 0x7130, 0x6020, 0xa106, 0x00c0, 0x7172, + 0x703c, 0xac06, 0x00c0, 0x7142, 0x037e, 0x2019, 0x0001, 0x1078, + 0x6e6c, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, + 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7148, 0x660c, 0x763a, + 0x7034, 0xac36, 0x00c0, 0x7156, 0x2c00, 0xaf36, 0x0040, 0x7154, + 0x2f00, 0x7036, 0x0078, 0x7156, 0x7037, 0x0000, 0x660c, 0x067e, + 0x2c00, 0xaf06, 0x0040, 0x715f, 0x7e0e, 0x0078, 0x7160, 0x2678, + 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x716a, + 0x1078, 0x9e70, 0x1078, 0x8c01, 0x87ff, 0x00c0, 0x7181, 0x0c7f, + 0x0078, 0x7114, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7114, 0xa006, + 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7178, + 0x0e7e, 0x2071, 0xa5ab, 0x2001, 0xa300, 0x2004, 0xa086, 0x0002, + 0x00c0, 0x7196, 0x7007, 0x0005, 0x0078, 0x7198, 0x7007, 0x0000, + 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e, + 0x127e, 0x2091, 0x8000, 0x2071, 0xa5ab, 0x2c10, 0x7638, 0x2660, + 0x2678, 0x8cff, 0x0040, 0x71d8, 0x2200, 0xac06, 0x00c0, 0x71d3, + 0x7038, 0xac36, 0x00c0, 0x71b6, 0x660c, 0x763a, 0x7034, 0xac36, + 0x00c0, 0x71c4, 0x2c00, 0xaf36, 0x0040, 0x71c2, 0x2f00, 0x7036, + 0x0078, 0x71c4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040, + 0x71cc, 0x7e0e, 0x0078, 0x71cd, 0x2678, 0x600f, 0x0000, 0xa085, + 0x0001, 0x0078, 0x71d8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x71a9, + 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, + 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, + 0x8000, 0x2071, 0xa5ab, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040, + 0x7279, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7274, + 0x7024, 0xac06, 0x00c0, 0x721f, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x724d, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x7188, + 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, + 0x0040, 0x7216, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0040, 0x721e, 0x6827, 0x0001, 0x037f, 0x700c, + 0xac36, 0x00c0, 0x7225, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0, + 0x7233, 0x2c00, 0xaf36, 0x0040, 0x7231, 0x2f00, 0x700a, 0x0078, + 0x7233, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, + 0x723c, 0x7e0e, 0x0078, 0x723d, 0x2678, 0x600f, 0x0000, 0x1078, + 0x8c27, 0x00c0, 0x7251, 0x1078, 0x2839, 0x1078, 0x8c3b, 0x00c0, + 0x726d, 0x1078, 0x7a05, 0x0078, 0x726d, 0x1078, 0x7188, 0x0078, + 0x721f, 0x1078, 0x8c3b, 0x00c0, 0x7259, 0x1078, 0x7a05, 0x0078, + 0x726d, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x726d, 0x601c, + 0xa086, 0x0003, 0x00c0, 0x7281, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x1078, + 0x7045, 0x0c7f, 0x0078, 0x71ee, 0x2c78, 0x600c, 0x2060, 0x0078, + 0x71ee, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x726d, 0x1078, 0x9e70, + 0x0078, 0x726d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006, + 0xa190, 0x0020, 0x221c, 0xa39e, 0x260c, 0x00c0, 0x729b, 0x8210, + 0x8000, 0x0078, 0x7292, 0xa005, 0x0040, 0x72a7, 0x20a9, 0x0020, + 0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f, + 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, + 0x65f8, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x2099, 0xa5a3, 0x20a9, 0x0004, 0x53a6, + 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8, + 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, + 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6c2d, + 0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x8ef5, + 0x00c0, 0x7361, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x1300, + 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040, + 0x733d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, + 0x7317, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7352, 0xa286, + 0x007f, 0x00c0, 0x7321, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078, + 0x7352, 0xd2bc, 0x0040, 0x7337, 0xa286, 0x0080, 0x00c0, 0x732e, + 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7352, 0xa2e8, 0xa434, + 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7352, 0x20a3, + 0x0000, 0x6098, 0x20a2, 0x0078, 0x7352, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa082, 0x007e, 0x0048, 0x734e, 0x0d7e, 0x2069, 0xa31a, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7352, 0x20a3, 0x0000, + 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6c2d, 0x017f, 0x0d7f, + 0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c, + 0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040, + 0x738a, 0xa186, 0x0003, 0x0040, 0x73e5, 0xa186, 0x0005, 0x0040, + 0x73c8, 0xa186, 0x0004, 0x0040, 0x73b8, 0xa186, 0x0008, 0x0040, + 0x73d2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7450, 0x027f, + 0x0d7f, 0x007c, 0x1078, 0x740d, 0x2009, 0x4000, 0x6800, 0x0079, + 0x7391, 0x73a4, 0x73b2, 0x73a6, 0x73b2, 0x73ad, 0x73a4, 0x73a4, + 0x73b2, 0x73b2, 0x73b2, 0x73b2, 0x73a4, 0x73a4, 0x73a4, 0x73a4, + 0x73a4, 0x73b2, 0x73a4, 0x73b2, 0x1078, 0x1328, 0x6824, 0xd0e4, + 0x0040, 0x73ad, 0xd0cc, 0x0040, 0x73b0, 0xa00e, 0x0078, 0x73b2, + 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x7403, + 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, + 0x6a00, 0xa286, 0x0002, 0x00c0, 0x73c6, 0xa00e, 0x0078, 0x7403, + 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, + 0x0078, 0x7403, 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x73e2, 0xa286, 0x0002, + 0x00c0, 0x73e3, 0xa00e, 0x0078, 0x7403, 0x1078, 0x740d, 0x6810, + 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, + 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040, + 0x7401, 0xa08e, 0x0004, 0x0040, 0x7401, 0x2009, 0x4000, 0x0078, + 0x7403, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018, + 0x1078, 0x6c2d, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e, + 0x067e, 0x20a1, 0x020b, 0x1078, 0x65f8, 0xa006, 0x20a3, 0x0200, + 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa092, 0x007e, 0x0048, 0x7433, 0x0d7e, 0x2069, 0xa31a, + 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa434, 0x2d6c, 0x6b10, 0x6c14, + 0x0d7f, 0x0078, 0x7439, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, + 0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0, + 0x7447, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x744b, 0x23a2, + 0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c, + 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, + 0x007c, 0x20a1, 0x020b, 0x1078, 0x655e, 0x20a3, 0x1400, 0x20a3, + 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c, + 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000, + 0x60c3, 0x0010, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x65ef, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810, + 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x007c, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x7499, 0x60c3, 0x0000, 0x1078, 0x6c2d, 0x147f, + 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x74b6, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, + 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x74be, 0x20a3, 0x0300, + 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819, + 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x2fa2, + 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061, + 0xaa00, 0x2a70, 0x7060, 0x7046, 0x704b, 0xaa00, 0x007c, 0x0e7e, + 0x127e, 0x2071, 0xa300, 0x2091, 0x8000, 0x7544, 0xa582, 0x0010, + 0x0048, 0x7509, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, + 0x74f5, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, 0x74f1, 0x0078, + 0x74e4, 0x2061, 0xaa00, 0x0078, 0x74e4, 0x6003, 0x0008, 0x8529, + 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, 0x7505, 0x754a, + 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0xaa00, 0x0078, + 0x7500, 0xa006, 0x0078, 0x7502, 0x0e7e, 0x2071, 0xa300, 0x7544, + 0xa582, 0x0010, 0x0048, 0x753a, 0x7048, 0x2060, 0x6000, 0xa086, + 0x0000, 0x0040, 0x7527, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, + 0x7523, 0x0078, 0x7516, 0x2061, 0xaa00, 0x0078, 0x7516, 0x6003, + 0x0008, 0x8529, 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, + 0x7536, 0x754a, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704b, 0xaa00, + 0x0078, 0x7532, 0xa006, 0x0078, 0x7534, 0xac82, 0xaa00, 0x1048, + 0x1328, 0x2001, 0xa315, 0x2004, 0xac02, 0x10c8, 0x1328, 0xa006, + 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, + 0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, + 0x603a, 0x603e, 0x2061, 0xa300, 0x6044, 0x8000, 0x6046, 0xa086, + 0x0001, 0x0040, 0x7564, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, + 0x6109, 0x127f, 0x0078, 0x7563, 0x601c, 0xa084, 0x000f, 0x0079, + 0x7571, 0x757a, 0x758b, 0x75a7, 0x75c3, 0x8f2d, 0x8f49, 0x8f65, + 0x757a, 0x758b, 0xa186, 0x0013, 0x00c0, 0x7583, 0x1078, 0x6010, + 0x1078, 0x6109, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x758a, 0xa016, + 0x1078, 0x15ec, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, + 0x1328, 0x1079, 0x7595, 0x067f, 0x007c, 0x75a5, 0x7891, 0x7a34, + 0x75a5, 0x7ab8, 0x75df, 0x75a5, 0x75a5, 0x7823, 0x7e6d, 0x75a5, + 0x75a5, 0x75a5, 0x75a5, 0x75a5, 0x75a5, 0x1078, 0x1328, 0x067e, + 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1328, 0x1079, 0x75b1, 0x067f, + 0x007c, 0x75c1, 0x8522, 0x75c1, 0x75c1, 0x75c1, 0x75c1, 0x75c1, + 0x75c1, 0x84c5, 0x86a8, 0x75c1, 0x8552, 0x85d8, 0x8552, 0x85d8, + 0x75c1, 0x1078, 0x1328, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, + 0x1328, 0x1079, 0x75cd, 0x067f, 0x007c, 0x75dd, 0x7eb4, 0x7f81, + 0x80c6, 0x8242, 0x75dd, 0x75dd, 0x75dd, 0x7e8d, 0x846d, 0x8471, + 0x75dd, 0x75dd, 0x75dd, 0x75dd, 0x84a1, 0x1078, 0x1328, 0xa1b6, + 0x0015, 0x00c0, 0x75e7, 0x1078, 0x753d, 0x0078, 0x75ed, 0xa1b6, + 0x0016, 0x10c0, 0x1328, 0x1078, 0x753d, 0x007c, 0x20a9, 0x000e, + 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, + 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, + 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x75fc, + 0x0e7e, 0x1078, 0x8a44, 0x0040, 0x7613, 0x6010, 0x2070, 0x7007, + 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x753d, 0x007c, 0x0d7e, + 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7624, 0x6018, 0x2068, + 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x762e, + 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x753d, + 0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c, + 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, + 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, + 0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, + 0x753d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68, + 0x017e, 0x2009, 0x0035, 0x1078, 0x8ef5, 0x017f, 0x00c0, 0x766f, + 0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xa88c, 0x6b1c, 0xa386, + 0x0003, 0x0040, 0x7673, 0xa386, 0x0006, 0x0040, 0x7677, 0x1078, + 0x753d, 0x0078, 0x7679, 0x1078, 0x767c, 0x0078, 0x7679, 0x1078, + 0x771e, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186, + 0x0015, 0x0040, 0x7705, 0xa18e, 0x0016, 0x00c0, 0x771c, 0x700c, + 0xa084, 0xff00, 0xa086, 0x1700, 0x00c0, 0x76e0, 0x8fff, 0x0040, + 0x771a, 0x6808, 0xa086, 0xffff, 0x00c0, 0x7709, 0x784c, 0xa084, + 0x0060, 0xa086, 0x0020, 0x00c0, 0x76a7, 0x797c, 0x7810, 0xa106, + 0x00c0, 0x7709, 0x7980, 0x7814, 0xa106, 0x00c0, 0x7709, 0x1078, + 0x8bf4, 0x6830, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e, + 0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x1078, 0x5a98, 0x7854, + 0xa20a, 0x0048, 0x76bc, 0x8011, 0x7a56, 0x82ff, 0x027f, 0x00c0, + 0x76c8, 0x0c7e, 0x2d60, 0x1078, 0x8832, 0x0c7f, 0x0078, 0x771a, + 0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc, 0x00c0, 0x76d3, 0x1078, + 0x4290, 0x0078, 0x76d5, 0x1078, 0x436e, 0x0d7f, 0x0c7f, 0x00c0, + 0x7709, 0x0c7e, 0x2d60, 0x1078, 0x753d, 0x0c7f, 0x0078, 0x771a, + 0x7008, 0xa086, 0x000b, 0x00c0, 0x76fa, 0x6018, 0x200c, 0xc1bc, + 0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, + 0x0078, 0x771a, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7709, 0x2001, + 0xa5a2, 0x2004, 0x683e, 0x0078, 0x771a, 0x1078, 0x7739, 0x0078, + 0x771c, 0x8fff, 0x1040, 0x1328, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68, + 0x684b, 0x0003, 0x1078, 0x8726, 0x1078, 0x8bf4, 0x1078, 0x8c01, + 0x0d7f, 0x0c7f, 0x1078, 0x753d, 0x0f7f, 0x007c, 0xa186, 0x0015, + 0x00c0, 0x7728, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x0078, 0x7736, + 0xa18e, 0x0016, 0x00c0, 0x7738, 0x0c7e, 0x2d00, 0x2060, 0x1078, + 0xa134, 0x1078, 0x5a41, 0x1078, 0x753d, 0x0c7f, 0x1078, 0x753d, + 0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80, 0x7b7c, 0xd2f4, + 0x0040, 0x7748, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x0078, 0x77ac, + 0x0c7e, 0x2d60, 0x1078, 0x874a, 0x0c7f, 0x6804, 0xa086, 0x0050, + 0x00c0, 0x7760, 0x0c7e, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, + 0x0050, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, 0x0078, 0x77ac, + 0x6800, 0xa086, 0x000f, 0x0040, 0x7782, 0x8fff, 0x1040, 0x1328, + 0x6824, 0xd0dc, 0x00c0, 0x7782, 0x6800, 0xa086, 0x0004, 0x00c0, + 0x7787, 0x784c, 0xd0ac, 0x0040, 0x7787, 0x784c, 0xc0dc, 0xc0f4, + 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, 0x0001, 0x682e, + 0x0078, 0x77a6, 0x2001, 0x0007, 0x682e, 0x0078, 0x77a6, 0x784c, + 0xd0b4, 0x00c0, 0x7794, 0xd0ac, 0x0040, 0x7782, 0x784c, 0xd0f4, + 0x00c0, 0x7782, 0x0078, 0x7775, 0xd2ec, 0x00c0, 0x7782, 0x7024, + 0xa306, 0x00c0, 0x779f, 0x7020, 0xa406, 0x0040, 0x7782, 0x7020, + 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x1078, 0x8d2b, + 0x1078, 0x6109, 0x0078, 0x77ae, 0x1078, 0x753d, 0x047f, 0x037f, + 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034, 0x2068, 0x6a1c, + 0xa286, 0x0007, 0x0040, 0x7806, 0xa286, 0x0002, 0x0040, 0x7806, + 0xa286, 0x0000, 0x0040, 0x7806, 0x6808, 0x6338, 0xa306, 0x00c0, + 0x7806, 0x2071, 0xa88c, 0xa186, 0x0015, 0x0040, 0x7800, 0xa18e, + 0x0016, 0x00c0, 0x77e8, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001, + 0x00c0, 0x77e8, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x77e8, 0x6034, + 0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0078, 0x7800, + 0x0c7e, 0x6034, 0x2060, 0x6010, 0x2068, 0x1078, 0x8a44, 0x1040, + 0x1328, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, + 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, 0x0078, 0x7806, + 0x6034, 0x2068, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x1078, 0x753d, + 0x027f, 0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, + 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7820, 0x6018, + 0x2068, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, + 0x0d7f, 0x0078, 0x7608, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1328, + 0xa1b2, 0x0040, 0x00c8, 0x7888, 0x0079, 0x782e, 0x787c, 0x7870, + 0x787c, 0x787c, 0x787c, 0x787c, 0x786e, 0x786e, 0x786e, 0x786e, + 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, + 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, + 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x787c, 0x786e, 0x787c, + 0x787c, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x787c, 0x786e, + 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, + 0x787c, 0x787c, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, + 0x786e, 0x786e, 0x786e, 0x787c, 0x786e, 0x786e, 0x1078, 0x1328, + 0x6003, 0x0001, 0x6106, 0x1078, 0x5c45, 0x127e, 0x2091, 0x8000, + 0x1078, 0x6109, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, + 0x5c45, 0x127e, 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, + 0x2600, 0x0079, 0x788b, 0x788f, 0x788f, 0x788f, 0x787c, 0x1078, + 0x1328, 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1328, 0xa1b6, 0x0013, + 0x00c0, 0x78a1, 0xa0b2, 0x0040, 0x00c8, 0x79fb, 0x2008, 0x0079, + 0x7941, 0xa1b6, 0x0027, 0x00c0, 0x78fe, 0x1078, 0x6010, 0x6004, + 0x1078, 0x8c27, 0x0040, 0x78be, 0x1078, 0x8c3b, 0x0040, 0x78f6, + 0xa08e, 0x0021, 0x0040, 0x78fa, 0xa08e, 0x0022, 0x0040, 0x78f6, + 0xa08e, 0x003d, 0x0040, 0x78fa, 0x0078, 0x78f1, 0x1078, 0x2839, + 0x2001, 0x0007, 0x1078, 0x443f, 0x6018, 0xa080, 0x0028, 0x200c, + 0x1078, 0x7a05, 0xa186, 0x007e, 0x00c0, 0x78d3, 0x2001, 0xa332, + 0x2014, 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, + 0x0028, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, 0x1078, 0x5c78, + 0x0c7e, 0x6018, 0xa065, 0x0040, 0x78e7, 0x1078, 0x471b, 0x0c7f, + 0x2c08, 0x1078, 0x9c38, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078, + 0x44bc, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0x1078, 0x7a05, + 0x0078, 0x78f1, 0x1078, 0x7a28, 0x0078, 0x78f1, 0xa186, 0x0014, + 0x00c0, 0x78f5, 0x1078, 0x6010, 0x1078, 0x2813, 0x1078, 0x8c27, + 0x00c0, 0x791d, 0x1078, 0x2839, 0x6018, 0xa080, 0x0028, 0x200c, + 0x1078, 0x7a05, 0xa186, 0x007e, 0x00c0, 0x791b, 0x2001, 0xa332, + 0x200c, 0xc185, 0x2102, 0x0078, 0x78f1, 0x1078, 0x8c3b, 0x00c0, + 0x7925, 0x1078, 0x7a05, 0x0078, 0x78f1, 0x6004, 0xa08e, 0x0032, + 0x00c0, 0x7936, 0x0e7e, 0x0f7e, 0x2071, 0xa381, 0x2079, 0x0000, + 0x1078, 0x2b56, 0x0f7f, 0x0e7f, 0x0078, 0x78f1, 0x6004, 0xa08e, + 0x0021, 0x0040, 0x7921, 0xa08e, 0x0022, 0x1040, 0x7a05, 0x0078, + 0x78f1, 0x7983, 0x7985, 0x7989, 0x798d, 0x7991, 0x7995, 0x7981, + 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, + 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, + 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7999, + 0x79ab, 0x7981, 0x79ad, 0x79ab, 0x7981, 0x7981, 0x7981, 0x7981, + 0x7981, 0x79ab, 0x79ab, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, + 0x7981, 0x7981, 0x7981, 0x79de, 0x79ab, 0x7981, 0x79a5, 0x7981, + 0x7981, 0x7981, 0x79a7, 0x7981, 0x7981, 0x7981, 0x79ab, 0x7981, + 0x7981, 0x1078, 0x1328, 0x0078, 0x79ab, 0x2001, 0x000b, 0x0078, + 0x79b8, 0x2001, 0x0003, 0x0078, 0x79b8, 0x2001, 0x0005, 0x0078, + 0x79b8, 0x2001, 0x0001, 0x0078, 0x79b8, 0x2001, 0x0009, 0x0078, + 0x79b8, 0x1078, 0x6010, 0x6003, 0x0005, 0x2001, 0xa5a2, 0x2004, + 0x603e, 0x1078, 0x6109, 0x0078, 0x79b7, 0x0078, 0x79ab, 0x0078, + 0x79ab, 0x1078, 0x443f, 0x0078, 0x79f0, 0x1078, 0x6010, 0x6003, + 0x0004, 0x2001, 0xa5a0, 0x2004, 0x6016, 0x1078, 0x6109, 0x007c, + 0x1078, 0x443f, 0x1078, 0x6010, 0x2001, 0xa5a2, 0x2004, 0x603e, + 0x6003, 0x0002, 0x037e, 0x2019, 0xa35c, 0x2304, 0xa084, 0xff00, + 0x00c0, 0x79cf, 0x2019, 0xa5a0, 0x231c, 0x0078, 0x79d8, 0x8007, + 0xa09a, 0x0004, 0x0048, 0x79ca, 0x8003, 0x801b, 0x831b, 0xa318, + 0x6316, 0x037f, 0x1078, 0x6109, 0x0078, 0x79b7, 0x0e7e, 0x0f7e, + 0x2071, 0xa381, 0x2079, 0x0000, 0x1078, 0x2b56, 0x0f7f, 0x0e7f, + 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, 0x0078, 0x79b7, + 0x1078, 0x6010, 0x6003, 0x0002, 0x2001, 0xa5a0, 0x2004, 0x6016, + 0x1078, 0x6109, 0x007c, 0x2600, 0x2008, 0x0079, 0x79ff, 0x7a03, + 0x7a03, 0x7a03, 0x79f0, 0x1078, 0x1328, 0x0e7e, 0x1078, 0x8a44, + 0x0040, 0x7a21, 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7a21, + 0x7007, 0x0000, 0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7a23, + 0xa08e, 0x003d, 0x0040, 0x7a23, 0x017f, 0x7037, 0x0103, 0x7033, + 0x0100, 0x0e7f, 0x007c, 0x017f, 0x1078, 0x7a28, 0x0078, 0x7a21, + 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, + 0x7023, 0x8001, 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, + 0xa084, 0x00ff, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1328, 0x6604, + 0xa6b6, 0x0043, 0x00c0, 0x7a48, 0x1078, 0x8e6d, 0x0078, 0x7aa7, + 0x6604, 0xa6b6, 0x0033, 0x00c0, 0x7a51, 0x1078, 0x8e11, 0x0078, + 0x7aa7, 0x6604, 0xa6b6, 0x0028, 0x00c0, 0x7a5a, 0x1078, 0x8c6a, + 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7a63, 0x1078, + 0x8c84, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7a6c, + 0x1078, 0x75ee, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0000, 0x00c0, + 0x7a75, 0x1078, 0x780c, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0022, + 0x00c0, 0x7a7e, 0x1078, 0x7617, 0x0078, 0x7aa7, 0x6604, 0xa6b6, + 0x0035, 0x00c0, 0x7a87, 0x1078, 0x7653, 0x0078, 0x7aa7, 0x6604, + 0xa6b6, 0x0039, 0x00c0, 0x7a90, 0x1078, 0x77b2, 0x0078, 0x7aa7, + 0x6604, 0xa6b6, 0x003d, 0x00c0, 0x7a99, 0x1078, 0x7633, 0x0078, + 0x7aa7, 0xa1b6, 0x0015, 0x00c0, 0x7aa1, 0x1079, 0x7aac, 0x0078, + 0x7aa7, 0xa1b6, 0x0016, 0x00c0, 0x7aa8, 0x1079, 0x7bfd, 0x007c, + 0x1078, 0x7583, 0x0078, 0x7aa7, 0x7ad0, 0x7ad3, 0x7ad0, 0x7b1e, + 0x7ad0, 0x7b91, 0x7c09, 0x7ad0, 0x7ad0, 0x7bd5, 0x7ad0, 0x7beb, + 0xa1b6, 0x0048, 0x0040, 0x7ac4, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x1078, 0x15ec, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, + 0x7000, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x753d, 0x007c, + 0x0005, 0x0005, 0x007c, 0x0e7e, 0x2071, 0xa300, 0x707c, 0xa086, + 0x0074, 0x00c0, 0x7b07, 0x1078, 0x9c0c, 0x00c0, 0x7af9, 0x0d7e, + 0x6018, 0x2068, 0x7030, 0xd08c, 0x0040, 0x7aec, 0x6800, 0xd0bc, + 0x0040, 0x7aec, 0xc0c5, 0x6802, 0x1078, 0x7b0b, 0x0d7f, 0x2001, + 0x0006, 0x1078, 0x443f, 0x1078, 0x2839, 0x1078, 0x753d, 0x0078, + 0x7b09, 0x2001, 0x000a, 0x1078, 0x443f, 0x1078, 0x2839, 0x6003, + 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7b09, 0x1078, + 0x7b81, 0x0e7f, 0x007c, 0x6800, 0xd084, 0x0040, 0x7b1d, 0x2001, + 0x0000, 0x1078, 0x442b, 0x2069, 0xa351, 0x6804, 0xd0a4, 0x0040, + 0x7b1d, 0x2001, 0x0006, 0x1078, 0x4472, 0x007c, 0x0d7e, 0x2011, + 0xa31f, 0x2204, 0xa086, 0x0074, 0x00c0, 0x7b7d, 0x6018, 0x2068, + 0x6aa0, 0xa286, 0x007e, 0x00c0, 0x7b31, 0x1078, 0x7d17, 0x0078, + 0x7b7f, 0x1078, 0x7d0d, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, + 0xa286, 0x0080, 0x00c0, 0x7b55, 0x6813, 0x00ff, 0x6817, 0xfffc, + 0x6010, 0xa005, 0x0040, 0x7b4b, 0x2068, 0x6807, 0x0000, 0x6837, + 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x1078, 0x443f, 0x1078, + 0x2839, 0x1078, 0x753d, 0x0078, 0x7b7f, 0x0e7e, 0x2071, 0xa332, + 0x2e04, 0xd09c, 0x0040, 0x7b70, 0x2071, 0xa880, 0x7108, 0x720c, + 0xa18c, 0x00ff, 0x00c0, 0x7b68, 0xa284, 0xff00, 0x0040, 0x7b70, + 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x00c0, 0x7b70, 0x7112, 0x7216, + 0x0e7f, 0x2001, 0x0004, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007, + 0x0003, 0x1078, 0x5c45, 0x0078, 0x7b7f, 0x1078, 0x7b81, 0x0d7f, + 0x007c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x0040, 0x7b8c, + 0x2001, 0x0007, 0x1078, 0x443f, 0x1078, 0x2839, 0x1078, 0x753d, + 0x007c, 0x0e7e, 0x2071, 0xa300, 0x707c, 0xa086, 0x0014, 0x00c0, + 0x7bcf, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7ba4, 0x6010, 0xa005, + 0x00c0, 0x7ba4, 0x1078, 0x35f7, 0x0d7e, 0x6018, 0x2068, 0x1078, + 0x457d, 0x1078, 0x7b0b, 0x0d7f, 0x1078, 0x7dba, 0x00c0, 0x7bcf, + 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x7bcf, + 0x2001, 0x0006, 0x1078, 0x443f, 0x0e7e, 0x6010, 0xa005, 0x0040, + 0x7bc8, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, + 0x0e7f, 0x1078, 0x2839, 0x1078, 0x753d, 0x0078, 0x7bd3, 0x1078, + 0x7a05, 0x1078, 0x7b81, 0x0e7f, 0x007c, 0x2011, 0xa31f, 0x2204, + 0xa086, 0x0014, 0x00c0, 0x7be8, 0x2001, 0x0002, 0x1078, 0x443f, + 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7bea, + 0x1078, 0x7b81, 0x007c, 0x2011, 0xa31f, 0x2204, 0xa086, 0x0004, + 0x00c0, 0x7bfa, 0x2001, 0x0007, 0x1078, 0x443f, 0x1078, 0x753d, + 0x0078, 0x7bfc, 0x1078, 0x7b81, 0x007c, 0x7ad0, 0x7c11, 0x7ad0, + 0x7c4e, 0x7ad0, 0x7cc0, 0x7c09, 0x7ad0, 0x7ad0, 0x7cd5, 0x7ad0, + 0x7ce8, 0x6604, 0xa6b6, 0x001e, 0x00c0, 0x7c10, 0x1078, 0x753d, + 0x007c, 0x0d7e, 0x0c7e, 0x1078, 0x7cfb, 0x00c0, 0x7c27, 0x2001, + 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f, 0x6003, + 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, 0x0078, 0x7c4b, 0x2009, + 0xa88e, 0x2104, 0xa086, 0x0009, 0x00c0, 0x7c3c, 0x6018, 0x2068, + 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x7c49, 0x8001, 0x6842, + 0x6017, 0x000a, 0x0078, 0x7c4b, 0x2009, 0xa88f, 0x2104, 0xa084, + 0xff00, 0xa086, 0x1900, 0x00c0, 0x7c49, 0x1078, 0x753d, 0x0078, + 0x7c4b, 0x1078, 0x7b81, 0x0c7f, 0x0d7f, 0x007c, 0x1078, 0x7d0a, + 0x00c0, 0x7c62, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, + 0x1078, 0x443f, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, + 0x0078, 0x7c8e, 0x1078, 0x7a05, 0x2009, 0xa88e, 0x2134, 0xa6b4, + 0x00ff, 0xa686, 0x0005, 0x0040, 0x7c8f, 0xa686, 0x000b, 0x0040, + 0x7c8c, 0x2009, 0xa88f, 0x2104, 0xa084, 0xff00, 0x00c0, 0x7c7c, + 0xa686, 0x0009, 0x0040, 0x7c8f, 0xa086, 0x1900, 0x00c0, 0x7c8c, + 0xa686, 0x0009, 0x0040, 0x7c8f, 0x2001, 0x0004, 0x1078, 0x443f, + 0x1078, 0x753d, 0x0078, 0x7c8e, 0x1078, 0x7b81, 0x007c, 0x0d7e, + 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x7c9d, 0x6838, 0xd0fc, + 0x0040, 0x7c9d, 0x0d7f, 0x0078, 0x7c8c, 0x6018, 0x2068, 0x6840, + 0xa084, 0x00ff, 0xa005, 0x0040, 0x7cae, 0x8001, 0x6842, 0x6017, + 0x000a, 0x6007, 0x0016, 0x0d7f, 0x0078, 0x7c8e, 0x68a0, 0xa086, + 0x007e, 0x00c0, 0x7cbb, 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, + 0x0e7f, 0x0078, 0x7cbd, 0x1078, 0x2813, 0x0d7f, 0x0078, 0x7c8c, + 0x1078, 0x7d0a, 0x00c0, 0x7cd0, 0x2001, 0x0004, 0x1078, 0x443f, + 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x5c45, 0x0078, 0x7cd4, + 0x1078, 0x7a05, 0x1078, 0x7b81, 0x007c, 0x1078, 0x7d0a, 0x00c0, + 0x7ce5, 0x2001, 0x0008, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007, + 0x0005, 0x1078, 0x5c45, 0x0078, 0x7ce7, 0x1078, 0x7b81, 0x007c, + 0x1078, 0x7d0a, 0x00c0, 0x7cf8, 0x2001, 0x000a, 0x1078, 0x443f, + 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7cfa, + 0x1078, 0x7b81, 0x007c, 0x2009, 0xa88e, 0x2104, 0xa086, 0x0003, + 0x00c0, 0x7d09, 0x2009, 0xa88f, 0x2104, 0xa084, 0xff00, 0xa086, + 0x2a00, 0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88, + 0x0006, 0x2164, 0x1078, 0x4513, 0x017f, 0x0c7f, 0x007c, 0x0f7e, + 0x0e7e, 0x0d7e, 0x037e, 0x017e, 0x6018, 0x2068, 0x2071, 0xa332, + 0x2e04, 0xa085, 0x0003, 0x2072, 0x1078, 0x7d8b, 0x0040, 0x7d50, + 0x2001, 0xa352, 0x2004, 0xd0a4, 0x0040, 0x7d39, 0xa006, 0x2020, + 0x2009, 0x002a, 0x1078, 0x9ec0, 0x2001, 0xa30c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x27e2, 0x2071, + 0xa300, 0x1078, 0x260d, 0x0c7e, 0x157e, 0x20a9, 0x0081, 0x2009, + 0x007f, 0x1078, 0x2921, 0x8108, 0x00f0, 0x7d49, 0x157f, 0x0c7f, + 0x1078, 0x7d0d, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xa880, + 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa31a, 0x206a, + 0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa31b, 0x206a, 0x78ea, + 0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa325, 0x200a, 0x2069, + 0xa88e, 0x2071, 0xa59c, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818, + 0x700a, 0x681c, 0x700e, 0x1078, 0x8da9, 0x2001, 0x0006, 0x1078, + 0x443f, 0x1078, 0x2839, 0x1078, 0x753d, 0x017f, 0x037f, 0x0d7f, + 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e, 0x2019, + 0xa325, 0x231c, 0x83ff, 0x0040, 0x7db5, 0x2071, 0xa880, 0x2e14, + 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x00c0, + 0x7db5, 0x2011, 0xa896, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, + 0x7e55, 0x00c0, 0x7db5, 0x2011, 0xa89a, 0xad98, 0x0006, 0x20a9, + 0x0004, 0x1078, 0x7e55, 0x00c0, 0x7db5, 0x157f, 0x0e7f, 0x037f, + 0x027f, 0x007c, 0x0e7e, 0x2071, 0xa88c, 0x7004, 0xa086, 0x0014, + 0x00c0, 0x7ddd, 0x7008, 0xa086, 0x0800, 0x00c0, 0x7ddd, 0x700c, + 0xd0ec, 0x0040, 0x7ddb, 0xa084, 0x0f00, 0xa086, 0x0100, 0x00c0, + 0x7ddb, 0x7024, 0xd0a4, 0x00c0, 0x7dd8, 0xd0ac, 0x0040, 0x7ddb, + 0xa006, 0x0078, 0x7ddd, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x0e7e, + 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, 0x127e, + 0x2091, 0x8000, 0x2029, 0xa5b4, 0x252c, 0x2021, 0xa5ba, 0x2424, + 0x2061, 0xaa00, 0x2071, 0xa300, 0x7244, 0x7060, 0xa202, 0x00c8, + 0x7e43, 0x1078, 0x9ee5, 0x0040, 0x7e3b, 0x671c, 0xa786, 0x0001, + 0x0040, 0x7e3b, 0xa786, 0x0007, 0x0040, 0x7e3b, 0x2500, 0xac06, + 0x0040, 0x7e3b, 0x2400, 0xac06, 0x0040, 0x7e3b, 0x0c7e, 0x6000, + 0xa086, 0x0004, 0x00c0, 0x7e16, 0x1078, 0x1749, 0xa786, 0x0008, + 0x00c0, 0x7e25, 0x1078, 0x8c3b, 0x00c0, 0x7e25, 0x0c7f, 0x1078, + 0x7a05, 0x1078, 0x8c01, 0x0078, 0x7e3b, 0x6010, 0x2068, 0x1078, + 0x8a44, 0x0040, 0x7e38, 0xa786, 0x0003, 0x00c0, 0x7e4d, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, + 0x1078, 0x8c01, 0x0c7f, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, + 0x7e43, 0x0078, 0x7df4, 0x127f, 0x007f, 0x027f, 0x047f, 0x057f, + 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0, + 0x7e2f, 0x1078, 0x9e70, 0x0078, 0x7e38, 0x220c, 0x2304, 0xa106, + 0x00c0, 0x7e60, 0x8210, 0x8318, 0x00f0, 0x7e55, 0xa006, 0x007c, + 0x2304, 0xa102, 0x0048, 0x7e68, 0x2001, 0x0001, 0x0078, 0x7e6a, + 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, 0x0044, + 0x10c8, 0x1328, 0x1078, 0x8c27, 0x0040, 0x7e7c, 0x1078, 0x8c3b, + 0x0040, 0x7e89, 0x0078, 0x7e82, 0x1078, 0x2839, 0x1078, 0x8c3b, + 0x0040, 0x7e89, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, + 0x007c, 0x1078, 0x7a05, 0x0078, 0x7e82, 0xa182, 0x0040, 0x0079, + 0x7e91, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, + 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea6, 0x7ea6, 0x7ea6, 0x7ea6, + 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea6, 0x1078, 0x1328, 0x600b, 0xffff, + 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, 0x8000, + 0x1078, 0x6109, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x7ebd, + 0x6004, 0xa082, 0x0040, 0x0079, 0x7f48, 0xa186, 0x0027, 0x00c0, + 0x7edf, 0x1078, 0x6010, 0x1078, 0x2813, 0x0d7e, 0x6110, 0x2168, + 0x1078, 0x8a44, 0x0040, 0x7ed9, 0x6837, 0x0103, 0x684b, 0x0029, + 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4982, 0x1078, + 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0xa186, + 0x0014, 0x00c0, 0x7ee8, 0x6004, 0xa082, 0x0040, 0x0079, 0x7f10, + 0xa186, 0x0046, 0x0040, 0x7ef4, 0xa186, 0x0045, 0x0040, 0x7ef4, + 0xa186, 0x0047, 0x10c0, 0x1328, 0x2001, 0x0109, 0x2004, 0xd084, + 0x0040, 0x7f0d, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, + 0x1078, 0x5ad2, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, + 0x0002, 0x00c0, 0x7f0d, 0x0078, 0x7f81, 0x1078, 0x7583, 0x007c, + 0x7f25, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, + 0x7f23, 0x7f23, 0x7f23, 0x7f41, 0x7f41, 0x7f41, 0x7f41, 0x7f23, + 0x7f41, 0x7f23, 0x7f41, 0x1078, 0x1328, 0x1078, 0x6010, 0x0d7e, + 0x6110, 0x2168, 0x1078, 0x8a44, 0x0040, 0x7f3b, 0x6837, 0x0103, + 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x1078, + 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, + 0x007c, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, + 0x7f5d, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, + 0x7f5b, 0x7f5b, 0x7f5b, 0x7f6f, 0x7f6f, 0x7f6f, 0x7f6f, 0x7f5b, + 0x7f7a, 0x7f5b, 0x7f6f, 0x1078, 0x1328, 0x1078, 0x6010, 0x2001, + 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x6109, 0x6010, + 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078, + 0x6010, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x6003, 0x000f, 0x1078, + 0x6109, 0x007c, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, + 0x007c, 0xa182, 0x0040, 0x0079, 0x7f85, 0x7f98, 0x7f98, 0x7f98, + 0x7f98, 0x7f98, 0x7f9a, 0x8095, 0x80b7, 0x7f98, 0x7f98, 0x7f98, + 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, + 0x1078, 0x1328, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2071, 0xa880, + 0x7124, 0x610a, 0x2071, 0xa88c, 0x6110, 0x2168, 0x7614, 0xa6b4, + 0x0fff, 0x86ff, 0x0040, 0x8058, 0xa68c, 0x0c00, 0x0040, 0x7fd1, + 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x7fcd, 0x684c, + 0xd0ac, 0x0040, 0x7fcd, 0x6024, 0xd0dc, 0x00c0, 0x7fcd, 0x6850, + 0xd0bc, 0x00c0, 0x7fcd, 0x7318, 0x6814, 0xa306, 0x00c0, 0x806f, + 0x731c, 0x6810, 0xa306, 0x00c0, 0x806f, 0x7318, 0x6b62, 0x731c, + 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x8004, 0xa186, + 0x0028, 0x00c0, 0x7fe1, 0x1078, 0x8c15, 0x684b, 0x001c, 0x0078, + 0x8006, 0xd6dc, 0x0040, 0x7ffd, 0x684b, 0x0015, 0x684c, 0xd0ac, + 0x0040, 0x7ffb, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x7ffb, + 0x7018, 0xa106, 0x00c0, 0x7ff8, 0x701c, 0xa206, 0x0040, 0x7ffb, + 0x6962, 0x6a5e, 0xc6dc, 0x0078, 0x8006, 0xd6d4, 0x0040, 0x8004, + 0x684b, 0x0007, 0x0078, 0x8006, 0x684b, 0x0000, 0x6837, 0x0103, + 0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x802f, 0xa686, 0x0100, 0x00c0, + 0x801a, 0x2001, 0xa899, 0x2004, 0xa005, 0x00c0, 0x801a, 0xc6c4, + 0x0078, 0x7fa9, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0040, 0x802f, + 0xa38a, 0x0009, 0x0048, 0x8026, 0x2019, 0x0008, 0x037e, 0x2308, + 0x2019, 0xa898, 0xad90, 0x0019, 0x1078, 0x8739, 0x037f, 0xd6cc, + 0x0040, 0x8085, 0x7124, 0x695a, 0x81ff, 0x0040, 0x8085, 0xa192, + 0x0021, 0x00c8, 0x8046, 0x2071, 0xa898, 0x831c, 0x2300, 0xae18, + 0xad90, 0x001d, 0x1078, 0x8739, 0x0078, 0x8085, 0x6838, 0xd0fc, + 0x0040, 0x804f, 0x2009, 0x0020, 0x695a, 0x0078, 0x803b, 0x0f7e, + 0x2d78, 0x1078, 0x86d1, 0x0f7f, 0x1078, 0x8726, 0x0078, 0x8087, + 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8075, 0x684c, + 0xd0ac, 0x0040, 0x8075, 0x6024, 0xd0dc, 0x00c0, 0x8075, 0x6850, + 0xd0bc, 0x00c0, 0x8075, 0x684c, 0xd0f4, 0x00c0, 0x8075, 0x1078, + 0x8cfa, 0x0d7f, 0x0e7f, 0x0078, 0x8094, 0x684b, 0x0000, 0x6837, + 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x8085, 0x6810, 0x6914, + 0xa115, 0x0040, 0x8085, 0x1078, 0x8233, 0x1078, 0x4982, 0x6218, + 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x1078, 0x8cc4, 0x0d7f, 0x0e7f, + 0x00c0, 0x8094, 0x1078, 0x753d, 0x007c, 0x0f7e, 0x6003, 0x0003, + 0x2079, 0xa88c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, + 0x784c, 0xd0ac, 0x0040, 0x80a8, 0x6003, 0x0002, 0x0f7f, 0x007c, + 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x603f, 0x0000, 0x2c10, + 0x1078, 0x1cab, 0x1078, 0x5c64, 0x1078, 0x61d3, 0x007c, 0x2001, + 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, + 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0xa182, 0x0040, + 0x0079, 0x80ca, 0x80dd, 0x80dd, 0x80dd, 0x80dd, 0x80dd, 0x80df, + 0x8182, 0x80dd, 0x80dd, 0x8198, 0x8209, 0x80dd, 0x80dd, 0x80dd, + 0x80dd, 0x8218, 0x80dd, 0x80dd, 0x80dd, 0x1078, 0x1328, 0x077e, + 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xa88c, 0x6110, 0x2178, 0x7614, + 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, + 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x817d, 0xa694, 0xff00, + 0xa284, 0x0c00, 0x0040, 0x8100, 0x7018, 0x7862, 0x701c, 0x785e, + 0xa284, 0x0300, 0x0040, 0x817d, 0x1078, 0x1381, 0x1040, 0x1328, + 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, + 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, + 0x0040, 0x811e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0040, 0x813a, 0xa186, 0x0028, 0x00c0, 0x812c, + 0x684b, 0x001c, 0x0078, 0x813c, 0xd6dc, 0x0040, 0x8133, 0x684b, + 0x0015, 0x0078, 0x813c, 0xd6d4, 0x0040, 0x813a, 0x684b, 0x0007, + 0x0078, 0x813c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, + 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x815a, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0040, 0x815a, 0xa38a, 0x0009, 0x0048, 0x8151, 0x2019, + 0x0008, 0x037e, 0x2308, 0x2019, 0xa898, 0xad90, 0x0019, 0x1078, + 0x8739, 0x037f, 0xd6cc, 0x0040, 0x817d, 0x7124, 0x695a, 0x81ff, + 0x0040, 0x817d, 0xa192, 0x0021, 0x00c8, 0x8171, 0x2071, 0xa898, + 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x8739, 0x0078, + 0x817d, 0x7838, 0xd0fc, 0x0040, 0x817a, 0x2009, 0x0020, 0x695a, + 0x0078, 0x8166, 0x2d78, 0x1078, 0x86d1, 0x0d7f, 0x0e7f, 0x0f7f, + 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xa88c, 0x7c04, + 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, + 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x1cab, 0x1078, 0x6c26, 0x007c, + 0x0d7e, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x81a4, + 0x2001, 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x60b8, + 0x1078, 0x61d3, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x8207, + 0xd1cc, 0x0040, 0x81de, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x81d6, + 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, + 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, + 0x8210, 0x00f0, 0x81c5, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, + 0x017f, 0x2168, 0x1078, 0x13aa, 0x0078, 0x8201, 0x017e, 0x1078, + 0x13aa, 0x0d7f, 0x1078, 0x8726, 0x0078, 0x8201, 0x6837, 0x0103, + 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, 0x81fd, 0xa086, + 0x0028, 0x00c0, 0x81ef, 0x684b, 0x001c, 0x0078, 0x81ff, 0xd1dc, + 0x0040, 0x81f6, 0x684b, 0x0015, 0x0078, 0x81ff, 0xd1d4, 0x0040, + 0x81fd, 0x684b, 0x0007, 0x0078, 0x81ff, 0x684b, 0x0000, 0x1078, + 0x4982, 0x1078, 0x8cc4, 0x00c0, 0x8207, 0x1078, 0x753d, 0x0d7f, + 0x007c, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x6003, 0x0002, 0x2001, + 0xa5a2, 0x2004, 0x603e, 0x1078, 0x60b8, 0x1078, 0x61d3, 0x007c, + 0x1078, 0x60b8, 0x1078, 0x2813, 0x0d7e, 0x6110, 0x2168, 0x1078, + 0x8a44, 0x0040, 0x822d, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, + 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, + 0x1078, 0x61d3, 0x007c, 0x684b, 0x0015, 0xd1fc, 0x0040, 0x823f, + 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, + 0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x8246, 0x8259, 0x8259, + 0x8259, 0x8259, 0x8259, 0x825b, 0x8259, 0x8333, 0x833f, 0x8259, + 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, + 0x8259, 0x1078, 0x1328, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, + 0xa88c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x0f7e, 0x2c78, + 0x1078, 0x4893, 0x0f7f, 0x0040, 0x827e, 0xa684, 0x00ff, 0x00c0, + 0x827e, 0x6024, 0xd0f4, 0x00c0, 0x827a, 0x7808, 0xa086, 0x0000, + 0x00c0, 0x827e, 0x1078, 0x8cfa, 0x0078, 0x832e, 0x7e46, 0x7f4c, + 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, + 0x0040, 0x8323, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x8294, + 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x8320, + 0xa686, 0x0100, 0x00c0, 0x82a6, 0x2001, 0xa899, 0x2004, 0xa005, + 0x00c0, 0x82a6, 0xc6c4, 0x7e46, 0x0078, 0x8287, 0x1078, 0x1381, + 0x1040, 0x1328, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, + 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, + 0x6e46, 0xa68c, 0x0c00, 0x0040, 0x82c1, 0x7318, 0x6b62, 0x731c, + 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x82dd, 0xa186, + 0x0028, 0x00c0, 0x82cf, 0x684b, 0x001c, 0x0078, 0x82df, 0xd6dc, + 0x0040, 0x82d6, 0x684b, 0x0015, 0x0078, 0x82df, 0xd6d4, 0x0040, + 0x82dd, 0x684b, 0x0007, 0x0078, 0x82df, 0x684b, 0x0000, 0x6f4e, + 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x82fd, + 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0040, 0x82fd, 0xa38a, 0x0009, + 0x0048, 0x82f4, 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xa898, + 0xad90, 0x0019, 0x1078, 0x8739, 0x037f, 0xd6cc, 0x0040, 0x8320, + 0x7124, 0x695a, 0x81ff, 0x0040, 0x8320, 0xa192, 0x0021, 0x00c8, + 0x8314, 0x2071, 0xa898, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, + 0x1078, 0x8739, 0x0078, 0x8320, 0x7838, 0xd0fc, 0x0040, 0x831d, + 0x2009, 0x0020, 0x695a, 0x0078, 0x8309, 0x2d78, 0x1078, 0x86d1, + 0xd6dc, 0x00c0, 0x8326, 0xa006, 0x0078, 0x832c, 0x2001, 0x0001, + 0x2071, 0xa88c, 0x7218, 0x731c, 0x1078, 0x1645, 0x0d7f, 0x0e7f, + 0x0f7f, 0x077f, 0x007c, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0x2001, + 0xa5a2, 0x2004, 0x603e, 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, + 0x694c, 0xd1e4, 0x0040, 0x846b, 0x603f, 0x0000, 0x0f7e, 0x2c78, + 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8385, 0x6814, 0x6910, 0xa115, + 0x0040, 0x8385, 0x6a60, 0xa206, 0x00c0, 0x8362, 0x685c, 0xa106, + 0x0040, 0x8385, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, + 0x0000, 0x685f, 0x0000, 0x6024, 0xd0f4, 0x00c0, 0x837a, 0x697c, + 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6024, + 0xc0f5, 0x6026, 0x0d7e, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, + 0x0d7f, 0x1078, 0x8cfa, 0x0078, 0x846b, 0x694c, 0xd1cc, 0x0040, + 0x8430, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x83ea, 0x017e, 0x684c, + 0x007e, 0x6850, 0x007e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, + 0xa0b6, 0x0002, 0x0040, 0x83bf, 0xa086, 0x0028, 0x00c0, 0x83a6, + 0x684b, 0x001c, 0x784b, 0x001c, 0x0078, 0x83ca, 0xd1dc, 0x0040, + 0x83b6, 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x8ea5, 0x0040, + 0x83b4, 0x7944, 0xc1dc, 0x7946, 0x0078, 0x83ca, 0xd1d4, 0x0040, + 0x83bf, 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x83ca, 0x684c, + 0xd0ac, 0x0040, 0x83ca, 0x6810, 0x6914, 0xa115, 0x0040, 0x83ca, + 0x1078, 0x8233, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, + 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, + 0x2304, 0x2012, 0x8318, 0x8210, 0x00f0, 0x83d8, 0x157f, 0x0f7f, + 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, 0x2168, 0x1078, 0x13aa, + 0x0078, 0x8465, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, + 0xa0b6, 0x0002, 0x0040, 0x8417, 0xa086, 0x0028, 0x00c0, 0x83fe, + 0x684b, 0x001c, 0x784b, 0x001c, 0x0078, 0x8422, 0xd1dc, 0x0040, + 0x840e, 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x8ea5, 0x0040, + 0x840c, 0x7944, 0xc1dc, 0x7946, 0x0078, 0x8422, 0xd1d4, 0x0040, + 0x8417, 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x8422, 0x684c, + 0xd0ac, 0x0040, 0x8422, 0x6810, 0x6914, 0xa115, 0x0040, 0x8422, + 0x1078, 0x8233, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, + 0x0f7f, 0x1078, 0x13aa, 0x0d7f, 0x1078, 0x8726, 0x0078, 0x8465, + 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, + 0x8456, 0xa086, 0x0028, 0x00c0, 0x8441, 0x684b, 0x001c, 0x0078, + 0x8463, 0xd1dc, 0x0040, 0x844f, 0x684b, 0x0015, 0x1078, 0x8ea5, + 0x0040, 0x844d, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8463, 0xd1d4, + 0x0040, 0x8456, 0x684b, 0x0007, 0x0078, 0x8463, 0x684b, 0x0000, + 0x684c, 0xd0ac, 0x0040, 0x8463, 0x6810, 0x6914, 0xa115, 0x0040, + 0x8463, 0x1078, 0x8233, 0x1078, 0x4982, 0x1078, 0x8cc4, 0x00c0, + 0x846b, 0x1078, 0x753d, 0x0d7f, 0x007c, 0x1078, 0x6010, 0x0078, + 0x8473, 0x1078, 0x60b8, 0x1078, 0x8a44, 0x0040, 0x8492, 0x0d7e, + 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa30c, 0x210c, 0xd18c, + 0x00c0, 0x849d, 0xd184, 0x00c0, 0x8499, 0x6108, 0x694a, 0xa18e, + 0x0029, 0x00c0, 0x848d, 0x1078, 0xa181, 0x6847, 0x0000, 0x1078, + 0x4982, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, 0x1078, 0x61d3, + 0x007c, 0x684b, 0x0004, 0x0078, 0x848d, 0x684b, 0x0004, 0x0078, + 0x848d, 0xa182, 0x0040, 0x0079, 0x84a5, 0x84b8, 0x84b8, 0x84b8, + 0x84b8, 0x84b8, 0x84ba, 0x84b8, 0x84bd, 0x84b8, 0x84b8, 0x84b8, + 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, + 0x1078, 0x1328, 0x1078, 0x753d, 0x007c, 0x007e, 0x027e, 0xa016, + 0x1078, 0x15ec, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, 0x0079, + 0x84c9, 0x84d2, 0x84d0, 0x84d0, 0x84de, 0x84d0, 0x84d0, 0x84d0, + 0x1078, 0x1328, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e, + 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x027e, 0x057e, + 0x0d7e, 0x0e7e, 0x2071, 0xa880, 0x7224, 0x6212, 0x7220, 0x1078, + 0x8a30, 0x0040, 0x8503, 0x2268, 0x6800, 0xa086, 0x0000, 0x0040, + 0x8503, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x8503, 0x0c7e, 0x2d60, + 0x1078, 0x874a, 0x0c7f, 0x0040, 0x8503, 0x6803, 0x0002, 0x6007, + 0x0086, 0x0078, 0x8505, 0x6007, 0x0087, 0x6003, 0x0001, 0x1078, + 0x5bf8, 0x1078, 0x6109, 0x0f7e, 0x2278, 0x1078, 0x4893, 0x0f7f, + 0x0040, 0x851d, 0x6824, 0xd0ec, 0x0040, 0x851d, 0x0c7e, 0x2260, + 0x603f, 0x0000, 0x1078, 0x8cfa, 0x0c7f, 0x0e7f, 0x0d7f, 0x057f, + 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x8533, 0x6004, 0xa08a, + 0x0085, 0x1048, 0x1328, 0xa08a, 0x008c, 0x10c8, 0x1328, 0xa082, + 0x0085, 0x0079, 0x8542, 0xa186, 0x0027, 0x0040, 0x853b, 0xa186, + 0x0014, 0x10c0, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, + 0x6109, 0x007c, 0x8549, 0x854b, 0x854b, 0x8549, 0x8549, 0x8549, + 0x8549, 0x1078, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, + 0x6109, 0x007c, 0xa186, 0x0013, 0x00c0, 0x855c, 0x6004, 0xa082, + 0x0085, 0x2008, 0x0078, 0x8597, 0xa186, 0x0027, 0x00c0, 0x857f, + 0x1078, 0x6010, 0x1078, 0x2813, 0x0d7e, 0x6010, 0x2068, 0x1078, + 0x8a44, 0x0040, 0x8575, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, + 0x0029, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, + 0x1078, 0x6109, 0x007c, 0x1078, 0x7583, 0x0078, 0x857a, 0xa186, + 0x0014, 0x00c0, 0x857b, 0x1078, 0x6010, 0x0d7e, 0x6010, 0x2068, + 0x1078, 0x8a44, 0x0040, 0x8575, 0x6837, 0x0103, 0x6847, 0x0000, + 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8571, 0x0079, + 0x8599, 0x85a2, 0x85a0, 0x85a0, 0x85a0, 0x85a0, 0x85a0, 0x85bd, + 0x1078, 0x1328, 0x1078, 0x6010, 0x6030, 0xa08c, 0xff00, 0x810f, + 0xa186, 0x0039, 0x0040, 0x85b0, 0xa186, 0x0035, 0x00c0, 0x85b4, + 0x2001, 0xa5a0, 0x0078, 0x85b6, 0x2001, 0xa5a1, 0x2004, 0x6016, + 0x6003, 0x000c, 0x1078, 0x6109, 0x007c, 0x1078, 0x6010, 0x6030, + 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x85cb, 0xa186, + 0x0035, 0x00c0, 0x85cf, 0x2001, 0xa5a0, 0x0078, 0x85d1, 0x2001, + 0xa5a1, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x6109, 0x007c, + 0xa182, 0x008c, 0x00c8, 0x85e2, 0xa182, 0x0085, 0x0048, 0x85e2, + 0x0079, 0x85e5, 0x1078, 0x7583, 0x007c, 0x85ec, 0x85ec, 0x85ec, + 0x85ec, 0x85ee, 0x8643, 0x85ec, 0x1078, 0x1328, 0x0f7e, 0x2c78, + 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8601, 0x6030, 0xa08c, 0xff00, + 0x810f, 0xa186, 0x0039, 0x0040, 0x865a, 0xa186, 0x0035, 0x0040, + 0x865a, 0x0d7e, 0x1078, 0x8bf4, 0x1078, 0x8a44, 0x0040, 0x8625, + 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x8616, + 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x8621, 0xd0bc, 0x0040, + 0x861d, 0x684b, 0x0002, 0x0078, 0x8621, 0x684b, 0x0005, 0x1078, + 0x8cc0, 0x6847, 0x0000, 0x1078, 0x4982, 0x2c68, 0x1078, 0x74d7, + 0x0040, 0x863e, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xa88e, + 0x210c, 0x6136, 0x2009, 0xa88f, 0x210c, 0x613a, 0x6918, 0x611a, + 0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5bf8, 0x2d60, 0x1078, + 0x753d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, + 0x0040, 0x8680, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, + 0x0040, 0x865a, 0xa186, 0x001e, 0x0040, 0x865a, 0xa186, 0x0039, + 0x00c0, 0x8680, 0x0d7e, 0x2c68, 0x1078, 0x8ef5, 0x00c0, 0x86a4, + 0x1078, 0x74d7, 0x0040, 0x867d, 0x6106, 0x6003, 0x0001, 0x601f, + 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, 0x6930, + 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, 0x6920, + 0x6122, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x2d60, 0x0078, 0x86a4, + 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x86a4, 0x6837, + 0x0103, 0x6850, 0xd0b4, 0x0040, 0x8693, 0xc0ec, 0x6852, 0x684b, + 0x0006, 0x0078, 0x869e, 0xd0bc, 0x0040, 0x869a, 0x684b, 0x0002, + 0x0078, 0x869e, 0x684b, 0x0005, 0x1078, 0x8cc0, 0x6847, 0x0000, + 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x007c, + 0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x86b8, + 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, 0x4982, + 0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x86ca, 0xa186, 0x0014, + 0x0040, 0x86ca, 0xa186, 0x0027, 0x0040, 0x86ca, 0x1078, 0x7583, + 0x0078, 0x86d0, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, + 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182, + 0x0101, 0x00c8, 0x86dd, 0x0078, 0x86df, 0x2009, 0x0100, 0x2130, + 0x2069, 0xa898, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, + 0x001d, 0x1078, 0x8739, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040, + 0x86f3, 0x1078, 0x13aa, 0x1078, 0x1381, 0x0040, 0x871d, 0x8528, + 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, + 0x00c8, 0x8709, 0x2608, 0xad90, 0x000f, 0x1078, 0x8739, 0x0078, + 0x871d, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f, + 0x1078, 0x8739, 0x0078, 0x86f3, 0x0f7f, 0x852f, 0xa5ad, 0x0003, + 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x8722, 0x0f7f, 0x852f, 0xa5ad, + 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff, + 0x0040, 0x8737, 0x6804, 0xa07d, 0x0040, 0x8735, 0x6807, 0x0000, + 0x1078, 0x4982, 0x2f68, 0x0078, 0x872a, 0x1078, 0x4982, 0x0f7f, + 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x873f, 0x8108, 0x810c, + 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x8741, + 0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031, 0x0001, + 0x601c, 0xa084, 0x000f, 0x1079, 0x8766, 0x127f, 0x067f, 0x007c, + 0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c, 0xa084, + 0x000f, 0x1079, 0x8766, 0x067f, 0x127f, 0x007c, 0x8780, 0x876e, + 0x877b, 0x879c, 0x876e, 0x877b, 0x879c, 0x877b, 0x1078, 0x1328, + 0x037e, 0x2019, 0x0010, 0x1078, 0x9a6a, 0x601f, 0x0006, 0x6003, + 0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, + 0x0d7e, 0x86ff, 0x00c0, 0x8797, 0x6010, 0x2068, 0x1078, 0x8a44, + 0x0040, 0x8799, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4a60, 0x1078, + 0x8cc0, 0x1078, 0x4982, 0x1078, 0x753d, 0xa085, 0x0001, 0x0d7f, + 0x007c, 0xa006, 0x0078, 0x8797, 0x6000, 0xa08a, 0x0010, 0x10c8, + 0x1328, 0x1079, 0x87a4, 0x007c, 0x87b4, 0x87d4, 0x87b6, 0x87f7, + 0x87d0, 0x87b4, 0x877b, 0x8780, 0x8780, 0x877b, 0x877b, 0x877b, + 0x877b, 0x877b, 0x877b, 0x877b, 0x1078, 0x1328, 0x86ff, 0x00c0, + 0x87cd, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x87c2, + 0x1078, 0x8cc0, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, + 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0xa085, 0x0001, 0x007c, + 0x1078, 0x1749, 0x0078, 0x87b6, 0x0e7e, 0x2071, 0xa5ab, 0x7024, + 0xac06, 0x00c0, 0x87dd, 0x1078, 0x6dda, 0x601c, 0xa084, 0x000f, + 0xa086, 0x0006, 0x00c0, 0x87ef, 0x087e, 0x097e, 0x2049, 0x0001, + 0x2c40, 0x1078, 0x7058, 0x097f, 0x087f, 0x0078, 0x87f1, 0x1078, + 0x6cd2, 0x0e7f, 0x00c0, 0x87b6, 0x1078, 0x877b, 0x007c, 0x037e, + 0x0e7e, 0x2071, 0xa5ab, 0x703c, 0xac06, 0x00c0, 0x8807, 0x2019, + 0x0000, 0x1078, 0x6e6c, 0x0e7f, 0x037f, 0x0078, 0x87b6, 0x1078, + 0x719a, 0x0e7f, 0x037f, 0x00c0, 0x87b6, 0x1078, 0x877b, 0x007c, + 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x8818, 0x0c7f, 0x007c, + 0x8827, 0x8895, 0x89cd, 0x8832, 0x8c01, 0x8827, 0x9a5b, 0x753d, + 0x8895, 0x1078, 0x8c3b, 0x00c0, 0x8827, 0x1078, 0x7a05, 0x007c, + 0x1078, 0x6010, 0x1078, 0x6109, 0x1078, 0x753d, 0x007c, 0x6017, + 0x0001, 0x007c, 0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, 0xa08a, + 0x0010, 0x10c8, 0x1328, 0x1079, 0x883e, 0x007c, 0x884e, 0x8850, + 0x8872, 0x8884, 0x8891, 0x884e, 0x8827, 0x8827, 0x8827, 0x8884, + 0x8884, 0x884e, 0x884e, 0x884e, 0x884e, 0x888e, 0x1078, 0x1328, + 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0xa5ab, + 0x7024, 0xac06, 0x0040, 0x886e, 0x1078, 0x6cd2, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa5a1, 0x2004, 0x6016, + 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x007c, 0x6017, 0x0001, + 0x0078, 0x886c, 0x0d7e, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, + 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, + 0x5bf8, 0x1078, 0x6109, 0x007c, 0x0d7e, 0x6017, 0x0001, 0x6010, + 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, 0x1078, 0x753d, + 0x007c, 0x1078, 0x1749, 0x0078, 0x8872, 0x6000, 0xa08a, 0x0010, + 0x10c8, 0x1328, 0x1079, 0x889d, 0x007c, 0x88ad, 0x882f, 0x88af, + 0x88ad, 0x88af, 0x88af, 0x8828, 0x88ad, 0x8821, 0x8821, 0x88ad, + 0x88ad, 0x88ad, 0x88ad, 0x88ad, 0x88ad, 0x1078, 0x1328, 0x0d7e, + 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c, + 0x10c8, 0x1328, 0x1079, 0x88bd, 0x007c, 0x88c9, 0x8971, 0x88cb, + 0x890b, 0x88cb, 0x890b, 0x88cb, 0x88d8, 0x88c9, 0x890b, 0x88c9, + 0x88f5, 0x1078, 0x1328, 0x6004, 0xa08e, 0x0016, 0x0040, 0x8906, + 0xa08e, 0x0004, 0x0040, 0x8906, 0xa08e, 0x0002, 0x0040, 0x8906, + 0x6004, 0x1078, 0x8c3b, 0x0040, 0x898c, 0xa08e, 0x0021, 0x0040, + 0x8990, 0xa08e, 0x0022, 0x0040, 0x898c, 0xa08e, 0x003d, 0x0040, + 0x8990, 0xa08e, 0x0039, 0x0040, 0x8994, 0xa08e, 0x0035, 0x0040, + 0x8994, 0xa08e, 0x001e, 0x0040, 0x8908, 0xa08e, 0x0001, 0x00c0, + 0x8904, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, + 0xa086, 0x0006, 0x0040, 0x8906, 0x1078, 0x2813, 0x1078, 0x7a05, + 0x1078, 0x8c01, 0x007c, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, + 0x0040, 0x8961, 0xa186, 0x0002, 0x00c0, 0x8934, 0x6018, 0x2068, + 0x68a0, 0xd0bc, 0x00c0, 0x89b8, 0x6840, 0xa084, 0x00ff, 0xa005, + 0x0040, 0x8934, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, + 0x6017, 0x0398, 0x1078, 0x74d7, 0x0040, 0x8934, 0x2d00, 0x601a, + 0x601f, 0x0001, 0x0078, 0x8961, 0x0d7f, 0x0c7f, 0x6004, 0xa08e, + 0x0002, 0x00c0, 0x8952, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, + 0x007e, 0x00c0, 0x8952, 0x2009, 0xa332, 0x2104, 0xc085, 0x200a, + 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, 0x0e7f, 0x1078, 0x7a05, + 0x0078, 0x8956, 0x1078, 0x7a05, 0x1078, 0x2813, 0x0e7e, 0x127e, + 0x2091, 0x8000, 0x1078, 0x2839, 0x127f, 0x0e7f, 0x1078, 0x8c01, + 0x007c, 0x2001, 0x0002, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007, + 0x0002, 0x1078, 0x5c45, 0x1078, 0x6109, 0x0d7f, 0x0c7f, 0x0078, + 0x8960, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040, 0x8961, + 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x8934, + 0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5c45, 0x1078, 0x6109, + 0x0d7f, 0x0c7f, 0x0078, 0x8960, 0x1078, 0x7a05, 0x0078, 0x8908, + 0x1078, 0x7a28, 0x0078, 0x8908, 0x0d7e, 0x2c68, 0x6104, 0x1078, + 0x8ef5, 0x0d7f, 0x0040, 0x89a0, 0x1078, 0x753d, 0x0078, 0x89b7, + 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, + 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, 0x600a, 0x2001, + 0xa5a1, 0x2004, 0x6016, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x007c, + 0x0d7f, 0x0c7f, 0x1078, 0x7a05, 0x1078, 0x2813, 0x0e7e, 0x127e, + 0x2091, 0x8000, 0x1078, 0x2839, 0x6013, 0x0000, 0x601f, 0x0007, + 0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000, 0xa08a, 0x0010, + 0x10c8, 0x1328, 0x1079, 0x89d5, 0x007c, 0x89e5, 0x89e5, 0x89e5, + 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x8827, 0x89e5, + 0x882f, 0x89e7, 0x882f, 0x89f5, 0x89e5, 0x1078, 0x1328, 0x6004, + 0xa086, 0x008b, 0x0040, 0x89f5, 0x6007, 0x008b, 0x6003, 0x000d, + 0x1078, 0x5bf8, 0x1078, 0x6109, 0x007c, 0x1078, 0x8bf4, 0x1078, + 0x8a44, 0x0040, 0x8a2d, 0x1078, 0x2813, 0x0d7e, 0x1078, 0x8a44, + 0x0040, 0x8a0f, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006, + 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, 0x4982, 0x2c68, + 0x1078, 0x74d7, 0x0040, 0x8a1d, 0x6818, 0x601a, 0x0c7e, 0x2d60, + 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x8a1e, 0x2d60, 0x0d7f, 0x6013, + 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, + 0x5c45, 0x1078, 0x6109, 0x0078, 0x8a2f, 0x1078, 0x8c01, 0x007c, + 0xa284, 0x000f, 0x00c0, 0x8a41, 0xa282, 0xaa00, 0x0048, 0x8a41, + 0x2001, 0xa315, 0x2004, 0xa202, 0x00c8, 0x8a41, 0xa085, 0x0001, + 0x007c, 0xa006, 0x0078, 0x8a40, 0x027e, 0x0e7e, 0x2071, 0xa300, + 0x6210, 0x7058, 0xa202, 0x0048, 0x8a56, 0x705c, 0xa202, 0x00c8, + 0x8a56, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, 0xa006, 0x0078, + 0x8a53, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, 0x2091, 0x8000, + 0x2061, 0xaa00, 0x2071, 0xa300, 0x7344, 0x7060, 0xa302, 0x00c8, + 0x8a83, 0x601c, 0xa206, 0x00c0, 0x8a7b, 0x1078, 0x8d66, 0x0040, + 0x8a7b, 0x1078, 0x8c3b, 0x00c0, 0x8a77, 0x1078, 0x7a05, 0x0c7e, + 0x1078, 0x753d, 0x0c7f, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, + 0x8a83, 0x0078, 0x8a64, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f, + 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa434, 0x210c, 0x81ff, + 0x0040, 0x8aa1, 0x2061, 0xaa00, 0x2071, 0xa300, 0x017e, 0x1078, + 0x74d7, 0x017f, 0x0040, 0x8aa4, 0x611a, 0x1078, 0x2813, 0x1078, + 0x753d, 0xa006, 0x0078, 0x8aa6, 0xa085, 0x0001, 0x017f, 0x0c7f, + 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, + 0x1078, 0x74d7, 0x057f, 0x0040, 0x8ac3, 0x6612, 0x651a, 0x601f, + 0x0003, 0x2009, 0x004b, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, + 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8abf, 0x0c7e, 0x057e, + 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x74d7, 0x057f, + 0x0040, 0x8af1, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, + 0x2560, 0x1078, 0x471b, 0x0c7f, 0x1078, 0x5d53, 0x077e, 0x2039, + 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x2009, + 0x004c, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, + 0x007c, 0xa006, 0x0078, 0x8aed, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, + 0x1078, 0x74d7, 0x2c78, 0x0c7f, 0x0040, 0x8b0e, 0x7e12, 0x2c00, + 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8b4e, 0x2f60, + 0x2009, 0x004d, 0x1078, 0x756c, 0xa085, 0x0001, 0x047f, 0x0c7f, + 0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x74d7, + 0x2c78, 0x0c7f, 0x0040, 0x8b2c, 0x7e12, 0x2c00, 0x781a, 0x781f, + 0x0003, 0x2021, 0x0005, 0x1078, 0x8b4e, 0x2f60, 0x2009, 0x004e, + 0x1078, 0x756c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, + 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x74d7, 0x2c78, 0x0c7f, + 0x0040, 0x8b4a, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, + 0x0004, 0x1078, 0x8b4e, 0x2f60, 0x2009, 0x0052, 0x1078, 0x756c, + 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, 0x097e, 0x077e, + 0x127e, 0x2091, 0x8000, 0x1078, 0x46a7, 0x0040, 0x8b5b, 0x2001, + 0x8b53, 0x0078, 0x8b61, 0x1078, 0x466d, 0x0040, 0x8b6a, 0x2001, + 0x8b5b, 0x007e, 0xa00e, 0x2400, 0x1078, 0x4a60, 0x1078, 0x4982, + 0x007f, 0x007a, 0x2418, 0x1078, 0x5fa7, 0x62a0, 0x087e, 0x2041, + 0x0001, 0x2039, 0x0001, 0x2608, 0x1078, 0x5d6d, 0x087f, 0x1078, + 0x5c78, 0x2f08, 0x2648, 0x1078, 0x9c38, 0x613c, 0x81ff, 0x1040, + 0x5e21, 0x127f, 0x077f, 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091, + 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8b9e, 0x660a, + 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, + 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, + 0x8b9b, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7, + 0x017f, 0x0040, 0x8bba, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, + 0x6012, 0x2009, 0x0021, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, + 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8bb7, 0x0c7e, 0x127e, 0x2091, + 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8bd6, 0x660a, + 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078, + 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, + 0x8bd3, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7, + 0x017f, 0x0040, 0x8bf1, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x0000, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, + 0x007c, 0xa006, 0x0078, 0x8bee, 0x027e, 0x0d7e, 0x6218, 0x2268, + 0x6a3c, 0x82ff, 0x0040, 0x8bfe, 0x8211, 0x6a3e, 0x0d7f, 0x027f, + 0x007c, 0x007e, 0x6000, 0xa086, 0x0000, 0x0040, 0x8c13, 0x6013, + 0x0000, 0x601f, 0x0007, 0x2001, 0xa5a1, 0x2004, 0x6016, 0x1078, + 0xa134, 0x603f, 0x0000, 0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e, + 0x2031, 0xa352, 0x2634, 0xd6e4, 0x0040, 0x8c23, 0x6618, 0x2660, + 0x6e48, 0x1078, 0x461b, 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e, + 0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, 0x8c38, 0xa08e, 0x0003, + 0x0040, 0x8c38, 0xa08e, 0x0004, 0x0040, 0x8c38, 0xa085, 0x0001, + 0x017f, 0x007f, 0x007c, 0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040, + 0x8c48, 0x6838, 0xd0fc, 0x0040, 0x8c48, 0xa006, 0x0078, 0x8c4a, + 0xa085, 0x0001, 0x0d7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, + 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8c67, 0x611a, + 0x601f, 0x0001, 0x2d00, 0x6012, 0x1078, 0x2813, 0x2009, 0x0028, + 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, + 0x0078, 0x8c64, 0xa186, 0x0015, 0x00c0, 0x8c7f, 0x2011, 0xa31f, + 0x2204, 0xa086, 0x0074, 0x00c0, 0x8c7f, 0x1078, 0x7d0d, 0x6003, + 0x0001, 0x6007, 0x0029, 0x1078, 0x5c45, 0x0078, 0x8c83, 0x1078, + 0x7a05, 0x1078, 0x753d, 0x007c, 0xa186, 0x0016, 0x00c0, 0x8c8e, + 0x2001, 0x0004, 0x1078, 0x443f, 0x0078, 0x8caf, 0xa186, 0x0015, + 0x00c0, 0x8cb3, 0x2011, 0xa31f, 0x2204, 0xa086, 0x0014, 0x00c0, + 0x8cb3, 0x0d7e, 0x6018, 0x2068, 0x1078, 0x457d, 0x0d7f, 0x1078, + 0x7dba, 0x00c0, 0x8cb3, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, + 0xa005, 0x0040, 0x8cb3, 0x2001, 0x0006, 0x1078, 0x443f, 0x1078, + 0x7608, 0x0078, 0x8cb7, 0x1078, 0x7a05, 0x1078, 0x753d, 0x007c, + 0x6848, 0xa086, 0x0005, 0x00c0, 0x8cbf, 0x1078, 0x8cc0, 0x007c, + 0x6850, 0xc0ad, 0x6852, 0x007c, 0x0e7e, 0x2071, 0xa88c, 0x7014, + 0xd0e4, 0x0040, 0x8cd5, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, + 0x0050, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x007c, 0x0c7e, + 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8ce4, 0x601c, + 0xa084, 0x000f, 0x1079, 0x8ce6, 0x0c7f, 0x007c, 0x8827, 0x8cf1, + 0x8cf4, 0x8cf7, 0x9f00, 0x9f1c, 0x9f1f, 0x8827, 0x8827, 0x1078, + 0x1328, 0x0005, 0x0005, 0x007c, 0x0005, 0x0005, 0x007c, 0x1078, + 0x8cfa, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0040, 0x8d29, + 0x1078, 0x74d7, 0x00c0, 0x8d0a, 0x2001, 0xa5a2, 0x2004, 0x783e, + 0x0078, 0x8d29, 0x7818, 0x601a, 0x781c, 0xa086, 0x0003, 0x0040, + 0x8d17, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0078, 0x8d1b, 0x7808, + 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, + 0x6003, 0x0001, 0x7920, 0x6122, 0x1078, 0x5bf8, 0x1078, 0x6109, + 0x2f60, 0x0f7f, 0x007c, 0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e, + 0x0001, 0x0040, 0x8d3c, 0xa086, 0x0005, 0x0040, 0x8d40, 0xa006, + 0x602a, 0x602e, 0x0078, 0x8d51, 0x6824, 0xc0f4, 0xc0d5, 0x6826, + 0x6810, 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, + 0x00c8, 0x8d37, 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, + 0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6920, + 0x6122, 0x601f, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x1078, + 0x5bf8, 0x6803, 0x0002, 0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e, + 0x6004, 0xa08e, 0x0034, 0x0040, 0x8d8b, 0xa08e, 0x0035, 0x0040, + 0x8d8b, 0xa08e, 0x0036, 0x0040, 0x8d8b, 0xa08e, 0x0037, 0x0040, + 0x8d8b, 0xa08e, 0x0038, 0x0040, 0x8d8b, 0xa08e, 0x0039, 0x0040, + 0x8d8b, 0xa08e, 0x003a, 0x0040, 0x8d8b, 0xa08e, 0x003b, 0x0040, + 0x8d8b, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78, + 0x1078, 0x4893, 0x00c0, 0x8d98, 0xa085, 0x0001, 0x0078, 0x8da7, + 0x6024, 0xd0f4, 0x00c0, 0x8da6, 0xc0f5, 0x6026, 0x6010, 0x2078, + 0x7828, 0x603a, 0x782c, 0x6036, 0x1078, 0x1749, 0xa006, 0x0f7f, + 0x007c, 0x007e, 0x017e, 0x027e, 0x037e, 0x0e7e, 0x2001, 0xa59c, + 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x1078, 0x5a98, 0x2001, + 0xa5a0, 0x82ff, 0x00c0, 0x8dbe, 0x2011, 0x0002, 0x2202, 0x2001, + 0xa59e, 0x200c, 0x8000, 0x2014, 0x2071, 0xa58c, 0x711a, 0x721e, + 0x2001, 0x0064, 0x1078, 0x5a98, 0x2001, 0xa5a1, 0x82ff, 0x00c0, + 0x8dd3, 0x2011, 0x0002, 0x2202, 0x2009, 0xa5a2, 0xa280, 0x000a, + 0x200a, 0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e, + 0x0e7e, 0x2001, 0xa5a0, 0x2003, 0x0028, 0x2001, 0xa5a1, 0x2003, + 0x0014, 0x2071, 0xa58c, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, + 0xa5a2, 0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8e0e, + 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078, + 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, + 0x8e0b, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa300, 0xa186, 0x0015, + 0x00c0, 0x8e40, 0x707c, 0xa086, 0x0018, 0x00c0, 0x8e40, 0x6010, + 0x2068, 0x6a3c, 0xd2e4, 0x00c0, 0x8e34, 0x2c78, 0x1078, 0x62c6, + 0x0040, 0x8e48, 0x7068, 0x6a50, 0xa206, 0x00c0, 0x8e3c, 0x706c, + 0x6a54, 0xa206, 0x00c0, 0x8e3c, 0x6218, 0xa290, 0x0028, 0x2214, + 0x2009, 0x0000, 0x1078, 0x285b, 0x1078, 0x7608, 0x0078, 0x8e44, + 0x1078, 0x7a05, 0x1078, 0x753d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, + 0x704c, 0xa080, 0x293f, 0x2004, 0x6a54, 0xa206, 0x0040, 0x8e34, + 0x0078, 0x8e3c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, + 0x74d7, 0x017f, 0x0040, 0x8e6a, 0x611a, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x0043, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, + 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e67, 0x0d7e, 0x0e7e, 0x0f7e, + 0x2071, 0xa300, 0xa186, 0x0015, 0x00c0, 0x8e93, 0x707c, 0xa086, + 0x0004, 0x00c0, 0x8e93, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078, + 0x62c6, 0x0040, 0x8e9b, 0x7068, 0x6a08, 0xa206, 0x00c0, 0x8e8f, + 0x706c, 0x6a0c, 0xa206, 0x00c0, 0x8e8f, 0x1078, 0x2813, 0x1078, + 0x7608, 0x0078, 0x8e97, 0x1078, 0x7a05, 0x1078, 0x753d, 0x0f7f, + 0x0e7f, 0x0d7f, 0x007c, 0x704c, 0xa080, 0x293f, 0x2004, 0x6a0c, + 0xa206, 0x0040, 0x8e8d, 0x0078, 0x8e8f, 0x017e, 0x027e, 0x684c, + 0xd0ac, 0x0040, 0x8ebd, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, + 0x8ebd, 0x6860, 0xa106, 0x00c0, 0x8eb9, 0x685c, 0xa206, 0x0040, + 0x8ebd, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c, + 0x0e7e, 0x127e, 0x2071, 0xa300, 0x2091, 0x8000, 0x7544, 0xa582, + 0x0001, 0x0048, 0x8ef2, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, + 0x0040, 0x8ede, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, 0x8eda, + 0x0078, 0x8ecd, 0x2061, 0xaa00, 0x0078, 0x8ecd, 0x6003, 0x0008, + 0x8529, 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, 0x8eee, + 0x754a, 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0xaa00, + 0x0078, 0x8ee9, 0xa006, 0x0078, 0x8eeb, 0x0c7e, 0x027e, 0x017e, + 0xa186, 0x0035, 0x0040, 0x8eff, 0x6a34, 0x0078, 0x8f00, 0x6a28, + 0x1078, 0x8a30, 0x0040, 0x8f29, 0x2260, 0x611c, 0xa186, 0x0003, + 0x0040, 0x8f0e, 0xa186, 0x0006, 0x00c0, 0x8f25, 0x6834, 0xa206, + 0x0040, 0x8f1d, 0x6838, 0xa206, 0x00c0, 0x8f25, 0x6108, 0x6834, + 0xa106, 0x00c0, 0x8f25, 0x0078, 0x8f22, 0x6008, 0x6938, 0xa106, + 0x00c0, 0x8f25, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f, + 0x007c, 0xa085, 0x0001, 0x0078, 0x8f25, 0x067e, 0x6000, 0xa0b2, + 0x0010, 0x10c8, 0x1328, 0x1079, 0x8f37, 0x067f, 0x007c, 0x8f47, + 0x93bb, 0x94d3, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f81, + 0x955e, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x1078, + 0x1328, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1328, 0x1079, + 0x8f53, 0x067f, 0x007c, 0x8f63, 0x99f6, 0x8f63, 0x8f63, 0x8f63, + 0x8f63, 0x8f63, 0x8f63, 0x99b4, 0x9a44, 0x8f63, 0xa053, 0xa087, + 0xa053, 0xa087, 0x8f63, 0x1078, 0x1328, 0x067e, 0x6000, 0xa0b2, + 0x0010, 0x10c8, 0x1328, 0x1079, 0x8f6f, 0x067f, 0x007c, 0x8f7f, + 0x969f, 0x976a, 0x9798, 0x9813, 0x8f7f, 0x9919, 0x98c1, 0x956a, + 0x9988, 0x999e, 0x8f7f, 0x8f7f, 0x8f7f, 0x8f7f, 0x8f7f, 0x1078, + 0x1328, 0xa1b2, 0x0044, 0x10c8, 0x1328, 0x2100, 0x0079, 0x8f88, + 0x8fc8, 0x919a, 0x8fc8, 0x8fc8, 0x8fc8, 0x91a2, 0x8fc8, 0x8fc8, + 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, + 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fca, + 0x902d, 0x9038, 0x9081, 0x909c, 0x911b, 0x918b, 0x8fc8, 0x8fc8, + 0x91a6, 0x8fc8, 0x8fc8, 0x91b5, 0x91bc, 0x8fc8, 0x8fc8, 0x8fc8, + 0x8fc8, 0x8fc8, 0x91ea, 0x8fc8, 0x8fc8, 0x91f5, 0x8fc8, 0x8fc8, + 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x920a, 0x8fc8, 0x8fc8, 0x8fc8, + 0x9291, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x9305, + 0x1078, 0x1328, 0x1078, 0x4897, 0x00c0, 0x8fd7, 0x2001, 0xa332, + 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, 0x8fdf, 0x6007, + 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, 0x9195, 0x1078, + 0x4887, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270, + 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, + 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x017f, + 0x2e60, 0x1078, 0x471b, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, + 0x6618, 0x0c7e, 0x2660, 0x1078, 0x4513, 0x0c7f, 0xa6b0, 0x0001, + 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x901f, 0x1078, + 0x9b6c, 0x00c0, 0x907b, 0x1078, 0x9afd, 0x00c0, 0x901b, 0x6007, + 0x0008, 0x0078, 0x9195, 0x6007, 0x0009, 0x0078, 0x9195, 0x1078, + 0x9d45, 0x0040, 0x9029, 0x1078, 0x9b6c, 0x0040, 0x9013, 0x0078, + 0x907b, 0x6013, 0x1900, 0x0078, 0x901b, 0x6106, 0x1078, 0x9aa8, + 0x6007, 0x0006, 0x0078, 0x9195, 0x6007, 0x0007, 0x0078, 0x9195, + 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x0d7e, 0x6618, 0x2668, 0x6e04, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x905d, 0xa686, + 0x0004, 0x0040, 0x905d, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, + 0x0040, 0x905d, 0xa686, 0x0004, 0x0040, 0x905d, 0xa686, 0x0005, + 0x0040, 0x905d, 0x0d7f, 0x0078, 0x907b, 0x1078, 0x9bd2, 0x00c0, + 0x9076, 0xa686, 0x0006, 0x00c0, 0x906f, 0x027e, 0x6218, 0xa290, + 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x285b, 0x027f, 0x1078, + 0x457d, 0x6007, 0x000a, 0x0d7f, 0x0078, 0x9195, 0x6007, 0x000b, + 0x0d7f, 0x0078, 0x9195, 0x1078, 0x2813, 0x6007, 0x0001, 0x0078, + 0x9195, 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x6618, 0x0d7e, 0x2668, + 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x907b, 0x027e, 0x6218, + 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x285b, 0x027f, + 0x6007, 0x000c, 0x0078, 0x9195, 0x1078, 0x4897, 0x00c0, 0x90a9, + 0x2001, 0xa332, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, + 0x90b1, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, + 0x9195, 0x1078, 0x4887, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, + 0x00ff, 0xa082, 0x0006, 0x0048, 0x90f5, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0004, 0x0040, 0x90c8, 0xa686, 0x0006, 0x00c0, 0x907b, + 0x1078, 0x9be1, 0x00c0, 0x90d0, 0x6007, 0x000e, 0x0078, 0x9195, + 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, + 0x047e, 0x1078, 0x2813, 0x047f, 0x017e, 0xa006, 0x2009, 0xa352, + 0x210c, 0xd1a4, 0x0040, 0x90ef, 0x2009, 0x0029, 0x1078, 0x9ec0, + 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f, + 0x047f, 0x6007, 0x0001, 0x0078, 0x9195, 0x2001, 0x0001, 0x1078, + 0x442b, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, + 0xa305, 0x2011, 0xa890, 0x1078, 0x7e55, 0x037f, 0x027f, 0x017f, + 0x157f, 0xa005, 0x0040, 0x9115, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0040, 0x90c8, 0x0078, 0x907b, 0x6013, 0x1900, 0x6007, + 0x0009, 0x0078, 0x9195, 0x1078, 0x4897, 0x00c0, 0x9128, 0x2001, + 0xa332, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, 0x9130, + 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, 0x9195, + 0x1078, 0x4887, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, + 0xa082, 0x0006, 0x0048, 0x9178, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0004, 0x0040, 0x9147, 0xa686, 0x0006, 0x00c0, 0x907b, 0x1078, + 0x9c0c, 0x00c0, 0x9153, 0x1078, 0x9afd, 0x00c0, 0x9153, 0x6007, + 0x0010, 0x0078, 0x9195, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, + 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2813, 0x047f, 0x017e, + 0xa006, 0x2009, 0xa352, 0x210c, 0xd1a4, 0x0040, 0x9172, 0x2009, + 0x0029, 0x1078, 0x9ec0, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, + 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x9195, + 0x1078, 0x9d45, 0x0040, 0x9185, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0040, 0x9147, 0x0078, 0x907b, 0x6013, 0x1900, 0x6007, + 0x0009, 0x0078, 0x9195, 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x1078, + 0x9343, 0x00c0, 0x907b, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, + 0x5c45, 0x007c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5c45, + 0x0078, 0x9199, 0x6007, 0x0005, 0x0078, 0x919c, 0x1078, 0xa0bf, + 0x00c0, 0x9340, 0x1078, 0x9343, 0x00c0, 0x907b, 0x6007, 0x0020, + 0x6003, 0x0001, 0x1078, 0x5c45, 0x007c, 0x6007, 0x0023, 0x6003, + 0x0001, 0x1078, 0x5c45, 0x007c, 0x1078, 0xa0bf, 0x00c0, 0x9340, + 0x1078, 0x9343, 0x00c0, 0x907b, 0x017e, 0x027e, 0x2011, 0xa890, + 0x2214, 0x2c08, 0x1078, 0x9e8c, 0x00c0, 0x91de, 0x2160, 0x6007, + 0x0026, 0x6013, 0x1700, 0x2011, 0xa889, 0x2214, 0xa296, 0xffff, + 0x00c0, 0x91e3, 0x6007, 0x0025, 0x0078, 0x91e3, 0x1078, 0x753d, + 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5c45, 0x027f, + 0x017f, 0x007c, 0x6106, 0x1078, 0x9363, 0x6007, 0x002b, 0x0078, + 0x9195, 0x6007, 0x002c, 0x0078, 0x9195, 0x1078, 0xa0bf, 0x00c0, + 0x9340, 0x1078, 0x9343, 0x00c0, 0x907b, 0x6106, 0x1078, 0x9368, + 0x00c0, 0x9206, 0x6007, 0x002e, 0x0078, 0x9195, 0x6007, 0x002f, + 0x0078, 0x9195, 0x0e7e, 0x0d7e, 0x0c7e, 0x6018, 0xa080, 0x0001, + 0x200c, 0xa184, 0x00ff, 0xa086, 0x0006, 0x0040, 0x9223, 0xa184, + 0xff00, 0x8007, 0xa086, 0x0006, 0x0040, 0x9223, 0x0c7f, 0x0d7f, + 0x0e7f, 0x0078, 0x919a, 0x2001, 0xa371, 0x2004, 0xd0e4, 0x0040, + 0x928d, 0x2071, 0xa88c, 0x7010, 0x6036, 0x7014, 0x603a, 0x7108, + 0x720c, 0x2001, 0xa352, 0x2004, 0xd0a4, 0x0040, 0x9241, 0x6018, + 0x2068, 0x6810, 0xa106, 0x00c0, 0x9241, 0x6814, 0xa206, 0x0040, + 0x9265, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x9281, 0x2069, + 0xa300, 0x686c, 0xa206, 0x00c0, 0x9281, 0x6868, 0xa106, 0x00c0, + 0x9281, 0x7210, 0x1078, 0x8a30, 0x0040, 0x9287, 0x1078, 0x9f31, + 0x0040, 0x9287, 0x622a, 0x6007, 0x0036, 0x6003, 0x0001, 0x1078, + 0x5bf8, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7214, 0xa286, 0xffff, + 0x0040, 0x9277, 0x1078, 0x8a30, 0x0040, 0x9287, 0xa280, 0x0002, + 0x2004, 0x7110, 0xa106, 0x00c0, 0x9287, 0x0078, 0x9252, 0x7210, + 0x2c08, 0x1078, 0x9e8c, 0x2c10, 0x2160, 0x0040, 0x9287, 0x0078, + 0x9252, 0x6007, 0x0037, 0x6013, 0x1500, 0x0078, 0x925d, 0x6007, + 0x0037, 0x6013, 0x1700, 0x0078, 0x925d, 0x6007, 0x0012, 0x0078, + 0x925d, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007, + 0xa086, 0x0006, 0x00c0, 0x919a, 0x0e7e, 0x0d7e, 0x0c7e, 0x2001, + 0xa371, 0x2004, 0xd0e4, 0x0040, 0x92fd, 0x2069, 0xa300, 0x2071, + 0xa88c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x00c0, + 0x92ba, 0x7208, 0x0c7e, 0x2c08, 0x1078, 0x9e8c, 0x2c10, 0x0c7f, + 0x0040, 0x92f1, 0x1078, 0x8a30, 0x0040, 0x92f1, 0x0c7e, 0x027e, + 0x2260, 0x1078, 0x874a, 0x027f, 0x0c7f, 0x7118, 0xa18c, 0xff00, + 0x810f, 0xa186, 0x0001, 0x0040, 0x92db, 0xa186, 0x0005, 0x0040, + 0x92d5, 0xa186, 0x0007, 0x00c0, 0x92e5, 0xa280, 0x0004, 0x2004, + 0xa005, 0x0040, 0x92e5, 0x057e, 0x7510, 0x7614, 0x1078, 0x9f46, + 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x6007, 0x003b, 0x602b, + 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x0078, + 0x92e1, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, 0x6003, + 0x0001, 0x1078, 0x5bf8, 0x0078, 0x92e1, 0x6007, 0x003b, 0x602b, + 0x000b, 0x6013, 0x0000, 0x0078, 0x925d, 0x0e7e, 0x027e, 0x1078, + 0x4897, 0x0040, 0x933a, 0x1078, 0x4887, 0x1078, 0xa148, 0x00c0, + 0x9338, 0x2071, 0xa300, 0x70c8, 0xc085, 0x70ca, 0x0f7e, 0x2079, + 0x0100, 0x7294, 0xa284, 0x00ff, 0x706a, 0x78e6, 0xa284, 0xff00, + 0x726c, 0xa205, 0x706e, 0x78ea, 0x0f7f, 0x70d3, 0x0000, 0x2001, + 0xa352, 0x2004, 0xd0a4, 0x0040, 0x9331, 0x2011, 0xa5c4, 0x2013, + 0x07d0, 0xd0ac, 0x00c0, 0x933a, 0x1078, 0x260d, 0x0078, 0x933a, + 0x1078, 0xa178, 0x027f, 0x0e7f, 0x1078, 0x753d, 0x0078, 0x9199, + 0x1078, 0x753d, 0x007c, 0x0d7e, 0x067e, 0x6618, 0x2668, 0x6e04, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x9360, 0xa686, + 0x0004, 0x0040, 0x9360, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, + 0x0040, 0x9360, 0xa686, 0x0004, 0x0040, 0x9360, 0xa085, 0x0001, + 0x067f, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x9397, 0x0d7f, 0x007c, + 0x0d7e, 0x1078, 0x93a6, 0x00c0, 0x9390, 0x680c, 0xa08c, 0xff00, + 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, + 0x0040, 0x937e, 0x2009, 0x0001, 0x0078, 0x938c, 0xd1ec, 0x0040, + 0x9390, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x1078, 0x24e3, 0x00c0, + 0x9390, 0x2110, 0x2009, 0x0000, 0x1078, 0x285b, 0x0078, 0x9394, + 0xa085, 0x0001, 0x0078, 0x9395, 0xa006, 0x0d7f, 0x007c, 0x2069, + 0xa88d, 0x6800, 0xa082, 0x0010, 0x00c8, 0x93a4, 0x6013, 0x0000, + 0xa085, 0x0001, 0x0078, 0x93a5, 0xa006, 0x007c, 0x6013, 0x0000, + 0x2069, 0xa88c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x00c0, + 0x93ba, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0040, 0x93ba, + 0xa08e, 0x0010, 0x007c, 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1328, + 0xa1b6, 0x0013, 0x00c0, 0x93c7, 0x2008, 0x0079, 0x93da, 0xa1b6, + 0x0027, 0x0040, 0x93cf, 0xa1b6, 0x0014, 0x10c0, 0x1328, 0x2001, + 0x0007, 0x1078, 0x4472, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, + 0x6109, 0x007c, 0x941a, 0x941c, 0x941a, 0x941a, 0x941a, 0x941c, + 0x9424, 0x94ae, 0x9471, 0x94ae, 0x9485, 0x94ae, 0x9424, 0x94ae, + 0x94a6, 0x94ae, 0x94a6, 0x94ae, 0x94ae, 0x941a, 0x941a, 0x941a, + 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, + 0x941c, 0x941a, 0x94ae, 0x941a, 0x941a, 0x94ae, 0x941a, 0x94ae, + 0x94ae, 0x941a, 0x941a, 0x941a, 0x941a, 0x94ae, 0x94ae, 0x941a, + 0x94ae, 0x94ae, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941c, + 0x94ae, 0x94ae, 0x941a, 0x941a, 0x94ae, 0x94ae, 0x941a, 0x941a, + 0x941a, 0x941a, 0x1078, 0x1328, 0x1078, 0x6010, 0x6003, 0x0002, + 0x1078, 0x6109, 0x0078, 0x94b4, 0x0f7e, 0x2079, 0xa351, 0x7804, + 0x0f7f, 0xd0ac, 0x00c0, 0x94ae, 0x2001, 0x0000, 0x1078, 0x442b, + 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x94ae, + 0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9448, 0x6010, + 0xa005, 0x0040, 0x9448, 0x0c7f, 0x1078, 0x35f7, 0x0078, 0x94ae, + 0x0c7f, 0x2001, 0xa300, 0x2004, 0xa086, 0x0002, 0x00c0, 0x9457, + 0x0f7e, 0x2079, 0xa300, 0x788c, 0x8000, 0x788e, 0x0f7f, 0x2001, + 0x0002, 0x1078, 0x443f, 0x1078, 0x6010, 0x601f, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, 0x1078, 0x6109, 0x0c7e, + 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x58e1, 0x0c7f, 0x0078, + 0x94b4, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x94ae, 0xa686, 0x0004, 0x0040, + 0x94ae, 0x2001, 0x0004, 0x0078, 0x94ac, 0x2001, 0xa300, 0x2004, + 0xa086, 0x0003, 0x00c0, 0x948e, 0x1078, 0x35f7, 0x2001, 0x0006, + 0x1078, 0x94b5, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x94ae, 0x2001, 0x0006, + 0x0078, 0x94ac, 0x2001, 0x0004, 0x0078, 0x94ac, 0x2001, 0x0006, + 0x1078, 0x94b5, 0x0078, 0x94ae, 0x1078, 0x4472, 0x1078, 0x6010, + 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0x017e, 0x0d7e, 0x6118, + 0x2168, 0x6900, 0xd184, 0x0040, 0x94d0, 0x6104, 0xa18e, 0x000a, + 0x00c0, 0x94c8, 0x699c, 0xd1a4, 0x00c0, 0x94c8, 0x2001, 0x0007, + 0x1078, 0x443f, 0x2001, 0x0000, 0x1078, 0x442b, 0x1078, 0x2839, + 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, + 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1328, 0xa1b6, + 0x0015, 0x00c0, 0x94e7, 0x1079, 0x94ee, 0x0078, 0x94ed, 0xa1b6, + 0x0016, 0x10c0, 0x1328, 0x1079, 0x94fa, 0x007c, 0x7ad0, 0x7ad0, + 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x9547, 0x9506, 0x7ad0, 0x7ad0, + 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, + 0x9547, 0x954f, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x0f7e, 0x2079, + 0xa351, 0x7804, 0xd0ac, 0x00c0, 0x952d, 0x6018, 0xa07d, 0x0040, + 0x952d, 0x7800, 0xd0f4, 0x00c0, 0x9519, 0x7810, 0xa005, 0x00c0, + 0x952d, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, + 0x443f, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, + 0x5c45, 0x1078, 0x6109, 0x0078, 0x9545, 0x2011, 0xa883, 0x2204, + 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x9545, 0x0c7e, 0x1078, + 0x4501, 0x0040, 0x9540, 0x0c7f, 0x1078, 0x753d, 0x0078, 0x9545, + 0x1078, 0x4235, 0x0c7f, 0x1078, 0x753d, 0x0f7f, 0x007c, 0x6604, + 0xa6b6, 0x001e, 0x00c0, 0x954e, 0x1078, 0x753d, 0x007c, 0x1078, + 0x7d0a, 0x00c0, 0x955b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, + 0x5c45, 0x0078, 0x955d, 0x1078, 0x753d, 0x007c, 0x6004, 0xa08a, + 0x0044, 0x10c8, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, + 0x6109, 0x007c, 0xa182, 0x0040, 0x0079, 0x956e, 0x9581, 0x9581, + 0x9581, 0x9581, 0x9583, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, + 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, + 0x9581, 0x1078, 0x1328, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, + 0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x9594, + 0x2021, 0x0000, 0x1078, 0xa111, 0x6106, 0x2071, 0xa880, 0x7444, + 0xa4a4, 0xff00, 0x0040, 0x95eb, 0xa486, 0x2000, 0x00c0, 0x95a6, + 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5a6d, 0x1078, 0x1381, + 0x1040, 0x1328, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, + 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, + 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084, + 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4982, + 0x017f, 0xa486, 0x2000, 0x00c0, 0x95d3, 0x2019, 0x0017, 0x1078, + 0x9e3b, 0x0078, 0x9645, 0xa486, 0x0400, 0x00c0, 0x95dd, 0x2019, + 0x0002, 0x1078, 0x9dec, 0x0078, 0x9645, 0xa486, 0x0200, 0x00c0, + 0x95e3, 0x1078, 0x9dd1, 0xa486, 0x1000, 0x00c0, 0x95e9, 0x1078, + 0x9e20, 0x0078, 0x9645, 0x2069, 0xa62d, 0x6a00, 0xd284, 0x0040, + 0x969b, 0xa284, 0x0300, 0x00c0, 0x9693, 0x6804, 0xa005, 0x0040, + 0x9683, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1366, 0x0040, 0x964c, + 0x7800, 0xd08c, 0x00c0, 0x9607, 0x7804, 0x8001, 0x7806, 0x6013, + 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, + 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, + 0x6986, 0x6846, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, + 0x0002, 0x00c0, 0x9627, 0x684f, 0x0040, 0x0078, 0x9631, 0xa286, + 0x0001, 0x00c0, 0x962f, 0x684f, 0x0080, 0x0078, 0x9631, 0x684f, + 0x0000, 0x20a9, 0x000a, 0x2001, 0xa890, 0xad90, 0x0015, 0x200c, + 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x9637, 0x200c, 0x6982, + 0x8000, 0x200c, 0x697e, 0x1078, 0x4982, 0x027f, 0x047f, 0x157f, + 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003, 0x0001, + 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9645, + 0x2069, 0xa892, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x00c0, + 0x9677, 0x2069, 0xa880, 0x686c, 0xa084, 0x00ff, 0x017e, 0x6110, + 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001, 0x6007, + 0x0043, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9645, 0x6013, + 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078, + 0x6109, 0x0078, 0x9645, 0x6013, 0x0300, 0x0078, 0x9689, 0x6013, + 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078, + 0x6109, 0x0078, 0x9645, 0x6013, 0x0500, 0x0078, 0x9689, 0x6013, + 0x0600, 0x0078, 0x9658, 0x6013, 0x0200, 0x0078, 0x9658, 0xa186, + 0x0013, 0x00c0, 0x96b1, 0x6004, 0xa08a, 0x0040, 0x1048, 0x1328, + 0xa08a, 0x0053, 0x10c8, 0x1328, 0xa082, 0x0040, 0x2008, 0x0079, + 0x9725, 0xa186, 0x0051, 0x0040, 0x96be, 0xa186, 0x0047, 0x00c0, + 0x96d7, 0x6004, 0xa086, 0x0041, 0x0040, 0x96e5, 0x2001, 0x0109, + 0x2004, 0xd084, 0x0040, 0x96e5, 0x127e, 0x2091, 0x2200, 0x007e, + 0x017e, 0x027e, 0x1078, 0x5ad2, 0x027f, 0x017f, 0x007f, 0x127f, + 0x6000, 0xa086, 0x0002, 0x00c0, 0x96e5, 0x0078, 0x976a, 0xa186, + 0x0027, 0x0040, 0x96df, 0xa186, 0x0014, 0x10c0, 0x1328, 0x6004, + 0xa082, 0x0040, 0x2008, 0x0079, 0x96e8, 0x1078, 0x7583, 0x007c, + 0x96fb, 0x96fd, 0x96fd, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, + 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, + 0x96fb, 0x96fb, 0x96fb, 0x1078, 0x1328, 0x1078, 0x6010, 0x1078, + 0x6109, 0x037e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x9722, 0xad84, + 0xf000, 0x0040, 0x9722, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, + 0x00c0, 0x9722, 0x2019, 0x0004, 0x1078, 0x9e70, 0x6013, 0x0000, + 0x6014, 0xa005, 0x00c0, 0x9720, 0x2001, 0xa5a1, 0x2004, 0x6016, + 0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c, 0x9738, 0x9757, 0x9741, + 0x9764, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, + 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, + 0x1078, 0x1328, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, + 0x200a, 0x1078, 0x6010, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, + 0x0040, 0x9752, 0x6003, 0x0007, 0x2009, 0x0043, 0x1078, 0x756c, + 0x0078, 0x9754, 0x6003, 0x0002, 0x1078, 0x6109, 0x007c, 0x1078, + 0x6010, 0x1078, 0xa0c6, 0x00c0, 0x9761, 0x1078, 0x5a41, 0x1078, + 0x753d, 0x1078, 0x6109, 0x007c, 0x1078, 0x6010, 0x2009, 0x0041, + 0x0078, 0x98c1, 0xa182, 0x0040, 0x0079, 0x976e, 0x9781, 0x9783, + 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9784, 0x9781, 0x9781, + 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x978f, + 0x9781, 0x1078, 0x1328, 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0x0d7e, + 0x1078, 0x5a41, 0x0d7f, 0x1078, 0xa134, 0x1078, 0x753d, 0x007c, + 0xa182, 0x0040, 0x0079, 0x979c, 0x97af, 0x97af, 0x97af, 0x97af, + 0x97af, 0x97af, 0x97af, 0x97b1, 0x97af, 0x97b4, 0x97df, 0x97af, + 0x97af, 0x97af, 0x97af, 0x97df, 0x97af, 0x97af, 0x97af, 0x1078, + 0x1328, 0x1078, 0x7583, 0x007c, 0x1078, 0x60b8, 0x1078, 0x61d3, + 0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x97ca, 0xa08c, + 0x0003, 0xa18e, 0x0002, 0x0040, 0x97d2, 0x2009, 0x0041, 0x0d7f, + 0x0078, 0x98c1, 0x6003, 0x0007, 0x6017, 0x0000, 0x1078, 0x5a41, + 0x0d7f, 0x007c, 0x1078, 0xa0c6, 0x0040, 0x97d8, 0x0d7f, 0x007c, + 0x1078, 0x5a41, 0x1078, 0x753d, 0x0d7f, 0x0078, 0x97d1, 0x037e, + 0x1078, 0x60b8, 0x1078, 0x61d3, 0x6010, 0x0d7e, 0x2068, 0x6018, + 0x2004, 0xd0bc, 0x0040, 0x97ff, 0x684c, 0xa084, 0x0003, 0xa086, + 0x0002, 0x0040, 0x97fb, 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, + 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0078, 0x9810, 0x2019, + 0x0004, 0x1078, 0x9e70, 0x6014, 0xa005, 0x00c0, 0x980c, 0x2001, + 0xa5a1, 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, + 0x0d7f, 0x037f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9821, 0x6004, + 0xa086, 0x0042, 0x10c0, 0x1328, 0x1078, 0x6010, 0x1078, 0x6109, + 0x007c, 0xa186, 0x0027, 0x0040, 0x9829, 0xa186, 0x0014, 0x00c0, + 0x9839, 0x6004, 0xa086, 0x0042, 0x10c0, 0x1328, 0x2001, 0x0007, + 0x1078, 0x4472, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, + 0x007c, 0xa182, 0x0040, 0x0079, 0x983d, 0x9850, 0x9850, 0x9850, + 0x9850, 0x9850, 0x9850, 0x9850, 0x9852, 0x985e, 0x9850, 0x9850, + 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, + 0x1078, 0x1328, 0x037e, 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x1078, 0x15ec, 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, + 0x2068, 0x6810, 0x6a14, 0x6118, 0x210c, 0xd1bc, 0x0040, 0x987d, + 0x6124, 0xd1f4, 0x00c0, 0x987d, 0x007e, 0x047e, 0x057e, 0x6c7c, + 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, + 0xa529, 0x652a, 0x057f, 0x047f, 0x007f, 0xa20d, 0x00c0, 0x9891, + 0x684c, 0xd0fc, 0x0040, 0x9889, 0x2009, 0x0041, 0x0d7f, 0x0078, + 0x98c1, 0x6003, 0x0007, 0x6017, 0x0000, 0x1078, 0x5a41, 0x0d7f, + 0x007c, 0x007e, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x007f, + 0x0040, 0x989e, 0x6003, 0x0002, 0x0d7f, 0x007c, 0x2009, 0xa30d, + 0x210c, 0xd19c, 0x0040, 0x98a8, 0x6003, 0x0007, 0x0078, 0x98aa, + 0x6003, 0x0006, 0x1078, 0x98b0, 0x1078, 0x5a43, 0x0d7f, 0x007c, + 0xd2fc, 0x0040, 0x98bc, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, + 0x2009, 0x0009, 0x0078, 0x98be, 0x2009, 0x0015, 0x6a6a, 0x6866, + 0x007c, 0xa182, 0x0040, 0x0048, 0x98c7, 0x0079, 0x98d4, 0xa186, + 0x0013, 0x0040, 0x98cf, 0xa186, 0x0014, 0x10c0, 0x1328, 0x6024, + 0xd0dc, 0x1040, 0x1328, 0x007c, 0x98e7, 0x98ee, 0x98fa, 0x9906, + 0x98e7, 0x98e7, 0x98e7, 0x9915, 0x98e7, 0x98e9, 0x98e9, 0x98e7, + 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x1078, + 0x1328, 0x6024, 0xd0dc, 0x1040, 0x1328, 0x007c, 0x6003, 0x0001, + 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, 0x8000, 0x1078, 0x6109, + 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e, + 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x6003, 0x0003, + 0x6106, 0x2c10, 0x1078, 0x1cab, 0x127e, 0x2091, 0x8000, 0x1078, + 0x5c64, 0x1078, 0x61d3, 0x127f, 0x007c, 0xa016, 0x1078, 0x15ec, + 0x007c, 0x127e, 0x2091, 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040, + 0x1079, 0x9926, 0x0d7f, 0x037f, 0x127f, 0x007c, 0x9936, 0x9938, + 0x994d, 0x996c, 0x9936, 0x9936, 0x9936, 0x9984, 0x9936, 0x9936, + 0x9936, 0x9936, 0x9936, 0x9936, 0x9936, 0x9936, 0x1078, 0x1328, + 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9962, 0xa09c, 0x0003, + 0xa39e, 0x0003, 0x0040, 0x9962, 0x6003, 0x0001, 0x6106, 0x1078, + 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9987, 0x6010, 0x2068, 0x684c, + 0xd0fc, 0x0040, 0x9962, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, + 0x9962, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x1078, 0x6109, + 0x0078, 0x9987, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, + 0x1078, 0x9e70, 0x0078, 0x9987, 0x6010, 0x2068, 0x684c, 0xd0fc, + 0x0040, 0x9962, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9962, + 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, 0x1cab, 0x1078, 0x5c64, + 0x1078, 0x61d3, 0x0078, 0x9987, 0xa016, 0x1078, 0x15ec, 0x007c, + 0x1078, 0x6010, 0x6110, 0x81ff, 0x0040, 0x9999, 0x0d7e, 0x2168, + 0x1078, 0xa181, 0x037e, 0x2019, 0x0029, 0x1078, 0x9e70, 0x037f, + 0x0d7f, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0x1078, 0x60b8, + 0x6110, 0x81ff, 0x0040, 0x99af, 0x0d7e, 0x2168, 0x1078, 0xa181, + 0x037e, 0x2019, 0x0029, 0x1078, 0x9e70, 0x037f, 0x0d7f, 0x1078, + 0x8c01, 0x1078, 0x61d3, 0x007c, 0xa182, 0x0085, 0x0079, 0x99b8, + 0x99c1, 0x99bf, 0x99bf, 0x99cd, 0x99bf, 0x99bf, 0x99bf, 0x1078, + 0x1328, 0x6003, 0x000b, 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, + 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078, + 0xa0bf, 0x0040, 0x99d7, 0x1078, 0x753d, 0x0078, 0x99f3, 0x2071, + 0xa880, 0x7224, 0x6212, 0x7220, 0x1078, 0x9d10, 0x0040, 0x99e4, + 0x6007, 0x0086, 0x0078, 0x99ed, 0x6007, 0x0087, 0x7224, 0xa296, + 0xffff, 0x00c0, 0x99ed, 0x6007, 0x0086, 0x6003, 0x0001, 0x1078, + 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, + 0x00c0, 0x9a07, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1328, 0xa08a, + 0x008c, 0x10c8, 0x1328, 0xa082, 0x0085, 0x0079, 0x9a1e, 0xa186, + 0x0027, 0x0040, 0x9a13, 0xa186, 0x0014, 0x0040, 0x9a13, 0x1078, + 0x7583, 0x0078, 0x9a1d, 0x2001, 0x0007, 0x1078, 0x4472, 0x1078, + 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0x9a25, 0x9a27, + 0x9a27, 0x9a25, 0x9a25, 0x9a25, 0x9a25, 0x1078, 0x1328, 0x1078, + 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0xa182, 0x0085, + 0x1048, 0x1328, 0xa182, 0x008c, 0x10c8, 0x1328, 0xa182, 0x0085, + 0x0079, 0x9a3a, 0x9a41, 0x9a41, 0x9a41, 0x9a43, 0x9a41, 0x9a41, + 0x9a41, 0x1078, 0x1328, 0x007c, 0xa186, 0x0013, 0x0040, 0x9a54, + 0xa186, 0x0014, 0x0040, 0x9a54, 0xa186, 0x0027, 0x0040, 0x9a54, + 0x1078, 0x7583, 0x0078, 0x9a5a, 0x1078, 0x6010, 0x1078, 0x8c01, + 0x1078, 0x6109, 0x007c, 0x037e, 0x1078, 0xa134, 0x603f, 0x0000, + 0x2019, 0x000b, 0x1078, 0x9a6a, 0x601f, 0x0006, 0x6003, 0x0007, + 0x037f, 0x007c, 0x127e, 0x037e, 0x2091, 0x8000, 0x087e, 0x2c40, + 0x097e, 0x2049, 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x00c0, + 0x9aa5, 0x077e, 0x2c38, 0x1078, 0x7105, 0x077f, 0x00c0, 0x9aa5, + 0x6000, 0xa086, 0x0000, 0x0040, 0x9aa5, 0x601c, 0xa086, 0x0007, + 0x0040, 0x9aa5, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x9a96, + 0x1078, 0xa134, 0x601f, 0x0007, 0x1078, 0x1749, 0x6010, 0x2068, + 0x1078, 0x8a44, 0x0040, 0x9a9e, 0x1078, 0x9e70, 0x0d7f, 0x6013, + 0x0000, 0x1078, 0xa134, 0x601f, 0x0007, 0x037f, 0x127f, 0x007c, + 0x0f7e, 0x0c7e, 0x037e, 0x157e, 0x2079, 0xa880, 0x7938, 0x783c, + 0x1078, 0x24e3, 0x00c0, 0x9af6, 0x017e, 0x0c7e, 0x1078, 0x4501, + 0x00c0, 0x9af6, 0x2011, 0xa890, 0xac98, 0x000a, 0x20a9, 0x0004, + 0x1078, 0x7e55, 0x00c0, 0x9af6, 0x017f, 0x027f, 0x027e, 0x017e, + 0x2019, 0x0029, 0x1078, 0x71e0, 0x1078, 0x5d53, 0x077e, 0x2039, + 0x0000, 0x1078, 0x5c78, 0x077f, 0x017f, 0x077e, 0x2039, 0x0000, + 0x1078, 0x9c38, 0x077f, 0x1078, 0x471b, 0x027e, 0x6204, 0xa294, + 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9aea, 0xa286, 0x0004, + 0x00c0, 0x9aed, 0x62a0, 0x1078, 0x28d5, 0x027f, 0x017f, 0x1078, + 0x4235, 0x6612, 0x6516, 0xa006, 0x0078, 0x9af8, 0x0c7f, 0x017f, + 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x0e7e, + 0x017e, 0x2009, 0xa31f, 0x2104, 0xa086, 0x0074, 0x00c0, 0x9b60, + 0x2069, 0xa88e, 0x690c, 0xa182, 0x0100, 0x0048, 0x9b50, 0x6908, + 0xa184, 0x8000, 0x0040, 0x9b5c, 0x6018, 0x2070, 0x7010, 0xa084, + 0x00ff, 0x0040, 0x9b1f, 0x7000, 0xd0f4, 0x0040, 0x9b23, 0xa184, + 0x0800, 0x0040, 0x9b5c, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9b54, + 0x6914, 0x2069, 0xa8ae, 0x6904, 0x81ff, 0x00c0, 0x9b48, 0x690c, + 0xa182, 0x0100, 0x0048, 0x9b50, 0x6908, 0x81ff, 0x00c0, 0x9b4c, + 0x6910, 0xa18a, 0x0001, 0x0048, 0x9b54, 0x6918, 0xa18a, 0x0001, + 0x0048, 0x9b5c, 0x0078, 0x9b66, 0x6013, 0x0100, 0x0078, 0x9b62, + 0x6013, 0x0300, 0x0078, 0x9b62, 0x6013, 0x0500, 0x0078, 0x9b62, + 0x6013, 0x0700, 0x0078, 0x9b62, 0x6013, 0x0900, 0x0078, 0x9b62, + 0x6013, 0x0b00, 0x0078, 0x9b62, 0x6013, 0x0f00, 0x0078, 0x9b62, + 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, 0x9b67, 0xa006, 0x017f, + 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x027e, 0x037e, + 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, + 0x0040, 0x9b90, 0xa286, 0x0004, 0x0040, 0x9b90, 0xa394, 0xff00, + 0x8217, 0xa286, 0x0006, 0x0040, 0x9b90, 0xa286, 0x0004, 0x0040, + 0x9b90, 0x0c7e, 0x2d60, 0x1078, 0x4513, 0x0c7f, 0x0078, 0x9bcb, + 0x2011, 0xa896, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, + 0x00c0, 0x9bcc, 0x2011, 0xa89a, 0xad98, 0x0006, 0x20a9, 0x0004, + 0x1078, 0x7e55, 0x00c0, 0x9bcc, 0x047e, 0x017e, 0x6aa0, 0xa294, + 0x00ff, 0x8227, 0xa006, 0x2009, 0xa352, 0x210c, 0xd1a4, 0x0040, + 0x9bb8, 0x2009, 0x0029, 0x1078, 0x9ec0, 0x6800, 0xc0e5, 0x6802, + 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, 0x1078, + 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x2001, 0x0007, 0x1078, + 0x4472, 0x017f, 0x047f, 0xa006, 0x157f, 0x037f, 0x027f, 0x0d7f, + 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xa88e, 0x6800, 0xa086, 0x0800, + 0x0040, 0x9bde, 0x6013, 0x0000, 0x0078, 0x9bdf, 0xa006, 0x0d7f, + 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2079, + 0xa88c, 0x7930, 0x7834, 0x1078, 0x24e3, 0x00c0, 0x9c05, 0x1078, + 0x4501, 0x00c0, 0x9c05, 0x2011, 0xa890, 0xac98, 0x000a, 0x20a9, + 0x0004, 0x1078, 0x7e55, 0x00c0, 0x9c05, 0x2011, 0xa894, 0xac98, + 0x0006, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x157f, 0x037f, 0x027f, + 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e, 0x017e, 0x027e, + 0x037e, 0x157e, 0x2011, 0xa883, 0x2204, 0x8211, 0x220c, 0x1078, + 0x24e3, 0x00c0, 0x9c31, 0x1078, 0x4501, 0x00c0, 0x9c31, 0x2011, + 0xa896, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x00c0, + 0x9c31, 0x2011, 0xa89a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, + 0x7e55, 0x157f, 0x037f, 0x027f, 0x017f, 0x007f, 0x0c7f, 0x007c, + 0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, + 0x127e, 0x2091, 0x8000, 0x2740, 0x2029, 0xa5b4, 0x252c, 0x2021, + 0xa5ba, 0x2424, 0x2061, 0xaa00, 0x2071, 0xa300, 0x7644, 0x7060, + 0x81ff, 0x0040, 0x9c59, 0x8001, 0xa602, 0x00c8, 0x9cc3, 0x0078, + 0x9c5c, 0xa606, 0x0040, 0x9cc3, 0x2100, 0xac06, 0x0040, 0x9cb9, + 0x1078, 0x9ee5, 0x0040, 0x9cb9, 0x671c, 0xa786, 0x0001, 0x0040, + 0x9cde, 0xa786, 0x0004, 0x0040, 0x9cde, 0xa786, 0x0007, 0x0040, + 0x9cb9, 0x2500, 0xac06, 0x0040, 0x9cb9, 0x2400, 0xac06, 0x0040, + 0x9cb9, 0x1078, 0x9ef9, 0x00c0, 0x9cb9, 0x88ff, 0x0040, 0x9c84, + 0x6020, 0xa906, 0x00c0, 0x9cb9, 0x0d7e, 0x6000, 0xa086, 0x0004, + 0x00c0, 0x9c8e, 0x017e, 0x1078, 0x1749, 0x017f, 0xa786, 0x0008, + 0x00c0, 0x9c9d, 0x1078, 0x8c3b, 0x00c0, 0x9c9d, 0x1078, 0x7a05, + 0x0d7f, 0x1078, 0x8c01, 0x0078, 0x9cb9, 0x6010, 0x2068, 0x1078, + 0x8a44, 0x0040, 0x9cb6, 0xa786, 0x0003, 0x00c0, 0x9ccd, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa181, 0x017e, 0x1078, + 0x8cb8, 0x1078, 0x4982, 0x017f, 0x1078, 0x8bf4, 0x0d7f, 0x1078, + 0x8c01, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, 0x00c8, + 0x9cc3, 0x0078, 0x9c4c, 0x127f, 0x027f, 0x047f, 0x057f, 0x067f, + 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0, + 0x9ca7, 0xa386, 0x0005, 0x0040, 0x9cdb, 0x1078, 0xa181, 0x1078, + 0x9e70, 0x0078, 0x9cb6, 0x0d7f, 0x0078, 0x9cb9, 0x1078, 0x9ef9, + 0x00c0, 0x9cb9, 0x81ff, 0x0040, 0x9cb9, 0xa180, 0x0001, 0x2004, + 0xa086, 0x0018, 0x0040, 0x9cf3, 0xa180, 0x0001, 0x2004, 0xa086, + 0x002d, 0x00c0, 0x9cb9, 0x6000, 0xa086, 0x0002, 0x00c0, 0x9cb9, + 0x1078, 0x8c27, 0x0040, 0x9d04, 0x1078, 0x8c3b, 0x00c0, 0x9cb9, + 0x1078, 0x7a05, 0x0078, 0x9d0c, 0x1078, 0x2839, 0x1078, 0x8c3b, + 0x00c0, 0x9d0c, 0x1078, 0x7a05, 0x1078, 0x8c01, 0x0078, 0x9cb9, + 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x9e8c, 0x017f, + 0x0040, 0x9d1f, 0x601c, 0xa084, 0x000f, 0x1079, 0x9d22, 0x0e7f, + 0x0c7f, 0x007c, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, + 0x9d2c, 0x9d2a, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, 0xa080, + 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, + 0x1078, 0x9ec0, 0x017f, 0x047f, 0x037e, 0x2019, 0x0002, 0x1078, + 0x9a6a, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0001, 0x1078, + 0x442b, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, + 0xa305, 0x2011, 0xa896, 0x1078, 0x7e55, 0x037f, 0x027f, 0x017f, + 0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x087e, 0x077e, + 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2061, 0xaa00, + 0x2079, 0x0001, 0x8fff, 0x0040, 0x9dc3, 0x2071, 0xa300, 0x7644, + 0x7060, 0x8001, 0xa602, 0x00c8, 0x9dc3, 0x88ff, 0x0040, 0x9d7e, + 0x2800, 0xac06, 0x00c0, 0x9db9, 0x2079, 0x0000, 0x1078, 0x9ee5, + 0x0040, 0x9db9, 0x2400, 0xac06, 0x0040, 0x9db9, 0x671c, 0xa786, + 0x0006, 0x00c0, 0x9db9, 0xa786, 0x0007, 0x0040, 0x9db9, 0x88ff, + 0x00c0, 0x9d9d, 0x6018, 0xa206, 0x00c0, 0x9db9, 0x85ff, 0x0040, + 0x9d9d, 0x6020, 0xa106, 0x00c0, 0x9db9, 0x0d7e, 0x6000, 0xa086, + 0x0004, 0x00c0, 0x9da9, 0x1078, 0xa134, 0x601f, 0x0007, 0x1078, + 0x1749, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x9db3, 0x047e, + 0x1078, 0x9e70, 0x047f, 0x0d7f, 0x1078, 0x8c01, 0x88ff, 0x00c0, + 0x9dcd, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, 0x00c8, + 0x9dc3, 0x0078, 0x9d6a, 0xa006, 0x127f, 0x027f, 0x067f, 0x077f, + 0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078, + 0x9dc4, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000, 0x2029, 0x0001, + 0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049, 0x0000, 0x1078, + 0x7058, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x7105, 0x1078, + 0x9d5b, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, 0x077e, + 0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x017e, 0x037e, 0x1078, 0x4501, 0x00c0, 0x9e14, 0x2c10, 0x057e, + 0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, 0x097e, 0x2049, + 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, + 0x7105, 0x1078, 0x9d5b, 0x057f, 0x037f, 0x017f, 0x8108, 0x00f0, + 0x9df8, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, 0x027f, 0x007c, + 0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000, 0x2029, 0x0001, + 0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078, 0x7058, 0x097f, + 0x087f, 0x2039, 0x0000, 0x1078, 0x7105, 0x2c20, 0x1078, 0x9d5b, + 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, 0x077e, 0x0c7e, + 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x037e, + 0x1078, 0x4501, 0x00c0, 0x9e64, 0x2c10, 0x087e, 0x2041, 0x0000, + 0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa111, 0x047f, 0x097e, + 0x2049, 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x2039, 0x0000, + 0x1078, 0x7105, 0x1078, 0x9d5b, 0x037f, 0x017f, 0x8108, 0x00f0, + 0x9e46, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, 0x027f, 0x007c, + 0x017e, 0x0f7e, 0xad82, 0xca00, 0x0048, 0x9e89, 0xad82, 0xffff, + 0x00c8, 0x9e89, 0x6800, 0xa07d, 0x0040, 0x9e86, 0x6803, 0x0000, + 0x6b52, 0x1078, 0x4982, 0x2f68, 0x0078, 0x9e7a, 0x6b52, 0x1078, + 0x4982, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061, + 0xaa00, 0x2071, 0xa300, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, + 0x9ebb, 0x2100, 0xac06, 0x0040, 0x9ead, 0x6000, 0xa086, 0x0000, + 0x0040, 0x9ead, 0x6008, 0xa206, 0x00c0, 0x9ead, 0x6018, 0xa1a0, + 0x0006, 0x2424, 0xa406, 0x0040, 0x9eb7, 0xace0, 0x0010, 0x2001, + 0xa315, 0x2004, 0xac02, 0x00c8, 0x9ebb, 0x0078, 0x9e91, 0xa085, + 0x0001, 0x0078, 0x9ebc, 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, + 0x0d7e, 0x007e, 0x1078, 0x1381, 0x007f, 0x1040, 0x1328, 0x6837, + 0x010d, 0x685e, 0x027e, 0x2010, 0x1078, 0x8a30, 0x2001, 0x0000, + 0x0040, 0x9ed6, 0x2200, 0xa080, 0x0008, 0x2004, 0x027f, 0x684a, + 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a, + 0x685a, 0x1078, 0x4982, 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000, + 0x0040, 0x9ef8, 0xa786, 0x0001, 0x0040, 0x9ef8, 0xa786, 0x000a, + 0x0040, 0x9ef8, 0xa786, 0x0009, 0x0040, 0x9ef8, 0xa085, 0x0001, + 0x007c, 0x0e7e, 0x6018, 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c, + 0x017e, 0x6004, 0xa08e, 0x001e, 0x00c0, 0x9f1a, 0x8007, 0x6130, + 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, + 0x601f, 0x0005, 0x2001, 0xa5a1, 0x2004, 0x6016, 0x1078, 0x5bf8, + 0x1078, 0x6109, 0x017f, 0x007c, 0x0005, 0x0005, 0x007c, 0x6024, + 0xd0e4, 0x0040, 0x9f30, 0xd0cc, 0x0040, 0x9f2a, 0x1078, 0x8cfa, + 0x0078, 0x9f30, 0x1078, 0xa134, 0x1078, 0x5a41, 0x1078, 0x753d, + 0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0079, 0x9f38, + 0x9f41, 0x9f41, 0x9f41, 0x9f43, 0x9f41, 0x9f43, 0x9f43, 0x9f41, + 0x9f43, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa280, 0x0007, + 0x2004, 0xa084, 0x000f, 0x0079, 0x9f4d, 0x9f56, 0x9f56, 0x9f56, + 0x9f56, 0x9f56, 0x9f56, 0x9f61, 0x9f56, 0x9f56, 0x6007, 0x003b, + 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x1078, 0x5bf8, + 0x007c, 0x0c7e, 0x2260, 0x1078, 0xa134, 0x603f, 0x0000, 0x6024, + 0xc0f4, 0xc0cc, 0x6026, 0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007, + 0x00c0, 0x9fc2, 0x6810, 0xa005, 0x0040, 0x9f7f, 0xa080, 0x0013, + 0x2004, 0xd0fc, 0x00c0, 0x9f7f, 0x0d7f, 0x0078, 0x9f56, 0x6007, + 0x003a, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7e, + 0x2d60, 0x6100, 0xa186, 0x0002, 0x00c0, 0xa050, 0x6010, 0xa005, + 0x00c0, 0x9f99, 0x6000, 0xa086, 0x0007, 0x10c0, 0x1328, 0x0078, + 0xa050, 0xa08c, 0xf000, 0x00c0, 0x9fa5, 0x0078, 0x9fa5, 0x2068, + 0x6800, 0xa005, 0x00c0, 0x9f9f, 0x2d00, 0xa080, 0x0013, 0x2004, + 0xa084, 0x0003, 0xa086, 0x0002, 0x00c0, 0x9fbe, 0x6010, 0x2068, + 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, + 0x2009, 0x0043, 0x1078, 0x98c1, 0x0078, 0xa050, 0x2009, 0x0041, + 0x0078, 0xa04a, 0xa186, 0x0005, 0x00c0, 0xa009, 0x6810, 0xa080, + 0x0013, 0x2004, 0xd0bc, 0x00c0, 0x9fd0, 0x0d7f, 0x0078, 0x9f56, + 0xd0b4, 0x0040, 0x9fd8, 0xd0fc, 0x1040, 0x1328, 0x0078, 0x9f72, + 0x6007, 0x003a, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x1078, 0x6109, + 0x0c7e, 0x2d60, 0x6100, 0xa186, 0x0002, 0x0040, 0x9feb, 0xa186, + 0x0004, 0x00c0, 0xa050, 0x2071, 0xa5e1, 0x7000, 0xa086, 0x0003, + 0x00c0, 0x9ff8, 0x7004, 0xac06, 0x00c0, 0x9ff8, 0x7003, 0x0000, + 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, + 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078, + 0xa04a, 0x037e, 0x0d7e, 0x0d7e, 0x1078, 0x1381, 0x037f, 0x1040, + 0x1328, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, + 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872, + 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa084, 0x00ff, 0x8007, 0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000, + 0x6d6a, 0x6e66, 0x686f, 0x0001, 0x1078, 0x4982, 0x2019, 0x0045, + 0x6008, 0x2068, 0x1078, 0x9a6a, 0x2d00, 0x600a, 0x601f, 0x0006, + 0x6003, 0x0007, 0x6017, 0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f, + 0x0078, 0xa051, 0x603f, 0x0000, 0x6003, 0x0007, 0x1078, 0x98c1, + 0x0c7f, 0x0d7f, 0x007c, 0xa186, 0x0013, 0x00c0, 0xa05d, 0x6004, + 0xa082, 0x0085, 0x2008, 0x0079, 0xa077, 0xa186, 0x0027, 0x00c0, + 0xa070, 0x1078, 0x6010, 0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019, + 0x0004, 0x1078, 0x9e70, 0x0d7f, 0x037f, 0x1078, 0x6109, 0x007c, + 0xa186, 0x0014, 0x0040, 0xa061, 0x1078, 0x7583, 0x007c, 0xa080, + 0xa07e, 0xa07e, 0xa07e, 0xa07e, 0xa07e, 0xa080, 0x1078, 0x1328, + 0x1078, 0x6010, 0x6003, 0x000c, 0x1078, 0x6109, 0x007c, 0xa182, + 0x008c, 0x00c8, 0xa091, 0xa182, 0x0085, 0x0048, 0xa091, 0x0079, + 0xa094, 0x1078, 0x7583, 0x007c, 0xa09b, 0xa09b, 0xa09b, 0xa09b, + 0xa09d, 0xa0bc, 0xa09b, 0x1078, 0x1328, 0x0d7e, 0x2c68, 0x1078, + 0x74d7, 0x0040, 0xa0b7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, + 0xa88e, 0x210c, 0x6136, 0x2009, 0xa88f, 0x210c, 0x613a, 0x600b, + 0xffff, 0x6918, 0x611a, 0x601f, 0x0004, 0x1078, 0x5bf8, 0x2d60, + 0x1078, 0x753d, 0x0d7f, 0x007c, 0x1078, 0x753d, 0x007c, 0x0e7e, + 0x6018, 0x2070, 0x7000, 0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa080, + 0x0013, 0x200c, 0xd1ec, 0x0040, 0xa110, 0x2001, 0xa371, 0x2004, + 0xd0ec, 0x0040, 0xa110, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, + 0xd1ac, 0x0040, 0xa0ee, 0x0f7e, 0x2c78, 0x1078, 0x488f, 0x0f7f, + 0x0040, 0xa0ee, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x2009, 0xa371, + 0x210c, 0xd1f4, 0x00c0, 0xa10e, 0x0078, 0xa100, 0x2009, 0xa371, + 0x210c, 0xd1f4, 0x0040, 0xa0fa, 0x6024, 0xc0e4, 0x6026, 0xa006, + 0x0078, 0xa110, 0x2001, 0xa5a2, 0x200c, 0x8103, 0xa100, 0x603e, + 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa10b, 0xa088, + 0x0003, 0x0078, 0xa103, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, + 0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b, 0x2e04, + 0x2060, 0x8cff, 0x0040, 0xa130, 0x84ff, 0x00c0, 0xa123, 0x6020, + 0xa106, 0x00c0, 0xa12b, 0x600c, 0x2072, 0x1078, 0x5a41, 0x1078, + 0x753d, 0x0078, 0xa12d, 0xacf0, 0x0003, 0x2e64, 0x0078, 0xa119, + 0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8, 0x002b, + 0x2d04, 0xa005, 0x0040, 0xa146, 0xac06, 0x0040, 0xa144, 0x2d04, + 0xa0e8, 0x0003, 0x0078, 0xa138, 0x600c, 0x206a, 0x0d7f, 0x007c, + 0x027e, 0x037e, 0x157e, 0x2011, 0xa325, 0x2204, 0xa084, 0x00ff, + 0x2019, 0xa88e, 0x2334, 0xa636, 0x00c0, 0xa174, 0x8318, 0x2334, + 0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa174, 0x2011, 0xa890, + 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x00c0, + 0xa174, 0x2011, 0xa894, 0x6018, 0xa098, 0x0006, 0x20a9, 0x0004, + 0x1078, 0x7e55, 0x00c0, 0xa174, 0x157f, 0x037f, 0x027f, 0x007c, + 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, 0x1078, 0x260d, 0x0e7f, + 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040, 0xa18a, + 0x1078, 0xa18c, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852, 0x007c, + 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, 0x017e, + 0x127e, 0x2091, 0x8000, 0x2029, 0xa5b4, 0x252c, 0x2021, 0xa5ba, + 0x2424, 0x2061, 0xaa00, 0x2071, 0xa300, 0x7644, 0x7060, 0xa606, + 0x0040, 0xa1e4, 0x671c, 0xa786, 0x0001, 0x0040, 0xa1b3, 0xa786, + 0x0008, 0x00c0, 0xa1da, 0x2500, 0xac06, 0x0040, 0xa1da, 0x2400, + 0xac06, 0x0040, 0xa1da, 0x1078, 0x9ee5, 0x0040, 0xa1da, 0x1078, + 0x9ef9, 0x00c0, 0xa1da, 0x6000, 0xa086, 0x0004, 0x00c0, 0xa1cc, + 0x017e, 0x1078, 0x1749, 0x017f, 0x1078, 0x8c27, 0x00c0, 0xa1d2, + 0x1078, 0x2839, 0x1078, 0x8c3b, 0x00c0, 0xa1d8, 0x1078, 0x7a05, + 0x1078, 0x8c01, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, + 0x00c8, 0xa1e4, 0x0078, 0xa1a3, 0x127f, 0x017f, 0x027f, 0x047f, + 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x007e, + 0x0e7e, 0x2091, 0x8000, 0x2071, 0xa340, 0xd5a4, 0x0040, 0xa1fb, + 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa201, 0x7030, 0x8000, + 0x7032, 0xd5ac, 0x0040, 0xa208, 0x2071, 0xa34a, 0x1078, 0xa237, + 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, + 0x8000, 0x2071, 0xa340, 0xd5a4, 0x0040, 0xa219, 0x7034, 0x8000, + 0x7036, 0xd5b4, 0x0040, 0xa21f, 0x7030, 0x8000, 0x7032, 0xd5ac, + 0x0040, 0xa226, 0x2071, 0xa34a, 0x1078, 0xa237, 0x0e7f, 0x007f, + 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, + 0xa342, 0x1078, 0xa237, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04, + 0x8000, 0x2072, 0x00c8, 0xa240, 0x8e70, 0x2e04, 0x8000, 0x2072, + 0x007c, 0x0e7e, 0x2071, 0xa340, 0x1078, 0xa237, 0x0e7f, 0x007c, + 0x0e7e, 0x2071, 0xa344, 0x1078, 0xa237, 0x0e7f, 0x007c, 0x0001, + 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, + 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x6286 +}; + +/************************************************************************ + * * + * --- ISP2200 Initiator/Target Firmware --- * + * with Fabric (Public Loop), Point-point, and * + * expanded LUN addressing for FCTAPE * + * * + ************************************************************************ + Copyright (C) 2000 and 2100 Qlogic Corporation + (www.qlogic.com) + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. +************************************************************************/ + +/* + * Firmware Version 2.01.27 (11:07 Dec 18, 2000) + */ + +unsigned short risc_code_length2200 = 0x9cbf; +unsigned short risc_code2200[] = { + 0x0470, 0x0000, 0x0000, 0x9cbf, 0x0000, 0x0002, 0x0001, 0x001b, + 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, + 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x322e, 0x3031, 0x2e32, 0x3720, 0x2020, 0x2020, 0x2400, 0x20c1, + 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xb1ff, 0x2091, + 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x27b5, + 0x2051, 0xad00, 0x2a70, 0x2029, 0xe400, 0x2031, 0xffff, 0x2039, + 0xe3e9, 0x2021, 0x0200, 0x0804, 0x1449, 0x20a1, 0xacbf, 0xa00e, + 0x20a9, 0x0741, 0x41a4, 0x3400, 0x755e, 0x7662, 0x775a, 0x7466, + 0x746a, 0x20a1, 0xb400, 0x7160, 0x810d, 0x810d, 0x810d, 0x810d, + 0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4, + 0x3400, 0x8211, 0x1dd8, 0x7160, 0x3400, 0xa102, 0x0120, 0x0218, + 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xad00, + 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, + 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, + 0x2009, 0xad00, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, + 0x41a4, 0x080c, 0x13fc, 0x080c, 0x1613, 0x080c, 0x17ac, 0x080c, + 0x1e67, 0x080c, 0x492e, 0x080c, 0x801a, 0x080c, 0x159c, 0x080c, + 0x2ce6, 0x080c, 0x5a01, 0x080c, 0x5045, 0x080c, 0x6487, 0x080c, + 0x236a, 0x080c, 0x6686, 0x080c, 0x5fae, 0x080c, 0x226b, 0x080c, + 0x2338, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820, + 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b, + 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, + 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3c98, 0x080c, + 0x2d0d, 0x080c, 0x5a4f, 0x080c, 0x51f4, 0x080c, 0x64a2, 0x0c80, + 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1203, 0x10e2, 0x12cc, 0x13f9, + 0x13fa, 0x13fb, 0x080c, 0x14f6, 0x0005, 0x0126, 0x00f6, 0x2091, + 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11d1, 0x080c, 0x1569, + 0x080c, 0x574f, 0x0150, 0x080c, 0x5775, 0x1580, 0x2079, 0x0100, + 0x7828, 0xa085, 0x1800, 0x782a, 0x0448, 0x080c, 0x569a, 0x7000, + 0xa086, 0x0001, 0x1904, 0x11d1, 0x7088, 0xa086, 0x0028, 0x1904, + 0x11d1, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0xa295, 0x1e2f, + 0x7a2a, 0x2011, 0x566e, 0x080c, 0x650d, 0x2011, 0x567b, 0x080c, + 0x650d, 0x2011, 0x481b, 0x080c, 0x650d, 0x2011, 0x8030, 0x2019, + 0x0000, 0x7087, 0x0000, 0x080c, 0x1d0f, 0x00e8, 0x080c, 0x41d1, + 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11d1, 0x2011, 0x481b, + 0x080c, 0x650d, 0x2011, 0x567b, 0x080c, 0x650d, 0x080c, 0x1d0f, + 0x2001, 0xaf8c, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842, + 0x2011, 0x8010, 0x73c8, 0x080c, 0x3c5c, 0x7238, 0xc284, 0x723a, + 0x2001, 0xad0c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x79bd, 0x2011, + 0x0004, 0x080c, 0x959c, 0x080c, 0x4f71, 0x080c, 0x574f, 0x0158, + 0x080c, 0x4917, 0x0140, 0x7087, 0x0001, 0x70c3, 0x0000, 0x080c, + 0x436e, 0x0804, 0x11d1, 0x080c, 0x502d, 0x0120, 0x7a0c, 0xc2b4, + 0x7a0e, 0x0050, 0x080c, 0x9937, 0x70d0, 0xd09c, 0x1128, 0x709c, + 0xa005, 0x0110, 0x080c, 0x48f5, 0x70db, 0x0000, 0x70d7, 0x0000, + 0x72d0, 0x080c, 0x574f, 0x1178, 0x2011, 0x0000, 0x0016, 0x080c, + 0x2744, 0x2019, 0xaf8e, 0x211a, 0x001e, 0x704f, 0xffff, 0x7053, + 0x00ef, 0x7073, 0x0000, 0x2079, 0xad51, 0x7804, 0xd0ac, 0x0108, + 0xc295, 0x72d2, 0x080c, 0x574f, 0x0118, 0xa296, 0x0004, 0x0508, + 0x2011, 0x0001, 0x080c, 0x959c, 0x7097, 0x0000, 0x709b, 0xffff, + 0x7003, 0x0002, 0x00fe, 0x080c, 0x28fa, 0x2011, 0x0005, 0x080c, + 0x7adf, 0x080c, 0x6c50, 0x080c, 0x574f, 0x0148, 0x00c6, 0x2061, + 0x0100, 0x0016, 0x080c, 0x2744, 0x61e2, 0x001e, 0x00ce, 0x012e, + 0x00d0, 0x7097, 0x0000, 0x709b, 0xffff, 0x7003, 0x0002, 0x2011, + 0x0005, 0x080c, 0x7adf, 0x080c, 0x6c50, 0x080c, 0x574f, 0x0148, + 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2744, 0x61e2, 0x001e, + 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x574f, 0x1118, + 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x574f, 0x1118, + 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x0016, 0x0026, 0x0036, + 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, 0x7cf4, 0x002e, 0x080c, + 0xac07, 0x003e, 0x002e, 0x001e, 0x080c, 0x2bc9, 0x8108, 0x1f04, + 0x11e5, 0x00ce, 0x706f, 0x0000, 0x7070, 0xa084, 0x00ff, 0x7072, + 0x709f, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, 0xa086, + 0x0002, 0x1904, 0x12ca, 0x7098, 0xa086, 0xffff, 0x0130, 0x080c, + 0x28fa, 0x080c, 0x6c50, 0x0804, 0x12ca, 0x70d0, 0xd0ac, 0x1110, + 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, 0x2001, 0x0103, + 0x2009, 0xaf8c, 0x210c, 0x2102, 0x001e, 0x000e, 0xd08c, 0x01d0, + 0x70d4, 0xa086, 0xffff, 0x0190, 0x080c, 0x2a56, 0x080c, 0x6c50, + 0x70d0, 0xd094, 0x1904, 0x12ca, 0x2011, 0x0001, 0x2019, 0x0000, + 0x080c, 0x2a8c, 0x080c, 0x6c50, 0x0804, 0x12ca, 0x70d8, 0xa005, + 0x1904, 0x12ca, 0x7094, 0xa005, 0x1904, 0x12ca, 0x70d0, 0xd0a4, + 0x0118, 0xd0b4, 0x0904, 0x12ca, 0x080c, 0x502d, 0x1904, 0x12ca, + 0x2001, 0xad52, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1118, 0x6000, + 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x125b, 0x00ce, 0x015e, + 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12ca, 0x0006, 0x0016, + 0x2001, 0x0103, 0x2009, 0xaf8c, 0x210c, 0x2102, 0x001e, 0x000e, + 0xa006, 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0xafb5, 0x40a1, + 0x706c, 0x8007, 0x7170, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x2009, + 0x0000, 0x080c, 0x14dc, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, + 0x40a1, 0xa006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, 0xafc5, + 0x40a1, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x709b, 0xffff, + 0x080c, 0x1562, 0xa006, 0x080c, 0x261e, 0x080c, 0x3cce, 0x00f6, + 0x2079, 0x0100, 0x080c, 0x5775, 0x0150, 0x080c, 0x574f, 0x7828, + 0x0118, 0xa084, 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, + 0x2001, 0xafc8, 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, 0x0000, + 0x080c, 0x7adf, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x080c, 0x6c50, + 0x080c, 0x6d0d, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, + 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0xad33, 0x2104, 0xa005, + 0x1110, 0x080c, 0x2770, 0x2009, 0x00f7, 0x080c, 0x48de, 0x7940, + 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, + 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, + 0xd1ac, 0x1904, 0x133a, 0x080c, 0x5761, 0x0158, 0x080c, 0x5775, + 0x1128, 0x2001, 0xaf9d, 0x2003, 0x0000, 0x0070, 0x080c, 0x5757, + 0x0dc0, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, + 0x0001, 0x080c, 0x569a, 0x0058, 0x080c, 0x574f, 0x0140, 0x2009, + 0x00f8, 0x080c, 0x48de, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, + 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x574f, 0x0138, 0x7824, + 0xd0ac, 0x1904, 0x13e0, 0x1f04, 0x1319, 0x0070, 0x7824, 0x080c, + 0x576b, 0x0118, 0xd0ac, 0x1904, 0x13e0, 0xa084, 0x1800, 0x0d98, + 0x7003, 0x0001, 0x0804, 0x13e0, 0x2001, 0x0001, 0x080c, 0x261e, + 0x0804, 0x13ef, 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, 0x0020, + 0x20a9, 0x0046, 0x1d04, 0x1342, 0x2091, 0x6000, 0x1f04, 0x1342, + 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, 0x0000, + 0x080c, 0x5761, 0x0158, 0x080c, 0x5775, 0x1128, 0x2001, 0xaf9d, + 0x2003, 0x0000, 0x0070, 0x080c, 0x5757, 0x0dc0, 0x2001, 0xaf9d, + 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x080c, 0x569a, + 0x0020, 0x2009, 0x00f8, 0x080c, 0x48de, 0x20a9, 0x000e, 0xe000, + 0x1f04, 0x136f, 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, 0x7852, + 0x080c, 0x574f, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, + 0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, 0x574f, + 0x05b8, 0x7824, 0xd0ac, 0x1904, 0x13e0, 0x080c, 0x5775, 0x1508, + 0x0046, 0x2021, 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8, + 0x7827, 0x0048, 0x20a9, 0x01f4, 0x1d04, 0x139c, 0x2091, 0x6000, + 0x1f04, 0x139c, 0x7824, 0xa084, 0x0068, 0x15a8, 0x2001, 0xaf9d, + 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x7003, 0x0001, + 0x0478, 0x8319, 0x1980, 0x2009, 0xad33, 0x2104, 0x8000, 0x200a, + 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, 0x2770, 0x00d8, + 0x080c, 0x5761, 0x1140, 0xa4a2, 0x0064, 0x1128, 0x080c, 0x5726, + 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, 0xe000, 0x7824, + 0x080c, 0x576b, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, 0x09c8, + 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x261e, 0x0048, + 0x2001, 0xad33, 0x2003, 0x0000, 0x7827, 0x0048, 0x7828, 0xc09d, + 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x015e, + 0x003e, 0x000e, 0x080c, 0x1539, 0x012e, 0x00fe, 0x004e, 0x001e, + 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2001, 0xaf9d, 0x2003, + 0x0000, 0x7087, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, + 0x0218, 0x704f, 0xffff, 0x0010, 0x704f, 0x0000, 0x7057, 0xffff, + 0x706f, 0x0000, 0x7073, 0x0000, 0x080c, 0x9937, 0x2061, 0xaf8d, + 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, + 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, + 0x2061, 0xaf95, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, + 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, + 0x601f, 0x0000, 0x2061, 0xafa6, 0x6003, 0x514c, 0x6007, 0x4f47, + 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xad27, 0x2003, 0x0000, + 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, 0xa186, 0x0001, + 0x1148, 0x2031, 0x8fff, 0x2039, 0xcc01, 0x2021, 0x0100, 0x2029, + 0xcc00, 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011, 0x0000, 0x00b8, + 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, 0x0088, 0xa186, 0x0009, + 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, 0x000a, 0x1118, 0x2011, + 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, 0x2011, 0x0003, 0x3800, + 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d, 0xa00e, 0x2011, + 0x0003, 0x2019, 0x1485, 0x0804, 0x14d6, 0x2019, 0xaaaa, 0x2061, + 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0xa306, 0x2262, + 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, 0x1498, 0x04f0, + 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, + 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04, 0x2061, 0xffff, + 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185, 0x2011, 0x0002, + 0x2019, 0x14b3, 0x0418, 0x2061, 0xffff, 0x2019, 0xaaaa, 0x2c14, + 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306, 0x1180, 0x2c14, + 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0x2c04, 0x2061, + 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, 0x0008, 0xc19d, 0x2011, + 0x0001, 0x2019, 0x14d4, 0x0010, 0x0804, 0x144a, 0x3800, 0xa084, + 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2011, 0x0000, 0x080c, 0x4cdc, + 0x1178, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0128, 0xa0c4, + 0xff00, 0xa8c6, 0x0600, 0x1120, 0xa186, 0x0080, 0x0108, 0x8210, + 0x8108, 0xa186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, + 0x0e04, 0x14f8, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084, + 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900, + 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0126, + 0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, 0xb0c8, 0x2091, 0x2000, + 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010, + 0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1, + 0x20a9, 0x0010, 0x2091, 0x2800, 0x40a1, 0x014e, 0x015e, 0x012e, + 0x2079, 0xad00, 0x7803, 0x0005, 0x2091, 0x4080, 0x04c9, 0x0cf8, + 0x0005, 0x0006, 0x080c, 0x1584, 0x1518, 0x00f6, 0x2079, 0xad23, + 0x2f04, 0x8000, 0x207a, 0xa082, 0x000f, 0x0258, 0xa006, 0x207a, + 0x2079, 0xad25, 0x2f04, 0xa084, 0x0001, 0xa086, 0x0001, 0x207a, + 0x0070, 0x2079, 0xad25, 0x2f7c, 0x8fff, 0x1128, 0x2001, 0x0c03, + 0x2003, 0x0040, 0x0020, 0x2001, 0x0c03, 0x2003, 0x00c0, 0x00fe, + 0x000e, 0x0005, 0x0409, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0080, + 0x0005, 0x00d1, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0005, + 0x0006, 0x0091, 0x1178, 0x2001, 0x0c03, 0x2003, 0x0040, 0x2009, + 0x0fff, 0x00a1, 0x2001, 0x0c03, 0x2003, 0x0080, 0x2009, 0x0fff, + 0x0069, 0x0c88, 0x000e, 0x0005, 0x00c6, 0x2061, 0x0c00, 0x2c04, + 0xa084, 0x00ff, 0xa086, 0x00aa, 0x00ce, 0x0005, 0x0156, 0x0126, + 0xa18c, 0x0fff, 0x21a8, 0x1d04, 0x1593, 0x2091, 0x6000, 0x1f04, + 0x1593, 0x012e, 0x015e, 0x0005, 0x2071, 0xad00, 0x715c, 0x712e, + 0x2021, 0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7060, + 0xa302, 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, + 0xd08c, 0x0148, 0x7060, 0xa086, 0xad00, 0x0128, 0x7063, 0xad00, + 0x2011, 0x1000, 0x0c48, 0x200b, 0x0000, 0x74ae, 0x74b2, 0x0005, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, 0x70b0, 0xa0ea, + 0x0010, 0x0268, 0x8001, 0x70b2, 0x702c, 0x2068, 0x2d04, 0x702e, + 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, + 0x0cd8, 0x00e6, 0x2071, 0xad00, 0x0126, 0x2091, 0x8000, 0x70b0, + 0x8001, 0x0260, 0x70b2, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, + 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, 0x702c, 0x206a, + 0x2d00, 0x702e, 0x70b0, 0x8000, 0x70b2, 0x012e, 0x00ee, 0x0005, + 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de, + 0x0cb8, 0x0005, 0x00e6, 0x2071, 0xad00, 0x70b0, 0xa08a, 0x0010, + 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xafec, 0x7007, 0x0000, + 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, + 0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6, 0x2270, 0x700b, 0x0000, + 0x2071, 0xafec, 0x7018, 0xa088, 0xaff5, 0x220a, 0x8000, 0xa084, + 0x0007, 0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, + 0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xafec, 0x7004, + 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee, + 0x0005, 0x7000, 0x0002, 0x164f, 0x16b3, 0x16d0, 0x16d0, 0x7018, + 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180, + 0xaff5, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e, + 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a, + 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de, + 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002, + 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, + 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, + 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016, + 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, 0x0014, + 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210, + 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, + 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e, + 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, 0xadf9, + 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, + 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, + 0x7002, 0x700b, 0xadf4, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, + 0x0136, 0x0146, 0x0156, 0x2001, 0xae28, 0x209c, 0x20a1, 0x0014, + 0x7803, 0x0026, 0x2001, 0xae29, 0x20ac, 0x53a6, 0x2099, 0xae2a, + 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, + 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, + 0x7002, 0x700b, 0xae25, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, + 0x0016, 0x00e6, 0x2071, 0xafec, 0x00f6, 0x2079, 0x0010, 0x7904, + 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, 0x0023, + 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1649, 0x1713, 0x1741, 0x176b, + 0x179b, 0x1712, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146, + 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, + 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c, + 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x167a, + 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, + 0x080c, 0x1649, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, + 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, 0x0188, 0x7830, + 0x7832, 0x7834, 0x7836, 0x080c, 0x168f, 0x0005, 0x7008, 0xa080, + 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, 0x1649, 0x0005, + 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, + 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000, + 0x080c, 0x1649, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146, + 0x0156, 0x2001, 0xadf7, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, + 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xadf9, + 0x2004, 0xd0bc, 0x0148, 0x2001, 0xae02, 0x2004, 0xa080, 0x000d, + 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007, + 0x0000, 0x080c, 0x5ae6, 0x080c, 0x1649, 0x0005, 0x2011, 0x8003, + 0x080c, 0x3c5c, 0x0cf8, 0xa18c, 0x0700, 0x1148, 0x2001, 0xae27, + 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1649, 0x0005, 0x2011, + 0x8004, 0x080c, 0x3c5c, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079, + 0x0030, 0x2071, 0xaffd, 0x7003, 0x0000, 0x700f, 0xb003, 0x7013, + 0xb003, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, 0x0005, 0x6934, + 0xa184, 0x0007, 0x0002, 0x17cb, 0x1809, 0x17cb, 0x17cb, 0x17cb, + 0x17f1, 0x17d8, 0x17cf, 0xa085, 0x0001, 0x0804, 0x1823, 0x684c, + 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8, + 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58, + 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, 0xa080, 0x000d, + 0x2004, 0xa084, 0x000f, 0xa080, 0x2186, 0x2005, 0x6832, 0x6858, + 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac, + 0x0990, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, + 0xa080, 0x2186, 0x2005, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, + 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17cb, 0xa006, 0x682e, 0x682a, + 0x6858, 0xa18c, 0x000f, 0xa188, 0x2186, 0x210d, 0x6932, 0x2d08, + 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, + 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000, + 0x2001, 0x020a, 0x2004, 0x82ff, 0x01a8, 0xa280, 0x0004, 0x00d6, + 0x206c, 0x684c, 0xd0dc, 0x1150, 0x080c, 0x17bf, 0x0138, 0x00de, + 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000, + 0x680a, 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200, + 0x002e, 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a, + 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0xb01e, 0x0210, + 0x2009, 0xb003, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118, + 0xa080, 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, 0x012e, 0x0005, + 0x7206, 0x2001, 0x1866, 0x0006, 0x2260, 0x0804, 0x197a, 0x0126, + 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e, + 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, 0x6a62, + 0x6b5e, 0xa005, 0x0904, 0x18c8, 0x6808, 0xa005, 0x0904, 0x18ff, + 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, 0x1904, + 0x1907, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, 0xd08c, + 0x0168, 0x0046, 0x080c, 0x1a6c, 0x004e, 0x2460, 0x6010, 0xa080, + 0x0002, 0x2004, 0xa005, 0x0904, 0x18ff, 0x0c10, 0x2001, 0x0207, + 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086, + 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, + 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, + 0x1904, 0x1907, 0x2009, 0x0048, 0x080c, 0x80a7, 0x0804, 0x1907, + 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110, + 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0160, 0x0046, 0x080c, 0x1a6c, 0x004e, 0x2460, 0x6010, + 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207, + 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50, + 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818, + 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, + 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x80a7, 0x00ce, + 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, + 0x0056, 0x080c, 0x1d86, 0x0026, 0x0056, 0x2071, 0xaffd, 0x7000, + 0xa086, 0x0000, 0x0580, 0x7004, 0xac06, 0x11f8, 0x2079, 0x0030, + 0x7000, 0xa086, 0x0003, 0x01c8, 0x7804, 0xd0fc, 0x1198, 0x2001, + 0x0207, 0x2004, 0xd09c, 0x1dc0, 0x7803, 0x0004, 0x7804, 0xd0ac, + 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, + 0x0000, 0x0018, 0x080c, 0x1a6c, 0x08d0, 0x0156, 0x20a9, 0x0009, + 0x2009, 0xb003, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, + 0x1f04, 0x1942, 0x015e, 0x005e, 0x002e, 0x2001, 0x015d, 0x201c, + 0x831a, 0x2302, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, + 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c, + 0x7110, 0xa106, 0x0904, 0x19dd, 0x2104, 0x7006, 0x2060, 0x8108, + 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb01e, 0x0210, 0x2009, + 0xb003, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, 0x2744, 0x2001, + 0x0138, 0x2102, 0x8cff, 0x0588, 0x6010, 0x2068, 0x2d58, 0x6828, + 0xa406, 0x1580, 0x682c, 0xa306, 0x1568, 0x7004, 0x2060, 0x6020, + 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, 0xffff, 0x6813, + 0xffff, 0x00d8, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810, + 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, + 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x04c9, 0x0118, + 0x2009, 0x0001, 0x04a9, 0x2d58, 0x0005, 0x080c, 0x1ced, 0x0904, + 0x195f, 0x0cd0, 0x6020, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034, + 0xa303, 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046, + 0x0036, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, 0xa303, + 0x6816, 0x003e, 0x004e, 0x0018, 0x080c, 0x98cb, 0x09f0, 0x601c, + 0xa08e, 0x0008, 0x0904, 0x1985, 0xa08e, 0x000a, 0x0904, 0x1985, + 0x080c, 0x21a6, 0x1990, 0x0804, 0x1985, 0x7003, 0x0000, 0x0005, + 0x8aff, 0x0904, 0x1a46, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8, + 0xd0f4, 0x1528, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1a30, + 0x1a15, 0x1a15, 0x1a30, 0x1a30, 0x1a29, 0x1a30, 0x1a15, 0x1a30, + 0x1a1a, 0x1a1a, 0x1a30, 0x1a30, 0x1a30, 0x1a21, 0x1a1a, 0x7803, + 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, + 0xd99c, 0x0548, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0420, 0xc0f4, + 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0428, 0x6b08, 0x6a0c, 0x6d00, + 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, + 0x1138, 0x00de, 0x080c, 0x2148, 0x1904, 0x19e0, 0xa00e, 0x00b0, + 0x00de, 0x080c, 0x14f6, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, + 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300, + 0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x2148, 0x0005, 0x080c, + 0x14f6, 0x080c, 0x1e1a, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, + 0x7003, 0x0000, 0x080c, 0x1d22, 0x080c, 0x9596, 0x0170, 0x6808, + 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, + 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x929c, + 0x0804, 0x1c5e, 0x080c, 0x14f6, 0x0126, 0x2091, 0x2200, 0x0006, + 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, + 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, + 0x0002, 0x1a89, 0x1a8f, 0x1b92, 0x1c39, 0x1c4d, 0x1a89, 0x1a89, + 0x1a89, 0x7804, 0xd09c, 0x1904, 0x1c5e, 0x080c, 0x14f6, 0x8001, + 0x7002, 0xa184, 0x0880, 0x1190, 0xd19c, 0x1904, 0x1b20, 0x8aff, + 0x0904, 0x1b20, 0x2009, 0x0001, 0x080c, 0x19e0, 0x0904, 0x1c5e, + 0x2009, 0x0001, 0x080c, 0x19e0, 0x0804, 0x1c5e, 0x7803, 0x0004, + 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1b00, 0x0026, 0x0036, 0x7c20, + 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, + 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, + 0x0009, 0x7003, 0x0004, 0x0010, 0x080c, 0x1c62, 0x6b28, 0x6a2c, + 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, + 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236, + 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x080c, 0x215e, 0x2a00, + 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, + 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004, + 0x2060, 0x2009, 0x0048, 0x080c, 0x80a7, 0x7000, 0xa086, 0x0004, + 0x0904, 0x1c5e, 0x7003, 0x0000, 0x080c, 0x195f, 0x0804, 0x1c5e, + 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0xac73, 0x005e, 0x080c, + 0x1d22, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5029, 0x0118, 0x7820, + 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, + 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, 0x1c5e, + 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, 0x0128, 0x6808, + 0x8001, 0x680a, 0x0804, 0x1c5e, 0x7818, 0x6812, 0x7a1c, 0x6a16, + 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, 0x2004, + 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1aa6, 0x684c, 0xc0f5, + 0x684e, 0x7814, 0xa005, 0x1180, 0x7003, 0x0000, 0x6808, 0x8001, + 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x80a7, + 0x080c, 0x195f, 0x0804, 0x1c5e, 0x7818, 0x6812, 0x781c, 0x6816, + 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214, + 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, + 0x810b, 0x080c, 0x1da5, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, + 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004, + 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, + 0x080c, 0x80a7, 0x080c, 0x1dd7, 0x0958, 0x7908, 0xd1ec, 0x1118, + 0x2009, 0x0009, 0x0010, 0x2009, 0x0019, 0x7902, 0x7003, 0x0003, + 0x0804, 0x1c5e, 0x8001, 0x7002, 0xd194, 0x01a8, 0x7804, 0xd0fc, + 0x1904, 0x1c2c, 0xd09c, 0x0130, 0x7804, 0xd0fc, 0x1904, 0x1a74, + 0xd09c, 0x11a8, 0x8aff, 0x0904, 0x1c5e, 0x2009, 0x0001, 0x080c, + 0x19e0, 0x0804, 0x1c5e, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, + 0x1c5e, 0x2009, 0x0001, 0x080c, 0x19e0, 0x0804, 0x1c5e, 0x7818, + 0x6812, 0x7a1c, 0x6a16, 0xa205, 0x0904, 0x1b3e, 0x7803, 0x0004, + 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1c0f, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x0029, 0x1118, 0xd19c, 0x1904, 0x1b3e, 0x0026, 0x0036, + 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, + 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, + 0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1c62, + 0x001e, 0x6b28, 0x6a2c, 0x080c, 0x215e, 0x00d6, 0x2805, 0xac68, + 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, + 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x1ac8, + 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, + 0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1b50, 0x0056, + 0x7d0c, 0x080c, 0xac73, 0x005e, 0x080c, 0x1d22, 0x00f6, 0x7004, + 0x2078, 0x080c, 0x5029, 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, + 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, + 0x791a, 0x6980, 0x791e, 0x0490, 0x7804, 0xd09c, 0x0904, 0x1a74, + 0x7c20, 0x7824, 0xa405, 0x1904, 0x1a74, 0x7803, 0x0002, 0x0804, + 0x1bb7, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0150, + 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, 0x0048, + 0x080c, 0x80a7, 0x080c, 0x195f, 0x0088, 0x7803, 0x0004, 0x7003, + 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, + 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x197a, 0x001e, 0x000e, + 0x012e, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1ce1, 0x7004, + 0x0016, 0x210c, 0xa106, 0x001e, 0x0904, 0x1ce1, 0x00d6, 0x00c6, + 0x216c, 0x2d00, 0xa005, 0x0904, 0x1cdf, 0x6820, 0xd0d4, 0x1904, + 0x1cdf, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x0558, 0x8108, 0x2104, + 0x6b2c, 0xa306, 0x1904, 0x1cdf, 0x8108, 0x2104, 0x6a28, 0xa206, + 0x1904, 0x1cdf, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, + 0x6870, 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, + 0x6034, 0xd09c, 0x0150, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, + 0x783a, 0x680c, 0x783e, 0x00de, 0x04a0, 0xa006, 0x783a, 0x783e, + 0x0480, 0x8108, 0x2104, 0xa005, 0x1590, 0x8108, 0x2104, 0xa005, + 0x1570, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160, + 0xa180, 0x000d, 0x2004, 0xd09c, 0x1170, 0x6008, 0x7822, 0x686e, + 0x600c, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0xa006, + 0x783a, 0x783e, 0x0070, 0x6010, 0x7822, 0x686e, 0x6014, 0x7826, + 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0x6008, 0x783a, 0x600c, + 0x783e, 0x6810, 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, + 0x00de, 0x0005, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, + 0x1118, 0x8109, 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x01e0, 0x7908, + 0xd1ec, 0x1160, 0x080c, 0x1dd7, 0x0148, 0x7803, 0x0009, 0x7904, + 0xd1fc, 0x0de8, 0x7803, 0x0006, 0x0c29, 0x0168, 0x780c, 0xd0a4, + 0x1150, 0x7007, 0x0000, 0x080c, 0x1dd7, 0x0140, 0x7803, 0x0019, + 0x7003, 0x0003, 0x0018, 0x00b1, 0xa085, 0x0001, 0x0005, 0x0126, + 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1150, 0x700c, 0x7110, + 0xa106, 0x0130, 0x20e1, 0x9028, 0x700f, 0xb003, 0x7013, 0xb003, + 0x012e, 0x0005, 0x00c6, 0x080c, 0x574f, 0x1550, 0x2001, 0x0160, + 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, 0x00c8, + 0xe000, 0xe000, 0x8211, 0x1de0, 0x080c, 0x1d7e, 0x700c, 0x7110, + 0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, + 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb01e, 0x0210, + 0x2009, 0xb003, 0x7112, 0x0c50, 0x080c, 0x57d1, 0x00ce, 0x0005, + 0x04a9, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x01d0, 0x2104, + 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, + 0xa188, 0x0003, 0xa182, 0xb01e, 0x0210, 0x2009, 0xb003, 0x7112, + 0x700c, 0xa106, 0x1d40, 0x080c, 0x2744, 0x2001, 0x0138, 0x2102, + 0x0c10, 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x2001, 0x0160, + 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x20e1, 0x9028, + 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x0005, 0x2001, 0x0138, + 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, + 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, + 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, 0x2001, 0x0111, 0x201c, + 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200, + 0x7808, 0xa084, 0xf000, 0xa10d, 0x08c9, 0x2019, 0x5000, 0x8319, + 0x0168, 0x2001, 0xb01e, 0x2004, 0xa086, 0x0000, 0x0138, 0x2001, + 0x0021, 0xd0fc, 0x0da0, 0x080c, 0x1ff4, 0x0c78, 0x20e1, 0x7000, + 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, + 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x7908, + 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0218, 0xa085, 0x0001, 0x0088, + 0x2001, 0x020a, 0x81ff, 0x0130, 0x20e1, 0x6000, 0x200c, 0x200c, + 0x200c, 0x200c, 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, + 0xa006, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, 0x2071, 0xaffd, + 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x01a8, + 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0dc8, 0x7904, + 0xa18c, 0x0780, 0x0016, 0x080c, 0x1a6c, 0x001e, 0x81ff, 0x1118, + 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, 0x001e, 0x00ee, + 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, + 0x0904, 0x1e66, 0x8109, 0x1dd0, 0x2009, 0x0100, 0x210c, 0xa18a, + 0x0003, 0x0a0c, 0x14f6, 0x080c, 0x20f2, 0x00e6, 0x00f6, 0x2071, + 0xafec, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0538, 0x7800, + 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, 0x7834, 0x0006, 0x7838, + 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, 0xe000, 0xe000, 0x2079, + 0x0030, 0x7804, 0xd0ac, 0x190c, 0x14f6, 0x2079, 0x0010, 0x000e, + 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, 0x000e, 0x7832, 0x000e, + 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, 0x00fe, 0x00ee, + 0x7804, 0xd0ac, 0x190c, 0x14f6, 0x080c, 0x6d0d, 0x0005, 0x00e6, + 0x2071, 0xb01e, 0x7003, 0x0000, 0x00ee, 0x0005, 0x00d6, 0xa280, + 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x1ee4, 0x6934, 0xa184, + 0x0007, 0x0002, 0x1e82, 0x1ecf, 0x1e82, 0x1e82, 0x1e82, 0x1eb6, + 0x1e95, 0x1e84, 0x080c, 0x14f6, 0x684c, 0xd0b4, 0x0904, 0x1fcc, + 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, + 0x6880, 0x680e, 0x6958, 0x0804, 0x1ed7, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x001e, 0x1d38, 0x684c, 0xd0b4, 0x0904, 0x1fcc, 0x6860, + 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, + 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, + 0xa080, 0x2186, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, 0x00ff, + 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x1fcc, 0x6804, + 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2186, + 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, 0x684c, + 0xd0b4, 0x0904, 0x1a47, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, + 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2186, 0x2005, 0x6832, + 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, 0x2079, + 0x0020, 0x7804, 0xd0fc, 0x190c, 0x1ff4, 0x00e6, 0x00d6, 0x2071, + 0xb01e, 0x7000, 0xa005, 0x1904, 0x1f4c, 0x00c6, 0x7206, 0xa280, + 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x00d6, + 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, 0x2079, + 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de, + 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, + 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, 0x701a, + 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x1120, + 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, 0x0046, 0x6b14, 0x6c10, + 0x080c, 0x21a6, 0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff, + 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, 0x0126, 0x2091, 0x8000, + 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, 0x0118, 0x2009, 0x0001, + 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, + 0x1fc5, 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04, + 0x1fc4, 0xa705, 0x0904, 0x1fc4, 0xa03e, 0x2730, 0x6850, 0xd0fc, + 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1fa7, 0x1f8c, + 0x1f8c, 0x1fa7, 0x1fa7, 0x1fa0, 0x1fa7, 0x1f8c, 0x1fa7, 0x1f91, + 0x1f91, 0x1fa7, 0x1fa7, 0x1fa7, 0x1f98, 0x1f91, 0xc0fc, 0x6852, + 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805, + 0xac68, 0x6f08, 0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, + 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090, + 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1138, + 0x00de, 0x080c, 0x2148, 0x1904, 0x1f56, 0xa00e, 0x00f0, 0x00de, + 0x080c, 0x14f6, 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, + 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, + 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, + 0x7012, 0x080c, 0x2148, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, + 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x14f6, 0x0026, 0x2001, + 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, + 0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, + 0x0118, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x929c, 0x20e1, + 0x9040, 0x080c, 0x7cb8, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x080c, + 0x6d0d, 0x002e, 0x0804, 0x20ad, 0x0126, 0x2091, 0x2400, 0x0006, + 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, + 0xb01e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, + 0x0700, 0x1920, 0x7000, 0x0002, 0x20ad, 0x2010, 0x2080, 0x20ab, + 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001, + 0x080c, 0x1f50, 0x0904, 0x20ad, 0x2009, 0x0001, 0x080c, 0x1f50, + 0x0804, 0x20ad, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc, + 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, 0x0026, + 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872, + 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, 0x003e, + 0x002e, 0x080c, 0x215e, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, + 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, 0x20ad, + 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, + 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, 0x2019, + 0x1000, 0x8319, 0x090c, 0x14f6, 0x7820, 0xd0bc, 0x1dd0, 0x003e, + 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, + 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012, + 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468, + 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x2004, + 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x1f50, + 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x215e, 0x00d6, + 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, + 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804, + 0x2033, 0x0804, 0x202f, 0x080c, 0x14f6, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, + 0xb01e, 0x7000, 0xa086, 0x0000, 0x0590, 0x2079, 0x0020, 0x0016, + 0x2009, 0x0207, 0x210c, 0xd194, 0x0158, 0x2009, 0x020c, 0x210c, + 0xa184, 0x0003, 0x0128, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, + 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x1110, + 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0d18, 0x080c, 0x1ff4, 0x7000, + 0xa086, 0x0000, 0x19e8, 0x001e, 0x7803, 0x0004, 0x7804, 0xd0ac, + 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee, + 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0xb01e, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, 0x7004, + 0x2060, 0x6010, 0x2068, 0x080c, 0x9596, 0x0158, 0x6850, 0xc0b5, + 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, 0xa206, + 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, + 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0x929c, 0x20e1, + 0x9040, 0x080c, 0x7cb8, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, 0xa205, + 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x1e6e, 0x2001, + 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, + 0x0000, 0x2069, 0xafc7, 0x6833, 0x0000, 0x683f, 0x0000, 0x08f8, + 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a, + 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2186, 0x2045, 0x88ff, + 0x090c, 0x14f6, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, + 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005, + 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, + 0x2196, 0x2045, 0x88ff, 0x090c, 0x14f6, 0x0005, 0x0000, 0x0011, + 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, + 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x217b, + 0x2177, 0x0000, 0x0000, 0x2185, 0x0000, 0x217b, 0x0000, 0x2182, + 0x217f, 0x0000, 0x0000, 0x0000, 0x2185, 0x2182, 0x0000, 0x217d, + 0x217d, 0x0000, 0x0000, 0x2185, 0x0000, 0x217d, 0x0000, 0x2183, + 0x2183, 0x0000, 0x0000, 0x0000, 0x2185, 0x2183, 0x00a6, 0x0096, + 0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, 0x2237, 0x2d60, + 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2186, 0xa986, 0x0007, 0x0130, + 0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, + 0x6060, 0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2237, + 0x6004, 0xa065, 0x0904, 0x2237, 0x0c18, 0x2805, 0xa005, 0x01a8, + 0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, + 0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, + 0x8a51, 0x0904, 0x2237, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, + 0x2237, 0x0830, 0x8a51, 0x0904, 0x2237, 0x8840, 0x2805, 0xa005, + 0x1158, 0x6004, 0xa065, 0x0904, 0x2237, 0x6034, 0xa0cc, 0x000f, + 0xa9c0, 0x2186, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, + 0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, + 0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, + 0x690c, 0x2300, 0xa11b, 0x0a0c, 0x14f6, 0x6800, 0xa420, 0x6804, + 0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, + 0x0a0c, 0x14f6, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, + 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, + 0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, + 0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, + 0xa084, 0x0007, 0x0002, 0x224b, 0x224c, 0x224f, 0x2252, 0x2257, + 0x225a, 0x225f, 0x2264, 0x0005, 0x080c, 0x1ff4, 0x0005, 0x080c, + 0x1a6c, 0x0005, 0x080c, 0x1a6c, 0x080c, 0x1ff4, 0x0005, 0x080c, + 0x16f8, 0x0005, 0x080c, 0x1ff4, 0x080c, 0x16f8, 0x0005, 0x080c, + 0x1a6c, 0x080c, 0x16f8, 0x0005, 0x080c, 0x1a6c, 0x080c, 0x1ff4, + 0x080c, 0x16f8, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, + 0x2071, 0xb280, 0x2069, 0xad00, 0x2009, 0x0004, 0x7912, 0x7817, + 0x0004, 0x080c, 0x2651, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x2283, 0x20e1, + 0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126, + 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2335, 0xa084, 0x0007, + 0x0002, 0x22b3, 0x22a1, 0x22a4, 0x22a7, 0x22ac, 0x22ae, 0x22b0, + 0x22b2, 0x080c, 0x5fb7, 0x0078, 0x080c, 0x5ff0, 0x0060, 0x080c, + 0x5fb7, 0x080c, 0x5ff0, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018, + 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026, + 0x7930, 0xa184, 0x0003, 0x0118, 0x20e1, 0x9040, 0x04a0, 0xa184, + 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, 0x1108, 0x00a0, 0x080c, + 0x574f, 0x1178, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, + 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, + 0x0010, 0x080c, 0x485e, 0x20e1, 0x9010, 0x00a8, 0xa184, 0x00c0, + 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xaffd, 0x080c, + 0x1d22, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0028, 0xa184, 0x0300, + 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005, + 0x0016, 0x00e6, 0x00f6, 0x2071, 0xad00, 0x7128, 0x2001, 0xaf90, + 0x2102, 0x2001, 0xaf98, 0x2102, 0xa182, 0x0211, 0x1218, 0x2009, + 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, + 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, + 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, + 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, + 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x080c, + 0x2651, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x14f6, + 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0xad00, 0x6024, + 0x6026, 0x6053, 0x0030, 0x080c, 0x2690, 0x6050, 0xa084, 0xfe7f, + 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x26a0, 0x60e7, + 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, + 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, 0x001e, + 0x600f, 0x00ff, 0x2001, 0xaf8c, 0x2003, 0x00ff, 0x602b, 0x002f, + 0x012e, 0x0005, 0x2001, 0xad31, 0x2003, 0x0000, 0x2001, 0xad30, + 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x6124, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a, + 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, 0x23a7, 0x238d, 0x2390, + 0x2393, 0x2398, 0x239a, 0x239e, 0x23a2, 0x080c, 0x6699, 0x00b8, + 0x080c, 0x6774, 0x00a0, 0x080c, 0x6774, 0x080c, 0x6699, 0x0078, + 0x0099, 0x0068, 0x080c, 0x6699, 0x0079, 0x0048, 0x080c, 0x6774, + 0x0059, 0x0028, 0x080c, 0x6774, 0x080c, 0x6699, 0x0029, 0x002e, + 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0xd19c, 0x1904, 0x25bf, + 0x080c, 0x574f, 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024, + 0xa084, 0x1800, 0x0178, 0x080c, 0x5775, 0x0118, 0x080c, 0x5761, + 0x1148, 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, 0xaf9d, 0x2003, + 0xaaaa, 0x0458, 0x080c, 0x5775, 0x15d0, 0x6024, 0xa084, 0x1800, + 0x1108, 0x04a8, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, + 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, 0x569a, + 0x0804, 0x25bf, 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4, + 0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x7088, 0xa086, 0x0028, + 0x1110, 0x080c, 0x58da, 0x0804, 0x25bf, 0x2001, 0xaf9e, 0x2003, + 0x0000, 0x0048, 0x2001, 0xaf9e, 0x2003, 0x0002, 0x0020, 0x080c, + 0x584d, 0x0804, 0x25bf, 0x080c, 0x597a, 0x0804, 0x25bf, 0xd1ac, + 0x0904, 0x2507, 0x080c, 0x574f, 0x11d8, 0x6027, 0x0020, 0x0006, + 0x0026, 0x0036, 0x080c, 0x576b, 0x1170, 0x2001, 0xaf9e, 0x2003, + 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, 0x569a, 0x003e, + 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5726, + 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, + 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ca, 0xa48c, + 0xff00, 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x7038, + 0xd084, 0x1148, 0xc085, 0x703a, 0x0036, 0x2418, 0x2011, 0x8016, + 0x080c, 0x3c5c, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7050, 0xa084, + 0x00ff, 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011, + 0xad52, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xad52, + 0x2214, 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248, + 0xa294, 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, + 0x24d2, 0x7034, 0xd08c, 0x1140, 0x2001, 0xad0c, 0x200c, 0xd1ac, + 0x1904, 0x24d2, 0xc1ad, 0x2102, 0x0036, 0x73c8, 0x2011, 0x8013, + 0x080c, 0x3c5c, 0x003e, 0x0804, 0x24d2, 0x7034, 0xd08c, 0x1140, + 0x2001, 0xad0c, 0x200c, 0xd1ac, 0x1904, 0x24d2, 0xc1ad, 0x2102, + 0x0036, 0x73c8, 0x2011, 0x8013, 0x080c, 0x3c5c, 0x003e, 0x7130, + 0xc185, 0x7132, 0x2011, 0xad52, 0x220c, 0xd1a4, 0x01d0, 0x0016, + 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x663f, 0x2019, 0x000e, + 0x080c, 0xa8eb, 0xa484, 0x00ff, 0xa080, 0x2be6, 0x200d, 0xa18c, + 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xa96c, + 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, + 0x080c, 0x2aac, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x080c, 0x4cdc, 0x1110, 0x080c, 0x493a, 0x8108, 0x1f04, + 0x24c9, 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x7adf, + 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, + 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, 0x003e, 0x60e3, 0x0000, + 0x001e, 0x2001, 0xad00, 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c, + 0x1118, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xad22, + 0x2003, 0x0000, 0x6027, 0x0020, 0x080c, 0x5775, 0x1140, 0x0016, + 0x2009, 0x07d0, 0x2011, 0x567b, 0x080c, 0x6593, 0x001e, 0xd194, + 0x0904, 0x25bf, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2570, 0x080c, + 0x6581, 0x080c, 0x7834, 0x6027, 0x0004, 0x00f6, 0x2019, 0xafd0, + 0x2304, 0xa07d, 0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6, + 0x00c6, 0x00e6, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, + 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, + 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a, + 0x080c, 0x6b73, 0x080c, 0x6c50, 0x7810, 0x2070, 0x7037, 0x0103, + 0x2f60, 0x080c, 0x8078, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, + 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, + 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, + 0xafc7, 0x6028, 0xa09a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, + 0x080c, 0x7827, 0x0804, 0x25be, 0x2019, 0xafd0, 0x2304, 0xa065, + 0x0120, 0x2009, 0x0027, 0x080c, 0x80a7, 0x00ce, 0x0804, 0x25be, + 0xd2bc, 0x0904, 0x25be, 0x080c, 0x658e, 0x6014, 0xa084, 0x0184, + 0xa085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, + 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, + 0x00de, 0x00c6, 0x2061, 0xafc7, 0x6044, 0xa09a, 0x00c8, 0x12f0, + 0x8000, 0x6046, 0x603c, 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0, + 0x080c, 0x6586, 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x1138, + 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114, + 0xa18c, 0x0184, 0xa18d, 0x0016, 0x6116, 0x0080, 0x0036, 0x2019, + 0x0001, 0x080c, 0x7a64, 0x003e, 0x2019, 0xafd6, 0x2304, 0xa065, + 0x0120, 0x2009, 0x004f, 0x080c, 0x80a7, 0x00ce, 0x001e, 0xd19c, + 0x0904, 0x261a, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027, + 0x0008, 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x25cd, 0x2091, + 0x6000, 0x1f04, 0x25cd, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, + 0x6052, 0x20a9, 0x0366, 0x1d04, 0x25db, 0x2091, 0x6000, 0x6020, + 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0490, + 0x080c, 0x2760, 0x1f04, 0x25db, 0x015e, 0x6152, 0x001e, 0x6027, + 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, + 0x7adf, 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, 0x79e1, 0x080c, + 0x6581, 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, 0x003e, 0x60e3, + 0x0000, 0x080c, 0xac8d, 0x080c, 0xaca8, 0xa085, 0x0001, 0x080c, + 0x5793, 0x2001, 0xad00, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, + 0x12cc, 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, + 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, + 0x71c0, 0x70c2, 0xa116, 0x01f0, 0x81ff, 0x0128, 0x2011, 0x8011, + 0x080c, 0x3c5c, 0x00b8, 0x2011, 0x8012, 0x080c, 0x3c5c, 0x2001, + 0xad71, 0x2004, 0xd0fc, 0x1170, 0x0036, 0x00c6, 0x080c, 0x26eb, + 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, 0x2aac, + 0x00ce, 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, + 0x0005, 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, 0xa190, + 0x2664, 0x2205, 0x60f2, 0x2011, 0x2671, 0x2205, 0x60ee, 0x002e, + 0x000e, 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, 0x0580, + 0x0420, 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, + 0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, + 0x00ff, 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, + 0x6278, 0x0038, 0xa080, 0x2be6, 0x200d, 0xa18c, 0xff00, 0x810f, + 0xa006, 0x0005, 0xa080, 0x2be6, 0x200d, 0xa18c, 0x00ff, 0x0005, + 0x00d6, 0x2069, 0x0140, 0x2001, 0xad14, 0x2003, 0x00ef, 0x20a9, + 0x0010, 0xa006, 0x6852, 0x6856, 0x1f04, 0x269b, 0x00de, 0x0005, + 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xad14, 0x2102, + 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, + 0xa006, 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xacae, 0x2005, + 0x6856, 0x8211, 0x1f04, 0x26b0, 0x002e, 0x00de, 0x000e, 0x0005, + 0x00c6, 0x2061, 0xad00, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, + 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, + 0x2069, 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, 0x8212, + 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, + 0x680e, 0x1f04, 0x26e0, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, + 0x00de, 0x015e, 0x0005, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0150, + 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, + 0xa96c, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, + 0x78c4, 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520, + 0x2011, 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, 0x2018, + 0x2300, 0x080c, 0x6665, 0x2011, 0x0030, 0x2200, 0x8007, 0xa085, + 0x004c, 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, 0x2009, + 0x0138, 0x200a, 0x080c, 0x574f, 0x1118, 0x2009, 0xaf8e, 0x200a, + 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, + 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, + 0x8000, 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1a6a, 0x002e, + 0x001e, 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, + 0xa082, 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c, + 0x00ff, 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f, + 0x0010, 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, 0x0005, + 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, + 0xd08c, 0x1110, 0x1f04, 0x2767, 0x00fe, 0x015e, 0x000e, 0x0005, + 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, 0x6048, + 0x0006, 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0, + 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, + 0x0006, 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xe000, + 0xe000, 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, + 0x60e2, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, + 0x60ee, 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e, + 0x60e6, 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, 0x080c, + 0x26a0, 0x000e, 0x00ce, 0x001e, 0x0005, 0x2845, 0x2849, 0x284d, + 0x2853, 0x2859, 0x285f, 0x2865, 0x286d, 0x2875, 0x287b, 0x2881, + 0x2889, 0x2891, 0x2899, 0x28a1, 0x28ab, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b7, 0x28b7, 0x28bc, + 0x28bc, 0x28c3, 0x28c3, 0x28ca, 0x28ca, 0x28d3, 0x28d3, 0x28da, + 0x28da, 0x28e3, 0x28e3, 0x28ec, 0x28ec, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, + 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x0106, 0x0006, 0x0804, + 0x28f7, 0x0106, 0x0006, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, + 0x2373, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x0804, + 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, + 0x0006, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, + 0x2373, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, + 0x2373, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, + 0x228f, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x228f, 0x0804, + 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x228f, 0x0804, + 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x228f, 0x0804, + 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x080c, 0x228f, 0x0804, + 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x080c, 0x228f, 0x0804, + 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x223d, 0x080c, + 0x228f, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, + 0x223d, 0x080c, 0x228f, 0x0804, 0x28f7, 0xe000, 0x0cf0, 0x0106, + 0x0006, 0x080c, 0x272f, 0x04d8, 0x0106, 0x0006, 0x080c, 0x272f, + 0x080c, 0x2373, 0x04a0, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, + 0x223d, 0x0468, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, 0x2373, + 0x080c, 0x223d, 0x0420, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, + 0x228f, 0x00e8, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, 0x2373, + 0x080c, 0x228f, 0x00a0, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, + 0x223d, 0x080c, 0x228f, 0x0058, 0x0106, 0x0006, 0x080c, 0x272f, + 0x080c, 0x2373, 0x080c, 0x223d, 0x080c, 0x228f, 0x0000, 0x000e, + 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c, + 0x502d, 0x1904, 0x29d4, 0x72d0, 0x2001, 0xaf9d, 0x2004, 0xa005, + 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x29d4, + 0x080c, 0x29d8, 0x0804, 0x29d4, 0x080c, 0x574f, 0x1120, 0x709b, + 0xffff, 0x0804, 0x29d4, 0xd294, 0x0120, 0x709b, 0xffff, 0x0804, + 0x29d4, 0x2001, 0xad14, 0x203c, 0x7284, 0xd284, 0x0904, 0x2976, + 0xd28c, 0x1904, 0x2976, 0x0036, 0x7398, 0xa38e, 0xffff, 0x1110, + 0x2019, 0x0001, 0x8314, 0xa2e0, 0xb3c0, 0x2c04, 0xa38c, 0x0001, + 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e, + 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230, + 0xd284, 0x1538, 0x7284, 0xc28d, 0x7286, 0x709b, 0xffff, 0x003e, + 0x0428, 0x2009, 0x0000, 0x080c, 0x2676, 0x080c, 0x4c80, 0x11b8, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c, + 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x29eb, 0x0140, 0x0028, + 0x080c, 0x2b1a, 0x080c, 0x2a19, 0x0110, 0x8318, 0x0818, 0x739a, + 0x0010, 0x709b, 0xffff, 0x003e, 0x0804, 0x29d4, 0xa780, 0x2be6, + 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x7098, 0xa096, + 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220, + 0x2008, 0xa802, 0x20a8, 0x0020, 0x709b, 0xffff, 0x0804, 0x29d4, + 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x4cdc, + 0x0120, 0x080c, 0x4c80, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000, + 0xd0bc, 0x11d0, 0x7284, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff, + 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x4c9f, 0x0028, + 0x080c, 0x2b9c, 0x0170, 0x080c, 0x2bc9, 0x0058, 0x080c, 0x2b1a, + 0x080c, 0x2a19, 0x0170, 0x0028, 0x080c, 0x2b9c, 0x0110, 0x0419, + 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2990, 0x709b, 0xffff, + 0x0018, 0x001e, 0x015e, 0x719a, 0x004e, 0x002e, 0x00ce, 0x0005, + 0x00c6, 0x0016, 0x709b, 0x0000, 0x2009, 0x007e, 0x080c, 0x4c80, + 0x1138, 0x080c, 0x2b1a, 0x04a9, 0x0118, 0x70d0, 0xc0bd, 0x70d2, + 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, + 0x2001, 0xad56, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9807, + 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2001, + 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0000, 0x080c, 0x4c30, 0x0126, + 0x2091, 0x8000, 0x7094, 0x8000, 0x7096, 0x012e, 0x2009, 0x0004, + 0x080c, 0x80a7, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, + 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xad56, + 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9807, 0x0550, 0x2d00, + 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140, + 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2ad9, + 0x080c, 0x9956, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, + 0x2001, 0x0002, 0x080c, 0x4c30, 0x0126, 0x2091, 0x8000, 0x7094, + 0x8000, 0x7096, 0x012e, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085, + 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, + 0x2009, 0x0080, 0x080c, 0x4c80, 0x1120, 0x0031, 0x0110, 0x70d7, + 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x2c68, 0x080c, 0x8022, 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9956, + 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, + 0x080c, 0x4c30, 0x0126, 0x2091, 0x8000, 0x70d8, 0x8000, 0x70da, + 0x012e, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085, 0x0001, 0x00ce, + 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x2009, 0x007f, 0x080c, 0x4c80, 0x1190, 0x2c68, 0x080c, + 0x8022, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, + 0x080c, 0x9956, 0x2009, 0x0022, 0x080c, 0x80a7, 0xa085, 0x0001, + 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, + 0x0026, 0x080c, 0x68f3, 0x080c, 0x689d, 0x080c, 0x8a15, 0x2130, + 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1120, 0x080c, + 0x4ecf, 0x080c, 0x493a, 0x001e, 0x8108, 0x1f04, 0x2ac3, 0x86ff, + 0x1110, 0x080c, 0x11d4, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, + 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, + 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039, + 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, 0x007e, 0x001e, + 0x2e60, 0x080c, 0x4ecf, 0x6210, 0x6314, 0x080c, 0x493a, 0x6212, + 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, + 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150, + 0x2071, 0xad00, 0x7094, 0xa005, 0x0110, 0x8001, 0x7096, 0x000e, + 0x00ee, 0x0005, 0x2071, 0xad00, 0x70d8, 0xa005, 0x0dc0, 0x8001, + 0x70da, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, + 0x20a9, 0x0001, 0x0098, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0150, + 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, + 0xa96c, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e, + 0x007e, 0x05c8, 0xa28e, 0x007f, 0x05b0, 0xa28e, 0x0080, 0x0598, + 0xa288, 0xae34, 0x210c, 0x81ff, 0x0570, 0x8fff, 0x05c1, 0x00c6, + 0x2160, 0x2001, 0x0001, 0x080c, 0x5037, 0x00ce, 0x2019, 0x0029, + 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x00c6, + 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x1118, + 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, + 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xa712, 0x001e, 0x007e, + 0x2160, 0x080c, 0x4ecf, 0x002e, 0x8210, 0x1f04, 0x2b3e, 0x015e, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, + 0x0026, 0x0016, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0148, 0xd0a4, + 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xa96c, + 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x7284, 0x82ff, 0x01f8, 0x2011, 0xad52, 0x2214, 0xd2ac, 0x11d0, + 0x2100, 0x080c, 0x268a, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, + 0xa2e0, 0xb3c0, 0x2c04, 0xd384, 0x0120, 0xa084, 0xff00, 0x8007, + 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, 0xa096, 0x00ff, 0x0110, + 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0xa180, 0xae34, + 0x2004, 0xa065, 0x0178, 0x0016, 0x00c6, 0x080c, 0x9807, 0x001e, + 0x090c, 0x14f6, 0x611a, 0x080c, 0x2ad9, 0x080c, 0x8078, 0x001e, + 0x080c, 0x4c9f, 0x012e, 0x00ce, 0x001e, 0x0005, 0x7eef, 0x7de8, + 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, + 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, + 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, + 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, + 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, + 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, + 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, + 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, + 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, + 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, + 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, + 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, + 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, + 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, + 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, + 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, + 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, + 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, + 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, + 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, + 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, + 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, + 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, + 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, + 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, + 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0xad81, + 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033, + 0xad91, 0x7037, 0xad91, 0x7007, 0x0001, 0x2061, 0xadd1, 0x6003, + 0x0002, 0x0005, 0x1004, 0x2d0c, 0x0e04, 0x2d0c, 0x2071, 0xad81, + 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069, + 0x1904, 0x2df1, 0x0804, 0x2d8a, 0x0005, 0x2071, 0xad81, 0x7004, + 0x0002, 0x2d15, 0x2d16, 0x2d1f, 0x2d30, 0x0005, 0x1004, 0x2d1e, + 0x0e04, 0x2d1e, 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78, + 0x2061, 0xadd1, 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200, + 0x0904, 0x2deb, 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, + 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60, + 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210, + 0x61c0, 0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, 0x2de8, 0x61c0, + 0x0804, 0x2d8a, 0x2dcc, 0x2df7, 0x2dff, 0x2e03, 0x2e0b, 0x2e11, + 0x2e15, 0x2e21, 0x2e24, 0x2e2e, 0x2e31, 0x2de8, 0x2de8, 0x2de8, + 0x2e34, 0x2de8, 0x2e43, 0x2e5a, 0x2e71, 0x2ee8, 0x2eed, 0x2f16, + 0x2f67, 0x2f78, 0x2f96, 0x2fcd, 0x2fd7, 0x2fe4, 0x2ff7, 0x3018, + 0x3021, 0x3057, 0x305d, 0x2de8, 0x3086, 0x2de8, 0x2de8, 0x2de8, + 0x2de8, 0x2de8, 0x308d, 0x3097, 0x2de8, 0x2de8, 0x2de8, 0x2de8, + 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x309f, 0x2de8, 0x2de8, 0x2de8, + 0x2de8, 0x2de8, 0x30b1, 0x30b9, 0x2de8, 0x2de8, 0x2de8, 0x2de8, + 0x2de8, 0x2de8, 0x0002, 0x30cb, 0x311f, 0x317a, 0x318a, 0x2de8, + 0x31a4, 0x35cb, 0x3fbb, 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x2de8, + 0x2de8, 0x2de8, 0x2de8, 0x2e2e, 0x2e31, 0x35cd, 0x2de8, 0x35da, + 0x403c, 0x4097, 0x40fb, 0x2de8, 0x415a, 0x4180, 0x419f, 0x2de8, + 0x2de8, 0x2de8, 0x2de8, 0x35de, 0x376b, 0x3785, 0x37a3, 0x3804, + 0x3858, 0x3863, 0x389a, 0x38a9, 0x38b8, 0x38bb, 0x38de, 0x3928, + 0x398e, 0x399b, 0x3a9c, 0x3bb3, 0x3bdc, 0x3cda, 0x3cfc, 0x3d08, + 0x3d41, 0x3e05, 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x3e6d, 0x3e88, + 0x3efa, 0x3fac, 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x3c39, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x2dd8, 0x7818, 0xd084, 0x0110, + 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001, + 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, + 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003, + 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e, + 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3c46, 0x7823, + 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, + 0x7930, 0x0804, 0x3c49, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804, + 0x2dcc, 0x7924, 0x2114, 0x0804, 0x2dcc, 0x2099, 0x0009, 0x20a1, + 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0804, + 0x2dcc, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0001, + 0x2019, 0x001b, 0x783b, 0x0017, 0x0804, 0x2dcc, 0x7d38, 0x7c3c, + 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, 0x1000, 0xe10c, 0xa006, + 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904, + 0x2dcc, 0x0804, 0x2dee, 0x2069, 0xad51, 0x7824, 0x7930, 0xa11a, + 0x1a04, 0x2df4, 0x8019, 0x0904, 0x2df4, 0x684a, 0x6942, 0x782c, + 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x5a1c, + 0x0804, 0x2dcc, 0x2069, 0xad51, 0x7824, 0x7934, 0xa11a, 0x1a04, + 0x2df4, 0x8019, 0x0904, 0x2df4, 0x684e, 0x6946, 0x782c, 0x6862, + 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x50d9, 0x0804, + 0x2dcc, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2df1, 0x7924, 0x7b28, + 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xad88, 0x41a1, 0x080c, 0x3c05, + 0x0904, 0x2df1, 0x2009, 0x0020, 0x080c, 0x3c46, 0x701b, 0x2e89, + 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0120, + 0xa096, 0x0019, 0x1904, 0x2df1, 0x810f, 0xa18c, 0x00ff, 0x0904, + 0x2df1, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3c05, + 0x0904, 0x2df1, 0x2009, 0x0020, 0x2061, 0xadd1, 0x6224, 0x6328, + 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, + 0xa5a9, 0x0000, 0x080c, 0x3c46, 0x701b, 0x2eb7, 0x0005, 0x6834, + 0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, + 0x2df1, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0x4b7c, 0x1128, 0x7007, 0x0003, 0x701b, 0x2ed1, 0x0005, 0x080c, + 0x51df, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xad88, + 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, + 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x3c49, + 0x61a8, 0x7824, 0x60aa, 0x0804, 0x2dcc, 0x2091, 0x8000, 0x7823, + 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, + 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, + 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, + 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, + 0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904, + 0x2df1, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, 0x1904, + 0x2df4, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, + 0x2df4, 0x7c28, 0x7d2c, 0x080c, 0x4e96, 0xd28c, 0x1118, 0x080c, + 0x4e41, 0x0010, 0x080c, 0x4e6f, 0x1518, 0x2061, 0xb400, 0x0126, + 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, + 0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, + 0xace0, 0x0018, 0x2001, 0xad16, 0x2004, 0xac02, 0x1a04, 0x2df1, + 0x0c30, 0x080c, 0x929c, 0x012e, 0x0904, 0x2df1, 0x0804, 0x2dcc, + 0xa00e, 0x2001, 0x0005, 0x080c, 0x51df, 0x0126, 0x2091, 0x8000, + 0x080c, 0x9803, 0x080c, 0x510c, 0x012e, 0x0804, 0x2dcc, 0x81ff, + 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, + 0x0904, 0x2df1, 0x080c, 0x4ea2, 0x0904, 0x2df1, 0x0804, 0x2dcc, + 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x080c, + 0x4f0d, 0x0904, 0x2df1, 0x2019, 0x0005, 0x080c, 0x4ebd, 0x0904, + 0x2df1, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x8003, 0x800b, + 0x810b, 0xa108, 0x080c, 0x6519, 0x0804, 0x2dcc, 0x0126, 0x2091, + 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0448, 0x2029, 0x00ff, + 0x644c, 0x2400, 0xa506, 0x01f0, 0x2508, 0x080c, 0x4cdc, 0x11d0, + 0x080c, 0x4f0d, 0x1128, 0x2009, 0x0002, 0x62b0, 0x2518, 0x00b8, + 0x2019, 0x0004, 0x080c, 0x4ebd, 0x1118, 0x2009, 0x0006, 0x0078, + 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108, + 0x080c, 0x6519, 0x8529, 0x1ae8, 0x012e, 0x0804, 0x2dcc, 0x012e, + 0x0804, 0x2df1, 0x012e, 0x0804, 0x2df4, 0x080c, 0x3c1a, 0x0904, + 0x2df4, 0x080c, 0x4dfc, 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x81ff, + 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4ded, + 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, + 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4e71, 0x0904, 0x2df1, 0x080c, + 0x4bc0, 0x080c, 0x4e3a, 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x080c, + 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x62a0, + 0x2019, 0x0005, 0x00c6, 0x080c, 0x4ecf, 0x2061, 0x0000, 0x080c, + 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2009, 0x0000, + 0x080c, 0xa712, 0x007e, 0x00ce, 0x080c, 0x4e96, 0x0804, 0x2dcc, + 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4e96, 0x2208, 0x0804, + 0x2dcc, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xae13, 0x6810, 0x6914, + 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, + 0x0000, 0x20a9, 0x007e, 0x2069, 0xae34, 0x2d04, 0xa075, 0x0130, + 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04, + 0x3035, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2dcc, + 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c, + 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, + 0xae13, 0x6910, 0x62ac, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, + 0x614c, 0xa190, 0x2be6, 0x2215, 0xa294, 0x00ff, 0x636c, 0x83ff, + 0x0108, 0x6270, 0x67d0, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090, + 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031, + 0x0002, 0x0040, 0x080c, 0x574f, 0x1118, 0x2031, 0x0004, 0x0010, + 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2dcc, 0x613c, 0x6240, + 0x2019, 0xafa3, 0x231c, 0x0804, 0x2dcc, 0x0126, 0x2091, 0x8000, + 0x6134, 0xa006, 0x2010, 0x2018, 0x012e, 0x0804, 0x2dcc, 0x080c, + 0x3c2a, 0x0904, 0x2df4, 0x6244, 0x6338, 0x0804, 0x2dcc, 0x613c, + 0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0xad51, 0x831f, + 0xa305, 0x6816, 0x782c, 0x2069, 0xafa3, 0x2d1c, 0x206a, 0x0804, + 0x2dcc, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x012e, 0x0804, + 0x2dcc, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x7828, 0xa00d, 0x0904, + 0x2df4, 0x782c, 0xa005, 0x0904, 0x2df4, 0x6244, 0x6146, 0x6338, + 0x603a, 0x0804, 0x2dcc, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, + 0x1904, 0x2df1, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, + 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xad14, 0x2004, 0xa085, + 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2be6, 0x210d, + 0xa18c, 0x00ff, 0x2001, 0xad14, 0x2004, 0xa116, 0x0550, 0x810f, + 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x8022, 0x000e, + 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x3c05, + 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x701b, 0x3173, 0x2d00, 0x6012, 0x2009, 0x0032, + 0x080c, 0x80a7, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, + 0x2df1, 0x00ce, 0x0804, 0x2df4, 0x080c, 0x8078, 0x0cb0, 0x2001, + 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x00c6, 0x2061, + 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, + 0x2001, 0xad14, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, + 0x16a0, 0xa188, 0x2be6, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xad14, + 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, + 0x0006, 0x080c, 0x8022, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05, + 0x601f, 0x0001, 0x080c, 0x3c05, 0x01d8, 0x6837, 0x0000, 0x7007, + 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x3173, + 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x80a7, 0x012e, 0x00ce, + 0x0005, 0x012e, 0x00ce, 0x0804, 0x2df1, 0x00ce, 0x0804, 0x2df4, + 0x080c, 0x8078, 0x0cb0, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, + 0x0804, 0x2dcc, 0x2061, 0xb048, 0x0126, 0x2091, 0x8000, 0x6000, + 0xd084, 0x0128, 0x6104, 0x6208, 0x012e, 0x0804, 0x2dcc, 0x012e, + 0x0804, 0x2df4, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x0904, + 0x2df1, 0x0126, 0x2091, 0x8000, 0x6244, 0x6064, 0xa202, 0x0248, + 0xa085, 0x0001, 0x080c, 0x26c0, 0x080c, 0x436e, 0x012e, 0x0804, + 0x2dcc, 0x012e, 0x0804, 0x2df4, 0x0126, 0x2091, 0x8000, 0x7824, + 0xa084, 0x0007, 0x0002, 0x31b6, 0x31bf, 0x31c6, 0x31b3, 0x31b3, + 0x31b3, 0x31b3, 0x31b3, 0x012e, 0x0804, 0x2df4, 0x2009, 0x0114, + 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, 0x332f, 0x0070, 0x2009, + 0x010b, 0x200b, 0x0010, 0x080c, 0x332f, 0x0038, 0x81ff, 0x0128, + 0x012e, 0x2021, 0x400b, 0x0804, 0x2dce, 0x0086, 0x0096, 0x00a6, + 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2009, 0x0101, 0x210c, + 0x0016, 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, + 0x007a, 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, + 0x2058, 0x080c, 0x3570, 0x080c, 0x34da, 0xa03e, 0x2720, 0x00f6, + 0x00e6, 0x00c6, 0x2d60, 0x2071, 0xb01e, 0x2079, 0x0020, 0x00d6, + 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, + 0x783e, 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, + 0x080c, 0x3486, 0x080c, 0x3486, 0x00ce, 0x00ee, 0x00fe, 0x080c, + 0x33d5, 0x080c, 0x34ae, 0x080c, 0x342b, 0x080c, 0x3394, 0x080c, + 0x33c5, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, + 0xa084, 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, + 0x330d, 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, + 0x0100, 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, + 0x7816, 0x080c, 0x330d, 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, + 0x0dc0, 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, + 0x8b58, 0x080c, 0x3317, 0x00fe, 0x0804, 0x32d7, 0x00fe, 0x080c, + 0x330d, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, + 0x2502, 0x080c, 0x3317, 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, + 0x2004, 0xa005, 0x1904, 0x3211, 0x8739, 0x0038, 0x2001, 0xaffd, + 0x2004, 0xa086, 0x0000, 0x1904, 0x3211, 0x2001, 0x0033, 0x2003, + 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, 0x32d7, + 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, 0x32d7, + 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, + 0x1148, 0x2001, 0xaffd, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, + 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, + 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, + 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, + 0x20a9, 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, + 0x2004, 0x1f04, 0x32ac, 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, + 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, + 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, + 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, + 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x31ef, 0x2061, + 0x0100, 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, + 0xa084, 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, + 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, + 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x2dcc, + 0x012e, 0x2021, 0x400c, 0x0804, 0x2dce, 0xa085, 0x0001, 0x1d04, + 0x3316, 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, + 0x0105, 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, + 0x0020, 0x2003, 0x0004, 0x2001, 0xaffd, 0x2003, 0x0000, 0x2001, + 0xb01e, 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, + 0x2079, 0x0100, 0x2001, 0xad14, 0x200c, 0x7932, 0x7936, 0x080c, + 0x26a0, 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, + 0x01f4, 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, + 0x782e, 0x20a9, 0x0046, 0x1d04, 0x334b, 0x2091, 0x6000, 0x1f04, + 0x334b, 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, + 0xa084, 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, + 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, + 0xe000, 0x1f04, 0x3368, 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, + 0x61a8, 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, + 0x7827, 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, + 0x2019, 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, + 0x2003, 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, + 0x7827, 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, + 0x00e6, 0x2071, 0xaffd, 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, + 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, + 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, + 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, + 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, + 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, + 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, + 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, + 0x2009, 0xad14, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, + 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0xa080, + 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0xa006, + 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, + 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, 0x7016, + 0x080c, 0x34ae, 0x080c, 0x330d, 0x1110, 0x8421, 0x0028, 0x7024, + 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, 0xaffd, + 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0120, + 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, 0x080c, + 0x3486, 0x2011, 0x0001, 0x080c, 0x3486, 0x00ee, 0x00fe, 0x7017, + 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xaffd, 0x2079, + 0x0030, 0x7904, 0xd1fc, 0x0904, 0x3483, 0x7803, 0x0002, 0xa026, + 0xd19c, 0x1904, 0x347f, 0x7000, 0x0002, 0x3483, 0x3441, 0x3465, + 0x347f, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, 0x2011, + 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, 0x7820, + 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, 0x200c, + 0x81ff, 0x0de8, 0x080c, 0x33b1, 0x2009, 0x0001, 0x7808, 0xd0ec, + 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, 0xa184, + 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, 0x00b1, + 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, 0x6000, + 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, 0x7803, + 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, 0xa005, + 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, 0x7832, + 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, 0x2804, + 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, 0xa802, + 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, 0x601a, + 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x2071, 0xb01e, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0, + 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x34d6, 0x34c1, + 0x34cd, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c, + 0x3486, 0x0160, 0x080c, 0x3486, 0x0048, 0x8001, 0x7002, 0x7804, + 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x3486, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x601b, + 0x0004, 0x2061, 0x0100, 0x60cf, 0x0400, 0x6004, 0xc0ac, 0xa085, + 0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, + 0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3c05, + 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, + 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, + 0x000d, 0x04a1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3c05, + 0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, + 0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, + 0x0020, 0x2079, 0x0100, 0x6013, 0x0400, 0x20e1, 0x9040, 0x2001, + 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, + 0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006, + 0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, + 0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336, + 0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122, + 0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003, + 0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6, + 0x2d60, 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x6018, 0x2070, 0x2d00, + 0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005, + 0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001, + 0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3c05, 0x2d60, + 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, + 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, + 0x000d, 0x080c, 0x353e, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c, + 0x3c05, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00, + 0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004, + 0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001, + 0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, + 0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027, + 0x0000, 0x2001, 0xaffd, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, + 0x0009, 0x00ee, 0x0005, 0x0804, 0x2dcc, 0x0126, 0x2091, 0x8000, + 0x20a9, 0x0011, 0x2001, 0xad40, 0x20a0, 0xa006, 0x40a4, 0x012e, + 0x0804, 0x2dcc, 0x7d38, 0x7c3c, 0x0804, 0x2e73, 0x080c, 0x3c05, + 0x0904, 0x2df1, 0x080c, 0x574f, 0x0110, 0x080c, 0x491f, 0x2009, + 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, 0x701b, + 0x35f2, 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x2df4, + 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2df4, 0xd094, 0x00c6, + 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218, + 0xa18c, 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c, + 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010, + 0xa18c, 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a, + 0x0002, 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04, + 0x2df4, 0xa288, 0x2be6, 0x210d, 0xa18c, 0x00ff, 0x6156, 0xd0dc, + 0x0130, 0x6828, 0xa08a, 0x007f, 0x1a04, 0x2df4, 0x604e, 0x6808, + 0xa08a, 0x0100, 0x0a04, 0x2df4, 0xa08a, 0x0841, 0x1a04, 0x2df4, + 0xa084, 0x0007, 0x1904, 0x2df4, 0x680c, 0xa005, 0x0904, 0x2df4, + 0x6810, 0xa005, 0x0904, 0x2df4, 0x6848, 0x6940, 0xa10a, 0x1a04, + 0x2df4, 0x8001, 0x0904, 0x2df4, 0x684c, 0x6944, 0xa10a, 0x1a04, + 0x2df4, 0x8001, 0x0904, 0x2df4, 0x6804, 0xd0fc, 0x0560, 0x080c, + 0x3c05, 0x0904, 0x2df1, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3c46, 0x701b, + 0x3672, 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, + 0xad6d, 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xad71, + 0x200c, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085, + 0x0b00, 0x6006, 0x00ce, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xad51, + 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, + 0x00ff, 0x6042, 0x080c, 0x5a1c, 0x080c, 0x5070, 0x080c, 0x50d9, + 0x6000, 0xa086, 0x0000, 0x1904, 0x3755, 0x6808, 0x602a, 0x080c, + 0x22f8, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, + 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, 0xe000, 0xe000, 0x200b, + 0x0000, 0x0036, 0x6b08, 0x080c, 0x26fb, 0x003e, 0x6818, 0x691c, + 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, + 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, + 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff, + 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, + 0x20a9, 0x0004, 0x20a1, 0xafad, 0x40a1, 0x080c, 0x659c, 0x6904, + 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70, + 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, + 0x5fa9, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, + 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, + 0x0010, 0x6003, 0x0001, 0x1f04, 0x36f3, 0x00ce, 0x2069, 0xad51, + 0x2001, 0xaf9d, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170, + 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa, + 0x080c, 0x2744, 0x2001, 0xaf8e, 0x2102, 0x0008, 0x2102, 0x00c6, + 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, + 0x574f, 0x0128, 0x080c, 0x3e5f, 0x0110, 0x080c, 0x26c0, 0x60c4, + 0xa005, 0x01b0, 0x6003, 0x0001, 0x2009, 0x373f, 0x00c0, 0x080c, + 0x574f, 0x1158, 0x2011, 0x566e, 0x080c, 0x650d, 0x2001, 0xaf9e, + 0x2003, 0x0000, 0x080c, 0x569a, 0x0040, 0x080c, 0x485e, 0x0028, + 0x6003, 0x0004, 0x2009, 0x3755, 0x0010, 0x0804, 0x2dcc, 0x2001, + 0x0100, 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004, + 0xa084, 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817, + 0x2091, 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x2df1, + 0x2069, 0xad51, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc, + 0x0118, 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0xa006, 0x080c, 0x26c0, + 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x1178, 0x2001, 0xaf9e, + 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0xa085, 0x0001, + 0x080c, 0x5793, 0x080c, 0x569a, 0x0020, 0x080c, 0x491f, 0x080c, + 0x485e, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, + 0x1110, 0x0804, 0x2df1, 0x6184, 0x81ff, 0x0198, 0x703f, 0x0000, + 0x2001, 0xb3c0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x0126, 0x2091, 0x8000, 0x080c, 0x3c49, 0x701b, 0x2dca, 0x012e, + 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0xb3c0, 0x20a9, 0x0040, + 0x20a1, 0xb3c0, 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x2be6, + 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, + 0xa506, 0x01a8, 0x080c, 0x4cdc, 0x1190, 0x6014, 0x821c, 0x0238, + 0xa398, 0xb3c0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0038, 0xa398, + 0xb3c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, + 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0xa105, + 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0xb3c0, 0x2099, 0xb3c0, + 0x080c, 0x48be, 0x0804, 0x37b0, 0x080c, 0x3c2a, 0x0904, 0x2df4, + 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2df1, 0x2001, 0xad52, 0x2004, 0xd0b4, 0x01f0, 0x6000, 0xd08c, + 0x11d8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x970b, 0x1120, 0x2009, + 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3830, 0x0005, + 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x20a9, 0x002b, 0x2c98, 0xade8, + 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, + 0xad80, 0x0006, 0x20a0, 0x080c, 0x48be, 0x20a9, 0x0004, 0xac80, + 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x48be, 0x2d00, + 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, + 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, + 0x4eab, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x7828, 0xa08a, + 0x1000, 0x1a04, 0x2df4, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x080c, + 0x4f0d, 0x0904, 0x2df1, 0x2019, 0x0004, 0x080c, 0x4ebd, 0x7924, + 0x810f, 0x7a28, 0x0011, 0x0804, 0x2dcc, 0xa186, 0x00ff, 0x0110, + 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xad00, 0x644c, 0x2400, + 0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, + 0x4cdc, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, + 0x6519, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, + 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, 0x4eb4, 0x0804, + 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, + 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, 0x4ea2, 0x0804, 0x2dcc, + 0x6100, 0x0804, 0x2dcc, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x2001, + 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x00d6, 0xace8, + 0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007, + 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, + 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x2dcc, 0x7824, 0xa09c, + 0x00ff, 0xa39a, 0x0003, 0x1a04, 0x2df1, 0x624c, 0xa294, 0x00ff, + 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0xad40, 0x2009, + 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0x81ff, + 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x1904, 0x2df1, 0x00c6, 0x080c, 0x3c05, + 0x00ce, 0x0904, 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x080c, 0x96b7, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3919, + 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, 0xad80, 0x000e, + 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, + 0xa006, 0x080c, 0x26c0, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, + 0x0118, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x0110, 0x080c, + 0x491f, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x7924, 0xa18c, + 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04, + 0x2df4, 0x2100, 0x080c, 0x268a, 0x0026, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x2061, 0xafda, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c, + 0x574f, 0x1178, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, + 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, + 0x00a0, 0x2061, 0x0100, 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, + 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, + 0x002d, 0x2011, 0x4883, 0x080c, 0x6593, 0x7924, 0xa18c, 0xff00, + 0x810f, 0x080c, 0x574f, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, + 0x387d, 0x012e, 0x00ce, 0x002e, 0x0804, 0x2dcc, 0x7924, 0xa18c, + 0xff00, 0x810f, 0x00c6, 0x080c, 0x4c80, 0x2c08, 0x00ce, 0x1904, + 0x2df4, 0x0804, 0x2dcc, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, + 0x2df1, 0x60d0, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, + 0x0804, 0x2df1, 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2df1, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, + 0x701b, 0x39bb, 0x0005, 0x2009, 0x0080, 0x080c, 0x4cdc, 0x1130, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, + 0x0804, 0x2dce, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, + 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3a32, + 0xa0be, 0x0112, 0x0904, 0x3a32, 0xa0be, 0x0113, 0x0904, 0x3a32, + 0xa0be, 0x0114, 0x0904, 0x3a32, 0xa0be, 0x0117, 0x0904, 0x3a32, + 0xa0be, 0x011a, 0x0904, 0x3a32, 0xa0be, 0x011c, 0x0904, 0x3a32, + 0xa0be, 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, + 0x05c8, 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, + 0x8007, 0x6832, 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, + 0x0528, 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, + 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, + 0x01c8, 0x00de, 0x0804, 0x2df4, 0xad80, 0x0010, 0x20a9, 0x0007, + 0x080c, 0x3a78, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3a78, + 0x0048, 0xad80, 0x000c, 0x080c, 0x3a86, 0x0050, 0xad80, 0x000e, + 0x080c, 0x3a86, 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3a78, + 0x00c6, 0x080c, 0x3c05, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837, + 0x0119, 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, + 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, + 0x689b, 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x96d3, 0x1120, + 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3a6f, + 0x0005, 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x2df1, 0x6820, + 0xa086, 0x8001, 0x1904, 0x2dcc, 0x2009, 0x0004, 0x0804, 0x2df1, + 0x0016, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, + 0x280a, 0x8108, 0x1f04, 0x3a7a, 0x001e, 0x0005, 0x0016, 0x00a6, + 0x00b6, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, + 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, + 0x00be, 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x2df1, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d0, + 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2df4, 0xa182, 0x00ff, + 0x1a04, 0x2df4, 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x1140, 0x6070, + 0xa24e, 0x0904, 0x2df4, 0xa9cc, 0xff00, 0x0904, 0x2df4, 0x00c6, + 0x080c, 0x3b58, 0x2c68, 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180, + 0x00c6, 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, 0x4f6e, 0x1108, + 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088, + 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, + 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, + 0x4006, 0x2020, 0x0804, 0x2dce, 0x2d00, 0x7022, 0x0016, 0x00b6, + 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x8022, 0x05d8, 0x2d00, 0x601a, + 0x080c, 0x9956, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3c05, + 0x00ce, 0x2b70, 0x1150, 0x080c, 0x8078, 0x00ee, 0x00ce, 0x00be, + 0x001e, 0x2009, 0x0002, 0x0804, 0x2df1, 0x6837, 0x0000, 0x683b, + 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, + 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2ad9, + 0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, + 0x0002, 0x080c, 0x4c30, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085, + 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3b3f, 0x0005, 0x6830, + 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, + 0xa294, 0x00ff, 0x0804, 0x2df1, 0x2009, 0x0000, 0x080c, 0x4f6e, + 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2dcc, + 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, 0xad34, 0x2004, 0xd0ac, + 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xae34, 0x0030, + 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xaeb4, 0x2e04, 0xa005, + 0x1130, 0x2100, 0xa406, 0x1548, 0x2428, 0xc5fd, 0x0430, 0x2068, + 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600, 0xa206, 0x1190, + 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0540, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x1510, 0x2001, 0x4000, 0x0400, 0x2001, + 0x4007, 0x00e8, 0x2400, 0xa106, 0x1140, 0x6e14, 0x87ff, 0x1110, + 0x86ff, 0x09d0, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, + 0x3b6e, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, + 0x0030, 0x080c, 0x4c80, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005, + 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c05, + 0x0904, 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824, + 0xa005, 0x0904, 0x2df4, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004, + 0x1a04, 0x2df4, 0x2010, 0x2d18, 0x080c, 0x2a8c, 0x0904, 0x2df1, + 0x7007, 0x0003, 0x701b, 0x3bd5, 0x0005, 0x6830, 0xa086, 0x0100, + 0x0904, 0x2df1, 0x0804, 0x2dcc, 0x7924, 0xa18c, 0xff00, 0x810f, + 0x60d0, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2df4, 0xa182, + 0x00ff, 0x1a04, 0x2df4, 0x0126, 0x2091, 0x8000, 0x080c, 0x95c6, + 0x1188, 0xa190, 0xae34, 0x2204, 0xa065, 0x0160, 0x080c, 0x493a, + 0x2001, 0xad34, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, + 0x0804, 0x2dcc, 0x012e, 0x0804, 0x2df1, 0x080c, 0x15d9, 0x0188, + 0xa006, 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, + 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, + 0x000d, 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, + 0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066, + 0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, + 0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff, + 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, + 0x15f0, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, + 0x0010, 0x2031, 0x0000, 0x2061, 0xadd1, 0x6606, 0x6112, 0x600e, + 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1624, 0x7007, + 0x0002, 0x701b, 0x2dcc, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, + 0x2079, 0x0000, 0x2001, 0xad8f, 0x2004, 0xa005, 0x1168, 0x0e04, + 0x3c74, 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b, + 0x0001, 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071, + 0xad81, 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078, + 0x7030, 0xa0e0, 0x0004, 0xac82, 0xadd1, 0x0210, 0x2061, 0xad91, + 0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262, + 0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, + 0x00e6, 0x2071, 0xad81, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x3ccb, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084, + 0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, + 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, + 0x703a, 0xa005, 0x1130, 0x7033, 0xad91, 0x7037, 0xad91, 0x00ce, + 0x0048, 0xac80, 0x0004, 0xa0fa, 0xadd1, 0x0210, 0x2001, 0xad91, + 0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, + 0xad52, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3c5c, + 0x002e, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x0126, 0x2091, 0x8000, + 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x574f, 0x1178, + 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, + 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, 0x0010, 0x080c, + 0x485e, 0x012e, 0x0804, 0x2dcc, 0x7824, 0x2008, 0xa18c, 0xfffd, + 0x1128, 0x61dc, 0xa10d, 0x61de, 0x0804, 0x2dcc, 0x0804, 0x2df4, + 0x81ff, 0x1904, 0x2df1, 0x6000, 0xa086, 0x0003, 0x1904, 0x2df1, + 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1904, 0x2df1, 0x080c, 0x3c2a, + 0x0904, 0x2df4, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, + 0x7828, 0xa005, 0x0904, 0x2dcc, 0x00c6, 0x080c, 0x3c05, 0x00ce, + 0x0904, 0x2df1, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x080c, 0x979c, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, + 0x3d3a, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, 0x0804, + 0x2dcc, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, + 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c05, 0x0904, + 0x2df1, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, + 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x4cdc, 0x1904, + 0x3db4, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4, + 0xff00, 0xa8c6, 0x0600, 0x1904, 0x3db4, 0x2001, 0xad52, 0x2004, + 0xd0ac, 0x1128, 0x080c, 0x4f6e, 0x1110, 0xd79c, 0x05e8, 0xd794, + 0x1110, 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, + 0x0004, 0x53a3, 0x080c, 0x3a86, 0xd794, 0x0148, 0xac80, 0x000a, + 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3a86, 0x21a2, + 0xd794, 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, + 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, + 0x3400, 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3a78, 0xac80, 0x0026, + 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110, + 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xad34, 0x2004, + 0xd0ac, 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, + 0x0100, 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118, + 0xa686, 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x3d5d, + 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x2dcc, 0x702f, 0x0001, + 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xadd1, 0x6007, + 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, + 0x2c10, 0x080c, 0x1624, 0x7007, 0x0002, 0x701b, 0x3df0, 0x0005, + 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, + 0x0000, 0x2061, 0xadd1, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, + 0x3d5d, 0x7120, 0x810b, 0x0804, 0x2dcc, 0x2029, 0x007e, 0x7924, + 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, + 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa184, 0x00ff, 0xa0e2, + 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa284, 0xff00, + 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, + 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, + 0x2df4, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2df4, + 0xa502, 0x0a04, 0x2df4, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04, + 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa484, 0xff00, 0x8007, 0xa0e2, + 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa484, 0x00ff, + 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0x2061, + 0xafa6, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2dcc, 0x0006, + 0x2001, 0xad52, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001, + 0xad71, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6164, 0x7a24, 0x6300, + 0x82ff, 0x1118, 0x7926, 0x0804, 0x2dcc, 0x83ff, 0x1904, 0x2df4, + 0x2001, 0xfff0, 0xa200, 0x1a04, 0x2df4, 0x2019, 0xffff, 0x6068, + 0xa302, 0xa200, 0x0a04, 0x2df4, 0x7926, 0x6266, 0x0804, 0x2dcc, + 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x7c28, + 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3c05, 0x0904, 0x2df1, 0x2009, + 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, + 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xae34, 0x2c64, 0x8cff, 0x01b8, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084, + 0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010, + 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, + 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff, + 0x1120, 0x7120, 0x810c, 0x0804, 0x2dcc, 0x702f, 0x0001, 0x711e, + 0x7020, 0xa300, 0x7022, 0x2061, 0xadd1, 0x6007, 0x0000, 0x6312, + 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c, + 0x1624, 0x7007, 0x0002, 0x701b, 0x3ee6, 0x0005, 0x702c, 0xa005, + 0x1168, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xadd1, + 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x3ea3, 0x7120, 0x810c, + 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x60d0, 0xd0ac, 0x1118, + 0xd09c, 0x0904, 0x2df1, 0x080c, 0x3c05, 0x0904, 0x2df1, 0x7924, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, 0x701b, 0x3f11, + 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148, + 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804, + 0x2df4, 0x6820, 0x6924, 0x080c, 0x2676, 0x1510, 0x080c, 0x4c80, + 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3c05, + 0x01b8, 0x080c, 0x3c05, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, + 0x96ef, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3f4b, 0x0005, + 0x00de, 0x0804, 0x2df1, 0x7120, 0x080c, 0x2bc9, 0x6820, 0xa086, + 0x8001, 0x0904, 0x2df1, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, + 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x48be, 0x000e, + 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xadd1, + 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, + 0xa7c6, 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2df4, 0x2009, + 0x0004, 0x0804, 0x3c49, 0xa7c6, 0x7200, 0x1904, 0x2df4, 0xa6c2, + 0x0054, 0x0a04, 0x2df4, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, + 0x642e, 0x6532, 0x2c10, 0x080c, 0x1624, 0x7007, 0x0002, 0x701b, + 0x3f92, 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, + 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, + 0x48be, 0x000e, 0x2009, 0x002a, 0x2061, 0xadd1, 0x6224, 0x6328, + 0x642c, 0x6530, 0x0804, 0x3c49, 0x81ff, 0x1904, 0x2df1, 0x080c, + 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, + 0x4ec6, 0x0804, 0x2dcc, 0x7824, 0xd084, 0x0904, 0x3804, 0x080c, + 0x3c2a, 0x0904, 0x2df4, 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, + 0x2009, 0x0002, 0x0804, 0x2df1, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, 0x1508, + 0x2001, 0xad52, 0x2004, 0xd0b4, 0x0904, 0x3834, 0x6000, 0xd08c, + 0x1904, 0x3834, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0x970b, 0x1120, 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, + 0x701b, 0x3ff3, 0x0005, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x0804, + 0x3834, 0x2009, 0xad30, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x2df1, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x0120, + 0x2009, 0x0007, 0x0804, 0x2df1, 0x2001, 0xad52, 0x2004, 0xd0ac, + 0x0120, 0x2009, 0x0008, 0x0804, 0x2df1, 0x609c, 0xd0a4, 0x1118, + 0xd0ac, 0x1904, 0x3834, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0x979c, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2df1, 0x7007, 0x0003, 0x701b, 0x402e, 0x0005, 0x6830, 0xa086, + 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2df1, 0x080c, 0x3c2a, + 0x0904, 0x2df4, 0x0804, 0x3fd8, 0x81ff, 0x2009, 0x0001, 0x1904, + 0x2df1, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x2df1, + 0x2001, 0xad52, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x2df1, + 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x2009, 0x0009, 0x1904, 0x2df1, 0x00c6, 0x080c, 0x3c05, + 0x00ce, 0x2009, 0x0002, 0x0904, 0x2df1, 0x6837, 0x0000, 0x6833, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c, + 0x00ff, 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956, + 0x0048, 0xa28e, 0x0100, 0x1904, 0x2df4, 0xc0e5, 0x6853, 0x0000, + 0x6857, 0x0000, 0x683e, 0x080c, 0x9957, 0x2009, 0x0003, 0x0904, + 0x2df1, 0x7007, 0x0003, 0x701b, 0x408e, 0x0005, 0x6830, 0xa086, + 0x0100, 0x2009, 0x0004, 0x0904, 0x2df1, 0x0804, 0x2dcc, 0x81ff, + 0x2009, 0x0001, 0x1904, 0x2df1, 0x6000, 0xa086, 0x0003, 0x2009, + 0x0007, 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2df1, + 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2df1, + 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x080c, 0x3c46, 0x701b, 0x40c5, 0x0005, 0x00d6, 0xade8, 0x000f, + 0x6800, 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808, + 0xa084, 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x2df4, 0x00de, + 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6, + 0x080c, 0x3c2a, 0x1118, 0x00ce, 0x0804, 0x2df4, 0x080c, 0x99a6, + 0x2009, 0x0003, 0x00ce, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, + 0x40f2, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, + 0x2df1, 0x0804, 0x2dcc, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, + 0x2df1, 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, + 0x2df1, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c, + 0x4cdc, 0x1904, 0x2df4, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x2df1, + 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9726, + 0x1120, 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, + 0x413a, 0x0005, 0x6808, 0x8007, 0xa086, 0x0100, 0x1120, 0x2009, + 0x0004, 0x0804, 0x2df1, 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084, + 0x00ff, 0x808e, 0x6814, 0x8007, 0xa084, 0x00ff, 0x8086, 0xa080, + 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x0804, 0x3c49, 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2df1, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, + 0x0110, 0x0804, 0x2df4, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x3c46, 0x701b, 0x4176, 0x0005, 0xad80, 0x000d, + 0x2098, 0x20a9, 0x001a, 0x20a1, 0xafad, 0x53a3, 0x0804, 0x2dcc, + 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804, 0x2df1, 0x7924, + 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, + 0x2df4, 0x2099, 0xafad, 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009, + 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0x7824, + 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x0126, 0x2091, 0x8000, 0x8003, + 0x800b, 0x810b, 0xa108, 0x00c6, 0x2061, 0xafda, 0x6142, 0x00ce, + 0x012e, 0x0804, 0x2dcc, 0x00c6, 0x080c, 0x574f, 0x1188, 0x2001, + 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0xa085, + 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, 0x080c, 0x14f6, 0x0038, + 0x2061, 0xad00, 0x6030, 0xc09d, 0x6032, 0x080c, 0x485e, 0x00ce, + 0x0005, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, + 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x4348, 0x0068, + 0xd08c, 0x0118, 0x080c, 0x4269, 0x0040, 0xd094, 0x0118, 0x080c, + 0x423a, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, + 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, + 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, + 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0xa294, + 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, + 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, + 0x080c, 0x48de, 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0040, + 0x6042, 0x6043, 0x0000, 0x7077, 0x0000, 0x7093, 0x0001, 0x70b7, + 0x0000, 0x70d3, 0x0000, 0x2009, 0xb3c0, 0x200b, 0x0000, 0x7087, + 0x0000, 0x707b, 0x000a, 0x2009, 0x000a, 0x2011, 0x4814, 0x080c, + 0x6593, 0x0005, 0x0156, 0x2001, 0xad73, 0x2004, 0xd08c, 0x0110, + 0x704f, 0xffff, 0x7078, 0xa005, 0x1510, 0x2011, 0x4814, 0x080c, + 0x650d, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, + 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x4251, 0x6242, 0x708b, + 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, + 0x0030, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, 0x0000, 0x015e, + 0x0005, 0x707c, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, + 0x14f6, 0x0005, 0x4275, 0x42c5, 0x4347, 0x00f6, 0x707f, 0x0001, + 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x22f8, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2079, 0xb200, 0x207b, 0x2200, 0x7807, + 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, + 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, + 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0xb20c, 0x207b, + 0x1101, 0x7807, 0x0000, 0x2099, 0xad05, 0x20a1, 0xb20e, 0x20a9, + 0x0004, 0x53a3, 0x2079, 0xb212, 0x207b, 0x0000, 0x7807, 0x0000, + 0x2099, 0xb200, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, + 0x000c, 0x600f, 0x0000, 0x080c, 0x4845, 0x00fe, 0x7083, 0x0000, + 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7080, 0x7083, + 0x0000, 0xa025, 0x0904, 0x432f, 0x6020, 0xd0b4, 0x1904, 0x432d, + 0x7190, 0x81ff, 0x0904, 0x431d, 0xa486, 0x000c, 0x1904, 0x4328, + 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, 0xb280, 0x2019, 0xb200, + 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, 0x1f04, 0x42e0, + 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, + 0x707f, 0x0002, 0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x481b, + 0x080c, 0x6593, 0x0490, 0x2069, 0xb280, 0x6930, 0xa18e, 0x1101, + 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, + 0x6804, 0xa005, 0x0190, 0x2011, 0xb28e, 0x2019, 0xad05, 0x20a9, + 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318, + 0x1f04, 0x4311, 0x0068, 0x7093, 0x0000, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xb280, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, + 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, 0x0005, 0x6040, + 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, + 0x2011, 0xafd1, 0x2013, 0x0000, 0x7083, 0x0000, 0x20e1, 0x9080, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x782b, 0x0c30, 0x0005, + 0x7088, 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x14f6, + 0x0005, 0x437b, 0x438a, 0x43b2, 0x43cb, 0x43ef, 0x4417, 0x443b, + 0x446c, 0x4490, 0x44b8, 0x44ef, 0x4517, 0x4533, 0x4549, 0x4569, + 0x457c, 0x4584, 0x45b1, 0x45d5, 0x45fd, 0x4621, 0x4652, 0x468f, + 0x46be, 0x46da, 0x4719, 0x4739, 0x4752, 0x4753, 0x00c6, 0x2061, + 0xad00, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, + 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, + 0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x481b, 0x080c, + 0x6593, 0x0005, 0x00f6, 0x7080, 0xa086, 0x0014, 0x1508, 0x6043, + 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xb280, 0x7a30, 0xa296, + 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128, + 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x2011, 0x481b, 0x080c, + 0x650d, 0x708b, 0x0010, 0x080c, 0x4584, 0x0010, 0x080c, 0x485e, + 0x00fe, 0x0005, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x481b, + 0x080c, 0x650d, 0x080c, 0x48c6, 0x20a3, 0x1102, 0x20a3, 0x0000, + 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x43c2, 0x60c3, 0x0014, + 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, 0x2011, + 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xb280, + 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, + 0x0004, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b, + 0x0005, 0x080c, 0x48c6, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xb28e, 0x080c, 0x4917, 0x1160, 0x7074, 0xa005, 0x1148, + 0x714c, 0xa186, 0xffff, 0x0128, 0x080c, 0x47df, 0x0110, 0x080c, + 0x48f5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, + 0x7080, 0xa005, 0x01f0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, + 0x0014, 0x11a8, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1103, 0x1178, + 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, + 0x1110, 0x70b7, 0x0001, 0x708b, 0x0006, 0x0029, 0x0010, 0x080c, + 0x485e, 0x00fe, 0x0005, 0x708b, 0x0007, 0x080c, 0x48c6, 0x20a3, + 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xb28e, 0x080c, 0x4917, + 0x11a8, 0x7074, 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, + 0xa180, 0x2be6, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x47df, + 0x0128, 0x080c, 0x3e66, 0x0110, 0x080c, 0x26c0, 0x20a9, 0x0008, + 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, + 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, + 0xb280, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, + 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, + 0x708b, 0x0008, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, + 0x708b, 0x0009, 0x080c, 0x48c6, 0x20a3, 0x1105, 0x20a3, 0x0100, + 0x3430, 0x080c, 0x4917, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c, + 0x4754, 0x1170, 0xa085, 0x0001, 0x080c, 0x26c0, 0x20a9, 0x0008, + 0x2099, 0xb28e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x4845, 0x0010, 0x080c, 0x436e, 0x0005, + 0x00f6, 0x7080, 0xa005, 0x0588, 0x2011, 0x481b, 0x080c, 0x650d, + 0xa086, 0x0014, 0x1540, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1105, + 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, 0x000a, + 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b4, + 0xa005, 0x1110, 0x70b7, 0x0001, 0x7087, 0x0000, 0x708b, 0x000e, + 0x080c, 0x4569, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b, + 0x000b, 0x2011, 0xb20e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, + 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x48c6, + 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, 0x4917, 0x0118, 0x2013, + 0x0000, 0x0020, 0x7050, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, + 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4845, 0x0005, 0x00f6, + 0x7080, 0xa005, 0x01b0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, + 0x0084, 0x1168, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1106, 0x1138, + 0x7834, 0xa005, 0x1120, 0x708b, 0x000c, 0x0029, 0x0010, 0x080c, + 0x485e, 0x00fe, 0x0005, 0x708b, 0x000d, 0x080c, 0x48c6, 0x20a3, + 0x1107, 0x20a3, 0x0000, 0x2099, 0xb28e, 0x20a9, 0x0040, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4845, + 0x0005, 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x481b, 0x080c, + 0x650d, 0xa086, 0x0084, 0x1188, 0x2079, 0xb280, 0x7a30, 0xa296, + 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c, + 0x48b8, 0x708b, 0x000e, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, + 0x0005, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, 0xbc85, 0x608f, + 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, + 0x481b, 0x080c, 0x6501, 0x0005, 0x7080, 0xa005, 0x0120, 0x2011, + 0x481b, 0x080c, 0x650d, 0x0005, 0x708b, 0x0011, 0x080c, 0x4917, + 0x1188, 0x716c, 0x81ff, 0x0170, 0x2009, 0x0000, 0x7070, 0xa084, + 0x00ff, 0x080c, 0x2676, 0xa186, 0x0080, 0x0120, 0x2011, 0xb28e, + 0x080c, 0x47df, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280, + 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, + 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4845, + 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, 0x2011, 0x481b, 0x080c, + 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xb280, 0x7a30, 0xa296, + 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, + 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, 0x0012, 0x0029, + 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b, 0x0013, 0x080c, + 0x48d2, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xb28e, + 0x080c, 0x4917, 0x1160, 0x7074, 0xa005, 0x1148, 0x714c, 0xa186, + 0xffff, 0x0128, 0x080c, 0x47df, 0x0110, 0x080c, 0x48f5, 0x20a9, + 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, + 0x01f0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, + 0x2079, 0xb280, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, + 0x0001, 0x708b, 0x0014, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, + 0x0005, 0x708b, 0x0015, 0x080c, 0x48d2, 0x20a3, 0x1104, 0x20a3, + 0x0000, 0x3430, 0x2011, 0xb28e, 0x080c, 0x4917, 0x11a8, 0x7074, + 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, 0xa180, 0x2be6, + 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x47df, 0x0128, 0x080c, + 0x3e66, 0x0110, 0x080c, 0x26c0, 0x20a9, 0x0008, 0x2298, 0x26a0, + 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, + 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05b8, 0x2011, 0x481b, + 0x080c, 0x650d, 0xa086, 0x0014, 0x1570, 0x2079, 0xb280, 0x7a30, + 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148, + 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, + 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, + 0x1110, 0x70b7, 0x0001, 0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0138, + 0x2001, 0xad73, 0x2004, 0xd0a4, 0x1110, 0x70d3, 0x0008, 0x708b, + 0x0016, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280, 0x20a1, 0x020b, 0x20a9, + 0x000e, 0x53a6, 0x3430, 0x2011, 0xb28e, 0x708b, 0x0017, 0x080c, + 0x4917, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c, 0x4754, 0x1170, + 0xa085, 0x0001, 0x080c, 0x26c0, 0x20a9, 0x0008, 0x2099, 0xb28e, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x080c, 0x4845, 0x0010, 0x080c, 0x436e, 0x0005, 0x00f6, 0x7080, + 0xa005, 0x01b0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0084, + 0x1168, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, + 0xa005, 0x1120, 0x708b, 0x0018, 0x0029, 0x0010, 0x080c, 0x485e, + 0x00fe, 0x0005, 0x708b, 0x0019, 0x080c, 0x48d2, 0x20a3, 0x1106, + 0x20a3, 0x0000, 0x3430, 0x2099, 0xb28e, 0x2039, 0xb20e, 0x27a0, + 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4917, 0x11e8, 0x2728, 0x2514, + 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, + 0xa205, 0x202a, 0x7050, 0x2310, 0x8214, 0xa2a0, 0xb20e, 0x2414, + 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, + 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4845, + 0x0005, 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x481b, 0x080c, + 0x650d, 0xa086, 0x0084, 0x1188, 0x2079, 0xb280, 0x7a30, 0xa296, + 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c, + 0x48b8, 0x708b, 0x001a, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, + 0x0005, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, + 0xb280, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, + 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, + 0x4845, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xad52, + 0x252c, 0x20a9, 0x0008, 0x2041, 0xb20e, 0x28a0, 0x2099, 0xb28e, + 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, + 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, + 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4769, 0x0804, 0x47d7, + 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, + 0xa1a6, 0x3fff, 0x0904, 0x47d7, 0xa18d, 0xc000, 0x20a9, 0x0010, + 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, + 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, + 0x0008, 0x8318, 0x1f04, 0x478f, 0x04d0, 0x23a8, 0x2021, 0x0001, + 0x8426, 0x8425, 0x1f04, 0x47a1, 0x2328, 0x8529, 0xa2be, 0x0007, + 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, + 0xa5a8, 0x0010, 0x1f04, 0x47b0, 0x754e, 0xa5c8, 0x2be6, 0x292d, + 0xa5ac, 0x00ff, 0x7572, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, + 0x26a0, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, + 0x201a, 0x7077, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006, + 0x0018, 0xa006, 0x080c, 0x14f6, 0x009e, 0x008e, 0x0005, 0x2118, + 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, + 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, + 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, + 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, 0x714e, 0xa1a0, + 0x2be6, 0x242d, 0xa5ac, 0x00ff, 0x7572, 0x6532, 0x6536, 0x0016, + 0x2508, 0x080c, 0x26a0, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7077, + 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, 0xad00, 0x707b, + 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, + 0x0140, 0x080c, 0x7834, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, + 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000, 0x2071, 0xad22, + 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, + 0x48de, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, + 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x2011, 0xafd1, 0x2013, 0x0000, 0x7083, 0x0000, 0x012e, 0x20e1, + 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x782b, 0x2009, + 0x07d0, 0x2011, 0x481b, 0x080c, 0x6593, 0x0005, 0x0016, 0x0026, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x2009, 0x00f7, 0x080c, 0x48de, + 0x2061, 0xafda, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xad00, + 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2009, 0x002d, 0x2011, 0x4883, 0x080c, 0x6501, 0x012e, 0x00ce, + 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x0100, 0x080c, 0x7834, 0x2071, 0x0140, 0x7004, 0xa084, + 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x5757, + 0x01a8, 0x080c, 0x5775, 0x1190, 0x2001, 0xaf9d, 0x2003, 0xaaaa, + 0x0016, 0x080c, 0x2744, 0x2001, 0xaf8e, 0x2102, 0x001e, 0x2001, + 0xaf9e, 0x2003, 0x0000, 0x080c, 0x569a, 0x0030, 0x2001, 0x0001, + 0x080c, 0x261e, 0x080c, 0x485e, 0x012e, 0x000e, 0x00ee, 0x0005, + 0x20a9, 0x0040, 0x20a1, 0xb3c0, 0x2099, 0xb28e, 0x3304, 0x8007, + 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x48be, 0x0005, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2099, 0xb200, 0x20a1, 0x020b, 0x20a9, 0x000c, + 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280, + 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006, + 0x2061, 0x0100, 0x810f, 0x2001, 0xad30, 0x2004, 0xa005, 0x1138, + 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185, + 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001, + 0xad52, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xa96c, 0x2001, 0xad0c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x2009, 0x0000, 0x080c, 0x2aac, 0x004e, 0x001e, 0x0005, + 0x080c, 0x485e, 0x708b, 0x0000, 0x7083, 0x0000, 0x0005, 0x0006, + 0x2001, 0xad0c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, + 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, + 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9, + 0x00ff, 0x2009, 0xae34, 0xa006, 0x200a, 0x8108, 0x1f04, 0x4934, + 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, + 0xad51, 0xa006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, + 0xa198, 0x2be6, 0x231d, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, + 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, + 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, + 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, + 0x607e, 0x6082, 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, + 0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, + 0x15f0, 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x15f0, + 0x60ab, 0x0000, 0x00de, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, + 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e, + 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6944, 0x6e48, + 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, 0x4a49, 0xa18c, 0xff00, + 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4a4e, 0x2001, 0xad0c, 0x2004, + 0xa084, 0x0003, 0x01c0, 0x2001, 0xad0c, 0x2004, 0xd084, 0x1904, + 0x4a31, 0xa188, 0xae34, 0x2104, 0xa065, 0x0904, 0x4a31, 0x6004, + 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4a31, 0x6000, 0xd0c4, + 0x0904, 0x4a31, 0x0068, 0xa188, 0xae34, 0x2104, 0xa065, 0x0904, + 0x4a15, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4a1a, + 0x60a4, 0xa00d, 0x0118, 0x080c, 0x4ef9, 0x05d0, 0x60a8, 0xa00d, + 0x0188, 0x080c, 0x4f43, 0x1170, 0x694c, 0xd1fc, 0x1118, 0x080c, + 0x4c11, 0x0448, 0x080c, 0x4bd3, 0x694c, 0xd1ec, 0x1520, 0x080c, + 0x4ded, 0x0408, 0x694c, 0xa184, 0xa000, 0x0178, 0xd1ec, 0x0140, + 0xd1fc, 0x0118, 0x080c, 0x4dfc, 0x0028, 0x080c, 0x4dfc, 0x0028, + 0xd1fc, 0x0118, 0x080c, 0x4bd3, 0x0070, 0x6050, 0xa00d, 0x0130, + 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0028, 0x2d00, 0x6052, + 0x604e, 0x6803, 0x0000, 0x080c, 0x67c5, 0xa006, 0x012e, 0x0005, + 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, 0x2001, 0x0028, 0x2009, + 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, 0x2001, 0xad34, 0x2004, + 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, 0x6100, 0xd1fc, 0x0904, + 0x49d0, 0x2001, 0x0029, 0x2009, 0x1000, 0x0420, 0x2001, 0x0028, + 0x00a8, 0x2009, 0xad0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, + 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0060, 0x2009, 0x0000, + 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, + 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, + 0x1a04, 0x4aa8, 0xa188, 0xae34, 0x2104, 0xa065, 0x01c0, 0x6004, + 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, 0x2c70, 0x080c, 0x8022, + 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x600b, 0xffff, 0x601f, + 0x000a, 0x2009, 0x0003, 0x080c, 0x80a7, 0xa006, 0x0460, 0x2001, + 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, 0x2001, 0xad34, 0x2004, + 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x09e8, + 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, + 0x2009, 0xad0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, + 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, + 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, + 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0000, + 0x2079, 0xad00, 0x6944, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, + 0x1a04, 0x4b77, 0x2001, 0xad0c, 0x2004, 0xa084, 0x0003, 0x1904, + 0x4b65, 0x080c, 0x4cdc, 0x1180, 0x6004, 0xa084, 0x00ff, 0xa082, + 0x0006, 0x1250, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1904, 0x4b60, + 0x60a0, 0xd0bc, 0x1904, 0x4b60, 0x6864, 0xa0c6, 0x006f, 0x0118, + 0x2008, 0x0804, 0x4b28, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f, + 0x78d0, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff, + 0x16b8, 0x6a70, 0x6b6c, 0x786c, 0xa306, 0x1160, 0x7870, 0xa24e, + 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208, + 0x2310, 0x0430, 0x080c, 0x3b58, 0x2c70, 0x0550, 0x2009, 0x0000, + 0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c, + 0x4f6e, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e, + 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, + 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, + 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0458, + 0x080c, 0x8022, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011, + 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0x9956, 0x2d00, 0x6012, + 0x601f, 0x0001, 0xa006, 0xd88c, 0x0110, 0x2001, 0x4000, 0x683a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x2ad9, 0x012e, 0x2001, 0x0000, + 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c, 0x4c30, 0x2009, 0x0002, + 0x080c, 0x80a7, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005, + 0x2001, 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xad0c, 0x210c, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001, + 0x0029, 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff, + 0xa082, 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, + 0x12e0, 0xa188, 0xae34, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, + 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c, + 0x4dfc, 0x04c9, 0x0030, 0x04b9, 0x684c, 0xd0fc, 0x0110, 0x080c, + 0x4ded, 0x080c, 0x4e3a, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, + 0x0000, 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20, + 0x2001, 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009, + 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005, + 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a, + 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, + 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005, + 0x0170, 0x00e6, 0x2071, 0xafc7, 0x7004, 0xa086, 0x0002, 0x0168, + 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, + 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80, + 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800, + 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c, + 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, + 0x0005, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a, + 0x6086, 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6, + 0x0026, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110, + 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005, + 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, + 0xa086, 0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xad52, + 0x2004, 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, + 0x1110, 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206, + 0x0006, 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c, + 0x14f6, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, + 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178, + 0x609c, 0xd0a4, 0x0160, 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1138, + 0xa284, 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, + 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, + 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, + 0xae34, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15c0, + 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, + 0x60ab, 0x0000, 0x080c, 0x493a, 0xa006, 0x002e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, + 0x0480, 0x00d6, 0xa190, 0xae34, 0x2204, 0xa06d, 0x0540, 0x2013, + 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c, + 0x15f0, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x15f0, 0x00ce, 0x00de, + 0x00d6, 0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, + 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0x1600, 0x080c, + 0x8078, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x15f0, 0x00de, + 0xa006, 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, + 0xa085, 0x0001, 0x0030, 0xa188, 0xae34, 0x2104, 0xa065, 0x0dc0, + 0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, + 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x574f, + 0x1538, 0x60a0, 0xa086, 0x007e, 0x2069, 0xb290, 0x0130, 0x2001, + 0xad34, 0x2004, 0xd0ac, 0x11e0, 0x0098, 0x2d04, 0xd0e4, 0x01c0, + 0x00d6, 0x2069, 0xb28e, 0x00c6, 0x2061, 0xaf9f, 0x6810, 0x2062, + 0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, + 0x8d69, 0x2d04, 0x2069, 0x0140, 0x6886, 0x2069, 0xad00, 0x68a2, + 0x2069, 0xb28e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, + 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, 0xb296, 0xac88, 0x000a, + 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xb29a, 0xac88, 0x0006, + 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xb2ae, 0x6808, 0x606a, + 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211, + 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, + 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, + 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, + 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, + 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e, + 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0xb28d, 0x2e04, + 0x6896, 0x2071, 0xb28e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00, + 0x2009, 0xad71, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, + 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008, + 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540, + 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010, + 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x4da8, 0x080c, + 0x14f6, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, 0x15d9, 0x01a8, + 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, + 0x200b, 0xffff, 0x8108, 0x1f04, 0x4dc0, 0x6807, 0x0001, 0x6e12, + 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, + 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800, + 0xa005, 0x1160, 0x080c, 0x4ef9, 0x1168, 0x200b, 0xffff, 0x6804, + 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x15f0, + 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x080c, 0x4f56, 0x0010, 0x080c, 0x4bc0, 0x080c, 0x4e71, 0x1dd8, + 0x080c, 0x4e3a, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282, + 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, + 0xffff, 0x0128, 0x8108, 0x1f04, 0x4e0e, 0x080c, 0x14f6, 0x260a, + 0x8210, 0x6a56, 0x0098, 0x080c, 0x15d9, 0x01d0, 0x2d00, 0x60aa, + 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, + 0x8108, 0x1f04, 0x4e26, 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, + 0x4c11, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, + 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x080c, 0x67c5, 0x012e, + 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, + 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01e8, + 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, + 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, + 0x6a00, 0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, + 0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, + 0x0010, 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, + 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, + 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, + 0x6a00, 0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, + 0x2202, 0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, + 0x4ef3, 0x1110, 0x2011, 0x0001, 0x080c, 0x4f3d, 0x1110, 0xa295, + 0x0002, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, 0x964b, 0x0010, + 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, 0x95e4, + 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, + 0x962e, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, + 0x080c, 0x9600, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, + 0x0118, 0x080c, 0x9667, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, + 0x0006, 0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800, + 0x0006, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, + 0x0006, 0x6000, 0xd0fc, 0x0110, 0x080c, 0xac03, 0x000e, 0x080c, + 0x510c, 0x000e, 0x0c50, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, + 0x000e, 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, + 0x0005, 0x00e6, 0x2170, 0x7000, 0xa005, 0x1160, 0x20a9, 0x0010, + 0xae88, 0x0004, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x4f02, + 0xa085, 0x0001, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x15d9, 0x01a0, 0x2d00, + 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, + 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x4f21, 0xa085, 0x0001, + 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x15f0, + 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, + 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, + 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, + 0x1f04, 0x4f4c, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, + 0x6854, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, + 0x15f0, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, + 0x0005, 0x00f6, 0x080c, 0x574f, 0x01b0, 0x71b4, 0x81ff, 0x1198, + 0x71d0, 0xd19c, 0x0180, 0x2001, 0x007e, 0xa080, 0xae34, 0x2004, + 0xa07d, 0x0148, 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, + 0x7800, 0xc0ed, 0x7802, 0x2079, 0xad51, 0x7804, 0xd0a4, 0x01e8, + 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, + 0x4cdc, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, + 0x0118, 0xa086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, + 0x8108, 0x1f04, 0x4f96, 0x00ce, 0x015e, 0x080c, 0x502d, 0x0120, + 0x2001, 0xafa2, 0x200c, 0x0038, 0x2079, 0xad51, 0x7804, 0xd0a4, + 0x0130, 0x2009, 0x07d0, 0x2011, 0x4fc1, 0x080c, 0x6593, 0x00fe, + 0x0005, 0x2011, 0x4fc1, 0x080c, 0x650d, 0x080c, 0x502d, 0x01f0, + 0x2001, 0xaeb2, 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, + 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, + 0x4fc1, 0x080c, 0x6593, 0x00e6, 0x2071, 0xad00, 0x706f, 0x0000, + 0x7073, 0x0000, 0x080c, 0x28fa, 0x00ee, 0x04b0, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1530, + 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, + 0xa006, 0x2009, 0x0029, 0x080c, 0xa96c, 0x6000, 0xc0e5, 0xc0ec, + 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, + 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, + 0x2009, 0x0000, 0x080c, 0xa712, 0x007e, 0x004e, 0x001e, 0x8108, + 0x1f04, 0x4fec, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, + 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac, + 0x0005, 0x7818, 0x2004, 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xaeb2, + 0x2004, 0xa07d, 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, + 0x0026, 0x2091, 0x8000, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, + 0xc2fc, 0x6202, 0x002e, 0x012e, 0x0005, 0x2071, 0xae13, 0x7003, + 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, + 0x0000, 0x701f, 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, + 0x0000, 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, + 0xaf7c, 0x7003, 0xae13, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, + 0xaf5c, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, + 0x0016, 0x00e6, 0x2071, 0xaf34, 0xa00e, 0x7186, 0x718a, 0x7097, + 0x0001, 0x2001, 0xad52, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xad52, + 0x2004, 0xa00e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x50d6, + 0x2001, 0xad71, 0x200c, 0xa184, 0x000f, 0x2009, 0xad72, 0x210c, + 0x0002, 0x507e, 0x50b1, 0x50b8, 0x50c2, 0x50c7, 0x507e, 0x507e, + 0x507e, 0x50a1, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e, + 0x507e, 0x7003, 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xad75, + 0x20a1, 0xaf85, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, + 0x0428, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, + 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, + 0x0001, 0x0088, 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, + 0x0121, 0x2001, 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, + 0xff00, 0x8007, 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, + 0x0005, 0x00e6, 0x2071, 0xae13, 0x684c, 0xa005, 0x1130, 0x7028, + 0xc085, 0x702a, 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, + 0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, + 0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, + 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, + 0x2100, 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, + 0x0001, 0xa006, 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, + 0xd0fc, 0x1904, 0x5165, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, + 0xad00, 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, + 0x81ff, 0x1dc8, 0x702e, 0x70b0, 0xa200, 0x70b2, 0x00de, 0x2071, + 0xae13, 0x701c, 0xa005, 0x1904, 0x5175, 0x20a9, 0x0032, 0x0f04, + 0x5173, 0x0e04, 0x512f, 0x2071, 0xaf34, 0x7200, 0x82ff, 0x05d8, + 0x6934, 0xa186, 0x0103, 0x1904, 0x5183, 0x6948, 0x6844, 0xa105, + 0x1540, 0x2009, 0x8020, 0x2200, 0x0002, 0x5173, 0x514a, 0x519b, + 0x51a7, 0x5173, 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5173, + 0x7018, 0xd084, 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, + 0x701b, 0x0001, 0x2091, 0x4080, 0x2071, 0xad00, 0x702c, 0x206a, + 0x2d00, 0x702e, 0x70b0, 0x8000, 0x70b2, 0x002e, 0x00ee, 0x015e, + 0x0005, 0x6844, 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, + 0x2009, 0x8020, 0x0880, 0x2071, 0xae13, 0x2d08, 0x206b, 0x0000, + 0x7010, 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, + 0x0008, 0x711e, 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, + 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc, + 0x0d10, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009, + 0x8021, 0x0804, 0x5143, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98, + 0x7186, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x7084, + 0x8008, 0xa092, 0x000f, 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003, + 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, + 0x0a04, 0x515c, 0x718c, 0x7084, 0xa10a, 0x0a04, 0x515c, 0x2071, + 0x0000, 0x7018, 0xd084, 0x1904, 0x515c, 0x2071, 0xaf34, 0x7000, + 0xa086, 0x0002, 0x1150, 0x080c, 0x5426, 0x2071, 0x0000, 0x701b, + 0x0001, 0x2091, 0x4080, 0x0804, 0x515c, 0x080c, 0x5450, 0x2071, + 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x515c, 0x0006, + 0x684c, 0x0006, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, + 0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, + 0x000e, 0x684a, 0x6952, 0x0005, 0x2071, 0xae13, 0x7004, 0x0002, + 0x5202, 0x5213, 0x5411, 0x5412, 0x541f, 0x5425, 0x5203, 0x5402, + 0x5398, 0x53ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5212, + 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, + 0x700b, 0x0000, 0x012e, 0x2069, 0xafda, 0x683c, 0xa005, 0x03f8, + 0x11f0, 0x0126, 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, + 0xae1f, 0x2004, 0xa10a, 0x0170, 0x0e04, 0x5236, 0x2069, 0x0000, + 0x6818, 0xd084, 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, + 0x2091, 0x4080, 0x2069, 0xafda, 0x683f, 0xffff, 0x012e, 0x2069, + 0xad00, 0x6844, 0x6964, 0xa102, 0x2069, 0xaf34, 0x688a, 0x6984, + 0x701c, 0xa06d, 0x0120, 0x81ff, 0x0904, 0x528c, 0x00a0, 0x81ff, + 0x0904, 0x5352, 0x2071, 0xaf34, 0x7184, 0x7088, 0xa10a, 0x1258, + 0x7190, 0x2071, 0xafda, 0x7038, 0xa005, 0x0128, 0x1b04, 0x5352, + 0x713a, 0x0804, 0x5352, 0x2071, 0xaf34, 0x718c, 0x0126, 0x2091, + 0x8000, 0x7084, 0xa10a, 0x0a04, 0x536d, 0x0e04, 0x530e, 0x2071, + 0x0000, 0x7018, 0xd084, 0x1904, 0x530e, 0x2001, 0xffff, 0x2071, + 0xafda, 0x703a, 0x2071, 0xaf34, 0x7000, 0xa086, 0x0002, 0x1150, + 0x080c, 0x5426, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, + 0x0804, 0x530e, 0x080c, 0x5450, 0x2071, 0x0000, 0x701b, 0x0001, + 0x2091, 0x4080, 0x0804, 0x530e, 0x2071, 0xaf34, 0x7000, 0xa005, + 0x0904, 0x5334, 0x6934, 0xa186, 0x0103, 0x1904, 0x5311, 0x684c, + 0xd0bc, 0x1904, 0x5334, 0x6948, 0x6844, 0xa105, 0x1904, 0x5329, + 0x2009, 0x8020, 0x2071, 0xaf34, 0x7000, 0x0002, 0x5334, 0x52f4, + 0x52cc, 0x52de, 0x52ab, 0x0136, 0x0146, 0x0156, 0x2099, 0xad75, + 0x20a1, 0xaf85, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, + 0x2071, 0xaf7c, 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, + 0x0002, 0x700b, 0x0000, 0x2e10, 0x080c, 0x1624, 0x2071, 0xae13, + 0x7007, 0x0009, 0x0804, 0x5352, 0x7084, 0x8008, 0xa092, 0x001e, + 0x1a04, 0x5352, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, + 0x2071, 0xae13, 0x080c, 0x54a7, 0x0804, 0x5352, 0x7084, 0x8008, + 0xa092, 0x000f, 0x1a04, 0x5352, 0xae90, 0x0003, 0x8003, 0xa210, + 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xae13, + 0x080c, 0x54a7, 0x0804, 0x5352, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x530e, 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, + 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, + 0x2071, 0xae13, 0x080c, 0x54a7, 0x0804, 0x5352, 0x012e, 0x0804, + 0x5352, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, + 0x0118, 0xa18e, 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, + 0xa084, 0x00ff, 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, + 0x52a2, 0x6844, 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, + 0x2009, 0x8020, 0x0804, 0x52a2, 0x2071, 0xae13, 0x080c, 0x54b9, + 0x01c8, 0x2071, 0xae13, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, + 0xa086, 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, + 0x710e, 0x7007, 0x0003, 0x080c, 0x54d2, 0x7050, 0xa086, 0x0100, + 0x0904, 0x5412, 0x0126, 0x2091, 0x8000, 0x2071, 0xae13, 0x7008, + 0xa086, 0x0001, 0x1180, 0x0e04, 0x536b, 0x2009, 0x000d, 0x7030, + 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, + 0x1110, 0x7007, 0x0001, 0x012e, 0x0005, 0x2071, 0xae13, 0x080c, + 0x54b9, 0x0518, 0x2071, 0xaf34, 0x7084, 0x700a, 0x20a9, 0x0020, + 0x2099, 0xaf35, 0x20a1, 0xaf5c, 0x53a3, 0x7087, 0x0000, 0x2071, + 0xae13, 0x2069, 0xaf7c, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, + 0x682e, 0x7078, 0x6832, 0x2d10, 0x080c, 0x1624, 0x7007, 0x0008, + 0x2001, 0xffff, 0x2071, 0xafda, 0x703a, 0x012e, 0x0804, 0x5352, + 0x2069, 0xaf7c, 0x6808, 0xa08e, 0x0000, 0x0904, 0x53ed, 0xa08e, + 0x0200, 0x0904, 0x53eb, 0xa08e, 0x0100, 0x1904, 0x53ed, 0x0126, + 0x2091, 0x8000, 0x0e04, 0x53e9, 0x2069, 0x0000, 0x6818, 0xd084, + 0x15c0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, + 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, + 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, + 0x0000, 0x2001, 0xaf59, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, + 0xaf34, 0x689c, 0x699e, 0x2069, 0xafda, 0xa102, 0x1118, 0x683c, + 0xa005, 0x1368, 0x2001, 0xaf5a, 0x200c, 0x810d, 0x693e, 0x0038, + 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, + 0x0001, 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xaf7e, + 0x2004, 0xa08e, 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x54a7, + 0x0005, 0xa08e, 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, + 0x0005, 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x54b9, 0x0140, + 0x7007, 0x0003, 0x080c, 0x54d2, 0x7050, 0xa086, 0x0100, 0x0110, + 0x0005, 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, + 0x0030, 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, + 0x5475, 0x7006, 0x080c, 0x54a7, 0x0005, 0x0005, 0x00e6, 0x0156, + 0x2071, 0xaf34, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, + 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, + 0x544a, 0x2014, 0x722a, 0x8000, 0x0f04, 0x544a, 0x2014, 0x722e, + 0x8000, 0x0f04, 0x544a, 0x2014, 0x723a, 0x8000, 0x0f04, 0x544a, + 0x2014, 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, + 0x00e6, 0x0156, 0x2071, 0xaf34, 0x7184, 0x81ff, 0x01d8, 0xa006, + 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, + 0x8000, 0x2014, 0x722a, 0x8000, 0x0f04, 0x546c, 0x2014, 0x723a, + 0x8000, 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, + 0x8042, 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, + 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, + 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, + 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x54a1, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, + 0x2001, 0x0001, 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, + 0x0005, 0x2001, 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, + 0xa06d, 0x0170, 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, + 0x2d04, 0x701e, 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x15f0, + 0x0005, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, + 0x230c, 0xa10e, 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, + 0xa102, 0x1118, 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, + 0x8002, 0x0005, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, + 0x0000, 0x0126, 0x2091, 0x8000, 0x2009, 0xafec, 0x2104, 0xc08d, + 0x200a, 0x012e, 0x080c, 0x163c, 0x0005, 0x7088, 0xa08a, 0x0029, + 0x1220, 0xa082, 0x001d, 0x0033, 0x0010, 0x080c, 0x14f6, 0x6027, + 0x1e00, 0x0005, 0x55c1, 0x555b, 0x5571, 0x5595, 0x55b4, 0x55e6, + 0x55f8, 0x5571, 0x55d2, 0x54ff, 0x552d, 0x54fe, 0x0005, 0x00d6, + 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, + 0x708b, 0x0028, 0x2069, 0xafac, 0x2d04, 0x7002, 0x080c, 0x584d, + 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, 0x708b, 0x0028, 0x2069, + 0xafac, 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, + 0x0036, 0x0046, 0x0056, 0x2071, 0xaffd, 0x080c, 0x1d22, 0x005e, + 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, + 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708b, 0x0028, + 0x2069, 0xafac, 0x2d04, 0x7002, 0x080c, 0x58da, 0x6028, 0xa085, + 0x0600, 0x602a, 0x00b0, 0x708b, 0x0028, 0x2069, 0xafac, 0x2d04, + 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, + 0x0056, 0x2071, 0xaffd, 0x080c, 0x1d22, 0x005e, 0x004e, 0x003e, + 0x00ee, 0x00de, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1180, + 0x080c, 0x5663, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1cc, 0x0140, + 0x708b, 0x0020, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, + 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x11c8, 0xd1dc, 0x11a0, + 0xd1e4, 0x1178, 0xa184, 0x1e00, 0x11b8, 0x60e3, 0x0001, 0x600c, + 0xc0b4, 0x600e, 0x080c, 0x577f, 0x6803, 0x0080, 0x708b, 0x0028, + 0x0058, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, 0x0028, 0x708b, + 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c, + 0xc0b4, 0x600e, 0x080c, 0x577f, 0x6803, 0x0080, 0x6124, 0xd1d4, + 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0xa184, 0x1e00, 0x1158, + 0x708b, 0x0028, 0x0040, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d, + 0x0010, 0x708b, 0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1dc, + 0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001d, + 0x0005, 0x080c, 0x568d, 0x6124, 0xd1dc, 0x1158, 0x080c, 0x5663, + 0xd1d4, 0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, + 0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, 0x1160, 0xd1cc, + 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028, + 0x708b, 0x001d, 0x0010, 0x708b, 0x0021, 0x0005, 0x080c, 0x568d, + 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, + 0x001e, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005, + 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, + 0x1128, 0xd1e4, 0x0158, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, + 0x0028, 0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x0016, + 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, + 0x2071, 0xad00, 0x2091, 0x8000, 0x080c, 0x574f, 0x11e8, 0x2001, + 0xad0c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, 0x6027, 0x0200, + 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, 0x6803, 0x00a0, 0x2001, + 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x0428, + 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x576b, 0x0150, 0x080c, + 0x5761, 0x1138, 0x2001, 0x0001, 0x080c, 0x261e, 0x080c, 0x5726, + 0x00a0, 0x080c, 0x568a, 0x0178, 0x2001, 0x0001, 0x080c, 0x261e, + 0x7088, 0xa086, 0x001e, 0x0120, 0x7088, 0xa086, 0x0022, 0x1118, + 0x708b, 0x0025, 0x0010, 0x708b, 0x0021, 0x012e, 0x00ee, 0x00de, + 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, + 0x566e, 0x080c, 0x6501, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, + 0x0016, 0x080c, 0x7834, 0x2071, 0xad00, 0x080c, 0x560f, 0x001e, + 0x00fe, 0x00ee, 0x0005, 0x2001, 0xad00, 0x2004, 0xa086, 0x0004, + 0x0140, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, + 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6803, 0x00c0, 0x0156, + 0x20a9, 0x002d, 0x1d04, 0x5692, 0x2091, 0x6000, 0x1f04, 0x5692, + 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0xad00, 0x2001, 0xaf9e, 0x200c, 0xa186, 0x0000, + 0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, + 0x0003, 0x0158, 0x0804, 0x5714, 0x708b, 0x0022, 0x0040, 0x708b, + 0x0021, 0x0028, 0x708b, 0x0023, 0x0020, 0x708b, 0x0024, 0x6043, + 0x0000, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, + 0x26cb, 0x0026, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, + 0x080c, 0x7ae9, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, + 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, + 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0118, 0x012e, 0x015e, 0x04d0, + 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130, + 0x6803, 0x0100, 0x1f04, 0x56e2, 0x080c, 0x57a0, 0x012e, 0x015e, + 0x080c, 0x5761, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006, + 0xa085, 0x0020, 0x6052, 0x080c, 0x57a0, 0xa006, 0x8001, 0x1df0, + 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x57a0, + 0x2001, 0xaf9e, 0x2003, 0x0004, 0x080c, 0x54e5, 0x080c, 0x5761, + 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, 0xaf9e, + 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xad00, 0x2001, + 0xaf9d, 0x2003, 0x0000, 0x2001, 0xaf8e, 0x2003, 0x0000, 0x708b, + 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, 0x080c, + 0x26cb, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, + 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, + 0x2001, 0xaf9d, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, 0x0006, + 0x2001, 0xad71, 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, 0x000e, + 0x0005, 0x0006, 0x2001, 0xad71, 0x2004, 0xa084, 0x0030, 0xa086, + 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xad71, 0x2004, 0xa084, + 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0xad71, + 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, 0x2001, + 0xad0c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x26eb, 0x0036, 0x0016, + 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2aac, 0x001e, 0x003e, + 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xad0c, 0x2e04, 0x0118, + 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, 0x0005, + 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, + 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, + 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, + 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, 0x0000, + 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x26cb, 0x6800, 0xa084, + 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, 0x6052, 0x6050, + 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xad00, 0x6020, 0xa084, + 0x0080, 0x0138, 0x2001, 0xad0c, 0x200c, 0xc1bd, 0x2102, 0x0804, + 0x5845, 0x2001, 0xad0c, 0x200c, 0xc1bc, 0x2102, 0x6028, 0xa084, + 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, 0x20a9, 0x0384, + 0x6024, 0xd0cc, 0x1518, 0x1d04, 0x57f8, 0x2091, 0x6000, 0x1f04, + 0x57f8, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c, + 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c, + 0x7a64, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, + 0xad00, 0x2003, 0x0001, 0xa085, 0x0001, 0x0438, 0x60e3, 0x0000, + 0x2001, 0xaf8e, 0x2004, 0x080c, 0x26cb, 0x60e2, 0x6803, 0x0080, + 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, + 0xa10c, 0x0138, 0x1d04, 0x582a, 0x2091, 0x6000, 0x1f04, 0x582a, + 0x0840, 0x6028, 0xa085, 0x1e00, 0x602a, 0x70a0, 0xa005, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, + 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, + 0x2069, 0x0140, 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, + 0x1904, 0x58a1, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, + 0x2001, 0x0000, 0x080c, 0x26cb, 0x2069, 0x0200, 0x6804, 0xa005, + 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, + 0x6027, 0x0400, 0x2069, 0xafac, 0x7000, 0x206a, 0x708b, 0x0026, + 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5884, 0x2091, 0x6000, + 0x1f04, 0x5884, 0x0804, 0x58d2, 0x2069, 0x0140, 0x20a9, 0x0384, + 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0530, + 0xa084, 0x1a00, 0x1518, 0x1d04, 0x5890, 0x2091, 0x6000, 0x1f04, + 0x5890, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c, + 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c, + 0x7a64, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, + 0xad00, 0x2003, 0x0001, 0xa085, 0x0001, 0x00a0, 0x6803, 0x0080, + 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a0, 0xa005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0x2001, 0xaf8e, 0x2004, 0x080c, 0x26cb, + 0x60e2, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, 0x6020, 0xa084, 0x00c0, + 0x01f0, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c, + 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c, + 0x7a64, 0x2069, 0x0140, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, + 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x0804, 0x5972, 0x2001, + 0xad0c, 0x200c, 0xd1b4, 0x1150, 0xc1b5, 0x2102, 0x080c, 0x5663, + 0x2069, 0x0140, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, + 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, 0x01b8, 0x6028, 0xa084, + 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, 0xafac, 0x7000, 0x206a, + 0x708b, 0x0027, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x592e, + 0x2091, 0x6000, 0x1f04, 0x592e, 0x04e8, 0x6027, 0x1e00, 0x2009, + 0x1e00, 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, + 0x1d04, 0x5935, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, + 0x64a2, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, + 0xafda, 0x7018, 0x00ee, 0xa005, 0x1d00, 0x01e0, 0x0026, 0x2011, + 0x566e, 0x080c, 0x650d, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, + 0x70a0, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, + 0xaf8e, 0x2004, 0x080c, 0x26cb, 0x60e2, 0x2001, 0xad0c, 0x200c, + 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, + 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, 0x7130, 0xd184, 0x1180, + 0x2011, 0xad52, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, + 0xad52, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x59df, + 0x7130, 0xc185, 0x7132, 0x2011, 0xad52, 0x220c, 0xd1a4, 0x0530, + 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x663f, 0x2019, + 0x000e, 0x080c, 0xa8eb, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, + 0xa186, 0x007e, 0x0170, 0xa186, 0x0080, 0x0158, 0x080c, 0x4cdc, + 0x1140, 0x8127, 0xa006, 0x0016, 0x2009, 0x000e, 0x080c, 0xa96c, + 0x001e, 0x8108, 0x1f04, 0x59b0, 0x015e, 0x001e, 0xd1ac, 0x1148, + 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2aac, 0x001e, + 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x4cdc, + 0x1110, 0x080c, 0x493a, 0x8108, 0x1f04, 0x59d6, 0x015e, 0x2011, + 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, + 0x79e1, 0x080c, 0x6581, 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, + 0x003e, 0x60e3, 0x0000, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, + 0x569a, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0005, 0x2071, 0xade1, 0x7003, 0x0000, 0x7007, 0x0000, 0x700f, + 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001, 0x705f, + 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000, 0x708f, + 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, 0xade1, 0x6848, + 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0428, + 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a, 0x685c, + 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009, 0x000c, + 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, + 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a, + 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005, 0x2b78, + 0x2071, 0xade1, 0x7004, 0x0043, 0x700c, 0x0002, 0x5a5b, 0x5a52, + 0x5a52, 0x5a52, 0x5a52, 0x0005, 0x5ab1, 0x5ab2, 0x5ae4, 0x5ae5, + 0x5aaf, 0x5b33, 0x5b38, 0x5b69, 0x5b6a, 0x5b85, 0x5b86, 0x5b87, + 0x5b88, 0x5b89, 0x5b8a, 0x5c40, 0x5c67, 0x700c, 0x0002, 0x5a74, + 0x5aaf, 0x5aaf, 0x5ab0, 0x5ab0, 0x7830, 0x7930, 0xa106, 0x0120, + 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8, 0x1210, + 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, 0x15c0, 0x01b0, + 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000, + 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xafec, 0x2104, 0xc085, + 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x163c, 0x0005, 0x080c, + 0x15c0, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x15c0, 0x1108, 0x0c10, + 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x08f8, 0x0005, + 0x0005, 0x0005, 0x700c, 0x0002, 0x5ab9, 0x5abc, 0x5aca, 0x5ae3, + 0x5ae3, 0x080c, 0x5a6d, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, + 0x0006, 0x080c, 0x5f90, 0x0120, 0x2091, 0x8000, 0x080c, 0x5a6d, + 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x5f90, 0x7058, + 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, + 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, 0x00db, 0x012e, 0x0005, + 0x012e, 0x080c, 0x5b8b, 0x0005, 0x0005, 0x0005, 0x00e6, 0x2071, + 0xade1, 0x700c, 0x0002, 0x5af0, 0x5af0, 0x5af0, 0x5af2, 0x5af5, + 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, 0x0002, 0x00ee, + 0x0005, 0x5b8b, 0x5b8b, 0x5ba7, 0x5b8b, 0x5d22, 0x5b8b, 0x5b8b, + 0x5b8b, 0x5b8b, 0x5b8b, 0x5ba7, 0x5d64, 0x5da7, 0x5df0, 0x5e04, + 0x5b8b, 0x5b8b, 0x5bc3, 0x5ba7, 0x5b8b, 0x5b8b, 0x5c1d, 0x5ead, + 0x5ec8, 0x5b8b, 0x5bc3, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5c13, + 0x5ec8, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, + 0x5b8b, 0x5b8b, 0x5bd7, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, + 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, + 0x5b8b, 0x5b8b, 0x5bec, 0x7020, 0x2068, 0x080c, 0x15f0, 0x0005, + 0x700c, 0x0002, 0x5b3f, 0x5b42, 0x5b50, 0x5b68, 0x5b68, 0x080c, + 0x5a6d, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, + 0x5f90, 0x0120, 0x2091, 0x8000, 0x080c, 0x5a6d, 0x00de, 0x0048, + 0x0126, 0x8001, 0x700e, 0x080c, 0x5f90, 0x7058, 0x2068, 0x7084, + 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, + 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, 0x0005, 0x012e, 0x0419, + 0x0005, 0x0005, 0x0005, 0x5b8b, 0x5ba7, 0x5d0e, 0x5b8b, 0x5ba7, + 0x5b8b, 0x5ba7, 0x5ba7, 0x5b8b, 0x5ba7, 0x5d0e, 0x5ba7, 0x5ba7, + 0x5ba7, 0x5ba7, 0x5ba7, 0x5b8b, 0x5ba7, 0x5d0e, 0x5b8b, 0x5b8b, + 0x5ba7, 0x5b8b, 0x5b8b, 0x5b8b, 0x5ba7, 0x0005, 0x0005, 0x0005, + 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x510c, 0x012e, + 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x7007, + 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, + 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x510c, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0988, + 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x5cd0, 0x7007, 0x0006, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5cd0, 0x0005, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x0904, 0x5b99, 0x8001, 0x1120, 0x7007, + 0x0001, 0x0804, 0x5ced, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, + 0x701a, 0x704b, 0x5ced, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, + 0xa086, 0x0001, 0x1904, 0x5b99, 0x7007, 0x0001, 0x2009, 0xad30, + 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853, + 0x0000, 0x080c, 0x4ab1, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, + 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x510c, 0x012e, 0x0ca0, + 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, 0xa086, 0x00c0, + 0x1120, 0x7007, 0x0001, 0x0804, 0x5ee0, 0x2d00, 0x7016, 0x701a, + 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, 0xae0c, 0x53a3, + 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x5bb5, 0x6a84, 0xa28a, + 0x0002, 0x1a04, 0x5bb5, 0x82ff, 0x1138, 0x6888, 0x698c, 0xa105, + 0x0118, 0x2001, 0x5ca3, 0x0018, 0xa280, 0x5c99, 0x2005, 0x70c6, + 0x7010, 0xa015, 0x0904, 0x5c85, 0x080c, 0x15c0, 0x1118, 0x7007, + 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x2c05, 0x6836, + 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, 0xa00e, 0x2200, + 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0108, 0xa108, + 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, 0x1624, 0x7090, + 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, 0x7007, 0x0010, + 0x0005, 0x7020, 0x2068, 0x080c, 0x15f0, 0x7014, 0x2068, 0x0804, + 0x5bb5, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, + 0x2068, 0x6906, 0x711a, 0x0804, 0x5c40, 0x7014, 0x2068, 0x7007, + 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, 0xa105, 0x0108, + 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0904, 0x5ee0, + 0x04b8, 0x5c9b, 0x5c9f, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, + 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x00f6, + 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, 0x6804, 0x2060, + 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, + 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, + 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0c78, 0x6004, + 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x2009, 0xad30, 0x210c, 0x81ff, 0x1198, 0x6838, 0xa084, 0x00ff, + 0x683a, 0x080c, 0x4993, 0x1108, 0x0005, 0x080c, 0x51df, 0x0126, + 0x2091, 0x8000, 0x080c, 0x97fd, 0x080c, 0x510c, 0x012e, 0x0ca0, + 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0xad30, 0x210c, + 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01b0, 0x6838, 0xa084, 0x00ff, + 0x683a, 0x6853, 0x0000, 0x080c, 0x4a55, 0x1108, 0x0005, 0x0126, + 0x2091, 0x8000, 0x080c, 0x51df, 0x080c, 0x510c, 0x012e, 0x0cb0, + 0x2001, 0x0028, 0x0ca0, 0x2001, 0x0000, 0x0c88, 0x7018, 0x6802, + 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, + 0x7007, 0x0006, 0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, + 0x080f, 0x0005, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, + 0x6848, 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0, + 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0178, 0xa005, + 0x11f0, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, 0x11b8, + 0x0066, 0x6e50, 0x080c, 0x4dcf, 0x006e, 0x0088, 0x0046, 0x2011, + 0xad0c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x4cdc, + 0x1110, 0x080c, 0x4f2d, 0x8108, 0x1f04, 0x5d4e, 0x00ce, 0x684c, + 0xd084, 0x1118, 0x080c, 0x15f0, 0x0005, 0x0126, 0x2091, 0x8000, + 0x080c, 0x510c, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, + 0x0001, 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0580, 0x2061, 0xb048, + 0x6100, 0xd184, 0x0178, 0x6858, 0xa084, 0x00ff, 0x1550, 0x6000, + 0xd084, 0x0520, 0x6004, 0xa005, 0x1538, 0x6003, 0x0000, 0x600b, + 0x0000, 0x00c8, 0x2011, 0x0001, 0x6860, 0xa005, 0x1110, 0x2001, + 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0178, 0x6006, + 0x6858, 0x8007, 0xa084, 0x00ff, 0x0148, 0x600a, 0x6858, 0x8000, + 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x5f7f, 0x012e, 0x0804, + 0x5f79, 0x012e, 0x0804, 0x5f73, 0x012e, 0x0804, 0x5f76, 0x0126, + 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xad52, 0x2004, 0xd0a4, + 0x05e0, 0x2061, 0xb048, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, + 0xd08c, 0x1530, 0x6c48, 0xa484, 0x0003, 0x0170, 0x6958, 0xa18c, + 0x00ff, 0x8001, 0x1120, 0x2100, 0xa210, 0x0620, 0x0028, 0x8001, + 0x1508, 0x2100, 0xa212, 0x02f0, 0xa484, 0x000c, 0x0188, 0x6958, + 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x1120, 0x2100, 0xa318, + 0x0288, 0x0030, 0xa082, 0x0004, 0x1168, 0x2100, 0xa31a, 0x0250, + 0x6860, 0xa005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, + 0x0804, 0x5f7f, 0x012e, 0x0804, 0x5f7c, 0x012e, 0x0804, 0x5f79, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xb048, 0x6300, + 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, + 0x5f8d, 0x012e, 0x0804, 0x5f7c, 0x0126, 0x00c6, 0x2091, 0x8000, + 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0xb048, + 0x6000, 0xa084, 0xfcff, 0x6002, 0x00ce, 0x0448, 0x6858, 0xa005, + 0x05d0, 0x685c, 0xa065, 0x0598, 0x2001, 0xad30, 0x2004, 0xa005, + 0x0118, 0x080c, 0x974e, 0x0068, 0x6013, 0x0400, 0x6057, 0x0000, + 0x694c, 0xd1a4, 0x0110, 0x6950, 0x6156, 0x2009, 0x0041, 0x080c, + 0x80a7, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x1140, 0x0026, + 0x2009, 0x0000, 0x2011, 0xfdff, 0x080c, 0x663f, 0x002e, 0x684c, + 0xd0c4, 0x0148, 0x2061, 0xb048, 0x6000, 0xd08c, 0x1120, 0x6008, + 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x5f7f, 0x00ce, + 0x012e, 0x0804, 0x5f79, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, + 0x002d, 0x0d28, 0xa186, 0x0045, 0x0510, 0xa186, 0x002a, 0x1130, + 0x2001, 0xad0c, 0x200c, 0xc194, 0x2102, 0x08c8, 0xa186, 0x0020, + 0x0170, 0xa186, 0x0029, 0x1d18, 0x6944, 0xa18c, 0xff00, 0x810f, + 0x080c, 0x4cdc, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c, + 0xa065, 0x09a8, 0x2001, 0xafa3, 0x2004, 0x6016, 0x0800, 0x685c, + 0xa065, 0x0968, 0x00e6, 0x6860, 0xa075, 0x2001, 0xad30, 0x2004, + 0xa005, 0x0150, 0x080c, 0x974e, 0x8eff, 0x0118, 0x2e60, 0x080c, + 0x974e, 0x00ee, 0x0804, 0x5e3f, 0x6020, 0xc0dc, 0xc0d5, 0x6022, + 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, + 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x67a8, + 0x080c, 0x6c50, 0x00ee, 0x0804, 0x5e3f, 0x2061, 0xb048, 0x6000, + 0xd084, 0x0190, 0xd08c, 0x1904, 0x5f8d, 0x0126, 0x2091, 0x8000, + 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x5f8d, 0x012e, + 0x6853, 0x0016, 0x0804, 0x5f86, 0x6853, 0x0007, 0x0804, 0x5f86, + 0x6834, 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5b99, 0x0078, + 0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, + 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5ee0, 0x0005, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2009, 0xad30, 0x210c, 0x81ff, + 0x1904, 0x5f5b, 0x2009, 0xad0c, 0x210c, 0xd194, 0x1904, 0x5f63, + 0x6848, 0x2070, 0xae82, 0xb400, 0x0a04, 0x5f4f, 0x2001, 0xad16, + 0x2004, 0xae02, 0x1a04, 0x5f4f, 0x2061, 0xb048, 0x6100, 0xa184, + 0x0301, 0xa086, 0x0001, 0x15a8, 0x711c, 0xa186, 0x0006, 0x15b0, + 0x7018, 0xa005, 0x0904, 0x5f5b, 0x2004, 0xd0e4, 0x1904, 0x5f5e, + 0x7020, 0xd0dc, 0x1904, 0x5f66, 0x6853, 0x0000, 0x6803, 0x0000, + 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, 0x1904, + 0x5f69, 0x2e60, 0x080c, 0x65aa, 0x012e, 0x00ee, 0x0005, 0x2068, + 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x15c8, + 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, 0x0006, 0x0804, + 0x5f86, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, 0x6944, 0xa18c, + 0xff00, 0x810f, 0x080c, 0x4cdc, 0x11c8, 0x6000, 0xd0e4, 0x11b0, + 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, 0x0088, 0x6853, + 0x0008, 0x0070, 0x6853, 0x000e, 0x0058, 0x6853, 0x0017, 0x0040, + 0x6853, 0x0035, 0x0028, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029, + 0x012e, 0x00ee, 0x0418, 0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045, + 0x0cb8, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x080c, 0xa566, + 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, + 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, + 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x0126, 0x2091, + 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x080c, 0x15f0, 0x0005, + 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x7072, + 0x7038, 0x7076, 0x0058, 0x7070, 0xa080, 0x0040, 0x7072, 0x1230, + 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, + 0x0005, 0x00d6, 0x080c, 0x65a1, 0x00de, 0x0005, 0x00d6, 0x2011, + 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1, + 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118, + 0xa086, 0x1000, 0x1540, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, + 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x1118, 0x080c, 0x61c6, + 0x00b0, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84, + 0x0007, 0x1188, 0xac82, 0xb400, 0x0270, 0x6858, 0xac02, 0x1258, + 0x6120, 0xd1f4, 0x1160, 0x2009, 0x0047, 0x080c, 0x80a7, 0x7a1c, + 0xd284, 0x1968, 0x0005, 0xa016, 0x080c, 0x1824, 0x0cc0, 0x0cd8, + 0x781c, 0xd08c, 0x0500, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, + 0x3d20, 0x3e28, 0xa584, 0x0076, 0x1530, 0xa484, 0x7000, 0xa086, + 0x1000, 0x11a8, 0x080c, 0x604e, 0x01f0, 0x20e1, 0x3000, 0x7828, + 0x7828, 0x080c, 0x606a, 0x014e, 0x013e, 0x015e, 0x2009, 0xafcf, + 0x2104, 0xa005, 0x1108, 0x0005, 0x080c, 0x6c50, 0x0ce0, 0xa484, + 0x7000, 0x1518, 0x0499, 0x01b8, 0x7000, 0xa084, 0xff00, 0xa086, + 0x8100, 0x0d18, 0x0080, 0xd5a4, 0x0158, 0x080c, 0x1d86, 0x20e1, + 0x9010, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0048, + 0x00e9, 0x6883, 0x0000, 0x080c, 0xac59, 0x20e1, 0x3000, 0x7828, + 0x7828, 0x014e, 0x013e, 0x015e, 0x08b0, 0x0081, 0x1130, 0x7000, + 0xa084, 0xff00, 0xa086, 0x8100, 0x1d70, 0x080c, 0xac59, 0x20e1, + 0x3000, 0x7828, 0x7828, 0x080c, 0x642d, 0x0c58, 0xa484, 0x01ff, + 0x6882, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, + 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, 0x20a9, + 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, + 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007, + 0xa196, 0x0000, 0x1118, 0x0804, 0x62cf, 0x0005, 0xa196, 0x2000, + 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x41d1, 0x0ca8, + 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x6372, 0x0c68, + 0x00c6, 0x6a80, 0x82ff, 0x0904, 0x61c0, 0x7110, 0xa18c, 0xff00, + 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, 0x1904, 0x61c0, + 0xa08e, 0x0023, 0x1570, 0x080c, 0x6408, 0x0904, 0x61c0, 0x7124, + 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, 0xa005, 0x1904, + 0x61c0, 0x2009, 0x0015, 0x080c, 0x80a7, 0x0804, 0x61c0, 0xa08e, + 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, + 0x80a7, 0x0804, 0x61c0, 0xa08e, 0x0100, 0x1904, 0x61c0, 0x7034, + 0xa005, 0x1904, 0x61c0, 0x2009, 0x0016, 0x080c, 0x80a7, 0x0804, + 0x61c0, 0xa08e, 0x0022, 0x1904, 0x61c0, 0x7030, 0xa08e, 0x0300, + 0x1580, 0x68d0, 0xd0a4, 0x0528, 0xc0b5, 0x68d2, 0x7100, 0xa18c, + 0x00ff, 0x696e, 0x7004, 0x6872, 0x00f6, 0x2079, 0x0100, 0x79e6, + 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x26a0, + 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2676, 0x694e, + 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0xad00, 0x70a2, + 0x00ee, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0017, 0x0804, + 0x6193, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, 0x1904, 0x61c0, + 0x68d0, 0xc0a5, 0x68d2, 0x2009, 0x0030, 0x0804, 0x6193, 0xa08e, + 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0018, + 0x0804, 0x6193, 0xa08e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, + 0x6193, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x6193, + 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, + 0x001b, 0x0804, 0x6193, 0xa08e, 0x5000, 0x1140, 0x7034, 0xa005, + 0x1904, 0x61c0, 0x2009, 0x001c, 0x0804, 0x6193, 0xa08e, 0x1300, + 0x1120, 0x2009, 0x0034, 0x0804, 0x6193, 0xa08e, 0x1200, 0x1140, + 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0024, 0x0804, 0x6193, + 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, 0x002d, 0x04d8, + 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, 0x002a, 0x0498, + 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, 0xa08e, 0x5300, + 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xb28d, 0x8208, + 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, + 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3c5c, 0x004e, 0x8108, + 0x1f04, 0x6176, 0x2009, 0x0023, 0x0070, 0xa08e, 0x6000, 0x1118, + 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, 0x0045, + 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xb283, 0x2204, 0x8211, + 0x220c, 0x080c, 0x2676, 0x1530, 0x080c, 0x4c80, 0x1518, 0x6612, + 0x6516, 0x86ff, 0x0180, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158, + 0x686c, 0xa606, 0x1140, 0x6870, 0xa506, 0xa084, 0xff00, 0x1118, + 0x6000, 0xc0f5, 0x6002, 0x00c6, 0x080c, 0x8022, 0x0168, 0x001e, + 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x80a7, + 0x00ce, 0x0005, 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046, + 0x080c, 0x6221, 0x1904, 0x621e, 0xa184, 0xff00, 0x8007, 0xa086, + 0x0008, 0x1904, 0x621e, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6408, + 0x0904, 0x621e, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, + 0x7034, 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x80a7, 0x04b0, + 0xa08e, 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, + 0x080c, 0x80a7, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, + 0x1400, 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xb283, 0x2204, + 0x8211, 0x220c, 0x080c, 0x2676, 0x11c0, 0x080c, 0x4c80, 0x11a8, + 0x6612, 0x6516, 0x00c6, 0x080c, 0x8022, 0x0170, 0x001e, 0x611a, + 0x080c, 0x9956, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, + 0x80a7, 0x080c, 0x6c50, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, + 0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, + 0x3c00, 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1df2, + 0x1590, 0x080c, 0x1ce2, 0x05c8, 0x04d9, 0x1130, 0x7908, 0xa18c, + 0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, + 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, + 0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0401, + 0x1120, 0xa08a, 0x0140, 0x1a0c, 0x14f6, 0x80ac, 0x20e1, 0x6000, + 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, + 0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, + 0x001e, 0x002e, 0x00de, 0x00fe, 0x0005, 0xa085, 0x0001, 0x0c98, + 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, 0x000e, 0x0005, + 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, 0x00ff, 0x1198, + 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x62ca, 0xa596, + 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, 0xfffc, 0x1118, + 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, 0xad34, 0x231c, + 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xae34, + 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, 0xaeb5, 0x2e1c, + 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, 0x0080, 0x2368, + 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, 0x1120, 0xa346, + 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, 0x0d58, 0x8420, + 0x8e70, 0x1f04, 0x62a7, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018, + 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, 0x0005, 0xa084, + 0x0007, 0x000a, 0x0005, 0x62db, 0x62db, 0x62db, 0x641a, 0x62db, + 0x62dc, 0x62f1, 0x635d, 0x0005, 0x7110, 0xd1bc, 0x0188, 0x7120, + 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xb400, 0x0248, 0x6858, + 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x80a7, + 0x0005, 0x00c6, 0x7110, 0xd1bc, 0x1904, 0x6344, 0x2011, 0xb283, + 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x1904, 0x6344, 0x080c, + 0x4c80, 0x1904, 0x6344, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15e0, + 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c, + 0x574f, 0x11d0, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0, + 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0530, + 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x2009, + 0x0044, 0x080c, 0x80a7, 0x00c0, 0x00c6, 0x080c, 0x8022, 0x001e, + 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, + 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00ce, 0x0005, 0x00c6, 0x080c, + 0x9807, 0x001e, 0x0dc8, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, + 0x7130, 0x6152, 0x6013, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0c38, 0x7110, 0xd1bc, 0x0188, + 0x7020, 0x2060, 0xac84, 0x0007, 0x1160, 0xac82, 0xb400, 0x0248, + 0x6858, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, + 0x80a7, 0x0005, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, + 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, 0x0005, + 0x6386, 0x6387, 0x6386, 0x6386, 0x63f0, 0x63fc, 0x0005, 0x7110, + 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x63ef, 0x700c, 0x7108, + 0x080c, 0x2676, 0x1904, 0x63ef, 0x080c, 0x4c80, 0x1904, 0x63ef, + 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, 0x00ff, + 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, 0x080c, + 0x6408, 0x00ce, 0x0904, 0x63ef, 0x00c6, 0x080c, 0x8022, 0x001e, + 0x05f0, 0x611a, 0x080c, 0x9956, 0x601f, 0x0002, 0x7120, 0x610a, + 0x2009, 0x0088, 0x080c, 0x80a7, 0x0490, 0xa28c, 0x00ff, 0xa186, + 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, 0x8217, + 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, 0x080c, + 0x8022, 0x001e, 0x01e0, 0x611a, 0x080c, 0x9956, 0x601f, 0x0005, + 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x80a7, 0x0080, 0x00c6, + 0x080c, 0x8022, 0x001e, 0x0158, 0x611a, 0x080c, 0x9956, 0x601f, + 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x80a7, 0x0005, + 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009, + 0x0089, 0x080c, 0x80a7, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041, + 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x80a7, 0x0005, + 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xb400, 0x0240, + 0x2001, 0xad16, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, 0x0005, + 0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, 0xac84, + 0x0007, 0x1150, 0xac82, 0xb400, 0x0238, 0x6858, 0xac02, 0x1220, + 0x2009, 0x0051, 0x080c, 0x80a7, 0x0005, 0x2031, 0x0105, 0x0069, + 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, + 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, + 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, 0x8022, + 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xb283, 0x2204, 0x8211, + 0x220c, 0x080c, 0x2676, 0x1580, 0x080c, 0x4c80, 0x1568, 0x6612, + 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0x9956, 0x080c, + 0x15d9, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, 0x0000, + 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3, + 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001, + 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00fe, 0x00de, 0x00ce, 0x0005, + 0x080c, 0x8078, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x2071, + 0xafda, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012, + 0x7017, 0xb400, 0x7007, 0x0000, 0x7026, 0x702b, 0x7841, 0x7032, + 0x7037, 0x789d, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, + 0x41b3, 0x0005, 0x2071, 0xafda, 0x1d04, 0x64fc, 0x2091, 0x6000, + 0x700c, 0x8001, 0x700e, 0x1180, 0x700f, 0x0361, 0x7007, 0x0001, + 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0148, 0x8109, 0x7142, + 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, + 0xa00d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, + 0x8109, 0x7126, 0xa186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, + 0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, 0x0158, 0x702c, 0x8001, + 0x702e, 0x1138, 0x702f, 0x0009, 0x8109, 0x7132, 0x1110, 0x7034, + 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, + 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x7018, 0xa00d, 0x0158, + 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, + 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6522, 0x6523, + 0x653b, 0x00e6, 0x2071, 0xafda, 0x7018, 0xa005, 0x1120, 0x711a, + 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0xafda, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee, + 0x0005, 0x00e6, 0x2071, 0xafda, 0x6088, 0xa102, 0x0208, 0x618a, + 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x4cdc, 0x1158, 0x6088, + 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6c50, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007, + 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, + 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, 0x9846, + 0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, 0xa186, + 0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, 0x6854, + 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, + 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, + 0x0010, 0x080c, 0x9350, 0x012e, 0xac88, 0x0018, 0x7116, 0x2001, + 0xe400, 0xa102, 0x0220, 0x7017, 0xb400, 0x7007, 0x0000, 0x0005, + 0x00e6, 0x2071, 0xafda, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, + 0x0005, 0x2001, 0xafe3, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xafda, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0xafe6, + 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xafda, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x2061, 0xb048, 0x00ce, + 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xb048, + 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, + 0xa005, 0x1150, 0x00c6, 0x2061, 0xb048, 0x6014, 0x00ce, 0xa005, + 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, + 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, + 0xa18e, 0x00c0, 0x05b0, 0xd0b4, 0x1138, 0xd0bc, 0x1528, 0x2009, + 0x0006, 0x080c, 0x661a, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003, + 0x0118, 0xa086, 0x0003, 0x15c0, 0x6020, 0xd0d4, 0x0130, 0xc0d4, + 0x6022, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xad73, 0x2104, + 0xd084, 0x0128, 0x2009, 0x0042, 0x080c, 0x80a7, 0x0005, 0x2009, + 0x0043, 0x080c, 0x80a7, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003, + 0x0118, 0xa086, 0x0003, 0x11c0, 0x2009, 0x0042, 0x080c, 0x80a7, + 0x0005, 0xd0fc, 0x0150, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0138, + 0x2009, 0x0041, 0x080c, 0x80a7, 0x0005, 0x0051, 0x0ce8, 0x2009, + 0x0043, 0x080c, 0x80a7, 0x0cc0, 0x2009, 0x0004, 0x0019, 0x0005, + 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x01f0, 0x2068, + 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, + 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb048, 0x6200, + 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, + 0x510c, 0x6010, 0xa06d, 0x190c, 0x65aa, 0x00de, 0x0005, 0x0156, + 0x00c6, 0x2061, 0xb048, 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, + 0xa204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, + 0x6808, 0xa005, 0x0120, 0x8001, 0x680a, 0xa085, 0x0001, 0x0005, + 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, + 0x1f04, 0x665c, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, + 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, + 0x1220, 0x1f04, 0x666c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, + 0x666c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, + 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, + 0x2800, 0x2079, 0xafc7, 0x012e, 0x00d6, 0x2069, 0xafc7, 0x6803, + 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, + 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, 0x0002, + 0x66aa, 0x66cb, 0x671e, 0x66b0, 0x66cb, 0x66aa, 0x66a8, 0x66a8, + 0x080c, 0x14f6, 0x080c, 0x6581, 0x080c, 0x6c50, 0x00ce, 0x0005, + 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x481b, 0x080c, + 0x650d, 0x7828, 0xa092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, + 0x4855, 0x0c88, 0x080c, 0x481b, 0x7807, 0x0003, 0x7827, 0x0000, + 0x782b, 0x0000, 0x0c40, 0x080c, 0x6581, 0x3c00, 0x0006, 0x2011, + 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, + 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, + 0x14f6, 0x2009, 0x0013, 0x080c, 0x80a7, 0x00ce, 0x0005, 0x3900, + 0xa082, 0xb0e8, 0x1210, 0x080c, 0x7d8d, 0x00c6, 0x7824, 0xa065, + 0x090c, 0x14f6, 0x7804, 0xa086, 0x0004, 0x0904, 0x675e, 0x7828, + 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x7827, + 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, 0x2071, 0xad00, + 0x70dc, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, + 0x2071, 0xad00, 0x080c, 0x485e, 0x00ee, 0x00ce, 0x080c, 0xaca2, + 0x2009, 0x0014, 0x080c, 0x80a7, 0x00ce, 0x0838, 0x2001, 0xafe3, + 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, + 0xa065, 0x090c, 0x14f6, 0x2009, 0x0013, 0x080c, 0x80fb, 0x00ce, + 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0xb0e8, 0x1210, 0x080c, + 0x7d8d, 0x7824, 0xa005, 0x090c, 0x14f6, 0x781c, 0xa06d, 0x090c, + 0x14f6, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x8078, + 0x693c, 0x81ff, 0x090c, 0x14f6, 0x8109, 0x693e, 0x6854, 0xa015, + 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, + 0x0000, 0x00de, 0x00ce, 0x080c, 0x6c50, 0x0888, 0x6104, 0xa186, + 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, 0x66f7, 0x7808, + 0xac06, 0x0904, 0x66f7, 0x080c, 0x6b73, 0x080c, 0x67ee, 0x00ce, + 0x080c, 0x6c50, 0x0804, 0x66e5, 0x00c6, 0x6027, 0x0002, 0x62c8, + 0x60c4, 0xa205, 0x1178, 0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009, + 0x0049, 0x080c, 0x80a7, 0x00ce, 0x0005, 0x2011, 0xafe6, 0x2013, + 0x0000, 0x0cc8, 0x3908, 0xa192, 0xb0e8, 0x1210, 0x080c, 0x7d8d, + 0x793c, 0x81ff, 0x0d90, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, + 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, 0xa085, 0x0012, 0x6016, + 0x0c10, 0x6014, 0xa084, 0x0184, 0xa085, 0x0016, 0x6016, 0x08d8, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0xafc7, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, + 0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xafc7, + 0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, + 0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x6c56, + 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, + 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xafc7, 0x0c18, + 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, + 0xafc7, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, + 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, + 0xafc7, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, + 0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x0076, 0x0066, 0x0026, 0x0016, 0x0006, 0x0126, 0x2071, + 0xafc7, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, + 0x6889, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x6884, + 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6884, 0x703c, 0xac06, + 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x7033, 0x0000, + 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x003e, 0x7038, + 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0x9596, 0x0198, 0x6010, 0x2068, 0x601c, 0xa086, + 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, + 0x97fd, 0x080c, 0xabfa, 0x080c, 0x510c, 0x080c, 0x9742, 0x080c, + 0x974e, 0x00ce, 0x0804, 0x682e, 0x2c78, 0x600c, 0x2060, 0x0804, + 0x682e, 0x012e, 0x000e, 0x001e, 0x002e, 0x006e, 0x007e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19d0, + 0x080c, 0xabfa, 0x080c, 0xa91f, 0x0c10, 0x0006, 0x0066, 0x00c6, + 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, + 0xafc7, 0x7838, 0xa065, 0x0558, 0x600c, 0x0006, 0x600f, 0x0000, + 0x783c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, + 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, + 0x003e, 0x080c, 0x9596, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, + 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, + 0x510c, 0x080c, 0x9742, 0x080c, 0x974e, 0x000e, 0x0898, 0x7e3a, + 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x601c, 0xa086, 0x0006, 0x1d30, 0x080c, 0xa91f, 0x0c60, 0x0016, + 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x69a9, 0x008e, + 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xafc7, 0x2091, + 0x8000, 0x080c, 0x6a36, 0x080c, 0x6aa8, 0x012e, 0x00fe, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0xafc7, 0x7614, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x6985, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, + 0x6980, 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6980, 0x7024, + 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, + 0x6581, 0x080c, 0x7834, 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7027, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, + 0x04b8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, + 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, + 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, + 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9596, 0x0188, + 0x601c, 0xa086, 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x97fd, 0x080c, 0xabfa, 0x080c, 0x510c, 0x080c, + 0x9742, 0x080c, 0x974e, 0x080c, 0x7b88, 0x00ce, 0x0804, 0x690f, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x690f, 0x012e, 0x000e, 0x001e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, + 0x0006, 0x1128, 0x080c, 0xabfa, 0x080c, 0xa91f, 0x0c10, 0x601c, + 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x0968, 0x08c8, + 0x601c, 0xa086, 0x0005, 0x19a8, 0x6004, 0xa086, 0x0085, 0x0d50, + 0x0880, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0xae34, + 0x2004, 0xa065, 0x0904, 0x6a32, 0x00f6, 0x00e6, 0x00d6, 0x0066, + 0x2071, 0xafc7, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c, + 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, + 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00, + 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, + 0x6002, 0x080c, 0x4c07, 0x0904, 0x6a2e, 0x7624, 0x86ff, 0x05e8, + 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0548, 0x080c, 0x6581, 0x080c, 0x7834, 0x68c3, + 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, + 0x080c, 0x974e, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, + 0x0009, 0x630a, 0x00ce, 0x0804, 0x69d9, 0x8dff, 0x0158, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, 0x080c, 0xabfa, + 0x080c, 0x510c, 0x080c, 0x7b88, 0x0804, 0x69d9, 0x006e, 0x00de, + 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, + 0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x6a88, + 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x6581, 0x080c, 0x7834, + 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7827, 0x0000, 0x0036, 0x2069, + 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, + 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010, + 0x2068, 0x080c, 0x9596, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, + 0x9742, 0x080c, 0x974e, 0x080c, 0x7b88, 0x000e, 0x0804, 0x6a3d, + 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, + 0xa086, 0x0006, 0x1118, 0x080c, 0xa91f, 0x0c58, 0x601c, 0xa086, + 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x09d0, 0x0c10, 0x601c, + 0xa086, 0x0005, 0x19f0, 0x6004, 0xa086, 0x0085, 0x0d60, 0x08c8, + 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6b0e, + 0x6054, 0x0006, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, + 0xc0dc, 0x6002, 0x080c, 0x4c07, 0x0904, 0x6b0b, 0x7e24, 0x86ff, + 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x6581, 0x080c, 0x7834, + 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7827, 0x0000, 0x0036, 0x2069, + 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, + 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0x974e, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, + 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6aba, 0x8dff, 0x0138, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, + 0x7b88, 0x0804, 0x6aba, 0x000e, 0x0804, 0x6aad, 0x781e, 0x781a, + 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, + 0x6000, 0xd0dc, 0x0188, 0x604c, 0xa06d, 0x0170, 0x6848, 0xa606, + 0x1158, 0x2071, 0xafc7, 0x7024, 0xa035, 0x0130, 0xa080, 0x0004, + 0x2004, 0xad06, 0x1108, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, + 0x00f6, 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, + 0x6003, 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7834, 0x78c3, + 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, + 0x7b04, 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, + 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, + 0x7ca8, 0x003e, 0x080c, 0x4c07, 0x00c6, 0x603c, 0xa005, 0x0110, + 0x8001, 0x603e, 0x2660, 0x080c, 0x8078, 0x00ce, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, 0x080c, 0x510c, 0x080c, + 0x7b88, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, 0xafc7, 0x7004, + 0xa084, 0x0007, 0x0002, 0x6b85, 0x6b88, 0x6b9e, 0x6bb7, 0x6bf0, + 0x6b85, 0x6b83, 0x6b83, 0x080c, 0x14f6, 0x00ce, 0x00ee, 0x0005, + 0x7024, 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, + 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, + 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, + 0x080c, 0x4c07, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, + 0x0120, 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, + 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, + 0xa065, 0x0598, 0x700c, 0xac06, 0x1160, 0x080c, 0x7b88, 0x600c, + 0xa015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0428, 0x720e, 0x720a, + 0x0410, 0x7014, 0xac06, 0x1160, 0x080c, 0x7b88, 0x600c, 0xa015, + 0x0120, 0x7216, 0x600f, 0x0000, 0x00b0, 0x7216, 0x7212, 0x0098, + 0x6018, 0x2060, 0x080c, 0x4c07, 0x6000, 0xc0dc, 0x6002, 0x080c, + 0x7b88, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e, + 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, + 0x7024, 0xa065, 0x0140, 0x080c, 0x7b88, 0x600c, 0xa015, 0x0150, + 0x720e, 0x600f, 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0xafc7, + 0x6830, 0xa084, 0x0003, 0x0002, 0x6c12, 0x6c14, 0x6c38, 0x6c10, + 0x080c, 0x14f6, 0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001, + 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, 0x0170, 0x6a3a, + 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0xafe6, + 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90, + 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, 0x0003, 0x0c50, + 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0168, + 0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, + 0x0020, 0x683f, 0x0000, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, + 0x00d6, 0x2069, 0xafc7, 0x6804, 0xa084, 0x0007, 0x0002, 0x6c61, + 0x6cfd, 0x6cfd, 0x6cfd, 0x6cfd, 0x6cff, 0x6c5f, 0x6c5f, 0x080c, + 0x14f6, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, + 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, + 0x6d49, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, 0x6807, + 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x6d49, 0x00ce, 0x00de, + 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, 0x6cf9, + 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, 0xa075, + 0x0120, 0xa20e, 0x0904, 0x6cf9, 0x0028, 0x6818, 0xa20e, 0x0904, + 0x6cf9, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70, + 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, 0x804f, + 0x0904, 0x6cf9, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, + 0x0014, 0x2004, 0xa084, 0x00ff, 0x605a, 0xa180, 0x0014, 0x2003, + 0x0000, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, + 0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, + 0x2c78, 0x71a0, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1110, 0xd1bc, + 0x0150, 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, + 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2be6, 0x2c0d, 0xa18c, 0x00ff, + 0x2061, 0x0100, 0x619a, 0x080c, 0x736f, 0x7300, 0xc3dd, 0x7302, + 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, + 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, + 0x0005, 0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, + 0x680c, 0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, + 0x080c, 0x6d49, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069, + 0xafc7, 0x6830, 0xa086, 0x0000, 0x11c0, 0x2001, 0xad0c, 0x200c, + 0xd1bc, 0x1550, 0x6838, 0xa07d, 0x0180, 0x6833, 0x0001, 0x683e, + 0x6847, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, + 0x1ee6, 0x1130, 0x012e, 0x080c, 0x76a5, 0x00de, 0x00fe, 0x0005, + 0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, + 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, + 0x0c60, 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x080c, 0x57d1, + 0x0888, 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, 0x6d57, 0x6d5c, + 0x7210, 0x732c, 0x6d5c, 0x7210, 0x732c, 0x6d57, 0x6d5c, 0x080c, + 0x6b73, 0x080c, 0x6c50, 0x0005, 0x0156, 0x0136, 0x0146, 0x00c6, + 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, 0x6118, 0x2178, + 0x79a0, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, + 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, + 0x0000, 0x0028, 0xa1f8, 0x2be6, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, + 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, 0x6dd0, 0x0033, + 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x6e7c, 0x6ec7, + 0x6ef4, 0x6fc1, 0x6fef, 0x6ff7, 0x701d, 0x702e, 0x703f, 0x7047, + 0x705d, 0x7047, 0x70b7, 0x702e, 0x70d8, 0x70e0, 0x703f, 0x70e0, + 0x70f1, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, + 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x790d, 0x7932, 0x7947, 0x796a, + 0x798b, 0x701d, 0x6dce, 0x701d, 0x7047, 0x6dce, 0x6ef4, 0x6fc1, + 0x6dce, 0x7daa, 0x7047, 0x6dce, 0x7dca, 0x7047, 0x6dce, 0x703f, + 0x6e75, 0x6de0, 0x6dce, 0x7def, 0x7e64, 0x7f3b, 0x6dce, 0x7f4c, + 0x7018, 0x7f68, 0x6dce, 0x79a0, 0x7fc3, 0x6dce, 0x080c, 0x14f6, + 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, + 0x6dde, 0x6dde, 0x6dde, 0x6e14, 0x6e32, 0x6e48, 0x080c, 0x14f6, + 0x00d6, 0x20a1, 0x020b, 0x080c, 0x710e, 0x7810, 0x2068, 0x20a3, + 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850, + 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0018, 0x080c, 0x7821, 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, + 0x68a0, 0x2069, 0xad00, 0x6ad0, 0xd2ac, 0x1110, 0xd0bc, 0x0110, + 0xa085, 0x0001, 0x00de, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, + 0x710e, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f, + 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2, + 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7821, + 0x00de, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x710e, + 0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3, + 0x0000, 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, + 0x20a3, 0x0000, 0x20a3, 0xdf10, 0x20a3, 0x0034, 0x2099, 0xad05, + 0x20a9, 0x0004, 0x53a6, 0x2099, 0xad01, 0x20a9, 0x0004, 0x53a6, + 0x2099, 0xafad, 0x20a9, 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398, + 0x1f04, 0x6e64, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, + 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, 0x2001, 0xad14, 0x2004, + 0x609a, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e, + 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0xad51, 0x6804, + 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c, 0x268a, + 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x20a9, 0x0004, + 0x2099, 0xad01, 0x53a6, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1138, + 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, + 0xad1b, 0x20a6, 0x2001, 0xad1c, 0x20a6, 0x0040, 0x20a3, 0x0000, + 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7821, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x710e, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, + 0xad34, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, + 0xa082, 0x007f, 0x0238, 0x2001, 0xad1b, 0x20a6, 0x2001, 0xad1c, + 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xad14, 0x2004, 0xa084, + 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x60c3, + 0x0010, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e, + 0x00c6, 0x7818, 0x2060, 0x2001, 0x0000, 0x080c, 0x5037, 0x00ce, + 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3, + 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3, + 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1904, + 0x6f83, 0x2001, 0xad34, 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xaf8d, + 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000, + 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001, + 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, + 0xaf8d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0x080c, 0x574f, + 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398, + 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x20a9, 0x0004, + 0x2099, 0xad01, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, + 0x6f5d, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6f63, 0x2099, + 0xaf95, 0x3304, 0xc0dd, 0x20a2, 0x2001, 0xad71, 0x2004, 0xd0e4, + 0x0158, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, + 0x33a6, 0x20a9, 0x0004, 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000, + 0x1f04, 0x6f7e, 0x0468, 0x2001, 0xad34, 0x2004, 0xd0a4, 0x0140, + 0x2001, 0xaf8e, 0x2004, 0x60e3, 0x0000, 0x080c, 0x26cb, 0x60e2, + 0x2099, 0xaf8d, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, + 0xad05, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xad01, 0x53a6, 0x20a9, + 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6fa1, 0x20a9, 0x0008, 0x20a3, + 0x0000, 0x1f04, 0x6fa7, 0x2099, 0xaf95, 0x20a9, 0x0008, 0x53a6, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6fb2, 0x20a9, 0x000a, + 0x20a3, 0x0000, 0x1f04, 0x6fb8, 0x60c3, 0x0074, 0x080c, 0x7821, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e, 0x20a3, 0x2010, 0x20a3, + 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xad51, 0x7904, 0x00fe, + 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, + 0xa085, 0x0002, 0x00d6, 0x0804, 0x7099, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x710e, 0x20a3, 0x5000, 0x0804, 0x6f0f, 0x20a1, + 0x020b, 0x080c, 0x710e, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x71a2, 0x0020, 0x20a1, 0x020b, 0x080c, + 0x71aa, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0004, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, + 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x0804, 0x6f0f, 0x20a1, + 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, + 0xa005, 0x0110, 0x20a2, 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2, + 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x00d6, 0x20a1, 0x020b, + 0x080c, 0x71aa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, + 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x1178, 0x6998, 0xa184, + 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, 0x0040, 0x20a3, + 0x0100, 0x0028, 0x20a3, 0x0400, 0x0010, 0x20a3, 0x0700, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xad51, + 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, + 0xa085, 0x0010, 0x2009, 0xad73, 0x210c, 0xd184, 0x1110, 0xa085, + 0x0002, 0x0026, 0x2009, 0xad71, 0x210c, 0xd1e4, 0x0130, 0xc0c5, + 0xa094, 0x0030, 0xa296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094, + 0x0030, 0xa296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2, + 0x20a2, 0x60c3, 0x0014, 0x080c, 0x7821, 0x00de, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, + 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x0804, 0x6e82, + 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7821, + 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, + 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, + 0x0000, 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x0026, 0x0036, + 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, + 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x11a0, + 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011, + 0xad14, 0x2214, 0x2001, 0xaf9d, 0x2004, 0xa005, 0x0118, 0x2011, + 0xad1c, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6, + 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x00c8, 0x2001, 0xad34, + 0x2004, 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, + 0x1130, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8, + 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8, + 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xad14, 0x2214, 0x22a2, 0xa485, 0x0029, + 0x20a2, 0x004e, 0x003e, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2, + 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x002e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, 0xad1b, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, + 0x08e0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, + 0x0000, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, + 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, + 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, + 0x02d8, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, + 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005, 0x1128, + 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0xad1b, 0x2da6, + 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, + 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, + 0x2011, 0xad14, 0x2214, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, + 0x0000, 0x004e, 0x003e, 0x080c, 0x7810, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x080c, 0x7810, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, + 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x14f6, 0xa08a, + 0x008c, 0x1a0c, 0x14f6, 0x6118, 0x2178, 0x79a0, 0x2011, 0xad34, + 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, + 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, + 0x2be6, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, + 0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x7247, 0x7251, + 0x726c, 0x7245, 0x7245, 0x7245, 0x7247, 0x080c, 0x14f6, 0x0146, + 0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x7821, 0x014e, + 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x72b8, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, + 0x080c, 0x7821, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, + 0x72f2, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0004, 0x080c, 0x7821, 0x014e, 0x0005, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, + 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8100, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14, + 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804, 0x7175, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, + 0x0288, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8400, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, + 0x8400, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, + 0xad14, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, + 0x0804, 0x7201, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, + 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, + 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, + 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, + 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, + 0x0000, 0x2011, 0xad14, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, + 0x20a3, 0x0000, 0x0804, 0x7201, 0x00c6, 0x00f6, 0x2c78, 0x7804, + 0xa08a, 0x0040, 0x0a0c, 0x14f6, 0xa08a, 0x0053, 0x1a0c, 0x14f6, + 0x7918, 0x2160, 0x61a0, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, + 0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, + 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2be6, 0x2c0d, 0xa18c, + 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, + 0x00ce, 0x0005, 0x736f, 0x747b, 0x7418, 0x761a, 0x736d, 0x736d, + 0x736d, 0x736d, 0x736d, 0x736d, 0x736d, 0x7b41, 0x7b51, 0x7b61, + 0x7b71, 0x736d, 0x7f79, 0x736d, 0x7b30, 0x080c, 0x14f6, 0x00d6, + 0x0156, 0x0146, 0x780b, 0xffff, 0x20a1, 0x020b, 0x080c, 0x73cf, + 0x7910, 0x2168, 0x6948, 0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2, + 0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, + 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, 0x0006, 0x8004, + 0x0016, 0x2008, 0x7858, 0xa084, 0x00ff, 0x8007, 0xa105, 0x001e, + 0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118, + 0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80, + 0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1, + 0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3, + 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, + 0x6016, 0x2001, 0xafe3, 0x2003, 0x07d0, 0x2001, 0xafe2, 0x2003, + 0x0009, 0x080c, 0x17bf, 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, + 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2019, 0xad34, 0x231c, 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, + 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, 0xad14, 0x210c, + 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000, + 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, + 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810, + 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, + 0x080c, 0x7821, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, + 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14, 0x2214, + 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x7810, + 0xa06d, 0x080c, 0x5025, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, + 0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, + 0x75d0, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, + 0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, + 0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, + 0x74b2, 0x7547, 0x7550, 0x7579, 0x758c, 0x75a7, 0x75b0, 0x74b0, + 0x080c, 0x14f6, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, + 0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, + 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, + 0x7583, 0xa186, 0x0001, 0x190c, 0x14f6, 0x6b78, 0x7820, 0xd0cc, + 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, + 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, + 0x0300, 0x0904, 0x7541, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, + 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, + 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x74f0, 0x015e, 0x22a2, + 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7541, 0x20a1, 0x020b, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14, + 0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, + 0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7810, 0x22a2, 0x20a3, + 0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7821, 0x0005, 0x2011, + 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0488, + 0x2011, 0x0302, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, + 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7821, + 0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, + 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, + 0x0018, 0x080c, 0x7821, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, + 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, + 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7821, 0x0005, 0x2011, + 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, + 0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, + 0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, + 0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, + 0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7583, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14, + 0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, + 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2, 0x20a3, + 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, + 0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, + 0x013e, 0x015e, 0x00de, 0x0005, 0x7634, 0x7634, 0x7636, 0x7634, + 0x7634, 0x7634, 0x7658, 0x7634, 0x080c, 0x14f6, 0x7910, 0xa18c, + 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, + 0x00f9, 0x00d6, 0x2069, 0xad51, 0x6804, 0xd0bc, 0x0130, 0x682c, + 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, + 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7821, 0x0005, + 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0100, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14, + 0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, + 0x7810, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xad00, 0x7150, + 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d0, 0xd6ac, 0x1130, 0xd0bc, + 0x1120, 0x6910, 0x6a14, 0x7450, 0x0020, 0x6910, 0x6a14, 0x736c, + 0x7470, 0x781c, 0xa0be, 0x0006, 0x0904, 0x775b, 0xa0be, 0x000a, + 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, + 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, + 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, + 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, + 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0x609f, 0x0000, 0x080c, 0x8014, 0x2009, 0x07d0, 0x60c4, 0xa084, + 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6586, 0x003e, + 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d0, 0xd0ac, + 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, + 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, + 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, + 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, + 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, + 0x8014, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, + 0x2009, 0x1b58, 0x080c, 0x6586, 0x003e, 0x004e, 0x005e, 0x00ce, + 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, + 0xa086, 0x0002, 0x0904, 0x77b1, 0x2001, 0xad34, 0x2004, 0xd0ac, + 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, + 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086, + 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, + 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, + 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, + 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8011, 0x0804, + 0x7749, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, + 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, + 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5025, + 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020, + 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889, + 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, + 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, + 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, + 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120, + 0x080c, 0x8014, 0x0804, 0x7749, 0x080c, 0x8011, 0x0804, 0x7749, + 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, + 0x8217, 0x0005, 0x00d6, 0x2069, 0xafc7, 0x6843, 0x0001, 0x00de, + 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019, + 0x080c, 0x6578, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085, + 0x0009, 0x6016, 0x000e, 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100, + 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, 0x6016, 0x00ce, 0x000e, + 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, + 0x0140, 0x080c, 0x574f, 0x1178, 0x2001, 0xafe3, 0x2004, 0xa005, + 0x1598, 0x080c, 0x57d1, 0x1118, 0x080c, 0x6578, 0x0468, 0x00c6, + 0x2061, 0xafc7, 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x08a1, + 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, 0xafc7, 0x6128, + 0xa192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, + 0x0198, 0x080c, 0x6578, 0x080c, 0x782b, 0x0070, 0x6124, 0xa1e5, + 0x0000, 0x0140, 0x080c, 0xaca2, 0x2009, 0x0014, 0x080c, 0x80a7, + 0x080c, 0x6581, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, + 0x0005, 0x2001, 0xafe3, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, + 0xafc7, 0x6128, 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, + 0x080c, 0x6578, 0x080c, 0x485e, 0x0c38, 0x00c6, 0x00d6, 0x00e6, + 0x0016, 0x0026, 0x080c, 0x658e, 0x2071, 0xafc7, 0x713c, 0x81ff, + 0x0570, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x574f, 0x1188, + 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x003e, 0x713c, 0x2160, + 0x080c, 0xaca2, 0x2009, 0x004a, 0x080c, 0x80a7, 0x080c, 0x57d1, + 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, 0x6803, + 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x003e, 0x713c, + 0x2160, 0x080c, 0xaca2, 0x2009, 0x004a, 0x080c, 0x80a7, 0x002e, + 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x00e6, 0x00d6, + 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000, + 0x6018, 0x2068, 0x6ca0, 0x2071, 0xafc7, 0x7018, 0x2068, 0x8dff, + 0x0198, 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010, + 0x2060, 0x643c, 0x6540, 0x6e48, 0x2d60, 0x080c, 0x4e41, 0x0120, + 0x080c, 0x7b88, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, 0x080c, + 0x710e, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c, + 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xad14, 0x2004, + 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006, + 0x20a2, 0x1f04, 0x7928, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x080c, + 0x7821, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x710e, + 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, + 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x20a3, + 0x0000, 0x20a9, 0x0006, 0x2011, 0xad40, 0x2019, 0xad41, 0x23a6, + 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7957, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7821, 0x014e, + 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, + 0x080c, 0x7183, 0x080c, 0x7199, 0x7810, 0xa080, 0x0000, 0x2004, + 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, + 0xa080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x7821, 0x002e, 0x001e, + 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, + 0x710e, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, + 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, + 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x710e, + 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, + 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x7821, + 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x700c, 0x2060, 0x8cff, + 0x0178, 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x600c, 0x0006, + 0x080c, 0x994e, 0x080c, 0x8078, 0x080c, 0x7b88, 0x00ce, 0x0c78, + 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee, + 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, + 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, + 0x2071, 0xafc7, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x7834, + 0x68c3, 0x0000, 0x080c, 0x6581, 0x2009, 0x0013, 0x080c, 0x80a7, + 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, + 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, + 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x7a02, 0x7804, + 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, + 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, + 0x012e, 0x0005, 0x2001, 0xad00, 0x2004, 0xa096, 0x0001, 0x0550, + 0xa096, 0x0004, 0x0538, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, + 0x481b, 0x080c, 0x650d, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, + 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, + 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, + 0x1f04, 0x7a3d, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, + 0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, + 0x0100, 0x2079, 0x0140, 0x2071, 0xafc7, 0x703c, 0x2060, 0x8cff, + 0x0904, 0x7ad5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, + 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x658e, 0x080c, 0x20b5, + 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, + 0xa084, 0x000f, 0xa086, 0x0004, 0x11b0, 0x68c7, 0x0000, 0x68cb, + 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, 0xb01e, 0x6814, + 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, 0x7003, + 0x0000, 0x00fe, 0x00ee, 0x200b, 0x0000, 0x004e, 0xa39d, 0x0000, + 0x1120, 0x2009, 0x0049, 0x080c, 0x80a7, 0x20a9, 0x03e8, 0x6824, + 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, + 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, + 0x0002, 0x0010, 0x1f04, 0x7ab7, 0x7804, 0xa084, 0x1000, 0x0120, + 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, + 0x0126, 0x2091, 0x8000, 0x2069, 0xafc7, 0x6a06, 0x012e, 0x00de, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xafc7, 0x6a32, + 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, + 0x0126, 0x2071, 0xafc7, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, + 0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, + 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, + 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, + 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, + 0x974e, 0x080c, 0x7b88, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, + 0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, + 0x7b80, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, + 0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, + 0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, + 0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, + 0x0089, 0x60c3, 0x0020, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, + 0x00e6, 0x2071, 0xafc7, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, + 0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x7b94, 0x20a2, + 0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x7614, 0x2660, + 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x7c24, 0x8cff, 0x0904, + 0x7c24, 0x601c, 0xa086, 0x0006, 0x1904, 0x7c1f, 0x88ff, 0x0138, + 0x2800, 0xac06, 0x1904, 0x7c1f, 0x2039, 0x0000, 0x0050, 0x6018, + 0xa206, 0x1904, 0x7c1f, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, + 0x7c1f, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x01f0, 0x080c, 0x6581, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, + 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, + 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, + 0x0009, 0x630a, 0x0460, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, + 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, + 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000, 0x6010, + 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0xa91f, 0x080c, 0x974e, + 0x080c, 0x7b88, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x7bab, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x7bab, 0xa006, 0x012e, 0x000e, 0x006e, + 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, + 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, + 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x7c98, 0x601c, 0xa086, + 0x0006, 0x1904, 0x7c93, 0x87ff, 0x0128, 0x2700, 0xac06, 0x1904, + 0x7c93, 0x0040, 0x6018, 0xa206, 0x15f0, 0x85ff, 0x0118, 0x6050, + 0xa106, 0x15c8, 0x703c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, + 0x080c, 0x7a64, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, + 0x7047, 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, + 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, + 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, + 0x9596, 0x0110, 0x080c, 0xa91f, 0x080c, 0x974e, 0x87ff, 0x1190, + 0x00ce, 0x0804, 0x7c43, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7c43, + 0xa006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, + 0x00e6, 0x2071, 0xafc7, 0x2001, 0xad00, 0x2004, 0xa086, 0x0002, + 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0xafc7, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0518, 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, + 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, + 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x760c, + 0x2660, 0x2678, 0x8cff, 0x0904, 0x7d7e, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x1904, 0x7d79, 0x7024, 0xac06, 0x1508, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x0904, 0x7d55, 0x080c, 0x7834, 0x68c3, + 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x080c, 0x9778, 0x1158, 0x080c, 0x2aff, 0x080c, + 0x9789, 0x11f0, 0x080c, 0x85f3, 0x00d8, 0x080c, 0x7ca8, 0x08c0, + 0x080c, 0x9789, 0x1118, 0x080c, 0x85f3, 0x0090, 0x6010, 0x2068, + 0x080c, 0x9596, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, 0x9742, + 0x080c, 0x994e, 0x080c, 0x974e, 0x080c, 0x7b88, 0x00ce, 0x0804, + 0x7d02, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7d02, 0x012e, 0x000e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, + 0x0006, 0x1d30, 0x080c, 0xa91f, 0x0c18, 0x0036, 0x0156, 0x0136, + 0x0146, 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x28f9, + 0x1118, 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, + 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, + 0x003e, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, + 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2099, 0xafa6, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, + 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x7821, + 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0214, + 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7821, 0x0005, 0x00d6, + 0x0016, 0x2f68, 0x2009, 0x0035, 0x080c, 0x9a34, 0x1904, 0x7e5d, + 0x20a1, 0x020b, 0x080c, 0x710e, 0x20a3, 0x1300, 0x20a3, 0x0000, + 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, + 0x0028, 0x2014, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x11d0, 0xa286, + 0x007e, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, + 0x007f, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, + 0x0180, 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, + 0x0428, 0xa2e8, 0xae34, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, + 0x00e8, 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xad34, + 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, + 0x007e, 0x0240, 0x00d6, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, + 0x7838, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, + 0x080c, 0x7821, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, + 0x0006, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, + 0x691c, 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x7ed3, + 0xa186, 0x0005, 0x0904, 0x7ebc, 0xa186, 0x0004, 0x05b8, 0xa186, + 0x0008, 0x0904, 0x7ec4, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, + 0x7f3b, 0x002e, 0x00de, 0x0005, 0x080c, 0x7ef7, 0x2009, 0x4000, + 0x6800, 0x0002, 0x7e9d, 0x7ea8, 0x7e9f, 0x7ea8, 0x7ea4, 0x7e9d, + 0x7e9d, 0x7ea8, 0x7ea8, 0x7ea8, 0x7ea8, 0x7e9d, 0x7e9d, 0x7e9d, + 0x7e9d, 0x7e9d, 0x7ea8, 0x7e9d, 0x7ea8, 0x080c, 0x14f6, 0x6820, + 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, + 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0804, 0x7eed, 0x080c, 0x7ef7, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, + 0x0002, 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, + 0x1108, 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, + 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, + 0x0000, 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, + 0x2009, 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, + 0x60c3, 0x0018, 0x080c, 0x7821, 0x002e, 0x00de, 0x0005, 0x0036, + 0x0046, 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x71aa, 0xa006, + 0x20a3, 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, + 0xa092, 0x007e, 0x0268, 0x00d6, 0x2069, 0xad1b, 0x2d2c, 0x8d68, + 0x2d34, 0xa0e8, 0xae34, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, + 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, + 0x24a2, 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, + 0x004e, 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, + 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, + 0x0008, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7106, + 0x20a3, 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, + 0x7828, 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, + 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x7821, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x71a2, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x7828, 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7821, + 0x0005, 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, + 0x7821, 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, + 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, + 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, + 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, + 0x6234, 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x7810, + 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, + 0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, + 0x080c, 0x782b, 0x080c, 0x6578, 0x0005, 0x0156, 0x0136, 0x0036, + 0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, + 0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, + 0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, + 0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, + 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, + 0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, + 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, + 0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, + 0x6116, 0x0005, 0x2061, 0xb400, 0x2a70, 0x7064, 0x7046, 0x704b, + 0xb400, 0x0005, 0x00e6, 0x0126, 0x2071, 0xad00, 0x2091, 0x8000, + 0x7544, 0xa582, 0x0010, 0x0608, 0x7048, 0x2060, 0x6000, 0xa086, + 0x0000, 0x0148, 0xace0, 0x0018, 0x7058, 0xac02, 0x1208, 0x0cb0, + 0x2061, 0xb400, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, + 0x0018, 0x7058, 0xa502, 0x1230, 0x754a, 0xa085, 0x0001, 0x012e, + 0x00ee, 0x0005, 0x704b, 0xb400, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, + 0x2071, 0xad00, 0x7544, 0xa582, 0x0010, 0x0600, 0x7048, 0x2060, + 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x7058, 0xac02, + 0x1208, 0x0cb0, 0x2061, 0xb400, 0x0c98, 0x6003, 0x0008, 0x8529, + 0x7546, 0xaca8, 0x0018, 0x7058, 0xa502, 0x1228, 0x754a, 0xa085, + 0x0001, 0x00ee, 0x0005, 0x704b, 0xb400, 0x0cc8, 0xa006, 0x0cc8, + 0xac82, 0xb400, 0x0a0c, 0x14f6, 0x2001, 0xad16, 0x2004, 0xac02, + 0x1a0c, 0x14f6, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, + 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6052, 0x6056, 0x6022, + 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x2061, + 0xad00, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0108, 0x0005, + 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0cc0, 0x601c, + 0xa084, 0x000f, 0x0002, 0x80b6, 0x80c5, 0x80e0, 0x80fb, 0x9a61, + 0x9a7c, 0x9a97, 0x80b6, 0x80c5, 0x80b6, 0x8116, 0xa186, 0x0013, + 0x1128, 0x080c, 0x6b73, 0x080c, 0x6c50, 0x0005, 0xa18e, 0x0047, + 0x1118, 0xa016, 0x080c, 0x1824, 0x0005, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x80de, 0x8478, + 0x862d, 0x80de, 0x86a2, 0x81cf, 0x80de, 0x80de, 0x840a, 0x8a91, + 0x80de, 0x80de, 0x80de, 0x80de, 0x80de, 0x80de, 0x080c, 0x14f6, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, + 0x0005, 0x80f9, 0x909a, 0x80f9, 0x80f9, 0x80f9, 0x80f9, 0x80f9, + 0x80f9, 0x9045, 0x9200, 0x80f9, 0x90c7, 0x913e, 0x90c7, 0x913e, + 0x80f9, 0x080c, 0x14f6, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x14f6, 0x0013, 0x006e, 0x0005, 0x8114, 0x8ad2, 0x8b98, 0x8cb8, + 0x8e12, 0x8114, 0x8114, 0x8114, 0x8aac, 0x8ff5, 0x8ff8, 0x8114, + 0x8114, 0x8114, 0x8114, 0x9022, 0x080c, 0x14f6, 0x0066, 0x6000, + 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x812f, + 0x812f, 0x812f, 0x8152, 0x81a5, 0x812f, 0x812f, 0x812f, 0x8131, + 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x080c, + 0x14f6, 0xa186, 0x0003, 0x190c, 0x14f6, 0x00d6, 0x6003, 0x0003, + 0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, + 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x00de, 0x2c10, 0x080c, + 0x1e6e, 0x080c, 0x680b, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d0d, + 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x815e, 0x815e, 0x8160, + 0x817f, 0x815e, 0x815e, 0x815e, 0x815e, 0x8191, 0x080c, 0x14f6, + 0x00d6, 0x0016, 0x080c, 0x6c05, 0x080c, 0x6d0d, 0x6003, 0x0004, + 0x6110, 0x2168, 0x6854, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, + 0x684f, 0x0020, 0x685c, 0x685a, 0x6874, 0x687e, 0x6878, 0x6882, + 0x6897, 0x0000, 0x689b, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, + 0x6c05, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9596, 0x0120, 0x684b, + 0x0006, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x080c, 0x6d0d, + 0x0005, 0x080c, 0x6c05, 0x080c, 0x2ad9, 0x00d6, 0x6110, 0x2168, + 0x080c, 0x9596, 0x0120, 0x684b, 0x0029, 0x080c, 0x510c, 0x00de, + 0x080c, 0x8078, 0x080c, 0x6d0d, 0x0005, 0xa182, 0x0047, 0x0002, + 0x81b3, 0x81c2, 0x81b1, 0x81b1, 0x81b1, 0x81b1, 0x81b1, 0x81b1, + 0x81b1, 0x080c, 0x14f6, 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4, + 0x684e, 0x00de, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, + 0x1824, 0x0005, 0x00d6, 0x6110, 0x2168, 0x684b, 0x0000, 0x6853, + 0x0000, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x0005, 0xa1b6, + 0x0015, 0x1118, 0x080c, 0x8078, 0x0030, 0xa1b6, 0x0016, 0x190c, + 0x14f6, 0x080c, 0x8078, 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010, + 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, + 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, + 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x81ea, 0x00e6, 0x080c, + 0x9596, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, + 0x00ee, 0x080c, 0x8078, 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386, + 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, + 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, + 0x6b32, 0x080c, 0x8078, 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9, + 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, + 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, + 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037, + 0x0103, 0x00ee, 0x080c, 0x8078, 0x001e, 0x0005, 0x0016, 0x2009, + 0x0000, 0x7030, 0xa086, 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff, + 0x808e, 0x703c, 0xa084, 0x00ff, 0x8086, 0xa080, 0x0004, 0xa108, + 0x21a8, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, + 0x080c, 0x48be, 0x00e6, 0x080c, 0x9596, 0x0140, 0x6010, 0x2070, + 0x7007, 0x0000, 0x7034, 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c, + 0x8078, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68, + 0x0016, 0x2009, 0x0035, 0x080c, 0x9a34, 0x001e, 0x1168, 0x0026, + 0x6228, 0x2268, 0x002e, 0x2071, 0xb28c, 0x6b1c, 0xa386, 0x0003, + 0x0130, 0xa386, 0x0006, 0x0128, 0x080c, 0x8078, 0x0020, 0x0031, + 0x0010, 0x080c, 0x8323, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810, + 0x2078, 0xa186, 0x0015, 0x0904, 0x830c, 0xa18e, 0x0016, 0x1904, + 0x8321, 0x700c, 0xa084, 0xff00, 0xa086, 0x1700, 0x1904, 0x82eb, + 0x8fff, 0x0904, 0x831f, 0x6808, 0xa086, 0xffff, 0x1904, 0x830e, + 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810, + 0xa106, 0x1904, 0x830e, 0x7980, 0x7814, 0xa106, 0x1904, 0x830e, + 0x080c, 0x9742, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, + 0x784e, 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6665, + 0x7854, 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138, + 0x00c6, 0x2d60, 0x080c, 0x9374, 0x00ce, 0x0804, 0x831f, 0x00c6, + 0x00d6, 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4993, 0x0010, + 0x080c, 0x4b7c, 0x00de, 0x00ce, 0x1548, 0x00c6, 0x2d60, 0x080c, + 0x8078, 0x00ce, 0x04a0, 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018, + 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7853, 0x0003, 0x6007, + 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x67a8, 0x080c, + 0x6c50, 0x00ce, 0x00e0, 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001, + 0xafa5, 0x2004, 0x683e, 0x0098, 0x0471, 0x0098, 0x8fff, 0x090c, + 0x14f6, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x684b, 0x0003, 0x080c, + 0x926f, 0x080c, 0x9742, 0x080c, 0x974e, 0x00de, 0x00ce, 0x080c, + 0x8078, 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xafa5, + 0x2004, 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00, + 0x2060, 0x080c, 0xabb4, 0x080c, 0x6618, 0x080c, 0x8078, 0x00ce, + 0x080c, 0x8078, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80, + 0x7b7c, 0xd2f4, 0x0130, 0x2001, 0xafa5, 0x2004, 0x683e, 0x0804, + 0x839d, 0x00c6, 0x2d60, 0x080c, 0x928f, 0x00ce, 0x6804, 0xa086, + 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, + 0x0050, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ce, 0x04f0, 0x6800, + 0xa086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x14f6, 0x6820, 0xd0dc, + 0x1198, 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180, + 0x784c, 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, + 0x2001, 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0, + 0x784c, 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0, + 0x0c38, 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406, + 0x0d58, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, + 0x080c, 0x9894, 0x080c, 0x6c50, 0x0010, 0x080c, 0x8078, 0x004e, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068, + 0x6a1c, 0xa286, 0x0007, 0x0904, 0x83ee, 0xa286, 0x0002, 0x05f0, + 0xa286, 0x0000, 0x05d8, 0x6808, 0x6338, 0xa306, 0x15b8, 0x2071, + 0xb28c, 0xa186, 0x0015, 0x0560, 0xa18e, 0x0016, 0x1190, 0x6030, + 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, 0xa086, 0x2a00, + 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, 0xc1f5, 0x2102, + 0x00b8, 0x00c6, 0x6034, 0x2060, 0x6010, 0x2068, 0x080c, 0x9596, + 0x090c, 0x14f6, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, + 0x601f, 0x0002, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ce, 0x0030, + 0x6034, 0x2070, 0x2001, 0xafa5, 0x2004, 0x703e, 0x080c, 0x8078, + 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, 0x000e, 0x2e98, + 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1148, 0x6018, 0x2068, + 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x00de, + 0x0804, 0x81f6, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b2, + 0x0040, 0x1a04, 0x846e, 0x0002, 0x8462, 0x8456, 0x8462, 0x8462, + 0x8462, 0x8462, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, + 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, + 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, + 0x8454, 0x8454, 0x8454, 0x8462, 0x8454, 0x8462, 0x8462, 0x8454, + 0x8454, 0x8454, 0x8454, 0x8454, 0x8462, 0x8454, 0x8454, 0x8454, + 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8462, 0x8462, + 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, + 0x8454, 0x8462, 0x8454, 0x8454, 0x080c, 0x14f6, 0x6003, 0x0001, + 0x6106, 0x080c, 0x67ee, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, + 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x67ee, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, 0x2600, 0x0002, + 0x8462, 0x8476, 0x8476, 0x8462, 0x8462, 0x8476, 0x080c, 0x14f6, + 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b6, 0x0013, 0x0904, + 0x8518, 0xa1b6, 0x0027, 0x1904, 0x84de, 0x080c, 0x6b73, 0x6004, + 0x080c, 0x9778, 0x0188, 0x080c, 0x9789, 0x0904, 0x84d8, 0xa08e, + 0x0021, 0x0904, 0x84db, 0xa08e, 0x0022, 0x0904, 0x84d8, 0xa08e, + 0x003d, 0x0904, 0x84db, 0x04a8, 0x080c, 0x2aff, 0x2001, 0x0007, + 0x080c, 0x4c30, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x85f3, + 0xa186, 0x007e, 0x1148, 0x2001, 0xad34, 0x2014, 0xc285, 0x080c, + 0x574f, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110, + 0x2019, 0x0028, 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, + 0x681d, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x4ecf, 0x00ce, + 0x2c08, 0x080c, 0xa712, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, + 0x4c9f, 0x080c, 0x994e, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, + 0x080c, 0x85f3, 0x0cb0, 0x080c, 0x8621, 0x0c98, 0xa186, 0x0014, + 0x1db0, 0x080c, 0x6b73, 0x080c, 0x2ad9, 0x080c, 0x9778, 0x1188, + 0x080c, 0x2aff, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x85f3, + 0xa186, 0x007e, 0x1128, 0x2001, 0xad34, 0x200c, 0xc185, 0x2102, + 0x08c0, 0x080c, 0x9789, 0x1118, 0x080c, 0x85f3, 0x0890, 0x6004, + 0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xad81, 0x2079, + 0x0000, 0x080c, 0x2df1, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, + 0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x85f3, 0x0804, 0x84d1, + 0xa0b2, 0x0040, 0x1a04, 0x85db, 0x2008, 0x0002, 0x8560, 0x8561, + 0x8564, 0x8567, 0x856a, 0x856d, 0x855e, 0x855e, 0x855e, 0x855e, + 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, + 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, + 0x855e, 0x855e, 0x855e, 0x855e, 0x8570, 0x857f, 0x855e, 0x8581, + 0x857f, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x857f, 0x857f, + 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, + 0x85bb, 0x857f, 0x855e, 0x857b, 0x855e, 0x855e, 0x855e, 0x857c, + 0x855e, 0x855e, 0x855e, 0x857f, 0x85b2, 0x855e, 0x080c, 0x14f6, + 0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, + 0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, + 0x080c, 0x6b73, 0x6003, 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, + 0x080c, 0x6c50, 0x00a0, 0x0018, 0x0010, 0x080c, 0x4c30, 0x0804, + 0x85cc, 0x080c, 0x6b73, 0x2001, 0xafa3, 0x2004, 0x6016, 0x2001, + 0xafa5, 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x6c50, 0x0005, + 0x080c, 0x4c30, 0x080c, 0x6b73, 0x6003, 0x0002, 0x2001, 0xafa5, + 0x2004, 0x603e, 0x0036, 0x2019, 0xad5c, 0x2304, 0xa084, 0xff00, + 0x1120, 0x2001, 0xafa3, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004, + 0x0ec0, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c, + 0x6c50, 0x08e8, 0x080c, 0x6b73, 0x080c, 0x994e, 0x080c, 0x8078, + 0x080c, 0x6c50, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xad81, 0x2079, + 0x0000, 0x080c, 0x2df1, 0x00fe, 0x00ee, 0x080c, 0x6b73, 0x080c, + 0x8078, 0x080c, 0x6c50, 0x0818, 0x080c, 0x6b73, 0x2001, 0xafa5, + 0x2004, 0x603e, 0x6003, 0x0002, 0x2001, 0xafa3, 0x2004, 0x6016, + 0x080c, 0x6c50, 0x0005, 0x2600, 0x2008, 0x0002, 0x85e6, 0x85e4, + 0x85e4, 0x85cc, 0x85cc, 0x85e4, 0x080c, 0x14f6, 0x080c, 0x6b73, + 0x00d6, 0x6010, 0x2068, 0x080c, 0x15f0, 0x00de, 0x080c, 0x8078, + 0x080c, 0x6c50, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0x9596, + 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001, + 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0x9a05, 0x0090, + 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e, + 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103, + 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, + 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, + 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, + 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x14f6, + 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0x99c1, 0x0804, 0x8692, + 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0x9971, 0x0804, 0x8692, + 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x97b9, 0x0804, 0x8692, + 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x97d0, 0x04d8, 0x6604, + 0xa6b6, 0x001f, 0x1118, 0x080c, 0x81dc, 0x04a0, 0x6604, 0xa6b6, + 0x0000, 0x1118, 0x080c, 0x83f4, 0x0468, 0x6604, 0xa6b6, 0x0022, + 0x1118, 0x080c, 0x8204, 0x0430, 0x6604, 0xa6b6, 0x0035, 0x1118, + 0x080c, 0x826b, 0x00f8, 0x6604, 0xa6b6, 0x0039, 0x1118, 0x080c, + 0x83a3, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x821e, + 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x823e, 0x0050, + 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118, + 0x0804, 0x883f, 0x0005, 0x080c, 0x80be, 0x0ce0, 0x86b9, 0x86bc, + 0x86b9, 0x86fe, 0x86b9, 0x87cc, 0x884d, 0x86b9, 0x86b9, 0x881b, + 0x86b9, 0x882f, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, 0x00e6, 0xacf0, 0x0004, + 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8078, + 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, 0xad00, 0x7080, + 0xa086, 0x0074, 0x1530, 0x080c, 0xa6e9, 0x11b0, 0x00d6, 0x6018, + 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, 0xc0c5, + 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, + 0x2aff, 0x080c, 0x8078, 0x0078, 0x2001, 0x000a, 0x080c, 0x4c30, + 0x080c, 0x2aff, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, + 0x0010, 0x080c, 0x87bd, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168, + 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2069, 0xad51, 0x6804, 0xd0a4, + 0x0120, 0x2001, 0x0006, 0x080c, 0x4c5d, 0x0005, 0x00d6, 0x2011, + 0xad20, 0x2204, 0xa086, 0x0074, 0x1904, 0x87ba, 0x6018, 0x2068, + 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x894d, 0x0804, 0x875e, + 0x080c, 0x8943, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, + 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, + 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200, + 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, 0x2aff, 0x080c, 0x8078, + 0x0804, 0x87bb, 0x00e6, 0x2071, 0xad34, 0x2e04, 0xd09c, 0x0188, + 0x2071, 0xb280, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284, + 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112, + 0x7216, 0x00ee, 0x6010, 0xa005, 0x0128, 0x2068, 0x6838, 0xd0f4, + 0x0108, 0x0880, 0x2001, 0x0004, 0x080c, 0x4c30, 0x6003, 0x0001, + 0x6007, 0x0003, 0x080c, 0x67ee, 0x0804, 0x87bb, 0x685c, 0xd0e4, + 0x01d0, 0x080c, 0x9903, 0x080c, 0x574f, 0x0110, 0xd0dc, 0x1900, + 0x2011, 0xad34, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xaf8e, 0x2004, + 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x26cb, 0x78e2, + 0x00fe, 0x0804, 0x8728, 0x080c, 0x9937, 0x2011, 0xad34, 0x2204, + 0xc0a5, 0x2012, 0x0006, 0x080c, 0xa801, 0x000e, 0x1904, 0x8728, + 0xc0b5, 0x2012, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x00c6, 0x2009, + 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe, + 0x080c, 0x26a0, 0x00f6, 0x2079, 0xad00, 0x7972, 0x2100, 0x2009, + 0x0000, 0x080c, 0x2676, 0x794e, 0x00fe, 0x8108, 0x080c, 0x4c80, + 0x2c00, 0x00ce, 0x1904, 0x8728, 0x601a, 0x2001, 0x0002, 0x080c, + 0x4c30, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, + 0x67ee, 0x0008, 0x0011, 0x00de, 0x0005, 0x2001, 0xad00, 0x2004, + 0xa086, 0x0003, 0x0120, 0x2001, 0x0007, 0x080c, 0x4c30, 0x080c, + 0x2aff, 0x080c, 0x8078, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, + 0xad00, 0x7080, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, + 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3cce, 0x00d6, 0x6018, + 0x2068, 0x080c, 0x4d72, 0x080c, 0x86ed, 0x00de, 0x080c, 0x89f7, + 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, + 0x2001, 0x0006, 0x080c, 0x4c30, 0x00e6, 0x6010, 0xa075, 0x01a8, + 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, + 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0x9a05, 0x0030, 0x7007, + 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2aff, + 0x080c, 0x8078, 0x0020, 0x080c, 0x85f3, 0x080c, 0x87bd, 0x001e, + 0x002e, 0x00ee, 0x0005, 0x2011, 0xad20, 0x2204, 0xa086, 0x0014, + 0x1158, 0x2001, 0x0002, 0x080c, 0x4c30, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x67ee, 0x0010, 0x080c, 0x87bd, 0x0005, 0x2011, + 0xad20, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c, + 0x4c30, 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x0005, 0x000b, + 0x0005, 0x86b9, 0x8854, 0x86b9, 0x888a, 0x86b9, 0x88ff, 0x884d, + 0x86b9, 0x86b9, 0x8912, 0x86b9, 0x8922, 0x6604, 0xa6b6, 0x001e, + 0x1110, 0x080c, 0x8078, 0x0005, 0x00d6, 0x00c6, 0x080c, 0x8932, + 0x1178, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c, + 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x00f8, + 0x2009, 0xb28e, 0x2104, 0xa086, 0x0009, 0x1160, 0x6018, 0x2068, + 0x6840, 0xa084, 0x00ff, 0xa005, 0x0180, 0x8001, 0x6842, 0x6017, + 0x000a, 0x0068, 0x2009, 0xb28f, 0x2104, 0xa084, 0xff00, 0xa086, + 0x1900, 0x1118, 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x00ce, + 0x00de, 0x0005, 0x080c, 0x8940, 0x00d6, 0x2069, 0xaf9d, 0x2d04, + 0xa005, 0x0168, 0x6018, 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138, + 0x2069, 0xad1c, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, + 0x0078, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c, + 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x0428, + 0x080c, 0x85f3, 0x2009, 0xb28e, 0x2134, 0xa6b4, 0x00ff, 0xa686, + 0x0005, 0x01e0, 0xa686, 0x000b, 0x01b0, 0x2009, 0xb28f, 0x2104, + 0xa084, 0xff00, 0x1118, 0xa686, 0x0009, 0x0180, 0xa086, 0x1900, + 0x1150, 0xa686, 0x0009, 0x0150, 0x2001, 0x0004, 0x080c, 0x4c30, + 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x0005, 0x00d6, 0x6010, + 0x2068, 0x080c, 0x9596, 0x0128, 0x6838, 0xd0fc, 0x0110, 0x00de, + 0x0c90, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, + 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x0c28, + 0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xad00, 0x080c, + 0x48f5, 0x00ee, 0x0010, 0x080c, 0x2ad9, 0x00de, 0x08a0, 0x080c, + 0x8940, 0x1158, 0x2001, 0x0004, 0x080c, 0x4c30, 0x6003, 0x0001, + 0x6007, 0x0003, 0x080c, 0x67ee, 0x0020, 0x080c, 0x85f3, 0x080c, + 0x87bd, 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c, 0x4c30, + 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x67ee, 0x0010, 0x080c, + 0x87bd, 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c, 0x4c30, + 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, 0x0010, 0x080c, + 0x87bd, 0x0005, 0x2009, 0xb28e, 0x2104, 0xa086, 0x0003, 0x1138, + 0x2009, 0xb28f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, + 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, + 0x080c, 0x4ceb, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, + 0x0036, 0x0016, 0x6018, 0x2068, 0x2071, 0xad34, 0x2e04, 0xa085, + 0x0003, 0x2072, 0x080c, 0x89cc, 0x0538, 0x2001, 0xad52, 0x2004, + 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xa96c, + 0x2001, 0xad0c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, + 0x0001, 0x080c, 0x2aac, 0x2071, 0xad00, 0x080c, 0x28fa, 0x00c6, + 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, 0x2bc9, 0x8108, + 0x1f04, 0x897d, 0x015e, 0x00ce, 0x080c, 0x8943, 0x6813, 0x00ff, + 0x6817, 0xfffe, 0x2071, 0xb280, 0x2079, 0x0100, 0x2e04, 0xa084, + 0x00ff, 0x2069, 0xad1b, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, + 0x2069, 0xad1c, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0xa084, + 0xff00, 0x001e, 0xa105, 0x2009, 0xad27, 0x200a, 0x2200, 0xa084, + 0x00ff, 0x2008, 0x080c, 0x26a0, 0x080c, 0x574f, 0x0170, 0x2069, + 0xb28e, 0x2071, 0xaf9f, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818, + 0x700a, 0x681c, 0x700e, 0x080c, 0x9903, 0x0040, 0x2001, 0x0006, + 0x080c, 0x4c30, 0x080c, 0x2aff, 0x080c, 0x8078, 0x001e, 0x003e, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156, + 0x2019, 0xad27, 0x231c, 0x83ff, 0x01e8, 0x2071, 0xb280, 0x2e14, + 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x1190, + 0x2011, 0xb296, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, + 0x1148, 0x2011, 0xb29a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, + 0x8a7c, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6, + 0x2071, 0xb28c, 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086, + 0x0800, 0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086, + 0x0100, 0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006, + 0x0010, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2029, 0xafd0, 0x252c, 0x2021, 0xafd6, 0x2424, 0x2061, 0xb400, + 0x2071, 0xad00, 0x7244, 0x7064, 0xa202, 0x16f0, 0x080c, 0xa990, + 0x05a0, 0x671c, 0xa786, 0x0001, 0x0580, 0xa786, 0x0007, 0x0568, + 0x2500, 0xac06, 0x0550, 0x2400, 0xac06, 0x0538, 0x00c6, 0x6000, + 0xa086, 0x0004, 0x1110, 0x080c, 0x190b, 0xa786, 0x0008, 0x1148, + 0x080c, 0x9789, 0x1130, 0x00ce, 0x080c, 0x85f3, 0x080c, 0x974e, + 0x00a0, 0x6010, 0x2068, 0x080c, 0x9596, 0x0160, 0xa786, 0x0003, + 0x11e8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, + 0x080c, 0x9742, 0x080c, 0x974e, 0x00ce, 0xace0, 0x0018, 0x7058, + 0xac02, 0x1210, 0x0804, 0x8a2a, 0x012e, 0x000e, 0x002e, 0x004e, + 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0xa786, 0x0006, + 0x1d00, 0x080c, 0xa91f, 0x0c30, 0x220c, 0x2304, 0xa106, 0x1130, + 0x8210, 0x8318, 0x1f04, 0x8a7c, 0xa006, 0x0005, 0x2304, 0xa102, + 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, + 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, 0x080c, 0x9778, + 0x0120, 0x080c, 0x9789, 0x0168, 0x0028, 0x080c, 0x2aff, 0x080c, + 0x9789, 0x0138, 0x080c, 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, + 0x0005, 0x080c, 0x85f3, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x8ac2, + 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, + 0x8ac2, 0x8ac2, 0x8ac4, 0x8ac4, 0x8ac4, 0x8ac4, 0x8ac2, 0x8ac2, + 0x8ac2, 0x8ac4, 0x080c, 0x14f6, 0x600b, 0xffff, 0x6003, 0x0001, + 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, + 0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040, + 0x0804, 0x8b5e, 0xa186, 0x0027, 0x11e8, 0x080c, 0x6b73, 0x080c, + 0x2ad9, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9596, 0x0168, 0x6837, + 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, + 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, 0x8078, 0x080c, + 0x6c50, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040, + 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186, + 0x0047, 0x190c, 0x14f6, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6699, + 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002, + 0x1110, 0x0804, 0x8b98, 0x080c, 0x80be, 0x0005, 0x0002, 0x8b3c, + 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, + 0x8b3a, 0x8b3a, 0x8b57, 0x8b57, 0x8b57, 0x8b57, 0x8b3a, 0x8b57, + 0x8b3a, 0x8b57, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x00d6, 0x6110, + 0x2168, 0x080c, 0x9596, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006, + 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c, 0x510c, 0x080c, + 0x9742, 0x00de, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c, + 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x0002, 0x8b74, + 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, + 0x8b72, 0x8b72, 0x8b86, 0x8b86, 0x8b86, 0x8b86, 0x8b72, 0x8b91, + 0x8b72, 0x8b86, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x2001, 0xafa5, + 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x6c50, 0x6010, 0xa088, + 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x6b73, + 0x2001, 0xafa5, 0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x6c50, + 0x0005, 0x080c, 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, + 0xa182, 0x0040, 0x0002, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, + 0x8bb0, 0x8c88, 0x8ca9, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, + 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x080c, 0x14f6, + 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xb280, 0x7124, 0x610a, + 0x2071, 0xb28c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, + 0x0904, 0x8c54, 0xa68c, 0x0c00, 0x01e8, 0x00f6, 0x2c78, 0x080c, + 0x5029, 0x00fe, 0x0198, 0x684c, 0xd0ac, 0x0180, 0x6020, 0xd0dc, + 0x1168, 0x6850, 0xd0bc, 0x1150, 0x7318, 0x6814, 0xa306, 0x1904, + 0x8c66, 0x731c, 0x6810, 0xa306, 0x1904, 0x8c66, 0x7318, 0x6b62, + 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0518, 0xa186, + 0x0028, 0x1128, 0x080c, 0x9767, 0x684b, 0x001c, 0x00e8, 0xd6dc, + 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, 0x6914, 0x6a10, + 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, 0x701c, 0xa206, + 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x684b, + 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, + 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, 0xb299, 0x2004, + 0xa005, 0x1118, 0xc6c4, 0x0804, 0x8bbf, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0xb298, 0xad90, 0x0019, 0x080c, 0x927f, 0x003e, + 0xd6cc, 0x0904, 0x8c79, 0x7124, 0x695a, 0x81ff, 0x0904, 0x8c79, + 0xa192, 0x0021, 0x1250, 0x2071, 0xb298, 0x831c, 0x2300, 0xae18, + 0xad90, 0x001d, 0x080c, 0x927f, 0x04a0, 0x6838, 0xd0fc, 0x0120, + 0x2009, 0x0020, 0x695a, 0x0c78, 0x00f6, 0x2d78, 0x080c, 0x9224, + 0x00fe, 0x080c, 0x926f, 0x0438, 0x00f6, 0x2c78, 0x080c, 0x5029, + 0x00fe, 0x0188, 0x684c, 0xd0ac, 0x0170, 0x6020, 0xd0dc, 0x1158, + 0x6850, 0xd0bc, 0x1140, 0x684c, 0xd0f4, 0x1128, 0x080c, 0x9866, + 0x00de, 0x00ee, 0x00e0, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, + 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, + 0x8e04, 0x080c, 0x510c, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, + 0x080c, 0x9834, 0x00de, 0x00ee, 0x1110, 0x080c, 0x8078, 0x0005, + 0x00f6, 0x6003, 0x0003, 0x2079, 0xb28c, 0x7c04, 0x7b00, 0x7e0c, + 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0120, 0x6003, 0x0002, + 0x00fe, 0x0005, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f, + 0x0000, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x680b, 0x080c, 0x6d0d, + 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, + 0xa182, 0x0040, 0x0002, 0x8cce, 0x8cce, 0x8cce, 0x8cce, 0x8cce, + 0x8cd0, 0x8d61, 0x8cce, 0x8cce, 0x8d77, 0x8ddb, 0x8cce, 0x8cce, + 0x8cce, 0x8cce, 0x8dea, 0x8cce, 0x8cce, 0x8cce, 0x080c, 0x14f6, + 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xb28c, 0x6110, 0x2178, + 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, + 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x8d5c, 0xa694, + 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, + 0xa284, 0x0300, 0x0904, 0x8d5c, 0x080c, 0x15d9, 0x090c, 0x14f6, + 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, + 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, + 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, + 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, + 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, + 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, + 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, + 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, + 0x2019, 0xb298, 0xad90, 0x0019, 0x080c, 0x927f, 0x003e, 0xd6cc, + 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, + 0x2071, 0xb298, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, + 0x927f, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, + 0x0c78, 0x2d78, 0x080c, 0x9224, 0x00de, 0x00ee, 0x00fe, 0x007e, + 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xb28c, 0x7c04, 0x7b00, + 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, + 0x00fe, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x781a, 0x0005, 0x00d6, + 0x00f6, 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0120, 0x2001, 0xafa5, + 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x6c05, 0x080c, 0x6d0d, + 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x8dd9, 0xd1cc, 0x0540, + 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, + 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, + 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x8da1, 0x015e, + 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1600, + 0x0418, 0x0016, 0x080c, 0x1600, 0x00de, 0x080c, 0x926f, 0x00e0, + 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, + 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118, + 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010, + 0x684b, 0x0000, 0x080c, 0x510c, 0x080c, 0x9834, 0x1110, 0x080c, + 0x8078, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x7a64, 0x6003, + 0x0002, 0x2001, 0xafa5, 0x2004, 0x603e, 0x080c, 0x6c05, 0x080c, + 0x6d0d, 0x0005, 0x080c, 0x6c05, 0x080c, 0x2ad9, 0x00d6, 0x6110, + 0x2168, 0x080c, 0x9596, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, + 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, + 0x8078, 0x080c, 0x6d0d, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138, + 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, + 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x8e28, 0x8e28, 0x8e28, + 0x8e28, 0x8e28, 0x8e2a, 0x8e28, 0x8ee3, 0x8eef, 0x8e28, 0x8e28, + 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, + 0x080c, 0x14f6, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xb28c, + 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c, + 0x5029, 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4, + 0x0120, 0x080c, 0x9866, 0x0804, 0x8ede, 0x7e46, 0x7f4c, 0xc7e5, + 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904, + 0x8ed4, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, + 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x8ed2, 0xa686, 0x0100, + 0x1140, 0x2001, 0xb299, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46, + 0x0c28, 0x080c, 0x15d9, 0x090c, 0x14f6, 0x2d00, 0x784a, 0x7f4c, + 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, + 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, + 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, + 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, + 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, + 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, + 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, + 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xb298, + 0xad90, 0x0019, 0x080c, 0x927f, 0x003e, 0xd6cc, 0x01d8, 0x7124, + 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xb298, + 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x927f, 0x0050, + 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, + 0x080c, 0x9224, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, 0x0001, + 0x2071, 0xb28c, 0x7218, 0x731c, 0x080c, 0x186f, 0x00de, 0x00ee, + 0x00fe, 0x007e, 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, 0x2001, + 0xafa5, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, 0x6110, 0x2168, + 0x694c, 0xd1e4, 0x0904, 0x8ff3, 0x603f, 0x0000, 0x00f6, 0x2c78, + 0x080c, 0x5029, 0x00fe, 0x0548, 0x6814, 0x6910, 0xa115, 0x0528, + 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x01f8, 0x684c, 0xc0e4, + 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, 0x697c, + 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020, + 0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, + 0x00de, 0x080c, 0x9866, 0x0804, 0x8ff3, 0x694c, 0xd1cc, 0x0904, + 0x8fc3, 0x6948, 0x6838, 0xd0fc, 0x0904, 0x8f88, 0x0016, 0x684c, + 0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, + 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, + 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, + 0x0015, 0x080c, 0x99ee, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, + 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, + 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x8e04, + 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, + 0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, + 0x8318, 0x8210, 0x1f04, 0x8f76, 0x015e, 0x00fe, 0x000e, 0x6852, + 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1600, 0x0804, 0x8fee, + 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, + 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, + 0x99ee, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, + 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x8e04, 0x6860, 0x7862, + 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, 0x1600, 0x00de, + 0x080c, 0x926f, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, + 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, + 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0x99ee, 0x0118, + 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, + 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, + 0xa115, 0x0110, 0x080c, 0x8e04, 0x080c, 0x510c, 0x080c, 0x9834, + 0x1110, 0x080c, 0x8078, 0x00de, 0x0005, 0x080c, 0x6b73, 0x0010, + 0x080c, 0x6c05, 0x080c, 0x9596, 0x01c0, 0x00d6, 0x6110, 0x2168, + 0x6837, 0x0103, 0x2009, 0xad0c, 0x210c, 0xd18c, 0x11c0, 0xd184, + 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, 0xabfa, + 0x6847, 0x0000, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x080c, + 0x6c50, 0x080c, 0x6d0d, 0x0005, 0x684b, 0x0004, 0x0c88, 0x684b, + 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0x9038, 0x9038, 0x9038, + 0x9038, 0x9038, 0x903a, 0x9038, 0x903d, 0x9038, 0x9038, 0x9038, + 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, + 0x080c, 0x14f6, 0x080c, 0x8078, 0x0005, 0x0006, 0x0026, 0xa016, + 0x080c, 0x1824, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, 0x0002, + 0x9051, 0x904f, 0x904f, 0x905d, 0x904f, 0x904f, 0x904f, 0x080c, + 0x14f6, 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, + 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, + 0x00e6, 0x2071, 0xb280, 0x7224, 0x6212, 0x7220, 0x080c, 0x9586, + 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, 0x6d18, + 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0x928f, 0x00ce, 0x0128, + 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, + 0x0001, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00f6, 0x2278, 0x080c, + 0x5029, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, 0x2260, + 0x603f, 0x0000, 0x080c, 0x9866, 0x00ce, 0x00ee, 0x00de, 0x005e, + 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, + 0x0a0c, 0x14f6, 0xa08a, 0x008c, 0x1a0c, 0x14f6, 0xa082, 0x0085, + 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x14f6, + 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0x90be, + 0x90c0, 0x90c0, 0x90be, 0x90be, 0x90be, 0x90be, 0x080c, 0x14f6, + 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0xa186, + 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, 0xa186, + 0x0027, 0x11e8, 0x080c, 0x6b73, 0x080c, 0x2ad9, 0x00d6, 0x6010, + 0x2068, 0x080c, 0x9596, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000, + 0x684b, 0x0029, 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, + 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c, 0x80be, 0x0ce0, 0xa186, + 0x0014, 0x1dd0, 0x080c, 0x6b73, 0x00d6, 0x6010, 0x2068, 0x080c, + 0x9596, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006, + 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0x910e, 0x910c, 0x910c, + 0x910c, 0x910c, 0x910c, 0x9126, 0x080c, 0x14f6, 0x080c, 0x6b73, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x2001, 0xafa3, 0x0010, 0x2001, 0xafa4, 0x2004, + 0x6016, 0x6003, 0x000c, 0x080c, 0x6c50, 0x0005, 0x080c, 0x6b73, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x2001, 0xafa3, 0x0010, 0x2001, 0xafa4, 0x2004, + 0x6016, 0x6003, 0x000e, 0x080c, 0x6c50, 0x0005, 0xa182, 0x008c, + 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x80be, 0x0005, + 0x914f, 0x914f, 0x914f, 0x914f, 0x9151, 0x91a4, 0x914f, 0x080c, + 0x14f6, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0168, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x00de, 0x0804, 0x91b7, 0x080c, 0x9742, 0x080c, + 0x9596, 0x01c8, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, + 0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, + 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9803, 0x6847, + 0x0000, 0x080c, 0x510c, 0x2c68, 0x080c, 0x8022, 0x01c0, 0x6003, + 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0xb28e, 0x210c, + 0x6136, 0x2009, 0xb28f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, + 0x9956, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, 0x67a8, 0x2d60, + 0x080c, 0x8078, 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5029, + 0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, + 0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, + 0x2c68, 0x080c, 0x9a34, 0x1904, 0x91fc, 0x080c, 0x8022, 0x01d8, + 0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, + 0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, + 0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, 0x9956, 0x080c, + 0x67a8, 0x080c, 0x6c50, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, + 0x080c, 0x9596, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, + 0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, + 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9803, 0x6847, 0x0000, + 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, 0x8078, 0x0005, + 0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, 0x0140, 0x6837, + 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x510c, 0x00de, + 0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, + 0x0027, 0x0118, 0x080c, 0x80be, 0x0030, 0x080c, 0x6b73, 0x080c, + 0x974e, 0x080c, 0x6c50, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, + 0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, + 0x2130, 0x2069, 0xb298, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, + 0xaf90, 0x001d, 0x080c, 0x927f, 0xa6b2, 0x0020, 0x7804, 0xa06d, + 0x0110, 0x080c, 0x1600, 0x080c, 0x15d9, 0x0500, 0x8528, 0x6837, + 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, + 0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, + 0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, + 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, + 0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, + 0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, + 0x510c, 0x2f68, 0x0cb8, 0x080c, 0x510c, 0x00fe, 0x0005, 0x0156, + 0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, + 0x2012, 0x8318, 0x8210, 0x1f04, 0x9286, 0x015e, 0x0005, 0x0066, + 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, + 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, + 0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, + 0x0005, 0x92c3, 0x92c3, 0x92be, 0x92e5, 0x92b1, 0x92be, 0x92e5, + 0x92be, 0x080c, 0x14f6, 0x0036, 0x2019, 0x0010, 0x080c, 0xa566, + 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0xa006, 0x0005, + 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068, + 0x080c, 0x9596, 0x01c0, 0x6834, 0xa086, 0x0139, 0x1128, 0x684b, + 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, 0x0005, 0x080c, + 0x51df, 0x080c, 0x9803, 0x080c, 0x510c, 0x080c, 0x8078, 0xa085, + 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010, + 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x92fc, 0x9319, 0x92fe, 0x9338, + 0x9316, 0x92fc, 0x92be, 0x92c3, 0x92c3, 0x92be, 0x92be, 0x92be, + 0x92be, 0x92be, 0x92be, 0x92be, 0x080c, 0x14f6, 0x86ff, 0x1198, + 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0x9803, + 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, + 0x67a8, 0x080c, 0x6c50, 0xa085, 0x0001, 0x0005, 0x080c, 0x190b, + 0x0c28, 0x00e6, 0x2071, 0xafc7, 0x7024, 0xac06, 0x1110, 0x080c, + 0x79e1, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, 0x0086, + 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x7b9a, 0x009e, 0x008e, + 0x0010, 0x080c, 0x78de, 0x00ee, 0x1948, 0x080c, 0x92be, 0x0005, + 0x0036, 0x00e6, 0x2071, 0xafc7, 0x703c, 0xac06, 0x1140, 0x2019, + 0x0000, 0x080c, 0x7a64, 0x00ee, 0x003e, 0x0804, 0x92fe, 0x080c, + 0x7cb8, 0x00ee, 0x003e, 0x1904, 0x92fe, 0x080c, 0x92be, 0x0005, + 0x00c6, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9369, + 0x93d3, 0x9501, 0x9374, 0x974e, 0x9369, 0xa558, 0x8078, 0x93d3, + 0x9362, 0x955f, 0x080c, 0x14f6, 0x080c, 0x9789, 0x1110, 0x080c, + 0x85f3, 0x0005, 0x080c, 0x6b73, 0x080c, 0x6c50, 0x080c, 0x8078, + 0x0005, 0x6017, 0x0001, 0x0005, 0x6010, 0xa080, 0x0019, 0x2c02, + 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x938f, + 0x9391, 0x93b1, 0x93c3, 0x93d0, 0x938f, 0x9369, 0x9369, 0x9369, + 0x93c3, 0x93c3, 0x938f, 0x938f, 0x938f, 0x938f, 0x93cd, 0x080c, + 0x14f6, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, + 0xafc7, 0x7024, 0xac06, 0x0190, 0x080c, 0x78de, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xafa4, 0x2004, 0x6016, + 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ee, 0x0005, 0x6017, 0x0001, + 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x67a8, + 0x080c, 0x6c50, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068, + 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x8078, 0x0005, + 0x080c, 0x190b, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, + 0x000b, 0x0005, 0x93ea, 0x9371, 0x93ec, 0x93ea, 0x93ec, 0x93ec, + 0x936a, 0x93ea, 0x9364, 0x9364, 0x93ea, 0x93ea, 0x93ea, 0x93ea, + 0x93ea, 0x93ea, 0x080c, 0x14f6, 0x00d6, 0x6018, 0x2068, 0x6804, + 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x14f6, 0x000b, + 0x0005, 0x9405, 0x94a7, 0x9407, 0x9441, 0x9407, 0x9441, 0x9407, + 0x9411, 0x9405, 0x9441, 0x9405, 0x942d, 0x080c, 0x14f6, 0x6004, + 0xa08e, 0x0016, 0x0588, 0xa08e, 0x0004, 0x0570, 0xa08e, 0x0002, + 0x0558, 0x6004, 0x080c, 0x9789, 0x0904, 0x94c0, 0xa08e, 0x0021, + 0x0904, 0x94c4, 0xa08e, 0x0022, 0x0904, 0x94c0, 0xa08e, 0x003d, + 0x0904, 0x94c4, 0xa08e, 0x0039, 0x0904, 0x94c8, 0xa08e, 0x0035, + 0x0904, 0x94c8, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150, + 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086, + 0x0006, 0x0110, 0x080c, 0x2ad9, 0x080c, 0x85f3, 0x080c, 0x974e, + 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9498, + 0xa186, 0x0002, 0x1518, 0x6018, 0x2068, 0x2001, 0xad34, 0x2004, + 0xd0ac, 0x1904, 0x94ea, 0x68a0, 0xd0bc, 0x1904, 0x94ea, 0x6840, + 0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x8022, + 0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce, + 0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa086, 0x007e, 0x1170, 0x2009, 0xad34, 0x2104, 0xc085, 0x200a, + 0x00e6, 0x2071, 0xad00, 0x080c, 0x48f5, 0x00ee, 0x080c, 0x85f3, + 0x0020, 0x080c, 0x85f3, 0x080c, 0x2ad9, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x080c, 0x2aff, 0x012e, 0x00ee, 0x080c, 0x974e, 0x0005, + 0x2001, 0x0002, 0x080c, 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00de, 0x00ce, 0x0c80, 0x00c6, + 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d58, 0x6018, 0x2068, 0x6840, + 0xa084, 0x00ff, 0xa005, 0x0904, 0x946e, 0x8001, 0x6842, 0x6003, + 0x0001, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00de, 0x00ce, 0x08b8, + 0x080c, 0x85f3, 0x0804, 0x943e, 0x080c, 0x8621, 0x0804, 0x943e, + 0x00d6, 0x2c68, 0x6104, 0x080c, 0x9a34, 0x00de, 0x0118, 0x080c, + 0x8078, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, + 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, + 0x600a, 0x2001, 0xafa4, 0x2004, 0x6016, 0x080c, 0x67a8, 0x080c, + 0x6c50, 0x0005, 0x00de, 0x00ce, 0x080c, 0x85f3, 0x080c, 0x2ad9, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2aff, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, 0x00ee, + 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, + 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, + 0x9518, 0x9369, 0x9518, 0x9371, 0x951a, 0x9371, 0x9527, 0x9518, + 0x080c, 0x14f6, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, 0x008b, + 0x6003, 0x000d, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0005, 0x080c, + 0x9742, 0x080c, 0x9596, 0x0580, 0x080c, 0x2ad9, 0x00d6, 0x080c, + 0x9596, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006, + 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x510c, 0x2c68, + 0x080c, 0x8022, 0x0150, 0x6818, 0x601a, 0x080c, 0x9956, 0x00c6, + 0x2d60, 0x080c, 0x974e, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013, + 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x67ee, 0x080c, 0x6c50, 0x0010, 0x080c, 0x974e, 0x0005, 0x6000, + 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x9576, 0x9576, + 0x9576, 0x9578, 0x9579, 0x9576, 0x9576, 0x9576, 0x9576, 0x9576, + 0x9576, 0x9576, 0x9576, 0x9576, 0x9576, 0x9576, 0x080c, 0x14f6, + 0x0005, 0x080c, 0x7cb8, 0x190c, 0x14f6, 0x6110, 0x2168, 0x684b, + 0x0006, 0x080c, 0x510c, 0x080c, 0x8078, 0x0005, 0xa284, 0x0007, + 0x1158, 0xa282, 0xb400, 0x0240, 0x2001, 0xad16, 0x2004, 0xa202, + 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210, + 0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2061, 0xb400, 0x2071, 0xad00, 0x7344, + 0x7064, 0xa302, 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0x98e3, + 0x0148, 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x00c6, 0x080c, + 0x8078, 0x00ce, 0xace0, 0x0018, 0x7058, 0xac02, 0x1208, 0x0c38, + 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, + 0x0016, 0xa188, 0xae34, 0x210c, 0x81ff, 0x0170, 0x2061, 0xb400, + 0x2071, 0xad00, 0x0016, 0x080c, 0x8022, 0x001e, 0x0138, 0x611a, + 0x080c, 0x2ad9, 0x080c, 0x8078, 0xa006, 0x0010, 0xa085, 0x0001, + 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x8022, 0x005e, 0x0180, 0x6612, 0x651a, + 0x080c, 0x9956, 0x601f, 0x0003, 0x2009, 0x004b, 0x080c, 0x80a7, + 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, + 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, + 0x8022, 0x005e, 0x0508, 0x6013, 0x0000, 0x651a, 0x080c, 0x9956, + 0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x4ecf, 0x00ce, 0x080c, + 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, + 0xa712, 0x007e, 0x2009, 0x004c, 0x080c, 0x80a7, 0xa085, 0x0001, + 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6, + 0x0046, 0x00c6, 0x080c, 0x8022, 0x2c78, 0x00ce, 0x0180, 0x7e12, + 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9683, + 0x2f60, 0x2009, 0x004d, 0x080c, 0x80a7, 0xa085, 0x0001, 0x004e, + 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, + 0x8022, 0x2c78, 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f, + 0x0003, 0x2021, 0x0005, 0x0439, 0x2f60, 0x2009, 0x004e, 0x080c, + 0x80a7, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, + 0x00c6, 0x0046, 0x00c6, 0x080c, 0x8022, 0x2c78, 0x00ce, 0x0178, + 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x0059, + 0x2f60, 0x2009, 0x0052, 0x080c, 0x80a7, 0xa085, 0x0001, 0x004e, + 0x00ce, 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, + 0x080c, 0x4e71, 0x0118, 0x2001, 0x9688, 0x0028, 0x080c, 0x4e43, + 0x0158, 0x2001, 0x968e, 0x0006, 0xa00e, 0x2400, 0x080c, 0x51df, + 0x080c, 0x510c, 0x000e, 0x0807, 0x2418, 0x080c, 0x6b15, 0x62a0, + 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x6900, + 0x008e, 0x080c, 0x681d, 0x2f08, 0x2648, 0x080c, 0xa712, 0x613c, + 0x81ff, 0x090c, 0x69a9, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188, + 0x660a, 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x001f, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x8022, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0x9956, + 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x80a7, + 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188, + 0x660a, 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x003d, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x9807, 0x001e, 0x0180, 0x611a, 0x080c, 0x9956, 0x601f, + 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x80a7, 0xa085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188, 0x660a, + 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x0044, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, + 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000, + 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001, + 0xafa3, 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004, + 0x6016, 0x080c, 0xabb4, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066, + 0x00c6, 0x00d6, 0x2031, 0xad52, 0x2634, 0xd6e4, 0x0128, 0x6618, + 0x2660, 0x6e48, 0x080c, 0x4dfc, 0x00de, 0x00ce, 0x006e, 0x0005, + 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, + 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, + 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086, + 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085, + 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x8022, 0x001e, 0x0190, 0x611a, 0x080c, 0x9956, + 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2ad9, 0x2009, 0x0028, + 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0xad20, 0x2204, 0xa086, + 0x0074, 0x1148, 0x080c, 0x8943, 0x6003, 0x0001, 0x6007, 0x0029, + 0x080c, 0x67ee, 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x0005, + 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x4c30, 0x00e8, + 0xa186, 0x0015, 0x11e8, 0x2011, 0xad20, 0x2204, 0xa086, 0x0014, + 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, 0x4d72, 0x00de, 0x080c, + 0x89f7, 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, + 0x0138, 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, 0x81f6, 0x0020, + 0x080c, 0x85f3, 0x080c, 0x8078, 0x0005, 0x6848, 0xa086, 0x0005, + 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6, + 0x0126, 0x2071, 0xad00, 0x2091, 0x8000, 0x7544, 0xa582, 0x0001, + 0x0608, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, + 0x0018, 0x7058, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xb400, 0x0c98, + 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0018, 0x7058, 0xa502, + 0x1230, 0x754a, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704b, + 0xb400, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xb28c, 0x7014, + 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, + 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ee, 0x0005, 0x00c6, 0x00f6, + 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f, + 0x0013, 0x00ce, 0x0005, 0x9369, 0x985e, 0x9861, 0x9864, 0xa9a7, + 0xa9c2, 0xa9c5, 0x9369, 0x9369, 0x080c, 0x14f6, 0xe000, 0xe000, + 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78, + 0x080c, 0x5029, 0x0538, 0x080c, 0x8022, 0x1128, 0x2001, 0xafa5, + 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0x9956, 0x781c, + 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020, + 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, + 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x67a8, 0x080c, + 0x6c50, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032, + 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a, + 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078, + 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834, + 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, + 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001, + 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, 0x67a8, 0x6803, 0x0002, + 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5029, 0x1118, + 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022, + 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x190b, + 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034, + 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e, + 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140, + 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001, + 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, + 0x2001, 0xaf9f, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, + 0x6665, 0x2001, 0xafa3, 0x82ff, 0x1110, 0x2011, 0x0002, 0x2202, + 0x2001, 0xafa1, 0x200c, 0x8000, 0x2014, 0x2071, 0xaf8d, 0x711a, + 0x721e, 0x2001, 0x0064, 0x080c, 0x6665, 0x2001, 0xafa4, 0x82ff, + 0x1110, 0x2011, 0x0002, 0x2202, 0x2009, 0xafa5, 0xa280, 0x000a, + 0x200a, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, + 0x00e6, 0x2001, 0xafa3, 0x2003, 0x0028, 0x2001, 0xafa4, 0x2003, + 0x0014, 0x2071, 0xaf8d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, + 0xafa5, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054, + 0xa06d, 0x0110, 0x080c, 0x15f0, 0x00de, 0x0005, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0178, + 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, + 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xad00, 0xa186, 0x0015, + 0x1500, 0x7080, 0xa086, 0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c, + 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x6e05, 0x01d8, 0x706c, 0x6a50, + 0xa206, 0x1160, 0x7070, 0x6a54, 0xa206, 0x1140, 0x6218, 0xa290, + 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2b1e, 0x080c, 0x81f6, + 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x00fe, 0x00ee, 0x00de, + 0x0005, 0x7050, 0x6a54, 0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0180, 0x611a, + 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0043, + 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xad00, 0xa186, 0x0015, + 0x11c0, 0x7080, 0xa086, 0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f, + 0x2c78, 0x080c, 0x6e05, 0x01a8, 0x706c, 0x6a08, 0xa206, 0x1130, + 0x7070, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2ad9, 0x080c, 0x81f6, + 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x00fe, 0x00ee, 0x00de, + 0x0005, 0x7050, 0x6a0c, 0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026, + 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0150, + 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e, + 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6310, + 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x1188, 0x00c6, 0x6318, + 0x2360, 0x2009, 0x0000, 0x080c, 0x4f6e, 0x1108, 0xc185, 0x6000, + 0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66, + 0x3918, 0xa398, 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6, + 0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c, + 0x510c, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, + 0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, 0x9586, 0x01f0, + 0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, + 0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, + 0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, + 0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, + 0x0cc8, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, + 0x006e, 0x0005, 0x9a7a, 0x9eff, 0xa027, 0x9a7a, 0x9a7a, 0x9a7a, + 0x9a7a, 0x9a7a, 0x9ab2, 0xa0a3, 0x9a7a, 0x9a7a, 0x9a7a, 0x9a7a, + 0x9a7a, 0x9a7a, 0x080c, 0x14f6, 0x0066, 0x6000, 0xa0b2, 0x0010, + 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x9a95, 0xa4fd, 0x9a95, + 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0xa4c1, 0xa545, 0x9a95, + 0xaaea, 0xab1a, 0xaaea, 0xab1a, 0x9a95, 0x080c, 0x14f6, 0x0066, + 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, + 0x9ab0, 0xa1d8, 0xa295, 0xa2c2, 0xa346, 0x9ab0, 0xa433, 0xa3de, + 0xa0af, 0xa497, 0xa4ac, 0x9ab0, 0x9ab0, 0x9ab0, 0x9ab0, 0x9ab0, + 0x080c, 0x14f6, 0xa1b2, 0x0080, 0x1a0c, 0x14f6, 0x2100, 0xa1b2, + 0x0040, 0x1a04, 0x9e79, 0x0002, 0x9afc, 0x9cab, 0x9afc, 0x9afc, + 0x9afc, 0x9cb2, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, + 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, + 0x9afc, 0x9afc, 0x9afc, 0x9afe, 0x9b5a, 0x9b65, 0x9ba6, 0x9bc0, + 0x9c3e, 0x9c9c, 0x9afc, 0x9afc, 0x9cb5, 0x9afc, 0x9afc, 0x9cc4, + 0x9ccb, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9d42, 0x9afc, + 0x9afc, 0x9d4d, 0x9afc, 0x9afc, 0x9d18, 0x9afc, 0x9afc, 0x9afc, + 0x9d61, 0x9afc, 0x9afc, 0x9afc, 0x9dd5, 0x9afc, 0x9afc, 0x9afc, + 0x9afc, 0x9afc, 0x9afc, 0x9e40, 0x080c, 0x14f6, 0x080c, 0x502d, + 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, + 0x1140, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, + 0x9ca6, 0x080c, 0x501d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, + 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x68e7, + 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, + 0x007e, 0x001e, 0x2e60, 0x080c, 0x4ecf, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4ceb, 0x00ce, + 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, + 0x080c, 0xa656, 0x1904, 0x9ba0, 0x080c, 0xa5f6, 0x1120, 0x6007, + 0x0008, 0x0804, 0x9ca6, 0x6007, 0x0009, 0x0804, 0x9ca6, 0x080c, + 0xa801, 0x0128, 0x080c, 0xa656, 0x0d78, 0x0804, 0x9ba0, 0x6013, + 0x1900, 0x0c88, 0x6106, 0x080c, 0xa5a6, 0x6007, 0x0006, 0x0804, + 0x9ca6, 0x6007, 0x0007, 0x0804, 0x9ca6, 0x080c, 0xab4e, 0x1904, + 0x9e76, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4, + 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686, + 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xa6b4, 0x11a0, 0xa686, + 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, + 0x0000, 0x080c, 0x2b1e, 0x002e, 0x080c, 0x4d72, 0x6007, 0x000a, + 0x00de, 0x0804, 0x9ca6, 0x6007, 0x000b, 0x00de, 0x0804, 0x9ca6, + 0x080c, 0x2ad9, 0x6007, 0x0001, 0x0804, 0x9ca6, 0x080c, 0xab4e, + 0x1904, 0x9e76, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686, + 0x0707, 0x0d70, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, + 0x0000, 0x080c, 0x2b1e, 0x002e, 0x6007, 0x000c, 0x0804, 0x9ca6, + 0x080c, 0x502d, 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, + 0xa086, 0x0008, 0x1110, 0x0804, 0x9b09, 0x080c, 0x501d, 0x6618, + 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06e8, + 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x4c5d, 0x002e, 0x0050, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, + 0x1904, 0x9ba0, 0x080c, 0xa6c1, 0x1120, 0x6007, 0x000e, 0x0804, + 0x9ca6, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, + 0x8427, 0x0046, 0x080c, 0x2ad9, 0x004e, 0x0016, 0xa006, 0x2009, + 0xad52, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xa96c, + 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, + 0x004e, 0x6007, 0x0001, 0x0804, 0x9ca6, 0x2001, 0x0001, 0x080c, + 0x4c1e, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, + 0xad05, 0x2011, 0xb290, 0x080c, 0x8a7c, 0x003e, 0x002e, 0x001e, + 0x015e, 0xa005, 0x0168, 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, + 0x0a04, 0x9ba0, 0xa682, 0x0007, 0x0a04, 0x9bea, 0x0804, 0x9ba0, + 0x6013, 0x1900, 0x6007, 0x0009, 0x0804, 0x9ca6, 0x080c, 0x502d, + 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, + 0x1110, 0x0804, 0x9b09, 0x080c, 0x501d, 0x6618, 0xa6b0, 0x0001, + 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06b0, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0x9ba0, + 0x080c, 0xa6e9, 0x1130, 0x080c, 0xa5f6, 0x1118, 0x6007, 0x0010, + 0x04e8, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, + 0x8427, 0x0046, 0x080c, 0x2ad9, 0x004e, 0x0016, 0xa006, 0x2009, + 0xad52, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xa96c, + 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, + 0x004e, 0x6007, 0x0001, 0x00d0, 0x080c, 0xa801, 0x0140, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0958, 0x0804, 0x9ba0, 0x6013, + 0x1900, 0x6007, 0x0009, 0x0050, 0x080c, 0xab4e, 0x1904, 0x9e76, + 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6007, 0x0012, 0x6003, 0x0001, + 0x080c, 0x67ee, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x67ee, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xab4e, 0x1904, + 0x9e76, 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6007, 0x0020, 0x6003, + 0x0001, 0x080c, 0x67ee, 0x0005, 0x6007, 0x0023, 0x6003, 0x0001, + 0x080c, 0x67ee, 0x0005, 0x080c, 0xab4e, 0x1904, 0x9e76, 0x080c, + 0x9e98, 0x1904, 0x9ba0, 0x0016, 0x0026, 0x2011, 0xb291, 0x2214, + 0xa286, 0xffff, 0x0190, 0x2c08, 0x080c, 0x9586, 0x01d8, 0x2260, + 0x2011, 0xb290, 0x2214, 0x6008, 0xa206, 0x11a0, 0x6018, 0xa190, + 0x0006, 0x2214, 0xa206, 0x01e0, 0x0068, 0x2011, 0xb290, 0x2214, + 0x2c08, 0x080c, 0xa940, 0x11a0, 0x2011, 0xb291, 0x2214, 0xa286, + 0xffff, 0x01a0, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, + 0xb289, 0x2214, 0xa296, 0xffff, 0x1160, 0x6007, 0x0025, 0x0048, + 0x601c, 0xa086, 0x0007, 0x1d70, 0x080c, 0x8078, 0x2160, 0x6007, + 0x0025, 0x6003, 0x0001, 0x080c, 0x67ee, 0x002e, 0x001e, 0x0005, + 0x2001, 0x0001, 0x080c, 0x4c1e, 0x0156, 0x0016, 0x0026, 0x0036, + 0x20a9, 0x0004, 0x2019, 0xad05, 0x2011, 0xb296, 0x080c, 0x8a7c, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, + 0x9ca6, 0x080c, 0x87bd, 0x080c, 0x574f, 0x1158, 0x0006, 0x0026, + 0x0036, 0x080c, 0x576b, 0x0110, 0x080c, 0x5726, 0x003e, 0x002e, + 0x000e, 0x0005, 0x6106, 0x080c, 0x9eb4, 0x6007, 0x002b, 0x0804, + 0x9ca6, 0x6007, 0x002c, 0x0804, 0x9ca6, 0x080c, 0xab4e, 0x1904, + 0x9e76, 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6106, 0x080c, 0x9eb8, + 0x1120, 0x6007, 0x002e, 0x0804, 0x9ca6, 0x6007, 0x002f, 0x0804, + 0x9ca6, 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, + 0xa184, 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, + 0xa086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0x9cab, + 0x2001, 0xad71, 0x2004, 0xd0e4, 0x0904, 0x9dd2, 0x2071, 0xb28c, + 0x7010, 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xad52, + 0x2004, 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, + 0x6814, 0xa206, 0x01f8, 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1580, + 0x2069, 0xad00, 0x6870, 0xa206, 0x1558, 0x686c, 0xa106, 0x1540, + 0x7210, 0x080c, 0x9586, 0x0548, 0x080c, 0xa9d4, 0x0530, 0x622a, + 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x67a8, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, 0x080c, 0x9586, + 0x01a0, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x1170, 0x0c08, + 0x7210, 0x2c08, 0x080c, 0xa940, 0x2c10, 0x2160, 0x0130, 0x08c8, + 0x6007, 0x0037, 0x6013, 0x1500, 0x08e8, 0x6007, 0x0037, 0x6013, + 0x1700, 0x08c0, 0x6007, 0x0012, 0x08a8, 0x6018, 0xa080, 0x0001, + 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, 0x1904, 0x9cab, + 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xad71, 0x2004, 0xd0e4, 0x0904, + 0x9e38, 0x2069, 0xad00, 0x2071, 0xb28c, 0x7008, 0x6036, 0x720c, + 0x623a, 0xa286, 0xffff, 0x1140, 0x7208, 0x00c6, 0x2c08, 0x080c, + 0xa940, 0x2c10, 0x00ce, 0x0588, 0x080c, 0x9586, 0x0570, 0x00c6, + 0x0026, 0x2260, 0x080c, 0x928f, 0x002e, 0x00ce, 0x7118, 0xa18c, + 0xff00, 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, + 0xa186, 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, + 0x0056, 0x7510, 0x7614, 0x080c, 0xa9eb, 0x005e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, + 0x6003, 0x0001, 0x080c, 0x67a8, 0x0c88, 0x6007, 0x003b, 0x602b, + 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, 0x67a8, 0x0c30, + 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0804, 0x9daa, + 0x00e6, 0x0026, 0x080c, 0x502d, 0x0558, 0x080c, 0x501d, 0x080c, + 0xabc5, 0x1520, 0x2071, 0xad00, 0x70d0, 0xc085, 0x70d2, 0x00f6, + 0x2079, 0x0100, 0x729c, 0xa284, 0x00ff, 0x706e, 0x78e6, 0xa284, + 0xff00, 0x7270, 0xa205, 0x7072, 0x78ea, 0x00fe, 0x70db, 0x0000, + 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0120, 0x2011, 0xafe0, 0x2013, + 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x28fa, 0x0010, 0x080c, 0xabf1, + 0x002e, 0x00ee, 0x080c, 0x8078, 0x0804, 0x9caa, 0x080c, 0x8078, + 0x0005, 0x2600, 0x0002, 0x9e81, 0x9e81, 0x9e81, 0x9e81, 0x9e81, + 0x9e83, 0x080c, 0x14f6, 0x080c, 0xab4e, 0x1d80, 0x0089, 0x1138, + 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x67ee, 0x0005, 0x080c, + 0x2ad9, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x67ee, 0x0005, + 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4, + 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085, + 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005, + 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, + 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009, + 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, + 0x080c, 0x2676, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x2b1e, + 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, + 0xb28d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, + 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0xb28c, + 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, 0x6800, 0xa084, + 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004, + 0xa0b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b6, 0x0013, 0x1130, 0x2008, + 0xa1b2, 0x0040, 0x1a04, 0x9ffb, 0x0092, 0xa1b6, 0x0027, 0x0120, + 0xa1b6, 0x0014, 0x190c, 0x14f6, 0x2001, 0x0007, 0x080c, 0x4c5d, + 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0x9f5f, + 0x9f61, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f61, 0x9f6f, 0x9ff4, 0x9fbf, + 0x9ff4, 0x9fd0, 0x9ff4, 0x9f6f, 0x9ff4, 0x9fec, 0x9ff4, 0x9fec, + 0x9ff4, 0x9ff4, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, + 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f61, 0x9f5f, 0x9ff4, + 0x9f5f, 0x9f5f, 0x9ff4, 0x9f5f, 0x9ff1, 0x9ff4, 0x9f5f, 0x9f5f, + 0x9f5f, 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, + 0x9f69, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9ff0, 0x9ff4, 0x9f5f, + 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x080c, + 0x14f6, 0x080c, 0x6b73, 0x6003, 0x0002, 0x080c, 0x6c50, 0x0804, + 0x9ffa, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x0804, 0x9ff4, 0x00f6, + 0x2079, 0xad51, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0x9ff4, 0x2001, + 0x0000, 0x080c, 0x4c1e, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, + 0x00ff, 0x1140, 0x00f6, 0x2079, 0xad00, 0x7894, 0x8000, 0x7896, + 0x00fe, 0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140, + 0x6010, 0xa005, 0x0128, 0x00ce, 0x080c, 0x3cce, 0x0804, 0x9ff4, + 0x00ce, 0x2001, 0xad00, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6, + 0x2079, 0xad00, 0x7894, 0x8000, 0x7896, 0x00fe, 0x2001, 0x0002, + 0x080c, 0x4c30, 0x080c, 0x6b73, 0x601f, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00c6, 0x6118, + 0x2160, 0x2009, 0x0001, 0x080c, 0x6519, 0x00ce, 0x04d8, 0x6618, + 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, 0x0410, + 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x3cce, + 0x2001, 0x0006, 0x0489, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, + 0x0048, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x00e9, 0x0020, + 0x0018, 0x0010, 0x080c, 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x8078, + 0x080c, 0x6c50, 0x0005, 0x2600, 0x0002, 0xa003, 0xa003, 0xa003, + 0xa003, 0xa003, 0xa005, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x080c, + 0x8078, 0x080c, 0x6c50, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168, + 0x6900, 0xd184, 0x0188, 0x6104, 0xa18e, 0x000a, 0x1128, 0x699c, + 0xd1a4, 0x1110, 0x2001, 0x0007, 0x080c, 0x4c30, 0x2001, 0x0000, + 0x080c, 0x4c1e, 0x080c, 0x2aff, 0x00de, 0x001e, 0x0005, 0x00d6, + 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2, + 0x000c, 0x1a0c, 0x14f6, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028, + 0xa1b6, 0x0016, 0x190c, 0x14f6, 0x006b, 0x0005, 0x86b9, 0x86b9, + 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0xa08f, 0xa056, 0x86b9, 0x86b9, + 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, + 0xa08f, 0xa096, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x00f6, 0x2079, + 0xad51, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, 0x7800, + 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, 0x080c, + 0x4c1e, 0x2001, 0x0002, 0x080c, 0x4c30, 0x601f, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00a8, + 0x2011, 0xb283, 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x1168, + 0x00c6, 0x080c, 0x4cdc, 0x0120, 0x00ce, 0x080c, 0x8078, 0x0028, + 0x080c, 0x493a, 0x00ce, 0x080c, 0x8078, 0x00fe, 0x0005, 0x6604, + 0xa6b6, 0x001e, 0x1110, 0x080c, 0x8078, 0x0005, 0x080c, 0x8940, + 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, 0x0010, + 0x080c, 0x8078, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, + 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0xa182, + 0x0040, 0x0002, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c7, 0xa0c5, + 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, + 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0x080c, 0x14f6, 0x00d6, + 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, 0x002b, + 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xab96, 0x6106, + 0x2071, 0xb280, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa129, 0xa486, + 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x663f, + 0x080c, 0x15d9, 0x090c, 0x14f6, 0x6003, 0x0007, 0x2d00, 0x6837, + 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, + 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, + 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, + 0x080c, 0x510c, 0x001e, 0xa486, 0x2000, 0x1130, 0x2019, 0x0017, + 0x080c, 0xa8eb, 0x0804, 0xa186, 0xa486, 0x0400, 0x1130, 0x2019, + 0x0002, 0x080c, 0xa89d, 0x0804, 0xa186, 0xa486, 0x0200, 0x1110, + 0x080c, 0xa882, 0xa486, 0x1000, 0x1110, 0x080c, 0xa8d0, 0x0804, + 0xa186, 0x2069, 0xb048, 0x6a00, 0xd284, 0x0904, 0xa1d5, 0xa284, + 0x0300, 0x1904, 0xa1cf, 0x6804, 0xa005, 0x0904, 0xa1c0, 0x2d78, + 0x6003, 0x0007, 0x080c, 0x15c0, 0x0904, 0xa18d, 0x7800, 0xd08c, + 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803, 0x0000, + 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a, + 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, 0x7928, + 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, 0x7934, 0x6996, 0x6853, + 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, 0x684f, + 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, 0x0010, + 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0xb290, 0xad90, 0x0015, + 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0xa178, 0x200c, + 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x510c, 0x002e, 0x004e, + 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x6013, 0x0100, 0x6003, + 0x0001, 0x6007, 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0c70, + 0x2069, 0xb292, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x11a8, + 0x2069, 0xb280, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, 0xa18c, + 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, + 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0888, 0x6013, 0x0200, 0x6003, + 0x0001, 0x6007, 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0830, + 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0804, 0xa186, 0x6013, + 0x0500, 0x0c98, 0x6013, 0x0600, 0x0818, 0x6013, 0x0200, 0x0800, + 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, 0x14f6, + 0xa08a, 0x0053, 0x1a0c, 0x14f6, 0xa082, 0x0040, 0x2008, 0x0804, + 0xa252, 0xa186, 0x0051, 0x0138, 0xa186, 0x0047, 0x11d8, 0x6004, + 0xa086, 0x0041, 0x0518, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6699, + 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, 0x0002, 0x1170, + 0x0804, 0xa295, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, + 0x14f6, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, 0x080c, 0x80be, + 0x0005, 0xa22c, 0xa22e, 0xa22e, 0xa22c, 0xa22c, 0xa22c, 0xa22c, + 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, + 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0x080c, 0x14f6, 0x080c, 0x6b73, + 0x080c, 0x6c50, 0x0036, 0x00d6, 0x6010, 0xa06d, 0x01c0, 0xad84, + 0xf000, 0x01a8, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, 0x1178, + 0x2019, 0x0004, 0x080c, 0xa91f, 0x6013, 0x0000, 0x6014, 0xa005, + 0x1120, 0x2001, 0xafa4, 0x2004, 0x6016, 0x6003, 0x0007, 0x00de, + 0x003e, 0x0005, 0x0002, 0xa266, 0xa283, 0xa26f, 0xa28f, 0xa266, + 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, + 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0x080c, 0x14f6, + 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x080c, + 0x6b73, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003, + 0x0007, 0x2009, 0x0043, 0x080c, 0x80a7, 0x0010, 0x6003, 0x0002, + 0x080c, 0x6c50, 0x0005, 0x080c, 0x6b73, 0x080c, 0xab55, 0x1120, + 0x080c, 0x6618, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c, + 0x6b73, 0x2009, 0x0041, 0x0804, 0xa3de, 0xa182, 0x0040, 0x0002, + 0xa2ab, 0xa2ad, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ae, + 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, + 0xa2ab, 0xa2b9, 0xa2ab, 0x080c, 0x14f6, 0x0005, 0x6003, 0x0004, + 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, + 0x0005, 0x00d6, 0x080c, 0x6618, 0x00de, 0x080c, 0xabb4, 0x080c, + 0x8078, 0x0005, 0xa182, 0x0040, 0x0002, 0xa2d8, 0xa2d8, 0xa2d8, + 0xa2d8, 0xa2d8, 0xa2d8, 0xa2d8, 0xa2da, 0xa2d8, 0xa2dd, 0xa316, + 0xa2d8, 0xa2d8, 0xa2d8, 0xa2d8, 0xa316, 0xa2d8, 0xa2d8, 0xa2d8, + 0x080c, 0x14f6, 0x080c, 0x80be, 0x0005, 0x2001, 0xad71, 0x2004, + 0xd0e4, 0x0158, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0228, + 0x2001, 0x011f, 0x2004, 0x6036, 0x0010, 0x6037, 0x0000, 0x080c, + 0x6c05, 0x080c, 0x6d0d, 0x6010, 0x00d6, 0x2068, 0x684c, 0xd0fc, + 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0168, 0x2009, 0x0041, + 0x00de, 0x0804, 0xa3de, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, + 0x6618, 0x00de, 0x0005, 0x080c, 0xab55, 0x0110, 0x00de, 0x0005, + 0x080c, 0x6618, 0x080c, 0x8078, 0x00de, 0x0ca0, 0x0036, 0x080c, + 0x6c05, 0x080c, 0x6d0d, 0x6010, 0x00d6, 0x2068, 0x6018, 0x2004, + 0xd0bc, 0x0188, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0140, + 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, + 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xa91f, 0x6014, + 0xa005, 0x1128, 0x2001, 0xafa4, 0x2004, 0x8003, 0x6016, 0x6013, + 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0xa186, 0x0013, + 0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x14f6, 0x080c, 0x6b73, + 0x080c, 0x6c50, 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, 0x0014, + 0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x14f6, 0x2001, 0x0007, + 0x080c, 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, + 0x0005, 0xa182, 0x0040, 0x0002, 0xa37f, 0xa37f, 0xa37f, 0xa37f, + 0xa37f, 0xa37f, 0xa37f, 0xa381, 0xa38d, 0xa37f, 0xa37f, 0xa37f, + 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0x080c, + 0x14f6, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x080c, 0x1824, 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068, + 0x6810, 0x6a14, 0x0006, 0x0046, 0x0056, 0x6c7c, 0xa422, 0x6d80, + 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, + 0x005e, 0x004e, 0x000e, 0xa20d, 0x1178, 0x684c, 0xd0fc, 0x0120, + 0x2009, 0x0041, 0x00de, 0x0490, 0x6003, 0x0007, 0x6017, 0x0000, + 0x080c, 0x6618, 0x00de, 0x0005, 0x0006, 0x00f6, 0x2c78, 0x080c, + 0x5029, 0x00fe, 0x000e, 0x0120, 0x6003, 0x0002, 0x00de, 0x0005, + 0x2009, 0xad0d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, + 0x6003, 0x0006, 0x0021, 0x080c, 0x661a, 0x00de, 0x0005, 0xd2fc, + 0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, + 0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040, + 0x0208, 0x0062, 0xa186, 0x0013, 0x0120, 0xa186, 0x0014, 0x190c, + 0x14f6, 0x6020, 0xd0dc, 0x090c, 0x14f6, 0x0005, 0xa401, 0xa408, + 0xa414, 0xa420, 0xa401, 0xa401, 0xa401, 0xa42f, 0xa401, 0xa403, + 0xa403, 0xa401, 0xa401, 0xa401, 0xa401, 0xa403, 0xa401, 0xa403, + 0xa401, 0x080c, 0x14f6, 0x6020, 0xd0dc, 0x090c, 0x14f6, 0x0005, + 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, + 0x080c, 0x6c50, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, + 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, + 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1e6e, 0x0126, 0x2091, + 0x8000, 0x080c, 0x680b, 0x080c, 0x6d0d, 0x012e, 0x0005, 0xa016, + 0x080c, 0x1824, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6, + 0xa182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, 0x0005, 0xa44f, + 0xa451, 0xa463, 0xa47e, 0xa44f, 0xa44f, 0xa44f, 0xa493, 0xa44f, + 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0x080c, + 0x14f6, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x01f8, 0xa09c, 0x0003, + 0xa39e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, + 0x080c, 0x6c50, 0x0498, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0168, + 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, + 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0408, 0x6013, 0x0000, 0x6017, + 0x0000, 0x2019, 0x0004, 0x080c, 0xa91f, 0x00c0, 0x6010, 0x2068, + 0x684c, 0xd0fc, 0x0d90, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0d68, + 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x680b, + 0x080c, 0x6d0d, 0x0018, 0xa016, 0x080c, 0x1824, 0x0005, 0x080c, + 0x6b73, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xabfa, + 0x0036, 0x2019, 0x0029, 0x080c, 0xa91f, 0x003e, 0x00de, 0x080c, + 0x974e, 0x080c, 0x6c50, 0x0005, 0x080c, 0x6c05, 0x6110, 0x81ff, + 0x0158, 0x00d6, 0x2168, 0x080c, 0xabfa, 0x0036, 0x2019, 0x0029, + 0x080c, 0xa91f, 0x003e, 0x00de, 0x080c, 0x974e, 0x080c, 0x6d0d, + 0x0005, 0xa182, 0x0085, 0x0002, 0xa4cd, 0xa4cb, 0xa4cb, 0xa4d9, + 0xa4cb, 0xa4cb, 0xa4cb, 0x080c, 0x14f6, 0x6003, 0x000b, 0x6106, + 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, + 0x0005, 0x0026, 0x00e6, 0x080c, 0xab4e, 0x0118, 0x080c, 0x8078, + 0x00c8, 0x2071, 0xb280, 0x7224, 0x6212, 0x7220, 0x080c, 0xa7ce, + 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0xa296, + 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x67a8, + 0x080c, 0x6c50, 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, + 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x14f6, 0xa08a, 0x008c, 0x1a0c, + 0x14f6, 0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, + 0x0014, 0x0118, 0x080c, 0x80be, 0x0050, 0x2001, 0x0007, 0x080c, + 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, + 0xa527, 0xa529, 0xa529, 0xa527, 0xa527, 0xa527, 0xa527, 0x080c, + 0x14f6, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, + 0xa182, 0x0085, 0x0a0c, 0x14f6, 0xa182, 0x008c, 0x1a0c, 0x14f6, + 0xa182, 0x0085, 0x0002, 0xa542, 0xa542, 0xa542, 0xa544, 0xa542, + 0xa542, 0xa542, 0x080c, 0x14f6, 0x0005, 0xa186, 0x0013, 0x0148, + 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x80be, + 0x0030, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, + 0x0036, 0x080c, 0xabb4, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031, + 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, + 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c, + 0x7b9a, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x7c34, + 0x007e, 0x1548, 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086, + 0x0007, 0x0508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, + 0xabb4, 0x601f, 0x0007, 0x2001, 0xafa3, 0x2004, 0x6016, 0x080c, + 0x190b, 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0xa91f, + 0x00de, 0x6013, 0x0000, 0x080c, 0xabb4, 0x601f, 0x0007, 0x2001, + 0xafa3, 0x2004, 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, + 0x0036, 0x0156, 0x2079, 0xb280, 0x7938, 0x783c, 0x080c, 0x2676, + 0x1904, 0xa5f1, 0x0016, 0x00c6, 0x080c, 0x4cdc, 0x15c0, 0x2011, + 0xb290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1578, + 0x001e, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x7cf4, + 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x007e, + 0x001e, 0x0076, 0x2039, 0x0000, 0x080c, 0xa712, 0x007e, 0x080c, + 0x4ecf, 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, + 0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2b87, 0x002e, + 0x001e, 0x080c, 0x493a, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce, + 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, + 0x00e6, 0x0016, 0x2009, 0xad20, 0x2104, 0xa086, 0x0074, 0x1904, + 0xa64b, 0x2069, 0xb28e, 0x690c, 0xa182, 0x0100, 0x06c0, 0x6908, + 0xa184, 0x8000, 0x05e8, 0x2001, 0xaf9d, 0x2004, 0xa005, 0x1160, + 0x6018, 0x2070, 0x7010, 0xa084, 0x00ff, 0x0118, 0x7000, 0xd0f4, + 0x0118, 0xa184, 0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610, + 0x6914, 0x2069, 0xb2ae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182, + 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001, + 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100, + 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013, + 0x0700, 0x0058, 0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028, + 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008, + 0xa006, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, + 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, + 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, 0x0178, 0xa394, 0xff00, + 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, 0x0004, 0x0130, 0x00c6, + 0x2d60, 0x080c, 0x4ceb, 0x00ce, 0x04c0, 0x2011, 0xb296, 0xad98, + 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1580, 0x2011, 0xb29a, + 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1538, 0x0046, + 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xad52, + 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xa96c, 0x6800, + 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039, + 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, 0x007e, 0x2001, + 0x0007, 0x080c, 0x4c5d, 0x001e, 0x004e, 0xa006, 0x015e, 0x003e, + 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0xb28e, 0x6800, + 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, 0xa006, 0x00de, + 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, + 0xb28c, 0x7930, 0x7834, 0x080c, 0x2676, 0x11a0, 0x080c, 0x4cdc, + 0x1188, 0x2011, 0xb290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, + 0x8a7c, 0x1140, 0x2011, 0xb294, 0xac98, 0x0006, 0x20a9, 0x0004, + 0x080c, 0x8a7c, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, + 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, + 0xb283, 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x11a0, 0x080c, + 0x4cdc, 0x1188, 0x2011, 0xb296, 0xac98, 0x000a, 0x20a9, 0x0004, + 0x080c, 0x8a7c, 0x1140, 0x2011, 0xb29a, 0xac98, 0x0006, 0x20a9, + 0x0004, 0x080c, 0x8a7c, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, + 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, + 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0xafd0, + 0x252c, 0x2021, 0xafd6, 0x2424, 0x2061, 0xb400, 0x2071, 0xad00, + 0x7644, 0x7064, 0x81ff, 0x0128, 0x8001, 0xa602, 0x1a04, 0xa78e, + 0x0018, 0xa606, 0x0904, 0xa78e, 0x2100, 0xac06, 0x0904, 0xa785, + 0x080c, 0xa990, 0x0904, 0xa785, 0x671c, 0xa786, 0x0001, 0x0904, + 0xa7a5, 0xa786, 0x0004, 0x0904, 0xa7a5, 0xa786, 0x0007, 0x05e8, + 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, 0xa9a0, + 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, 0x6000, + 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x190b, 0x001e, 0xa786, + 0x0008, 0x1148, 0x080c, 0x9789, 0x1130, 0x080c, 0x85f3, 0x00de, + 0x080c, 0x974e, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9596, 0x0190, + 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0xabfa, 0x0016, 0x080c, 0x97fd, 0x080c, 0x510c, 0x001e, + 0x080c, 0x9742, 0x00de, 0x080c, 0x974e, 0xace0, 0x0018, 0x2001, + 0xad16, 0x2004, 0xac02, 0x1210, 0x0804, 0xa726, 0x012e, 0x002e, + 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, + 0xa786, 0x0006, 0x19c0, 0xa386, 0x0005, 0x0128, 0x080c, 0xabfa, + 0x080c, 0xa91f, 0x08f8, 0x00de, 0x0c00, 0x080c, 0xa9a0, 0x19e8, + 0x81ff, 0x09d8, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x0130, + 0xa180, 0x0001, 0x2004, 0xa086, 0x002d, 0x1978, 0x6000, 0xa086, + 0x0002, 0x1958, 0x080c, 0x9778, 0x0130, 0x080c, 0x9789, 0x1928, + 0x080c, 0x85f3, 0x0038, 0x080c, 0x2aff, 0x080c, 0x9789, 0x1110, + 0x080c, 0x85f3, 0x080c, 0x974e, 0x0804, 0xa785, 0x00c6, 0x00e6, + 0x0016, 0x2c08, 0x2170, 0x080c, 0xa940, 0x001e, 0x0120, 0x601c, + 0xa084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xa7e6, 0xa7e6, + 0xa7e6, 0xa7e6, 0xa7e6, 0xa7e6, 0xa7e8, 0xa7e6, 0xa006, 0x0005, + 0x0046, 0x0016, 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, + 0x8427, 0x2c00, 0x2009, 0x0020, 0x080c, 0xa96c, 0x001e, 0x004e, + 0x0036, 0x2019, 0x0002, 0x080c, 0xa566, 0x003e, 0xa085, 0x0001, + 0x0005, 0x2001, 0x0001, 0x080c, 0x4c1e, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0xad05, 0x2011, 0xb296, 0x080c, + 0x8a7c, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, + 0x8000, 0x2740, 0x2061, 0xb400, 0x2079, 0x0001, 0x8fff, 0x0904, + 0xa875, 0x2071, 0xad00, 0x7644, 0x7064, 0x8001, 0xa602, 0x1a04, + 0xa875, 0x88ff, 0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, + 0x080c, 0xa990, 0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, + 0x0006, 0x1550, 0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, + 0xa206, 0x1510, 0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, + 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xabb4, 0x601f, 0x0007, + 0x2001, 0xafa3, 0x2004, 0x6016, 0x080c, 0x190b, 0x6010, 0x2068, + 0x080c, 0x9596, 0x0120, 0x0046, 0x080c, 0xa91f, 0x004e, 0x00de, + 0x080c, 0x974e, 0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xad16, + 0x2004, 0xac02, 0x1210, 0x0804, 0xa826, 0xa006, 0x012e, 0x002e, + 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, + 0x0001, 0x0ca0, 0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, + 0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, + 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x7c34, + 0x080c, 0xa817, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, + 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x0016, 0x0036, 0x080c, 0x4cdc, 0x11b0, 0x2c10, 0x0056, + 0x0086, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, + 0x0000, 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, + 0x7c34, 0x080c, 0xa817, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, + 0xa8a9, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, + 0x0076, 0x0056, 0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, + 0x2019, 0x0048, 0x0096, 0x2049, 0x0000, 0x080c, 0x7b9a, 0x009e, + 0x008e, 0x2039, 0x0000, 0x080c, 0x7c34, 0x2c20, 0x080c, 0xa817, + 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, + 0x0156, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, + 0x080c, 0x4cdc, 0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, + 0x0046, 0x2021, 0x0001, 0x080c, 0xab96, 0x004e, 0x0096, 0x2049, + 0x0000, 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, + 0x7c34, 0x080c, 0xa817, 0x003e, 0x001e, 0x8108, 0x1f04, 0xa8f6, + 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, + 0x00f6, 0x3800, 0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, + 0xad00, 0x0230, 0xad82, 0xe400, 0x0280, 0xad82, 0xffff, 0x1268, + 0x6800, 0xa07d, 0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x510c, + 0x2f68, 0x0cb0, 0x6b52, 0x080c, 0x510c, 0x00fe, 0x001e, 0x0005, + 0x00e6, 0x0046, 0x0036, 0x2061, 0xb400, 0x2071, 0xad00, 0x7444, + 0x7064, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, + 0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, + 0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xad16, + 0x2004, 0xac02, 0x1220, 0x0c08, 0xa085, 0x0001, 0x0008, 0xa006, + 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15d9, + 0x000e, 0x090c, 0x14f6, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, + 0x080c, 0x9586, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, + 0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006, + 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, 0x510c, 0x00de, 0x0005, + 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, 0x0001, 0x0140, 0xa786, + 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, 0xa085, 0x0001, 0x0005, + 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00ee, 0x0005, 0x0016, + 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, 0x6130, 0xa18c, 0x00ff, + 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005, + 0x2001, 0xafa4, 0x2004, 0x6016, 0x080c, 0x67a8, 0x080c, 0x6c50, + 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, 0x6020, 0xd0e4, 0x0158, + 0xd0cc, 0x0118, 0x080c, 0x9866, 0x0030, 0x080c, 0xabb4, 0x080c, + 0x6618, 0x080c, 0x8078, 0x0005, 0xa280, 0x0007, 0x2004, 0xa084, + 0x000f, 0x0002, 0xa9e3, 0xa9e3, 0xa9e3, 0xa9e8, 0xa9e3, 0xa9e5, + 0xa9e5, 0xa9e3, 0xa9e5, 0xa006, 0x0005, 0x00c6, 0x2260, 0x00ce, + 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, + 0x0002, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xaa05, + 0xa9fa, 0xa9fa, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, + 0x6003, 0x0001, 0x080c, 0x67a8, 0x0005, 0x00c6, 0x2260, 0x080c, + 0xabb4, 0x603f, 0x0000, 0x6020, 0xc0f4, 0xc0cc, 0x6022, 0x6037, + 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, 0x0007, 0x1904, 0xaa60, + 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x1110, + 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x67a8, + 0x080c, 0x6c50, 0x00c6, 0x2d60, 0x6100, 0xa186, 0x0002, 0x1904, + 0xaae7, 0x6010, 0xa005, 0x1138, 0x6000, 0xa086, 0x0007, 0x190c, + 0x14f6, 0x0804, 0xaae7, 0xa08c, 0xf000, 0x1130, 0x0028, 0x2068, + 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084, + 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, 0x2068, 0x684c, 0xc0dc, + 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043, + 0x080c, 0xa3de, 0x0804, 0xaae7, 0x2009, 0x0041, 0x0804, 0xaae1, + 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc, + 0x1118, 0x00de, 0x0804, 0xa9fa, 0xd0b4, 0x0128, 0xd0fc, 0x090c, + 0x14f6, 0x0804, 0xaa18, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, + 0x67a8, 0x080c, 0x6c50, 0x00c6, 0x2d60, 0x6100, 0xa186, 0x0002, + 0x0120, 0xa186, 0x0004, 0x1904, 0xaae7, 0x2071, 0xaffd, 0x7000, + 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, 0x1110, 0x7003, 0x0000, + 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, + 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0804, + 0xaae1, 0x0036, 0x00d6, 0x00d6, 0x080c, 0x15d9, 0x003e, 0x090c, + 0x14f6, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, + 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872, + 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, 0x6846, 0x684f, 0x0000, + 0x6d6a, 0x6e66, 0x686f, 0x0001, 0x080c, 0x510c, 0x2019, 0x0045, + 0x6008, 0x2068, 0x080c, 0xa566, 0x2d00, 0x600a, 0x601f, 0x0006, + 0x6003, 0x0007, 0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, + 0x0038, 0x603f, 0x0000, 0x6003, 0x0007, 0x080c, 0xa3de, 0x00ce, + 0x00de, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, + 0x2008, 0x00c2, 0xa186, 0x0027, 0x1178, 0x080c, 0x6b73, 0x0036, + 0x00d6, 0x6010, 0x2068, 0x2019, 0x0004, 0x080c, 0xa91f, 0x00de, + 0x003e, 0x080c, 0x6c50, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, + 0x80be, 0x0005, 0xab13, 0xab11, 0xab11, 0xab11, 0xab11, 0xab11, + 0xab13, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x6003, 0x000c, 0x080c, + 0x6c50, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, + 0x001a, 0x080c, 0x80be, 0x0005, 0xab2b, 0xab2b, 0xab2b, 0xab2b, + 0xab2d, 0xab4b, 0xab2b, 0x080c, 0x14f6, 0x00d6, 0x2c68, 0x080c, + 0x8022, 0x01a0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xb28e, + 0x210c, 0x6136, 0x2009, 0xb28f, 0x210c, 0x613a, 0x600b, 0xffff, + 0x6918, 0x611a, 0x601f, 0x0004, 0x080c, 0x67a8, 0x2d60, 0x080c, + 0x8078, 0x00de, 0x0005, 0x080c, 0x8078, 0x0005, 0x00e6, 0x6018, + 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa080, 0x0013, + 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xad71, 0x2004, 0xd0ec, 0x05a8, + 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, 0x00f6, + 0x2c78, 0x080c, 0x5025, 0x00fe, 0x0150, 0x2001, 0xafa5, 0x2004, + 0x603e, 0x2009, 0xad71, 0x210c, 0xd1f4, 0x11e8, 0x0080, 0x2009, + 0xad71, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, 0xa006, + 0x00a0, 0x2001, 0xafa5, 0x200c, 0x8103, 0xa100, 0x603e, 0x6018, + 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, 0x0cd0, + 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, 0x00c6, + 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, 0x8cff, 0x0180, + 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, 0x080c, + 0x6618, 0x080c, 0x8078, 0x0010, 0xacf0, 0x0003, 0x2e64, 0x0c70, + 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, 0x002b, + 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, 0x0003, + 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, + 0x2011, 0xad27, 0x2204, 0xa084, 0x00ff, 0x2019, 0xb28e, 0x2334, + 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, 0xa636, + 0x11a0, 0x2011, 0xb290, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, + 0x080c, 0x8a7c, 0x1150, 0x2011, 0xb294, 0x6018, 0xa098, 0x0006, + 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1100, 0x015e, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x2071, 0xad00, 0x080c, 0x48f5, 0x080c, 0x28fa, + 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0108, + 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, 0x00e6, + 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, + 0x2091, 0x8000, 0x2029, 0xafd0, 0x252c, 0x2021, 0xafd6, 0x2424, + 0x2061, 0xb400, 0x2071, 0xad00, 0x7644, 0x7064, 0xa606, 0x0578, + 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, 0x2500, + 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xa990, 0x01b8, + 0x080c, 0xa9a0, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, + 0x080c, 0x190b, 0x001e, 0x080c, 0x9778, 0x1110, 0x080c, 0x2aff, + 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x080c, 0x974e, 0xace0, + 0x0018, 0x2001, 0xad16, 0x2004, 0xac02, 0x1208, 0x0858, 0x012e, + 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xad40, + 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, + 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0xad4a, 0x0451, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, + 0x2071, 0xad40, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, + 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0xad4a, + 0x0081, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, + 0x2091, 0x8000, 0x2071, 0xad42, 0x0021, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, + 0x2072, 0x0005, 0x00e6, 0x2071, 0xad40, 0x0c99, 0x00ee, 0x0005, + 0x00e6, 0x2071, 0xad44, 0x0c69, 0x00ee, 0x0005, 0x0001, 0x0002, + 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, + 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x8529 +}; + diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.4.9/linux/drivers/scsi/sd.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/scsi/sd.c Sat Sep 8 12:02:32 2001 @@ -238,8 +238,10 @@ case BLKFLSBUF: case BLKSSZGET: case BLKPG: - case BLKELVGET: - case BLKELVSET: + case BLKELVGET: + case BLKELVSET: + case BLKBSZGET: + case BLKBSZSET: return blk_ioctl(inode->i_rdev, cmd, arg); case BLKRRPART: /* Re-read partition tables */ @@ -576,7 +578,6 @@ static struct gendisk *sd_gendisks = &sd_gendisk; #define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR] -#define LAST_SD_GENDISK sd_gendisks[N_USED_SD_MAJORS - 1] /* * rw_intr is the interrupt routine for the device driver. @@ -1020,7 +1021,7 @@ cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ? ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0; cmd[2] = 0x3f; /* Get all pages */ - cmd[4] = 8; /* But we only want the 8 byte header */ + cmd[4] = 255; /* But we only want the 8 byte header */ SRpnt->sr_cmd_len = 0; SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[2] = 0; @@ -1145,12 +1146,10 @@ sd_gendisks[i].part = sd + (i * SCSI_DISKS_PER_MAJOR << 4); sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4); sd_gendisks[i].nr_real = 0; - sd_gendisks[i].next = sd_gendisks + i + 1; sd_gendisks[i].real_devices = (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR); } - LAST_SD_GENDISK.next = NULL; return 0; cleanup_gendisks_flags: @@ -1182,19 +1181,13 @@ static void sd_finish() { - struct gendisk *gendisk; int i; for (i = 0; i < N_USED_SD_MAJORS; i++) { blk_dev[SD_MAJOR(i)].queue = sd_find_queue; + add_gendisk(&sd_gendisks[i]); } - for (gendisk = gendisk_head; gendisk != NULL; gendisk = gendisk->next) - if (gendisk == sd_gendisks) - break; - if (gendisk == NULL) { - LAST_SD_GENDISK.next = gendisk_head; - gendisk_head = sd_gendisks; - } + for (i = 0; i < sd_template.dev_max; ++i) if (!rscsi_disks[i].capacity && rscsi_disks[i].device) { sd_init_onedisk(i); @@ -1375,10 +1368,7 @@ static void __exit exit_sd(void) { - struct gendisk **prev_sdgd_link; - struct gendisk *sdgd; int i; - int removed = 0; scsi_unregister_module(MODULE_SCSI_DEV, &sd_template); @@ -1392,26 +1382,9 @@ kfree(sd_blocksizes); kfree(sd_hardsizes); kfree((char *) sd); - - /* - * Now remove sd_gendisks from the linked list - */ - prev_sdgd_link = &gendisk_head; - while ((sdgd = *prev_sdgd_link) != NULL) { - if (sdgd >= sd_gendisks && sdgd <= &LAST_SD_GENDISK) { - removed++; - *prev_sdgd_link = sdgd->next; - continue; - } - prev_sdgd_link = &sdgd->next; - } - - if (removed != N_USED_SD_MAJORS) - printk("%s %d sd_gendisks in disk chain", - removed > N_USED_SD_MAJORS ? "total" : "just", removed); - } for (i = 0; i < N_USED_SD_MAJORS; i++) { + del_gendisk(&sd_gendisks[i]); blk_size[SD_MAJOR(i)] = NULL; hardsect_size[SD_MAJOR(i)] = NULL; read_ahead[SD_MAJOR(i)] = 0; diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c --- v2.4.9/linux/drivers/scsi/seagate.c Sat Nov 11 19:01:11 2000 +++ linux/drivers/scsi/seagate.c Fri Sep 7 09:28:37 2001 @@ -123,7 +123,7 @@ #define FAST #endif -#undef LINKED /* Linked commands are currently broken! */ +#undef LINKED /* Linked commands are currently broken! */ #if defined(OVERRIDE) && !defined(CONTROLLER) #error Please use -DCONTROLLER=SEAGATE or -DCONTROLLER=FD to override controller type @@ -152,11 +152,11 @@ STATUS */ #ifdef SWAPSTAT - #define STAT_MSG 0x08 - #define STAT_CD 0x02 +#define STAT_MSG 0x08 +#define STAT_CD 0x02 #else - #define STAT_MSG 0x02 - #define STAT_CD 0x08 +#define STAT_MSG 0x02 +#define STAT_CD 0x08 #endif #define STAT_BSY 0x01 @@ -181,9 +181,9 @@ extern volatile int seagate_st0x_timeout; #ifdef PARITY - #define BASE_CMD CMD_EN_PARITY +#define BASE_CMD CMD_EN_PARITY #else - #define BASE_CMD 0 +#define BASE_CMD 0 #endif /* @@ -193,7 +193,7 @@ #define PHASE_BUS_FREE 1 #define PHASE_ARBITRATION 2 #define PHASE_SELECTION 4 -#define PHASE_DATAIN 8 +#define PHASE_DATAIN 8 #define PHASE_DATAOUT 0x10 #define PHASE_CMDOUT 0x20 #define PHASE_MSGIN 0x40 @@ -216,44 +216,43 @@ #define ST0X_BUS_FREE_DELAY 25 #define ST0X_SELECTION_DELAY 25 -#define SEAGATE 1 /* these determine the type of the controller */ +#define SEAGATE 1 /* these determine the type of the controller */ #define FD 2 #define ST0X_ID_STR "Seagate ST-01/ST-02" #define FD_ID_STR "TMC-8XX/TMC-950" - static int internal_command (unsigned char target, unsigned char lun, - const void *cmnd, - void *buff, int bufflen, int reselect); + const void *cmnd, + void *buff, int bufflen, int reselect); -static int incommand; /* set if arbitration has finished - and we are in some command phase. */ +static int incommand; /* set if arbitration has finished + and we are in some command phase. */ -static unsigned int base_address = 0; /* Where the card ROM starts, used to - calculate memory mapped register - location. */ - -static unsigned long st0x_cr_sr; /* control register write, status - register read. 256 bytes in - length. - Read is status of SCSI BUS, as per - STAT masks. */ - -static unsigned long st0x_dr; /* data register, read write 256 - bytes in length. */ - -static volatile int st0x_aborted = 0; /* set when we are aborted, ie by a - time out, etc. */ - -static unsigned char controller_type = 0; /* set to SEAGATE for ST0x - boards or FD for TMC-8xx - boards */ +static unsigned int base_address = 0; /* Where the card ROM starts, used to + calculate memory mapped register + location. */ + +static unsigned long st0x_cr_sr; /* control register write, status + register read. 256 bytes in + length. + Read is status of SCSI BUS, as per + STAT masks. */ + +static unsigned long st0x_dr; /* data register, read write 256 + bytes in length. */ + +static volatile int st0x_aborted = 0; /* set when we are aborted, ie by a + time out, etc. */ + +static unsigned char controller_type = 0; /* set to SEAGATE for ST0x + boards or FD for TMC-8xx + boards */ static int irq = IRQ; -MODULE_PARM(base_address, "i"); -MODULE_PARM(controller_type, "b"); -MODULE_PARM(irq, "i"); +MODULE_PARM (base_address, "i"); +MODULE_PARM (controller_type, "b"); +MODULE_PARM (irq, "i"); #define retcode(result) (((result) << 16) | (message << 8) | status) #define STATUS ((u8) isa_readb(st0x_cr_sr)) @@ -261,40 +260,38 @@ #define WRITE_CONTROL(d) { isa_writeb((d), st0x_cr_sr); } #define WRITE_DATA(d) { isa_writeb((d), st0x_dr); } -void st0x_setup (char *str, int *ints) +void +st0x_setup (char *str, int *ints) { - controller_type = SEAGATE; - base_address = ints[1]; - irq = ints[2]; + controller_type = SEAGATE; + base_address = ints[1]; + irq = ints[2]; } -void tmc8xx_setup (char *str, int *ints) +void +tmc8xx_setup (char *str, int *ints) { - controller_type = FD; - base_address = ints[1]; - irq = ints[2]; + controller_type = FD; + base_address = ints[1]; + irq = ints[2]; } #ifndef OVERRIDE -static unsigned int seagate_bases[] = -{ - 0xc8000, 0xca000, 0xcc000, - 0xce000, 0xdc000, 0xde000 +static unsigned int seagate_bases[] = { + 0xc8000, 0xca000, 0xcc000, + 0xce000, 0xdc000, 0xde000 }; -typedef struct -{ - const unsigned char *signature; - unsigned offset; - unsigned length; - unsigned char type; -} -Signature; - -static const Signature __initdata signatures[] = -{ - {"ST01 v1.7 (C) Copyright 1987 Seagate", 15, 37, SEAGATE}, - {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE}, +typedef struct { + const unsigned char *signature; + unsigned offset; + unsigned length; + unsigned char type; +} Signature; + +static Signature __initdata signatures[] = { + {"ST01 v1.7 (C) Copyright 1987 Seagate", 15, 37, SEAGATE}, + {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE}, /* * The following two lines are NOT mistakes. One detects ROM revision @@ -303,28 +300,28 @@ * are probably "good enough" */ - {"SEAGATE SCSI BIOS ", 16, 17, SEAGATE}, - {"SEAGATE SCSI BIOS ", 17, 17, SEAGATE}, + {"SEAGATE SCSI BIOS ", 16, 17, SEAGATE}, + {"SEAGATE SCSI BIOS ", 17, 17, SEAGATE}, /* * However, future domain makes several incompatible SCSI boards, so specific * signatures must be used. */ - {"FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89", 5, 46, FD}, - {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89", 5, 46, FD}, - {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90", 5, 47, FD}, - {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90", 5, 47, FD}, - {"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FD}, - {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FD}, - {"IBM F1 BIOS V1.1004/30/92", 5, 25, FD}, - {"FUTURE DOMAIN TMC-950", 5, 21, FD}, - /* Added for 2.2.16 by Matthias_Heidbrink@b.maus.de */ - {"IBM F1 V1.2009/22/93", 5, 25, FD}, + {"FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89", 5, 46, FD}, + {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89", 5, 46, FD}, + {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90", 5, 47, FD}, + {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90", 5, 47, FD}, + {"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FD}, + {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FD}, + {"IBM F1 BIOS V1.1004/30/92", 5, 25, FD}, + {"FUTURE DOMAIN TMC-950", 5, 21, FD}, + /* Added for 2.2.16 by Matthias_Heidbrink@b.maus.de */ + {"IBM F1 V1.2009/22/93", 5, 25, FD}, }; #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature)) -#endif /* n OVERRIDE */ +#endif /* n OVERRIDE */ /* * hostno stores the hostnumber, as told to us by the init routine. @@ -382,35 +379,37 @@ */ static int borken_calibration = 0; + static void __init borken_init (void) { - register int count = 0, start = jiffies + 1, stop = start + 25; + register int count = 0, start = jiffies + 1, stop = start + 25; - while (time_before(jiffies, start)) ; - for (; time_before(jiffies, stop); ++count) ; + while (time_before (jiffies, start)) ; + for (; time_before (jiffies, stop); ++count) ; /* * Ok, we now have a count for .25 seconds. Convert to a * count per second and divide by transfer rate in K. */ - borken_calibration = (count * 4) / (SLOW_RATE * 1024); + borken_calibration = (count * 4) / (SLOW_RATE * 1024); - if (borken_calibration < 1) - borken_calibration = 1; + if (borken_calibration < 1) + borken_calibration = 1; } static inline void borken_wait (void) { - register int count; + register int count; - for (count = borken_calibration; count && (STATUS & STAT_REQ); --count) ; + for (count = borken_calibration; count && (STATUS & STAT_REQ); + --count) ; #if (DEBUG & DEBUG_BORKEN) - if (count) - printk ("scsi%d : borken timeout\n", hostno); + if (count) + printk ("scsi%d : borken timeout\n", hostno); #endif } -#endif /* def SLOW_RATE */ +#endif /* def SLOW_RATE */ /* These beasts only live on ISA, and ISA means 8MHz. Each ULOOP() * contains at least one ISA access, which takes more than 0.125 @@ -422,33 +421,34 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt) { - struct Scsi_Host *instance; - int i, j; + struct Scsi_Host *instance; + int i, j; - tpnt->proc_name = "seagate"; + tpnt->proc_name = "seagate"; /* - * First, we try for the manual override. */ - DANY ("Autodetecting ST0x / TMC-8xx\n"); + * First, we try for the manual override. + */ + DANY ("Autodetecting ST0x / TMC-8xx\n"); - if (hostno != -1) { - printk (KERN_ERR "seagate_st0x_detect() called twice?!\n"); - return 0; - } + if (hostno != -1) { + printk (KERN_ERR "seagate_st0x_detect() called twice?!\n"); + return 0; + } /* If the user specified the controller type from the command line, controller_type will be non-zero, so don't try to detect one */ - if (!controller_type) - { + if (!controller_type) { #ifdef OVERRIDE - base_address = OVERRIDE; - controller_type = CONTROLLER; + base_address = OVERRIDE; + controller_type = CONTROLLER; - DANY("Base address overridden to %x, controller type is %s\n", - base_address, controller_type == SEAGATE ? "SEAGATE" : "FD"); -#else /* OVERRIDE */ + DANY ("Base address overridden to %x, controller type is %s\n", + base_address, + controller_type == SEAGATE ? "SEAGATE" : "FD"); +#else /* OVERRIDE */ /* - * To detect this card, we simply look for the signature + * To detect this card, we simply look for the signature * from the BIOS version notice in all the possible locations * of the ROM's. This has a nice side effect of not trashing * any register locations that might be used by something else. @@ -457,106 +457,112 @@ * space for the on-board RAM instead. */ - for (i = 0; i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i) + for (i = 0; + i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i) - for (j = 0; !base_address && j < NUM_SIGNATURES; ++j) - if (isa_check_signature (seagate_bases[i] + signatures[j].offset, - signatures[j].signature, signatures[j].length)) - { - base_address = seagate_bases[i]; - controller_type = signatures[j].type; - } -#endif /* OVERRIDE */ - } /* (! controller_type) */ - - tpnt->this_id = (controller_type == SEAGATE) ? 7 : 6; - tpnt->name = (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR; - - if (!base_address) { - DANY ("ST0x / TMC-8xx not detected.\n"); - return 0; - } + for (j = 0; !base_address && j < NUM_SIGNATURES; ++j) + if (isa_check_signature + (seagate_bases[i] + signatures[j].offset, + signatures[j].signature, + signatures[j].length)) { + base_address = seagate_bases[i]; + controller_type = signatures[j].type; + } +#endif /* OVERRIDE */ + } + /* (! controller_type) */ + tpnt->this_id = (controller_type == SEAGATE) ? 7 : 6; + tpnt->name = (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR; + + if (!base_address) { + DANY ("ST0x / TMC-8xx not detected.\n"); + return 0; + } - st0x_cr_sr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00); - st0x_dr = st0x_cr_sr + 0x200; + st0x_cr_sr = + base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00); + st0x_dr = st0x_cr_sr + 0x200; - DANY ("%s detected. Base address = %x, cr = %x, dr = %x\n", - tpnt->name, base_address, st0x_cr_sr, st0x_dr); + DANY ("%s detected. Base address = %x, cr = %x, dr = %x\n", + tpnt->name, base_address, st0x_cr_sr, st0x_dr); /* - * At all times, we will use IRQ 5. Should also check for IRQ3 if we + * At all times, we will use IRQ 5. Should also check for IRQ3 if we * loose our first interrupt. */ - instance = scsi_register (tpnt, 0); - if(instance == NULL) - return 0; - - hostno = instance->host_no; - if (request_irq (irq, do_seagate_reconnect_intr, SA_INTERRUPT, - (controller_type == SEAGATE) ? "seagate" : "tmc-8xx", NULL)) { - printk ("scsi%d : unable to allocate IRQ%d\n", hostno, irq); - return 0; - } - instance->irq = irq; - instance->io_port = base_address; + instance = scsi_register (tpnt, 0); + if (instance == NULL) + return 0; + + hostno = instance->host_no; + if (request_irq (irq, do_seagate_reconnect_intr, SA_INTERRUPT, + (controller_type == SEAGATE) ? "seagate" : "tmc-8xx", + NULL)) { + printk ("scsi%d : unable to allocate IRQ%d\n", hostno, irq); + return 0; + } + instance->irq = irq; + instance->io_port = base_address; #ifdef SLOW_RATE - printk( "Calibrating borken timer... " ); - borken_init (); - printk( " %d cycles per transfer\n", borken_calibration ); + printk (KERN_INFO "Calibrating borken timer... "); + borken_init (); + printk (" %d cycles per transfer\n", borken_calibration); #endif - printk( "This is one second... " ); - { - int clock; - ULOOP( 1*1000*1000 ) { - STATUS; - if (TIMEOUT) break; - } - } + printk (KERN_INFO "This is one second... "); + { + int clock; + ULOOP (1 * 1000 * 1000) { + STATUS; + if (TIMEOUT) + break; + } + } - printk ("done, %s options:" + printk ("done, %s options:" #ifdef ARBITRATE - " ARBITRATE" + " ARBITRATE" #endif #ifdef DEBUG - " DEBUG" + " DEBUG" #endif #ifdef FAST - " FAST" + " FAST" #ifdef FAST32 - "32" + "32" #endif #endif #ifdef LINKED - " LINKED" + " LINKED" #endif #ifdef PARITY - " PARITY" + " PARITY" #endif #ifdef SEAGATE_USE_ASM - " SEAGATE_USE_ASM" + " SEAGATE_USE_ASM" #endif #ifdef SLOW_RATE - " SLOW_RATE" + " SLOW_RATE" #endif #ifdef SWAPSTAT - " SWAPSTAT" + " SWAPSTAT" #endif #ifdef SWAPCNTDATA - " SWAPCNTDATA" + " SWAPCNTDATA" #endif - "\n", tpnt->name); - return 1; + "\n", tpnt->name); + return 1; } -const char *seagate_st0x_info (struct Scsi_Host *shpnt) +const char * +seagate_st0x_info (struct Scsi_Host *shpnt) { - static char buffer[64]; + static char buffer[64]; - sprintf (buffer, "%s at irq %d, address 0x%05X", - (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR, - irq, base_address); - return buffer; + sprintf (buffer, "%s at irq %d, address 0x%05X", + (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR, + irq, base_address); + return buffer; } /* @@ -616,50 +622,50 @@ static void do_seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs) { - unsigned long flags; + unsigned long flags; - spin_lock_irqsave(&io_request_lock, flags); - seagate_reconnect_intr(irq, dev_id, regs); - spin_unlock_irqrestore(&io_request_lock, flags); + spin_lock_irqsave (&io_request_lock, flags); + seagate_reconnect_intr (irq, dev_id, regs); + spin_unlock_irqrestore (&io_request_lock, flags); } static void seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs) { - int temp; - Scsi_Cmnd *SCtmp; + int temp; + Scsi_Cmnd *SCtmp; - DPRINTK (PHASE_RESELECT, "scsi%d : seagate_reconnect_intr() called\n", hostno); + DPRINTK (PHASE_RESELECT, "scsi%d : seagate_reconnect_intr() called\n", + hostno); - if (!should_reconnect) - printk ("scsi%d: unexpected interrupt.\n", hostno); - else - { - should_reconnect = 0; - - DPRINTK (PHASE_RESELECT, "scsi%d : internal_command(" - "%d, %08x, %08x, RECONNECT_NOW\n", hostno, - current_target, current_data, current_bufflen); - - temp = internal_command (current_target, current_lun, current_cmnd, - current_data, current_bufflen, RECONNECT_NOW); - - if (msg_byte (temp) != DISCONNECT) - { - if (done_fn) - { - DPRINTK (PHASE_RESELECT, "scsi%d : done_fn(%d,%08x)", hostno, - hostno, temp); - if (!SCint) - panic ("SCint == NULL in seagate"); - SCtmp = SCint; - SCint = NULL; - SCtmp->result = temp; - done_fn (SCtmp); - } - else - printk ("done_fn() not defined.\n"); - } - } + if (!should_reconnect) + printk ("scsi%d: unexpected interrupt.\n", hostno); + else { + should_reconnect = 0; + + DPRINTK (PHASE_RESELECT, "scsi%d : internal_command(" + "%d, %08x, %08x, RECONNECT_NOW\n", hostno, + current_target, current_data, current_bufflen); + + temp = + internal_command (current_target, current_lun, current_cmnd, + current_data, current_bufflen, + RECONNECT_NOW); + + if (msg_byte (temp) != DISCONNECT) { + if (done_fn) { + DPRINTK (PHASE_RESELECT, + "scsi%d : done_fn(%d,%08x)", hostno, + hostno, temp); + if (!SCint) + panic ("SCint == NULL in seagate"); + SCtmp = SCint; + SCint = NULL; + SCtmp->result = temp; + done_fn (SCtmp); + } else + printk ("done_fn() not defined.\n"); + } + } } /* @@ -677,212 +683,215 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) { - int result, reconnect; - Scsi_Cmnd *SCtmp; + int result, reconnect; + Scsi_Cmnd *SCtmp; - DANY( "seagate: que_command" ); - done_fn = done; - current_target = SCpnt->target; - current_lun = SCpnt->lun; - (const void *) current_cmnd = SCpnt->cmnd; - current_data = (unsigned char *) SCpnt->request_buffer; - current_bufflen = SCpnt->request_bufflen; - SCint = SCpnt; - if (recursion_depth) return 0; - recursion_depth++; - do - { + DANY ("seagate: que_command"); + done_fn = done; + current_target = SCpnt->target; + current_lun = SCpnt->lun; + (const void *) current_cmnd = SCpnt->cmnd; + current_data = (unsigned char *) SCpnt->request_buffer; + current_bufflen = SCpnt->request_bufflen; + SCint = SCpnt; + if (recursion_depth) + return 0; + recursion_depth++; + do { #ifdef LINKED /* * Set linked command bit in control field of SCSI command. */ - current_cmnd[SCpnt->cmd_len] |= 0x01; - if (linked_connected) - { - DPRINTK (DEBUG_LINKED, - "scsi%d : using linked commands, current I_T_L nexus is ", hostno); - if ((linked_target == current_target) && (linked_lun == current_lun)) - { - DPRINTK (DEBUG_LINKED, "correct\n"); - reconnect = LINKED_RIGHT; - } - else - { - DPRINTK (DEBUG_LINKED, "incorrect\n"); - reconnect = LINKED_WRONG; - } - } - else -#endif /* LINKED */ - reconnect = CAN_RECONNECT; - - result = internal_command (SCint->target, SCint->lun, SCint->cmnd, - SCint->request_buffer, SCint->request_bufflen, reconnect); - if (msg_byte (result) == DISCONNECT) break; - SCtmp = SCint; - SCint = NULL; - SCtmp->result = result; - done_fn (SCtmp); - } - while (SCint); - recursion_depth--; - return 0; + current_cmnd[SCpnt->cmd_len] |= 0x01; + if (linked_connected) { + DPRINTK (DEBUG_LINKED, + "scsi%d : using linked commands, current I_T_L nexus is ", + hostno); + if ((linked_target == current_target) + && (linked_lun == current_lun)) { + DPRINTK (DEBUG_LINKED, "correct\n"); + reconnect = LINKED_RIGHT; + } else { + DPRINTK (DEBUG_LINKED, "incorrect\n"); + reconnect = LINKED_WRONG; + } + } else +#endif /* LINKED */ + reconnect = CAN_RECONNECT; + + result = + internal_command (SCint->target, SCint->lun, SCint->cmnd, + SCint->request_buffer, + SCint->request_bufflen, reconnect); + if (msg_byte (result) == DISCONNECT) + break; + SCtmp = SCint; + SCint = NULL; + SCtmp->result = result; + done_fn (SCtmp); + } + while (SCint); + recursion_depth--; + return 0; } int seagate_st0x_command (Scsi_Cmnd * SCpnt) { - return internal_command (SCpnt->target, SCpnt->lun, SCpnt->cmnd, - SCpnt->request_buffer, SCpnt->request_bufflen, - (int) NO_RECONNECT); + return internal_command (SCpnt->target, SCpnt->lun, SCpnt->cmnd, + SCpnt->request_buffer, SCpnt->request_bufflen, + (int) NO_RECONNECT); } -static int internal_command (unsigned char target, unsigned char lun, - const void *cmnd, void *buff, int bufflen, int reselect) +static int internal_command (unsigned char target, unsigned char lun, + const void *cmnd, void *buff, int bufflen, int reselect) { - unsigned char *data = NULL; - struct scatterlist *buffer = NULL; - int clock, temp, nobuffs = 0, done = 0, len = 0; - unsigned long flags; + unsigned char *data = NULL; + struct scatterlist *buffer = NULL; + int clock, temp, nobuffs = 0, done = 0, len = 0; + unsigned long flags; #ifdef DEBUG - int transfered = 0, phase = 0, newphase; + int transfered = 0, phase = 0, newphase; #endif - register unsigned char status_read; - unsigned char tmp_data, tmp_control, status = 0, message = 0; + register unsigned char status_read; + unsigned char tmp_data, tmp_control, status = 0, message = 0; - unsigned transfersize = 0, underflow = 0; + unsigned transfersize = 0, underflow = 0; #ifdef SLOW_RATE - int borken = (int) SCint->device->borken; /* Does the current target require - Very Slow I/O ? */ + int borken = (int) SCint->device->borken; /* Does the current target require + Very Slow I/O ? */ #endif - incommand = 0; - st0x_aborted = 0; + incommand = 0; + st0x_aborted = 0; #if (DEBUG & PRINT_COMMAND) - printk ("scsi%d : target = %d, command = ", hostno, target); - print_command ((unsigned char *) cmnd); + printk ("scsi%d : target = %d, command = ", hostno, target); + print_command ((unsigned char *) cmnd); #endif #if (DEBUG & PHASE_RESELECT) - switch (reselect) - { - case RECONNECT_NOW: - printk ("scsi%d : reconnecting\n", hostno); - break; + switch (reselect) { + case RECONNECT_NOW: + printk ("scsi%d : reconnecting\n", hostno); + break; #ifdef LINKED - case LINKED_RIGHT: - printk ("scsi%d : connected, can reconnect\n", hostno); - break; - case LINKED_WRONG: - printk ("scsi%d : connected to wrong target, can reconnect\n", hostno); - break; -#endif - case CAN_RECONNECT: - printk ("scsi%d : allowed to reconnect\n", hostno); - break; - default: - printk ("scsi%d : not allowed to reconnect\n", hostno); - } + case LINKED_RIGHT: + printk ("scsi%d : connected, can reconnect\n", hostno); + break; + case LINKED_WRONG: + printk ("scsi%d : connected to wrong target, can reconnect\n", + hostno); + break; +#endif + case CAN_RECONNECT: + printk ("scsi%d : allowed to reconnect\n", hostno); + break; + default: + printk ("scsi%d : not allowed to reconnect\n", hostno); + } #endif - if (target == (controller_type == SEAGATE ? 7 : 6)) - return DID_BAD_TARGET; + if (target == (controller_type == SEAGATE ? 7 : 6)) + return DID_BAD_TARGET; /* - * We work it differently depending on if this is is "the first time," + * We work it differently depending on if this is is "the first time," * or a reconnect. If this is a reselect phase, then SEL will * be asserted, and we must skip selection / arbitration phases. */ - switch (reselect) - { - case RECONNECT_NOW: - DPRINTK ( PHASE_RESELECT, "scsi%d : phase RESELECT \n", hostno); + switch (reselect) { + case RECONNECT_NOW: + DPRINTK (PHASE_RESELECT, "scsi%d : phase RESELECT \n", hostno); /* - * At this point, we should find the logical or of our ID and the original + * At this point, we should find the logical or of our ID and the original * target's ID on the BUS, with BSY, SEL, and I/O signals asserted. * * After ARBITRATION phase is completed, only SEL, BSY, and the * target ID are asserted. A valid initiator ID is not on the bus * until IO is asserted, so we must wait for that. */ - ULOOP( 100*1000 ) { - temp = STATUS; - if ((temp & STAT_IO) && !(temp & STAT_BSY)) - break; - - if (TIMEOUT) { - DPRINTK (PHASE_RESELECT, - "scsi%d : RESELECT timed out while waiting for IO .\n", hostno); - return (DID_BAD_INTR << 16); - } - } + ULOOP (100 * 1000) { + temp = STATUS; + if ((temp & STAT_IO) && !(temp & STAT_BSY)) + break; + + if (TIMEOUT) { + DPRINTK (PHASE_RESELECT, + "scsi%d : RESELECT timed out while waiting for IO .\n", + hostno); + return (DID_BAD_INTR << 16); + } + } /* - * After I/O is asserted by the target, we can read our ID and its + * After I/O is asserted by the target, we can read our ID and its * ID off of the BUS. */ - if (!((temp = DATA) & (controller_type == SEAGATE ? 0x80 : 0x40))) - { - DPRINTK (PHASE_RESELECT, - "scsi%d : detected reconnect request to different target.\n" - "\tData bus = %d\n", hostno, temp); - return (DID_BAD_INTR << 16); - } - - if (!(temp & (1 << current_target))) - { - printk ("scsi%d : Unexpected reselect interrupt. Data bus = %d\n", - hostno, temp); - return (DID_BAD_INTR << 16); - } - - buffer = current_buffer; - cmnd = current_cmnd; /* WDE add */ - data = current_data; /* WDE add */ - len = current_bufflen; /* WDE add */ - nobuffs = current_nobuffs; + if (! + ((temp = + DATA) & (controller_type == SEAGATE ? 0x80 : 0x40))) { + DPRINTK (PHASE_RESELECT, + "scsi%d : detected reconnect request to different target.\n" + "\tData bus = %d\n", hostno, temp); + return (DID_BAD_INTR << 16); + } + + if (!(temp & (1 << current_target))) { + printk + ("scsi%d : Unexpected reselect interrupt. Data bus = %d\n", + hostno, temp); + return (DID_BAD_INTR << 16); + } + + buffer = current_buffer; + cmnd = current_cmnd; /* WDE add */ + data = current_data; /* WDE add */ + len = current_bufflen; /* WDE add */ + nobuffs = current_nobuffs; /* - * We have determined that we have been selected. At this point, + * We have determined that we have been selected. At this point, * we must respond to the reselection by asserting BSY ourselves */ #if 1 - WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY); + WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY); #else - WRITE_CONTROL (BASE_CMD | CMD_BSY); + WRITE_CONTROL (BASE_CMD | CMD_BSY); #endif /* - * The target will drop SEL, and raise BSY, at which time we must drop + * The target will drop SEL, and raise BSY, at which time we must drop * BSY. */ - ULOOP( 100*1000 ) { - if (!(STATUS & STAT_SEL)) break; - if (TIMEOUT) { - WRITE_CONTROL (BASE_CMD | CMD_INTR); - DPRINTK (PHASE_RESELECT, - "scsi%d : RESELECT timed out while waiting for SEL.\n", hostno); - return (DID_BAD_INTR << 16); - } - } + ULOOP (100 * 1000) { + if (!(STATUS & STAT_SEL)) + break; + if (TIMEOUT) { + WRITE_CONTROL (BASE_CMD | CMD_INTR); + DPRINTK (PHASE_RESELECT, + "scsi%d : RESELECT timed out while waiting for SEL.\n", + hostno); + return (DID_BAD_INTR << 16); + } + } - WRITE_CONTROL (BASE_CMD); + WRITE_CONTROL (BASE_CMD); /* - * At this point, we have connected with the target and can get + * At this point, we have connected with the target and can get * on with our lives. */ - break; - case CAN_RECONNECT: + break; + case CAN_RECONNECT: #ifdef LINKED /* @@ -892,11 +901,12 @@ * message on MESSAGE OUT phase, and then loop back to here. */ - connect_loop: + connect_loop: #endif - DPRINTK (PHASE_BUS_FREE, "scsi%d : phase = BUS FREE \n", hostno); + DPRINTK (PHASE_BUS_FREE, "scsi%d : phase = BUS FREE \n", + hostno); /* * BUS FREE PHASE @@ -909,21 +919,22 @@ #ifndef ARBITRATE #error FIXME: this is broken: we may not use jiffies here - we are under cli(). It will hardlock. - clock = jiffies + ST0X_BUS_FREE_DELAY; + clock = jiffies + ST0X_BUS_FREE_DELAY; - while (((STATUS | STATUS | STATUS) & - (STAT_BSY | STAT_SEL)) && - (!st0x_aborted) && time_before(jiffies, clock)); + while (((STATUS | STATUS | STATUS) & + (STAT_BSY | STAT_SEL)) && + (!st0x_aborted) && time_before (jiffies, clock)) ; - if (time_after(jiffies, clock)) - return retcode (DID_BUS_BUSY); - else if (st0x_aborted) - return retcode (st0x_aborted); + if (time_after (jiffies, clock)) + return retcode (DID_BUS_BUSY); + else if (st0x_aborted) + return retcode (st0x_aborted); #endif - DPRINTK (PHASE_SELECTION, "scsi%d : phase = SELECTION\n", hostno); + DPRINTK (PHASE_SELECTION, "scsi%d : phase = SELECTION\n", + hostno); - clock = jiffies + ST0X_SELECTION_DELAY; + clock = jiffies + ST0X_SELECTION_DELAY; /* * Arbitration/selection procedure : @@ -937,26 +948,30 @@ */ #ifdef ARBITRATE - save_flags (flags); - cli (); - WRITE_CONTROL (0); - WRITE_DATA ((controller_type == SEAGATE) ? 0x80 : 0x40); - WRITE_CONTROL (CMD_START_ARB); - restore_flags (flags); - - ULOOP( ST0X_SELECTION_DELAY * 10000 ) { - status_read = STATUS; - if (status_read & STAT_ARB_CMPL) break; - if (st0x_aborted) /* FIXME: What? We are going to do something even after abort? */ - break; - if (TIMEOUT || (status_read & STAT_SEL)) { - printk( "scsi%d : arbitration lost or timeout.\n", hostno ); - WRITE_CONTROL (BASE_CMD); - return retcode (DID_NO_CONNECT); - } - } + save_flags (flags); + cli (); + WRITE_CONTROL (0); + WRITE_DATA ((controller_type == SEAGATE) ? 0x80 : 0x40); + WRITE_CONTROL (CMD_START_ARB); + restore_flags (flags); + + ULOOP (ST0X_SELECTION_DELAY * 10000) { + status_read = STATUS; + if (status_read & STAT_ARB_CMPL) + break; + if (st0x_aborted) /* FIXME: What? We are going to do something even after abort? */ + break; + if (TIMEOUT || (status_read & STAT_SEL)) { + printk + ("scsi%d : arbitration lost or timeout.\n", + hostno); + WRITE_CONTROL (BASE_CMD); + return retcode (DID_NO_CONNECT); + } + } - DPRINTK (PHASE_SELECTION, "scsi%d : arbitration complete\n", hostno); + DPRINTK (PHASE_SELECTION, "scsi%d : arbitration complete\n", + hostno); #endif /* @@ -971,92 +986,103 @@ * try this with a SCSI protocol or logic analyzer to see what is * going on. */ - tmp_data = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40)); - tmp_control = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | (reselect ? CMD_ATTN : 0); + tmp_data = + (unsigned char) ((1 << target) | + (controller_type == + SEAGATE ? 0x80 : 0x40)); + tmp_control = + BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | (reselect ? CMD_ATTN + : 0); - save_flags(flags); - cli(); + save_flags (flags); + cli (); #ifdef OLDCNTDATASCEME #ifdef SWAPCNTDATA - WRITE_CONTROL (tmp_control); - WRITE_DATA (tmp_data); + WRITE_CONTROL (tmp_control); + WRITE_DATA (tmp_data); #else - WRITE_DATA (tmp_data); - WRITE_CONTROL (tmp_control); + WRITE_DATA (tmp_data); + WRITE_CONTROL (tmp_control); #endif #else - tmp_control ^= CMD_BSY; /* This is guesswork. What used to be in driver */ - WRITE_CONTROL (tmp_control); /* could never work: it sent data into control */ - WRITE_DATA (tmp_data); /* register and control info into data. Hopefully */ - tmp_control ^= CMD_BSY; /* fixed, but order of first two may be wrong. */ - WRITE_CONTROL (tmp_control); /* -- pavel@ucw.cz */ -#endif - + tmp_control ^= CMD_BSY; /* This is guesswork. What used to be in driver */ + WRITE_CONTROL (tmp_control); /* could never work: it sent data into control */ + WRITE_DATA (tmp_data); /* register and control info into data. Hopefully */ + tmp_control ^= CMD_BSY; /* fixed, but order of first two may be wrong. */ + WRITE_CONTROL (tmp_control); /* -- pavel@ucw.cz */ +#endif - restore_flags (flags); + restore_flags (flags); - ULOOP( 250*1000 ) { - if (st0x_aborted) { + ULOOP (250 * 1000) { + if (st0x_aborted) { /* - * If we have been aborted, and we have a command in progress, IE the + * If we have been aborted, and we have a command in progress, IE the * target still has BSY asserted, then we will reset the bus, and * notify the midlevel driver to expect sense. */ - WRITE_CONTROL (BASE_CMD); - if (STATUS & STAT_BSY) { - printk ("scsi%d : BST asserted after we've been aborted.\n", hostno); - seagate_st0x_reset (NULL, 0); - return retcode (DID_RESET); - } - return retcode (st0x_aborted); - } - if (STATUS & STAT_BSY) break; - if (TIMEOUT) { - DPRINTK (PHASE_SELECTION, "scsi%d : NO CONNECT with target %d, stat = %x \n", - hostno, target, STATUS); - return retcode (DID_NO_CONNECT); - } - } + WRITE_CONTROL (BASE_CMD); + if (STATUS & STAT_BSY) { + printk + ("scsi%d : BST asserted after we've been aborted.\n", + hostno); + seagate_st0x_reset (NULL, 0); + return retcode (DID_RESET); + } + return retcode (st0x_aborted); + } + if (STATUS & STAT_BSY) + break; + if (TIMEOUT) { + DPRINTK (PHASE_SELECTION, + "scsi%d : NO CONNECT with target %d, stat = %x \n", + hostno, target, STATUS); + return retcode (DID_NO_CONNECT); + } + } /* Establish current pointers. Take into account scatter / gather */ - if ((nobuffs = SCint->use_sg)) - { + if ((nobuffs = SCint->use_sg)) { #if (DEBUG & DEBUG_SG) - { - int i; + { + int i; - printk ("scsi%d : scatter gather requested, using %d buffers.\n", - hostno, nobuffs); - for (i = 0; i < nobuffs; ++i) - printk ("scsi%d : buffer %d address = %08x length = %d\n", - hostno, i, buffer[i].address, buffer[i].length); - } -#endif - - buffer = (struct scatterlist *) SCint->buffer; - len = buffer->length; - data = (unsigned char *) buffer->address; - } - else - { - DPRINTK (DEBUG_SG, "scsi%d : scatter gather not requested.\n", hostno); - buffer = NULL; - len = SCint->request_bufflen; - data = (unsigned char *) SCint->request_buffer; - } + printk + ("scsi%d : scatter gather requested, using %d buffers.\n", + hostno, nobuffs); + for (i = 0; i < nobuffs; ++i) + printk + ("scsi%d : buffer %d address = %08x length = %d\n", + hostno, i, buffer[i].address, + buffer[i].length); + } +#endif + + buffer = (struct scatterlist *) SCint->buffer; + len = buffer->length; + data = (unsigned char *) buffer->address; + } else { + DPRINTK (DEBUG_SG, + "scsi%d : scatter gather not requested.\n", + hostno); + buffer = NULL; + len = SCint->request_bufflen; + data = (unsigned char *) SCint->request_buffer; + } - DPRINTK (PHASE_DATAIN | PHASE_DATAOUT, "scsi%d : len = %d\n", hostno, len); + DPRINTK (PHASE_DATAIN | PHASE_DATAOUT, "scsi%d : len = %d\n", + hostno, len); - break; + break; #ifdef LINKED - case LINKED_RIGHT: - break; - case LINKED_WRONG: - break; + case LINKED_RIGHT: + break; + case LINKED_WRONG: + break; #endif - } /* end of switch(reselect) */ + } /* end of switch(reselect) */ /* * There are several conditions under which we wish to send a message : @@ -1069,14 +1095,14 @@ /* GCC does not like an ifdef inside a macro, so do it the hard way. */ #ifdef LINKED - WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | - (((reselect == CAN_RECONNECT) - || (reselect == LINKED_WRONG) - )? CMD_ATTN : 0)); + WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | + (((reselect == CAN_RECONNECT) + || (reselect == LINKED_WRONG) + )? CMD_ATTN : 0)); #else - WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | - (((reselect == CAN_RECONNECT) - )? CMD_ATTN : 0)); + WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | + (((reselect == CAN_RECONNECT) + )? CMD_ATTN : 0)); #endif /* @@ -1091,134 +1117,145 @@ * */ - DPRINTK (PHASE_ETC, "scsi%d : phase = INFORMATION TRANSFER\n", hostno); + DPRINTK (PHASE_ETC, "scsi%d : phase = INFORMATION TRANSFER\n", hostno); - incommand = 1; - transfersize = SCint->transfersize; - underflow = SCint->underflow; + incommand = 1; + transfersize = SCint->transfersize; + underflow = SCint->underflow; /* - * Now, we poll the device for status information, + * Now, we poll the device for status information, * and handle any requests it makes. Note that since we are unsure of * how much data will be flowing across the system, etc and cannot * make reasonable timeouts, that we will instead have the midlevel * driver handle any timeouts that occur in this phase. */ - while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done) - { + while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done) { #ifdef PARITY - if (status_read & STAT_PARITY) - { - printk ("scsi%d : got parity error\n", hostno); - st0x_aborted = DID_PARITY; - } + if (status_read & STAT_PARITY) { + printk ("scsi%d : got parity error\n", hostno); + st0x_aborted = DID_PARITY; + } #endif - if (status_read & STAT_REQ) - { + if (status_read & STAT_REQ) { #if ((DEBUG & PHASE_ETC) == PHASE_ETC) - if ((newphase = (status_read & REQ_MASK)) != phase) - { - phase = newphase; - switch (phase) - { - case REQ_DATAOUT: - printk ("scsi%d : phase = DATA OUT\n", hostno); - break; - case REQ_DATAIN: - printk ("scsi%d : phase = DATA IN\n", hostno); - break; - case REQ_CMDOUT: - printk ("scsi%d : phase = COMMAND OUT\n", hostno); - break; - case REQ_STATIN: - printk ("scsi%d : phase = STATUS IN\n", hostno); - break; - case REQ_MSGOUT: - printk ("scsi%d : phase = MESSAGE OUT\n", hostno); - break; - case REQ_MSGIN: - printk ("scsi%d : phase = MESSAGE IN\n", hostno); - break; - default: - printk ("scsi%d : phase = UNKNOWN\n", hostno); - st0x_aborted = DID_ERROR; - } - } -#endif - switch (status_read & REQ_MASK) - { - case REQ_DATAOUT: + if ((newphase = (status_read & REQ_MASK)) != phase) { + phase = newphase; + switch (phase) { + case REQ_DATAOUT: + printk ("scsi%d : phase = DATA OUT\n", + hostno); + break; + case REQ_DATAIN: + printk ("scsi%d : phase = DATA IN\n", + hostno); + break; + case REQ_CMDOUT: + printk + ("scsi%d : phase = COMMAND OUT\n", + hostno); + break; + case REQ_STATIN: + printk ("scsi%d : phase = STATUS IN\n", + hostno); + break; + case REQ_MSGOUT: + printk + ("scsi%d : phase = MESSAGE OUT\n", + hostno); + break; + case REQ_MSGIN: + printk ("scsi%d : phase = MESSAGE IN\n", + hostno); + break; + default: + printk ("scsi%d : phase = UNKNOWN\n", + hostno); + st0x_aborted = DID_ERROR; + } + } +#endif + switch (status_read & REQ_MASK) { + case REQ_DATAOUT: /* * If we are in fast mode, then we simply splat the data out * in word-sized chunks as fast as we can. */ - if (!len) - { + if (!len) { #if 0 - printk ("scsi%d: underflow to target %d lun %d \n", hostno, target, lun); - st0x_aborted = DID_ERROR; - fast = 0; -#endif - break; - } - - if (fast && transfersize && !(len % transfersize) - && (len >= transfersize) + printk + ("scsi%d: underflow to target %d lun %d \n", + hostno, target, lun); + st0x_aborted = DID_ERROR; + fast = 0; +#endif + break; + } + + if (fast && transfersize + && !(len % transfersize) + && (len >= transfersize) #ifdef FAST32 - && !(transfersize % 4) + && !(transfersize % 4) #endif - ) - { - DPRINTK (DEBUG_FAST, - "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" - " len = %d, data = %08x\n", - hostno, SCint->underflow, SCint->transfersize, len, data); + ) { + DPRINTK (DEBUG_FAST, + "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" + " len = %d, data = %08x\n", + hostno, SCint->underflow, + SCint->transfersize, len, + data); /* SJT: Start. Fast Write */ #ifdef SEAGATE_USE_ASM - __asm__( - "cld\n\t" + __asm__ ("cld\n\t" #ifdef FAST32 - "shr $2, %%ecx\n\t" - "1:\t" - "lodsl\n\t" - "movl %%eax, (%%edi)\n\t" + "shr $2, %%ecx\n\t" + "1:\t" + "lodsl\n\t" + "movl %%eax, (%%edi)\n\t" #else - "1:\t" - "lodsb\n\t" - "movb %%al, (%%edi)\n\t" -#endif - "loop 1b;" -/* output */ : -/* input */ : "D" (phys_to_virt(st0x_dr)), "S" (data), "c" (SCint->transfersize) -/* clobbered */ : "eax", "ecx", "esi" ); -#else /* SEAGATE_USE_ASM */ - { + "1:\t" + "lodsb\n\t" + "movb %%al, (%%edi)\n\t" +#endif + "loop 1b;" + /* output */ : + /* input */ :"D" (phys_to_virt (st0x_dr)), + "S" + (data), + "c" (SCint->transfersize) +/* clobbered */ + : "eax", "ecx", + "esi"); +#else /* SEAGATE_USE_ASM */ + { #ifdef FAST32 - unsigned int *iop = phys_to_virt (st0x_dr); - const unsigned int *dp = (unsigned int *) data; - int xferlen = transfersize >> 2; + unsigned int *iop = + phys_to_virt (st0x_dr); + const unsigned int *dp = + (unsigned int *) data; + int xferlen = transfersize >> 2; #else - unsigned char *iop = phys_to_virt (st0x_dr); - const unsigned char *dp = data; - int xferlen = transfersize; -#endif - for (; xferlen; --xferlen) - *iop = *dp++; - } -#endif /* SEAGATE_USE_ASM */ + unsigned char *iop = + phys_to_virt (st0x_dr); + const unsigned char *dp = data; + int xferlen = transfersize; +#endif + for (; xferlen; --xferlen) + *iop = *dp++; + } +#endif /* SEAGATE_USE_ASM */ /* SJT: End */ - len -= transfersize; - data += transfersize; - DPRINTK (DEBUG_FAST, - "scsi%d : FAST transfer complete len = %d data = %08x\n", - hostno, len, data); - } - else - { + len -= transfersize; + data += transfersize; + DPRINTK (DEBUG_FAST, + "scsi%d : FAST transfer complete len = %d data = %08x\n", + hostno, len, data); + } else { /* * We loop as long as we are in a data out phase, there is data to send, * and BSY is still active. @@ -1227,7 +1264,7 @@ /* SJT: Start. Slow Write. */ #ifdef SEAGATE_USE_ASM -int __dummy_1,__dummy_2; + int __dummy_1, __dummy_2; /* * We loop as long as we are in a data out phase, there is data to send, @@ -1236,159 +1273,173 @@ /* Local variables : len = ecx , data = esi, st0x_cr_sr = ebx, st0x_dr = edi */ - __asm__ ( - /* Test for any data here at all. */ - "orl %%ecx, %%ecx\n\t" - "jz 2f\n\t" - "cld\n\t" + __asm__ ( + /* Test for any data here at all. */ + "orl %%ecx, %%ecx\n\t" + "jz 2f\n\t" "cld\n\t" /* "movl " SYMBOL_NAME_STR(st0x_cr_sr) ", %%ebx\n\t" */ /* "movl " SYMBOL_NAME_STR(st0x_dr) ", %%edi\n\t" */ - "1:\t" - "movb (%%ebx), %%al\n\t" - /* Test for BSY */ - "test $1, %%al\n\t" - "jz 2f\n\t" - /* Test for data out phase - STATUS & REQ_MASK should be - REQ_DATAOUT, which is 0. */ - "test $0xe, %%al\n\t" - "jnz 2f\n\t" - /* Test for REQ */ - "test $0x10, %%al\n\t" - "jz 1b\n\t" - "lodsb\n\t" - "movb %%al, (%%edi)\n\t" - "loop 1b\n\t" - "2:\n" -/* output */ : "=S" (data), "=c" (len) ,"=b" (__dummy_1) ,"=D" (__dummy_2) -/* input */ : "0" (data), "1" (len), "2" (phys_to_virt(st0x_cr_sr)), "3" (phys_to_virt(st0x_dr)) -/* clobbered */ : "eax"); -#else /* SEAGATE_USE_ASM */ - while (len) - { - unsigned char stat; - - stat = STATUS; - if (!(stat & STAT_BSY) || ((stat & REQ_MASK) != REQ_DATAOUT)) - break; - if (stat & STAT_REQ) - { - WRITE_DATA (*data++); - --len; - } - } -#endif /* SEAGATE_USE_ASM */ + "1:\t" + "movb (%%ebx), %%al\n\t" + /* Test for BSY */ + "test $1, %%al\n\t" + "jz 2f\n\t" + /* Test for data out phase - STATUS & REQ_MASK should be + REQ_DATAOUT, which is 0. */ + "test $0xe, %%al\n\t" + "jnz 2f\n\t" + /* Test for REQ */ + "test $0x10, %%al\n\t" + "jz 1b\n\t" + "lodsb\n\t" + "movb %%al, (%%edi)\n\t" + "loop 1b\n\t" "2:\n" + /* output */ :"=S" (data), "=c" (len), + "=b" + (__dummy_1), + "=D" (__dummy_2) +/* input */ + : "0" (data), "1" (len), + "2" (phys_to_virt + (st0x_cr_sr)), + "3" (phys_to_virt + (st0x_dr)) +/* clobbered */ + : "eax"); +#else /* SEAGATE_USE_ASM */ + while (len) { + unsigned char stat; + + stat = STATUS; + if (!(stat & STAT_BSY) + || ((stat & REQ_MASK) != + REQ_DATAOUT)) + break; + if (stat & STAT_REQ) { + WRITE_DATA (*data++); + --len; + } + } +#endif /* SEAGATE_USE_ASM */ /* SJT: End. */ - } + } - if (!len && nobuffs) - { - --nobuffs; - ++buffer; - len = buffer->length; - data = (unsigned char *) buffer->address; - DPRINTK (DEBUG_SG, - "scsi%d : next scatter-gather buffer len = %d address = %08x\n", - hostno, len, data); - } - break; + if (!len && nobuffs) { + --nobuffs; + ++buffer; + len = buffer->length; + data = + (unsigned char *) buffer->address; + DPRINTK (DEBUG_SG, + "scsi%d : next scatter-gather buffer len = %d address = %08x\n", + hostno, len, data); + } + break; - case REQ_DATAIN: + case REQ_DATAIN: #ifdef SLOW_RATE - if (borken) - { + if (borken) { #if (DEBUG & (PHASE_DATAIN)) - transfered += len; + transfered += len; #endif - for (; - len && (STATUS & (REQ_MASK | STAT_REQ)) == (REQ_DATAIN | - STAT_REQ) - ; --len) - { - *data++ = DATA; - borken_wait (); - } + for (; + len + && (STATUS & (REQ_MASK | STAT_REQ)) + == (REQ_DATAIN | STAT_REQ); + --len) { + *data++ = DATA; + borken_wait (); + } #if (DEBUG & (PHASE_DATAIN)) - transfered -= len; + transfered -= len; #endif - } - else + } else #endif - if (fast && transfersize && !(len % transfersize) && - (len >= transfersize) + if (fast && transfersize + && !(len % transfersize) + && (len >= transfersize) #ifdef FAST32 - && !(transfersize % 4) + && !(transfersize % 4) #endif - ) - { - DPRINTK (DEBUG_FAST, - "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" - " len = %d, data = %08x\n", - hostno, SCint->underflow, SCint->transfersize, len, data); + ) { + DPRINTK (DEBUG_FAST, + "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" + " len = %d, data = %08x\n", + hostno, SCint->underflow, + SCint->transfersize, len, + data); /* SJT: Start. Fast Read */ #ifdef SEAGATE_USE_ASM - __asm__( - "cld\n\t" + __asm__ ("cld\n\t" #ifdef FAST32 - "shr $2, %%ecx\n\t" - "1:\t" - "movl (%%esi), %%eax\n\t" - "stosl\n\t" + "shr $2, %%ecx\n\t" + "1:\t" + "movl (%%esi), %%eax\n\t" + "stosl\n\t" #else - "1:\t" - "movb (%%esi), %%al\n\t" - "stosb\n\t" -#endif - "loop 1b\n\t" -/* output */ : -/* input */ : "S" (phys_to_virt(st0x_dr)), "D" (data), "c" (SCint->transfersize) -/* clobbered */ : "eax", "ecx", "edi"); -#else /* SEAGATE_USE_ASM */ - { + "1:\t" + "movb (%%esi), %%al\n\t" + "stosb\n\t" +#endif + "loop 1b\n\t" + /* output */ : + /* input */ :"S" (phys_to_virt (st0x_dr)), + "D" + (data), + "c" (SCint->transfersize) +/* clobbered */ + : "eax", "ecx", + "edi"); +#else /* SEAGATE_USE_ASM */ + { #ifdef FAST32 - const unsigned int *iop = phys_to_virt (st0x_dr); - unsigned int *dp = (unsigned int *) data; - int xferlen = len >> 2; + const unsigned int *iop = + phys_to_virt (st0x_dr); + unsigned int *dp = + (unsigned int *) data; + int xferlen = len >> 2; #else - const unsigned char *iop = phys_to_virt (st0x_dr); - unsigned char *dp = data; - int xferlen = len; -#endif - for (; xferlen; --xferlen) - *dp++ = *iop; - } -#endif /* SEAGATE_USE_ASM */ + const unsigned char *iop = + phys_to_virt (st0x_dr); + unsigned char *dp = data; + int xferlen = len; +#endif + for (; xferlen; --xferlen) + *dp++ = *iop; + } +#endif /* SEAGATE_USE_ASM */ /* SJT: End */ - len -= transfersize; - data += transfersize; + len -= transfersize; + data += transfersize; #if (DEBUG & PHASE_DATAIN) - printk ("scsi%d: transfered += %d\n", hostno, transfersize); - transfered += transfersize; + printk ("scsi%d: transfered += %d\n", + hostno, transfersize); + transfered += transfersize; #endif - DPRINTK (DEBUG_FAST, - "scsi%d : FAST transfer complete len = %d data = %08x\n", - hostno, len, data); - } - else - { + DPRINTK (DEBUG_FAST, + "scsi%d : FAST transfer complete len = %d data = %08x\n", + hostno, len, data); + } else { #if (DEBUG & PHASE_DATAIN) - printk ("scsi%d: transfered += %d\n", hostno, len); - transfered += len; /* Assume we'll transfer it all, then - subtract what we *didn't* transfer */ + printk ("scsi%d: transfered += %d\n", + hostno, len); + transfered += len; /* Assume we'll transfer it all, then + subtract what we *didn't* transfer */ #endif /* - * We loop as long as we are in a data in phase, there is room to read, + * We loop as long as we are in a data in phase, there is room to read, * and BSY is still active */ /* SJT: Start. */ #ifdef SEAGATE_USE_ASM -int __dummy_3,__dummy_4; + int __dummy_3, __dummy_4; /* Dummy clobbering variables for the new gcc-2.95 */ @@ -1396,175 +1447,200 @@ * We loop as long as we are in a data in phase, there is room to read, * and BSY is still active */ - /* Local variables : ecx = len, edi = data - esi = st0x_cr_sr, ebx = st0x_dr */ - __asm__ ( - /* Test for room to read */ - "orl %%ecx, %%ecx\n\t" - "jz 2f\n\t" - "cld\n\t" + /* Local variables : ecx = len, edi = data + esi = st0x_cr_sr, ebx = st0x_dr */ + __asm__ ( + /* Test for room to read */ + "orl %%ecx, %%ecx\n\t" + "jz 2f\n\t" "cld\n\t" /* "movl " SYMBOL_NAME_STR(st0x_cr_sr) ", %%esi\n\t" */ /* "movl " SYMBOL_NAME_STR(st0x_dr) ", %%ebx\n\t" */ - "1:\t" - "movb (%%esi), %%al\n\t" - /* Test for BSY */ - "test $1, %%al\n\t" - "jz 2f\n\t" - /* Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, - = STAT_IO, which is 4. */ - "movb $0xe, %%ah\n\t" - "andb %%al, %%ah\n\t" - "cmpb $0x04, %%ah\n\t" - "jne 2f\n\t" - /* Test for REQ */ - "test $0x10, %%al\n\t" - "jz 1b\n\t" - "movb (%%ebx), %%al\n\t" - "stosb\n\t" - "loop 1b\n\t" - "2:\n" -/* output */ : "=D" (data), "=c" (len) ,"=S" (__dummy_3) ,"=b" (__dummy_4) -/* input */ : "0" (data), "1" (len), "2" (phys_to_virt(st0x_cr_sr)), "3" (phys_to_virt(st0x_dr)) -/* clobbered */ : "eax" ); -#else /* SEAGATE_USE_ASM */ - while (len) - { - unsigned char stat; - - stat = STATUS; - if (!(stat & STAT_BSY) || ((stat & REQ_MASK) != REQ_DATAIN)) - break; - if (stat & STAT_REQ) - { - *data++ = DATA; - --len; - } - } -#endif /* SEAGATE_USE_ASM */ + "1:\t" + "movb (%%esi), %%al\n\t" + /* Test for BSY */ + "test $1, %%al\n\t" + "jz 2f\n\t" + /* Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, + = STAT_IO, which is 4. */ + "movb $0xe, %%ah\n\t" + "andb %%al, %%ah\n\t" + "cmpb $0x04, %%ah\n\t" + "jne 2f\n\t" + /* Test for REQ */ + "test $0x10, %%al\n\t" + "jz 1b\n\t" + "movb (%%ebx), %%al\n\t" + "stosb\n\t" + "loop 1b\n\t" "2:\n" + /* output */ :"=D" (data), "=c" (len), + "=S" + (__dummy_3), + "=b" (__dummy_4) +/* input */ + : "0" (data), "1" (len), + "2" (phys_to_virt + (st0x_cr_sr)), + "3" (phys_to_virt + (st0x_dr)) +/* clobbered */ + : "eax"); +#else /* SEAGATE_USE_ASM */ + while (len) { + unsigned char stat; + + stat = STATUS; + if (!(stat & STAT_BSY) + || ((stat & REQ_MASK) != + REQ_DATAIN)) + break; + if (stat & STAT_REQ) { + *data++ = DATA; + --len; + } + } +#endif /* SEAGATE_USE_ASM */ /* SJT: End. */ #if (DEBUG & PHASE_DATAIN) - printk ("scsi%d: transfered -= %d\n", hostno, len); - transfered -= len; /* Since we assumed all of Len got * - transfered, correct our mistake */ -#endif - } - - if (!len && nobuffs) - { - --nobuffs; - ++buffer; - len = buffer->length; - data = (unsigned char *) buffer->address; - DPRINTK (DEBUG_SG, - "scsi%d : next scatter-gather buffer len = %d address = %08x\n", - hostno, len, data); - } - - break; - - case REQ_CMDOUT: - while (((status_read = STATUS) & STAT_BSY) && - ((status_read & REQ_MASK) == REQ_CMDOUT)) - if (status_read & STAT_REQ) - { - WRITE_DATA (*(const unsigned char *) cmnd); - cmnd = 1 + (const unsigned char *) cmnd; + printk ("scsi%d: transfered -= %d\n", + hostno, len); + transfered -= len; /* Since we assumed all of Len got * + transfered, correct our mistake */ +#endif + } + + if (!len && nobuffs) { + --nobuffs; + ++buffer; + len = buffer->length; + data = + (unsigned char *) buffer->address; + DPRINTK (DEBUG_SG, + "scsi%d : next scatter-gather buffer len = %d address = %08x\n", + hostno, len, data); + } + + break; + + case REQ_CMDOUT: + while (((status_read = STATUS) & STAT_BSY) && + ((status_read & REQ_MASK) == REQ_CMDOUT)) + if (status_read & STAT_REQ) { + WRITE_DATA (* + (const unsigned char + *) cmnd); + cmnd = + 1 + + (const unsigned char *) + cmnd; #ifdef SLOW_RATE - if (borken) - borken_wait (); + if (borken) + borken_wait (); #endif - } - break; + } + break; - case REQ_STATIN: - status = DATA; - break; + case REQ_STATIN: + status = DATA; + break; - case REQ_MSGOUT: + case REQ_MSGOUT: /* - * We can only have sent a MSG OUT if we requested to do this + * We can only have sent a MSG OUT if we requested to do this * by raising ATTN. So, we must drop ATTN. */ - WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE); + WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE); /* - * If we are reconnecting, then we must send an IDENTIFY message in - * response to MSGOUT. + * If we are reconnecting, then we must send an IDENTIFY message in + * response to MSGOUT. */ - switch (reselect) - { - case CAN_RECONNECT: - WRITE_DATA (IDENTIFY (1, lun)); - - DPRINTK (PHASE_RESELECT | PHASE_MSGOUT, "scsi%d : sent IDENTIFY message.\n", hostno); - break; + switch (reselect) { + case CAN_RECONNECT: + WRITE_DATA (IDENTIFY (1, lun)); + + DPRINTK (PHASE_RESELECT | PHASE_MSGOUT, + "scsi%d : sent IDENTIFY message.\n", + hostno); + break; #ifdef LINKED - case LINKED_WRONG: - WRITE_DATA (ABORT); - linked_connected = 0; - reselect = CAN_RECONNECT; - goto connect_loop; - DPRINTK (PHASE_MSGOUT | DEBUG_LINKED, - "scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.\n", hostno); -#endif /* LINKED */ - DPRINTK (DEBUG_LINKED, "correct\n"); - default: - WRITE_DATA (NOP); - printk ("scsi%d : target %d requested MSGOUT, sent NOP message.\n", hostno, target); - } - break; - - case REQ_MSGIN: - switch (message = DATA) - { - case DISCONNECT: - DANY ("seagate: deciding to disconnect\n"); - should_reconnect = 1; - current_data = data; /* WDE add */ - current_buffer = buffer; - current_bufflen = len; /* WDE add */ - current_nobuffs = nobuffs; + case LINKED_WRONG: + WRITE_DATA (ABORT); + linked_connected = 0; + reselect = CAN_RECONNECT; + goto connect_loop; + DPRINTK (PHASE_MSGOUT | DEBUG_LINKED, + "scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.\n", + hostno); +#endif /* LINKED */ + DPRINTK (DEBUG_LINKED, "correct\n"); + default: + WRITE_DATA (NOP); + printk + ("scsi%d : target %d requested MSGOUT, sent NOP message.\n", + hostno, target); + } + break; + + case REQ_MSGIN: + switch (message = DATA) { + case DISCONNECT: + DANY ("seagate: deciding to disconnect\n"); + should_reconnect = 1; + current_data = data; /* WDE add */ + current_buffer = buffer; + current_bufflen = len; /* WDE add */ + current_nobuffs = nobuffs; #ifdef LINKED - linked_connected = 0; + linked_connected = 0; #endif - done = 1; - DPRINTK ((PHASE_RESELECT | PHASE_MSGIN), "scsi%d : disconnected.\n", hostno); - break; + done = 1; + DPRINTK ((PHASE_RESELECT | PHASE_MSGIN), + "scsi%d : disconnected.\n", + hostno); + break; #ifdef LINKED - case LINKED_CMD_COMPLETE: - case LINKED_FLG_CMD_COMPLETE: + case LINKED_CMD_COMPLETE: + case LINKED_FLG_CMD_COMPLETE: #endif - case COMMAND_COMPLETE: + case COMMAND_COMPLETE: /* * Note : we should check for underflow here. */ - DPRINTK (PHASE_MSGIN, "scsi%d : command complete.\n", hostno); - done = 1; - break; - case ABORT: - DPRINTK (PHASE_MSGIN, "scsi%d : abort message.\n", hostno); - done = 1; - break; - case SAVE_POINTERS: - current_buffer = buffer; - current_bufflen = len; /* WDE add */ - current_data = data; /* WDE mod */ - current_nobuffs = nobuffs; - DPRINTK (PHASE_MSGIN, "scsi%d : pointers saved.\n", hostno); - break; - case RESTORE_POINTERS: - buffer = current_buffer; - cmnd = current_cmnd; - data = current_data; /* WDE mod */ - len = current_bufflen; - nobuffs = current_nobuffs; - DPRINTK (PHASE_MSGIN, "scsi%d : pointers restored.\n", hostno); - break; - default: + DPRINTK (PHASE_MSGIN, + "scsi%d : command complete.\n", + hostno); + done = 1; + break; + case ABORT: + DPRINTK (PHASE_MSGIN, + "scsi%d : abort message.\n", + hostno); + done = 1; + break; + case SAVE_POINTERS: + current_buffer = buffer; + current_bufflen = len; /* WDE add */ + current_data = data; /* WDE mod */ + current_nobuffs = nobuffs; + DPRINTK (PHASE_MSGIN, + "scsi%d : pointers saved.\n", + hostno); + break; + case RESTORE_POINTERS: + buffer = current_buffer; + cmnd = current_cmnd; + data = current_data; /* WDE mod */ + len = current_bufflen; + nobuffs = current_nobuffs; + DPRINTK (PHASE_MSGIN, + "scsi%d : pointers restored.\n", + hostno); + break; + default: /* - * IDENTIFY distinguishes itself from the other messages by setting the + * IDENTIFY distinguishes itself from the other messages by setting the * high byte. [FIXME: should not this read "the high bit"? - pavel@ucw.cz] * * Note : we need to handle at least one outstanding command per LUN, @@ -1572,13 +1648,12 @@ * known ID (at this point) and LUN. */ - if (message & 0x80) - { - DPRINTK (PHASE_MSGIN, "scsi%d : IDENTIFY message received from id %d, lun %d.\n", - hostno, target, message & 7); - } - else - { + if (message & 0x80) { + DPRINTK (PHASE_MSGIN, + "scsi%d : IDENTIFY message received from id %d, lun %d.\n", + hostno, target, + message & 7); + } else { /* * We should go into a MESSAGE OUT phase, and send a MESSAGE_REJECT @@ -1586,17 +1661,19 @@ * needs some serious restructuring first though. */ - DPRINTK (PHASE_MSGIN, - "scsi%d : unknown message %d from target %d.\n", hostno, message, target); - } - } - break; - - default: - printk ("scsi%d : unknown phase.\n", hostno); - st0x_aborted = DID_ERROR; - } /* end of switch (status_read & - REQ_MASK) */ + DPRINTK (PHASE_MSGIN, + "scsi%d : unknown message %d from target %d.\n", + hostno, message, + target); + } + } + break; + + default: + printk ("scsi%d : unknown phase.\n", hostno); + st0x_aborted = DID_ERROR; + } /* end of switch (status_read & + REQ_MASK) */ #ifdef SLOW_RATE /* @@ -1604,34 +1681,34 @@ * byte transfer case (ie, message in, message out, status), so * I'll do the wait here if necessary. */ - if (borken) - borken_wait (); + if (borken) + borken_wait (); #endif - } /* if(status_read & STAT_REQ) ends */ - } /* while(((status_read = STATUS)...) - ends */ + } /* if(status_read & STAT_REQ) ends */ + } /* while(((status_read = STATUS)...) + ends */ - DPRINTK (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT, - "scsi%d : Transfered %d bytes\n", hostno, transfered); + DPRINTK (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT, + "scsi%d : Transfered %d bytes\n", hostno, transfered); #if (DEBUG & PHASE_EXIT) -#if 0 /* Doesn't work for scatter/gather */ - printk ("Buffer : \n"); - for (i = 0; i < 20; ++i) - printk ("%02x ", ((unsigned char *) data)[i]); /* WDE mod */ - printk ("\n"); -#endif - printk ("scsi%d : status = ", hostno); - print_status (status); - printk ("message = %02x\n", message); +#if 0 /* Doesn't work for scatter/gather */ + printk ("Buffer : \n"); + for (i = 0; i < 20; ++i) + printk ("%02x ", ((unsigned char *) data)[i]); /* WDE mod */ + printk ("\n"); +#endif + printk ("scsi%d : status = ", hostno); + print_status (status); + printk ("message = %02x\n", message); #endif /* We shouldn't reach this until *after* BSY has been deasserted */ #ifdef LINKED - else - { + else + { /* * Fix the message byte so that unsuspecting high level drivers don't * puke when they see a LINKED COMMAND message in place of the COMMAND @@ -1642,52 +1719,53 @@ * and we are now disconnected. */ - switch (message) - { - case LINKED_CMD_COMPLETE: - case LINKED_FLG_CMD_COMPLETE: - message = COMMAND_COMPLETE; - linked_target = current_target; - linked_lun = current_lun; - linked_connected = 1; - DPRINTK (DEBUG_LINKED, "scsi%d : keeping I_T_L nexus established" - "for linked command.\n", hostno); - /* We also will need to adjust status to accommodate intermediate - conditions. */ - if ((status == INTERMEDIATE_GOOD) || - (status == INTERMEDIATE_C_GOOD)) - status = GOOD; + switch (message) { + case LINKED_CMD_COMPLETE: + case LINKED_FLG_CMD_COMPLETE: + message = COMMAND_COMPLETE; + linked_target = current_target; + linked_lun = current_lun; + linked_connected = 1; + DPRINTK (DEBUG_LINKED, + "scsi%d : keeping I_T_L nexus established" + "for linked command.\n", hostno); + /* We also will need to adjust status to accommodate intermediate + conditions. */ + if ((status == INTERMEDIATE_GOOD) || + (status == INTERMEDIATE_C_GOOD)) + status = GOOD; - break; + break; /* * We should also handle what are "normal" termination messages * here (ABORT, BUS_DEVICE_RESET?, and COMMAND_COMPLETE individually, * and flake if things aren't right. */ - default: - DPRINTK (DEBUG_LINKED, "scsi%d : closing I_T_L nexus.\n", hostno); - linked_connected = 0; - } - } -#endif /* LINKED */ - - if (should_reconnect) - { - DPRINTK (PHASE_RESELECT, "scsi%d : exiting seagate_st0x_queue_command()" - "with reconnect enabled.\n", hostno); - WRITE_CONTROL (BASE_CMD | CMD_INTR); - } - else - WRITE_CONTROL (BASE_CMD); + default: + DPRINTK (DEBUG_LINKED, + "scsi%d : closing I_T_L nexus.\n", hostno); + linked_connected = 0; + } + } +#endif /* LINKED */ - return retcode (st0x_aborted); -} /* end of internal_command */ + if (should_reconnect) { + DPRINTK (PHASE_RESELECT, + "scsi%d : exiting seagate_st0x_queue_command()" + "with reconnect enabled.\n", hostno); + WRITE_CONTROL (BASE_CMD | CMD_INTR); + } else + WRITE_CONTROL (BASE_CMD); -int seagate_st0x_abort (Scsi_Cmnd * SCpnt) + return retcode (st0x_aborted); +} /* end of internal_command */ + +static int seagate_st0x_abort (Scsi_Cmnd * SCpnt) { - st0x_aborted = DID_ABORT; - return SCSI_ABORT_PENDING; + st0x_aborted = DID_ABORT; + return SCSI_ABORT_PENDING; } + #undef ULOOP #undef TIMEOUT @@ -1695,23 +1773,22 @@ * the seagate_st0x_reset function resets the SCSI bus */ -int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags) +static int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags) { /* No timeouts - this command is going to fail because it was reset. */ - DANY ("scsi%d: Reseting bus... ", hostno ); + DANY ("scsi%d: Reseting bus... ", hostno); /* assert RESET signal on SCSI bus. */ - WRITE_CONTROL (BASE_CMD | CMD_RST); + WRITE_CONTROL (BASE_CMD | CMD_RST); - udelay( 20*1000 ); + udelay (20 * 1000); - WRITE_CONTROL (BASE_CMD); - st0x_aborted = DID_RESET; + WRITE_CONTROL (BASE_CMD); + st0x_aborted = DID_RESET; - DANY ("done.\n"); - return SCSI_RESET_WAKEUP; + DANY ("done.\n"); + return SCSI_RESET_WAKEUP; } - /* Eventually this will go into an include file, but this will be later */ static Scsi_Host_Template driver_template = SEAGATE_ST0X; diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/seagate.h linux/drivers/scsi/seagate.h --- v2.4.9/linux/drivers/scsi/seagate.h Sun Sep 17 09:51:57 2000 +++ linux/drivers/scsi/seagate.h Fri Sep 7 09:28:37 2001 @@ -16,9 +16,9 @@ int seagate_st0x_command(Scsi_Cmnd *); int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int seagate_st0x_abort(Scsi_Cmnd *); +static int seagate_st0x_abort(Scsi_Cmnd *); const char *seagate_st0x_info(struct Scsi_Host *); -int seagate_st0x_reset(Scsi_Cmnd *, unsigned int); +static int seagate_st0x_reset(Scsi_Cmnd *, unsigned int); #define SEAGATE_ST0X { detect: seagate_st0x_detect, \ info: seagate_st0x_info, \ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v2.4.9/linux/drivers/scsi/sg.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/scsi/sg.c Fri Sep 7 09:28:37 2001 @@ -19,9 +19,9 @@ */ #include #ifdef CONFIG_PROC_FS - static char sg_version_str[] = "Version: 3.1.19 (20010623)"; + static char sg_version_str[] = "Version: 3.1.20 (20010814)"; #endif - static int sg_version_num = 30119; /* 2 digits for each component */ + static int sg_version_num = 30120; /* 2 digits for each component */ /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First @@ -271,6 +271,7 @@ /* Prevent the device driver from vanishing while we sleep */ if (sdp->device->host->hostt->module) __MOD_INC_USE_COUNT(sdp->device->host->hostt->module); + sdp->device->access_count++; if (! ((flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) { @@ -323,6 +324,7 @@ return 0; error_out: + sdp->device->access_count--; if ((! sdp->detached) && sdp->device->host->hostt->module) __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module); return retval; @@ -342,8 +344,11 @@ SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev))); sg_fasync(-1, filp, 0); /* remove filp from async notification list */ if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */ - if ((! sdp->detached) && sdp->device->host->hostt->module) - __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module); + if (! sdp->detached) { + sdp->device->access_count--; + if (sdp->device->host->hostt->module) + __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module); + } sdp->exclude = 0; wake_up_interruptible(&sdp->o_excl_wait); } @@ -874,6 +879,9 @@ return 0; case SG_GET_VERSION_NUM: return put_user(sg_version_num, (int *)arg); + case SG_GET_ACCESS_COUNT: + val = (sdp->device ? sdp->device->access_count : 0); + return put_user(val, (int *)arg); case SG_GET_REQUEST_TABLE: result = verify_area(VERIFY_WRITE, (void *) arg, SZ_SG_REQ_INFO * SG_MAX_QUEUE); @@ -1116,6 +1124,7 @@ sg_remove_sfp(sdp, sfp); sfp = NULL; } + sdp->device->access_count--; if (sg_template.module) __MOD_DEC_USE_COUNT(sg_template.module); if (sdp->device->host->hostt->module) @@ -1241,6 +1250,15 @@ for(k = 0; k < sg_template.dev_max; k++) if(! sg_dev_arr[k]) break; + if (k > MINORMASK) { + scsidp->attached--; + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + printk("Unable to attach sg device <%d, %d, %d, %d>" + " type=%d, minor number exceed %d\n", scsidp->host->host_no, + scsidp->channel, scsidp->id, scsidp->lun, scsidp->type, + MINORMASK); + return 1; + } if(k < sg_template.dev_max) sdp = (Sg_device *)kmalloc(sizeof(Sg_device), GFP_ATOMIC); else @@ -1264,7 +1282,7 @@ sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT, SCSI_GENERIC_MAJOR, k, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - &sg_fops, NULL); + &sg_fops, sdp); sg_template.nr_dev++; sg_dev_arr[k] = sdp; write_unlock_irqrestore(&sg_dev_arr_lock, iflags); @@ -1314,6 +1332,7 @@ sg_finish_rem_req(srp); } if (sfp->closed) { + sdp->device->access_count--; if (sg_template.module) __MOD_DEC_USE_COUNT(sg_template.module); if (sdp->device->host->hostt->module) @@ -2210,6 +2229,7 @@ } else { sfp->closed = 1; /* flag dirty state on this fd */ + sdp->device->access_count++; /* MOD_INC's to inhibit unloading sg and associated adapter driver */ if (sg_template.module) __MOD_INC_USE_COUNT(sg_template.module); @@ -2753,7 +2773,7 @@ static int sg_proc_devhdr_info(char * buffer, int * len, off_t * begin, off_t offset, int size) { - PRINT_PROC("host\tchan\tid\tlun\ttype\tbopens\tqdepth\tbusy\tonline\n"); + PRINT_PROC("host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n"); return 1; } diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.4.9/linux/drivers/scsi/sr.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/scsi/sr.c Mon Aug 27 14:20:21 2001 @@ -101,7 +101,6 @@ { if (scsi_CDs[MINOR(cdi->dev)].device->sector_size > 2048) sr_set_blocklength(MINOR(cdi->dev), 2048); - sync_dev(cdi->dev); scsi_CDs[MINOR(cdi->dev)].device->access_count--; if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module) __MOD_DEC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module); diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/ds1286.c linux/drivers/sgi/char/ds1286.c --- v2.4.9/linux/drivers/sgi/char/ds1286.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sgi/char/ds1286.c Mon Aug 27 08:56:31 2001 @@ -1,32 +1,30 @@ -/* $Id: ds1286.c,v 1.6 1999/10/09 00:01:31 ralf Exp $ - * - * Real Time Clock interface for Linux +/* + * DS1286 Real Time Clock interface for Linux * - * Copyright (C) 1998, 1999 Ralf Baechle + * Copyright (C) 1998, 1999, 2000 Ralf Baechle * - * Based on code written by Paul Gortmaker. + * Based on code written by Paul Gortmaker. * - * This driver allows use of the real time clock (built into - * nearly all computers) from user space. It exports the /dev/rtc - * interface supporting various ioctl() and also the /proc/rtc - * pseudo-file for status information. + * This driver allows use of the real time clock (built into nearly all + * computers) from user space. It exports the /dev/rtc interface supporting + * various ioctl() and also the /proc/rtc pseudo-file for status + * information. * - * The ioctls can be used to set the interrupt behaviour and - * generation rate from the RTC via IRQ 8. Then the /dev/rtc - * interface can be used to make use of these timer interrupts, - * be they interval or alarm based. + * The ioctls can be used to set the interrupt behaviour and generation rate + * from the RTC via IRQ 8. Then the /dev/rtc interface can be used to make + * use of these timer interrupts, be they interval or alarm based. * - * The /dev/rtc interface will block on reads until an interrupt - * has been received. If a RTC interrupt has already happened, - * it will output an unsigned long and then block. The output value - * contains the interrupt status in the low byte and the number of - * interrupts since the last read in the remaining high bytes. The - * /dev/rtc interface can also be used with the select(2) call. + * The /dev/rtc interface will block on reads until an interrupt has been + * received. If a RTC interrupt has already happened, it will output an + * unsigned long and then block. The output value contains the interrupt + * status in the low byte and the number of interrupts since the last read + * in the remaining high bytes. The /dev/rtc interface can also be used with + * the select(2) call. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. */ #include #include @@ -38,7 +36,6 @@ #include #include #include -#include #include #include @@ -81,58 +78,20 @@ #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ #define RTC_TIMER_ON 0x02 /* missed irq timer active */ -unsigned char ds1286_status = 0; /* bitmapped status byte. */ -unsigned long ds1286_freq = 0; /* Current periodic IRQ rate */ -unsigned long ds1286_irq_data = 0; /* our output to the world */ +unsigned char ds1286_status; /* bitmapped status byte. */ +unsigned long ds1286_freq; /* Current periodic IRQ rate */ unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* - * A very tiny interrupt handler. It runs with SA_INTERRUPT set, - * so that there is no possibility of conflicting with the - * set_rtc_mmss() call that happens during some timer interrupts. - * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) - */ - -/* * Now all the various file operations that we export. */ static ssize_t ds1286_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - DECLARE_WAITQUEUE(wait, current); - unsigned long data; - ssize_t retval; - - if (count < sizeof(unsigned long)) - return -EINVAL; - - add_wait_queue(&ds1286_wait, &wait); - - current->state = TASK_INTERRUPTIBLE; - - while ((data = xchg(&ds1286_irq_data, 0)) == 0) { - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - goto out; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - goto out; - } - schedule(); - } - - retval = put_user(data, (unsigned long *)buf); - if (!retval) - retval = sizeof(unsigned long); - out: - current->state = TASK_RUNNING; - remove_wait_queue(&ds1286_wait, &wait); - - return retval; + return -EIO; } static int ds1286_ioctl(struct inode *inode, struct file *file, @@ -338,27 +297,32 @@ static int ds1286_open(struct inode *inode, struct file *file) { - if(ds1286_status & RTC_IS_OPEN) - return -EBUSY; + spin_lock_irq(&ds1286_lock); + + if (ds1286_status & RTC_IS_OPEN) + goto out_busy; ds1286_status |= RTC_IS_OPEN; - ds1286_irq_data = 0; + + spin_lock_irq(&ds1286_lock); return 0; + +out_busy: + spin_lock_irq(&ds1286_lock); + return -EBUSY; } static int ds1286_release(struct inode *inode, struct file *file) { - lock_kernel(); ds1286_status &= ~RTC_IS_OPEN; - unlock_kernel(); + return 0; } static unsigned int ds1286_poll(struct file *file, poll_table *wait) { poll_wait(file, &ds1286_wait, wait); - if (ds1286_irq_data != 0) - return POLLIN | POLLRDNORM; + return 0; } @@ -407,7 +371,7 @@ get_rtc_time(&tm); hundredth = CMOS_READ(RTC_HUNDREDTH_SECOND); - hundredth = BCD_TO_BIN(hundredth); + BCD_TO_BIN(hundredth); p += sprintf(p, "rtc_time\t: %02d:%02d:%02d.%02d\n" diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c --- v2.4.9/linux/drivers/sgi/char/graphics.c Mon Mar 19 12:35:09 2001 +++ linux/drivers/sgi/char/graphics.c Mon Aug 27 08:56:31 2001 @@ -1,5 +1,4 @@ -/* $Id: graphics.c,v 1.22 2000/02/18 00:24:43 ralf Exp $ - * +/* * gfx.c: support for SGI's /dev/graphics, /dev/opengl * * Author: Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -214,8 +213,7 @@ /* * This is the core of the direct rendering engine. */ - -unsigned long +struct page * sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int no_share) { @@ -250,7 +248,6 @@ pgd = pgd_offset(current->mm, address); pmd = pmd_offset(pgd, address); pte = pte_offset(pmd, address); - printk("page: %08lx\n", pte_page(*pte)); return pte_page(*pte); } diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/graphics_syms.c linux/drivers/sgi/char/graphics_syms.c --- v2.4.9/linux/drivers/sgi/char/graphics_syms.c Mon Feb 28 07:18:20 2000 +++ linux/drivers/sgi/char/graphics_syms.c Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* - * graphics_syms.c: interfaces for SGI Indy newport graphics - * - * Copyright (C) 1999 Alex deVries - * - * We should not even be trying to compile this if we are not doing - * a module. - */ - -#define __NO_VERSION__ -#include - -/* extern int rrm_command (unsigned int cmd, void *arg); -extern int rrm_close (struct inode *inode, struct file *file); -EXPORT_SYMBOL(rrm_command); -EXPORT_SYMBOL(rrm_close); - - -*/ -extern void shmiq_init (void); -extern void usema_init(void); - -EXPORT_SYMBOL(shmiq_init); -EXPORT_SYMBOL(usema_init); - -extern void disable_gconsole(void); -extern void enable_gconsole(void); -extern void remove_mapping (struct task_struct *task, unsigned long start, - unsigned long end); - -EXPORT_SYMBOL(disable_gconsole); -EXPORT_SYMBOL(enable_gconsole); -EXPORT_SYMBOL(remove_mapping); - -EXPORT_SYMBOL(npregs); diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/newport.c linux/drivers/sgi/char/newport.c --- v2.4.9/linux/drivers/sgi/char/newport.c Mon Feb 28 07:18:20 2000 +++ linux/drivers/sgi/char/newport.c Mon Aug 27 08:56:31 2001 @@ -16,6 +16,8 @@ struct newport_regs *npregs; +EXPORT_SYMBOL(npregs); + /* Kernel routines for supporting graphics context switching */ void newport_save (void *y) diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/rrm.c linux/drivers/sgi/char/rrm.c --- v2.4.9/linux/drivers/sgi/char/rrm.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/sgi/char/rrm.c Mon Aug 27 08:56:31 2001 @@ -9,12 +9,11 @@ * * Fixes: */ +#include + #include #include -#ifdef MODULE -#include -#endif int rrm_open_rn (int rnid, void *arg) @@ -71,3 +70,6 @@ /* This routine is invoked when the device is closed */ return 0; } + +EXPORT_SYMBOL(rrm_command); +EXPORT_SYMBOL(rrm_close); diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/sgicons.c linux/drivers/sgi/char/sgicons.c --- v2.4.9/linux/drivers/sgi/char/sgicons.c Sun Jul 9 22:32:58 2000 +++ linux/drivers/sgi/char/sgicons.c Mon Aug 27 08:56:31 2001 @@ -1,5 +1,4 @@ -/* $Id: sgicons.c,v 1.10 1998/08/25 09:18:58 ralf Exp $ - * +/* * sgicons.c: Setting up and registering console I/O on the SGI. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -10,12 +9,10 @@ #include #include #include +#include #include #include "gconsole.h" -/* To make psaux code cleaner */ -unsigned char aux_device_present = 0xaa; - /* This is the system graphics console (the first adapter found) */ struct console_ops *gconsole = 0; struct console_ops *real_gconsole = 0; @@ -35,6 +32,9 @@ gconsole = 0; } } + +EXPORT_SYMBOL(disable_gconsole); +EXPORT_SYMBOL(enable_gconsole); void register_gconsole (struct console_ops *gc) diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/sgiserial.c linux/drivers/sgi/char/sgiserial.c --- v2.4.9/linux/drivers/sgi/char/sgiserial.c Thu Oct 12 14:20:47 2000 +++ linux/drivers/sgi/char/sgiserial.c Mon Aug 27 08:56:31 2001 @@ -13,6 +13,9 @@ * thorough pass to merge in the rest of the updates. * Better still, someone really ought to make it a common * code module for both platforms. kevink@mips.com + * + * 20010616 - Klaus Naumann : Make serial console work with + * any speed - not only 9600 */ #include /* for CONFIG_REMOTE_DEBUG */ @@ -58,9 +61,9 @@ static int zilog_irq = SGI_SERIAL_IRQ; /* Console hooks... */ -static int zs_cons_chanout = 0; -static int zs_cons_chanin = 0; -struct sgi_serial *zs_consinfo = 0; +static int zs_cons_chanout; +static int zs_cons_chanin; +struct sgi_serial *zs_consinfo; static unsigned char kgdb_regs[16] = { 0, 0, 0, /* write 0, 1, 2 */ @@ -97,6 +100,7 @@ DECLARE_TASK_QUEUE(tq_serial); struct tty_driver serial_driver, callout_driver; +struct console *sgisercon; static int serial_refcount; /* serial subtype definitions */ @@ -144,10 +148,10 @@ dev_t device, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = + static const char *badmagic = KERN_WARNING "Warning: bad magic number for serial struct (%d, %d) in %s\n"; - static const char *badinfo = - "Warning: null sun_serial for (%d, %d) in %s\n"; + static const char *badinfo = KERN_WARNING + "Warning: null sgi_serial for (%d, %d) in %s\n"; if (!info) { printk(badinfo, MAJOR(device), MINOR(device), routine); @@ -178,7 +182,8 @@ * interrupts are enabled. Therefore we have to check ioc_iocontrol before we * access it. */ -static inline unsigned char read_zsreg(struct sgi_zschannel *channel, unsigned char reg) +static inline unsigned char read_zsreg(struct sgi_zschannel *channel, + unsigned char reg) { unsigned char retval; volatile unsigned char junk; @@ -192,7 +197,8 @@ return retval; } -static inline void write_zsreg(struct sgi_zschannel *channel, unsigned char reg, unsigned char value) +static inline void write_zsreg(struct sgi_zschannel *channel, + unsigned char reg, unsigned char value) { volatile unsigned char junk; @@ -323,7 +329,7 @@ */ static void batten_down_hatches(void) { - prom_imode(); + ArcEnterInteractiveMode(); #if 0 /* If we are doing kadb, we call the debugger * else we just drop into the boot monitor. @@ -682,7 +688,7 @@ save_flags(flags); cli(); #ifdef SERIAL_DEBUG_OPEN - printk("starting up ttys%d (irq %d)...", info->line, info->irq); + printk("starting up ttys%d (irq %d)...\n", info->line, info->irq); #endif /* @@ -1302,6 +1308,59 @@ junk = ioc_icontrol->istat0; sti(); return put_user(status,value); +} + +static int get_modem_info(struct sgi_serial * info, unsigned int *value) +{ + unsigned char status; + unsigned int result; + + cli(); + status = info->zs_channel->control; + udelay(2); + sti(); + result = ((info->curregs[5] & RTS) ? TIOCM_RTS : 0) + | ((info->curregs[5] & DTR) ? TIOCM_DTR : 0) + | ((status & DCD) ? TIOCM_CAR : 0) + | ((status & SYNC) ? TIOCM_DSR : 0) + | ((status & CTS) ? TIOCM_CTS : 0); + if (put_user(result, value)) + return -EFAULT; + return 0; +} + +static int set_modem_info(struct sgi_serial * info, unsigned int cmd, + unsigned int *value) +{ + unsigned int arg; + + if (get_user(arg, value)) + return -EFAULT; + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + info->curregs[5] |= RTS; + if (arg & TIOCM_DTR) + info->curregs[5] |= DTR; + break; + case TIOCMBIC: + if (arg & TIOCM_RTS) + info->curregs[5] &= ~RTS; + if (arg & TIOCM_DTR) + info->curregs[5] &= ~DTR; + break; + case TIOCMSET: + info->curregs[5] = ((info->curregs[5] & ~(RTS | DTR)) + | ((arg & TIOCM_RTS) ? RTS : 0) + | ((arg & TIOCM_DTR) ? DTR : 0)); + break; + default: + return -EINVAL; + } + cli(); + write_zsreg(info->zs_channel, 5, info->curregs[5]); + sti(); + return 0; } /* @@ -1322,11 +1381,10 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - int error; - struct sgi_serial * info = (struct sgi_serial *)tty->driver_data; + struct sgi_serial * info = (struct sgi_serial *) tty->driver_data; int retval; - if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + if (serial_paranoia_check(info, tty->device, "zs_ioctl")) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && @@ -1353,45 +1411,36 @@ send_break(info, arg ? arg*(HZ/10) : HZ/4); return 0; case TIOCGSOFTCAR: - error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); - if (error) - return error; - put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long *) arg); + if (put_user(C_CLOCAL(tty) ? 1 : 0, + (unsigned long *) arg)) + return -EFAULT; return 0; case TIOCSSOFTCAR: - error = get_user(arg, (unsigned long *)arg); - if (error) - return error; + if (get_user(arg, (unsigned long *) arg)) + return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; + case TIOCMGET: + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); case TIOCGSERIAL: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct)); - if (error) - return error; return get_serial_info(info, (struct serial_struct *) arg); case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; - else - return get_lsr_info(info, (unsigned int *) arg); + return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct sgi_serial)); - if (error) - return error; - copy_to_user((struct sun_serial *) arg, - info, sizeof(struct sgi_serial)); + if (copy_to_user((struct sgi_serial *) arg, + info, sizeof(struct sgi_serial))) + return -EFAULT; return 0; default: @@ -1727,11 +1776,19 @@ change_speed(info); } + /* If this is the serial console change the speed to + * the right value + */ + if (info->is_cons) { + info->tty->termios->c_cflag = sgisercon->cflag; + change_speed(info); + } + info->session = current->session; info->pgrp = current->pgrp; #ifdef SERIAL_DEBUG_OPEN - printk("rs_open ttys%d successful...", info->line); + printk("rs_open ttys%d successful...\n", info->line); #endif return 0; } @@ -1748,13 +1805,10 @@ { extern struct hpc3_miscregs *hpc3mregs; - if(chip > 0) { - prom_printf("Wheee, bogus zs chip number requested.\n"); - prom_getchar(); - romvec->imode(); - } - return (struct sgi_zslayout *) (&hpc3mregs->ser1cmd); + if (chip > 0) + panic("Wheee, bogus zs chip number requested."); + return (struct sgi_zslayout *) (&hpc3mregs->ser1cmd); } @@ -1784,13 +1838,6 @@ } if(o && i) io = 1; - if(ss->zs_baud != 9562) { /* Don't ask... */ - prom_printf("BAD console baud rate %d\n", ss->zs_baud); - prom_getchar(); - prom_imode(); - panic("Console baud rate weirdness"); - } - /* Set flag variable for this port so that it cannot be * opened for other uses by accident. @@ -1798,7 +1845,7 @@ ss->is_cons = 1; if(io) { - if(!msg_printed) { + if (!msg_printed) { printk("zs%d: console I/O\n", ((channel>>1)&1)); msg_printed = 1; } @@ -1806,7 +1853,6 @@ } else { printk("zs%d: console %s\n", ((channel>>1)&1), (i==1 ? "input" : (o==1 ? "output" : "WEIRD"))); - } } @@ -2002,7 +2048,6 @@ rs_cons_hook(int chip, int out, int line) { int channel; - if(chip) panic("rs_cons_hook called with chip not zero"); @@ -2087,11 +2132,11 @@ static int __init zs_console_setup(struct console *con, char *options) { struct sgi_serial *info; - int baud = 9600; + int baud; int bits = 8; int parity = 'n'; int cflag = CREAD | HUPCL | CLOCAL; - char *s; + char *s, *dbaud; int i, brg; if (options) { @@ -2102,6 +2147,21 @@ if (*s) parity = *s++; if (*s) bits = *s - '0'; } + else { + /* If the user doesn't set console=... try to read the + * PROM variable - if this fails use 9600 baud and + * inform the user about the problem + */ + dbaud = ArcGetEnvironmentVariable("dbaud"); + if(dbaud) baud = simple_strtoul(dbaud, NULL, 10); + else { + /* Use prom_printf() to make sure that the user + * is getting anything ... + */ + prom_printf("No dbaud set in PROM ?!? Using 9600.\n"); + baud = 9600; + } + } /* * Now construct a cflag setting. @@ -2156,7 +2216,8 @@ info = zs_soft + con->index; info->is_cons = 1; - printk("Console: ttyS%d (Zilog8530)\n", info->line); + printk("Console: ttyS%d (Zilog8530), %d baud\n", + info->line, baud); i = con->cflag & CBAUD; if (con->cflag & CBAUDEX) { @@ -2195,6 +2256,8 @@ zscons_regs[4] |= SB2; else zscons_regs[4] |= SB1; + + sgisercon = con; brg = BPS_TO_BRG(baud, ZS_CLOCK / info->clk_divisor); zscons_regs[12] = brg & 0xff; diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/sgiserial.h linux/drivers/sgi/char/sgiserial.h --- v2.4.9/linux/drivers/sgi/char/sgiserial.h Fri Jun 25 17:39:34 1999 +++ linux/drivers/sgi/char/sgiserial.h Mon Aug 27 08:56:31 2001 @@ -359,7 +359,7 @@ #define ZCOUNT 0x2 /* Zero count */ #define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ #define DCD 0x8 /* DCD */ -#define SYNC_HUNT 0x10 /* Sync/hunt */ +#define SYNC 0x10 /* Sync/hunt */ #define CTS 0x20 /* CTS */ #define TxEOM 0x40 /* Tx underrun */ #define BRK_ABRT 0x80 /* Break/Abort */ diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c --- v2.4.9/linux/drivers/sgi/char/shmiq.c Mon Mar 19 12:35:09 2001 +++ linux/drivers/sgi/char/shmiq.c Mon Aug 27 08:56:31 2001 @@ -1,5 +1,4 @@ -/* $Id: shmiq.c,v 1.19 2000/02/23 00:41:21 ralf Exp $ - * +/* * shmiq.c: shared memory input queue driver * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * @@ -42,7 +41,6 @@ * Until then, I just allow for 1 qcntl device. * */ - #include #include #include @@ -52,6 +50,7 @@ #include #include #include +#include #include #include @@ -470,3 +469,5 @@ S_IFCHR | S_IRUSR | S_IWUSR, &shmiq_fops, NULL); } + +EXPORT_SYMBOL(shmiq_init); diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/usema.c linux/drivers/sgi/char/usema.c --- v2.4.9/linux/drivers/sgi/char/usema.c Wed Jul 12 21:58:43 2000 +++ linux/drivers/sgi/char/usema.c Mon Aug 27 08:56:31 2001 @@ -20,8 +20,7 @@ * usema(7m), usinit(3p), usnewsema(3p) * /usr/include/sys/usioctl.h * -*/ - + */ #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include #include #include "usema.h" @@ -180,3 +180,5 @@ SGI_USEMACLONE); misc_register(&dev_usemaclone); } + +EXPORT_SYMBOL(usema_init); diff -u --recursive --new-file v2.4.9/linux/drivers/sound/Config.in linux/drivers/sound/Config.in --- v2.4.9/linux/drivers/sound/Config.in Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/Config.in Fri Sep 7 09:28:37 2001 @@ -45,6 +45,9 @@ if [ "$CONFIG_VISWS" = "y" ]; then dep_tristate ' SGI Visual Workstation Sound' CONFIG_SOUND_VWSND $CONFIG_SOUND fi +if [ "$CONFIG_DDB5477" = "y" ]; then + dep_tristate ' NEC Vrc5477 AC97 sound' CONFIG_SOUND_VRC5477 $CONFIG_SOUND +fi dep_tristate ' Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core' CONFIG_SOUND_TRIDENT $CONFIG_SOUND dep_tristate ' Support for Turtle Beach MultiSound Classic, Tahiti, Monterey' CONFIG_SOUND_MSNDCLAS $CONFIG_SOUND diff -u --recursive --new-file v2.4.9/linux/drivers/sound/ac97.h linux/drivers/sound/ac97.h --- v2.4.9/linux/drivers/sound/ac97.h Mon Dec 11 13:02:32 2000 +++ linux/drivers/sound/ac97.h Fri Sep 7 09:28:37 2001 @@ -39,7 +39,7 @@ #define AC97_PCM_FRONT_DAC_RATE 0x002C /* PCM Front DAC Rate */ #define AC97_PCM_SURR_DAC_RATE 0x002E /* PCM Surround DAC Rate */ #define AC97_PCM_LFE_DAC_RATE 0x0030 /* PCM LFE DAC Rate */ -#define AC97_PCM_LR_DAC_RATE 0x0032 /* PCM LR DAC Rate */ +#define AC97_PCM_LR_ADC_RATE 0x0032 /* PCM LR DAC Rate */ #define AC97_PCM_MIC_ADC_RATE 0x0034 /* PCM MIC ADC Rate */ #define AC97_CENTER_LFE_MASTER 0x0036 /* Center + LFE Master Volume */ #define AC97_SURROUND_MASTER 0x0038 /* Surround (Rear) Master Volume */ diff -u --recursive --new-file v2.4.9/linux/drivers/sound/ac97_codec.c linux/drivers/sound/ac97_codec.c --- v2.4.9/linux/drivers/sound/ac97_codec.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/ac97_codec.c Fri Sep 7 09:28:37 2001 @@ -104,6 +104,7 @@ {0x41445303, "Analog Devices AD1819", &null_ops}, {0x41445340, "Analog Devices AD1881", &null_ops}, {0x41445348, "Analog Devices AD1881A", &null_ops}, + {0x41445360, "Analog Devices AD1885", &default_ops}, {0x41445460, "Analog Devices AD1885", &default_ops}, {0x414B4D00, "Asahi Kasei AK4540", &null_ops}, {0x414B4D01, "Asahi Kasei AK4542", &null_ops}, @@ -937,3 +938,85 @@ EXPORT_SYMBOL(ac97_read_proc); EXPORT_SYMBOL(ac97_probe_codec); + +/* + * AC97 library support routines + */ + +/** + * ac97_set_dac_rate - set codec rate adaption + * @codec: ac97 code + * @rate: rate in hertz + * + * Set the DAC rate. Assumes the codec supports VRA. The caller is + * expected to have checked this little detail. + */ + +unsigned int ac97_set_dac_rate(struct ac97_codec *codec, unsigned int rate) +{ + unsigned int new_rate = rate; + u32 dacp; + u32 mast_vol, phone_vol, mono_vol, pcm_vol; + u32 mute_vol = 0x8000; /* The mute volume? */ + + if(rate != codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE)) + { + /* Mute several registers */ + mast_vol = codec->codec_read(codec, AC97_MASTER_VOL_STEREO); + mono_vol = codec->codec_read(codec, AC97_MASTER_VOL_MONO); + phone_vol = codec->codec_read(codec, AC97_HEADPHONE_VOL); + pcm_vol = codec->codec_read(codec, AC97_PCMOUT_VOL); + codec->codec_write(codec, AC97_MASTER_VOL_STEREO, mute_vol); + codec->codec_write(codec, AC97_MASTER_VOL_MONO, mute_vol); + codec->codec_write(codec, AC97_HEADPHONE_VOL, mute_vol); + codec->codec_write(codec, AC97_PCMOUT_VOL, mute_vol); + + /* Power down the DAC */ + dacp=codec->codec_read(codec, AC97_POWER_CONTROL); + codec->codec_write(codec, AC97_POWER_CONTROL, dacp|0x0200); + /* Load the rate and read the effective rate */ + codec->codec_write(codec, AC97_PCM_FRONT_DAC_RATE, rate); + new_rate=codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE); + /* Power it back up */ + codec->codec_write(codec, AC97_POWER_CONTROL, dacp); + + /* Restore volumes */ + codec->codec_write(codec, AC97_MASTER_VOL_STEREO, mast_vol); + codec->codec_write(codec, AC97_MASTER_VOL_MONO, mono_vol); + codec->codec_write(codec, AC97_HEADPHONE_VOL, phone_vol); + codec->codec_write(codec, AC97_PCMOUT_VOL, pcm_vol); + } + return new_rate; +} + +EXPORT_SYMBOL(ac97_set_dac_rate); + +/** + * ac97_set_adc_rate - set codec rate adaption + * @codec: ac97 code + * @rate: rate in hertz + * + * Set the ADC rate. Assumes the codec supports VRA. The caller is + * expected to have checked this little detail. + */ + +unsigned int ac97_set_adc_rate(struct ac97_codec *codec, unsigned int rate) +{ + unsigned int new_rate = rate; + u32 dacp; + + if(rate != codec->codec_read(codec, AC97_PCM_LR_ADC_RATE)) + { + /* Power down the ADC */ + dacp=codec->codec_read(codec, AC97_POWER_CONTROL); + codec->codec_write(codec, AC97_POWER_CONTROL, dacp|0x0100); + /* Load the rate and read the effective rate */ + codec->codec_write(codec, AC97_PCM_LR_ADC_RATE, rate); + new_rate=codec->codec_read(codec, AC97_PCM_LR_ADC_RATE); + /* Power it back up */ + codec->codec_write(codec, AC97_POWER_CONTROL, dacp); + } + return new_rate; +} + +EXPORT_SYMBOL(ac97_set_adc_rate); diff -u --recursive --new-file v2.4.9/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c --- v2.4.9/linux/drivers/sound/ad1848.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/sound/ad1848.c Fri Sep 7 09:28:37 2001 @@ -29,6 +29,7 @@ * Christoph Hellwig : adapted to module_init/module_exit * Aki Laukkanen : added power management support * Arnaldo C. de Melo : added missing restore_flags in ad1848_resume + * Miguel Freitas : added ISA PnP support * * Status: * Tested. Believed fully functional. @@ -39,6 +40,7 @@ #include #include #include +#include #define DEB(x) #define DEB1(x) @@ -160,6 +162,18 @@ ,{CAP_F_TIMER} /* MD_1845_SSCAPE */ }; +#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE +static int isapnp = 1; +static int isapnpjump = 0; +static int reverse = 0; + +static int audio_activated = 0; +#else +static int isapnp = 0; +#endif + + + static int ad1848_open(int dev, int mode); static void ad1848_close(int dev); static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag); @@ -2812,34 +2826,207 @@ MODULE_PARM(dma, "i"); /* First DMA channel */ MODULE_PARM(dma2, "i"); /* Second DMA channel */ MODULE_PARM(type, "i"); /* Card type */ -MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen -*/ +MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen */ MODULE_PARM(deskpro_m, "i"); /* Special magic for Deskpro M box */ -MODULE_PARM(soundpro, "i"); /* More special magic for SoundPro -chips */ +MODULE_PARM(soundpro, "i"); /* More special magic for SoundPro chips */ + +#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE +MODULE_PARM(isapnp, "i"); +MODULE_PARM(isapnpjump, "i"); +MODULE_PARM(reverse, "i"); +MODULE_PARM_DESC(isapnp, "When set to 0, Plug & Play support will be disabled"); +MODULE_PARM_DESC(isapnpjump, "Jumps to a specific slot in the driver's PnP table. Use the source, Luke."); +MODULE_PARM_DESC(reverse, "When set to 1, will reverse ISAPnP search order"); + +struct pci_dev *ad1848_dev = NULL; + +/* Please add new entries at the end of the table */ +static struct { + char *name; + unsigned short card_vendor, card_device, + vendor, function; + short mss_io, irq, dma, dma2; /* index into isapnp table */ + int type; +} ad1848_isapnp_list[] __initdata = { + {"CMI 8330 SoundPRO", + ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), + ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), + 0, 0, 0,-1, 0}, + {"CS4232 based card", + ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000), + 0, 0, 0, 1, 0}, + {"CS4232 based card", + ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), + 0, 0, 0, 1, 0}, + {"OPL3-SA2 WSS mode", + ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), + 1, 0, 0, 1, 1}, + {0} +}; + +static struct isapnp_device_id id_table[] __devinitdata = { + { ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), + ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000), 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), 0 }, + {0} +}; + +MODULE_DEVICE_TABLE(isapnp, id_table); + +static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev) +{ + int err; + + /* Device already active? Let's use it */ + if(dev->active) + return(dev); + + if((err = dev->activate(dev)) < 0) { + printk(KERN_ERR "ad1848: %s %s config failed (out of resources?)[%d]\n", devname, resname, err); + + dev->deactivate(dev); + + return(NULL); + } + return(dev); +} + +static struct pci_dev *ad1848_init_generic(struct pci_bus *bus, struct address_info *hw_config, int slot) +{ + + /* Configure Audio device */ + if((ad1848_dev = isapnp_find_dev(bus, ad1848_isapnp_list[slot].vendor, ad1848_isapnp_list[slot].function, NULL))) + { + int ret; + ret = ad1848_dev->prepare(ad1848_dev); + /* If device is active, assume configured with /proc/isapnp + * and use anyway. Some other way to check this? */ + if(ret && ret != -EBUSY) { + printk(KERN_ERR "ad1848: ISAPnP found device that could not be autoconfigured.\n"); + return(NULL); + } + if(ret == -EBUSY) + audio_activated = 1; + + if((ad1848_dev = activate_dev(ad1848_isapnp_list[slot].name, "ad1848", ad1848_dev))) + { + hw_config->io_base = ad1848_dev->resource[ad1848_isapnp_list[slot].mss_io].start; + hw_config->irq = ad1848_dev->irq_resource[ad1848_isapnp_list[slot].irq].start; + hw_config->dma = ad1848_dev->dma_resource[ad1848_isapnp_list[slot].dma].start; + if(ad1848_isapnp_list[slot].dma2 != -1) + hw_config->dma2 = ad1848_dev->dma_resource[ad1848_isapnp_list[slot].dma2].start; + else + hw_config->dma2 = -1; + hw_config->card_subtype = ad1848_isapnp_list[slot].type; + } else + return(NULL); + } else + return(NULL); + + return(ad1848_dev); +} + +static int __init ad1848_isapnp_init(struct address_info *hw_config, struct pci_bus *bus, int slot) +{ + char *busname = bus->name[0] ? bus->name : ad1848_isapnp_list[slot].name; + + printk(KERN_INFO "ad1848: %s detected\n", busname); + + /* Initialize this baby. */ + + if(ad1848_init_generic(bus, hw_config, slot)) { + /* We got it. */ + + printk(KERN_NOTICE "ad1848: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n", + busname, + hw_config->io_base, hw_config->irq, hw_config->dma, + hw_config->dma2); + return 1; + } + else + printk(KERN_INFO "ad1848: Failed to initialize %s\n", busname); + + return 0; +} + +static int __init ad1848_isapnp_probe(struct address_info *hw_config) +{ + static int first = 1; + int i; + + /* Count entries in sb_isapnp_list */ + for (i = 0; ad1848_isapnp_list[i].card_vendor != 0; i++); + i--; + + /* Check and adjust isapnpjump */ + if( isapnpjump < 0 || isapnpjump > i) { + isapnpjump = reverse ? i : 0; + printk(KERN_ERR "ad1848: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump); + } + + if(!first || !reverse) + i = isapnpjump; + first = 0; + while(ad1848_isapnp_list[i].card_vendor != 0) { + static struct pci_bus *bus = NULL; + + while ((bus = isapnp_find_card( + ad1848_isapnp_list[i].card_vendor, + ad1848_isapnp_list[i].card_device, + bus))) { + + if(ad1848_isapnp_init(hw_config, bus, i)) { + isapnpjump = i; /* start next search from here */ + return 0; + } + } + i += reverse ? -1 : 1; + } + + return -ENODEV; +} +#endif + static int __init init_ad1848(void) { printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n"); +#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE + if(isapnp && (ad1848_isapnp_probe(&cfg) < 0) ) { + printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n"); + isapnp = 0; + } +#endif + if(io != -1) { - if(irq == -1 || dma == -1) { - printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n"); - return -EINVAL; - } + if( isapnp == 0 ) + { + if(irq == -1 || dma == -1) { + printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n"); + return -EINVAL; + } - cfg.irq = irq; - cfg.io_base = io; - cfg.dma = dma; - cfg.dma2 = dma2; - cfg.card_subtype = type; + cfg.irq = irq; + cfg.io_base = io; + cfg.dma = dma; + cfg.dma2 = dma2; + cfg.card_subtype = type; + } if(!probe_ms_sound(&cfg)) return -ENODEV; attach_ms_sound(&cfg, THIS_MODULE); loaded = 1; } - return 0; } @@ -2847,6 +3034,12 @@ { if(loaded) unload_ms_sound(&cfg); + +#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE + if(audio_activated) + if(ad1848_dev) + ad1848_dev->deactivate(ad1848_dev); +#endif } module_init(init_ad1848); diff -u --recursive --new-file v2.4.9/linux/drivers/sound/awe_wave.c linux/drivers/sound/awe_wave.c --- v2.4.9/linux/drivers/sound/awe_wave.c Fri Mar 2 11:12:11 2001 +++ linux/drivers/sound/awe_wave.c Mon Aug 27 08:11:43 2001 @@ -4873,7 +4873,7 @@ /* any three numbers you like */ #define UNIQUE_ID1 0x1234 #define UNIQUE_ID2 0x4321 -#define UNIQUE_ID3 0xFFFF +#define UNIQUE_ID3 0xABCD static void __init awe_check_dram(void) diff -u --recursive --new-file v2.4.9/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- v2.4.9/linux/drivers/sound/cmpci.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/cmpci.c Fri Sep 7 09:28:37 2001 @@ -75,13 +75,14 @@ * was calling prog_dmabuf with s->lock held, call missing * unlock_kernel in cm_midi_release * - * Fri May 25 2001 - Carlos Eduardo Gorges - * - some driver cleanups - * - spin[un]lock* revision ( fix SMP support ) - * - cosmetic code changes + * Carlos Eduardo Gorges + * Fri May 25 2001 + * - SMP support ( spin[un]lock* revision ) + * - speaker mixer support + * Mon Aug 13 2001 + * - optimizations and cleanups * */ - /*****************************************************************************/ #include @@ -104,119 +105,98 @@ #include #include #include +#include #include "dm.h" /* --------------------------------------------------------------------- */ - #undef OSS_DOCUMENTED_MIXER_SEMANTICS - +#undef DMABYTEIO /* --------------------------------------------------------------------- */ -#ifndef PCI_VENDOR_ID_CMEDIA -#define PCI_VENDOR_ID_CMEDIA 0x13F6 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8338A -#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8338B -#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8738 -#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B -#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112 -#endif - #define CM_MAGIC ((PCI_VENDOR_ID_CMEDIA<<16)|PCI_DEVICE_ID_CMEDIA_CM8338A) -/* - * CM8338 registers definition - */ +/* CM8338 registers definition ****************/ -#define CODEC_CMI_FUNCTRL0 (0x00) -#define CODEC_CMI_FUNCTRL1 (0x04) -#define CODEC_CMI_CHFORMAT (0x08) -#define CODEC_CMI_INT_HLDCLR (0x0C) -#define CODEC_CMI_INT_STATUS (0x10) -#define CODEC_CMI_LEGACY_CTRL (0x14) -#define CODEC_CMI_MISC_CTRL (0x18) -#define CODEC_CMI_TDMA_POS (0x1C) -#define CODEC_CMI_MIXER (0x20) -#define CODEC_SB16_DATA (0x22) -#define CODEC_SB16_ADDR (0x23) -#define CODEC_CMI_MIXER1 (0x24) -#define CODEC_CMI_MIXER2 (0x25) -#define CODEC_CMI_AUX_VOL (0x26) -#define CODEC_CMI_MISC (0x27) -#define CODEC_CMI_AC97 (0x28) - -#define CODEC_CMI_CH0_FRAME1 (0x80) -#define CODEC_CMI_CH0_FRAME2 (0x84) -#define CODEC_CMI_CH1_FRAME1 (0x88) -#define CODEC_CMI_CH1_FRAME2 (0x8C) - -#define CODEC_CMI_EXT_REG (0xF0) -#define UCHAR unsigned char -/* -** Mixer registers for SB16 -*/ - -#define DSP_MIX_DATARESETIDX ((UCHAR)(0x00)) - -#define DSP_MIX_MASTERVOLIDX_L ((UCHAR)(0x30)) -#define DSP_MIX_MASTERVOLIDX_R ((UCHAR)(0x31)) -#define DSP_MIX_VOICEVOLIDX_L ((UCHAR)(0x32)) -#define DSP_MIX_VOICEVOLIDX_R ((UCHAR)(0x33)) -#define DSP_MIX_FMVOLIDX_L ((UCHAR)(0x34)) -#define DSP_MIX_FMVOLIDX_R ((UCHAR)(0x35)) -#define DSP_MIX_CDVOLIDX_L ((UCHAR)(0x36)) -#define DSP_MIX_CDVOLIDX_R ((UCHAR)(0x37)) -#define DSP_MIX_LINEVOLIDX_L ((UCHAR)(0x38)) -#define DSP_MIX_LINEVOLIDX_R ((UCHAR)(0x39)) - -#define DSP_MIX_MICVOLIDX ((UCHAR)(0x3A)) -#define DSP_MIX_SPKRVOLIDX ((UCHAR)(0x3B)) - -#define DSP_MIX_OUTMIXIDX ((UCHAR)(0x3C)) - -#define DSP_MIX_ADCMIXIDX_L ((UCHAR)(0x3D)) -#define DSP_MIX_ADCMIXIDX_R ((UCHAR)(0x3E)) - -#define DSP_MIX_INGAINIDX_L ((UCHAR)(0x3F)) -#define DSP_MIX_INGAINIDX_R ((UCHAR)(0x40)) -#define DSP_MIX_OUTGAINIDX_L ((UCHAR)(0x41)) -#define DSP_MIX_OUTGAINIDX_R ((UCHAR)(0x42)) - -#define DSP_MIX_AGCIDX ((UCHAR)(0x43)) - -#define DSP_MIX_TREBLEIDX_L ((UCHAR)(0x44)) -#define DSP_MIX_TREBLEIDX_R ((UCHAR)(0x45)) -#define DSP_MIX_BASSIDX_L ((UCHAR)(0x46)) -#define DSP_MIX_BASSIDX_R ((UCHAR)(0x47)) -#define CM_CH0_RESET 0x04 -#define CM_CH1_RESET 0x08 -#define CM_EXTENT_CODEC 0x100 -#define CM_EXTENT_MIDI 0x2 -#define CM_EXTENT_SYNTH 0x4 -#define CM_INT_CH0 1 -#define CM_INT_CH1 2 - -#define CM_CFMT_STEREO 0x01 -#define CM_CFMT_16BIT 0x02 -#define CM_CFMT_MASK 0x03 -#define CM_CFMT_DACSHIFT 2 -#define CM_CFMT_ADCSHIFT 0 +#define CODEC_CMI_FUNCTRL0 (0x00) +#define CODEC_CMI_FUNCTRL1 (0x04) +#define CODEC_CMI_CHFORMAT (0x08) +#define CODEC_CMI_INT_HLDCLR (0x0C) +#define CODEC_CMI_INT_STATUS (0x10) +#define CODEC_CMI_LEGACY_CTRL (0x14) +#define CODEC_CMI_MISC_CTRL (0x18) +#define CODEC_CMI_TDMA_POS (0x1C) +#define CODEC_CMI_MIXER (0x20) +#define CODEC_SB16_DATA (0x22) +#define CODEC_SB16_ADDR (0x23) +#define CODEC_CMI_MIXER1 (0x24) +#define CODEC_CMI_MIXER2 (0x25) +#define CODEC_CMI_AUX_VOL (0x26) +#define CODEC_CMI_MISC (0x27) +#define CODEC_CMI_AC97 (0x28) + +#define CODEC_CMI_CH0_FRAME1 (0x80) +#define CODEC_CMI_CH0_FRAME2 (0x84) +#define CODEC_CMI_CH1_FRAME1 (0x88) +#define CODEC_CMI_CH1_FRAME2 (0x8C) + +#define CODEC_CMI_EXT_REG (0xF0) + +/* Mixer registers for SB16 ******************/ + +#define DSP_MIX_DATARESETIDX ((unsigned char)(0x00)) + +#define DSP_MIX_MASTERVOLIDX_L ((unsigned char)(0x30)) +#define DSP_MIX_MASTERVOLIDX_R ((unsigned char)(0x31)) +#define DSP_MIX_VOICEVOLIDX_L ((unsigned char)(0x32)) +#define DSP_MIX_VOICEVOLIDX_R ((unsigned char)(0x33)) +#define DSP_MIX_FMVOLIDX_L ((unsigned char)(0x34)) +#define DSP_MIX_FMVOLIDX_R ((unsigned char)(0x35)) +#define DSP_MIX_CDVOLIDX_L ((unsigned char)(0x36)) +#define DSP_MIX_CDVOLIDX_R ((unsigned char)(0x37)) +#define DSP_MIX_LINEVOLIDX_L ((unsigned char)(0x38)) +#define DSP_MIX_LINEVOLIDX_R ((unsigned char)(0x39)) + +#define DSP_MIX_MICVOLIDX ((unsigned char)(0x3A)) +#define DSP_MIX_SPKRVOLIDX ((unsigned char)(0x3B)) + +#define DSP_MIX_OUTMIXIDX ((unsigned char)(0x3C)) + +#define DSP_MIX_ADCMIXIDX_L ((unsigned char)(0x3D)) +#define DSP_MIX_ADCMIXIDX_R ((unsigned char)(0x3E)) + +#define DSP_MIX_INGAINIDX_L ((unsigned char)(0x3F)) +#define DSP_MIX_INGAINIDX_R ((unsigned char)(0x40)) +#define DSP_MIX_OUTGAINIDX_L ((unsigned char)(0x41)) +#define DSP_MIX_OUTGAINIDX_R ((unsigned char)(0x42)) + +#define DSP_MIX_AGCIDX ((unsigned char)(0x43)) + +#define DSP_MIX_TREBLEIDX_L ((unsigned char)(0x44)) +#define DSP_MIX_TREBLEIDX_R ((unsigned char)(0x45)) +#define DSP_MIX_BASSIDX_L ((unsigned char)(0x46)) +#define DSP_MIX_BASSIDX_R ((unsigned char)(0x47)) + +#define CM_CH0_RESET 0x04 +#define CM_CH1_RESET 0x08 +#define CM_EXTENT_CODEC 0x100 +#define CM_EXTENT_MIDI 0x2 +#define CM_EXTENT_SYNTH 0x4 +#define CM_INT_CH0 1 +#define CM_INT_CH1 2 + +#define CM_CFMT_STEREO 0x01 +#define CM_CFMT_16BIT 0x02 +#define CM_CFMT_MASK 0x03 +#define CM_CFMT_DACSHIFT 2 +#define CM_CFMT_ADCSHIFT 0 -static const unsigned sample_size[] = { 1, 2, 2, 4 }; -static const unsigned sample_shift[] = { 0, 1, 1, 2 }; +static const unsigned sample_shift[] = { 0, 1, 1, 2 }; #define CM_ENABLE_CH1 0x2 #define CM_ENABLE_CH0 0x1 - -/* MIDI buffer sizes */ +/* MIDI buffer sizes **************************/ #define MIDIINBUF 256 #define MIDIOUTBUF 256 @@ -229,35 +209,29 @@ #define SND_DEV_DSP16 5 -/* --------------------------------------------------------------------- */ +#define NR_DEVICE 3 /* maximum number of devices */ -struct cm_state { - /* magic */ - unsigned int magic; +/*********************************************/ - /* we keep cm cards in a linked list */ - struct cm_state *next; +struct cm_state { + unsigned int magic; /* magic */ + struct cm_state *next; /* we keep cm cards in a linked list */ - /* soundcore stuff */ - int dev_audio; + int dev_audio; /* soundcore stuff */ int dev_mixer; int dev_midi; int dev_dmfm; - /* hardware resources */ - unsigned int iosb, iobase, iosynth, iomidi, iogame, irq; - unsigned short deviceid; + unsigned int iosb, iobase, iosynth, + iomidi, iogame, irq; /* hardware resources */ + unsigned short deviceid; /* pci_id */ - /* mixer stuff */ - struct { + struct { /* mixer stuff */ unsigned int modcnt; -#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS unsigned short vol[13]; -#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ } mix; - /* wave stuff */ - unsigned int rateadc, ratedac; + unsigned int rateadc, ratedac; /* wave stuff */ unsigned char fmt, enable; spinlock_t lock; @@ -274,15 +248,15 @@ unsigned hwptr, swptr; unsigned total_bytes; int count; - unsigned error; /* over/underrun */ + unsigned error; /* over/underrun */ wait_queue_head_t wait; - /* redundant, but makes calculations easier */ - unsigned fragsize; + + unsigned fragsize; /* redundant, but makes calculations easier */ unsigned dmasize; unsigned fragsamples; unsigned dmasamples; - /* OSS stuff */ - unsigned mapped:1; + + unsigned mapped:1; /* OSS stuff */ unsigned ready:1; unsigned endcleared:1; unsigned ossfragshift; @@ -290,8 +264,7 @@ unsigned subdivision; } dma_dac, dma_adc; - /* midi stuff */ - struct { + struct { /* midi stuff */ unsigned ird, iwr, icnt; unsigned ord, owr, ocnt; wait_queue_head_t iwait; @@ -301,44 +274,41 @@ unsigned char obuf[MIDIOUTBUF]; } midi; - /* misc stuff */ - int chip_version; + int chip_version; int max_channels; - int curr_channels; - int speakers; // number of speakers - int capability; // HW capability, various for chip versions - int status; // HW or SW state + int curr_channels; + int speakers; /* number of speakers */ + int capability; /* HW capability, various for chip versions */ + + int status; /* HW or SW state */ - /* spdif frame counter */ - int spdif_counter; + int spdif_counter; /* spdif frame counter */ }; /* flags used for capability */ -#define CAN_AC3_HW 0x00000001 // 037 or later -#define CAN_AC3_SW 0x00000002 // 033 or later -#define CAN_AC3 (CAN_AC3_HW | CAN_AC3_SW) -#define CAN_DUAL_DAC 0x00000004 // 033 or later -#define CAN_MULTI_CH_HW 0x00000008 // 039 or later -#define CAN_MULTI_CH (CAN_MULTI_CH_HW | CAN_DUAL_DAC) -#define CAN_LINE_AS_REAR 0x00000010 // 033 or later -#define CAN_LINE_AS_BASS 0x00000020 // 039 or later -#define CAN_MIC_AS_BASS 0x00000040 // 039 or later +#define CAN_AC3_HW 0x00000001 /* 037 or later */ +#define CAN_AC3_SW 0x00000002 /* 033 or later */ +#define CAN_AC3 (CAN_AC3_HW | CAN_AC3_SW) +#define CAN_DUAL_DAC 0x00000004 /* 033 or later */ +#define CAN_MULTI_CH_HW 0x00000008 /* 039 or later */ +#define CAN_MULTI_CH (CAN_MULTI_CH_HW | CAN_DUAL_DAC) +#define CAN_LINE_AS_REAR 0x00000010 /* 033 or later */ +#define CAN_LINE_AS_BASS 0x00000020 /* 039 or later */ +#define CAN_MIC_AS_BASS 0x00000040 /* 039 or later */ /* flags used for status */ -#define DO_AC3_HW 0x00000001 -#define DO_AC3_SW 0x00000002 -#define DO_AC3 (DO_AC3_HW | DO_AC3_SW) -#define DO_DUAL_DAC 0x00000004 -#define DO_MULTI_CH_HW 0x00000008 -#define DO_MULTI_CH (DO_MULTI_CH_HW | DO_DUAL_DAC) -#define DO_LINE_AS_REAR 0x00000010 // 033 or later -#define DO_LINE_AS_BASS 0x00000020 // 039 or later -#define DO_MIC_AS_BASS 0x00000040 // 039 or later -#define DO_SPDIF_OUT 0x00000100 -#define DO_SPDIF_IN 0x00000200 -#define DO_SPDIF_LOOP 0x00000400 - -/* --------------------------------------------------------------------- */ +#define DO_AC3_HW 0x00000001 +#define DO_AC3_SW 0x00000002 +#define DO_AC3 (DO_AC3_HW | DO_AC3_SW) +#define DO_DUAL_DAC 0x00000004 +#define DO_MULTI_CH_HW 0x00000008 +#define DO_MULTI_CH (DO_MULTI_CH_HW | DO_DUAL_DAC) +#define DO_LINE_AS_REAR 0x00000010 /* 033 or later */ +#define DO_LINE_AS_BASS 0x00000020 /* 039 or later */ +#define DO_MIC_AS_BASS 0x00000040 /* 039 or later */ +#define DO_SPDIF_OUT 0x00000100 +#define DO_SPDIF_IN 0x00000200 +#define DO_SPDIF_LOOP 0x00000400 static struct cm_state *devs; static unsigned long wavetable_mem; @@ -347,55 +317,25 @@ static inline unsigned ld2(unsigned int x) { - unsigned r = 0; + unsigned exp=16,l=5,r=0; + static const unsigned num[]={0x2,0x4,0x10,0x100,0x10000}; + + /* num: 2, 4, 16, 256, 65536 */ + /* exp: 1, 2, 4, 8, 16 */ - if (x >= 0x10000) { - x >>= 16; - r += 16; - } - if (x >= 0x100) { - x >>= 8; - r += 8; - } - if (x >= 0x10) { - x >>= 4; - r += 4; - } - if (x >= 4) { - x >>= 2; - r += 2; + while(l--) { + if( x >= num[l] ) { + if(num[l]>2) x >>= exp; + r+=exp; + } + exp>>=1; } - if (x >= 2) - r++; - return r; -} - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ -#ifdef hweight32 -#undef hweight32 -#endif - -static inline unsigned int hweight32(unsigned int w) -{ - unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); - res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); - return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); + return r; } /* --------------------------------------------------------------------- */ -/* - * Why use byte IO? Nobody knows, but S3 does it also in their Windows driver. - */ - -#undef DMABYTEIO - static void maskb(unsigned int addr, unsigned int mask, unsigned int value) { outb((inb(addr) & mask) | value, addr); @@ -451,15 +391,10 @@ { unsigned int curr_addr; -#if 1 curr_addr = inw(s->iobase + CODEC_CMI_CH1_FRAME2) + 1; curr_addr <<= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]; curr_addr = s->dma_dac.dmasize - curr_addr; -#else - curr_addr = inl(s->iobase + CODEC_CMI_CH1_FRAME1); - curr_addr &= ~(sample_size[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]-1); - curr_addr -= s->dma_dac.rawphys; -#endif + return curr_addr; } @@ -467,39 +402,45 @@ { unsigned int curr_addr; -#if 1 curr_addr = inw(s->iobase + CODEC_CMI_CH0_FRAME2) + 1; curr_addr <<= sample_shift[(s->fmt >> CM_CFMT_ADCSHIFT) & CM_CFMT_MASK]; curr_addr = s->dma_adc.dmasize - curr_addr; -#else - curr_addr = inl(s->iobase + CODEC_CMI_CH0_FRAME1); - curr_addr &= ~(sample_size[(s->fmt >> CM_CFMT_ADCSHIFT) & CM_CFMT_MASK]-1); - curr_addr -= s->dma_adc.rawphys; -#endif + return curr_addr; } static void wrmixer(struct cm_state *s, unsigned char idx, unsigned char data) { outb(idx, s->iobase + CODEC_SB16_ADDR); + udelay(10); outb(data, s->iobase + CODEC_SB16_DATA); + udelay(10); } static unsigned char rdmixer(struct cm_state *s, unsigned char idx) { unsigned char v; - + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); outb(idx, s->iobase + CODEC_SB16_ADDR); + udelay(10); v = inb(s->iobase + CODEC_SB16_DATA); + udelay(10); + spin_unlock_irqrestore(&s->lock, flags); return v; } static void set_fmt_unlocked(struct cm_state *s, unsigned char mask, unsigned char data) { if (mask) + { s->fmt = inb(s->iobase + CODEC_CMI_CHFORMAT); + udelay(10); + } s->fmt = (s->fmt & mask) | data; outb(s->fmt, s->iobase + CODEC_CMI_CHFORMAT); + udelay(10); } static void set_fmt(struct cm_state *s, unsigned char mask, unsigned char data) @@ -514,7 +455,9 @@ static void frobindir(struct cm_state *s, unsigned char idx, unsigned char mask, unsigned char data) { outb(idx, s->iobase + CODEC_SB16_ADDR); + udelay(10); outb((inb(s->iobase + CODEC_SB16_DATA) & mask) | data, s->iobase + CODEC_SB16_DATA); + udelay(10); } static struct { @@ -746,6 +689,7 @@ { /* reset bus master */ outb(s->enable | CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + udelay(10); outb(s->enable & ~CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); } @@ -887,15 +831,6 @@ } } -//static void start_dac1(struct cm_state *s) -//{ -// unsigned long flags; -// -// spin_lock_irqsave(&s->lock, flags); -// start_dac1_unlocked(s); -// spin_unlock_irqrestore(&s->lock, flags); -//} - static void start_dac_unlocked(struct cm_state *s) { if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) { @@ -964,7 +899,7 @@ set_adc_rate_unlocked(s, s->ratedac); } - // N4SPK3D, disable 4 speaker mode (analog duplicate) + if (s->speakers > 2) maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~0x04, 0); s->curr_channels = channels; @@ -1041,10 +976,10 @@ db->buforder = order; db->rawphys = virt_to_bus(db->rawbuf); if ((db->rawphys ^ (db->rawphys + (PAGE_SIZE << db->buforder) - 1)) & ~0xffff) - printk(KERN_DEBUG "cm: DMA buffer crosses 64k boundary: busaddr 0x%lx size %ld\n", + printk(KERN_DEBUG "cmpci: DMA buffer crosses 64k boundary: busaddr 0x%lx size %ld\n", (long) db->rawphys, PAGE_SIZE << db->buforder); if ((db->rawphys + (PAGE_SIZE << db->buforder) - 1) & ~0xffffff) - printk(KERN_DEBUG "cm: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n", + printk(KERN_DEBUG "cmpci: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n", (long) db->rawphys, PAGE_SIZE << db->buforder); /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); @@ -1260,7 +1195,7 @@ /* --------------------------------------------------------------------- */ -static const char invalid_magic[] = KERN_CRIT "cm: invalid magic value\n"; +static const char invalid_magic[] = KERN_CRIT "cmpci: invalid magic value\n"; #ifdef CONFIG_SOUND_CMPCI /* support multiple chips */ #define VALIDATE_STATE(s) @@ -1298,59 +1233,6 @@ [SOUND_MIXER_SPEAKER]= { DSP_MIX_SPKRVOLIDX, DSP_MIX_SPKRVOLIDX, MT_5MUTEMONO, 0x01, 0x01 } }; -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - -static int return_mixval(struct cm_state *s, unsigned i, int *arg) -{ - unsigned long flags; - unsigned char l, r, rl, rr; - - spin_lock_irqsave(&s->lock, flags); - l = rdmixer(s, mixtable[i].left); - r = rdmixer(s, mixtable[i].right); - spin_unlock_irqrestore(&s->lock, flags); - switch (mixtable[i].type) { - case MT_4: - r &= 0xf; - l &= 0xf; - rl = 10 + 6 * (l & 15); - rr = 10 + 6 * (r & 15); - break; - - case MT_4MUTEMONO: - rl = 55 - 3 * (l & 15); - if (r & 0x10) - rl += 45; - rr = rl; - r = l; - break; - - case MT_5MUTEMONO: - r = l; - rl = 100 - 3 * ((l >> 3) & 31); - rr = rl; - break; - - case MT_5MUTE: - default: - rl = 100 - 3 * ((l >> 3) & 31); - rr = 100 - 3 * ((r >> 3) & 31); - break; - - case MT_6MUTE: - rl = 100 - 3 * (l & 63) / 2; - rr = 100 - 3 * (r & 63) / 2; - break; - } - if (l & 0x80) - rl = 0; - if (r & 0x80) - rr = 0; - return put_user((rr << 8) | rl, arg); -} - -#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */ - static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = { [SOUND_MIXER_CD] = 1, @@ -1362,16 +1244,11 @@ [SOUND_MIXER_SPEAKER]= 7 }; -#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ - static unsigned mixer_recmask(struct cm_state *s) { - unsigned long flags; int i, j, k; - spin_lock_irqsave(&s->lock, flags); j = rdmixer(s, DSP_MIX_ADCMIXIDX_L); - spin_unlock_irqrestore(&s->lock, flags); j &= 0x7f; for (k = i = 0; i < SOUND_MIXER_NRDEVICES; i++) if (j & mixtable[i].rec) @@ -1446,13 +1323,9 @@ i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type) return -EINVAL; -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - return return_mixval(s, i, (int *)arg); -#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */ if (!volidx[i]) return -EINVAL; return put_user(s->mix.vol[volidx[i]-1], (int *)arg); -#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ } } if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) @@ -1462,7 +1335,7 @@ case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ if (get_user(val, (int *)arg)) return -EFAULT; - i = hweight32(val); + i = generic_hweight32(val); for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) { if (!(val & (1 << i))) continue; @@ -1554,14 +1427,11 @@ break; } spin_unlock_irqrestore(&s->lock, flags); -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - return return_mixval(s, i, (int *)arg); -#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */ + if (!volidx[i]) return -EINVAL; s->mix.vol[volidx[i]-1] = val; return put_user(s->mix.vol[volidx[i]-1], (int *)arg); -#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ } } @@ -1631,7 +1501,7 @@ tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac; tmo >>= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]; if (!schedule_timeout(tmo + 1)) - printk(KERN_DEBUG "cm: dma timed out??\n"); + printk(KERN_DEBUG "cmpci: dma timed out??\n"); } remove_wait_queue(&s->dma_dac.wait, &wait); current->state = TASK_RUNNING; @@ -1660,11 +1530,7 @@ if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; ret = 0; -#if 0 - spin_lock_irqsave(&s->lock, flags); - cm_update_ptr(s); - spin_unlock_irqrestore(&s->lock, flags); -#endif + while (count > 0) { spin_lock_irqsave(&s->lock, flags); swptr = s->dma_adc.swptr; @@ -1679,7 +1545,7 @@ if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) { - printk(KERN_DEBUG "cm: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + printk(KERN_DEBUG "cmpci: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, s->dma_adc.hwptr, s->dma_adc.swptr); spin_lock_irqsave(&s->lock, flags); @@ -1735,11 +1601,7 @@ return -EFAULT; } ret = 0; -#if 0 - spin_lock_irqsave(&s->lock, flags); - cm_update_ptr(s); - spin_unlock_irqrestore(&s->lock, flags); -#endif + while (count > 0) { spin_lock_irqsave(&s->lock, flags); if (s->dma_dac.count < 0) { @@ -1770,7 +1632,7 @@ if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) { - printk(KERN_DEBUG "cm: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + printk(KERN_DEBUG "cmpci: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, s->dma_dac.hwptr, s->dma_dac.swptr); spin_lock_irqsave(&s->lock, flags); @@ -2387,11 +2249,11 @@ down(&s->open_sem); if (file->f_mode & FMODE_WRITE) { stop_dac(s); -#ifndef FIXEDDMA + dealloc_dmabuf(&s->dma_dac); if (s->status & DO_DUAL_DAC) dealloc_dmabuf(&s->dma_adc); -#endif + if (s->status & DO_MULTI_CH) set_dac_channels(s, 0); if (s->status & DO_AC3) @@ -2401,9 +2263,7 @@ } if (file->f_mode & FMODE_READ) { stop_adc(s); -#ifndef FIXEDDMA dealloc_dmabuf(&s->dma_adc); -#endif } s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); up(&s->open_sem); @@ -2668,7 +2528,7 @@ } tmo = (count * HZ) / 3100; if (!schedule_timeout(tmo ? : 1) && tmo) - printk(KERN_DEBUG "cm: midi timed out??\n"); + printk(KERN_DEBUG "cmpci: midi timed out??\n"); } remove_wait_queue(&s->midi.owait, &wait); set_current_state(TASK_RUNNING); @@ -2867,18 +2727,7 @@ }; #endif /* CONFIG_SOUND_CMPCI_FM */ -/* --------------------------------------------------------------------- */ -/* maximum number of devices */ -#define NR_DEVICE 5 - -#if 0 -static int reverb[NR_DEVICE] = { 0, }; - -static int wavetable[NR_DEVICE] = { 0, }; -#endif - -/* --------------------------------------------------------------------- */ static struct initvol { int mixch; @@ -2941,14 +2790,14 @@ } #ifdef CONFIG_SOUND_CMPCI_MIDI -static int mpu_io = CONFIG_SOUND_CMPCI_MPUIO; +static int mpuio = CONFIG_SOUND_CMPCI_MPUIO; #else -static int mpu_io; +static int mpuio; #endif #ifdef CONFIG_SOUND_CMPCI_FM -static int fm_io = CONFIG_SOUND_CMPCI_FMIO; +static int fmio = CONFIG_SOUND_CMPCI_FMIO; #else -static int fm_io; +static int fmio; #endif #ifdef CONFIG_SOUND_CMPCI_SPDIFINVERSE static int spdif_inverse = 1; @@ -2980,16 +2829,16 @@ #else static int joystick; #endif -MODULE_PARM(mpu_io, "i"); -MODULE_PARM(fm_io, "i"); +MODULE_PARM(mpuio, "i"); +MODULE_PARM(fmio, "i"); MODULE_PARM(spdif_inverse, "i"); MODULE_PARM(spdif_loop, "i"); MODULE_PARM(speakers, "i"); MODULE_PARM(use_line_as_rear, "i"); MODULE_PARM(use_line_as_bass, "i"); MODULE_PARM(joystick, "i"); -MODULE_PARM_DESC(mpu_io, "(0x330, 0x320, 0x310, 0x300) Base of MPU-401, 0 to disable"); -MODULE_PARM_DESC(fm_io, "(0x388, 0x3C8, 0x3E0) Base of OPL3, 0 to disable"); +MODULE_PARM_DESC(mpuio, "(0x330, 0x320, 0x310, 0x300) Base of MPU-401, 0 to disable"); +MODULE_PARM_DESC(fmio, "(0x388, 0x3C8, 0x3E0) Base of OPL3, 0 to disable"); MODULE_PARM_DESC(spdif_inverse, "(1/0) Invert S/PDIF-in signal"); MODULE_PARM_DESC(spdif_loop, "(1/0) Route S/PDIF-in to S/PDIF-out directly"); MODULE_PARM_DESC(speakers, "(2-6) Number of speakers you connect"); @@ -3021,7 +2870,7 @@ return; s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) { - printk(KERN_WARNING "cm: out of memory\n"); + printk(KERN_WARNING "cmpci: out of memory\n"); return; } /* search device name */ @@ -3042,8 +2891,8 @@ spin_lock_init(&s->lock); s->magic = CM_MAGIC; s->iobase = pci_resource_start(pcidev, 0); - s->iosynth = fm_io; - s->iomidi = mpu_io; + s->iosynth = fmio; + s->iomidi = mpuio; s->status = 0; /* range check */ if (speakers < 2) @@ -3056,7 +2905,7 @@ s->irq = pcidev->irq; if (!request_region(s->iobase, CM_EXTENT_CODEC, "cmpci")) { - printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1); + printk(KERN_ERR "cmpci: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1); goto err_region5; } #ifdef CONFIG_SOUND_CMPCI_MIDI @@ -3064,7 +2913,7 @@ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x04, 0); if (s->iomidi) { if (!request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi")) { - printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1); + printk(KERN_ERR "cmpci: io ports %#x-%#x in use\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1); s->iomidi = 0; } else { /* set IO based at 0x330 */ @@ -3098,7 +2947,7 @@ maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~8, 0); if (s->iosynth) { if (!request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM")) { - printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1); + printk(KERN_ERR "cmpci: io ports %#x-%#x in use\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1); s->iosynth = 0; } else { /* set IO based at 0x388 */ @@ -3140,10 +2989,10 @@ /* request irq */ if (request_irq(s->irq, cm_interrupt, SA_SHIRQ, "cmpci", s)) { - printk(KERN_ERR "cm: irq %u in use\n", s->irq); + printk(KERN_ERR "cmpci: irq %u in use\n", s->irq); goto err_irq; } - printk(KERN_INFO "cm: found %s adapter at io %#06x irq %u\n", + printk(KERN_INFO "cmpci: found %s adapter at io %#06x irq %u\n", devicename, s->iobase, s->irq); /* register devices */ if ((s->dev_audio = register_sound_dsp(&cm_audio_fops, -1)) < 0) @@ -3174,15 +3023,18 @@ /* use channel 0 for record, channel 1 for play */ maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~2, 1); s->deviceid = pcidev->device; + if (pcidev->device == PCI_DEVICE_ID_CMEDIA_CM8738) { + /* chip version and hw capability check */ s->chip_version = query_chip(s); - printk(KERN_INFO "chip version = 0%d\n", s->chip_version); + printk(KERN_INFO "cmpci: chip version = 0%d\n", s->chip_version); + /* seet SPDIF-in inverse before enable SPDIF loop */ if (spdif_inverse) { /* turn on spdif-in inverse */ maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 1); - printk(KERN_INFO "cm: Inverse SPDIF-in\n"); + printk(KERN_INFO "cmpci: Inverse SPDIF-in\n"); } else { /* turn off spdif-ininverse */ maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~1, 0); @@ -3193,7 +3045,7 @@ s->status |= DO_SPDIF_LOOP; /* turn on spdif-in to spdif-out */ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x80); - printk(KERN_INFO "cm: Enable SPDIF loop\n"); + printk(KERN_INFO "cmpci: Enable SPDIF loop\n"); } else { s->status &= ~DO_SPDIF_LOOP; /* turn off spdif-in to spdif-out */ @@ -3234,7 +3086,7 @@ err_dev2: unregister_sound_dsp(s->dev_audio); err_dev1: - printk(KERN_ERR "cm: cannot register misc device\n"); + printk(KERN_ERR "cmpci: cannot register misc device\n"); free_irq(s->irq, s); err_irq: #ifdef CONFIG_SOUND_CMPCI_FM @@ -3264,11 +3116,8 @@ if (!pci_present()) /* No PCI bus in this machine! */ #endif return -ENODEV; - printk(KERN_INFO "cm: version $Revision: 5.64 $ time " __TIME__ " " __DATE__ "\n"); -#if 0 - if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) - printk(KERN_INFO "cm: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); -#endif + printk(KERN_INFO "cmpci: version $Revision: 5.64 $ time " __TIME__ " " __DATE__ "\n"); + while (index < NR_DEVICE && ( (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, pcidev)))) { initialize_chip(pcidev); @@ -3302,10 +3151,6 @@ synchronize_irq(); outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */ free_irq(s->irq, s); -#ifdef FIXEDDMA - dealloc_dmabuf(&s->dma_dac); - dealloc_dmabuf(&s->dma_adc); -#endif /* reset mixer */ wrmixer(s, DSP_MIX_DATARESETIDX, 0); @@ -3329,7 +3174,7 @@ } if (wavetable_mem) free_pages(wavetable_mem, 20-PAGE_SHIFT); - printk(KERN_INFO "cm: unloading\n"); + printk(KERN_INFO "cmpci: unloading\n"); } module_init(init_cmpci); diff -u --recursive --new-file v2.4.9/linux/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c --- v2.4.9/linux/drivers/sound/cs46xx.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/cs46xx.c Fri Sep 7 09:28:37 2001 @@ -1887,7 +1887,7 @@ spin_unlock_irqrestore(&card->midi.lock, flags); card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE)); up(&card->midi.open_sem); - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; /* for 2.2 */ return 0; } @@ -1926,7 +1926,7 @@ card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE))); up(&card->midi.open_sem); wake_up(&card->midi.open_wait); - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; /* for 2.2 */ return 0; } @@ -3294,7 +3294,6 @@ state->open_mode |= FMODE_READ; up(&state->open_sem); - MOD_INC_USE_COUNT; } if(file->f_mode & FMODE_WRITE) { @@ -3366,10 +3365,10 @@ state->open_mode |= FMODE_WRITE; up(&state->open_sem); - MOD_INC_USE_COUNT; if((ret = prog_dmabuf(state))) return ret; } + MOD_INC_USE_COUNT; /* for 2.2 */ CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n") ); return 0; } @@ -3421,7 +3420,6 @@ kfree(state); } - MOD_DEC_USE_COUNT; } state = card->states[0]; @@ -3454,10 +3452,10 @@ kfree(state); } - MOD_DEC_USE_COUNT; } CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n") ); + MOD_DEC_USE_COUNT; /* For 2.2 */ return 0; } @@ -4088,7 +4086,7 @@ } card->amplifier_ctrl(card, 1); CS_INC_USE_COUNT(&card->mixer_use_cnt); - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; /* for 2.2 */ CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n")); return 0; @@ -4119,7 +4117,7 @@ return -ENODEV; } match: - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; /* for 2.2 */ if(!CS_DEC_AND_TEST(&card->mixer_use_cnt)) { CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, diff -u --recursive --new-file v2.4.9/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- v2.4.9/linux/drivers/sound/esssolo1.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/esssolo1.c Fri Sep 7 09:28:37 2001 @@ -2262,7 +2262,7 @@ solo1_suspend(struct pci_dev *pci_dev, u32 state) { struct solo1_state *s = (struct solo1_state*)pci_get_drvdata(pci_dev); if (!s) - return; + return 1; outb(0, s->iobase+6); /* DMA master clear */ outb(0, s->ddmabase+0xd); diff -u --recursive --new-file v2.4.9/linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c --- v2.4.9/linux/drivers/sound/i810_audio.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/i810_audio.c Fri Sep 7 09:28:37 2001 @@ -191,7 +191,7 @@ #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) -#define DRIVER_VERSION "0.03" +#define DRIVER_VERSION "0.04" /* magic numbers to protect our data structures */ #define I810_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -429,20 +429,11 @@ dmabuf->rate = (rate * 48000)/clocking; } - if(rate != i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE)) - { - /* Power down the DAC */ - dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); - i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0200); - /* Load the rate and read the effective rate */ - i810_ac97_set(codec, AC97_PCM_FRONT_DAC_RATE, rate); - new_rate=i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE); - /* Power it back up */ - i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); - if(new_rate != rate) { - dmabuf->rate = (new_rate * 48000)/clocking; - rate = new_rate; - } + new_rate = ac97_set_dac_rate(codec, rate); + + if(new_rate != rate) { + dmabuf->rate = (new_rate * 48000)/clocking; + rate = new_rate; } #ifdef DEBUG printk("i810_audio: called i810_set_dac_rate : rate = %d/%d\n", dmabuf->rate, rate); @@ -478,21 +469,12 @@ rate = 8000; dmabuf->rate = (rate * 48000)/clocking; } + + new_rate = ac97_set_adc_rate(codec, rate); - if(rate != i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE)) - { - /* Power down the ADC */ - dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); - i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0100); - /* Load the rate and read the effective rate */ - i810_ac97_set(codec, AC97_PCM_LR_DAC_RATE, rate); - new_rate=i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE); - /* Power it back up */ - i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); - if(new_rate != rate) { - dmabuf->rate = (new_rate * 48000)/clocking; - rate = new_rate; - } + if(new_rate != rate) { + dmabuf->rate = (new_rate * 48000)/clocking; + rate = new_rate; } #ifdef DEBUG printk("i810_audio: called i810_set_adc_rate : rate = %d/%d\n", dmabuf->rate, rate); @@ -985,8 +967,10 @@ dmabuf = &state->dmabuf; if(dmabuf->enable & DAC_RUNNING) c=dmabuf->write_channel; - else + else if(dmabuf->enable & ADC_RUNNING) c=dmabuf->read_channel; + else /* This can occur going from R/W to close */ + continue; port+=c->port; @@ -1450,18 +1434,14 @@ #endif if (get_user(val, (int *)arg)) return -EFAULT; - if(val==0) { - return -EINVAL; - } else { - ret = 1; - } + if (dmabuf->enable & DAC_RUNNING) { stop_dac(state); } if (dmabuf->enable & ADC_RUNNING) { stop_adc(state); } - return put_user(ret, (int *)arg); + return put_user(1, (int *)arg); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { @@ -1493,6 +1473,17 @@ #ifdef DEBUG printk("SNDCTL_DSP_CHANNELS\n"); #endif + if (get_user(val, (int *)arg)) + return -EFAULT; + + if (val > 0) { + if (dmabuf->enable & DAC_RUNNING) { + stop_dac(state); + } + if (dmabuf->enable & ADC_RUNNING) { + stop_adc(state); + } + } return put_user(2, (int *)arg); case SNDCTL_DSP_POST: /* the user has sent all data and is notifying us */ @@ -2038,6 +2029,75 @@ return num_ac97; } +static void __init i810_configure_clocking (void) +{ + struct i810_card *card; + struct i810_state *state; + struct dmabuf *dmabuf; + unsigned int i, offset, new_offset; + unsigned long flags; + + card = devs; + /* We could try to set the clocking for multiple cards, but can you even have + * more than one i810 in a machine? Besides, clocking is global, so unless + * someone actually thinks more than one i810 in a machine is possible and + * decides to rewrite that little bit, setting the rate for more than one card + * is a waste of time. + */ + if(card != NULL) { + state = card->states[0] = (struct i810_state *) + kmalloc(sizeof(struct i810_state), GFP_KERNEL); + if (state == NULL) + return; + memset(state, 0, sizeof(struct i810_state)); + dmabuf = &state->dmabuf; + + dmabuf->write_channel = card->alloc_pcm_channel(card); + state->virt = 0; + state->card = card; + state->magic = I810_STATE_MAGIC; + init_waitqueue_head(&dmabuf->wait); + init_MUTEX(&state->open_sem); + dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT; + dmabuf->trigger = PCM_ENABLE_OUTPUT; + i810_set_dac_rate(state, 48000); + if(prog_dmabuf(state, 0) != 0) { + goto config_out_nodmabuf; + } + if(dmabuf->dmasize < 16384) { + goto config_out; + } + dmabuf->count = dmabuf->dmasize; + outb(31,card->iobase+dmabuf->write_channel->port+OFF_LVI); + save_flags(flags); + cli(); + start_dac(state); + offset = i810_get_dma_addr(state, 0); + mdelay(50); + new_offset = i810_get_dma_addr(state, 0); + stop_dac(state); + outb(2,card->iobase+dmabuf->write_channel->port+OFF_CR); + restore_flags(flags); + i = new_offset - offset; +#ifdef DEBUG + printk("i810_audio: %d bytes in 50 milliseconds\n", i); +#endif + if(i == 0) + goto config_out; + i = i / 4 * 20; + if (i > 48500 || i < 47500) { + clocking = clocking * clocking / i; + printk("i810_audio: setting clocking to %d\n", clocking); + } +config_out: + dealloc_dmabuf(state); +config_out_nodmabuf: + state->card->free_pcm_channel(state->card,state->dmabuf.write_channel->num); + kfree(state); + card->states[0] = NULL; + } +} + /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */ @@ -2102,27 +2162,37 @@ kfree(card); return -ENODEV; } - /* register /dev/dsp */ - if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) { - printk(KERN_ERR "i810_audio: couldn't register DSP device!\n"); + + /* initialize AC97 codec and register /dev/mixer */ + if (i810_ac97_init(card) <= 0) { release_region(card->iobase, 64); release_region(card->ac97base, 256); free_irq(card->irq, card); kfree(card); return -ENODEV; } + pci_dev->driver_data = card; + if(clocking == 48000) { + i810_configure_clocking(); + } - /* initialize AC97 codec and register /dev/mixer */ - if (i810_ac97_init(card) <= 0) { - unregister_sound_dsp(card->dev_audio); + /* register /dev/dsp */ + if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) { + int i; + printk(KERN_ERR "i810_audio: couldn't register DSP device!\n"); release_region(card->iobase, 64); release_region(card->ac97base, 256); free_irq(card->irq, card); + for (i = 0; i < NR_AC97; i++) + if (card->ac97_codec[i] != NULL) { + unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); + kfree (card->ac97_codec[i]); + } kfree(card); return -ENODEV; } - pci_dev->driver_data = card; + return 0; } @@ -2137,7 +2207,7 @@ /* unregister audio devices */ for (i = 0; i < NR_AC97; i++) - if (devs->ac97_codec[i] != NULL) { + if (card->ac97_codec[i] != NULL) { unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); kfree (card->ac97_codec[i]); } @@ -2161,74 +2231,6 @@ remove: i810_remove, }; -static void __init i810_configure_clocking (void) -{ - struct i810_card *card; - struct i810_state *state; - struct dmabuf *dmabuf; - unsigned int i, offset, new_offset; - unsigned long flags; - - card = devs; - /* We could try to set the clocking for multiple cards, but can you even have - * more than one i810 in a machine? Besides, clocking is global, so unless - * someone actually thinks more than one i810 in a machine is possible and - * decides to rewrite that little bit, setting the rate for more than one card - * is a waste of time. - */ - if(card != NULL) { - state = card->states[0] = (struct i810_state *) - kmalloc(sizeof(struct i810_state), GFP_KERNEL); - if (state == NULL) - return; - memset(state, 0, sizeof(struct i810_state)); - dmabuf = &state->dmabuf; - - dmabuf->write_channel = card->alloc_pcm_channel(card); - state->virt = 0; - state->card = card; - state->magic = I810_STATE_MAGIC; - init_waitqueue_head(&dmabuf->wait); - init_MUTEX(&state->open_sem); - dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT; - dmabuf->trigger = PCM_ENABLE_OUTPUT; - i810_set_dac_rate(state, 48000); - if(prog_dmabuf(state, 0) != 0) { - goto config_out_nodmabuf; - } - if(dmabuf->dmasize < 16384) { - goto config_out; - } - dmabuf->count = dmabuf->dmasize; - outb(31,card->iobase+dmabuf->write_channel->port+OFF_LVI); - save_flags(flags); - cli(); - start_dac(state); - offset = i810_get_dma_addr(state, 0); - mdelay(50); - new_offset = i810_get_dma_addr(state, 0); - stop_dac(state); - outb(2,card->iobase+dmabuf->write_channel->port+OFF_CR); - restore_flags(flags); - i = new_offset - offset; -#ifdef DEBUG - printk("i810_audio: %d bytes in 50 milliseconds\n", i); -#endif - if(i == 0) - goto config_out; - i = i / 4 * 20; - if (i > 48500 || i < 47500) { - clocking = clocking * clocking / i; - printk("i810_audio: setting clocking to %d\n", clocking); - } -config_out: - dealloc_dmabuf(state); -config_out_nodmabuf: - state->card->free_pcm_channel(state->card,state->dmabuf.write_channel->num); - kfree(state); - card->states[0] = NULL; - } -} static int __init i810_init_module (void) { diff -u --recursive --new-file v2.4.9/linux/drivers/sound/ite8172.c linux/drivers/sound/ite8172.c --- v2.4.9/linux/drivers/sound/ite8172.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/ite8172.c Fri Sep 7 09:28:37 2001 @@ -0,0 +1,1957 @@ +/* + * ite8172.c -- ITE IT8172G Sound Driver. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * stevel@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Module command line parameters: + * + * Supported devices: + * /dev/dsp standard OSS /dev/dsp device + * /dev/mixer standard OSS /dev/mixer device + * + * Notes: + * + * 1. Much of the OSS buffer allocation, ioctl's, and mmap'ing are + * taken, slightly modified or not at all, from the ES1371 driver, + * so refer to the credits in es1371.c for those. The rest of the + * code (probe, open, read, write, the ISR, etc.) is new. + * 2. The following support is untested: + * * Memory mapping the audio buffers, and the ioctl controls that go + * with it. + * * S/PDIF output. + * 3. The following is not supported: + * * I2S input. + * * legacy audio mode. + * 4. Support for volume button interrupts is implemented but doesn't + * work yet. + * + * Revision history + * 02.08.2001 0.1 Initial release + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* --------------------------------------------------------------------- */ + +#undef OSS_DOCUMENTED_MIXER_SEMANTICS +#define IT8172_DEBUG +#undef IT8172_VERBOSE_DEBUG +#define DBG(x) {} + +static const unsigned sample_shift[] = { 0, 1, 1, 2 }; + + +/* + * Audio Controller register bit definitions follow. See + * include/asm/it8172/it8172.h for register offsets. + */ + +/* PCM Out Volume Reg */ +#define PCMOV_PCMOM (1<<15) /* PCM Out Mute default 1: mute */ +#define PCMOV_PCMRCG_BIT 8 /* PCM Right channel Gain */ +#define PCMOV_PCMRCG_MASK (0x1f<= 0x10000) { + x >>= 16; + r += 16; + } + if (x >= 0x100) { + x >>= 8; + r += 8; + } + if (x >= 0x10) { + x >>= 4; + r += 4; + } + if (x >= 4) { + x >>= 2; + r += 2; + } + if (x >= 2) + r++; + return r; +} + +/* --------------------------------------------------------------------- */ + +static void it8172_delay(int msec) +{ + unsigned long tmo; + signed long tmo2; + + if (in_interrupt()) + return; + + tmo = jiffies + (msec*HZ)/1000; + for (;;) { + tmo2 = tmo - jiffies; + if (tmo2 <= 0) + break; + schedule_timeout(tmo2); + } +} + + +static unsigned short +get_compat_rate(unsigned* rate) +{ + unsigned rate_out = *rate; + unsigned short sr; + + if (rate_out >= 46050) { + sr = CC_SR_48000; rate_out = 48000; + } else if (rate_out >= 41250) { + sr = CC_SR_44100; rate_out = 44100; + } else if (rate_out >= 35200) { + sr = CC_SR_38400; rate_out = 38400; + } else if (rate_out >= 27025) { + sr = CC_SR_32000; rate_out = 32000; + } else if (rate_out >= 20625) { + sr = CC_SR_22050; rate_out = 22050; + } else if (rate_out >= 17600) { + sr = CC_SR_19200; rate_out = 19200; + } else if (rate_out >= 13513) { + sr = CC_SR_16000; rate_out = 16000; + } else if (rate_out >= 10313) { + sr = CC_SR_11025; rate_out = 11025; + } else if (rate_out >= 8800) { + sr = CC_SR_9600; rate_out = 9600; + } else if (rate_out >= 6750) { + sr = CC_SR_8000; rate_out = 8000; + } else { + sr = CC_SR_5500; rate_out = 5500; + } + + *rate = rate_out; + return sr; +} + +static void set_adc_rate(struct it8172_state *s, unsigned rate) +{ + unsigned long flags; + unsigned short sr; + + sr = get_compat_rate(&rate); + + spin_lock_irqsave(&s->lock, flags); + s->capcc &= ~CC_SR_MASK; + s->capcc |= sr; + outw(s->capcc, s->io+IT_AC_CAPCC); + spin_unlock_irqrestore(&s->lock, flags); + + s->adcrate = rate; +} + + +static void set_dac_rate(struct it8172_state *s, unsigned rate) +{ + unsigned long flags; + unsigned short sr; + + sr = get_compat_rate(&rate); + + spin_lock_irqsave(&s->lock, flags); + s->pcc &= ~CC_SR_MASK; + s->pcc |= sr; + outw(s->pcc, s->io+IT_AC_PCC); + spin_unlock_irqrestore(&s->lock, flags); + + s->dacrate = rate; +} + + +/* --------------------------------------------------------------------- */ + +static u16 rdcodec(struct ac97_codec *codec, u8 addr) +{ + struct it8172_state *s = (struct it8172_state *)codec->private_data; + unsigned long flags; + unsigned short circp, data; + int i; + + spin_lock_irqsave(&s->lock, flags); + + for (i = 0; i < POLL_COUNT; i++) + if (!(inw(s->io+IT_AC_CIRCP) & CIRCP_CPS)) + break; + if (i == POLL_COUNT) + printk(KERN_INFO PFX "rdcodec: codec ready poll expired!\n"); + + circp = addr & CIRCP_CIA_MASK; + circp |= (codec->id << CIRCP_CID_BIT); + circp |= CIRCP_RWC; // read command + outw(circp, s->io+IT_AC_CIRCP); + + /* now wait for the data */ + for (i = 0; i < POLL_COUNT; i++) + if (inw(s->io+IT_AC_CIRCP) & CIRCP_DPVF) + break; + if (i == POLL_COUNT) + printk(KERN_INFO PFX "rdcodec: read poll expired!\n"); + + data = inw(s->io+IT_AC_CIRDP); + spin_unlock_irqrestore(&s->lock, flags); + + return data; +} + + +static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data) +{ + struct it8172_state *s = (struct it8172_state *)codec->private_data; + unsigned long flags; + unsigned short circp; + int i; + + spin_lock_irqsave(&s->lock, flags); + + for (i = 0; i < POLL_COUNT; i++) + if (!(inw(s->io+IT_AC_CIRCP) & CIRCP_CPS)) + break; + if (i == POLL_COUNT) + printk(KERN_INFO PFX "wrcodec: codec ready poll expired!\n"); + + circp = addr & CIRCP_CIA_MASK; + circp |= (codec->id << CIRCP_CID_BIT); + circp &= ~CIRCP_RWC; // write command + + outw(data, s->io+IT_AC_CIRDP); // send data first + outw(circp, s->io+IT_AC_CIRCP); + + spin_unlock_irqrestore(&s->lock, flags); +} + + +static void waitcodec(struct ac97_codec *codec) +{ + unsigned short temp; + + /* codec_wait is used to wait for a ready state after + an AC97_RESET. */ + it8172_delay(10); + + temp = rdcodec(codec, 0x26); + + // If power down, power up + if (temp & 0x3f00) { + // Power on + wrcodec(codec, 0x26, 0); + it8172_delay(100); + // Reread + temp = rdcodec(codec, 0x26); + } + + // Check if Codec REF,ANL,DAC,ADC ready***/ + if ((temp & 0x3f0f) != 0x000f) { + printk(KERN_INFO PFX "codec reg 26 status (0x%x) not ready!!\n", + temp); + return; + } +} + + +/* --------------------------------------------------------------------- */ + +extern inline void stop_adc(struct it8172_state *s) +{ + struct dmabuf* db = &s->dma_adc; + unsigned long flags; + unsigned char imc; + + if (db->stopped) + return; + + spin_lock_irqsave(&s->lock, flags); + + s->capcc &= ~(CC_CA | CC_CP | CC_CB2L | CC_CB1L); + s->capcc |= CC_CSP; + outw(s->capcc, s->io+IT_AC_CAPCC); + + // disable capture interrupt + imc = inb(s->io+IT_AC_IMC); + outb(imc | IMC_CCIM, s->io+IT_AC_IMC); + + db->stopped = 1; + + spin_unlock_irqrestore(&s->lock, flags); +} + +extern inline void stop_dac(struct it8172_state *s) +{ + struct dmabuf* db = &s->dma_dac; + unsigned long flags; + unsigned char imc; + + if (db->stopped) + return; + + spin_lock_irqsave(&s->lock, flags); + + s->pcc &= ~(CC_CA | CC_CP | CC_CB2L | CC_CB1L); + s->pcc |= CC_CSP; + outw(s->pcc, s->io+IT_AC_PCC); + + // disable playback interrupt + imc = inb(s->io+IT_AC_IMC); + outb(imc | IMC_PCIM, s->io+IT_AC_IMC); + + db->stopped = 1; + + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_dac(struct it8172_state *s) +{ + struct dmabuf* db = &s->dma_dac; + unsigned long flags; + unsigned char imc; + unsigned long buf1, buf2; + + if (!db->stopped) + return; + + spin_lock_irqsave(&s->lock, flags); + + // reset Buffer 1 and 2 pointers to nextOut and nextOut+fragsize + buf1 = virt_to_bus(db->nextOut); + buf2 = buf1 + db->fragsize; + if (buf2 >= db->dmaaddr + db->dmasize) + buf2 -= db->dmasize; + + outl(buf1, s->io+IT_AC_PCB1STA); + outl(buf2, s->io+IT_AC_PCB2STA); + db->curBufPtr = IT_AC_PCB1STA; + + // enable playback interrupt + imc = inb(s->io+IT_AC_IMC); + outb(imc & ~IMC_PCIM, s->io+IT_AC_IMC); + + s->pcc &= ~(CC_CSP | CC_CP | CC_CB2L | CC_CB1L); + s->pcc |= CC_CA; + outw(s->pcc, s->io+IT_AC_PCC); + + db->stopped = 0; + + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_adc(struct it8172_state *s) +{ + struct dmabuf* db = &s->dma_adc; + unsigned long flags; + unsigned char imc; + unsigned long buf1, buf2; + + if (!db->stopped) + return; + + spin_lock_irqsave(&s->lock, flags); + + // reset Buffer 1 and 2 pointers to nextIn and nextIn+fragsize + buf1 = virt_to_bus(db->nextIn); + buf2 = buf1 + db->fragsize; + if (buf2 >= db->dmaaddr + db->dmasize) + buf2 -= db->dmasize; + + outl(buf1, s->io+IT_AC_CAPB1STA); + outl(buf2, s->io+IT_AC_CAPB2STA); + db->curBufPtr = IT_AC_CAPB1STA; + + // enable capture interrupt + imc = inb(s->io+IT_AC_IMC); + outb(imc & ~IMC_CCIM, s->io+IT_AC_IMC); + + s->capcc &= ~(CC_CSP | CC_CP | CC_CB2L | CC_CB1L); + s->capcc |= CC_CA; + outw(s->capcc, s->io+IT_AC_CAPCC); + + db->stopped = 0; + + spin_unlock_irqrestore(&s->lock, flags); +} + +/* --------------------------------------------------------------------- */ + +#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT) +#define DMABUF_MINORDER 1 + +extern inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db) +{ + struct page *page, *pend; + + if (db->rawbuf) { + /* undo marking the pages as reserved */ + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_unreserve(page); + pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, + db->rawbuf, db->dmaaddr); + } + db->rawbuf = db->nextIn = db->nextOut = NULL; + db->mapped = db->ready = 0; +} + +static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db, + unsigned rate, unsigned fmt, unsigned reg) +{ + int order; + unsigned bytepersec; + unsigned bufs; + struct page *page, *pend; + + if (!db->rawbuf) { + db->ready = db->mapped = 0; + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) + if ((db->rawbuf = pci_alloc_consistent(s->dev, + PAGE_SIZE << order, + &db->dmaaddr))) + break; + if (!db->rawbuf) + return -ENOMEM; + db->buforder = order; + /* now mark the pages as reserved; + otherwise remap_page_range doesn't do what we want */ + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_reserve(page); + } + + db->count = 0; + db->nextIn = db->nextOut = db->rawbuf; + + bytepersec = rate << sample_shift[fmt]; + bufs = PAGE_SIZE << db->buforder; + if (db->ossfragshift) { + if ((1000 << db->ossfragshift) < bytepersec) + db->fragshift = ld2(bytepersec/1000); + else + db->fragshift = db->ossfragshift; + } else { + db->fragshift = ld2(bytepersec/100/(db->subdivision ? + db->subdivision : 1)); + if (db->fragshift < 3) + db->fragshift = 3; + } + db->numfrag = bufs >> db->fragshift; + while (db->numfrag < 4 && db->fragshift > 3) { + db->fragshift--; + db->numfrag = bufs >> db->fragshift; + } + db->fragsize = 1 << db->fragshift; + if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) + db->numfrag = db->ossmaxfrags; + db->fragsamples = db->fragsize >> sample_shift[fmt]; + db->dmasize = db->numfrag << db->fragshift; + memset(db->rawbuf, (fmt & (CC_DF>>CC_FMT_BIT)) ? 0 : 0x80, db->dmasize); + + // set data length register + outw(db->fragsize, s->io+reg+2); + db->ready = 1; + + return 0; +} + +extern inline int prog_dmabuf_adc(struct it8172_state *s) +{ + stop_adc(s); + return prog_dmabuf(s, &s->dma_adc, s->adcrate, + (s->capcc & CC_FMT_MASK) >> CC_FMT_BIT, + IT_AC_CAPCC); +} + +extern inline int prog_dmabuf_dac(struct it8172_state *s) +{ + stop_dac(s); + return prog_dmabuf(s, &s->dma_dac, s->dacrate, + (s->pcc & CC_FMT_MASK) >> CC_FMT_BIT, + IT_AC_PCC); +} + + +/* hold spinlock for the following! */ + +static void it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct it8172_state *s = (struct it8172_state *)dev_id; + struct dmabuf* dac = &s->dma_dac; + struct dmabuf* adc = &s->dma_adc; + unsigned char isc, vs; + unsigned short vol, mute; + unsigned long newptr; + + spin_lock(&s->lock); + + isc = inb(s->io+IT_AC_ISC); + + /* fastpath out, to ease interrupt sharing */ + if (!(isc & (ISC_VCI | ISC_CCI | ISC_PCI))) + return; + + /* clear audio interrupts first */ + outb(isc | ISC_VCI | ISC_CCI | ISC_PCI, s->io+IT_AC_ISC); + + /* handle volume button events */ + if (isc & ISC_VCI) { + vs = inb(s->io+IT_AC_VS); + outb(0, s->io+IT_AC_VS); + vol = inw(s->io+IT_AC_PCMOV); + mute = vol & PCMOV_PCMOM; + vol &= PCMOV_PCMLCG_MASK; + if ((vs & VS_VUP) && vol > 0) + vol--; + if ((vs & VS_VDP) && vol < 0x1f) + vol++; + vol |= (vol << PCMOV_PCMRCG_BIT); + if (vs & VS_VMP) + vol |= (mute ^ PCMOV_PCMOM); + outw(vol, s->io+IT_AC_PCMOV); + } + + /* update capture pointers */ + if (isc & ISC_CCI) { + if (adc->count > adc->dmasize - adc->fragsize) { + // Overrun. Stop ADC and log the error + stop_adc(s); + adc->error++; + printk(KERN_INFO PFX "adc overrun\n"); + } else { + newptr = virt_to_bus(adc->nextIn) + 2*adc->fragsize; + if (newptr >= adc->dmaaddr + adc->dmasize) + newptr -= adc->dmasize; + + outl(newptr, s->io+adc->curBufPtr); + adc->curBufPtr = (adc->curBufPtr == IT_AC_CAPB1STA) ? + IT_AC_CAPB2STA : IT_AC_CAPB1STA; + + adc->nextIn += adc->fragsize; + if (adc->nextIn >= adc->rawbuf + adc->dmasize) + adc->nextIn -= adc->dmasize; + + adc->count += adc->fragsize; + adc->total_bytes += adc->fragsize; + + /* wake up anybody listening */ + if (waitqueue_active(&adc->wait)) + wake_up_interruptible(&adc->wait); + } + } + + /* update playback pointers */ + if (isc & ISC_PCI) { + newptr = virt_to_bus(dac->nextOut) + 2*dac->fragsize; + if (newptr >= dac->dmaaddr + dac->dmasize) + newptr -= dac->dmasize; + + outl(newptr, s->io+dac->curBufPtr); + dac->curBufPtr = (dac->curBufPtr == IT_AC_PCB1STA) ? + IT_AC_PCB2STA : IT_AC_PCB1STA; + + dac->nextOut += dac->fragsize; + if (dac->nextOut >= dac->rawbuf + dac->dmasize) + dac->nextOut -= dac->dmasize; + + dac->count -= dac->fragsize; + dac->total_bytes += dac->fragsize; + + /* wake up anybody listening */ + if (waitqueue_active(&dac->wait)) + wake_up_interruptible(&dac->wait); + + if (dac->count <= 0) + stop_dac(s); + } + + spin_unlock(&s->lock); +} + +/* --------------------------------------------------------------------- */ + +static loff_t it8172_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + + +static int it8172_open_mixdev(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct list_head *list; + struct it8172_state *s; + + for (list = devs.next; ; list = list->next) { + if (list == &devs) + return -ENODEV; + s = list_entry(list, struct it8172_state, devs); + if (s->codec.dev_mixer == minor) + break; + } + file->private_data = s; + return 0; +} + +static int it8172_release_mixdev(struct inode *inode, struct file *file) +{ + return 0; +} + + +static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, + unsigned long arg) +{ + return codec->mixer_ioctl(codec, cmd, arg); +} + +static int it8172_ioctl_mixdev(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct it8172_state *s = (struct it8172_state *)file->private_data; + struct ac97_codec *codec = &s->codec; + + return mixdev_ioctl(codec, cmd, arg); +} + +static /*const*/ struct file_operations it8172_mixer_fops = { + owner: THIS_MODULE, + llseek: it8172_llseek, + ioctl: it8172_ioctl_mixdev, + open: it8172_open_mixdev, + release: it8172_release_mixdev, +}; + +/* --------------------------------------------------------------------- */ + +static int drain_dac(struct it8172_state *s, int nonblock) +{ + unsigned long flags; + int count, tmo; + + if (s->dma_dac.mapped || !s->dma_dac.ready) + return 0; + + for (;;) { + spin_lock_irqsave(&s->lock, flags); + count = s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + if (count <= 0) + break; + if (signal_pending(current)) + break; + if (nonblock) + return -EBUSY; + tmo = 1000 * count / s->dacrate; + tmo >>= sample_shift[(s->pcc & CC_FMT_MASK) >> CC_FMT_BIT]; + it8172_delay(tmo); + } + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + +/* --------------------------------------------------------------------- */ + +static ssize_t it8172_read(struct file *file, char *buffer, + size_t count, loff_t *ppos) +{ + struct it8172_state *s = (struct it8172_state *)file->private_data; + struct dmabuf *db = &s->dma_adc; + ssize_t ret; + unsigned long flags; + int cnt, bufcnt, avail; + + if (ppos != &file->f_pos) + return -ESPIPE; + if (db->mapped) + return -ENXIO; + if (!access_ok(VERIFY_WRITE, buffer, count)) + return -EFAULT; + ret = 0; + + while (count > 0) { + // wait for samples in capture buffer + do { + spin_lock_irqsave(&s->lock, flags); + if (db->stopped) + start_adc(s); + avail = db->count; + spin_unlock_irqrestore(&s->lock, flags); + if (avail <= 0) { + if (file->f_flags & O_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + return ret; + } + interruptible_sleep_on(&db->wait); + if (signal_pending(current)) { + if (!ret) + ret = -ERESTARTSYS; + return ret; + } + } + } while (avail <= 0); + + cnt = count > avail ? avail : count; + bufcnt = cnt; + if (cnt % db->fragsize) { + // round count up to nearest fragment + int newcnt = db->fragsize * ((cnt + db->fragsize) / db->fragsize); + cnt = newcnt; + } + + // copy from nextOut to user + if (copy_to_user(buffer, db->nextOut, bufcnt)) { + if (!ret) + ret = -EFAULT; + return ret; + } + + spin_lock_irqsave(&s->lock, flags); + db->count -= cnt; + spin_unlock_irqrestore(&s->lock, flags); + + db->nextOut += cnt; + if (db->nextOut >= db->rawbuf + db->dmasize) + db->nextOut -= db->dmasize; + + count -= bufcnt; + buffer += bufcnt; + ret += bufcnt; + } // while (count > 0) + + return ret; +} + +static ssize_t it8172_write(struct file *file, const char *buffer, + size_t count, loff_t *ppos) +{ + struct it8172_state *s = (struct it8172_state *)file->private_data; + struct dmabuf *db = &s->dma_dac; + ssize_t ret; + unsigned long flags; + int cnt, bufcnt, avail; + + if (ppos != &file->f_pos) + return -ESPIPE; + if (db->mapped) + return -ENXIO; + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; + ret = 0; + + while (count > 0) { + // wait for space in playback buffer + do { + spin_lock_irqsave(&s->lock, flags); + avail = db->dmasize - db->count; + spin_unlock_irqrestore(&s->lock, flags); + if (avail <= 0) { + if (file->f_flags & O_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + return ret; + } + interruptible_sleep_on(&db->wait); + if (signal_pending(current)) { + if (!ret) + ret = -ERESTARTSYS; + return ret; + } + } + } while (avail <= 0); + + cnt = count > avail ? avail : count; + // copy to nextIn + if (copy_from_user(db->nextIn, buffer, cnt)) { + if (!ret) + ret = -EFAULT; + return ret; + } + + bufcnt = cnt; + if (cnt % db->fragsize) { + // round count up to nearest fragment, and fill remainder of + // fragment with silence + int newcnt = db->fragsize * ((cnt + db->fragsize) / db->fragsize); + memset(db->nextIn + cnt, (s->pcc & CC_DF) ? 0 : 0x80, newcnt - cnt); + cnt = newcnt; + } + + spin_lock_irqsave(&s->lock, flags); + db->count += cnt; + if (db->stopped) + start_dac(s); + spin_unlock_irqrestore(&s->lock, flags); + + db->nextIn += cnt; + if (db->nextIn >= db->rawbuf + db->dmasize) + db->nextIn -= db->dmasize; + + count -= bufcnt; + buffer += bufcnt; + ret += bufcnt; + } // while (count > 0) + + return ret; +} + +/* No kernel lock - we have our own spinlock */ +static unsigned int it8172_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct it8172_state *s = (struct it8172_state *)file->private_data; + unsigned long flags; + unsigned int mask = 0; + + if (file->f_mode & FMODE_WRITE) + poll_wait(file, &s->dma_dac.wait, wait); + if (file->f_mode & FMODE_READ) + poll_wait(file, &s->dma_adc.wait, wait); + spin_lock_irqsave(&s->lock, flags); + if (file->f_mode & FMODE_READ) { + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) + mask |= POLLIN | POLLRDNORM; + } + if (file->f_mode & FMODE_WRITE) { + if (s->dma_dac.mapped) { + if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) + mask |= POLLOUT | POLLWRNORM; + } else { + if ((signed)s->dma_dac.dmasize >= + s->dma_dac.count + (signed)s->dma_dac.fragsize) + mask |= POLLOUT | POLLWRNORM; + } + } + spin_unlock_irqrestore(&s->lock, flags); + return mask; +} + +static int it8172_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct it8172_state *s = (struct it8172_state *)file->private_data; + struct dmabuf *db; + unsigned long size; + + lock_kernel(); + if (vma->vm_flags & VM_WRITE) + db = &s->dma_dac; + else if (vma->vm_flags & VM_READ) + db = &s->dma_adc; + else { + unlock_kernel(); + return -EINVAL; + } + if (vma->vm_pgoff != 0) { + unlock_kernel(); + return -EINVAL; + } + size = vma->vm_end - vma->vm_start; + if (size > (PAGE_SIZE << db->buforder)) { + unlock_kernel(); + return -EINVAL; + } + if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), + size, vma->vm_page_prot)) { + unlock_kernel(); + return -EAGAIN; + } + db->mapped = 1; + unlock_kernel(); + return 0; +} + + +#ifdef IT8172_VERBOSE_DEBUG +static struct ioctl_str_t { + unsigned int cmd; + const char* str; +} ioctl_str[] = { + {SNDCTL_DSP_RESET, "SNDCTL_DSP_RESET"}, + {SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC"}, + {SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED"}, + {SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO"}, + {SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE"}, + {SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE"}, + {SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS"}, + {SOUND_PCM_WRITE_CHANNELS, "SOUND_PCM_WRITE_CHANNELS"}, + {SOUND_PCM_WRITE_FILTER, "SOUND_PCM_WRITE_FILTER"}, + {SNDCTL_DSP_POST, "SNDCTL_DSP_POST"}, + {SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE"}, + {SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT"}, + {SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS"}, + {SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT"}, + {SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE"}, + {SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE"}, + {SNDCTL_DSP_NONBLOCK, "SNDCTL_DSP_NONBLOCK"}, + {SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_GETCAPS"}, + {SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER"}, + {SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER"}, + {SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR"}, + {SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR"}, + {SNDCTL_DSP_MAPINBUF, "SNDCTL_DSP_MAPINBUF"}, + {SNDCTL_DSP_MAPOUTBUF, "SNDCTL_DSP_MAPOUTBUF"}, + {SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO"}, + {SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX"}, + {SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY"}, + {SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK"}, + {SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL"}, + {OSS_GETVERSION, "OSS_GETVERSION"}, + {SOUND_PCM_READ_RATE, "SOUND_PCM_READ_RATE"}, + {SOUND_PCM_READ_CHANNELS, "SOUND_PCM_READ_CHANNELS"}, + {SOUND_PCM_READ_BITS, "SOUND_PCM_READ_BITS"}, + {SOUND_PCM_READ_FILTER, "SOUND_PCM_READ_FILTER"} +}; +#endif + +static int it8172_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct it8172_state *s = (struct it8172_state *)file->private_data; + unsigned long flags; + audio_buf_info abinfo; + count_info cinfo; + int count; + int val, mapped, ret, diff; + + mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || + ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); + +#ifdef IT8172_VERBOSE_DEBUG + for (count=0; countf_mode & FMODE_WRITE) + return drain_dac(s, file->f_flags & O_NONBLOCK); + return 0; + + case SNDCTL_DSP_SETDUPLEX: + return 0; + + case SNDCTL_DSP_GETCAPS: + return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | + DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); + + case SNDCTL_DSP_RESET: + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + synchronize_irq(); + s->dma_dac.count = s->dma_dac.total_bytes = 0; + s->dma_dac.nextIn = s->dma_dac.nextOut = s->dma_dac.rawbuf; + } + if (file->f_mode & FMODE_READ) { + stop_adc(s); + synchronize_irq(); + s->dma_adc.count = s->dma_adc.total_bytes = 0; + s->dma_adc.nextIn = s->dma_adc.nextOut = s->dma_adc.rawbuf; + } + return 0; + + case SNDCTL_DSP_SPEED: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val >= 0) { + if (file->f_mode & FMODE_READ) { + stop_adc(s); + set_adc_rate(s, val); + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + set_dac_rate(s, val); + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + } + return put_user((file->f_mode & FMODE_READ) ? + s->adcrate : s->dacrate, (int *)arg); + + case SNDCTL_DSP_STEREO: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (file->f_mode & FMODE_READ) { + stop_adc(s); + if (val) + s->capcc |= CC_SM; + else + s->capcc &= ~CC_SM; + outw(s->capcc, s->io+IT_AC_CAPCC); + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + if (val) + s->pcc |= CC_SM; + else + s->pcc &= ~CC_SM; + outw(s->pcc, s->io+IT_AC_PCC); + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + return 0; + + case SNDCTL_DSP_CHANNELS: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val != 0) { + if (file->f_mode & FMODE_READ) { + stop_adc(s); + if (val >= 2) { + val = 2; + s->capcc |= CC_SM; + } + else + s->capcc &= ~CC_SM; + outw(s->capcc, s->io+IT_AC_CAPCC); + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + switch (val) { + case 1: + s->pcc &= ~CC_SM; + break; + case 2: + s->pcc |= CC_SM; + break; + default: + // FIX! support multichannel??? + val = 2; + s->pcc |= CC_SM; + break; + } + outw(s->pcc, s->io+IT_AC_PCC); + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + } + return put_user(val, (int *)arg); + + case SNDCTL_DSP_GETFMTS: /* Returns a mask */ + return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); + + case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val != AFMT_QUERY) { + if (file->f_mode & FMODE_READ) { + stop_adc(s); + if (val == AFMT_S16_LE) + s->capcc |= CC_DF; + else { + val = AFMT_U8; + s->capcc &= ~CC_DF; + } + outw(s->capcc, s->io+IT_AC_CAPCC); + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + if (val == AFMT_S16_LE) + s->pcc |= CC_DF; + else { + val = AFMT_U8; + s->pcc &= ~CC_DF; + } + outw(s->pcc, s->io+IT_AC_PCC); + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + } else { + if (file->f_mode & FMODE_READ) + val = (s->capcc & CC_DF) ? AFMT_S16_LE : AFMT_U8; + else + val = (s->pcc & CC_DF) ? AFMT_S16_LE : AFMT_U8; + } + return put_user(val, (int *)arg); + + case SNDCTL_DSP_POST: + return 0; + + case SNDCTL_DSP_GETTRIGGER: + val = 0; + spin_lock_irqsave(&s->lock, flags); + if (file->f_mode & FMODE_READ && !s->dma_adc.stopped) + val |= PCM_ENABLE_INPUT; + if (file->f_mode & FMODE_WRITE && !s->dma_dac.stopped) + val |= PCM_ENABLE_OUTPUT; + spin_unlock_irqrestore(&s->lock, flags); + return put_user(val, (int *)arg); + + case SNDCTL_DSP_SETTRIGGER: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (file->f_mode & FMODE_READ) { + if (val & PCM_ENABLE_INPUT) + start_adc(s); + else + stop_adc(s); + } + if (file->f_mode & FMODE_WRITE) { + if (val & PCM_ENABLE_OUTPUT) + start_dac(s); + else + stop_dac(s); + } + return 0; + + case SNDCTL_DSP_GETOSPACE: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + abinfo.fragsize = s->dma_dac.fragsize; + spin_lock_irqsave(&s->lock, flags); + count = s->dma_dac.count; + if (!s->dma_dac.stopped) + count -= (s->dma_dac.fragsize - inw(s->io+IT_AC_PCDL)); + spin_unlock_irqrestore(&s->lock, flags); + if (count < 0) + count = 0; + abinfo.bytes = s->dma_dac.dmasize - count; + abinfo.fragstotal = s->dma_dac.numfrag; + abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + + case SNDCTL_DSP_GETISPACE: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + abinfo.fragsize = s->dma_adc.fragsize; + spin_lock_irqsave(&s->lock, flags); + count = s->dma_adc.count; + if (!s->dma_adc.stopped) + count += (s->dma_adc.fragsize - inw(s->io+IT_AC_CAPCDL)); + spin_unlock_irqrestore(&s->lock, flags); + if (count < 0) + count = 0; + abinfo.bytes = count; + abinfo.fragstotal = s->dma_adc.numfrag; + abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; + + case SNDCTL_DSP_GETODELAY: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + count = s->dma_dac.count; + if (!s->dma_dac.stopped) + count -= (s->dma_dac.fragsize - inw(s->io+IT_AC_PCDL)); + spin_unlock_irqrestore(&s->lock, flags); + if (count < 0) + count = 0; + return put_user(count, (int *)arg); + + case SNDCTL_DSP_GETIPTR: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + cinfo.bytes = s->dma_adc.total_bytes; + count = s->dma_adc.count; + if (!s->dma_adc.stopped) { + diff = s->dma_adc.fragsize - inw(s->io+IT_AC_CAPCDL); + count += diff; + cinfo.bytes += diff; + cinfo.ptr = inl(s->io+s->dma_adc.curBufPtr) - s->dma_adc.dmaaddr; + } else + cinfo.ptr = virt_to_bus(s->dma_adc.nextIn) - s->dma_adc.dmaaddr; + if (s->dma_adc.mapped) + s->dma_adc.count &= s->dma_adc.fragsize-1; + spin_unlock_irqrestore(&s->lock, flags); + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_adc.fragshift; + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_GETOPTR: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + cinfo.bytes = s->dma_dac.total_bytes; + count = s->dma_dac.count; + if (!s->dma_dac.stopped) { + diff = s->dma_dac.fragsize - inw(s->io+IT_AC_CAPCDL); + count -= diff; + cinfo.bytes += diff; + cinfo.ptr = inl(s->io+s->dma_dac.curBufPtr) - s->dma_dac.dmaaddr; + } else + cinfo.ptr = virt_to_bus(s->dma_dac.nextOut) - s->dma_dac.dmaaddr; + if (s->dma_dac.mapped) + s->dma_dac.count &= s->dma_dac.fragsize-1; + spin_unlock_irqrestore(&s->lock, flags); + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_dac.fragshift; + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_GETBLKSIZE: + if (file->f_mode & FMODE_WRITE) + return put_user(s->dma_dac.fragsize, (int *)arg); + else + return put_user(s->dma_adc.fragsize, (int *)arg); + + case SNDCTL_DSP_SETFRAGMENT: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ossfragshift = val & 0xffff; + s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; + if (s->dma_adc.ossfragshift < 4) + s->dma_adc.ossfragshift = 4; + if (s->dma_adc.ossfragshift > 15) + s->dma_adc.ossfragshift = 15; + if (s->dma_adc.ossmaxfrags < 4) + s->dma_adc.ossmaxfrags = 4; + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ossfragshift = val & 0xffff; + s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff; + if (s->dma_dac.ossfragshift < 4) + s->dma_dac.ossfragshift = 4; + if (s->dma_dac.ossfragshift > 15) + s->dma_dac.ossfragshift = 15; + if (s->dma_dac.ossmaxfrags < 4) + s->dma_dac.ossmaxfrags = 4; + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + return 0; + + case SNDCTL_DSP_SUBDIVIDE: + if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || + (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) + return -EINVAL; + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val != 1 && val != 2 && val != 4) + return -EINVAL; + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.subdivision = val; + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.subdivision = val; + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + return 0; + + case SOUND_PCM_READ_RATE: + return put_user((file->f_mode & FMODE_READ) ? + s->adcrate : s->dacrate, (int *)arg); + + case SOUND_PCM_READ_CHANNELS: + if (file->f_mode & FMODE_READ) + return put_user((s->capcc & CC_SM) ? 2 : 1, (int *)arg); + else + return put_user((s->pcc & CC_SM) ? 2 : 1, (int *)arg); + + case SOUND_PCM_READ_BITS: + if (file->f_mode & FMODE_READ) + return put_user((s->capcc & CC_DF) ? 16 : 8, (int *)arg); + else + return put_user((s->pcc & CC_DF) ? 16 : 8, (int *)arg); + + case SOUND_PCM_WRITE_FILTER: + case SNDCTL_DSP_SETSYNCRO: + case SOUND_PCM_READ_FILTER: + return -EINVAL; + } + + return mixdev_ioctl(&s->codec, cmd, arg); +} + + +static int it8172_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + struct list_head *list; + struct it8172_state *s; + int ret; + + for (list = devs.next; ; list = list->next) { + if (list == &devs) + return -ENODEV; + s = list_entry(list, struct it8172_state, devs); + if (!((s->dev_audio ^ minor) & ~0xf)) + break; + } + file->private_data = s; + /* wait for device to become free */ + down(&s->open_sem); + while (s->open_mode & file->f_mode) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem); + return -EBUSY; + } + add_wait_queue(&s->open_wait, &wait); + __set_current_state(TASK_INTERRUPTIBLE); + up(&s->open_sem); + schedule(); + remove_wait_queue(&s->open_wait, &wait); + set_current_state(TASK_RUNNING); + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem); + } + + spin_lock_irqsave(&s->lock, flags); + + if (file->f_mode & FMODE_READ) { + s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = + s->dma_adc.subdivision = s->dma_adc.total_bytes = 0; + s->capcc &= ~(CC_SM | CC_DF); + set_adc_rate(s, 8000); + if ((minor & 0xf) == SND_DEV_DSP16) + s->capcc |= CC_DF; + outw(s->capcc, s->io+IT_AC_CAPCC); + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = + s->dma_dac.subdivision = s->dma_dac.total_bytes = 0; + s->pcc &= ~(CC_SM | CC_DF); + set_dac_rate(s, 8000); + if ((minor & 0xf) == SND_DEV_DSP16) + s->pcc |= CC_DF; + outw(s->pcc, s->io+IT_AC_PCC); + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + + spin_unlock_irqrestore(&s->lock, flags); + + s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); + up(&s->open_sem); + return 0; +} + +static int it8172_release(struct inode *inode, struct file *file) +{ + struct it8172_state *s = (struct it8172_state *)file->private_data; + + lock_kernel(); + if (file->f_mode & FMODE_WRITE) + drain_dac(s, file->f_flags & O_NONBLOCK); + down(&s->open_sem); + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + dealloc_dmabuf(s, &s->dma_dac); + } + if (file->f_mode & FMODE_READ) { + stop_adc(s); + dealloc_dmabuf(s, &s->dma_adc); + } + s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); + up(&s->open_sem); + wake_up(&s->open_wait); + unlock_kernel(); + return 0; +} + +static /*const*/ struct file_operations it8172_audio_fops = { + owner: THIS_MODULE, + llseek: it8172_llseek, + read: it8172_read, + write: it8172_write, + poll: it8172_poll, + ioctl: it8172_ioctl, + mmap: it8172_mmap, + open: it8172_open, + release: it8172_release, +}; + + +/* --------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------- */ + +/* + * for debugging purposes, we'll create a proc device that dumps the + * CODEC chipstate + */ + +#ifdef IT8172_DEBUG +static int proc_it8172_dump (char *buf, char **start, off_t fpos, + int length, int *eof, void *data) +{ + struct it8172_state *s; + int cnt, len = 0; + + if (list_empty(&devs)) + return 0; + s = list_entry(devs.next, struct it8172_state, devs); + + /* print out header */ + len += sprintf(buf + len, "\n\t\tIT8172 Audio Debug\n\n"); + + // print out digital controller state + len += sprintf (buf + len, "IT8172 Audio Controller registers\n"); + len += sprintf (buf + len, "---------------------------------\n"); + cnt=0; + while (cnt < 0x72) { + if (cnt == IT_AC_PCB1STA || cnt == IT_AC_PCB2STA || + cnt == IT_AC_CAPB1STA || cnt == IT_AC_CAPB2STA || + cnt == IT_AC_PFDP) { + len+= sprintf (buf + len, "reg %02x = %08x\n", + cnt, inl(s->io+cnt)); + cnt += 4; + } else { + len+= sprintf (buf + len, "reg %02x = %04x\n", + cnt, inw(s->io+cnt)); + cnt += 2; + } + } + + /* print out CODEC state */ + len += sprintf (buf + len, "\nAC97 CODEC registers\n"); + len += sprintf (buf + len, "----------------------\n"); + for (cnt=0; cnt <= 0x7e; cnt = cnt +2) + len+= sprintf (buf + len, "reg %02x = %04x\n", + cnt, rdcodec(&s->codec, cnt)); + + if (fpos >=len){ + *start = buf; + *eof =1; + return 0; + } + *start = buf + fpos; + if ((len -= fpos) > length) + return length; + *eof =1; + return len; + +} +#endif /* IT8172_DEBUG */ + +/* --------------------------------------------------------------------- */ + +/* maximum number of devices; only used for command line params */ +#define NR_DEVICE 5 + +static int spdif[NR_DEVICE] = { 0, }; + +static unsigned int devindex = 0; + +MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i"); +MODULE_PARM_DESC(spdif, "if 1 the S/PDIF digital output is enabled"); + +MODULE_AUTHOR("Monta Vista Software, stevel@mvista.com"); +MODULE_DESCRIPTION("IT8172 AudioPCI97 Driver"); + +/* --------------------------------------------------------------------- */ + +static int __devinit it8172_probe(struct pci_dev *pcidev, + const struct pci_device_id *pciid) +{ + struct it8172_state *s; + int i, val; + unsigned short pcisr, vol; + unsigned char legacy, imc; + char proc_str[80]; + + if (pcidev->irq == 0) + return -1; + + if (!(s = kmalloc(sizeof(struct it8172_state), GFP_KERNEL))) { + printk(KERN_ERR PFX "alloc of device struct failed\n"); + return -1; + } + + memset(s, 0, sizeof(struct it8172_state)); + init_waitqueue_head(&s->dma_adc.wait); + init_waitqueue_head(&s->dma_dac.wait); + init_waitqueue_head(&s->open_wait); + init_MUTEX(&s->open_sem); + spin_lock_init(&s->lock); + s->dev = pcidev; + s->io = pci_resource_start(pcidev, 0); + s->irq = pcidev->irq; + s->vendor = pcidev->vendor; + s->device = pcidev->device; + pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev); + s->codec.private_data = s; + s->codec.id = 0; + s->codec.codec_read = rdcodec; + s->codec.codec_write = wrcodec; + s->codec.codec_wait = waitcodec; + + if (!request_region(s->io, pci_resource_len(pcidev,0), + IT8172_MODULE_NAME)) { + printk(KERN_ERR PFX "io ports %#lx->%#lx in use\n", + s->io, s->io + pci_resource_len(pcidev,0)-1); + goto err_region; + } + if (request_irq(s->irq, it8172_interrupt, SA_INTERRUPT, + IT8172_MODULE_NAME, s)) { + printk(KERN_ERR PFX "irq %u in use\n", s->irq); + goto err_irq; + } + + printk(KERN_INFO PFX "IO at %#lx, IRQ %d\n", s->io, s->irq); + + /* register devices */ + if ((s->dev_audio = register_sound_dsp(&it8172_audio_fops, -1)) < 0) + goto err_dev1; + if ((s->codec.dev_mixer = + register_sound_mixer(&it8172_mixer_fops, -1)) < 0) + goto err_dev2; + +#ifdef IT8172_DEBUG + /* intialize the debug proc device */ + s->ps = create_proc_read_entry(IT8172_MODULE_NAME, 0, NULL, + proc_it8172_dump, NULL); +#endif /* IT8172_DEBUG */ + + /* + * Reset the Audio device using the IT8172 PCI Reset register. This + * creates an audible double click on a speaker connected to Line-out. + */ + IT_IO_READ16(IT_PM_PCISR, pcisr); + pcisr |= IT_PM_PCISR_ACSR; + IT_IO_WRITE16(IT_PM_PCISR, pcisr); + /* wait up to 100msec for reset to complete */ + for (i=0; pcisr & IT_PM_PCISR_ACSR; i++) { + it8172_delay(10); + if (i == 10) + break; + IT_IO_READ16(IT_PM_PCISR, pcisr); + } + if (i == 10) { + printk(KERN_ERR PFX "chip reset timeout!\n"); + goto err_dev3; + } + + /* enable pci io and bus mastering */ + if (pci_enable_device(pcidev)) + goto err_dev3; + pci_set_master(pcidev); + + /* get out of legacy mode */ + pci_read_config_byte (pcidev, 0x40, &legacy); + pci_write_config_byte (pcidev, 0x40, legacy & ~1); + + s->spdif_volume = -1; + /* check to see if s/pdif mode is being requested */ + if (spdif[devindex]) { + printk(KERN_INFO PFX "enabling S/PDIF output\n"); + s->spdif_volume = 0; + outb(GC_SOE, s->io+IT_AC_GC); + } else { + printk(KERN_INFO PFX "disabling S/PDIF output\n"); + outb(0, s->io+IT_AC_GC); + } + + /* cold reset the AC97 */ + outw(CODECC_CR, s->io+IT_AC_CODECC); + udelay(1000); + outw(0, s->io+IT_AC_CODECC); + /* need to delay around 500msec(bleech) to give + some CODECs enough time to wakeup */ + it8172_delay(500); + + /* AC97 warm reset to start the bitclk */ + outw(CODECC_WR, s->io+IT_AC_CODECC); + udelay(1000); + outw(0, s->io+IT_AC_CODECC); + + /* codec init */ + if (!ac97_probe_codec(&s->codec)) + goto err_dev3; + + /* Enable Volume button interrupts */ + imc = inb(s->io+IT_AC_IMC); + outb(imc & ~IMC_VCIM, s->io+IT_AC_IMC); + + /* Un-mute PCM and FM out on the controller */ + vol = inw(s->io+IT_AC_PCMOV); + outw(vol & ~PCMOV_PCMOM, s->io+IT_AC_PCMOV); + vol = inw(s->io+IT_AC_FMOV); + outw(vol & ~FMOV_FMOM, s->io+IT_AC_FMOV); + + /* set channel defaults to 8-bit, mono, 8 Khz */ + s->pcc = 0; + s->capcc = 0; + set_dac_rate(s, 8000); + set_adc_rate(s, 8000); + + /* set mic to be the recording source */ + val = SOUND_MASK_MIC; + mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); + + /* mute master and PCM when in S/PDIF mode */ + if (s->spdif_volume != -1) { + val = 0x0000; + mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_VOLUME, + (unsigned long)&val); + mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_PCM, + (unsigned long)&val); + } + +#ifdef IT8172_DEBUG + sprintf(proc_str, "driver/%s/%d/ac97", IT8172_MODULE_NAME, s->codec.id); + s->ac97_ps = create_proc_read_entry (proc_str, 0, NULL, + ac97_read_proc, &s->codec); +#endif + + /* store it in the driver field */ + pci_set_drvdata(pcidev, s); + pcidev->dma_mask = 0xffffffff; + /* put it into driver list */ + list_add_tail(&s->devs, &devs); + /* increment devindex */ + if (devindex < NR_DEVICE-1) + devindex++; + return 0; + + err_dev3: + unregister_sound_mixer(s->codec.dev_mixer); + err_dev2: + unregister_sound_dsp(s->dev_audio); + err_dev1: + printk(KERN_ERR PFX "cannot register misc device\n"); + free_irq(s->irq, s); + err_irq: + release_region(s->io, pci_resource_len(pcidev,0)); + err_region: + kfree(s); + return -1; +} + +static void __devinit it8172_remove(struct pci_dev *dev) +{ + struct it8172_state *s = pci_get_drvdata(dev); + + if (!s) + return; + list_del(&s->devs); +#ifdef IT8172_DEBUG + if (s->ps) + remove_proc_entry(IT8172_MODULE_NAME, NULL); +#endif /* IT8172_DEBUG */ + synchronize_irq(); + free_irq(s->irq, s); + release_region(s->io, pci_resource_len(dev,0)); + unregister_sound_dsp(s->dev_audio); + unregister_sound_mixer(s->codec.dev_mixer); + kfree(s); + pci_set_drvdata(dev, NULL); +} + + + +static struct pci_device_id id_table[] __devinitdata = { + { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G_AUDIO, PCI_ANY_ID, + PCI_ANY_ID, 0, 0 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, id_table); + +static struct pci_driver it8172_driver = { + name: IT8172_MODULE_NAME, + id_table: id_table, + probe: it8172_probe, + remove: it8172_remove +}; + +static int __init init_it8172(void) +{ + if (!pci_present()) /* No PCI bus in this machine! */ + return -ENODEV; + printk("version v0.26 time " __TIME__ " " __DATE__ "\n"); + return pci_module_init(&it8172_driver); +} + +static void __exit cleanup_it8172(void) +{ + printk(KERN_INFO PFX "unloading\n"); + pci_unregister_driver(&it8172_driver); +} + +module_init(init_it8172); +module_exit(cleanup_it8172); + diff -u --recursive --new-file v2.4.9/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c --- v2.4.9/linux/drivers/sound/msnd_pinnacle.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/sound/msnd_pinnacle.c Fri Sep 7 09:28:37 2001 @@ -29,7 +29,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: msnd_pinnacle.c,v 1.75 1999/03/21 16:50:09 andrewtv Exp $ + * $Id: msnd_pinnacle.c,v 1.8 2000/12/30 00:33:21 sycamore Exp $ + * + * 12-3-2000 Modified IO port validation Steve Sycamore + * + * + * $$$: msnd_pinnacle.c,v 1.75 1999/03/21 16:50:09 andrewtv $$$ $ * ********************************************************************/ @@ -1703,6 +1708,7 @@ if (io == -1 || irq == -1 || mem == -1) printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); +#ifdef MSND_CLASSIC if (io == -1 || !(io == 0x290 || io == 0x260 || @@ -1715,6 +1721,15 @@ printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, or 0x3E0\n"); return -EINVAL; } +#else + if (io == -1 || + io < 0x100 || + io > 0x3e0 || + (io % 0x10) != 0) { + printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must within the range 0x100 to 0x3E0 and must be evenly divisible by 0x10\n"); + return -EINVAL; + } +#endif /* MSND_CLASSIC */ if (irq == -1 || !(irq == 5 || diff -u --recursive --new-file v2.4.9/linux/drivers/sound/nec_vrc5477.c linux/drivers/sound/nec_vrc5477.c --- v2.4.9/linux/drivers/sound/nec_vrc5477.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/nec_vrc5477.c Fri Sep 7 09:28:37 2001 @@ -0,0 +1,2044 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * drivers/sound/nec_vrc5477.c + * AC97 sound dirver for NEC Vrc5477 chip (an integrated, + * multi-function controller chip for MIPS CPUs) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + *********************************************************************** + */ + +/* + * This code is derived from ite8172.c, which is written by Steve Longerbeam. + * + * Features: + * Currently we only support the following capabilities: + * . mono output to PCM L/R (line out). + * . stereo output to PCM L/R (line out). + * . mono input from PCM L (line in). + * . stereo output from PCM (line in). + * . sampling rate at 48k or variable sampling rate + * . support /dev/dsp, /dev/mixer devices, standard OSS devices. + * . only support 16-bit PCM format (hardware limit, no software + * translation) + * . support duplex, but no trigger or realtime. + * + * Specifically the following are not supported: + * . app-set frag size. + * . mmap'ed buffer access + */ + +/* + * Original comments from ite8172.c file. + */ + +/* + * + * Notes: + * + * 1. Much of the OSS buffer allocation, ioctl's, and mmap'ing are + * taken, slightly modified or not at all, from the ES1371 driver, + * so refer to the credits in es1371.c for those. The rest of the + * code (probe, open, read, write, the ISR, etc.) is new. + * 2. The following support is untested: + * * Memory mapping the audio buffers, and the ioctl controls that go + * with it. + * * S/PDIF output. + * 3. The following is not supported: + * * I2S input. + * * legacy audio mode. + * 4. Support for volume button interrupts is implemented but doesn't + * work yet. + * + * Revision history + * 02.08.2001 0.1 Initial release + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef VRC5477_AC97_VERBOSE_DEBUG + +/* one must turn on CONFIG_LL_DEBUG before VERBOSE_DEBUG is turned */ +#if defined(VRC5477_AC97_VERBOSE_DEBUG) +#if !defined(CONFIG_LL_DEBUG) +#error "You must turn CONFIG_LL_DEBUG" +#endif +#endif + +#if defined(VRC5477_AC97_VERBOSE_DEBUG) +static u16 inTicket=0; /* check sync between intr & write */ +static u16 outTicket=0; +#endif + +/* --------------------------------------------------------------------- */ + +#undef OSS_DOCUMENTED_MIXER_SEMANTICS + +static const unsigned sample_shift[] = { 0, 1, 1, 2 }; + +#define VRC5477_INT_CLR 0x0 +#define VRC5477_INT_STATUS 0x0 +#define VRC5477_CODEC_WR 0x4 +#define VRC5477_CODEC_RD 0x8 +#define VRC5477_CTRL 0x18 +#define VRC5477_ACLINK_CTRL 0x1c +#define VRC5477_INT_MASK 0x24 + +#define VRC5477_DAC1_CTRL 0x30 +#define VRC5477_DAC1L 0x34 +#define VRC5477_DAC1_BADDR 0x38 +#define VRC5477_DAC2_CTRL 0x3c +#define VRC5477_DAC2L 0x40 +#define VRC5477_DAC2_BADDR 0x44 +#define VRC5477_DAC3_CTRL 0x48 +#define VRC5477_DAC3L 0x4c +#define VRC5477_DAC3_BADDR 0x50 + +#define VRC5477_ADC1_CTRL 0x54 +#define VRC5477_ADC1L 0x58 +#define VRC5477_ADC1_BADDR 0x5c +#define VRC5477_ADC2_CTRL 0x60 +#define VRC5477_ADC2L 0x64 +#define VRC5477_ADC2_BADDR 0x68 +#define VRC5477_ADC3_CTRL 0x6c +#define VRC5477_ADC3L 0x70 +#define VRC5477_ADC3_BADDR 0x74 + +#define VRC5477_CODEC_WR_RWC (1 << 23) + +#define VRC5477_CODEC_RD_RRDYA (1 << 31) +#define VRC5477_CODEC_RD_RRDYD (1 << 30) + +#define VRC5477_ACLINK_CTRL_RST_ON (1 << 15) +#define VRC5477_ACLINK_CTRL_RST_TIME 0x7f +#define VRC5477_ACLINK_CTRL_SYNC_ON (1 << 30) +#define VRC5477_ACLINK_CTRL_CK_STOP_ON (1 << 31) + +#define VRC5477_CTRL_DAC2ENB (1 << 15) +#define VRC5477_CTRL_ADC2ENB (1 << 14) +#define VRC5477_CTRL_DAC1ENB (1 << 13) +#define VRC5477_CTRL_ADC1ENB (1 << 12) + +#define VRC5477_INT_MASK_NMASK (1 << 31) +#define VRC5477_INT_MASK_DAC1END (1 << 5) +#define VRC5477_INT_MASK_DAC2END (1 << 4) +#define VRC5477_INT_MASK_DAC3END (1 << 3) +#define VRC5477_INT_MASK_ADC1END (1 << 2) +#define VRC5477_INT_MASK_ADC2END (1 << 1) +#define VRC5477_INT_MASK_ADC3END (1 << 0) + +#define VRC5477_DMA_ACTIVATION (1 << 31) +#define VRC5477_DMA_WIP (1 << 30) + + +#define VRC5477_AC97_MODULE_NAME "NEC_Vrc5477_audio" +#define PFX VRC5477_AC97_MODULE_NAME ": " + +/* --------------------------------------------------------------------- */ + +struct vrc5477_ac97_state { + /* list of vrc5477_ac97 devices */ + struct list_head devs; + + /* the corresponding pci_dev structure */ + struct pci_dev *dev; + + /* soundcore stuff */ + int dev_audio; + + /* hardware resources */ + unsigned long io; + unsigned int irq; + +#ifdef CONFIG_LL_DEBUG + /* debug /proc entry */ + struct proc_dir_entry *ps; + struct proc_dir_entry *ac97_ps; +#endif /* CONFIG_LL_DEBUG */ + + struct ac97_codec codec; + + unsigned dacChannels, adcChannels; + unsigned short dacRate, adcRate; + + spinlock_t lock; + struct semaphore open_sem; + mode_t open_mode; + wait_queue_head_t open_wait; + + struct dmabuf { + void *lbuf, *rbuf; + dma_addr_t lbufDma, rbufDma; + unsigned bufOrder; + unsigned numFrag; + unsigned fragShift; + unsigned fragSize; /* redundant */ + unsigned fragTotalSize; /* = numFrag * fragSize(real) */ + unsigned nextIn; + unsigned nextOut; + int count; + unsigned error; /* over/underrun */ + wait_queue_head_t wait; + /* OSS stuff */ + unsigned stopped:1; + unsigned ready:1; + } dma_dac, dma_adc; + + #define WORK_BUF_SIZE 2048 + struct { + u16 lchannel; + u16 rchannel; + } workBuf[WORK_BUF_SIZE/4]; +}; + +/* --------------------------------------------------------------------- */ + +static LIST_HEAD(devs); + +/* --------------------------------------------------------------------- */ + +extern inline unsigned ld2(unsigned int x) +{ + unsigned r = 0; + + if (x >= 0x10000) { + x >>= 16; + r += 16; + } + if (x >= 0x100) { + x >>= 8; + r += 8; + } + if (x >= 0x10) { + x >>= 4; + r += 4; + } + if (x >= 4) { + x >>= 2; + r += 2; + } + if (x >= 2) + r++; + return r; +} + +/* --------------------------------------------------------------------- */ + +static u16 rdcodec(struct ac97_codec *codec, u8 addr) +{ + struct vrc5477_ac97_state *s = + (struct vrc5477_ac97_state *)codec->private_data; + unsigned long flags; + u32 result; + + spin_lock_irqsave(&s->lock, flags); + + /* wait until we can access codec registers */ + while (inl(s->io + VRC5477_CODEC_WR) & 0x80000000); + + /* write the address and "read" command to codec */ + addr = addr & 0x7f; + outl((addr << 16) | VRC5477_CODEC_WR_RWC, s->io + VRC5477_CODEC_WR); + + /* get the return result */ + udelay(100); /* workaround hardware bug */ + while ( (result = inl(s->io + VRC5477_CODEC_RD)) & + (VRC5477_CODEC_RD_RRDYA | VRC5477_CODEC_RD_RRDYD) ) { + /* we get either addr or data, or both */ + if (result & VRC5477_CODEC_RD_RRDYA) { + MIPS_ASSERT(addr == ((result >> 16) & 0x7f) ); + } + if (result & VRC5477_CODEC_RD_RRDYD) { + break; + } + } + + spin_unlock_irqrestore(&s->lock, flags); + + return result & 0xffff;; +} + + +static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data) +{ + struct vrc5477_ac97_state *s = + (struct vrc5477_ac97_state *)codec->private_data; + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + + /* wait until we can access codec registers */ + while (inl(s->io + VRC5477_CODEC_WR) & 0x80000000); + + /* write the address and value to codec */ + outl((addr << 16) | data, s->io + VRC5477_CODEC_WR); + + spin_unlock_irqrestore(&s->lock, flags); +} + + +static void waitcodec(struct ac97_codec *codec) +{ + struct vrc5477_ac97_state *s = + (struct vrc5477_ac97_state *)codec->private_data; + + /* wait until we can access codec registers */ + while (inl(s->io + VRC5477_CODEC_WR) & 0x80000000); +} + + +/* --------------------------------------------------------------------- */ + +static void vrc5477_ac97_delay(int msec) +{ + unsigned long tmo; + signed long tmo2; + + if (in_interrupt()) + return; + + tmo = jiffies + (msec*HZ)/1000; + for (;;) { + tmo2 = tmo - jiffies; + if (tmo2 <= 0) + break; + schedule_timeout(tmo2); + } +} + + +static void set_adc_rate(struct vrc5477_ac97_state *s, unsigned rate) +{ + wrcodec(&s->codec, AC97_PCM_LR_ADC_RATE, rate); + s->adcRate = rate; +} + + +static void set_dac_rate(struct vrc5477_ac97_state *s, unsigned rate) +{ + wrcodec(&s->codec, AC97_PCM_FRONT_DAC_RATE, rate); + s->dacRate = rate; +} + + +/* --------------------------------------------------------------------- */ + +extern inline void +stop_dac(struct vrc5477_ac97_state *s) +{ + struct dmabuf* db = &s->dma_dac; + unsigned long flags; + u32 temp; + + spin_lock_irqsave(&s->lock, flags); + + if (db->stopped) { + spin_unlock_irqrestore(&s->lock, flags); + return; + } + + /* deactivate the dma */ + outl(0, s->io + VRC5477_DAC1_CTRL); + outl(0, s->io + VRC5477_DAC2_CTRL); + + /* wait for DAM completely stop */ + while (inl(s->io + VRC5477_DAC1_CTRL) & VRC5477_DMA_WIP); + while (inl(s->io + VRC5477_DAC2_CTRL) & VRC5477_DMA_WIP); + + /* disable dac slots in aclink */ + temp = inl(s->io + VRC5477_CTRL); + temp &= ~ (VRC5477_CTRL_DAC1ENB | VRC5477_CTRL_DAC2ENB); + outl (temp, s->io + VRC5477_CTRL); + + /* disable interrupts */ + temp = inl(s->io + VRC5477_INT_MASK); + temp &= ~ (VRC5477_INT_MASK_DAC1END | VRC5477_INT_MASK_DAC2END); + outl (temp, s->io + VRC5477_INT_MASK); + + /* clear pending ones */ + outl(VRC5477_INT_MASK_DAC1END | VRC5477_INT_MASK_DAC2END, + s->io + VRC5477_INT_CLR); + + db->stopped = 1; + + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_dac(struct vrc5477_ac97_state *s) +{ + struct dmabuf* db = &s->dma_dac; + unsigned long flags; + u32 dmaLength; + u32 temp; + + spin_lock_irqsave(&s->lock, flags); + + if (!db->stopped) { + spin_unlock_irqrestore(&s->lock, flags); + return; + } + + /* we should have some data to do the DMA trasnfer */ + MIPS_ASSERT(db->count >= db->fragSize); + + /* clear pending fales interrupts */ + outl(VRC5477_INT_MASK_DAC1END | VRC5477_INT_MASK_DAC2END, + s->io + VRC5477_INT_CLR); + + /* enable interrupts */ + temp = inl(s->io + VRC5477_INT_MASK); + temp |= VRC5477_INT_MASK_DAC1END | VRC5477_INT_MASK_DAC2END; + outl(temp, s->io + VRC5477_INT_MASK); + + /* setup dma base addr */ + outl(db->lbufDma + db->nextOut, s->io + VRC5477_DAC1_BADDR); + if (s->dacChannels == 1) { + outl(db->lbufDma + db->nextOut, s->io + VRC5477_DAC2_BADDR); + } else { + outl(db->rbufDma + db->nextOut, s->io + VRC5477_DAC2_BADDR); + } + + /* set dma length, in the unit of 0x10 bytes */ + dmaLength = db->fragSize >> 4; + outl(dmaLength, s->io + VRC5477_DAC1L); + outl(dmaLength, s->io + VRC5477_DAC2L); + + /* activate dma */ + outl(VRC5477_DMA_ACTIVATION, s->io + VRC5477_DAC1_CTRL); + outl(VRC5477_DMA_ACTIVATION, s->io + VRC5477_DAC2_CTRL); + + /* enable dac slots - we should hear the music now! */ + temp = inl(s->io + VRC5477_CTRL); + temp |= (VRC5477_CTRL_DAC1ENB | VRC5477_CTRL_DAC2ENB); + outl (temp, s->io + VRC5477_CTRL); + + /* it is time to setup next dma transfer */ + MIPS_ASSERT(inl(s->io + VRC5477_DAC1_CTRL) & VRC5477_DMA_WIP); + MIPS_ASSERT(inl(s->io + VRC5477_DAC2_CTRL) & VRC5477_DMA_WIP); + + temp = db->nextOut + db->fragSize; + if (temp >= db->fragTotalSize) { + MIPS_ASSERT(temp == db->fragTotalSize); + temp = 0; + } + + outl(db->lbufDma + temp, s->io + VRC5477_DAC1_BADDR); + if (s->dacChannels == 1) { + outl(db->lbufDma + temp, s->io + VRC5477_DAC2_BADDR); + } else { + outl(db->rbufDma + temp, s->io + VRC5477_DAC2_BADDR); + } + + db->stopped = 0; + +#if defined(VRC5477_AC97_VERBOSE_DEBUG) + outTicket = *(u16*)(db->lbuf+db->nextOut); + if (db->count > db->fragSize) { + MIPS_ASSERT((u16)(outTicket+1) == *(u16*)(db->lbuf+temp)); + } +#endif + + spin_unlock_irqrestore(&s->lock, flags); +} + +extern inline void stop_adc(struct vrc5477_ac97_state *s) +{ + struct dmabuf* db = &s->dma_adc; + unsigned long flags; + u32 temp; + + spin_lock_irqsave(&s->lock, flags); + + if (db->stopped) { + spin_unlock_irqrestore(&s->lock, flags); + return; + } + + /* deactivate the dma */ + outl(0, s->io + VRC5477_ADC1_CTRL); + outl(0, s->io + VRC5477_ADC2_CTRL); + + /* disable adc slots in aclink */ + temp = inl(s->io + VRC5477_CTRL); + temp &= ~ (VRC5477_CTRL_ADC1ENB | VRC5477_CTRL_ADC2ENB); + outl (temp, s->io + VRC5477_CTRL); + + /* disable interrupts */ + temp = inl(s->io + VRC5477_INT_MASK); + temp &= ~ (VRC5477_INT_MASK_ADC1END | VRC5477_INT_MASK_ADC2END); + outl (temp, s->io + VRC5477_INT_MASK); + + /* clear pending ones */ + outl(VRC5477_INT_MASK_ADC1END | VRC5477_INT_MASK_ADC2END, + s->io + VRC5477_INT_CLR); + + db->stopped = 1; + + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_adc(struct vrc5477_ac97_state *s) +{ + struct dmabuf* db = &s->dma_adc; + unsigned long flags; + u32 dmaLength; + u32 temp; + + spin_lock_irqsave(&s->lock, flags); + + if (!db->stopped) { + spin_unlock_irqrestore(&s->lock, flags); + return; + } + + /* we should at least have some free space in the buffer */ + MIPS_ASSERT(db->count < db->fragTotalSize - db->fragSize * 2); + + /* clear pending ones */ + outl(VRC5477_INT_MASK_ADC1END | VRC5477_INT_MASK_ADC2END, + s->io + VRC5477_INT_CLR); + + /* enable interrupts */ + temp = inl(s->io + VRC5477_INT_MASK); + temp |= VRC5477_INT_MASK_ADC1END | VRC5477_INT_MASK_ADC2END; + outl(temp, s->io + VRC5477_INT_MASK); + + /* setup dma base addr */ + outl(db->lbufDma + db->nextIn, s->io + VRC5477_ADC1_BADDR); + outl(db->rbufDma + db->nextIn, s->io + VRC5477_ADC2_BADDR); + + /* setup dma length */ + dmaLength = db->fragSize >> 4; + outl(dmaLength, s->io + VRC5477_ADC1L); + outl(dmaLength, s->io + VRC5477_ADC2L); + + /* activate dma */ + outl(VRC5477_DMA_ACTIVATION, s->io + VRC5477_ADC1_CTRL); + outl(VRC5477_DMA_ACTIVATION, s->io + VRC5477_ADC2_CTRL); + + /* enable adc slots */ + temp = inl(s->io + VRC5477_CTRL); + temp |= (VRC5477_CTRL_ADC1ENB | VRC5477_CTRL_ADC2ENB); + outl (temp, s->io + VRC5477_CTRL); + + /* it is time to setup next dma transfer */ + temp = db->nextIn + db->fragSize; + if (temp >= db->fragTotalSize) { + MIPS_ASSERT(temp == db->fragTotalSize); + temp = 0; + } + outl(db->lbufDma + temp, s->io + VRC5477_ADC1_BADDR); + outl(db->rbufDma + temp, s->io + VRC5477_ADC2_BADDR); + + db->stopped = 0; + + spin_unlock_irqrestore(&s->lock, flags); +} + +/* --------------------------------------------------------------------- */ + +#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) +#define DMABUF_MINORDER 1 + +extern inline void dealloc_dmabuf(struct vrc5477_ac97_state *s, + struct dmabuf *db) +{ + if (db->lbuf) { + MIPS_ASSERT(db->rbuf); + pci_free_consistent(s->dev, PAGE_SIZE << db->bufOrder, + db->lbuf, db->lbufDma); + pci_free_consistent(s->dev, PAGE_SIZE << db->bufOrder, + db->rbuf, db->rbufDma); + db->lbuf = db->rbuf = NULL; + } + db->nextIn = db->nextOut = 0; + db->ready = 0; +} + +static int prog_dmabuf(struct vrc5477_ac97_state *s, + struct dmabuf *db, + unsigned rate) +{ + int order; + unsigned bufsize; + + if (!db->lbuf) { + MIPS_ASSERT(!db->rbuf); + + db->ready = 0; + for (order = DMABUF_DEFAULTORDER; + order >= DMABUF_MINORDER; + order--) { + db->lbuf = pci_alloc_consistent(s->dev, + PAGE_SIZE << order, + &db->lbufDma); + db->rbuf = pci_alloc_consistent(s->dev, + PAGE_SIZE << order, + &db->rbufDma); + if (db->lbuf && db->rbuf) break; + if (db->lbuf) { + MIPS_ASSERT(!db->rbuf); + pci_free_consistent(s->dev, + PAGE_SIZE << order, + db->lbuf, + db->lbufDma); + } + } + if (!db->lbuf) { + MIPS_ASSERT(!db->rbuf); + return -ENOMEM; + } + + db->bufOrder = order; + } + + db->count = 0; + db->nextIn = db->nextOut = 0; + + bufsize = PAGE_SIZE << db->bufOrder; + db->fragShift = ld2(rate * 2 / 100); + if (db->fragShift < 4) db->fragShift = 4; + + db->numFrag = bufsize >> db->fragShift; + while (db->numFrag < 4 && db->fragShift > 4) { + db->fragShift--; + db->numFrag = bufsize >> db->fragShift; + } + db->fragSize = 1 << db->fragShift; + db->fragTotalSize = db->numFrag << db->fragShift; + memset(db->lbuf, 0, db->fragTotalSize); + memset(db->rbuf, 0, db->fragTotalSize); + + db->ready = 1; + + return 0; +} + +extern inline int prog_dmabuf_adc(struct vrc5477_ac97_state *s) +{ + stop_adc(s); + return prog_dmabuf(s, &s->dma_adc, s->adcRate); +} + +extern inline int prog_dmabuf_dac(struct vrc5477_ac97_state *s) +{ + stop_dac(s); + return prog_dmabuf(s, &s->dma_dac, s->dacRate); +} + + +/* --------------------------------------------------------------------- */ +/* hold spinlock for the following! */ + +static inline void vrc5477_ac97_adc_interrupt(struct vrc5477_ac97_state *s) +{ + struct dmabuf* adc = &s->dma_adc; + unsigned temp; + + /* we need two frags avaiable because one is already being used + * and the other will be used when next interrupt happens. + */ + if (adc->count >= adc->fragTotalSize - adc->fragSize) { + stop_adc(s); + adc->error++; + printk(KERN_INFO PFX "adc overrun\n"); + return; + } + + /* set the base addr for next DMA transfer */ + temp = adc->nextIn + 2*adc->fragSize; + if (temp >= adc->fragTotalSize) { + MIPS_ASSERT( (temp == adc->fragTotalSize) || + (temp == adc->fragTotalSize + adc->fragSize) ); + temp -= adc->fragTotalSize; + } + outl(adc->lbufDma + temp, s->io + VRC5477_ADC1_BADDR); + outl(adc->rbufDma + temp, s->io + VRC5477_ADC2_BADDR); + + /* adjust nextIn */ + adc->nextIn += adc->fragSize; + if (adc->nextIn >= adc->fragTotalSize) { + MIPS_ASSERT(adc->nextIn == adc->fragTotalSize); + adc->nextIn = 0; + } + + /* adjust count */ + adc->count += adc->fragSize; + + /* wake up anybody listening */ + if (waitqueue_active(&adc->wait)) { + wake_up_interruptible(&adc->wait); + } +} + +static inline void vrc5477_ac97_dac_interrupt(struct vrc5477_ac97_state *s) +{ + struct dmabuf* dac = &s->dma_dac; + unsigned temp; + + /* next DMA transfer should already started */ + MIPS_ASSERT(inl(s->io + VRC5477_DAC1_CTRL) & VRC5477_DMA_WIP); + MIPS_ASSERT(inl(s->io + VRC5477_DAC2_CTRL) & VRC5477_DMA_WIP); + + /* let us set for next next DMA transfer */ + temp = dac->nextOut + dac->fragSize*2; + if (temp >= dac->fragTotalSize) { + MIPS_ASSERT( (temp == dac->fragTotalSize) || + (temp == dac->fragTotalSize + dac->fragSize) ); + temp -= dac->fragTotalSize; + } + outl(dac->lbufDma + temp, s->io + VRC5477_DAC1_BADDR); + if (s->dacChannels == 1) { + outl(dac->lbufDma + temp, s->io + VRC5477_DAC2_BADDR); + } else { + outl(dac->rbufDma + temp, s->io + VRC5477_DAC2_BADDR); + } + +#if defined(VRC5477_AC97_VERBOSE_DEBUG) + if (*(u16*)(dac->lbuf + dac->nextOut) != outTicket) { + printk("assert fail: - %d vs %d\n", + *(u16*)(dac->lbuf + dac->nextOut), + outTicket); + MIPS_ASSERT(1 == 0); + } +#endif + + /* adjust nextOut pointer */ + dac->nextOut += dac->fragSize; + if (dac->nextOut >= dac->fragTotalSize) { + MIPS_ASSERT(dac->nextOut == dac->fragTotalSize); + dac->nextOut = 0; + } + + /* adjust count */ + dac->count -= dac->fragSize; + if (dac->count <=0 ) { + MIPS_ASSERT(dac->count == 0); + MIPS_ASSERT(dac->nextIn == dac->nextOut); + /* buffer under run */ + stop_dac(s); + } + +#if defined(VRC5477_AC97_VERBOSE_DEBUG) + if (dac->count) { + outTicket ++; + MIPS_ASSERT(*(u16*)(dac->lbuf + dac->nextOut) == outTicket); + } +#endif + + /* we cannot have both under run and someone is waiting on us */ + MIPS_ASSERT(! (waitqueue_active(&dac->wait) && (dac->count <= 0)) ); + + /* wake up anybody listening */ + if (waitqueue_active(&dac->wait)) + wake_up_interruptible(&dac->wait); +} + +static void vrc5477_ac97_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct vrc5477_ac97_state *s = (struct vrc5477_ac97_state *)dev_id; + u32 irqStatus; + u32 adcInterrupts, dacInterrupts; + + spin_lock(&s->lock); + + /* get irqStatus and clear the detected ones */ + irqStatus = inl(s->io + VRC5477_INT_STATUS); + outl(irqStatus, s->io + VRC5477_INT_CLR); + + /* let us see what we get */ + dacInterrupts = VRC5477_INT_MASK_DAC1END | VRC5477_INT_MASK_DAC2END; + adcInterrupts = VRC5477_INT_MASK_ADC1END | VRC5477_INT_MASK_ADC2END; + if (irqStatus & dacInterrupts) { + /* we should get both interrupts, but just in case ... */ + if (irqStatus & VRC5477_INT_MASK_DAC1END) { + vrc5477_ac97_dac_interrupt(s); + } + if ( (irqStatus & dacInterrupts) != dacInterrupts ) { + printk(KERN_WARNING "vrc5477_ac97 : dac interrupts not in sync!!!\n"); + stop_dac(s); + start_dac(s); + } + } else if (irqStatus & adcInterrupts) { + /* we should get both interrupts, but just in case ... */ + if(irqStatus & VRC5477_INT_MASK_ADC1END) { + vrc5477_ac97_adc_interrupt(s); + } + if ( (irqStatus & adcInterrupts) != adcInterrupts ) { + printk(KERN_WARNING "vrc5477_ac97 : adc interrupts not in sync!!!\n"); + stop_adc(s); + start_adc(s); + } + } + + spin_unlock(&s->lock); +} + +/* --------------------------------------------------------------------- */ + +static loff_t vrc5477_ac97_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + + +static int vrc5477_ac97_open_mixdev(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct list_head *list; + struct vrc5477_ac97_state *s; + + for (list = devs.next; ; list = list->next) { + if (list == &devs) + return -ENODEV; + s = list_entry(list, struct vrc5477_ac97_state, devs); + if (s->codec.dev_mixer == minor) + break; + } + file->private_data = s; + return 0; +} + +static int vrc5477_ac97_release_mixdev(struct inode *inode, struct file *file) +{ + return 0; +} + + +static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, + unsigned long arg) +{ + return codec->mixer_ioctl(codec, cmd, arg); +} + +static int vrc5477_ac97_ioctl_mixdev(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct vrc5477_ac97_state *s = + (struct vrc5477_ac97_state *)file->private_data; + struct ac97_codec *codec = &s->codec; + + return mixdev_ioctl(codec, cmd, arg); +} + +static /*const*/ struct file_operations vrc5477_ac97_mixer_fops = { + owner: THIS_MODULE, + llseek: vrc5477_ac97_llseek, + ioctl: vrc5477_ac97_ioctl_mixdev, + open: vrc5477_ac97_open_mixdev, + release: vrc5477_ac97_release_mixdev, +}; + +/* --------------------------------------------------------------------- */ + +static int drain_dac(struct vrc5477_ac97_state *s, int nonblock) +{ + unsigned long flags; + int count, tmo; + + if (!s->dma_dac.ready) + return 0; + + for (;;) { + spin_lock_irqsave(&s->lock, flags); + count = s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + if (count <= 0) + break; + if (signal_pending(current)) + break; + if (nonblock) + return -EBUSY; + tmo = 1000 * count / s->dacRate / 2; + vrc5477_ac97_delay(tmo); + } + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int inline +copy_two_channel_adc_to_user(struct vrc5477_ac97_state *s, + char *buffer, + int copyCount) +{ + struct dmabuf *db = &s->dma_adc; + int bufStart = db->nextOut; + for (; copyCount > 0; ) { + int i; + int count = copyCount; + if (count > WORK_BUF_SIZE/2) count = WORK_BUF_SIZE/2; + for (i=0; i< count/2; i++) { + s->workBuf[i].lchannel = + *(u16*)(db->lbuf + bufStart + i*2); + s->workBuf[i].rchannel = + *(u16*)(db->rbuf + bufStart + i*2); + } + if (copy_to_user(buffer, s->workBuf, count*2)) { + return -1; + } + + copyCount -= count; + bufStart += count; + MIPS_ASSERT(bufStart <= db->fragTotalSize); + buffer += count *2; + } + return 0; +} + +/* return the total bytes that is copied */ +static int inline +copy_adc_to_user(struct vrc5477_ac97_state *s, + char * buffer, + size_t count, + int avail) +{ + struct dmabuf *db = &s->dma_adc; + int copyCount=0; + int copyFragCount=0; + int totalCopyCount = 0; + int totalCopyFragCount = 0; + unsigned long flags; + + /* adjust count to signel channel byte count */ + count >>= s->adcChannels - 1; + + /* we may have to "copy" twice as ring buffer wraps around */ + for (; (avail > 0) && (count > 0); ) { + /* determine max possible copy count for single channel */ + copyCount = count; + if (copyCount > avail) { + copyCount = avail; + } + if (copyCount + db->nextOut > db->fragTotalSize) { + copyCount = db->fragTotalSize - db->nextOut; + MIPS_ASSERT((copyCount % db->fragSize) == 0); + } + + copyFragCount = (copyCount-1) >> db->fragShift; + copyFragCount = (copyFragCount+1) << db->fragShift; + MIPS_ASSERT(copyFragCount >= copyCount); + + /* we copy differently based on adc channels */ + if (s->adcChannels == 1) { + if (copy_to_user(buffer, + db->lbuf + db->nextOut, + copyCount)) + return -1; + } else { + /* *sigh* we have to mix two streams into one */ + if (copy_two_channel_adc_to_user(s, buffer, copyCount)) + return -1; + } + + count -= copyCount; + totalCopyCount += copyCount; + avail -= copyFragCount; + totalCopyFragCount += copyFragCount; + + buffer += copyCount << (s->adcChannels-1); + + db->nextOut += copyFragCount; + if (db->nextOut >= db->fragTotalSize) { + MIPS_ASSERT(db->nextOut == db->fragTotalSize); + db->nextOut = 0; + } + + MIPS_ASSERT((copyFragCount % db->fragSize) == 0); + MIPS_ASSERT( (count == 0) || (copyCount == copyFragCount)); + } + + spin_lock_irqsave(&s->lock, flags); + db->count -= totalCopyFragCount; + spin_unlock_irqrestore(&s->lock, flags); + + return totalCopyCount << (s->adcChannels-1); +} + +static ssize_t +vrc5477_ac97_read(struct file *file, + char *buffer, + size_t count, + loff_t *ppos) +{ + struct vrc5477_ac97_state *s = + (struct vrc5477_ac97_state *)file->private_data; + struct dmabuf *db = &s->dma_adc; + ssize_t ret = 0; + unsigned long flags; + int copyCount; + size_t avail; + + if (ppos != &file->f_pos) + return -ESPIPE; + if (!access_ok(VERIFY_WRITE, buffer, count)) + return -EFAULT; + + MIPS_ASSERT(db->ready); + + while (count > 0) { + // wait for samples in capture buffer + do { + spin_lock_irqsave(&s->lock, flags); + if (db->stopped) + start_adc(s); + avail = db->count; + spin_unlock_irqrestore(&s->lock, flags); + if (avail <= 0) { + if (file->f_flags & O_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + return ret; + } + interruptible_sleep_on(&db->wait); + if (signal_pending(current)) { + if (!ret) + ret = -ERESTARTSYS; + return ret; + } + } + } while (avail <= 0); + + MIPS_ASSERT( (avail % db->fragSize) == 0); + copyCount = copy_adc_to_user(s, buffer, count, avail); + if (copyCount <=0 ) { + if (!ret) ret = -EFAULT; + return ret; + } + + count -= copyCount; + buffer += copyCount; + ret += copyCount; + } // while (count > 0) + + return ret; +} + +static int inline +copy_two_channel_dac_from_user(struct vrc5477_ac97_state *s, + const char *buffer, + int copyCount) +{ + struct dmabuf *db = &s->dma_dac; + int bufStart = db->nextIn; + + MIPS_ASSERT(db->ready); + + for (; copyCount > 0; ) { + int i; + int count = copyCount; + if (count > WORK_BUF_SIZE/2) count = WORK_BUF_SIZE/2; + if (copy_from_user(s->workBuf, buffer, count*2)) { + return -1; + } + for (i=0; i< count/2; i++) { + *(u16*)(db->lbuf + bufStart + i*2) = + s->workBuf[i].lchannel; + *(u16*)(db->rbuf + bufStart + i*2) = + s->workBuf[i].rchannel; + } + + copyCount -= count; + bufStart += count; + MIPS_ASSERT(bufStart <= db->fragTotalSize); + buffer += count *2; + } + return 0; + +} + +/* return the total bytes that is copied */ +static int inline +copy_dac_from_user(struct vrc5477_ac97_state *s, + const char *buffer, + size_t count, + int avail) +{ + struct dmabuf *db = &s->dma_dac; + int copyCount=0; + int copyFragCount=0; + int totalCopyCount = 0; + int totalCopyFragCount = 0; + unsigned long flags; +#if defined(VRC5477_AC97_VERBOSE_DEBUG) + int i; +#endif + + /* adjust count to signel channel byte count */ + count >>= s->dacChannels - 1; + + /* we may have to "copy" twice as ring buffer wraps around */ + for (; (avail > 0) && (count > 0); ) { + /* determine max possible copy count for single channel */ + copyCount = count; + if (copyCount > avail) { + copyCount = avail; + } + if (copyCount + db->nextIn > db->fragTotalSize) { + copyCount = db->fragTotalSize - db->nextIn; + MIPS_ASSERT((copyCount % db->fragSize) == 0); + MIPS_ASSERT(copyCount > 0); + } + + copyFragCount = (copyCount-1) >> db->fragShift; + copyFragCount = (copyFragCount+1) << db->fragShift; + MIPS_ASSERT(copyFragCount >= copyCount); + + /* we copy differently based on the number channels */ + if (s->dacChannels == 1) { + if (copy_from_user(db->lbuf + db->nextIn, + buffer, + copyCount)) + return -1; + /* fill gaps with 0 */ + memset(db->lbuf + db->nextIn + copyCount, + 0, + copyFragCount - copyCount); + } else { + /* we have demux the stream into two separate ones */ + if (copy_two_channel_dac_from_user(s, buffer, copyCount)) + return -1; + /* fill gaps with 0 */ + memset(db->lbuf + db->nextIn + copyCount, + 0, + copyFragCount - copyCount); + memset(db->rbuf + db->nextIn + copyCount, + 0, + copyFragCount - copyCount); + } + +#if defined(VRC5477_AC97_VERBOSE_DEBUG) + for (i=0; i< copyFragCount; i+= db->fragSize) { + *(u16*)(db->lbuf + db->nextIn + i) = inTicket ++; + } +#endif + + count -= copyCount; + totalCopyCount =+ copyCount; + avail -= copyFragCount; + totalCopyFragCount += copyFragCount; + + buffer += copyCount << (s->dacChannels - 1); + + db->nextIn += copyFragCount; + if (db->nextIn >= db->fragTotalSize) { + MIPS_ASSERT(db->nextIn == db->fragTotalSize); + db->nextIn = 0; + } + + MIPS_ASSERT((copyFragCount % db->fragSize) == 0); + MIPS_ASSERT( (count == 0) || (copyCount == copyFragCount)); + } + + spin_lock_irqsave(&s->lock, flags); + db->count += totalCopyFragCount; + if (db->stopped) { + start_dac(s); + } + + /* nextIn should not be equal to nextOut unless we are full */ + MIPS_ASSERT( ( (db->count == db->fragTotalSize) && + (db->nextIn == db->nextOut) ) || + ( (db->count < db->fragTotalSize) && + (db->nextIn != db->nextOut) ) ); + + spin_unlock_irqrestore(&s->lock, flags); + + return totalCopyCount << (s->dacChannels-1); + +} + +static ssize_t vrc5477_ac97_write(struct file *file, const char *buffer, + size_t count, loff_t *ppos) +{ + struct vrc5477_ac97_state *s = + (struct vrc5477_ac97_state *)file->private_data; + struct dmabuf *db = &s->dma_dac; + ssize_t ret; + unsigned long flags; + int copyCount, avail; + + if (ppos != &file->f_pos) + return -ESPIPE; + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; + ret = 0; + + while (count > 0) { + // wait for space in playback buffer + do { + spin_lock_irqsave(&s->lock, flags); + avail = db->fragTotalSize - db->count; + spin_unlock_irqrestore(&s->lock, flags); + if (avail <= 0) { + if (file->f_flags & O_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + return ret; + } + interruptible_sleep_on(&db->wait); + if (signal_pending(current)) { + if (!ret) + ret = -ERESTARTSYS; + return ret; + } + } + } while (avail <= 0); + + MIPS_ASSERT( (avail % db->fragSize) == 0); + copyCount = copy_dac_from_user(s, buffer, count, avail); + if (copyCount < 0) { + if (!ret) ret = -EFAULT; + return ret; + } + + count -= copyCount; + buffer += copyCount; + ret += copyCount; + } // while (count > 0) + + return ret; +} + +/* No kernel lock - we have our own spinlock */ +static unsigned int vrc5477_ac97_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct vrc5477_ac97_state *s = (struct vrc5477_ac97_state *)file->private_data; + unsigned long flags; + unsigned int mask = 0; + + if (file->f_mode & FMODE_WRITE) + poll_wait(file, &s->dma_dac.wait, wait); + if (file->f_mode & FMODE_READ) + poll_wait(file, &s->dma_adc.wait, wait); + spin_lock_irqsave(&s->lock, flags); + if (file->f_mode & FMODE_READ) { + if (s->dma_adc.count >= (signed)s->dma_adc.fragSize) + mask |= POLLIN | POLLRDNORM; + } + if (file->f_mode & FMODE_WRITE) { + if ((signed)s->dma_dac.fragTotalSize >= + s->dma_dac.count + (signed)s->dma_dac.fragSize) + mask |= POLLOUT | POLLWRNORM; + } + spin_unlock_irqrestore(&s->lock, flags); + return mask; +} + +#ifdef CONFIG_LL_DEBUG +static struct ioctl_str_t { + unsigned int cmd; + const char* str; +} ioctl_str[] = { + {SNDCTL_DSP_RESET, "SNDCTL_DSP_RESET"}, + {SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC"}, + {SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED"}, + {SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO"}, + {SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE"}, + {SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT"}, + {SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE"}, + {SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS"}, + {SOUND_PCM_WRITE_CHANNELS, "SOUND_PCM_WRITE_CHANNELS"}, + {SOUND_PCM_WRITE_FILTER, "SOUND_PCM_WRITE_FILTER"}, + {SNDCTL_DSP_POST, "SNDCTL_DSP_POST"}, + {SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE"}, + {SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT"}, + {SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS"}, + {SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE"}, + {SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE"}, + {SNDCTL_DSP_NONBLOCK, "SNDCTL_DSP_NONBLOCK"}, + {SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_GETCAPS"}, + {SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER"}, + {SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER"}, + {SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR"}, + {SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR"}, + {SNDCTL_DSP_MAPINBUF, "SNDCTL_DSP_MAPINBUF"}, + {SNDCTL_DSP_MAPOUTBUF, "SNDCTL_DSP_MAPOUTBUF"}, + {SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO"}, + {SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX"}, + {SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY"}, + {SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK"}, + {SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL"}, + {OSS_GETVERSION, "OSS_GETVERSION"}, + {SOUND_PCM_READ_RATE, "SOUND_PCM_READ_RATE"}, + {SOUND_PCM_READ_CHANNELS, "SOUND_PCM_READ_CHANNELS"}, + {SOUND_PCM_READ_BITS, "SOUND_PCM_READ_BITS"}, + {SOUND_PCM_READ_FILTER, "SOUND_PCM_READ_FILTER"} +}; +#endif + +static int vrc5477_ac97_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct vrc5477_ac97_state *s = (struct vrc5477_ac97_state *)file->private_data; + unsigned long flags; + audio_buf_info abinfo; + int count; + int val, ret; + +#ifdef CONFIG_LL_DEBUG + for (count=0; countf_mode & FMODE_WRITE) + return drain_dac(s, file->f_flags & O_NONBLOCK); + return 0; + + case SNDCTL_DSP_SETDUPLEX: + return 0; + + case SNDCTL_DSP_GETCAPS: + return put_user(DSP_CAP_DUPLEX, (int *)arg); + + case SNDCTL_DSP_RESET: + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + synchronize_irq(); + s->dma_dac.count = 0; + s->dma_dac.nextIn = s->dma_dac.nextOut = 0; + } + if (file->f_mode & FMODE_READ) { + stop_adc(s); + synchronize_irq(); + s->dma_adc.count = 0; + s->dma_adc.nextIn = s->dma_adc.nextOut = 0; + } + return 0; + + case SNDCTL_DSP_SPEED: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val >= 0) { + if (file->f_mode & FMODE_READ) { + stop_adc(s); + set_adc_rate(s, val); + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + set_dac_rate(s, val); + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + } + return put_user((file->f_mode & FMODE_READ) ? + s->adcRate : s->dacRate, (int *)arg); + + case SNDCTL_DSP_STEREO: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (file->f_mode & FMODE_READ) { + stop_adc(s); + if (val) + s->adcChannels = 2; + else + s->adcChannels = 1; + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + if (val) + s->dacChannels = 2; + else + s->dacChannels = 1; + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + return 0; + + case SNDCTL_DSP_CHANNELS: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val != 0) { + if ( (val != 1) && (val != 2)) val = 2; + + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dacChannels = val; + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dacChannels = val; + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + } + return put_user(val, (int *)arg); + + case SNDCTL_DSP_GETFMTS: /* Returns a mask */ + return put_user(AFMT_S16_LE, (int *)arg); + + case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val != AFMT_QUERY) { + if (val != AFMT_S16_LE) return -EINVAL; + if (file->f_mode & FMODE_READ) { + stop_adc(s); + if ((ret = prog_dmabuf_adc(s))) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + if ((ret = prog_dmabuf_dac(s))) + return ret; + } + } else { + val = AFMT_S16_LE; + } + return put_user(val, (int *)arg); + + case SNDCTL_DSP_POST: + return 0; + + case SNDCTL_DSP_GETTRIGGER: + case SNDCTL_DSP_SETTRIGGER: + /* NO trigger */ + return -EINVAL; + + case SNDCTL_DSP_GETOSPACE: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + abinfo.fragsize = s->dma_dac.fragSize << (s->dacChannels-1); + spin_lock_irqsave(&s->lock, flags); + count = s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + abinfo.bytes = (s->dma_dac.fragTotalSize - count) << + (s->dacChannels-1); + abinfo.fragstotal = s->dma_dac.numFrag; + abinfo.fragments = abinfo.bytes >> s->dma_dac.fragShift >> + (s->dacChannels-1); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + + case SNDCTL_DSP_GETISPACE: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + abinfo.fragsize = s->dma_adc.fragSize << (s->adcChannels-1); + spin_lock_irqsave(&s->lock, flags); + count = s->dma_adc.count; + spin_unlock_irqrestore(&s->lock, flags); + if (count < 0) + count = 0; + abinfo.bytes = count << (s->adcChannels-1); + abinfo.fragstotal = s->dma_adc.numFrag; + abinfo.fragments = (abinfo.bytes >> s->dma_adc.fragShift) >> + (s->adcChannels-1); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; + + case SNDCTL_DSP_GETODELAY: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + count = s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + return put_user(count, (int *)arg); + + case SNDCTL_DSP_GETIPTR: + case SNDCTL_DSP_GETOPTR: + /* we cannot get DMA ptr */ + return -EINVAL; + + case SNDCTL_DSP_GETBLKSIZE: + if (file->f_mode & FMODE_WRITE) + return put_user(s->dma_dac.fragSize << (s->dacChannels-1), (int *)arg); + else + return put_user(s->dma_adc.fragSize << (s->adcChannels-1), (int *)arg); + + case SNDCTL_DSP_SETFRAGMENT: + /* we ignore fragment size request */ + return 0; + + case SNDCTL_DSP_SUBDIVIDE: + /* what is this for? [jsun] */ + return 0; + + case SOUND_PCM_READ_RATE: + return put_user((file->f_mode & FMODE_READ) ? + s->adcRate : s->dacRate, (int *)arg); + + case SOUND_PCM_READ_CHANNELS: + if (file->f_mode & FMODE_READ) + return put_user(s->adcChannels, (int *)arg); + else + return put_user(s->dacChannels ? 2 : 1, (int *)arg); + + case SOUND_PCM_READ_BITS: + return put_user(16, (int *)arg); + + case SOUND_PCM_WRITE_FILTER: + case SNDCTL_DSP_SETSYNCRO: + case SOUND_PCM_READ_FILTER: + return -EINVAL; + } + + return mixdev_ioctl(&s->codec, cmd, arg); +} + + +static int vrc5477_ac97_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + struct list_head *list; + struct vrc5477_ac97_state *s; + int ret=0; + + for (list = devs.next; ; list = list->next) { + if (list == &devs) + return -ENODEV; + s = list_entry(list, struct vrc5477_ac97_state, devs); + if (!((s->dev_audio ^ minor) & ~0xf)) + break; + } + file->private_data = s; + + /* wait for device to become free */ + down(&s->open_sem); + while (s->open_mode & file->f_mode) { + + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem); + return -EBUSY; + } + add_wait_queue(&s->open_wait, &wait); + __set_current_state(TASK_INTERRUPTIBLE); + up(&s->open_sem); + schedule(); + remove_wait_queue(&s->open_wait, &wait); + set_current_state(TASK_RUNNING); + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem); + } + + spin_lock_irqsave(&s->lock, flags); + + if (file->f_mode & FMODE_READ) { + /* set default settings */ + set_adc_rate(s, 48000); + s->adcChannels = 2; + + ret = prog_dmabuf_adc(s); + if (ret) goto bailout; + } + if (file->f_mode & FMODE_WRITE) { + /* set default settings */ + set_dac_rate(s, 48000); + s->dacChannels = 2; + + ret = prog_dmabuf_dac(s); + if (ret) goto bailout; + } + + s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); + + bailout: + spin_unlock_irqrestore(&s->lock, flags); + + up(&s->open_sem); + return ret; +} + +static int vrc5477_ac97_release(struct inode *inode, struct file *file) +{ + struct vrc5477_ac97_state *s = + (struct vrc5477_ac97_state *)file->private_data; + + lock_kernel(); + if (file->f_mode & FMODE_WRITE) + drain_dac(s, file->f_flags & O_NONBLOCK); + down(&s->open_sem); + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + dealloc_dmabuf(s, &s->dma_dac); + } + if (file->f_mode & FMODE_READ) { + stop_adc(s); + dealloc_dmabuf(s, &s->dma_adc); + } + s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); + up(&s->open_sem); + wake_up(&s->open_wait); + unlock_kernel(); + return 0; +} + +static /*const*/ struct file_operations vrc5477_ac97_audio_fops = { + owner: THIS_MODULE, + llseek: vrc5477_ac97_llseek, + read: vrc5477_ac97_read, + write: vrc5477_ac97_write, + poll: vrc5477_ac97_poll, + ioctl: vrc5477_ac97_ioctl, + // mmap: vrc5477_ac97_mmap, + open: vrc5477_ac97_open, + release: vrc5477_ac97_release, +}; + + +/* --------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------- */ + +/* + * for debugging purposes, we'll create a proc device that dumps the + * CODEC chipstate + */ + +#ifdef CONFIG_LL_DEBUG + +struct { + const char *regname; + unsigned regaddr; +} vrc5477_ac97_regs[] = { + {"VRC5477_INT_STATUS", VRC5477_INT_STATUS}, + {"VRC5477_CODEC_WR", VRC5477_CODEC_WR}, + {"VRC5477_CODEC_RD", VRC5477_CODEC_RD}, + {"VRC5477_CTRL", VRC5477_CTRL}, + {"VRC5477_ACLINK_CTRL", VRC5477_ACLINK_CTRL}, + {"VRC5477_INT_MASK", VRC5477_INT_MASK}, + {"VRC5477_DAC1_CTRL", VRC5477_DAC1_CTRL}, + {"VRC5477_DAC1L", VRC5477_DAC1L}, + {"VRC5477_DAC1_BADDR", VRC5477_DAC1_BADDR}, + {"VRC5477_DAC2_CTRL", VRC5477_DAC2_CTRL}, + {"VRC5477_DAC2L", VRC5477_DAC2L}, + {"VRC5477_DAC2_BADDR", VRC5477_DAC2_BADDR}, + {"VRC5477_DAC3_CTRL", VRC5477_DAC3_CTRL}, + {"VRC5477_DAC3L", VRC5477_DAC3L}, + {"VRC5477_DAC3_BADDR", VRC5477_DAC3_BADDR}, + {"VRC5477_ADC1_CTRL", VRC5477_ADC1_CTRL}, + {"VRC5477_ADC1L", VRC5477_ADC1L}, + {"VRC5477_ADC1_BADDR", VRC5477_ADC1_BADDR}, + {"VRC5477_ADC2_CTRL", VRC5477_ADC2_CTRL}, + {"VRC5477_ADC2L", VRC5477_ADC2L}, + {"VRC5477_ADC2_BADDR", VRC5477_ADC2_BADDR}, + {"VRC5477_ADC3_CTRL", VRC5477_ADC3_CTRL}, + {"VRC5477_ADC3L", VRC5477_ADC3L}, + {"VRC5477_ADC3_BADDR", VRC5477_ADC3_BADDR}, + {NULL, 0x0} +}; + +static int proc_vrc5477_ac97_dump (char *buf, char **start, off_t fpos, + int length, int *eof, void *data) +{ + struct vrc5477_ac97_state *s; + int cnt, len = 0; + + if (list_empty(&devs)) + return 0; + s = list_entry(devs.next, struct vrc5477_ac97_state, devs); + + /* print out header */ + len += sprintf(buf + len, "\n\t\tVrc5477 Audio Debug\n\n"); + + // print out digital controller state + len += sprintf (buf + len, "NEC Vrc5477 Audio Controller registers\n"); + len += sprintf (buf + len, "---------------------------------\n"); + for (cnt=0; vrc5477_ac97_regs[cnt].regname != NULL; cnt++) { + len+= sprintf (buf + len, "%-20s = %08x\n", + vrc5477_ac97_regs[cnt].regname, + inl(s->io + vrc5477_ac97_regs[cnt].regaddr)); + } + + /* print out driver state */ + len += sprintf (buf + len, "NEC Vrc5477 Audio driver states\n"); + len += sprintf (buf + len, "---------------------------------\n"); + len += sprintf (buf + len, "dacChannels = %d\n", s->dacChannels); + len += sprintf (buf + len, "adcChannels = %d\n", s->adcChannels); + len += sprintf (buf + len, "dacRate = %d\n", s->dacRate); + len += sprintf (buf + len, "adcRate = %d\n", s->adcRate); + + len += sprintf (buf + len, "dma_dac is %s ready\n", + s->dma_dac.ready? "" : "not"); + if (s->dma_dac.ready) { + len += sprintf (buf + len, "dma_dac is %s stopped.\n", + s->dma_dac.stopped? "" : "not"); + len += sprintf (buf + len, "dma_dac.fragSize = %x\n", + s->dma_dac.fragSize); + len += sprintf (buf + len, "dma_dac.fragShift = %x\n", + s->dma_dac.fragShift); + len += sprintf (buf + len, "dma_dac.numFrag = %x\n", + s->dma_dac.numFrag); + len += sprintf (buf + len, "dma_dac.fragTotalSize = %x\n", + s->dma_dac.fragTotalSize); + len += sprintf (buf + len, "dma_dac.nextIn = %x\n", + s->dma_dac.nextIn); + len += sprintf (buf + len, "dma_dac.nextOut = %x\n", + s->dma_dac.nextOut); + len += sprintf (buf + len, "dma_dac.count = %x\n", + s->dma_dac.count); + } + + len += sprintf (buf + len, "dma_adc is %s ready\n", + s->dma_adc.ready? "" : "not"); + if (s->dma_adc.ready) { + len += sprintf (buf + len, "dma_adc is %s stopped.\n", + s->dma_adc.stopped? "" : "not"); + len += sprintf (buf + len, "dma_adc.fragSize = %x\n", + s->dma_adc.fragSize); + len += sprintf (buf + len, "dma_adc.fragShift = %x\n", + s->dma_adc.fragShift); + len += sprintf (buf + len, "dma_adc.numFrag = %x\n", + s->dma_adc.numFrag); + len += sprintf (buf + len, "dma_adc.fragTotalSize = %x\n", + s->dma_adc.fragTotalSize); + len += sprintf (buf + len, "dma_adc.nextIn = %x\n", + s->dma_adc.nextIn); + len += sprintf (buf + len, "dma_adc.nextOut = %x\n", + s->dma_adc.nextOut); + len += sprintf (buf + len, "dma_adc.count = %x\n", + s->dma_adc.count); + } + + /* print out CODEC state */ + len += sprintf (buf + len, "\nAC97 CODEC registers\n"); + len += sprintf (buf + len, "----------------------\n"); + for (cnt=0; cnt <= 0x7e; cnt = cnt +2) + len+= sprintf (buf + len, "reg %02x = %04x\n", + cnt, rdcodec(&s->codec, cnt)); + + if (fpos >=len){ + *start = buf; + *eof =1; + return 0; + } + *start = buf + fpos; + if ((len -= fpos) > length) + return length; + *eof =1; + return len; + +} +#endif /* CONFIG_LL_DEBUG */ + +/* --------------------------------------------------------------------- */ + +/* maximum number of devices; only used for command line params */ +#define NR_DEVICE 5 + +static unsigned int devindex = 0; + +MODULE_AUTHOR("Monta Vista Software, jsun@mvista.com or jsun@junsun.net"); +MODULE_DESCRIPTION("NEC Vrc5477 audio (AC97) Driver"); + +/* --------------------------------------------------------------------- */ +extern void jsun_scan_pci_bus(void); +extern void vrc5477_show_pci_regs(void); +extern void vrc5477_show_pdar_regs(void); + +/* -------------------------------------------------------- */ +#define AC97_BASE 0xbb000000 +#define myinl(x) *(volatile u32*)(AC97_BASE + (x)) +#define myoutl(x,y) *(volatile u32*)(AC97_BASE + (y)) = (x) + +u16 myrdcodec(u8 addr) +{ + u32 result; + + /* wait until we can access codec registers */ + // while (inl(VRC5477_CODEC_WR) & 0x80000000); + + /* write the address and "read" command to codec */ + addr = addr & 0x7f; + myoutl((addr << 16) | VRC5477_CODEC_WR_RWC, VRC5477_CODEC_WR); + + /* get the return result */ + udelay(100); /* workaround hardware bug */ + // dump_memory(0xbb000000, 48); + while ( ((result=myinl(VRC5477_CODEC_RD)) & 0xc0000000) != 0xc0000000); + MIPS_ASSERT(addr == ((result >> 16) & 0x7f) ); + return result & 0xffff; +} + +void mywrcodec(u8 addr, u16 data) +{ + /* wait until we can access codec registers */ + while (myinl(VRC5477_CODEC_WR) & 0x80000000); + + /* write the address and value to codec */ + myoutl((addr << 16) | data, VRC5477_CODEC_WR); + +} + + +void jsun_ac97_test(struct vrc5477_ac97_state *s) +{ + int i; + + /* reset codec */ + /* + wrcodec(&s->codec, 0, 0); + while (inl(s->io + VRC5477_CODEC_WR) & 0x80000000); + */ + mywrcodec(0, 0); + while (myinl(VRC5477_CODEC_WR) & 0x80000000); + + for (i=0; i< 0x40; i+=4) { + MIPS_ASSERT(inl(s->io+i) == myinl(i)); + } + + printk("codec registers : "); + for (i=0; i<= 0x3a; i+=2) { + if ( (i%0x10) == 0) { + printk("\n%02x\t", i); + } + // printk("%04x\t", rdcodec(&s->codec, i)); + printk("%04x\t", myrdcodec(i)); + } + printk("\n\n"); + printk("codec registers : "); + for (i=0; i<= 0x3a; i+=2) { + if ( (i%0x10) == 0) { + printk("\n%02x\t", i); + } + printk("%04x\t", rdcodec(&s->codec, i)); + } + printk("\n\n"); +} + +static int __devinit vrc5477_ac97_probe(struct pci_dev *pcidev, + const struct pci_device_id *pciid) +{ + struct vrc5477_ac97_state *s; + char proc_str[80]; + + MIPS_DEBUG(printk("vrc5477_ac97_probe() invoked\n")); + + if (pcidev->irq == 0) + return -1; + + if (!(s = kmalloc(sizeof(struct vrc5477_ac97_state), GFP_KERNEL))) { + printk(KERN_ERR PFX "alloc of device struct failed\n"); + return -1; + } + memset(s, 0, sizeof(struct vrc5477_ac97_state)); + + init_waitqueue_head(&s->dma_adc.wait); + init_waitqueue_head(&s->dma_dac.wait); + init_waitqueue_head(&s->open_wait); + init_MUTEX(&s->open_sem); + spin_lock_init(&s->lock); + + s->dev = pcidev; + s->io = pci_resource_start(pcidev, 0); + s->irq = pcidev->irq; + + s->codec.private_data = s; + s->codec.id = 0; + s->codec.codec_read = rdcodec; + s->codec.codec_write = wrcodec; + s->codec.codec_wait = waitcodec; + + /* setting some other default values such as + * adcChannels, adcRate is done in open() so that + * no persistent state across file opens. + */ + + if (!request_region(s->io, pci_resource_len(pcidev,0), + VRC5477_AC97_MODULE_NAME)) { + printk(KERN_ERR PFX "io ports %#lx->%#lx in use\n", + s->io, s->io + pci_resource_len(pcidev,0)-1); + goto err_region; + } + if (request_irq(s->irq, vrc5477_ac97_interrupt, SA_INTERRUPT, + VRC5477_AC97_MODULE_NAME, s)) { + printk(KERN_ERR PFX "irq %u in use\n", s->irq); + goto err_irq; + } + + printk(KERN_INFO PFX "IO at %#lx, IRQ %d\n", s->io, s->irq); + + /* register devices */ + if ((s->dev_audio = register_sound_dsp(&vrc5477_ac97_audio_fops, -1)) < 0) + goto err_dev1; + if ((s->codec.dev_mixer = + register_sound_mixer(&vrc5477_ac97_mixer_fops, -1)) < 0) + goto err_dev2; + +#ifdef CONFIG_LL_DEBUG + /* intialize the debug proc device */ + s->ps = create_proc_read_entry(VRC5477_AC97_MODULE_NAME, 0, NULL, + proc_vrc5477_ac97_dump, NULL); +#endif /* CONFIG_LL_DEBUG */ + + /* enable pci io and bus mastering */ + if (pci_enable_device(pcidev)) + goto err_dev3; + pci_set_master(pcidev); + +/* +jsun_scan_pci_bus(); +vrc5477_show_pci_regs(); +vrc5477_show_pdar_regs(); +*/ + + /* cold reset the AC97 */ + outl(VRC5477_ACLINK_CTRL_RST_ON | VRC5477_ACLINK_CTRL_RST_TIME, + s->io + VRC5477_ACLINK_CTRL); + while (inl(s->io + VRC5477_ACLINK_CTRL) & VRC5477_ACLINK_CTRL_RST_ON); + +/* +jsun_ac97_test(s); +*/ + + /* codec init */ + if (!ac97_probe_codec(&s->codec)) + goto err_dev3; + +#ifdef CONFIG_LL_DEBUG + sprintf(proc_str, "driver/%s/%d/ac97", + VRC5477_AC97_MODULE_NAME, s->codec.id); + s->ac97_ps = create_proc_read_entry (proc_str, 0, NULL, + ac97_read_proc, &s->codec); + /* TODO : why this proc file does not show up? */ +#endif + + /* let us get the default volumne louder */ + wrcodec(&s->codec, 0x2, 0); + wrcodec(&s->codec, 0x18, 0x0707); + /* mute line in loopback to line out */ + wrcodec(&s->codec, 0x10, 0x8000); + + /* by default we select line in the input */ + wrcodec(&s->codec, 0x1a, 0x0404); + /* pick middle value for record gain */ + // wrcodec(&s->codec, 0x1c, 0x0707); + wrcodec(&s->codec, 0x1c, 0x0f0f); + wrcodec(&s->codec, 0x1e, 0x07); + + /* enable the master interrupt but disable all others */ + outl(VRC5477_INT_MASK_NMASK, s->io + VRC5477_INT_MASK); + + /* store it in the driver field */ + pci_set_drvdata(pcidev, s); + pcidev->dma_mask = 0xffffffff; + /* put it into driver list */ + list_add_tail(&s->devs, &devs); + /* increment devindex */ + if (devindex < NR_DEVICE-1) + devindex++; + return 0; + + err_dev3: + unregister_sound_mixer(s->codec.dev_mixer); + err_dev2: + unregister_sound_dsp(s->dev_audio); + err_dev1: + printk(KERN_ERR PFX "cannot register misc device\n"); + free_irq(s->irq, s); + err_irq: + release_region(s->io, pci_resource_len(pcidev,0)); + err_region: + kfree(s); + return -1; +} + +static void __devinit vrc5477_ac97_remove(struct pci_dev *dev) +{ + struct vrc5477_ac97_state *s = pci_get_drvdata(dev); + + if (!s) + return; + list_del(&s->devs); +#ifdef CONFIG_LL_DEBUG + if (s->ps) + remove_proc_entry(VRC5477_AC97_MODULE_NAME, NULL); +#endif /* CONFIG_LL_DEBUG */ + synchronize_irq(); + free_irq(s->irq, s); + release_region(s->io, pci_resource_len(dev,0)); + unregister_sound_dsp(s->dev_audio); + unregister_sound_mixer(s->codec.dev_mixer); + kfree(s); + pci_set_drvdata(dev, NULL); +} + + +#define PCI_VENDOR_ID_NEC 0x1033 +#define PCI_DEVICE_ID_NEC_VRC5477_AC97 0x00A6 +static struct pci_device_id id_table[] __devinitdata = { + { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_VRC5477_AC97, + PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, id_table); + +static struct pci_driver vrc5477_ac97_driver = { + name: VRC5477_AC97_MODULE_NAME, + id_table: id_table, + probe: vrc5477_ac97_probe, + remove: vrc5477_ac97_remove +}; + +static int __init init_vrc5477_ac97(void) +{ + if (!pci_present()) /* No PCI bus in this machine! */ + return -ENODEV; + printk("Vrc5477 AC97 driver: version v0.1 time " __TIME__ " " __DATE__ " by Jun Sun\n"); + return pci_module_init(&vrc5477_ac97_driver); +} + +static void __exit cleanup_vrc5477_ac97(void) +{ + printk(KERN_INFO PFX "unloading\n"); + pci_unregister_driver(&vrc5477_ac97_driver); +} + +module_init(init_vrc5477_ac97); +module_exit(cleanup_vrc5477_ac97); + diff -u --recursive --new-file v2.4.9/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.4.9/linux/drivers/sound/sonicvibes.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/sonicvibes.c Fri Sep 7 09:28:37 2001 @@ -2496,7 +2496,7 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { - static const char __initdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; + static char __initdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; struct sv_state *s; mm_segment_t fs; int i, val, ret; diff -u --recursive --new-file v2.4.9/linux/drivers/sound/trident.c linux/drivers/sound/trident.c --- v2.4.9/linux/drivers/sound/trident.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/trident.c Fri Sep 7 09:28:37 2001 @@ -1,6 +1,10 @@ /* + * OSS driver for Linux 2.4.x for * - * Trident 4D-Wave/SiS 7018/ALi 5451 OSS driver for Linux 2.2.x + * Trident 4D-Wave + * SiS 7018 + * ALi 5451 + * Tvia/IGST CyberPro 5050 * * Driver: Alan Cox * @@ -14,6 +18,7 @@ * Ollie Lho SiS 7018 Audio Core Support * Ching-Ling Lee ALi 5451 Audio Core Support * Matt Wu ALi 5451 Audio Core Support + * Peter Wächtler CyberPro5050 support * * * This program is free software; you can redistribute it and/or modify @@ -31,6 +36,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.14.9c + * August 10 2001 Peter Wächtler + * added support for Tvia (formerly Integraphics/IGST) CyberPro5050 + * this chip is often found in settop boxes (combined video+audio) * v0.14.9b * Switch to static inline not extern inline (gcc 3) * v0.14.9a @@ -61,7 +70,7 @@ * Implement multi-channels and S/PDIF in support for ALi 1535+ * v0.14.6 * Nov 1 2000 Ching-Ling Lee - * Fix the bug of memory leak when swithing 5.1-channels to 2 channels. + * Fix the bug of memory leak when switching 5.1-channels to 2 channels. * Add lock protection into dynamic changing format of data. * Oct 18 2000 Ching-Ling Lee * 5.1-channels support for ALi @@ -167,7 +176,7 @@ #include -#define DRIVER_VERSION "0.14.9b" +#define DRIVER_VERSION "0.14.9c" /* magic numbers to protect our data structures */ #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -195,14 +204,16 @@ TRIDENT_4D_DX = 0, TRIDENT_4D_NX, SIS_7018, - ALI_5451 + ALI_5451, + CYBER5050 }; static char * card_names[] = { "Trident 4DWave DX", "Trident 4DWave NX", "SiS 7018 PCI Audio", - "ALi Audio Accelerator" + "ALi Audio Accelerator", + "Tvia/IGST CyberPro 5050" }; static struct pci_device_id trident_pci_tbl [] __devinitdata = { @@ -214,6 +225,8 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}, {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451}, + { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, CYBER5050}, {0,} }; @@ -456,6 +469,7 @@ case PCI_DEVICE_ID_ALI_5451: case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: + case PCI_DEVICE_ID_INTERG_5050: global_control |= (ENDLP_IE | MIDLP_IE); break; default: @@ -466,7 +480,7 @@ #ifdef DEBUG printk("trident: Enable Loop Interrupts, globctl = 0x%08X\n", - global_control); + inl(TRID_REG(card, T4D_LFO_GC_CIR))); #endif return (TRUE); } @@ -497,9 +511,9 @@ outl(reg, TRID_REG(card, addr)); #ifdef DEBUG - reg = inl(TRID_REG(card, T4D_AINTEN_B)); - printk("trident: enabled IRQ on channel %d, AINTEN_B = 0x%08x\n", - channel, reg); + reg = inl(TRID_REG(card, addr)); + printk("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); #endif } @@ -517,9 +531,9 @@ outl(mask, TRID_REG(card, bank->addresses->aint)); #ifdef DEBUG - reg = inl(TRID_REG(card, T4D_AINTEN_B)); - printk("trident: disabled IRQ on channel %d, AINTEN_B = 0x%08x\n", - channel, reg); + reg = inl(TRID_REG(card, addr)); + printk("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); #endif } @@ -536,9 +550,9 @@ outl(mask, TRID_REG(card, addr)); #ifdef DEBUG - reg = inl(TRID_REG(card, T4D_START_B)); - printk("trident: start voice on channel %d, START_B = 0x%08x\n", - channel, reg); + reg = inl(TRID_REG(card, addr)); + printk("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_START_B? "START_B":"START_A",reg,addr); #endif } @@ -555,9 +569,9 @@ outl(mask, TRID_REG(card, addr)); #ifdef DEBUG - reg = inl(TRID_REG(card, T4D_STOP_B)); - printk("trident: stop voice on channel %d, STOP_B = 0x%08x\n", - channel, reg); + reg = inl(TRID_REG(card, addr)); + printk("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_STOP_B? "STOP_B":"STOP_A",reg,addr); #endif } @@ -575,8 +589,8 @@ #ifdef DEBUG if (reg & mask) - printk("trident: channel %d has interrupt, AINT_B = 0x%08x\n", - channel, reg); + printk("trident: channel %d has interrupt, %s = 0x%08x\n", + channel,reg==T4D_AINT_B? "AINT_B":"AINT_A", reg); #endif return (reg & mask) ? TRUE : FALSE; } @@ -614,7 +628,7 @@ } } - /* no more free channels avaliable */ + /* no more free channels available */ printk(KERN_ERR "trident: no more channels available on Bank B.\n"); return NULL; } @@ -632,7 +646,94 @@ card->banks[bank].bitmap &= ~(1 << (channel)); } -/* called with spin lock held */ +static struct trident_channel * cyber_alloc_pcm_channel(struct trident_card *card) +{ + struct trident_pcm_bank *bank; + int idx; + + /* The cyberpro 5050 has only 32 voices and one bank */ + /* .. at least they are not documented (if you want to call that + * crap documentation), perhaps broken ? */ + + bank = &card->banks[BANK_A]; + + for (idx = 31; idx >= 0; idx--) { + if (!(bank->bitmap & (1 << idx))) { + struct trident_channel *channel = &bank->channels[idx]; + bank->bitmap |= 1 << idx; + channel->num = idx; + return channel; + } + } + + /* no more free channels available */ + printk(KERN_ERR "cyberpro5050: no more channels available on Bank A.\n"); + return NULL; +} + +static void cyber_free_pcm_channel(struct trident_card *card, unsigned int channel) +{ + if (channel > 31) + return; + card->banks[BANK_A].bitmap &= ~(1 << (channel)); +} + +static inline void cyber_outidx(int port,int idx,int data) +{ + outb(idx,port); + outb(data,port+1); +} + +static inline int cyber_inidx(int port,int idx) +{ + outb(idx,port); + return inb(port+1); +} + +static int cyber_init_ritual(struct trident_card *card) +{ + /* some black magic, taken from SDK samples */ + /* remove this and nothing will work */ + int portDat; + int ret = 0; + unsigned long flags; + + /* + * Keep interrupts off for the configure - we don't want to + * clash with another cyberpro config event + */ + + save_flags(flags); + cli(); + portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); + /* enable, if it was disabled */ + if( (portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE ) { + printk(KERN_INFO "cyberpro5050: enabling audio controller\n" ); + cyber_outidx( CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE, + portDat | CYBER_BMSK_AUENZ_ENABLE ); + /* check again if hardware is enabled now */ + portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); + } + if( (portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE ) + { + printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n" ); + ret = -1; + } + else + { + cyber_outidx( CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE, CYBER_BMSK_AUDIO_INT_ENABLE ); + cyber_outidx( CYBER_PORT_AUDIO, 0xbf, 0x01 ); + cyber_outidx( CYBER_PORT_AUDIO, 0xba, 0x20 ); + cyber_outidx( CYBER_PORT_AUDIO, 0xbb, 0x08 ); + cyber_outidx( CYBER_PORT_AUDIO, 0xbf, 0x02 ); + cyber_outidx( CYBER_PORT_AUDIO, 0xb3, 0x06 ); + cyber_outidx( CYBER_PORT_AUDIO, 0xbf, 0x00 ); + } + restore_flags(flags); + return ret; +} + +/* called with spin lock held */ static int trident_load_channel_registers(struct trident_card *card, u32 *data, unsigned int channel) { @@ -651,7 +752,8 @@ continue; outl(data[i], TRID_REG(card, CHANNEL_START + 4*i)); } - if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { + if (card->pci_id == PCI_DEVICE_ID_ALI_5451 || + card->pci_id == PCI_DEVICE_ID_INTERG_5050) { outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1)); outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2)); } @@ -677,6 +779,7 @@ data[3] = 0; break; case PCI_DEVICE_ID_SI_7018: + case PCI_DEVICE_ID_INTERG_5050: data[0] = 0; /* Current Sample Offset */ data[2] = (channel->eso << 16) | (channel->delta & 0xffff); data[3] = (channel->attribute << 16) | (channel->fm_vol & 0xffff); @@ -814,7 +917,7 @@ channel->control |= CHANNEL_STEREO; #ifdef DEBUG printk("trident: trident_play_setup, LBA = 0x%08x, " - "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", + "Delta = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", channel->lba, channel->delta, channel->eso, channel->control); #endif trident_write_voice_regs(state); @@ -852,6 +955,9 @@ /* enable and set record channel */ outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); break; + case PCI_DEVICE_ID_INTERG_5050: + /* don't know yet, using special channel 22 in GC1(0xd4)? */ + break; default: return; } @@ -920,6 +1026,7 @@ case PCI_DEVICE_ID_ALI_5451: case PCI_DEVICE_ID_SI_7018: case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: + case PCI_DEVICE_ID_INTERG_5050: /* 16 bits ESO, CSO for 7018 and DX */ cso = inw(TRID_REG(state->card, CH_DX_CSO_ALPHA_FMS + 2)); break; @@ -1271,7 +1378,8 @@ /* No matter how much data is left in the buffer, we have to wait until CSO == ESO/2 or CSO == ESO when address engine interrupts */ - if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) + if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 || + state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) { diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize ; diff = diff % (dmabuf->dmasize); @@ -1528,6 +1636,38 @@ ali_set_timer(card); } +static void cyber_address_interrupt(struct trident_card *card) +{ + int i,irq_status; + struct trident_state *state; + + /* Update the pointers for all channels we are running. */ + /* FIXED: read interrupt status only once */ + irq_status=inl(TRID_REG(card, T4D_AINT_A) ); +#ifdef DEBUG + printk("cyber_address_interrupt: irq_status 0x%X\n",irq_status); +#endif + for (i = 0; i < NR_HW_CH; i++) { + if (irq_status & ( 1 << (31 - i)) ) { + + /* clear bit by writing a 1, zeroes are ignored */ + outl( (1 <<(31-i)), TRID_REG(card, T4D_AINT_A)); + +#ifdef DEBUG + printk("cyber_interrupt: channel %d\n", 31-i); +#endif + if ((state = card->states[i]) != NULL) { + trident_update_ptr(state); + } else { + printk("cyber5050: spurious channel irq %d.\n", + 31 - i); + trident_stop_voice(card, 31 - i); + trident_disable_voice_irq(card, 31 - i); + } + } + } +} + static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct trident_card *card = (struct trident_card *)dev_id; @@ -2537,6 +2677,11 @@ drain_dac(state, file->f_flags & O_NONBLOCK); } +#ifdef DEBUG + printk(KERN_ERR "trident: closing virtual channel %d, hard channel %d\n", + state->virt, dmabuf->channel->num); +#endif + /* stop DMA state machine and free DMA buffers/channels */ down(&card->open_sem); @@ -2626,6 +2771,12 @@ mask |= NX_AC97_WRITE_SECONDARY; busy = NX_AC97_BUSY_WRITE; break; + case PCI_DEVICE_ID_INTERG_5050: + address = SI_AC97_WRITE; + mask = busy = SI_AC97_BUSY_WRITE; + if (codec->id) + mask |= SI_AC97_SECONDARY; + break; } spin_lock_irqsave(&card->lock, flags); @@ -2678,6 +2829,12 @@ mask = NX_AC97_BUSY_READ; busy = NX_AC97_BUSY_READ | NX_AC97_BUSY_DATA; break; + case PCI_DEVICE_ID_INTERG_5050: + address = SI_AC97_READ; + mask = busy = SI_AC97_BUSY_READ; + if (codec->id) + mask |= SI_AC97_SECONDARY; + break; } data = (mask | (reg & AC97_REG_ADDR)); @@ -3707,6 +3864,18 @@ ready_2nd = inl(TRID_REG(card, NX_ACR0_AC97_COM_STAT)); ready_2nd &= NX_AC97_SECONDARY_READY; break; + case PCI_DEVICE_ID_INTERG_5050: + /* disable AC97 GPIO interrupt */ + outl(0x00, TRID_REG(card, SI_AC97_GPIO)); + /* when power up, the AC link is in cold reset mode, so stop it */ + outl(PCMOUT|SURROUT|CENTEROUT|LFEOUT, + TRID_REG(card, SI_SERIAL_INTF_CTRL)); + /* it take a long time to recover from a cold reset (especially when you have + more than one codec) */ + udelay(2000); + ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL)); + ready_2nd &= SI_AC97_SECONDARY_READY; + break; } for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { @@ -3769,7 +3938,7 @@ struct pci_dev *pci_dev_m1533 = NULL; if (pci_enable_device(pci_dev)) - return -ENODEV; + return -ENODEV; if (pci_set_dma_mask(pci_dev, TRIDENT_DMA_MASK)) { printk(KERN_ERR "trident: architecture does not support" @@ -3778,7 +3947,11 @@ } pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); - iobase = pci_resource_start(pci_dev, 0); + if (pci_id->device == PCI_DEVICE_ID_INTERG_5050) + iobase = pci_resource_start(pci_dev, 1); + else + iobase = pci_resource_start(pci_dev, 0); + if (check_region(iobase, 256)) { printk(KERN_ERR "trident: can't allocate I/O space at 0x%4.4lx\n", iobase); @@ -3855,7 +4028,16 @@ pci_write_config_byte(pci_dev_m1533, 0x7b, bits); } } - else { + else if(card->pci_id == PCI_DEVICE_ID_INTERG_5050) + { + card->alloc_pcm_channel = cyber_alloc_pcm_channel; + card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel; + card->free_pcm_channel = cyber_free_pcm_channel; + card->address_interrupt = cyber_address_interrupt; + cyber_init_ritual(card); + } + else + { card->alloc_pcm_channel = trident_alloc_pcm_channel; card->alloc_rec_pcm_channel = trident_alloc_pcm_channel; card->free_pcm_channel = trident_free_pcm_channel; @@ -3982,7 +4164,7 @@ } MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho, Ching Ling Lee"); -MODULE_DESCRIPTION("Trident 4DWave/SiS 7018/ALi 5451 PCI Audio Driver"); +MODULE_DESCRIPTION("Trident 4DWave/SiS 7018/ALi 5451 and Tvia/IGST CyberPro5050 PCI Audio Driver"); #define TRIDENT_MODULE_NAME "trident" @@ -4000,7 +4182,7 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451 PCI Audio, version " + printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro 5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); if (!pci_register_driver(&trident_pci_driver)) { diff -u --recursive --new-file v2.4.9/linux/drivers/sound/trident.h linux/drivers/sound/trident.h --- v2.4.9/linux/drivers/sound/trident.h Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/trident.h Fri Sep 7 09:28:37 2001 @@ -315,12 +315,19 @@ #define TRID_REG( trident, x ) ( (trident) -> iobase + (x) ) +#define CYBER_PORT_AUDIO 0x3CE +#define CYBER_IDX_AUDIO_ENABLE 0x7B +#define CYBER_BMSK_AUDIO_INT_ENABLE 0x09 +#define CYBER_BMSK_AUENZ 0x01 +#define CYBER_BMSK_AUENZ_ENABLE 0x00 +#define CYBER_IDX_IRQ_ENABLE 0x12 + #define VALIDATE_MAGIC(FOO,MAG) \ -({ \ - if (!(FOO) || (FOO)->magic != MAG) { \ - printk(invalid_magic,__FUNCTION__); \ - return -ENXIO; \ - } \ +({ \ + if (!(FOO) || (FOO)->magic != MAG) { \ + printk(invalid_magic,__FUNCTION__); \ + return -ENXIO; \ + } \ }) #define VALIDATE_STATE(a) VALIDATE_MAGIC(a,TRIDENT_STATE_MAGIC) diff -u --recursive --new-file v2.4.9/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c --- v2.4.9/linux/drivers/sound/via82cxxx_audio.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/via82cxxx_audio.c Fri Sep 7 09:28:37 2001 @@ -90,10 +90,6 @@ #define VIA_MIN_FRAG_NUMBER 2 -#ifndef AC97_PCM_LR_ADC_RATE -# define AC97_PCM_LR_ADC_RATE AC97_PCM_LR_DAC_RATE -#endif - /* 82C686 function 5 (audio codec) PCI configuration registers */ #define VIA_ACLINK_CTRL 0x41 #define VIA_FUNC_ENABLE 0x42 diff -u --recursive --new-file v2.4.9/linux/drivers/tc/lk201-map.map linux/drivers/tc/lk201-map.map --- v2.4.9/linux/drivers/tc/lk201-map.map Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/lk201-map.map Mon Aug 27 08:56:31 2001 @@ -0,0 +1,356 @@ +# Default kernel keymap. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 +# Change the above line into +# keymaps 0-2,4-6,8,12 +# in case you want the entries +# altgr control keycode 83 = Boot +# altgr control keycode 111 = Boot +# below. +# +# In fact AltGr is used very little, and one more keymap can +# be saved by mapping AltGr to Alt (and adapting a few entries): +# keycode 100 = Alt +# +keycode 0x15 = grave tilde + alt keycode 0x15 = Escape + control keycode 0x15 = Meta_Escape +keycode 0x16 = one exclam + alt keycode 0x16 = Meta_one +keycode 0x17 = two at at + control keycode 0x17 = nul + shift control keycode 0x17 = nul + alt keycode 0x17 = Meta_two +keycode 0x18 = three numbersign + control keycode 0x18 = Escape + alt keycode 0x18 = Meta_three +keycode 0x19 = four dollar dollar + control keycode 0x19 = Control_backslash + alt keycode 0x19 = Meta_four +keycode 0x1a = five percent + control keycode 0x1a = Control_bracketright + alt keycode 0x1a = Meta_five +keycode 0x1b = six asciicircum + control keycode 0x1b = Control_asciicircum + alt keycode 0x1b = Meta_six +keycode 0x1c = seven ampersand braceleft + control keycode 0x1c = Control_underscore + alt keycode 0x1c = Meta_seven +keycode 0x1d = eight asterisk bracketleft + control keycode 0x1d = Delete + alt keycode 0x1d = Meta_eight +keycode 0x1e = nine parenleft bracketright + alt keycode 0x1e = Meta_nine +keycode 0x1f = zero parenright braceright + alt keycode 0x1f = Meta_zero +keycode 0x20 = minus underscore backslash + control keycode 0x20 = Control_underscore + shift control keycode 0x20 = Control_underscore + alt keycode 0x20 = Meta_minus +keycode 0x21 = equal plus + alt keycode 0x21 = Meta_equal +keycode 0x22 = Delete Delete + control keycode 0x22 = BackSpace + alt keycode 0x22 = Meta_Delete +keycode 0x2a = Tab Tab + alt keycode 0x2a = Meta_Tab +keycode 0x2b = q +keycode 0x2c = w +keycode 0x2d = e + altgr keycode 0x2d = Hex_E +keycode 0x2e = r +keycode 0x2f = t +keycode 0x30 = y +keycode 0x31 = u +keycode 0x32 = i +keycode 0x33 = o +keycode 0x34 = p +keycode 0x35 = bracketleft braceleft + control keycode 0x35 = Escape + alt keycode 0x35 = Meta_bracketleft +keycode 0x36 = bracketright braceright asciitilde + control keycode 0x36 = Control_bracketright + alt keycode 0x36 = Meta_bracketright +keycode 0x37 = Return + alt keycode 0x37 = Meta_Control_m +keycode 0x3f = Control +keycode 0x41 = a + altgr keycode 0x41 = Hex_A +keycode 0x42 = s +keycode 0x43 = d + altgr keycode 0x43 = Hex_D +keycode 0x44 = f + altgr keycode 0x44 = Hex_F +keycode 0x45 = g +keycode 0x46 = h +keycode 0x47 = j +keycode 0x48 = k +keycode 0x49 = l +keycode 0x4a = semicolon colon + alt keycode 0x4a = Meta_semicolon +keycode 0x4b = apostrophe quotedbl + control keycode 0x4b = Control_g + alt keycode 0x4b = Meta_apostrophe +# keycode 41 = grave asciitilde +# control keycode 41 = nul +# alt keycode 41 = Meta_grave +keycode 0x52 = Shift +keycode 0x4c = backslash bar + control keycode 0x4c = Control_backslash + alt keycode 0x4c = Meta_backslash +keycode 0x53 = greater less +keycode 0x54 = z +keycode 0x55 = x +keycode 0x56 = c + altgr keycode 0x56 = Hex_C +keycode 0x57 = v +keycode 0x58 = b + altgr keycode 0x58 = Hex_B +keycode 0x59 = n +keycode 0x5a = m +keycode 0x5b = comma less + alt keycode 0x5b = Meta_comma +keycode 0x5c = period greater + control keycode 0x5c = Compose + alt keycode 0x5c = Meta_period +keycode 0x5d = slash question + control keycode 0x5d = Delete + alt keycode 0x5d = Meta_slash + +keycode 0x67 = Alt +keycode 0x68 = space space + control keycode 0x68 = nul + alt keycode 0x68 = Meta_space +keycode 0x40 = Caps_Lock +keycode 0x01 = F1 + control keycode 0x01 = F1 + alt keycode 0x01 = Console_1 + control alt keycode 0x01 = Console_1 +keycode 0x02 = F2 + control keycode 0x02 = F2 + alt keycode 0x02 = Console_2 + control alt keycode 0x02 = Console_2 +keycode 0x03 = F3 + control keycode 0x03 = F3 + alt keycode 0x03 = Console_3 + control alt keycode 0x03 = Console_3 +keycode 0x04 = F4 + control keycode 0x04 = F4 + alt keycode 0x04 = Console_4 + control alt keycode 0x04 = Console_4 +keycode 0x05 = F5 + control keycode 0x05 = F5 + alt keycode 0x05 = Console_5 + control alt keycode 0x05 = Console_5 +keycode 0x06 = F6 + control keycode 0x06 = F6 + alt keycode 0x06 = Console_6 + control alt keycode 0x06 = Console_6 +keycode 0x07 = F7 + control keycode 0x07 = F7 + alt keycode 0x07 = Console_7 + control alt keycode 0x07 = Console_7 +keycode 0x08 = F8 + control keycode 0x08 = F8 + alt keycode 0x08 = Console_8 + control alt keycode 0x08 = Console_8 +keycode 0x09 = F9 + control keycode 0x09 = F9 + alt keycode 0x09 = Console_9 + control alt keycode 0x09 = Console_9 +keycode 0x0a = F10 + control keycode 0x0a = F10 + alt keycode 0x0a = Console_10 + control alt keycode 0x0a = Console_10 +keycode 0x0b = F11 + control keycode 0x0b = F11 + alt keycode 0x0b = Console_11 + control alt keycode 0x0b = Console_11 +keycode 0x0c = F12 + control keycode 0x0c = F12 + alt keycode 0x0c = Console_12 + control alt keycode 0x0c = Console_12 +keycode 0x0d = F13 + control keycode 0x0d = F13 + alt keycode 0x0d = Console_13 + control alt keycode 0x0d = Console_13 +keycode 0x0e = F14 + control keycode 0x0e = F14 + alt keycode 0x0e = Console_14 + control alt keycode 0x0e = Console_14 + +keycode 0x11 = F17 + control keycode 0x11 = F17 + alt keycode 0x11 = Console_17 + control alt keycode 0x11 = Console_17 +keycode 0x12 = F18 + control keycode 0x12 = F18 + alt keycode 0x12 = Console_18 + control alt keycode 0x12 = Console_18 +keycode 0x13 = F19 + control keycode 0x13 = F19 + alt keycode 0x13 = Console_19 + control alt keycode 0x13 = Console_19 +keycode 0x14 = F20 + control keycode 0x14 = F20 + alt keycode 0x14 = Console_20 + control alt keycode 0x14 = Console_20 + + +keycode 0x3b = KP_7 + alt keycode 0x3b = Ascii_7 + altgr keycode 0x3b = Hex_7 +keycode 0x3c = KP_8 + alt keycode 0x3c = Ascii_8 + altgr keycode 0x3c = Hex_8 +keycode 0x3d = KP_9 + alt keycode 0x3d = Ascii_9 + altgr keycode 0x3d = Hex_9 +keycode 0x3e = KP_Subtract +keycode 0x4e = KP_4 + alt keycode 0x4e = Ascii_4 + altgr keycode 0x4e = Hex_4 +keycode 0x4f = KP_5 + alt keycode 0x4f = Ascii_5 + altgr keycode 0x4f = Hex_5 +keycode 0x50 = KP_6 + alt keycode 0x50 = Ascii_6 + altgr keycode 0x50 = Hex_6 +keycode 0x62 = KP_1 + alt keycode 0x62 = Ascii_1 + altgr keycode 0x62 = Hex_1 +keycode 0x63 = KP_2 + alt keycode 0x63 = Ascii_2 + altgr keycode 0x63 = Hex_2 +keycode 0x64 = KP_3 + alt keycode 0x64 = Ascii_3 + altgr keycode 0x64 = Hex_3 +keycode 0x6b = KP_0 + alt keycode 0x6b = Ascii_0 + altgr keycode 0x6b = Hex_0 +keycode 0x6c = KP_Period +# altgr control keycode 0x6c = Boot + control alt keycode 0x6c = Boot +keycode 0x65 = KP_Enter + +keycode 0x3f = Control + +# keycode 100 = AltGr + +keycode 0x23 = Find +keycode 0x4d = Up +keycode 0x39 = Prior + shift keycode 0x39 = Scroll_Backward +keycode 0x5f = Left + alt keycode 0x5f = Decr_Console +keycode 0x61 = Right + alt keycode 0x61 = Incr_Console +keycode 0x38 = Select +keycode 0x60 = Down +keycode 0x3a = Next + shift keycode 0x3a = Scroll_Forward +keycode 0x24 = Insert +keycode 0x25 = Remove +# altgr control keycode 0x25 = Boot + control alt keycode 0x25 = Boot + +keycode 0x0f = Help Show_Memory Show_Registers + control keycode 0x0f = Show_State + +keycode 0x10 = Do + +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -u --recursive --new-file v2.4.9/linux/drivers/tc/lk201-remap.c linux/drivers/tc/lk201-remap.c --- v2.4.9/linux/drivers/tc/lk201-remap.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/lk201-remap.c Mon Aug 27 08:56:31 2001 @@ -0,0 +1,172 @@ +/* + * Keyboard mappings for DEC LK201/401/501 keyboards + * + * 17.05.99 Michael Engel (engel@unix-ag.org) + * + * DEC US keyboards generate keycodes in the range 0x55 - 0xfb + * + * This conflicts with Linux scancode conventions which define + * 0x00-0x7f as "normal" and 0x80-0xff as "shifted" scancodes, so we + * have to remap the keycodes to 0x00-0x7f with the scancodeRemap + * array. The generated scancode is simply the number of the key counted + * from the left upper to the right lower corner of the keyboard ... + * + * These scancodes are then being remapped (I hope ;-)) with the + * lk501*map[] arrays which define scancode -> Linux code mapping + * + * Oh man is this horrible ;-) + * + * Scancodes with dual labels exist for keyboards as follows: + * + * code: left label / right label + * + * 0x73: LKx01, LK421 / LK443, LK444 + * 0x74: LKx01, LK421 / LK443, LK444 + * 0x7c: LKx01, LK421 / LK443, LK444 + * 0x8a: LKx01, LK421 / LK443, LK444 + * 0x8b: LKx01, LK421 / LK443, LK444 + * 0x8c: LKx01, LK421 / LK443, LK444 + * 0x8d: LKx01, LK421 / LK443, LK444 + * 0x8e: LKx01, LK421 / LK443, LK444 + * 0x8f: LKx01, LK421 / LK443, LK444 + * 0x9c: LKx01, LK421 / LK443, LK444 + * 0xa1: LKx01, LK421 / LK443, LK444 + * 0xa2: LKx01, LK421 / LK443, LK444 + * 0xa3: LKx01, LK421 / LK443, LK444 + * 0xa4: LKx01, LK421 / LK443, LK444 + * 0xad: LK421 / LK443, LK444 + * 0xc9: LKx01, LK421, LK443 / LK444 + * 0xf7: LKx01, LK443 / LK444 + */ + +unsigned char scancodeRemap[256] = { +/* ----- */ +/* 0 */ 0, 0, 0, 0, +/* ----- */ +/* 4 */ 0, 0, 0, 0, +/* ----- */ +/* 8 */ 0, 0, 0, 0, +/* ----- */ +/* c */ 0, 0, 0, 0, +/* ----- */ +/* 10 */ 0, 0, 0, 0, +/* ----- */ +/* 14 */ 0, 0, 0, 0, +/* ----- */ +/* 18 */ 0, 0, 0, 0, +/* ----- */ +/* 1c */ 0, 0, 0, 0, +/* ----- */ +/* 20 */ 0, 0, 0, 0, +/* ----- */ +/* 24 */ 0, 0, 0, 0, +/* ----- */ +/* 28 */ 0, 0, 0, 0, +/* ----- */ +/* 2c */ 0, 0, 0, 0, +/* ----- */ +/* 30 */ 0, 0, 0, 0, +/* ----- */ +/* 34 */ 0, 0, 0, 0, +/* ----- */ +/* 38 */ 0, 0, 0, 0, +/* ----- */ +/* 3c */ 0, 0, 0, 0, +/* ----- */ +/* 40 */ 0, 0, 0, 0, +/* ----- */ +/* 44 */ 0, 0, 0, 0, +/* ----- */ +/* 48 */ 0, 0, 0, 0, +/* ----- */ +/* 4c */ 0, 0, 0, 0, +/* ----- */ +/* 50 */ 0, 0, 0, 0, +/* ----- ESC F1 F2 */ +/* 54 */ 0, 0, 0x01, 0x02, +/* ----- F3 F4 F5 */ +/* 58 */ 0x03, 0x04, 0x05, 0, +/* ----- */ +/* 5c */ 0, 0, 0, 0, +/* ----- */ +/* 60 */ 0, 0, 0, 0, +/* ----- F6 F7 F8 F9 */ +/* 64 */ 0x06, 0x07, 0x08, 0x09, +/* ----- F10 */ +/* 68 */ 0x0a, 0, 0, 0, +/* ----- */ +/* 6c */ 0, 0, 0, 0, +/* ----- F11 F12 F13/PRNT SCRN */ +/* 70 */ 0, 0x0b, 0x0c, 0x0d, +/* ----- F14/SCRL LCK */ +/* 74 */ 0x0e, 0, 0, 0, +/* ----- */ +/* 78 */ 0, 0, 0, 0, +/* ----- HELP/PAUSE DO */ +/* 7c */ 0x0f, 0x10, 0, 0, +/* ----- F17 F18 F19 F20 */ +/* 80 */ 0x11, 0x12, 0x13, 0x14, +/* ----- */ +/* 84 */ 0, 0, 0, 0, +/* ----- FIND/INSERT INSERT/HOME */ +/* 88 */ 0, 0, 0x23, 0x24, +/* ----- REMOVE/PG UP SELECT/DELETE PREVIOUS/END NEXT/PG DN */ +/* 8c */ 0x25, 0x38, 0x39, 0x3a, +/* ----- KP 0 */ +/* 90 */ 0, 0, 0x6b, 0, +/* ----- KP . KP ENTER KP 1 KP 2 */ +/* 94 */ 0x6c, 0x65, 0x62, 0x63, +/* ----- KP 3 KP 4 KP 5 KP 6 */ +/* 98 */ 0x64, 0x4e, 0x4f, 0x50, +/* ----- KP ,/KP + KP 7 KP 8 KP 9 */ +/* 9c */ 0x51, 0x3b, 0x3c, 0x3d, +/* ----- KP - KP F1/NUM LCK KP F2/KP / KP F3/KP * */ +/* a0 */ 0x3e, 0x26, 0x27, 0x28, +/* ----- KP F4/KP - LEFT */ +/* a4 */ 0x29, 0, 0, 0x5f, +/* ----- RIGHT DOWN UP SHIFT Rt */ +/* a8 */ 0x61, 0x60, 0x4d, 0x5e, +/* ----- ALT COMP Rt/CTRL Rt SHIFT CONTROL */ +/* ac */ 0, 0, 0x52, 0x3f, +/* ----- CAPS COMPOSE ALT Rt */ +/* b0 */ 0x40, 0x67, 0, 0, +/* ----- */ +/* b4 */ 0, 0, 0, 0, +/* ----- */ +/* b8 */ 0, 0, 0, 0, +/* ----- BKSP RET TAB ` */ +/* bc */ 0x22, 0x37, 0x2a, 0x15, +/* ----- 1 q a z */ +/* c0 */ 0x16, 0x2b, 0x41, 0x54, +/* ----- 2 w s */ +/* c4 */ 0, 0x17, 0x2c, 0x42, +/* ----- x +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zs.h" +#include "lk201.h" + +/* Simple translation table for the SysRq keys */ + +#ifdef CONFIG_MAGIC_SYSRQ +/* + * Actually no translation at all, at least until we figure out + * how to define SysRq for LK201 and friends. --macro + */ +unsigned char lk201_sysrq_xlate[128]; +unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate; +#endif + +#define KEYB_LINE 3 + +static int __init lk201_init(struct dec_serial *); +static void __init lk201_info(struct dec_serial *); +static void lk201_kbd_rx_char(unsigned char, unsigned char); + +struct zs_hook lk201_kbdhook = { + init_channel: lk201_init, + init_info: lk201_info, + rx_char: NULL, + poll_rx_char: NULL, + poll_tx_char: NULL, + cflags: B4800 | CS8 | CSTOPB | CLOCAL +}; + +/* + * This is used during keyboard initialisation + */ +static unsigned char lk201_reset_string[] = { + LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */ + LK_CMD_SET_DEFAULTS, + LK_CMD_MODE(LK_MODE_RPT_DOWN, 1), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 2), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 3), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 4), + LK_CMD_MODE(LK_MODE_DOWN_UP, 5), + LK_CMD_MODE(LK_MODE_DOWN_UP, 6), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 7), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 8), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 9), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 10), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 11), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 12), + LK_CMD_MODE(LK_MODE_DOWN, 13), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 14), + LK_CMD_ENB_RPT, + LK_CMD_DIS_KEYCLK, + LK_CMD_RESUME, + LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4), + LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf) +}; + +static int __init lk201_reset(struct dec_serial *info) +{ + int i; + + for (i = 0; i < sizeof(lk201_reset_string); i++) + if (info->hook->poll_tx_char(info, lk201_reset_string[i])) { + printk(__FUNCTION__" transmit timeout\n"); + return -EIO; + } + return 0; +} + +void kbd_leds(unsigned char leds) +{ + return; +} + +int kbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + return -EINVAL; +} + +int kbd_getkeycode(unsigned int scancode) +{ + return -EINVAL; +} + +int kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + *keycode = scancode; + return 1; +} + +char kbd_unexpected_up(unsigned char keycode) +{ + return 0x80; +} + +static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat) +{ + static int shift_state = 0; + static int prev_scancode; + unsigned char c = scancodeRemap[ch]; + + if (!stat || stat == 4) { + switch (ch) { + case LK_KEY_ACK: + break; + case LK_KEY_LOCK: + shift_state ^= LK_LOCK; + handle_scancode(c, shift_state && LK_LOCK ? 1 : 0); + break; + case LK_KEY_SHIFT: + shift_state ^= LK_SHIFT; + handle_scancode(c, shift_state && LK_SHIFT ? 1 : 0); + break; + case LK_KEY_CTRL: + shift_state ^= LK_CTRL; + handle_scancode(c, shift_state && LK_CTRL ? 1 : 0); + break; + case LK_KEY_COMP: + shift_state ^= LK_COMP; + handle_scancode(c, shift_state && LK_COMP ? 1 : 0); + break; + case LK_KEY_RELEASE: + if (shift_state & LK_SHIFT) + handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0); + if (shift_state & LK_CTRL) + handle_scancode(scancodeRemap[LK_KEY_CTRL], 0); + if (shift_state & LK_COMP) + handle_scancode(scancodeRemap[LK_KEY_COMP], 0); + if (shift_state & LK_LOCK) + handle_scancode(scancodeRemap[LK_KEY_LOCK], 0); + shift_state = 0; + break; + case LK_KEY_REPEAT: + handle_scancode(prev_scancode, 1); + break; + default: + prev_scancode = c; + handle_scancode(c, 1); + break; + } + } else + printk("Error reading LKx01 keyboard: 0x%02x\n", stat); +} + +static void __init lk201_info(struct dec_serial *info) +{ +} + +static int __init lk201_init(struct dec_serial *info) +{ + unsigned int ch, id = 0; + int result; + + printk("DECstation LK keyboard driver v0.04... "); + + result = lk201_reset(info); + if (result) + return result; + mdelay(10); + + /* + * Detect whether there is an LK201 or an LK401 + * The LK401 has ALT keys... + */ + info->hook->poll_tx_char(info, LK_CMD_REQ_ID); + while ((ch = info->hook->poll_rx_char(info)) > 0) + id = ch; + + switch (id) { + case 1: + printk("LK201 detected\n"); + break; + case 2: + printk("LK401 detected\n"); + break; + default: + printk("unknown keyboard, ID %d,\n", id); + printk("... please report to \n"); + } + + /* + * now we're ready + */ + info->hook->rx_char = lk201_kbd_rx_char; + + return 0; +} + +void __init kbd_init_hw(void) +{ + extern int register_zs_hook(unsigned int, struct zs_hook *); + extern int unregister_zs_hook(unsigned int); + + if (TURBOCHANNEL) { + if (mips_machtype != MACH_DS5000_XX) { + /* + * This is not a MAXINE, so: + * + * kbd_init_hw() is being called before + * rs_init() so just register the kbd hook + * and let zs_init do the rest :-) + */ + if (mips_machtype == MACH_DS5000_200) + printk("LK201 Support for DS5000/200 not yet ready ...\n"); + else + if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook)) + unregister_zs_hook(KEYB_LINE); + } + } else { + /* + * TODO: modify dz.c to allow similar hooks + * for LK201 handling on DS2100, DS3100, and DS5000/200 + */ + printk("LK201 Support for DS3100 not yet ready ...\n"); + } +} + + + + diff -u --recursive --new-file v2.4.9/linux/drivers/tc/lk201.h linux/drivers/tc/lk201.h --- v2.4.9/linux/drivers/tc/lk201.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/lk201.h Mon Aug 27 08:56:31 2001 @@ -0,0 +1,53 @@ +/* + * Commands to the keyboard processor + */ + +#define LK_PARAM 0x80 /* start/end parameter list */ + +#define LK_CMD_RESUME 0x8b +#define LK_CMD_INHIBIT 0xb9 +#define LK_CMD_LEDS_ON 0x13 /* 1 param: led bitmask */ +#define LK_CMD_LEDS_OFF 0x11 /* 1 param: led bitmask */ +#define LK_CMD_DIS_KEYCLK 0x99 +#define LK_CMD_ENB_KEYCLK 0x1b /* 1 param: volume */ +#define LK_CMD_DIS_CTLCLK 0xb9 +#define LK_CMD_ENB_CTLCLK 0xbb +#define LK_CMD_SOUND_CLK 0x9f +#define LK_CMD_DIS_BELL 0xa1 +#define LK_CMD_ENB_BELL 0x23 /* 1 param: volume */ +#define LK_CMD_BELL 0xa7 +#define LK_CMD_TMP_NORPT 0xc1 +#define LK_CMD_ENB_RPT 0xe3 +#define LK_CMD_DIS_RPT 0xe1 +#define LK_CMD_RPT_TO_DOWN 0xd9 +#define LK_CMD_REQ_ID 0xab +#define LK_CMD_POWER_UP 0xfd +#define LK_CMD_TEST_MODE 0xcb +#define LK_CMD_SET_DEFAULTS 0xd3 + +/* there are 4 leds, represent them in the low 4 bits of a byte */ +#define LK_PARAM_LED_MASK(ledbmap) (LK_PARAM|(ledbmap)) + +/* max volume is 0, lowest is 0x7 */ +#define LK_PARAM_VOLUME(v) (LK_PARAM|((v)&0x7)) + +/* mode set command(s) details */ +#define LK_MODE_DOWN 0x0 +#define LK_MODE_RPT_DOWN 0x2 +#define LK_MODE_DOWN_UP 0x6 +#define LK_CMD_MODE(m,div) (LK_PARAM|(div<<3)|m) + +#define LK_SHIFT 1<<0 +#define LK_CTRL 1<<1 +#define LK_LOCK 1<<2 +#define LK_COMP 1<<3 + +#define LK_KEY_SHIFT 174 +#define LK_KEY_CTRL 175 +#define LK_KEY_LOCK 176 +#define LK_KEY_COMP 177 +#define LK_KEY_RELEASE 179 +#define LK_KEY_REPEAT 180 +#define LK_KEY_ACK 186 + +extern unsigned char scancodeRemap[256]; \ No newline at end of file diff -u --recursive --new-file v2.4.9/linux/drivers/tc/tc.c linux/drivers/tc/tc.c --- v2.4.9/linux/drivers/tc/tc.c Sat May 13 08:31:25 2000 +++ linux/drivers/tc/tc.c Mon Aug 27 08:56:31 2001 @@ -1,4 +1,4 @@ -/* $Id: tc.c,v 1.3 1999/10/09 00:01:32 ralf Exp $ +/* * tc-init: We assume the TURBOchannel to be up and running so * just probe for Modules and fill in the global data structure * tc_bus. @@ -8,9 +8,7 @@ * for more details. * * Copyright (c) Harald Koerfgen, 1998 - * */ - #include #include #include @@ -23,14 +21,15 @@ #include #include +#include #define TC_DEBUG slot_info tc_bus[MAX_SLOT]; -static int max_tcslot = 0; -static tcinfo *info = (tcinfo *)0; +static int max_tcslot; +static tcinfo *info; -unsigned long system_base = 0; +unsigned long system_base; extern void (*dbe_board_handler)(struct pt_regs *regs); extern unsigned long *(*rex_slot_address)(int); @@ -112,19 +111,19 @@ for (slot = 0; slot <= max_slot; slot++) { module = (char *)(startaddr + slot * size); offset = -1; - if (module[OLDCARD + PATTERN0] == 0x55 && module[OLDCARD + PATTERN1] == 0x00 - && module[OLDCARD + PATTERN2] == 0xaa && module[OLDCARD + PATTERN3] == 0xff) + if (module[OLDCARD + TC_PATTERN0] == 0x55 && module[OLDCARD + TC_PATTERN1] == 0x00 + && module[OLDCARD + TC_PATTERN2] == 0xaa && module[OLDCARD + TC_PATTERN3] == 0xff) offset = OLDCARD; - if (module[PATTERN0] == 0x55 && module[PATTERN1] == 0x00 - && module[PATTERN2] == 0xaa && module[PATTERN3] == 0xff) + if (module[TC_PATTERN0] == 0x55 && module[TC_PATTERN1] == 0x00 + && module[TC_PATTERN2] == 0xaa && module[TC_PATTERN3] == 0xff) offset = 0; if (offset != -1) { tc_bus[slot].base_addr = (unsigned long)module; for(i = 0; i < 8; i++) { - tc_bus[slot].firmware[i] = module[FIRM_VER + offset + 4 * i]; - tc_bus[slot].vendor[i] = module[VENDOR + offset + 4 * i]; - tc_bus[slot].name[i] = module[MODULE + offset + 4 * i]; + tc_bus[slot].firmware[i] = module[TC_FIRM_VER + offset + 4 * i]; + tc_bus[slot].vendor[i] = module[TC_VENDOR + offset + 4 * i]; + tc_bus[slot].name[i] = module[TC_MODULE + offset + 4 * i]; } tc_bus[slot].firmware[8] = 0; tc_bus[slot].vendor[8] = 0; @@ -206,7 +205,7 @@ if (TURBOCHANNEL && info->slot_size && slot0addr) { printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision, tc_clock / 10, tc_clock % 10); - printk("(%sparity)\n", info->parity ? "" : "no "); + printk("(with%s parity)\n", info->parity ? "" : "out"); slot_size = info->slot_size << 20; @@ -235,3 +234,11 @@ ioport_resource.end = KSEG2 - 1; } } + +EXPORT_SYMBOL(search_tc_card); +EXPORT_SYMBOL(claim_tc_card); +EXPORT_SYMBOL(release_tc_card); +EXPORT_SYMBOL(get_tc_base_addr); +EXPORT_SYMBOL(get_tc_irq_nr); +EXPORT_SYMBOL(get_tc_speed); + diff -u --recursive --new-file v2.4.9/linux/drivers/tc/tcsyms.c linux/drivers/tc/tcsyms.c --- v2.4.9/linux/drivers/tc/tcsyms.c Sat May 13 08:31:25 2000 +++ linux/drivers/tc/tcsyms.c Wed Dec 31 16:00:00 1969 @@ -1,14 +0,0 @@ -/* - * TURBOchannel Services -- Exported Symbols - * - */ - -#include -#include - -EXPORT_SYMBOL(search_tc_card); -EXPORT_SYMBOL(claim_tc_card); -EXPORT_SYMBOL(release_tc_card); -EXPORT_SYMBOL(get_tc_base_addr); -EXPORT_SYMBOL(get_tc_irq_nr); -EXPORT_SYMBOL(get_tc_speed); diff -u --recursive --new-file v2.4.9/linux/drivers/tc/zs.c linux/drivers/tc/zs.c --- v2.4.9/linux/drivers/tc/zs.c Thu Oct 12 14:20:47 2000 +++ linux/drivers/tc/zs.c Mon Aug 27 08:56:31 2001 @@ -1,22 +1,46 @@ /* - * decserial.c: Serial port driver for IOASIC DECsatations. + * decserial.c: Serial port driver for IOASIC DECstations. * - * Derived from drivers/macintosh/macserial.c by Harald Koerfgen. * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. + * Derived from drivers/macintosh/macserial.c by Harald Koerfgen. * * DECstation changes - * Copyright (C) 1998 Harald Koerfgen (Harald.Koerfgen@home.ivm.de) + * Copyright (C) 1998-2000 Harald Koerfgen + * Copyright (C) 2000,2001 Maciej W. Rozycki * * For the rest of the code the original Copyright applies: * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * - * Keyboard and mouse are not supported right now. If you want to change this, - * you might want to have a look at drivers/sbus/char/sunserial.c to see - * how this might be done. HK + * + * Note: for IOASIC systems the wiring is as follows: + * + * mouse/keyboard: + * DIN-7 MJ-4 signal SCC + * 2 1 TxD <- A.TxD + * 3 4 RxD -> A.RxD + * + * EIA-232/EIA-423: + * DB-25 MMJ-6 signal SCC + * 2 2 TxD <- B.TxD + * 3 5 RxD -> B.RxD + * 4 RTS <- ~A.RTS + * 5 CTS -> ~B.CTS + * 6 6 DSR -> ~A.SYNC + * 8 CD -> ~B.DCD + * 12 DSRS(DCE) -> ~A.CTS (*) + * 15 TxC -> B.TxC + * 17 RxC -> B.RxC + * 20 1 DTR <- ~A.DTR + * 22 RI -> ~A.DCD + * 23 DSRS(DTE) <- ~B.RTS + * + * (*) EIA-232 defines the signal at this pin to be SCD, while DSRS(DCE) + * is shared with DSRS(DTE) at pin 23. */ #include +#include #include #include #include @@ -31,6 +55,7 @@ #include #include #include +#include #ifdef CONFIG_SERIAL_CONSOLE #include #endif @@ -43,17 +68,26 @@ #include #include #include +#include +#ifdef CONFIG_DECSTATION #include #include #include #include +#endif +#ifdef CONFIG_BAGET_MIPS +#include +unsigned long system_base; +#endif #ifdef CONFIG_KGDB #include #endif +#ifdef CONFIG_MAGIC_SYSRQ +#include +#endif #include "zs.h" - /* * It would be nice to dynamically allocate everything that * depends on NUM_SERIAL, so we could support any number of @@ -61,11 +95,60 @@ */ #define NUM_SERIAL 2 /* Max number of ZS chips supported */ #define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ +#define CHANNEL_A_NR (zs_parms->channel_a_offset > zs_parms->channel_b_offset) + /* Number of channel A in the chip */ +#define ZS_CHAN_IO_SIZE 8 +#define ZS_CLOCK 7372800 /* Z8530 RTxC input clock rate */ #define RECOVERY_DELAY udelay(2) -struct dec_zschannel zs_channels[NUM_CHANNELS]; +struct zs_parms { + unsigned long scc0; + unsigned long scc1; + int channel_a_offset; + int channel_b_offset; + int irq; + int clock; +}; +static struct zs_parms *zs_parms; + +#ifdef CONFIG_DECSTATION +static struct zs_parms ds_parms = { + scc0 : SCC0, + scc1 : SCC1, + channel_a_offset : 1, + channel_b_offset : 9, + irq : SERIAL, + clock : ZS_CLOCK +}; +#endif +#ifdef CONFIG_BAGET_MIPS +static struct zs_parms baget_parms = { + scc0 : UNI_SCC0, + scc1 : UNI_SCC1, + channel_a_offset : 9, + channel_b_offset : 1, + irq : BAGET_SCC_IRQ, + clock : 14745000 +}; +#endif + +#ifdef CONFIG_DECSTATION +#define DS_BUS_PRESENT (IOASIC) +#else +#define DS_BUS_PRESENT 0 +#endif + +#ifdef CONFIG_BAGET_MIPS +#define BAGET_BUS_PRESENT (mips_machtype == MACH_BAGET202) +#else +#define BAGET_BUS_PRESENT 0 +#endif + +#define BUS_PRESENT (DS_BUS_PRESENT || BAGET_BUS_PRESENT) + +struct dec_zschannel zs_channels[NUM_CHANNELS]; struct dec_serial zs_soft[NUM_CHANNELS]; int zs_channels_found; struct dec_serial *zs_chain; /* list of all channels */ @@ -75,19 +158,9 @@ #ifdef CONFIG_SERIAL_CONSOLE static struct console sercons; #endif - -#ifdef CONFIG_KGDB -struct dec_zschannel *zs_kgdbchan; -static unsigned char scc_inittab[] = { - 9, 0x80, /* reset A side (CHRA) */ - 13, 0, /* set baud rate divisor */ - 12, 1, - 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */ - 11, 0x50, /* clocks = br gen (RCBR | TCBR) */ - 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */ - 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/ - 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/ -}; +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) \ + && !defined(MODULE) +static unsigned long break_pressed; /* break, really ... */ #endif static unsigned char zs_init_regs[16] __initdata = { @@ -106,8 +179,6 @@ 0 /* write 15 */ }; -#define ZS_CLOCK 7372800 /* Z8530 RTxC input clock rate */ - DECLARE_TASK_QUEUE(tq_zs_serial); struct tty_driver serial_driver, callout_driver; @@ -129,6 +200,12 @@ #undef SERIAL_DEBUG_THROTTLE #undef SERIAL_PARANOIA_CHECK +#undef ZS_DEBUG_REGS + +#ifdef SERIAL_DEBUG_THROTTLE +#define _tty_name(tty,buf) tty_name(tty,buf) +#endif + #define RS_STROBE_TIME 10 #define RS_ISR_PASS_LIMIT 256 @@ -184,7 +261,7 @@ */ static int baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 0, 0 }; + 9600, 19200, 38400, 57600, 115200, 0 }; /* * Reading and writing Z8530 registers. @@ -256,16 +333,21 @@ } /* Sets or clears DTR/RTS on the requested line */ -static inline void zs_rtsdtr(struct dec_serial *ss, int set) +static inline void zs_rtsdtr(struct dec_serial *info, int which, int set) { - if (ss->zs_channel != ss->zs_chan_a) { - if (set) - ss->zs_chan_a->curregs[5] |= (RTS | DTR); - else - ss->zs_chan_a->curregs[5] &= ~(RTS | DTR); - write_zsreg(ss->zs_chan_a, 5, ss->zs_chan_a->curregs[5]); + unsigned long flags; + + + save_flags(flags); cli(); + if (info->zs_channel != info->zs_chan_a) { + if (set) { + info->zs_chan_a->curregs[5] |= (which & (RTS | DTR)); + } else { + info->zs_chan_a->curregs[5] &= ~(which & (RTS | DTR)); + } + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); } - return; + restore_flags(flags); } /* Utility routines for the Zilog */ @@ -281,7 +363,7 @@ */ brg = (read_zsreg(channel, 13) << 8); brg |= read_zsreg(channel, 12); - return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor))); + return BRG_TO_BPS(brg, (zs_parms->clock/(ss->clk_divisor))); } /* On receive, this clears errors and the receiver interrupts */ @@ -302,6 +384,8 @@ * ----------------------------------------------------------------------- */ +static int tty_break; /* Set whenever BREAK condition is detected. */ + /* * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. @@ -320,23 +404,59 @@ struct tty_struct *tty = info->tty; unsigned char ch, stat, flag; - while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) { + while ((read_zsreg(info->zs_channel, R0) & Rx_CH_AV) != 0) { stat = read_zsreg(info->zs_channel, R1); ch = read_zsdata(info->zs_channel); -#ifdef CONFIG_KGDB - if (info->kgdb_channel) { - if (ch == 0x03 || ch == '$') - breakpoint(); - if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) - write_zsreg(info->zs_channel, 0, ERR_RES); - return; + if (!tty && !info->hook && !info->hook->rx_char) + continue; + + if (tty_break) { + tty_break = 0; +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) + if (info->line == sercons.index) { + if (!break_pressed) { + break_pressed = jiffies; + goto ignore_char; + } + break_pressed = 0; + } +#endif + flag = TTY_BREAK; + if (info->flags & ZILOG_SAK) + do_SAK(tty); + } else { + if (stat & Rx_OVR) { + flag = TTY_OVERRUN; + } else if (stat & FRM_ERR) { + flag = TTY_FRAME; + } else if (stat & PAR_ERR) { + flag = TTY_PARITY; + } else + flag = 0; + if (flag) + /* reset the error indication */ + write_zsreg(info->zs_channel, R0, ERR_RES); + } + +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) + if (break_pressed && info->line == sercons.index) { + if (ch != 0 && + time_before(jiffies, break_pressed + HZ*5)) { + handle_sysrq(ch, regs, NULL, NULL); + break_pressed = 0; + goto ignore_char; + } + break_pressed = 0; } #endif - if (!tty) - continue; + if (info->hook && info->hook->rx_char) { + (*info->hook->rx_char)(ch, flag); + return; + } + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { static int flip_buf_ovf; ++flip_buf_ovf; @@ -348,26 +468,18 @@ if (flip_max_cnt < tty->flip.count) flip_max_cnt = tty->flip.count; } - if (stat & Rx_OVR) { - flag = TTY_OVERRUN; - } else if (stat & FRM_ERR) { - flag = TTY_FRAME; - } else if (stat & PAR_ERR) { - flag = TTY_PARITY; - } else - flag = 0; - if (flag) - /* reset the error indication */ - write_zsreg(info->zs_channel, 0, ERR_RES); + *tty->flip.flag_buf_ptr++ = flag; *tty->flip.char_buf_ptr++ = ch; + ignore_char: } - tty_flip_buffer_push(tty); + if (tty) + tty_flip_buffer_push(tty); } static void transmit_chars(struct dec_serial *info) { - if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) + if ((read_zsreg(info->zs_channel, R0) & Tx_BUF_EMP) == 0) return; info->tx_active = 0; @@ -379,8 +491,9 @@ return; } - if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) { - write_zsreg(info->zs_channel, 0, RES_Tx_P); + if ((info->xmit_cnt <= 0) || (info->tty && info->tty->stopped) + || info->tx_stopped) { + write_zsreg(info->zs_channel, R0, RES_Tx_P); return; } /* Send char */ @@ -395,45 +508,48 @@ static _INLINE_ void status_handle(struct dec_serial *info) { - unsigned char status; + unsigned char stat; /* Get status from Read Register 0 */ - status = read_zsreg(info->zs_channel, 0); + stat = read_zsreg(info->zs_channel, R0); + + if (stat & BRK_ABRT) { +#ifdef SERIAL_DEBUG_INTR + printk("handling break...."); +#endif + tty_break = 1; + } - /* FIXEM: Check for DCD transitions */ - if (((status ^ info->read_reg_zero) & DCD) != 0 - && info->tty && !C_CLOCAL(info->tty)) { - if (status & DCD) { - wake_up_interruptible(&info->open_wait); - } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { - if (info->tty) + if (info->zs_channel != info->zs_chan_a) { + + /* FIXEM: Check for DCD transitions */ + if (((stat ^ info->read_reg_zero) & DCD) != 0 + && info->tty && !C_CLOCAL(info->tty)) { + if (stat & DCD) { + wake_up_interruptible(&info->open_wait); + } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { tty_hangup(info->tty); + } } - } - /* Check for CTS transitions */ - if (info->tty && C_CRTSCTS(info->tty)) { - /* - * For some reason, on the Power Macintosh, - * it seems that the CTS bit is 1 when CTS is - * *negated* and 0 when it is asserted. - * The DCD bit doesn't seem to be inverted - * like this. - */ - if ((status & CTS) != 0) { - if (info->tx_stopped) { - info->tx_stopped = 0; - if (!info->tx_active) - transmit_chars(info); + /* Check for CTS transitions */ + if (info->tty && C_CRTSCTS(info->tty)) { + if ((stat & CTS) != 0) { + if (info->tx_stopped) { + info->tx_stopped = 0; + if (!info->tx_active) + transmit_chars(info); + } + } else { + info->tx_stopped = 1; } - } else { - info->tx_stopped = 1; } + } /* Clear status condition... */ - write_zsreg(info->zs_channel, 0, RES_EXT_INT); - info->read_reg_zero = status; + write_zsreg(info->zs_channel, R0, RES_EXT_INT); + info->read_reg_zero = stat; } /* @@ -459,7 +575,7 @@ shift = 0; /* Channel B */ for (;;) { - zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; + zs_intreg = read_zsreg(info->zs_chan_a, R3) >> shift; if ((zs_intreg & CHAN_IRQMASK) == 0) break; @@ -473,8 +589,31 @@ status_handle(info); } } + + /* Why do we need this ? */ + write_zsreg(info->zs_channel, 0, RES_H_IUS); } +#ifdef ZS_DEBUG_REGS +void zs_dump (void) { + int i, j; + for (i = 0; i < zs_channels_found; i++) { + struct dec_zschannel *ch = &zs_channels[i]; + if ((long)ch->control == UNI_IO_BASE+UNI_SCC1A_CTRL) { + for (j = 0; j < 15; j++) { + printk("W%d = 0x%x\t", + j, (int)ch->curregs[j]); + } + for (j = 0; j < 15; j++) { + printk("R%d = 0x%x\t", + j, (int)read_zsreg(ch,j)); + } + printk("\n\n"); + } + } +} +#endif + /* * ------------------------------------------------------------------- * Here ends the serial interrupt routines. @@ -559,7 +698,7 @@ } } -static int startup(struct dec_serial * info) +int zs_startup(struct dec_serial * info) { unsigned long flags; @@ -575,7 +714,7 @@ save_flags(flags); cli(); #ifdef SERIAL_DEBUG_OPEN - printk("starting up ttyS%d (irq %d)...", info->line, info->irq); + printk("starting up ttyS%02d (irq %d)...", info->line, info->irq); #endif /* @@ -593,7 +732,7 @@ /* * Turn on RTS and DTR. */ - zs_rtsdtr(info, 1); + zs_rtsdtr(info, RTS | DTR, 1); /* * Finally, enable sequencing and interrupts @@ -664,8 +803,7 @@ info->zs_channel->curregs[5] &= ~TxENAB; write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); if (!info->tty || C_HUPCL(info->tty)) { - info->zs_chan_a->curregs[5] &= ~(DTR | RTS); - write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + zs_rtsdtr(info, RTS | DTR, 0); } if (info->tty) @@ -681,29 +819,45 @@ */ static void change_speed(struct dec_serial *info) { - unsigned short port; unsigned cflag; int i; - int brg; + int brg, bits; unsigned long flags; - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - if (!(port = info->port)) - return; + if (!info->hook) { + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!info->port) + return; + } else { + cflag = info->hook->cflags; + } + i = cflag & CBAUD; + if (i & CBAUDEX) { + i &= ~CBAUDEX; + if (i < 1 || i > 2) { + if (!info->hook) + info->tty->termios->c_cflag &= ~CBAUDEX; + else + info->hook->cflags &= ~CBAUDEX; + } else + i += 15; + } save_flags(flags); cli(); info->zs_baud = baud_table[i]; info->clk_divisor = 16; - - switch (info->zs_baud) { - default: + if (info->zs_baud) { info->zs_channel->curregs[4] = X16CLK; - brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); + brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor); info->zs_channel->curregs[12] = (brg & 255); info->zs_channel->curregs[13] = ((brg >> 8) & 255); + zs_rtsdtr(info, DTR, 1); + } else { + zs_rtsdtr(info, RTS | DTR, 0); + return; } /* byte size and parity */ @@ -711,24 +865,31 @@ info->zs_channel->curregs[5] &= ~TxNBITS_MASK; switch (cflag & CSIZE) { case CS5: + bits = 7; info->zs_channel->curregs[3] |= Rx5; info->zs_channel->curregs[5] |= Tx5; break; case CS6: + bits = 8; info->zs_channel->curregs[3] |= Rx6; info->zs_channel->curregs[5] |= Tx6; break; case CS7: + bits = 9; info->zs_channel->curregs[3] |= Rx7; info->zs_channel->curregs[5] |= Tx7; break; case CS8: default: /* defaults to 8 bits */ + bits = 10; info->zs_channel->curregs[3] |= Rx8; info->zs_channel->curregs[5] |= Tx8; break; } + info->timeout = ((info->xmit_fifo_size*HZ*bits) / info->zs_baud); + info->timeout += HZ/50; /* Add .02 seconds of slop */ + info->zs_channel->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); if (cflag & CSTOPB) { info->zs_channel->curregs[4] |= SB2; @@ -750,7 +911,7 @@ info->zs_channel->curregs[15] &= ~DCDIE; if (cflag & CRTSCTS) { info->zs_channel->curregs[15] |= CTSIE; - if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) + if ((read_zsreg(info->zs_channel, 0) & CTS) == 0) info->tx_stopped = 1; } else { info->zs_channel->curregs[15] &= ~CTSIE; @@ -895,17 +1056,7 @@ } if (C_CRTSCTS(tty)) { - /* - * Here we want to turn off the RTS line. On Macintoshes, - * we only get the DTR line, which goes to both DTR and - * RTS on the modem. RTS doesn't go out to the serial - * port socket. So you should make sure your modem is - * set to ignore DTR if you're using CRTSCTS. - */ - save_flags(flags); cli(); - info->zs_chan_a->curregs[5] &= ~(DTR | RTS); - write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); - restore_flags(flags); + zs_rtsdtr(info, RTS, 0); } } @@ -937,11 +1088,7 @@ } if (C_CRTSCTS(tty)) { - /* Assert RTS and DTR lines */ - save_flags(flags); cli(); - info->zs_chan_a->curregs[5] |= DTR | RTS; - write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); - restore_flags(flags); + zs_rtsdtr(info, RTS, 1); } } @@ -983,7 +1130,7 @@ copy_from_user(&new_serial,new_info,sizeof(new_serial)); old_info = *info; - if (!suser()) { + if (!capable(CAP_SYS_ADMIN)) { if ((new_serial.baud_base != info->baud_base) || (new_serial.type != info->type) || (new_serial.close_delay != info->close_delay) || @@ -1012,7 +1159,7 @@ info->closing_wait = new_serial.closing_wait; check_and_exit: - retval = startup(info); + retval = zs_startup(info); return retval; } @@ -1039,18 +1186,25 @@ static int get_modem_info(struct dec_serial *info, unsigned int *value) { - unsigned char control, status; + unsigned char control, status_a, status_b; unsigned int result; - cli(); - control = info->zs_chan_a->curregs[5]; - status = read_zsreg(info->zs_channel, 0); - sti(); - result = ((control & RTS) ? TIOCM_RTS: 0) - | ((control & DTR) ? TIOCM_DTR: 0) - | ((status & DCD) ? TIOCM_CAR: 0) - | ((status & CTS) ? 0: TIOCM_CTS); - put_user(result,value); + if (info->zs_channel == info->zs_chan_a) + result = 0; + else { + cli(); + control = info->zs_chan_a->curregs[5]; + status_a = read_zsreg(info->zs_chan_a, 0); + status_b = read_zsreg(info->zs_channel, 0); + sti(); + result = ((control & RTS) ? TIOCM_RTS: 0) + | ((control & DTR) ? TIOCM_DTR: 0) + | ((status_b & DCD) ? TIOCM_CAR: 0) + | ((status_a & DCD) ? TIOCM_RNG: 0) + | ((status_a & SYNC_HUNT) ? TIOCM_DSR: 0) + | ((status_b & CTS) ? TIOCM_CTS: 0); + } + put_user(result, value); return 0; } @@ -1063,6 +1217,10 @@ error = verify_area(VERIFY_READ, value, sizeof(int)); if (error) return error; + + if (info->zs_channel == info->zs_chan_a) + return 0; + get_user(arg, value); bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); cli(); @@ -1074,7 +1232,8 @@ info->zs_chan_a->curregs[5] &= ~bits; break; case TIOCMSET: - info->zs_chan_a->curregs[5] = (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits; + info->zs_chan_a->curregs[5] = + (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits; break; default: sti(); @@ -1113,10 +1272,9 @@ int error; struct dec_serial * info = (struct dec_serial *)tty->driver_data; -#ifdef CONFIG_KGDB - if (info->kgdb_channel) + if (info->hook) return -ENODEV; -#endif + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) return -ENODEV; @@ -1210,7 +1368,7 @@ } #ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttys%d, count = %d\n", info->line, info->count); + printk("rs_close ttyS%02d, count = %d\n", info->line, info->count); #endif if ((tty->count == 1) && (info->count != 1)) { /* @@ -1225,7 +1383,7 @@ info->count = 1; } if (--info->count < 0) { - printk("rs_close: bad serial port count for ttys%d: %d\n", + printk("rs_close: bad serial port count for ttyS%02d: %d\n", info->line, info->count); info->count = 0; } @@ -1415,7 +1573,7 @@ retval = 0; add_wait_queue(&info->open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttys%d, count = %d\n", + printk("block_til_ready before block: ttyS%02d, count = %d\n", info->line, info->count); #endif cli(); @@ -1427,7 +1585,7 @@ cli(); if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && (tty->termios->c_cflag & CBAUD)) - zs_rtsdtr(info, 1); + zs_rtsdtr(info, RTS | DTR, 1); sti(); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || @@ -1451,7 +1609,7 @@ break; } #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttys%d, count = %d\n", + printk("block_til_ready blocking: ttyS%02d, count = %d\n", info->line, info->count); #endif schedule(); @@ -1462,7 +1620,7 @@ info->count++; info->blocked_open--; #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttys%d, count = %d\n", + printk("block_til_ready after blocking: ttyS%02d, count = %d\n", info->line, info->count); #endif if (retval) @@ -1487,10 +1645,9 @@ return -ENODEV; info = zs_soft + line; -#ifdef CONFIG_KGDB - if (info->kgdb_channel) + if (info->hook) return -ENODEV; -#endif + if (serial_paranoia_check(info, tty->device, "rs_open")) return -ENODEV; #ifdef SERIAL_DEBUG_OPEN @@ -1520,7 +1677,7 @@ /* * Start up serial port */ - retval = startup(info); + retval = zs_startup(info); if (retval) return retval; @@ -1552,7 +1709,7 @@ info->pgrp = current->pgrp; #ifdef SERIAL_DEBUG_OPEN - printk("rs_open ttys%d successful...", info->line); + printk("rs_open ttyS%02d successful...", info->line); #endif /* tty->low_latency = 1; */ return 0; @@ -1562,7 +1719,7 @@ static void __init show_serial_version(void) { - printk("DECstation Z8530 serial driver version 0.03\n"); + printk("DECstation Z8530 serial driver version 0.05\n"); } /* Initialize Z8530s zs_channels @@ -1576,7 +1733,7 @@ /* * did we get here by accident? */ - if(!IOASIC) { + if(!BUS_PRESENT) { printk("Not on JUNKIO machine, skipping probe_sccs\n"); return; } @@ -1587,19 +1744,36 @@ * system_base for this case :-(. HK */ switch(mips_machtype) { +#ifdef CONFIG_DECSTATION case MACH_DS5000_2X0: system_base = 0xbf800000; n_chips = 2; + zs_parms = &ds_parms; break; case MACH_DS5000_1XX: system_base = 0xbc000000; n_chips = 2; + zs_parms = &ds_parms; break; case MACH_DS5000_XX: system_base = 0xbc000000; n_chips = 1; + zs_parms = &ds_parms; + break; +#endif +#ifdef CONFIG_BAGET_MIPS + case MACH_BAGET202: + system_base = UNI_IO_BASE; + n_chips = 2; + zs_parms = &baget_parms; + zs_init_regs[2] = 0x8; break; +#endif + default: + panic("zs: unsupported bus"); } + if (!zs_parms) + panic("zs: uninitialized parms"); pp = &zs_chain; @@ -1610,16 +1784,44 @@ /* * The sccs reside on the high byte of the 16 bit IOBUS */ - zs_channels[n_channels].control = (volatile unsigned char *) - system_base + (0 == chip ? SCC0 : SCC1) + (0 == channel ? 1 : 9); - zs_channels[n_channels].data = zs_channels[n_channels].control + 4; + zs_channels[n_channels].control = + (volatile unsigned char *)system_base + + (0 == chip ? zs_parms->scc0 : zs_parms->scc1) + + (0 == channel ? zs_parms->channel_a_offset : + zs_parms->channel_b_offset); + zs_channels[n_channels].data = + zs_channels[n_channels].control + 4; + +#ifndef CONFIG_SERIAL_CONSOLE + /* + * We're called early and memory managment isn't up, yet. + * Thus check_region would fail. + */ + if (check_region((unsigned long) + zs_channels[n_channels].control, + ZS_CHAN_IO_SIZE) < 0) { + panic("SCC I/O region is not free"); + } + request_region((unsigned long) + zs_channels[n_channels].control, + ZS_CHAN_IO_SIZE, "SCC"); +#endif zs_soft[n_channels].zs_channel = &zs_channels[n_channels]; - zs_soft[n_channels].irq = SERIAL; + zs_soft[n_channels].irq = zs_parms->irq; - if (0 == channel) - zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels+1]; + /* + * Identification of channel A. Location of channel A + * inside chip depends on mapping of internal address + * the chip decodes channels by. + * CHANNEL_A_NR returns either 0 (in case of + * DECstations) or 1 (in case of Baget). + */ + if (CHANNEL_A_NR == channel) + zs_soft[n_channels].zs_chan_a = + &zs_channels[n_channels+1-2*CHANNEL_A_NR]; else - zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels]; + zs_soft[n_channels].zs_chan_a = + &zs_channels[n_channels]; *pp = &zs_soft[n_channels]; pp = &zs_soft[n_channels].zs_next; @@ -1639,9 +1841,9 @@ /* save_and_cli(flags); for (n = 0; n < zs_channels_found; n++) { if (((int)zs_channels[n].control & 0xf) == 1) { - write_zsreg(zs_soft[channel].zs_chan_a, R9, FHWRES); - udelay(10000); - write_zsreg(zs_soft[channel].zs_chan_a, R9, 0); + write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES); + mdelay(10); + write_zsreg(zs_soft[n].zs_chan_a, R9, 0); } load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs); } @@ -1655,7 +1857,7 @@ unsigned long flags; struct dec_serial *info; - if(!IOASIC) + if(!BUS_PRESENT) return -ENODEV; /* Setup base handler, and timer table. */ @@ -1672,7 +1874,11 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; +#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) + serial_driver.name = "tts/%d"; +#else serial_driver.name = "ttyS"; +#endif serial_driver.major = TTY_MAJOR; serial_driver.minor_start = 64; serial_driver.num = zs_channels_found; @@ -1682,7 +1888,7 @@ serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; serial_driver.refcount = &serial_refcount; serial_driver.table = serial_table; serial_driver.termios = serial_termios; @@ -1710,7 +1916,11 @@ * major number and the subtype code. */ callout_driver = serial_driver; +#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) + callout_driver.name = "cua/%d"; +#else callout_driver.name = "cua"; +#endif callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; @@ -1722,36 +1932,26 @@ save_flags(flags); cli(); for (channel = 0; channel < zs_channels_found; ++channel) { -#ifdef CONFIG_KGDB - if (zs_soft[channel].kgdb_channel) { - continue; - } -#endif + if (zs_soft[channel].hook && + zs_soft[channel].hook->init_channel) + (*zs_soft[channel].hook->init_channel) + (&zs_soft[channel]); + zs_soft[channel].clk_divisor = 16; zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); - if (request_irq(SERIAL, rs_interrupt, SA_SHIRQ, + if (request_irq(zs_parms->irq, rs_interrupt, SA_SHIRQ, "SCC", &zs_soft[channel])) printk(KERN_ERR "decserial: can't get irq %d\n", - SERIAL); - - /* If console serial line, then enable interrupts. */ -/* if (zs_soft[channel].is_cons) { - write_zsreg(zs_soft[channel].zs_channel, R1, - (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); - write_zsreg(zs_soft[channel].zs_channel, R9, - (VIS | MIE)); - } -*/ + zs_parms->irq); } for (info = zs_chain, i = 0; info; info = info->zs_next, i++) { -#ifdef CONFIG_KGDB - if (info->kgdb_channel) { + if (info->hook && info->hook->init_info) { + (*info->hook->init_info)(info); continue; } -#endif info->magic = SERIAL_MAGIC; info->port = (int) info->zs_channel->control; info->line = i; @@ -1765,13 +1965,18 @@ info->blocked_open = 0; info->tqueue.routine = do_softint; info->tqueue.data = info; - info->callout_termios =callout_driver.init_termios; + info->callout_termios = callout_driver.init_termios; info->normal_termios = serial_driver.init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); - printk("tty%02d at 0x%08x (irq = %d)", info->line, + printk("ttyS%02d at 0x%08x (irq = %d)", info->line, info->port, info->irq); printk(" is a Z85C30 SCC\n"); + tty_register_devfs(&serial_driver, 0, + serial_driver.minor_start + info->line); + tty_register_devfs(&callout_driver, 0, + callout_driver.minor_start + info->line); + } restore_flags(flags); @@ -1795,38 +2000,116 @@ } /* - * ------------------------------------------------------------ - * Serial console driver - * ------------------------------------------------------------ + * polling I/O routines */ -#ifdef CONFIG_SERIAL_CONSOLE +static int +zs_poll_tx_char(struct dec_serial *info, unsigned char ch) +{ + struct dec_zschannel *chan = info->zs_channel; + int ret; + if(chan) { + int loops = 10000; +// int nine = read_zsreg(chan, R9); -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - */ + RECOVERY_DELAY; +// write_zsreg(chan, R9, nine & ~MIE); + wbflush(); + RECOVERY_DELAY; + + while (!(*(chan->control) & Tx_BUF_EMP) && --loops) + RECOVERY_DELAY; + + if (loops) { + ret = 0; + *(chan->data) = ch; + wbflush(); + RECOVERY_DELAY; + } else + ret = -EAGAIN; + +// write_zsreg(chan, R9, nine); + wbflush(); + RECOVERY_DELAY; + + return ret; + } -/* This is for console output */ -static void -zs_console_putchar(struct dec_serial *info, char ch) + return -ENODEV; +} + +static int +zs_poll_rx_char(struct dec_serial *info) { - int loops = 10000; - unsigned long flags; + struct dec_zschannel *chan = info->zs_channel; + int ret; - if(!info->zs_channel) - return; + if(chan) { + int loops = 10000; - save_flags(flags); cli(); + while((read_zsreg(chan, 0) & Rx_CH_AV) == 0) + loops--; - while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops) - RECOVERY_DELAY; - *(info->zs_channel->data) = ch; - wbflush(); RECOVERY_DELAY; + if (loops) + ret = read_zsdata(chan); + else + ret = -EAGAIN; - restore_flags(flags); + return ret; + } else + return -ENODEV; +} + +unsigned int register_zs_hook(unsigned int channel, struct zs_hook *hook) +{ + struct dec_serial *info = &zs_soft[channel]; + + if (info->hook) { + printk(__FUNCTION__": line %d has already a hook registered\n", channel); + + return 0; + } else { + info->hook = hook; + + if (zs_chain == 0) + probe_sccs(); + + if (!(info->flags & ZILOG_INITIALIZED)) + zs_startup(info); + + hook->poll_rx_char = zs_poll_rx_char; + hook->poll_tx_char = zs_poll_tx_char; + + return 1; + } +} + +unsigned int unregister_zs_hook(unsigned int channel) +{ + struct dec_serial *info = &zs_soft[channel]; + + if (info->hook) { + info->hook = NULL; + return 1; + } else { + printk(__FUNCTION__": trying to unregister hook on line %d," + " but none is registered\n", channel); + return 0; + } } +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ +#ifdef CONFIG_SERIAL_CONSOLE + + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + */ static void serial_console_write(struct console *co, const char *s, unsigned count) { @@ -1835,28 +2118,11 @@ info = zs_soft + co->index; -#if 0 - /* - * disable master interrupt if necessary - */ - nine = info->zs_channel->curregs[9]; - if(nine & MIE) - write_zsreg(info->zs_channel, R9, nine & ~MIE); -#endif - /* - * do it - */ for (i = 0; i < count; i++, s++) { if(*s == '\n') - zs_console_putchar(info, '\r'); - zs_console_putchar(info, *s); + zs_poll_tx_char(info, '\r'); + zs_poll_tx_char(info, *s); } - /* - * restore master interrupt enable - */ -#if 0 - write_zsreg(info->zs_channel, R9, nine); -#endif } /* @@ -1864,7 +2130,11 @@ */ static int serial_console_wait_key(struct console *co) { - return 0; + struct dec_serial *info; + + info = zs_soft + co->index; + + return zs_poll_rx_char(info); } static kdev_t serial_console_device(struct console *c) @@ -1888,7 +2158,7 @@ char *s; unsigned long flags; - if(!IOASIC) + if(!BUS_PRESENT) return -ENODEV; info = zs_soft + co->index; @@ -1963,7 +2233,7 @@ /* * Turn on RTS and DTR. */ - zs_rtsdtr(info, 1); + zs_rtsdtr(info, RTS | DTR, 1); /* * Finally, enable sequencing @@ -2017,6 +2287,18 @@ #endif /* ifdef CONFIG_SERIAL_CONSOLE */ #ifdef CONFIG_KGDB +struct dec_zschannel *zs_kgdbchan; +static unsigned char scc_inittab[] = { + 9, 0x80, /* reset A side (CHRA) */ + 13, 0, /* set baud rate divisor */ + 12, 1, + 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */ + 11, 0x50, /* clocks = br gen (RCBR | TCBR) */ + 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */ + 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/ + 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/ +}; + /* These are for receiving and sending characters under the kgdb * source level kernel debugger. */ @@ -2051,6 +2333,25 @@ write_zsreg(chan, 1, one); write_zsreg(chan, 9, nine); } + +static int kgdbhook_init_channel(struct dec_serial* info) +{ + return 0; +} + +static void kgdbhook_init_info(struct dec_serial* info) +{ +} + +static void kgdbhook_rx_char(struct dec_serial* info, + unsigned char ch, unsigned char stat) +{ + if (ch == 0x03 || ch == '$') + breakpoint(); + if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) + write_zsreg(info->zs_channel, 0, ERR_RES); +} + /* This sets up the serial port we're using, and turns on * interrupts for that channel, so kgdb is usable once we're done. */ @@ -2059,7 +2360,7 @@ int brg; int i, x; volatile char *sccc = ms->control; - brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + brg = BPS_TO_BRG(bps, zs_parms->clock/16); printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg); for (i = 20000; i != 0; --i) { x = *sccc; eieio(); @@ -2074,6 +2375,13 @@ * for /dev/ttyb which is determined in setup_arch() from the * boot command line flags. */ +struct zs_hook zs_kgdbhook = { + init_channel : kgdbhook_init_channel, + init_info : kgdbhook_init_info, + cflags : B38400|CS8|CLOCAL, + rx_char : kgdbhook_rx_char, +} + void __init zs_kgdb_hook(int tty_num) { /* Find out how many Z8530 SCCs we have */ @@ -2084,11 +2392,12 @@ zs_soft[tty_num].change_needed = 0; zs_soft[tty_num].clk_divisor = 16; zs_soft[tty_num].zs_baud = 38400; - zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */ - zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */ + zs_soft[tty_num].hook = &zs_kgdbhook; /* This runs kgdb */ /* Turn on transmitter/receiver at 8-bits/char */ kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400); printk("KGDB: on channel %d initialized\n", tty_num); set_debug_traps(); /* init stub */ } #endif /* ifdef CONFIG_KGDB */ + + diff -u --recursive --new-file v2.4.9/linux/drivers/tc/zs.h linux/drivers/tc/zs.h --- v2.4.9/linux/drivers/tc/zs.h Sat May 13 08:31:25 2000 +++ linux/drivers/tc/zs.h Mon Aug 27 08:56:31 2001 @@ -89,6 +89,18 @@ unsigned char curregs[NUM_ZSREGS]; }; +struct dec_serial; + +struct zs_hook { + int (*init_channel)(struct dec_serial* info); + void (*init_info)(struct dec_serial* info); + void (*rx_char)(unsigned char ch, unsigned char stat); + int (*poll_rx_char)(struct dec_serial* info); + int (*poll_tx_char)(struct dec_serial* info, + unsigned char ch); + unsigned cflags; +}; + struct dec_serial { struct dec_serial *zs_next; /* For IRQ servicing chain */ struct dec_zschannel *zs_channel; /* Channel registers */ @@ -97,7 +109,7 @@ char soft_carrier; /* Use soft carrier on this channel */ char break_abort; /* Is serial console in, so process brk/abrt */ - char kgdb_channel; /* Kgdb is running on this channel */ + struct zs_hook *hook; /* Hook on this channel */ char is_cons; /* Is this our console. */ unsigned char tx_active; /* character is being xmitted */ unsigned char tx_stopped; /* output is suspended */ diff -u --recursive --new-file v2.4.9/linux/drivers/telephony/Config.in linux/drivers/telephony/Config.in --- v2.4.9/linux/drivers/telephony/Config.in Wed Dec 29 17:13:59 1999 +++ linux/drivers/telephony/Config.in Fri Sep 7 09:28:37 2001 @@ -6,4 +6,5 @@ tristate 'Linux telephony support' CONFIG_PHONE dep_tristate 'QuickNet Internet LineJack/PhoneJack support' CONFIG_PHONE_IXJ $CONFIG_PHONE +dep_tristate 'QuickNet Internet LineJack/PhoneJack PCMCIA support' CONFIG_PHONE_IXJ_PCMCIA $CONFIG_PHONE_IXJ endmenu diff -u --recursive --new-file v2.4.9/linux/drivers/telephony/Makefile linux/drivers/telephony/Makefile --- v2.4.9/linux/drivers/telephony/Makefile Fri Dec 29 14:07:23 2000 +++ linux/drivers/telephony/Makefile Fri Sep 7 09:28:37 2001 @@ -10,10 +10,11 @@ obj-n := obj-m := obj- := -export-objs := phonedev.o +export-objs := phonedev.o ixj.o obj-$(CONFIG_PHONE) += phonedev.o obj-$(CONFIG_PHONE_IXJ) += ixj.o +obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o O_TARGET := telephony.o diff -u --recursive --new-file v2.4.9/linux/drivers/telephony/ixj-ver.h linux/drivers/telephony/ixj-ver.h --- v2.4.9/linux/drivers/telephony/ixj-ver.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/telephony/ixj-ver.h Fri Sep 7 09:28:37 2001 @@ -0,0 +1,4 @@ +/* configuration management identifiers */ +#define IXJ_VER_MAJOR 1 +#define IXJ_VER_MINOR 0 +#define IXJ_BLD_VER 1 diff -u --recursive --new-file v2.4.9/linux/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c --- v2.4.9/linux/drivers/telephony/ixj.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/telephony/ixj.c Fri Sep 7 09:28:37 2001 @@ -1,10 +1,12 @@ /**************************************************************************** * ixj.c * - * Device Driver for the Internet PhoneJACK and - * Internet LineJACK Telephony Cards. + * Device Driver for Quicknet Technologies, Inc.'s Telephony cards + * including the Internet PhoneJACK, Internet PhoneJACK Lite, + * Internet PhoneJACK PCI, Internet LineJACK, Internet PhoneCARD and + * SmartCABLE * - * (c) Copyright 1999-2000 Quicknet Technologies, Inc. + * (c) Copyright 1999-2001 Quicknet Technologies, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,17 +20,17 @@ * John Sellers, * Mike Preston, * - * Fixes: - * Marc Boucher, - * David Huggins-Daines - * + * Fixes: David Huggins-Daines, + * Fabio Ferrari, + * Artis Kugevics, + * * More information about the hardware related to this driver can be found * at our website: http://www.quicknet.net * * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET - * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * TECHNOLOGIES, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY @@ -38,14 +40,215 @@ * ***************************************************************************/ -static char ixj_c_rcsid[] = "$Id: ixj.c,v 3.31 2000/04/14 19:24:47 jaugenst Exp $"; -static char ixj_c_revision[] = "$Revision: 3.31 $"; +static char ixj_c_rcsid[] = "$Id: ixj.c,v 4.7 2001/08/13 06:19:33 craigs Exp $"; +static char ixj_c_revision[] = "$Revision: 4.7 $"; -//#define PERFMON_STATS +/* + * $Log: ixj.c,v $ + * Revision 4.7 2001/08/13 06:19:33 craigs + * Added additional changes from Alan Cox and John Anderson for + * 2.2 to 2.4 cleanup and bounds checking + * + * Revision 4.6 2001/08/13 01:05:05 craigs + * Really fixed PHONE_QUERY_CODEC problem this time + * + * Revision 4.5 2001/08/13 00:11:03 craigs + * Fixed problem in handling of PHONE_QUERY_CODEC, thanks to Shane Anderson + * + * Revision 4.4 2001/08/07 07:58:12 craigs + * Changed back to three digit version numbers + * Added tagbuild target to allow automatic and easy tagging of versions + * + * Revision 4.3 2001/08/07 07:24:47 craigs + * Added ixj-ver.h to allow easy configuration management of driver + * Added display of version number in /prox/ixj + * + * Revision 4.2 2001/08/06 07:07:19 craigs + * Reverted IXJCTL_DSP_TYPE and IXJCTL_DSP_VERSION files to original + * behaviour of returning int rather than short * + * + * Revision 4.1 2001/08/05 00:17:37 craigs + * More changes for correct PCMCIA installation + * Start of changes for backward Linux compatibility + * + * Revision 4.0 2001/08/04 12:33:12 craigs + * New version using GNU autoconf + * + * Revision 3.105 2001/07/20 23:14:32 eokerson + * More work on CallerID generation when using ring cadences. + * + * Revision 3.104 2001/07/06 01:33:55 eokerson + * Some bugfixes from Robert Vojta and a few mods to the Makefile. + * + * Revision 3.103 2001/07/05 19:20:16 eokerson + * Updated HOWTO + * Changed mic gain to 30dB on Internet LineJACK mic/speaker port. + * + * Revision 3.102 2001/07/03 23:51:21 eokerson + * Un-mute mic on Internet LineJACK when in speakerphone mode. + * + * Revision 3.101 2001/07/02 19:26:56 eokerson + * Removed initialiazation of ixjdebug and ixj_convert_loaded so they will go in the .bss instead of the .data + * + * Revision 3.100 2001/07/02 19:18:27 eokerson + * Changed driver to make dynamic allocation possible. We now pass IXJ * between functions instead of array indexes. + * Fixed the way the POTS and PSTN ports interact during a PSTN call to allow local answering. + * Fixed speaker mode on Internet LineJACK. + * + * Revision 3.99 2001/05/09 14:11:16 eokerson + * Fixed kmalloc error in ixj_build_filter_cadence. Thanks David Chan . + * + * Revision 3.98 2001/05/08 19:55:33 eokerson + * Fixed POTS hookstate detection while it is connected to PSTN port. + * + * Revision 3.97 2001/05/08 00:01:04 eokerson + * Fixed kernel oops when sending caller ID data. + * + * Revision 3.96 2001/05/04 23:09:30 eokerson + * Now uses one kernel timer for each card, instead of one for the entire driver. + * + * Revision 3.95 2001/04/25 22:06:47 eokerson + * Fixed squawking at beginning of some G.723.1 calls. + * + * Revision 3.94 2001/04/03 23:42:00 eokerson + * Added linear volume ioctls + * Added raw filter load ioctl + * + * Revision 3.93 2001/02/27 01:00:06 eokerson + * Fixed blocking in CallerID. + * Reduced size of ixj structure for smaller driver footprint. + * + * Revision 3.92 2001/02/20 22:02:59 eokerson + * Fixed isapnp and pcmcia module compatibility for 2.4.x kernels. + * Improved PSTN ring detection. + * Fixed wink generation on POTS ports. + * + * Revision 3.91 2001/02/13 00:55:44 eokerson + * Turn AEC back on after changing frame sizes. + * + * Revision 3.90 2001/02/12 16:42:00 eokerson + * Added ALAW codec, thanks to Fabio Ferrari for the table based converters to make ALAW from ULAW. + * + * Revision 3.89 2001/02/12 15:41:16 eokerson + * Fix from Artis Kugevics - Tone gains were not being set correctly. + * + * Revision 3.88 2001/02/05 23:25:42 eokerson + * Fixed lockup bugs with deregister. + * + * Revision 3.87 2001/01/29 21:00:39 eokerson + * Fix from Fabio Ferrari to properly handle EAGAIN and EINTR during non-blocking write. + * Updated copyright date. + * + * Revision 3.86 2001/01/23 23:53:46 eokerson + * Fixes to G.729 compatibility. + * + * Revision 3.85 2001/01/23 21:30:36 eokerson + * Added verbage about cards supported. + * Removed commands that put the card in low power mode at some times that it should not be in low power mode. + * + * Revision 3.84 2001/01/22 23:32:10 eokerson + * Some bugfixes from David Huggins-Daines, and other cleanups. + * + * Revision 3.83 2001/01/19 14:51:41 eokerson + * Fixed ixj_WriteDSPCommand to decrement usage counter when command fails. + * + * Revision 3.82 2001/01/19 00:34:49 eokerson + * Added verbosity to write overlap errors. + * + * Revision 3.81 2001/01/18 23:56:54 eokerson + * Fixed PSTN line test functions. + * + * Revision 3.80 2001/01/18 22:29:27 eokerson + * Updated AEC/AGC values for different cards. + * + * Revision 3.79 2001/01/17 02:58:54 eokerson + * Fixed AEC reset after Caller ID. + * Fixed Codec lockup after Caller ID on Call Waiting when not using 30ms frames. + * + * Revision 3.78 2001/01/16 19:43:09 eokerson + * Added support for Linux 2.4.x kernels. + * + * Revision 3.77 2001/01/09 04:00:52 eokerson + * Linetest will now test the line, even if it has previously succeded. + * + * Revision 3.76 2001/01/08 19:27:00 eokerson + * Fixed problem with standard cable on Internet PhoneCARD. + * + * Revision 3.75 2000/12/22 16:52:14 eokerson + * Modified to allow hookstate detection on the POTS port when the PSTN port is selected. + * + * Revision 3.74 2000/12/08 22:41:50 eokerson + * Added capability for G729B. + * + * Revision 3.73 2000/12/07 23:35:16 eokerson + * Added capability to have different ring pattern before CallerID data. + * Added hookstate checks in CallerID routines to stop FSK. + * + * Revision 3.72 2000/12/06 19:31:31 eokerson + * Modified signal behavior to only send one signal per event. + * + * Revision 3.71 2000/12/06 03:23:08 eokerson + * Fixed CallerID on Call Waiting. + * + * Revision 3.70 2000/12/04 21:29:37 eokerson + * Added checking to Smart Cable gain functions. + * + * Revision 3.69 2000/12/04 21:05:20 eokerson + * Changed ixjdebug levels. + * Added ioctls to change gains in Internet Phone CARD Smart Cable. + * + * Revision 3.68 2000/12/04 00:17:21 craigs + * Changed mixer voice gain to +6dB rather than 0dB + * + * Revision 3.67 2000/11/30 21:25:51 eokerson + * Fixed write signal errors. + * + * Revision 3.66 2000/11/29 22:42:44 eokerson + * Fixed PSTN ring detect problems. + * + * Revision 3.65 2000/11/29 07:31:55 craigs + * Added new 425Hz filter co-efficients + * Added card-specific DTMF prescaler initialisation + * + * Revision 3.64 2000/11/28 14:03:32 craigs + * Changed certain mixer initialisations to be 0dB rather than 12dB + * Added additional information to /proc/ixj + * + * Revision 3.63 2000/11/28 11:38:41 craigs + * Added display of AEC modes in AUTO and AGC mode + * + * Revision 3.62 2000/11/28 04:05:44 eokerson + * Improved PSTN ring detection routine. + * + * Revision 3.61 2000/11/27 21:53:12 eokerson + * Fixed flash detection. + * + * Revision 3.60 2000/11/27 15:57:29 eokerson + * More work on G.729 load routines. + * + * Revision 3.59 2000/11/25 21:55:12 eokerson + * Fixed errors in G.729 load routine. + * + * Revision 3.58 2000/11/25 04:08:29 eokerson + * Added board locks around G.729 and TS85 load routines. + * + * Revision 3.57 2000/11/24 05:35:17 craigs + * Added ability to retrieve mixer values on LineJACK + * Added complete initialisation of all mixer values at startup + * Fixed spelling mistake + * + * Revision 3.56 2000/11/23 02:52:11 robertj + * Added cvs change log keyword. + * Fixed bug in capabilities list when using G.729 module. + * + */ + +#include "ixj-ver.h" + +#define PERFMON_STATS #define IXJDEBUG 0 #define MAXRINGS 5 -#include #include #include @@ -68,34 +271,128 @@ #include #include -#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) -#include -#include -#include -#include -#include -#endif - -#ifdef CONFIG_ISAPNP #include -#endif #include "ixj.h" #define TYPE(dev) (MINOR(dev) >> 4) #define NUM(dev) (MINOR(dev) & 0xf) -static int ixjdebug = 0; +static int ixjdebug; static int hertz = HZ; static int samplerate = 100; MODULE_PARM(ixjdebug, "i"); -static IXJ* ixj[IXJMAX]; +/************************************************************************ +* +* ixjdebug meanings are now bit mapped instead of level based +* Values can be or'ed together to turn on multiple messages +* +* bit 0 (0x0001) = any failure +* bit 1 (0x0002) = general messages +* bit 2 (0x0004) = POTS ringing related +* bit 3 (0x0008) = PSTN events +* bit 4 (0x0010) = PSTN Cadence state details +* bit 5 (0x0020) = Tone detection triggers +* bit 6 (0x0040) = Tone detection cadence details +* bit 7 (0x0080) = ioctl tracking +* bit 8 (0x0100) = signal tracking +* bit 9 (0x0200) = CallerID generation details +* +************************************************************************/ + +#ifdef IXJ_DYN_ALLOC -static struct timer_list ixj_timer; +static IXJ *ixj[IXJMAX]; +#define get_ixj(b) ixj[(b)] -int ixj_convert_loaded = 0; +/* + * Allocate a free IXJ device + */ + +static IXJ *ixj_alloc() +{ + for(cnt=0; cntDSPbase) + { + j = kmalloc(sizeof(IXJ), GFP_KERNEL); + if (j == NULL) + return NULL; + ixj[cnt] = j; + return j; + } + } + return NULL; +} + +static void ixj_fsk_free(IXJ *j) +{ + if(j->fskdata != NULL) { + kfree(j->fskdata); + j->fskdata = NULL; + } +} + +static void ixj_fsk_alloc(IXJ *j) +{ + if(!j->fskdata) { + j->fskdata = kmalloc(8000, GFP_KERNEL); + if (!j->fskdata) { + if(ixjdebug & 0x0200) { + printk("IXJ phone%d - allocate failed\n", j->board); + } + return; + } else { + j->fsksize = 8000; + if(ixjdebug & 0x0200) { + printk("IXJ phone%d - allocate succeded\n", j->board); + } + } + } +} + +#else + +static IXJ ixj[IXJMAX]; +#define get_ixj(b) (&ixj[(b)]) + +/* + * Allocate a free IXJ device + */ + +static IXJ *ixj_alloc(void) +{ + int cnt; + for(cnt=0; cntfsksize = 8000; +} + +#endif + +#ifdef PERFMON_STATS +#define ixj_perfmon(x) ((x)++) +#else +#deifne ixj_perfmon(x) do {} while(0); +#endif + +static int ixj_convert_loaded; + +static int ixj_WriteDSPCommand(unsigned short, IXJ *j); /************************************************************************ * @@ -104,7 +401,7 @@ * ************************************************************************/ -static int Stub(IXJ * j, unsigned long arg) +static int Stub(IXJ * J, unsigned long arg) { return 0; } @@ -120,8 +417,8 @@ static void ixj_read_frame(IXJ *j); static void ixj_write_frame(IXJ *j); -static void ixj_init_timer(void); -static void ixj_add_timer(void); +static void ixj_init_timer(IXJ *j); +static void ixj_add_timer(IXJ * j); static void ixj_timeout(unsigned long ptr); static int read_filters(IXJ *j); static int LineMonitor(IXJ *j); @@ -132,12 +429,15 @@ static int ixj_record_start(IXJ *j); static void ixj_record_stop(IXJ *j); static void set_rec_volume(IXJ *j, int volume); +static int get_rec_volume(IXJ *j); +static int set_rec_codec(IXJ *j, int rate); static void ixj_vad(IXJ *j, int arg); static int ixj_play_start(IXJ *j); static void ixj_play_stop(IXJ *j); static int ixj_set_tone_on(unsigned short arg, IXJ *j); static int ixj_set_tone_off(unsigned short, IXJ *j); static int ixj_play_tone(IXJ *j, char tone); +static void ixj_aec_start(IXJ *j, int level); static int idle(IXJ *j); static void ixj_ring_on(IXJ *j); static void ixj_ring_off(IXJ *j); @@ -147,6 +447,7 @@ static void ixj_dialtone(IXJ *j); static void ixj_cpt_stop(IXJ *j); static char daa_int_read(IXJ *j); +static char daa_CR_read(IXJ *j, int cr); static int daa_set_mode(IXJ *j, int mode); static int ixj_linetest(IXJ *j); static int ixj_daa_write(IXJ *j); @@ -158,22 +459,24 @@ static void DAA_Coeff_Australia(IXJ *j); static void DAA_Coeff_Japan(IXJ *j); static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf); +static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr); static int ixj_init_tone(IXJ *j, IXJ_TONE * ti); static int ixj_build_cadence(IXJ *j, IXJ_CADENCE * cp); static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * cp); -// Serial Control Interface funtions +/* Serial Control Interface funtions */ static int SCI_Control(IXJ *j, int control); static int SCI_Prepare(IXJ *j); static int SCI_WaitHighSCI(IXJ *j); static int SCI_WaitLowSCI(IXJ *j); static DWORD PCIEE_GetSerialNumber(WORD wAddress); static int ixj_PCcontrol_wait(IXJ *j); +static void ixj_pre_cid(IXJ *j); static void ixj_write_cid(IXJ *j); static void ixj_write_cid_bit(IXJ *j, int bit); static int set_base_frame(IXJ *j, int size); static int set_play_codec(IXJ *j, int rate); static void set_rec_depth(IXJ *j, int depth); -static void set_play_depth(IXJ *j, int depth); +static int ixj_mixer(long val, IXJ *j); /************************************************************************ CT8020/CT8021 Host Programmers Model @@ -186,58 +489,95 @@ 8-9 Hardware Status Register Read Only A-B Hardware Control Register Read Write C-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write Only -E-F Host Receive (Read) Data Buffer Access Port (buffer input) Read Only +E-F Host Recieve (Read) Data Buffer Access Port (buffer input) Read Only ************************************************************************/ -extern __inline__ void ixj_read_HSR(IXJ *j) +static inline void ixj_read_HSR(IXJ *j) { j->hsr.bytes.low = inb_p(j->DSPbase + 8); j->hsr.bytes.high = inb_p(j->DSPbase + 9); } -extern __inline__ int IsControlReady(IXJ *j) +static inline int IsControlReady(IXJ *j) { ixj_read_HSR(j); return j->hsr.bits.controlrdy ? 1 : 0; } -extern __inline__ int IsPCControlReady(IXJ *j) +static inline int IsPCControlReady(IXJ *j) { j->pccr1.byte = inb_p(j->XILINXbase + 3); return j->pccr1.bits.crr ? 1 : 0; } -extern __inline__ int IsStatusReady(IXJ *j) +static inline int IsStatusReady(IXJ *j) { ixj_read_HSR(j); return j->hsr.bits.statusrdy ? 1 : 0; } -extern __inline__ int IsRxReady(IXJ *j) +static inline int IsRxReady(IXJ *j) { ixj_read_HSR(j); -#ifdef PERFMON_STATS - ++j->rxreadycheck; -#endif + ixj_perfmon(j->rxreadycheck); return j->hsr.bits.rxrdy ? 1 : 0; } -extern __inline__ int IsTxReady(IXJ *j) +static inline int IsTxReady(IXJ *j) { ixj_read_HSR(j); -#ifdef PERFMON_STATS - ++j->txreadycheck; -#endif + ixj_perfmon(j->txreadycheck); return j->hsr.bits.txrdy ? 1 : 0; } -extern __inline__ void set_play_volume(IXJ *j, int volume) +static inline void set_play_volume(IXJ *j, int volume) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone%d Setting Play Volume to 0x%4.4x\n", j->board, volume); ixj_WriteDSPCommand(0xCF02, j); ixj_WriteDSPCommand(volume, j); } -extern __inline__ void set_play_depth(IXJ *j, int depth) +static int set_play_volume_linear(IXJ *j, int volume) +{ + int newvolume, dspplaymax; + + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Play Volume to 0x%4.4x\n", j->board, volume); + if(volume > 100 || volume < 0) { + return -1; + } + + /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ + switch (j->cardtype) { + case QTI_PHONEJACK: + dspplaymax = 0x380; + break; + case QTI_LINEJACK: + if(j->port == PORT_PSTN) { + dspplaymax = 0x48; + } else { + dspplaymax = 0x100; + } + break; + case QTI_PHONEJACK_LITE: + dspplaymax = 0x380; + break; + case QTI_PHONEJACK_PCI: + dspplaymax = 0x6C; + break; + case QTI_PHONECARD: + dspplaymax = 0x50; + break; + default: + return -1; + } + newvolume = (dspplaymax * volume) / 100; + set_play_volume(j, newvolume); + return 0; +} + +static inline void set_play_depth(IXJ *j, int depth) { if (depth > 60) depth = 60; @@ -246,13 +586,48 @@ ixj_WriteDSPCommand(0x5280 + depth, j); } -extern __inline__ int get_play_volume(IXJ *j) +static inline int get_play_volume(IXJ *j) { ixj_WriteDSPCommand(0xCF00, j); return j->ssr.high << 8 | j->ssr.low; } -extern __inline__ BYTE SLIC_GetState(IXJ *j) +static int get_play_volume_linear(IXJ *j) +{ + int volume, newvolume, dspplaymax; + + /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ + switch (j->cardtype) { + case QTI_PHONEJACK: + dspplaymax = 0x380; + break; + case QTI_LINEJACK: + if(j->port == PORT_PSTN) { + dspplaymax = 0x48; + } else { + dspplaymax = 0x100; + } + break; + case QTI_PHONEJACK_LITE: + dspplaymax = 0x380; + break; + case QTI_PHONEJACK_PCI: + dspplaymax = 0x6C; + break; + case QTI_PHONECARD: + dspplaymax = 100; + break; + default: + return -1; + } + volume = get_play_volume(j); + newvolume = (volume * 100) / dspplaymax; + if(newvolume > 100) + newvolume = 100; + return newvolume; +} + +static inline BYTE SLIC_GetState(IXJ *j) { if (j->cardtype == QTI_PHONECARD) { j->pccr1.byte = 0; @@ -295,7 +670,7 @@ fRetVal = TRUE; } break; - case PLD_SLIC_STATE_OHT: // On-hook transmit + case PLD_SLIC_STATE_OHT: /* On-hook transmit */ case PLD_SLIC_STATE_STANDBY: case PLD_SLIC_STATE_ACTIVE: @@ -307,9 +682,9 @@ j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0; fRetVal = TRUE; break; - case PLD_SLIC_STATE_APR: // Active polarity reversal + case PLD_SLIC_STATE_APR: /* Active polarity reversal */ - case PLD_SLIC_STATE_OHTPR: // OHT polarity reversal + case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ default: fRetVal = FALSE; @@ -321,7 +696,7 @@ ixj_PCcontrol_wait(j); } } else { - // Set the C1, C2, C3 & B2EN signals. + /* Set the C1, C2, C3 & B2EN signals. */ switch (byState) { case PLD_SLIC_STATE_OC: j->pld_slicw.bits.c1 = 0; @@ -347,7 +722,7 @@ outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); fRetVal = TRUE; break; - case PLD_SLIC_STATE_OHT: // On-hook transmit + case PLD_SLIC_STATE_OHT: /* On-hook transmit */ j->pld_slicw.bits.c1 = 1; j->pld_slicw.bits.c2 = 1; @@ -372,7 +747,7 @@ outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); fRetVal = TRUE; break; - case PLD_SLIC_STATE_APR: // Active polarity reversal + case PLD_SLIC_STATE_APR: /* Active polarity reversal */ j->pld_slicw.bits.c1 = 0; j->pld_slicw.bits.c2 = 1; @@ -381,7 +756,7 @@ outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); fRetVal = TRUE; break; - case PLD_SLIC_STATE_OHTPR: // OHT polarity reversal + case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ j->pld_slicw.bits.c1 = 1; j->pld_slicw.bits.c2 = 1; @@ -399,22 +774,52 @@ return fRetVal; } -int ixj_register(int index, IXJ_REGFUNC regfunc) +static int ixj_wink(IXJ *j) +{ + BYTE slicnow; + + slicnow = SLIC_GetState(j); + + j->pots_winkstart = jiffies; + SLIC_SetState(PLD_SLIC_STATE_OC, j); + + while (time_before(jiffies, j->pots_winkstart + j->winktime)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + + SLIC_SetState(slicnow, j); + return 0; +} + +static int ixj_register(int index, IXJ_REGFUNC regfunc) { int cnt; int retval = 0; switch (index) { case G729LOADER: ixj_DownloadG729 = regfunc; - for (cnt = 0; cnt < IXJMAX; cnt++) - if (ixj[cnt] != NULL) - ixj_DownloadG729(ixj[cnt], 0L); + for (cnt = 0; cnt < IXJMAX; cnt++) { + IXJ *j = get_ixj(cnt); + while(test_and_set_bit(cnt, (void *)&j->busyflags) != 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + ixj_DownloadG729(j, 0L); + clear_bit(cnt, &j->busyflags); + } break; case TS85LOADER: ixj_DownloadTS85 = regfunc; - for (cnt = 0; cnt < IXJMAX; cnt++) - if (ixj[cnt] != NULL) - ixj_DownloadTS85(ixj[cnt], 0L); + for (cnt = 0; cnt < IXJMAX; cnt++) { + IXJ *j = get_ixj(cnt); + while(test_and_set_bit(cnt, (void *)&j->busyflags) != 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + ixj_DownloadTS85(j, 0L); + clear_bit(cnt, &j->busyflags); + } break; case PRE_READ: ixj_PreRead = regfunc; @@ -440,7 +845,9 @@ return retval; } -int ixj_unregister(int index) +EXPORT_SYMBOL(ixj_register); + +static int ixj_unregister(int index) { int retval = 0; switch (index) { @@ -474,17 +881,19 @@ return retval; } -static void ixj_init_timer(void) +EXPORT_SYMBOL(ixj_unregister); + +static void ixj_init_timer(IXJ *j) { - init_timer(&ixj_timer); - ixj_timer.function = ixj_timeout; - ixj_timer.data = (int) NULL; + init_timer(&j->timer); + j->timer.function = ixj_timeout; + j->timer.data = (unsigned long)j; } -static void ixj_add_timer(void) +static void ixj_add_timer(IXJ *j) { - ixj_timer.expires = jiffies + (hertz / samplerate); - add_timer(&ixj_timer); + j->timer.expires = jiffies + (hertz / samplerate); + add_timer(&j->timer); } static void ixj_tone_timeout(IXJ *j) @@ -537,268 +946,573 @@ } } -extern __inline__ void ixj_kill_fasync(IXJ *j, int band) +static inline void ixj_kill_fasync(IXJ *j, IXJ_SIGEVENT event, int dir) { - kill_fasync(&j->async_queue, SIGIO, band); + if(j->ixj_signals[event]) { + if(ixjdebug & 0x0100) + printk("Sending signal for event %d\n", event); + /* Send apps notice of change */ + /* see config.h for macro definition */ + kill_fasync(&(j->async_queue), j->ixj_signals[event], dir); + } } -static void ixj_timeout(unsigned long ptr) +static void ixj_pstn_state(IXJ *j) { - int board; - unsigned long jifon; + int var; + union XOPXR0 XR0, daaint; - for (board = 0; board < IXJMAX; board++) { - IXJ *j = ixj[board]; + var = 10; - if (j == NULL) - continue; + XR0.reg = j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg; + daaint.reg = 0; + XR0.bitreg.RMR = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR; - if (j->DSPbase) { -#ifdef PERFMON_STATS - j->timerchecks++; -#endif - if (j->tone_state) { - if (!ixj_hookstate(j)) { - ixj_cpt_stop(j); - if (j->m_hook) { - j->m_hook = 0; - j->ex.bits.hookstate = 1; - ixj_kill_fasync(j, POLL_PRI); + j->pld_scrr.byte = inb_p(j->XILINXbase); + if (j->pld_scrr.bits.daaflag) { + daa_int_read(j); + if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) { + if(time_after(jiffies, j->pstn_sleeptil) && !(j->flags.pots_pstn && j->hookstate)) { + daaint.bitreg.RING = 1; + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ DAA Ring Interrupt /dev/phone%d at %ld\n", j->board, jiffies); + } + } else { + daa_set_mode(j, SOP_PU_RESET); + } + } + if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Caller_ID) { + daaint.bitreg.Caller_ID = 1; + j->pstn_cid_intr = 1; + j->pstn_cid_received = jiffies; + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ DAA Caller_ID Interrupt /dev/phone%d at %ld\n", j->board, jiffies); + } + } + if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Cadence) { + daaint.bitreg.Cadence = 1; + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ DAA Cadence Interrupt /dev/phone%d at %ld\n", j->board, jiffies); + } + } + if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK != XR0.bitreg.VDD_OK) { + daaint.bitreg.VDD_OK = 1; + daaint.bitreg.SI_0 = j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK; + } + } + daa_CR_read(j, 1); + if(j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR != XR0.bitreg.RMR && time_after(jiffies, j->pstn_sleeptil) && !(j->flags.pots_pstn && j->hookstate)) { + daaint.bitreg.RMR = 1; + daaint.bitreg.SI_1 = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR; + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ DAA RMR /dev/phone%d was %s for %ld\n", j->board, XR0.bitreg.RMR?"on":"off", jiffies - j->pstn_last_rmr); + } + j->pstn_prev_rmr = j->pstn_last_rmr; + j->pstn_last_rmr = jiffies; + } + switch(j->daa_mode) { + case SOP_PU_SLEEP: + if (daaint.bitreg.RING) { + if (!j->flags.pstn_ringing) { + if (j->daa_mode != SOP_PU_RINGING) { + j->pstn_ring_int = jiffies; + daa_set_mode(j, SOP_PU_RINGING); } - continue; } - if (j->tone_state == 1) - jifon = (hertz * j->tone_on_time * 25 / 100000); - else - jifon = (hertz * j->tone_on_time * 25 / 100000) + - (hertz * j->tone_off_time * 25 / 100000); - if (time_before(jiffies, j->tone_start_jif + jifon)) { - if (j->tone_state == 1) { - ixj_play_tone(j, j->tone_index); - if (j->dsp.low == 0x20) { - continue; + } + break; + case SOP_PU_RINGING: + if (daaint.bitreg.RMR) { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence a state = %d /dev/phone%d at %ld\n", j->cadence_f[4].state, j->board, jiffies); + } + if (daaint.bitreg.SI_1) { /* Rising edge of RMR */ + j->flags.pstn_rmr = 1; + j->pstn_ring_start = jiffies; + j->pstn_ring_stop = 0; + j->ex.bits.pstn_ring = 0; + if (j->cadence_f[4].state == 0) { + j->cadence_f[4].state = 1; + j->cadence_f[4].on1min = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100 - var)) / 10000); + j->cadence_f[4].on1dot = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100)) / 10000); + j->cadence_f[4].on1max = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100 + var)) / 10000); + } else if (j->cadence_f[4].state == 2) { + if((time_after(jiffies, j->cadence_f[4].off1min) && + time_before(jiffies, j->cadence_f[4].off1max))) { + if (j->cadence_f[4].on2) { + j->cadence_f[4].state = 3; + j->cadence_f[4].on2min = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].on2dot = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100)) / 10000)); + j->cadence_f[4].on2max = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].off1); + } + j->cadence_f[4].state = 0; } - } else { - ixj_play_tone(j, 0); - if (j->dsp.low == 0x20) { - continue; + } else if (j->cadence_f[4].state == 4) { + if((time_after(jiffies, j->cadence_f[4].off2min) && + time_before(jiffies, j->cadence_f[4].off2max))) { + if (j->cadence_f[4].on3) { + j->cadence_f[4].state = 5; + j->cadence_f[4].on3min = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].on3dot = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100)) / 10000)); + j->cadence_f[4].on3max = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].off2); + } + j->cadence_f[4].state = 0; } - } - } else { - ixj_tone_timeout(j); - if (j->flags.dialtone) { - ixj_dialtone(j); - } - if (j->flags.busytone) { - ixj_busytone(j); - if (j->dsp.low == 0x20) { - continue; + } else if (j->cadence_f[4].state == 6) { + if((time_after(jiffies, j->cadence_f[4].off3min) && + time_before(jiffies, j->cadence_f[4].off3max))) { + j->cadence_f[4].state = 7; + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].off3); + } + j->cadence_f[4].state = 0; } + } else { + j->cadence_f[4].state = 0; } - if (j->flags.ringback) { - ixj_ringback(j); - if (j->dsp.low == 0x20) { - continue; + } else { /* Falling edge of RMR */ + j->pstn_ring_start = 0; + j->pstn_ring_stop = jiffies; + if (j->cadence_f[4].state == 1) { + if(!j->cadence_f[4].on1) { + j->cadence_f[4].state = 7; + } else if((time_after(jiffies, j->cadence_f[4].on1min) && + time_before(jiffies, j->cadence_f[4].on1max))) { + if (j->cadence_f[4].off1) { + j->cadence_f[4].state = 2; + j->cadence_f[4].off1min = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].off1dot = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100)) / 10000)); + j->cadence_f[4].off1max = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].on1); + } + j->cadence_f[4].state = 0; + } + } else if (j->cadence_f[4].state == 3) { + if((time_after(jiffies, j->cadence_f[4].on2min) && + time_before(jiffies, j->cadence_f[4].on2max))) { + if (j->cadence_f[4].off2) { + j->cadence_f[4].state = 4; + j->cadence_f[4].off2min = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].off2dot = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100)) / 10000)); + j->cadence_f[4].off2max = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].on2); + } + j->cadence_f[4].state = 0; } + } else if (j->cadence_f[4].state == 5) { + if((time_after(jiffies, j->cadence_f[4].on3min) && + time_before(jiffies, j->cadence_f[4].on3max))) { + if (j->cadence_f[4].off3) { + j->cadence_f[4].state = 6; + j->cadence_f[4].off3min = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].off3dot = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100)) / 10000)); + j->cadence_f[4].off3max = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + j->cadence_f[4].state = 0; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].on3); + } + j->cadence_f[4].state = 0; } - if (!j->tone_state) { - if (j->dsp.low == 0x20 || (j->play_mode == -1 && j->rec_mode == -1)) - idle(j); - if (j->dsp.low == 0x20 && j->play_mode != -1) - ixj_play_start(j); - if (j->dsp.low == 0x20 && j->rec_mode != -1) - ixj_record_start(j); + } + if (ixjdebug & 0x0010) { + printk(KERN_INFO "IXJ Ring Cadence b state = %d /dev/phone%d at %ld\n", j->cadence_f[4].state, j->board, jiffies); + } + if (ixjdebug & 0x0010) { + switch(j->cadence_f[4].state) { + case 1: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].on1, j->cadence_f[4].on1min, j->cadence_f[4].on1dot, j->cadence_f[4].on1max); + break; + case 2: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].off1, j->cadence_f[4].off1min, j->cadence_f[4].off1dot, j->cadence_f[4].off1max); + break; + case 3: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].on2, j->cadence_f[4].on2min, j->cadence_f[4].on2dot, j->cadence_f[4].on2max); + break; + case 4: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].off2, j->cadence_f[4].off2min, j->cadence_f[4].off2dot, j->cadence_f[4].off2max); + break; + case 5: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].on3, j->cadence_f[4].on3min, j->cadence_f[4].on3dot, j->cadence_f[4].on3max); + break; + case 6: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].off3, j->cadence_f[4].off3min, j->cadence_f[4].off3dot, j->cadence_f[4].off3max); + break; } } } - if (!(j->tone_state && j->dsp.low == 0x20)) { - if (IsRxReady(j)) { - ixj_read_frame(j); + if (j->cadence_f[4].state == 7) { + j->cadence_f[4].state = 0; + j->pstn_ring_stop = jiffies; + j->ex.bits.pstn_ring = 1; + ixj_kill_fasync(j, SIG_PSTN_RING, POLL_IN); + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring int set /dev/phone%d at %ld\n", j->board, jiffies); + } + } + if((j->pstn_ring_int != 0 && time_after(jiffies, j->pstn_ring_int + (hertz * 5)) && !j->flags.pstn_rmr) || + (j->pstn_ring_stop != 0 && time_after(jiffies, j->pstn_ring_stop + (hertz * 5)))) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA no ring in 5 seconds /dev/phone%d at %ld\n", j->board, jiffies); + printk("IXJ DAA pstn ring int /dev/phone%d at %ld\n", j->board, j->pstn_ring_int); + printk("IXJ DAA pstn ring stop /dev/phone%d at %ld\n", j->board, j->pstn_ring_stop); } - if (IsTxReady(j) && !j->flags.cidplay) { - ixj_write_frame(j); + j->pstn_ring_stop = j->pstn_ring_int = 0; + daa_set_mode(j, SOP_PU_SLEEP); + } + outb_p(j->pld_scrw.byte, j->XILINXbase); + if (j->pstn_cid_intr && time_after(jiffies, j->pstn_cid_received + hertz)) { + ixj_daa_cid_read(j); + j->ex.bits.caller_id = 1; + ixj_kill_fasync(j, SIG_CALLER_ID, POLL_IN); + j->pstn_cid_intr = 0; + } + if (daaint.bitreg.Cadence) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA Cadence interrupt going to sleep /dev/phone%d\n", j->board); } + daa_set_mode(j, SOP_PU_SLEEP); + j->ex.bits.pstn_ring = 0; } - if (j->flags.cringing) { - if (ixj_hookstate(j) & 1) { - j->flags.cringing = 0; - ixj_ring_off(j); + break; + case SOP_PU_CONVERSATION: + if (daaint.bitreg.VDD_OK) { + if(!daaint.bitreg.SI_0) { + if (!j->pstn_winkstart) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA possible wink /dev/phone%d %ld\n", j->board, jiffies); + } + j->pstn_winkstart = jiffies; + } } else { - if (jiffies - j->ring_cadence_jif >= (hertz/2)) { - if (j->flags.cidring && !j->flags.cidsent) { - j->flags.cidsent = 1; - ixj_write_cid(j); - j->flags.cidring = 0; + if (j->pstn_winkstart) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA possible wink end /dev/phone%d %ld\n", j->board, jiffies); } - j->ring_cadence_t--; - if (j->ring_cadence_t == -1) - j->ring_cadence_t = 15; - j->ring_cadence_jif = jiffies; - } - if (j->ring_cadence & 1 << j->ring_cadence_t) { - ixj_ring_on(j); - } else { - ixj_ring_off(j); - j->flags.cidring = 1; + j->pstn_winkstart = 0; } - continue; } } - if (!j->flags.ringing) { - if (ixj_hookstate(j)) { - if (j->dsp.low != 0x20 && - SLIC_GetState(j) != PLD_SLIC_STATE_ACTIVE) { - SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); - } - LineMonitor(j); - read_filters(j); - ixj_WriteDSPCommand(0x511B, j); - j->proc_load = j->ssr.high << 8 | j->ssr.low; - if (!j->m_hook) { - j->m_hook = j->ex.bits.hookstate = 1; - ixj_kill_fasync(j, POLL_PRI); + if (j->pstn_winkstart && time_after(jiffies, j->pstn_winkstart + ((hertz * j->winktime) / 1000))) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA wink detected going to sleep /dev/phone%d %ld\n", j->board, jiffies); + } + daa_set_mode(j, SOP_PU_SLEEP); + j->pstn_winkstart = 0; + j->ex.bits.pstn_wink = 1; + ixj_kill_fasync(j, SIG_PSTN_WINK, POLL_IN); + } + break; + } +} + +static void ixj_timeout(unsigned long ptr) +{ + int board; + unsigned long jifon; + IXJ *j = (IXJ *)ptr; + board = j->board; + + if (j->DSPbase && atomic_read(&j->DSPWrite) == 0 && test_and_set_bit(board, (void *)&j->busyflags) == 0) { + ixj_perfmon(j->timerchecks); + j->hookstate = ixj_hookstate(j); + if (j->tone_state) { + if (!(j->hookstate)) { + ixj_cpt_stop(j); + if (j->m_hook) { + j->m_hook = 0; + j->ex.bits.hookstate = 1; + ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); + } + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } + if (j->tone_state == 1) + jifon = ((hertz * j->tone_on_time) * 25 / 100000); + else + jifon = ((hertz * j->tone_on_time) * 25 / 100000) + ((hertz * j->tone_off_time) * 25 / 100000); + if (time_before(jiffies, j->tone_start_jif + jifon)) { + if (j->tone_state == 1) { + ixj_play_tone(j, j->tone_index); + if (j->dsp.low == 0x20) { + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; } } else { - if (j->dsp.low != 0x20 && - SLIC_GetState(j) == PLD_SLIC_STATE_ACTIVE) - // Internet LineJACK - { - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); + ixj_play_tone(j, 0); + if (j->dsp.low == 0x20) { + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; } - if (j->ex.bits.dtmf_ready) { - j->dtmf_wp = j->dtmf_rp = j->ex.bits.dtmf_ready = 0; + } + } else { + ixj_tone_timeout(j); + if (j->flags.dialtone) { + ixj_dialtone(j); + } + if (j->flags.busytone) { + ixj_busytone(j); + if (j->dsp.low == 0x20) { + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; } - if (j->m_hook) { - j->m_hook = 0; - j->ex.bits.hookstate = 1; - ixj_kill_fasync(j, POLL_PRI); + } + if (j->flags.ringback) { + ixj_ringback(j); + if (j->dsp.low == 0x20) { + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; } } + if (!j->tone_state) { + ixj_cpt_stop(j); + } } - if (j->cardtype == 300 && !j->flags.incheck) { - if (j->flags.pstn_present) { - j->pld_scrr.byte = inb_p(j->XILINXbase); - if (j->pld_scrr.bits.daaflag) { - daa_int_read(j); - if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) { - if (!j->flags.pstn_ringing) { - j->flags.pstn_ringing = 1; - if (j->daa_mode != SOP_PU_RINGING) - daa_set_mode(j, SOP_PU_RINGING); + } + if (!(j->tone_state && j->dsp.low == 0x20)) { + if (IsRxReady(j)) { + ixj_read_frame(j); + } + if (IsTxReady(j)) { + ixj_write_frame(j); + } + } + if (j->flags.cringing) { + if (j->hookstate & 1) { + j->flags.cringing = 0; + ixj_ring_off(j); + } else if(j->cadence_f[5].enable && ((!j->cadence_f[5].en_filter) || (j->cadence_f[5].en_filter && j->flags.firstring))) { + switch(j->cadence_f[5].state) { + case 0: + j->cadence_f[5].on1dot = jiffies + (long)((j->cadence_f[5].on1 * (hertz * 100) / 10000)); + if (time_before(jiffies, j->cadence_f[5].on1dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); } + ixj_ring_on(j); } - if (time_after(jiffies, j->pstn_sleeptil) && j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { - j->pstn_winkstart = 0; - j->pstn_ring_stop = 0; - j->pld_scrw.bits.led1 = 1; - if (j->flags.pstn_ringing && !j->pstn_envelope) { - if (j->daa_mode != SOP_PU_RINGING) { - j->flags.pstn_ringing = 0; - } else { - j->pld_scrw.bits.led2 = 0; - j->pstn_envelope = 1; - j->pstn_ring_start = jiffies; - j->pstn_ring_stop = 0; - } - j->ex.bits.pstn_ring = 0; + j->cadence_f[5].state = 1; + break; + case 1: + if (time_after(jiffies, j->cadence_f[5].on1dot)) { + j->cadence_f[5].off1dot = jiffies + (long)((j->cadence_f[5].off1 * (hertz * 100) / 10000)); + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); } - outb_p(j->pld_scrw.byte, j->XILINXbase); - } else { - j->pld_scrw.bits.led1 = 0; - j->pld_scrw.bits.led2 = 1; - outb_p(j->pld_scrw.byte, j->XILINXbase); - if (j->flags.pstn_ringing && j->pstn_envelope) { - if(!j->pstn_ring_stop) { - j->pstn_ring_stop = jiffies; - } else if (time_after(jiffies, j->pstn_ring_stop + ((hertz * 5) / 100))){ - j->pstn_ring_stop = 0; - j->ex.bits.pstn_ring = 1; - j->pstn_envelope = 0; - } - } else if (j->daa_mode == SOP_PU_CONVERSATION) { - if (!j->pstn_winkstart) { - j->pstn_winkstart = jiffies; - } else if (time_after(jiffies, j->pstn_winkstart + (hertz * j->winktime / 1000))) { - daa_set_mode(j, SOP_PU_SLEEP); - j->pstn_winkstart = 0; - j->ex.bits.pstn_wink = 1; - } + ixj_ring_off(j); + j->cadence_f[5].state = 2; + } + break; + case 2: + if (time_after(jiffies, j->cadence_f[5].off1dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_on(j); + if (j->cadence_f[5].on2) { + j->cadence_f[5].on2dot = jiffies + (long)((j->cadence_f[5].on2 * (hertz * 100) / 10000)); + j->cadence_f[5].state = 3; } else { - j->ex.bits.pstn_ring = 0; + j->cadence_f[5].state = 7; } } - if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Cadence) { - if (j->daa_mode == SOP_PU_RINGING) { - daa_set_mode(j, SOP_PU_SLEEP); - j->flags.pstn_ringing = 0; - j->ex.bits.pstn_ring = 0; + break; + case 3: + if (time_after(jiffies, j->cadence_f[5].on2dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); } - } - if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Caller_ID) { - if (j->daa_mode == SOP_PU_RINGING && j->flags.pstn_ringing) { - j->pstn_cid_intr = 1; - j->pstn_cid_received = jiffies; + ixj_ring_off(j); + if (j->cadence_f[5].off2) { + j->cadence_f[5].off2dot = jiffies + (long)((j->cadence_f[5].off2 * (hertz * 100) / 10000)); + j->cadence_f[5].state = 4; + } else { + j->cadence_f[5].state = 7; } } - } else { - if (j->pld_scrr.bits.daaflag) { - daa_int_read(j); + break; + case 4: + if (time_after(jiffies, j->cadence_f[5].off2dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_on(j); + if (j->cadence_f[5].on3) { + j->cadence_f[5].on3dot = jiffies + (long)((j->cadence_f[5].on3 * (hertz * 100) / 10000)); + j->cadence_f[5].state = 5; + } else { + j->cadence_f[5].state = 7; + } } - j->ex.bits.pstn_ring = 0; - if (j->pstn_cid_intr && jiffies > j->pstn_cid_received + (hertz * 3)) { - if (j->daa_mode == SOP_PU_RINGING) { - ixj_daa_cid_read(j); - j->ex.bits.caller_id = 1; + break; + case 5: + if (time_after(jiffies, j->cadence_f[5].on3dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_off(j); + if (j->cadence_f[5].off3) { + j->cadence_f[5].off3dot = jiffies + (long)((j->cadence_f[5].off3 * (hertz * 100) / 10000)); + j->cadence_f[5].state = 6; + } else { + j->cadence_f[5].state = 7; } - j->pstn_cid_intr = 0; - } else { - j->ex.bits.caller_id = 0; } - if (!j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { - j->pld_scrw.bits.led1 = 0; - j->pld_scrw.bits.led2 = 1; - outb_p(j->pld_scrw.byte, j->XILINXbase); - if (j->flags.pstn_ringing && j->pstn_envelope) { - if(!j->pstn_ring_stop) { - j->pstn_ring_stop = jiffies; - } else if (time_after(jiffies, j->pstn_ring_stop + ((hertz * 5) / 100))){ - j->pstn_ring_stop = 0; - j->ex.bits.pstn_ring = 1; - j->pstn_envelope = 0; - } - j->pld_scrw.bits.led1 = 0; - outb_p(j->pld_scrw.byte, j->XILINXbase); - } else if (j->daa_mode == SOP_PU_CONVERSATION) { - if (!j->pstn_winkstart) { - j->pstn_winkstart = jiffies; - } else if (time_after(jiffies, j->pstn_winkstart + (hertz * j->winktime / 1000))) { - daa_set_mode(j, SOP_PU_SLEEP); - j->pstn_winkstart = 0; - j->ex.bits.pstn_wink = 1; - } + break; + case 6: + if (time_after(jiffies, j->cadence_f[5].off3dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); } + j->cadence_f[5].state = 7; + } + break; + case 7: + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); } + j->flags.cidring = 1; + j->cadence_f[5].state = 0; + break; + } + if (j->flags.cidring && !j->flags.cidsent) { + j->flags.cidsent = 1; + if(j->fskdcnt) { + SLIC_SetState(PLD_SLIC_STATE_OHT, j); + ixj_pre_cid(j); + } + j->flags.cidring = 0; + } + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } else { + if (time_after(jiffies, j->ring_cadence_jif + (hertz / 2))) { + if (j->flags.cidring && !j->flags.cidsent) { + j->flags.cidsent = 1; + if(j->fskdcnt) { + SLIC_SetState(PLD_SLIC_STATE_OHT, j); + ixj_pre_cid(j); + } + j->flags.cidring = 0; + } + j->ring_cadence_t--; + if (j->ring_cadence_t == -1) + j->ring_cadence_t = 15; + j->ring_cadence_jif = jiffies; + + if (j->ring_cadence & 1 << j->ring_cadence_t) { + if(j->flags.cidsent && j->cadence_f[5].en_filter) + j->flags.firstring = 1; + else + ixj_ring_on(j); + } else { + ixj_ring_off(j); + if(!j->flags.cidsent) + j->flags.cidring = 1; } } + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; } - if (j->ex.bytes) { - wake_up_interruptible(&j->poll_q); // Wake any blocked selects - ixj_kill_fasync(j, POLL_PRI); + } + if (!j->flags.ringing) { + if (j->hookstate) { /* & 1) { */ + if (j->dsp.low != 0x20 && + SLIC_GetState(j) != PLD_SLIC_STATE_ACTIVE) { + SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); + } + LineMonitor(j); + read_filters(j); + ixj_WriteDSPCommand(0x511B, j); + j->proc_load = j->ssr.high << 8 | j->ssr.low; + if (!j->m_hook && (j->hookstate & 1)) { + j->m_hook = j->ex.bits.hookstate = 1; + ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); + } + } else { + if (j->ex.bits.dtmf_ready) { + j->dtmf_wp = j->dtmf_rp = j->ex.bits.dtmf_ready = 0; + } + if (j->m_hook) { + j->m_hook = 0; + j->ex.bits.hookstate = 1; + ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); + } } - } else { - break; } + if (j->cardtype == QTI_LINEJACK && !j->flags.pstncheck && j->flags.pstn_present) { + ixj_pstn_state(j); + } + if (j->ex.bytes) { + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ + } + clear_bit(board, &j->busyflags); } - ixj_add_timer(); + ixj_add_timer(j); } static int ixj_status_wait(IXJ *j) { unsigned long jif; - jif = jiffies; + jif = jiffies + ((60 * hertz) / 100); while (!IsStatusReady(j)) { - if (jiffies - jif > (60 * (hertz / 100))) { + ixj_perfmon(j->statuswait); + if (time_after(jiffies, jif)) { + ixj_perfmon(j->statuswaitfail); return -1; } } @@ -809,39 +1523,69 @@ { unsigned long jif; - jif = jiffies; + jif = jiffies + ((60 * hertz) / 100); while (!IsPCControlReady(j)) { - if (jiffies - jif > (60 * (hertz / 100))) { + ixj_perfmon(j->pcontrolwait); + if (time_after(jiffies, jif)) { + ixj_perfmon(j->pcontrolwaitfail); return -1; } } return 0; } -int ixj_WriteDSPCommand(unsigned short cmd, IXJ *j) +static int ixj_WriteDSPCommand(unsigned short cmd, IXJ *j) { BYTES bytes; unsigned long jif; + atomic_inc(&j->DSPWrite); + if(atomic_read(&j->DSPWrite) > 1) { + printk("IXJ %d DSP write overlap attempting command 0x%4.4x\n", j->board, cmd); + return -1; + } bytes.high = (cmd & 0xFF00) >> 8; bytes.low = cmd & 0x00FF; - jif = jiffies; + jif = jiffies + ((60 * hertz) / 100); while (!IsControlReady(j)) { - if (jiffies - jif > (60 * (hertz / 100))) { + ixj_perfmon(j->iscontrolready); + if (time_after(jiffies, jif)) { + ixj_perfmon(j->iscontrolreadyfail); + atomic_dec(&j->DSPWrite); + if(atomic_read(&j->DSPWrite) > 0) { + printk("IXJ %d DSP overlaped command 0x%4.4x during control ready failure.\n", j->board, cmd); + while(atomic_read(&j->DSPWrite) > 0) { + atomic_dec(&j->DSPWrite); + } + } return -1; } } - outb_p(bytes.low, j->DSPbase + 6); - outb_p(bytes.high, j->DSPbase + 7); + outb(bytes.low, j->DSPbase + 6); + outb(bytes.high, j->DSPbase + 7); if (ixj_status_wait(j)) { j->ssr.low = 0xFF; j->ssr.high = 0xFF; + atomic_dec(&j->DSPWrite); + if(atomic_read(&j->DSPWrite) > 0) { + printk("IXJ %d DSP overlaped command 0x%4.4x during status wait failure.\n", j->board, cmd); + while(atomic_read(&j->DSPWrite) > 0) { + atomic_dec(&j->DSPWrite); + } + } return -1; } /* Read Software Status Register */ j->ssr.low = inb_p(j->DSPbase + 2); j->ssr.high = inb_p(j->DSPbase + 3); + atomic_dec(&j->DSPWrite); + if(atomic_read(&j->DSPWrite) > 0) { + printk("IXJ %d DSP overlaped command 0x%4.4x\n", j->board, cmd); + while(atomic_read(&j->DSPWrite) > 0) { + atomic_dec(&j->DSPWrite); + } + } return 0; } @@ -850,7 +1594,7 @@ * General Purpose IO Register read routine * ***************************************************************************/ -extern __inline__ int ixj_gpio_read(IXJ *j) +static inline int ixj_gpio_read(IXJ *j) { if (ixj_WriteDSPCommand(0x5143, j)) return -1; @@ -861,7 +1605,7 @@ return 0; } -extern __inline__ void LED_SetState(int state, IXJ *j) +static inline void LED_SetState(int state, IXJ *j) { if (j->cardtype == QTI_LINEJACK) { j->pld_scrw.bits.led1 = state & 0x1 ? 1 : 0; @@ -869,7 +1613,7 @@ j->pld_scrw.bits.led3 = state & 0x4 ? 1 : 0; j->pld_scrw.bits.led4 = state & 0x8 ? 1 : 0; - outb_p(j->pld_scrw.byte, j->XILINXbase); + outb(j->pld_scrw.byte, j->XILINXbase); } } @@ -908,22 +1652,31 @@ case QTI_PHONEJACK_PCI: j->pld_slicw.pcib.mic = 0; j->pld_slicw.pcib.spk = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); break; case QTI_LINEJACK: - ixj_set_pots(j, 0); + ixj_set_pots(j, 0); /* Disconnect POTS/PSTN relay */ if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to Software Control Register */ return 2; - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - outb_p(j->pld_scrw.byte, j->XILINXbase); + outb(j->pld_scrw.byte, j->XILINXbase); j->pld_clock.byte = 0; - outb_p(j->pld_clock.byte, j->XILINXbase + 0x04); + outb(j->pld_clock.byte, j->XILINXbase + 0x04); j->pld_slicw.bits.rly1 = 1; j->pld_slicw.bits.spken = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + ixj_mixer(0x1200, j); /* Turn Off MIC switch on mixer left */ + ixj_mixer(0x1401, j); /* Turn On Mono1 switch on mixer left */ + ixj_mixer(0x1300, j); /* Turn Off MIC switch on mixer right */ + ixj_mixer(0x1501, j); /* Turn On Mono1 switch on mixer right */ + ixj_mixer(0x0E80, j); /*Mic mute */ + ixj_mixer(0x0F00, j); /* Set mono out (SLIC) to 0dB */ + ixj_mixer(0x0080, j); /* Mute Master Left volume */ + ixj_mixer(0x0180, j); /* Mute Master Right volume */ SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); +/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ break; case QTI_PHONEJACK: j->gpio.bytes.high = 0x0B; @@ -940,7 +1693,7 @@ j->pld_slicw.bits.rly3 = 0; j->pld_slicw.bits.rly1 = 1; j->pld_slicw.bits.spken = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); j->port = PORT_PSTN; } else { return 4; @@ -957,10 +1710,29 @@ case QTI_PHONEJACK_PCI: j->pld_slicw.pcib.mic = 1; j->pld_slicw.pcib.spk = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); break; case QTI_LINEJACK: - ixj_set_pots(j, 0); + ixj_set_pots(j, 0); /* Disconnect POTS/PSTN relay */ + if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to + Software Control Register */ + return 2; + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb(j->pld_scrw.byte, j->XILINXbase); + j->pld_clock.byte = 0; + outb(j->pld_clock.byte, j->XILINXbase + 0x04); + j->pld_slicw.bits.rly1 = 1; + j->pld_slicw.bits.spken = 1; + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + ixj_mixer(0x1201, j); /* Turn On MIC switch on mixer left */ + ixj_mixer(0x1400, j); /* Turn Off Mono1 switch on mixer left */ + ixj_mixer(0x1301, j); /* Turn On MIC switch on mixer right */ + ixj_mixer(0x1500, j); /* Turn Off Mono1 switch on mixer right */ + ixj_mixer(0x0E06, j); /*Mic un-mute 0dB */ + ixj_mixer(0x0F80, j); /* Mute mono out (SLIC) */ + ixj_mixer(0x0000, j); /* Set Master Left volume to 0dB */ + ixj_mixer(0x0100, j); /* Set Master Right volume to 0dB */ break; case QTI_PHONEJACK: j->gpio.bytes.high = 0x0B; @@ -971,7 +1743,7 @@ } break; case PORT_HANDSET: - if (j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONEJACK_PCI) { + if (j->cardtype != QTI_PHONEJACK) { return 5; } else { j->gpio.bytes.high = 0x0B; @@ -994,14 +1766,17 @@ if (arg) { if (j->port == PORT_PSTN) { j->pld_slicw.bits.rly1 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->flags.pots_pstn = 1; return 1; } else { + j->flags.pots_pstn = 0; return 0; } } else { j->pld_slicw.bits.rly1 = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->flags.pots_pstn = 0; return 1; } } else { @@ -1011,18 +1786,76 @@ static void ixj_ring_on(IXJ *j) { - if (j->dsp.low == 0x20) { // Internet PhoneJACK + if (j->dsp.low == 0x20) /* Internet PhoneJACK */ + { + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board); + j->gpio.bytes.high = 0x0B; j->gpio.bytes.low = 0x00; j->gpio.bits.gpio1 = 1; j->gpio.bits.gpio2 = 1; j->gpio.bits.gpio5 = 0; ixj_WriteDSPCommand(j->gpio.word, j); /* send the ring signal */ - } else { // Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI + } else /* Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI */ + { + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board); + SLIC_SetState(PLD_SLIC_STATE_RINGING, j); } } +static int ixj_siadc(IXJ *j, int val) +{ + if(j->cardtype == QTI_PHONECARD){ + if(j->flags.pcmciascp){ + if(val == -1) + return j->siadc.bits.rxg; + + if(val < 0 || val > 0x1F) + return -1; + + j->siadc.bits.hom = 0; /* Handset Out Mute */ + j->siadc.bits.lom = 0; /* Line Out Mute */ + j->siadc.bits.rxg = val; /*(0xC000 - 0x41C8) / 0x4EF; RX PGA Gain */ + j->psccr.bits.addr = 6; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(j->siadc.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + return j->siadc.bits.rxg; + } + } + return -1; +} + +static int ixj_sidac(IXJ *j, int val) +{ + if(j->cardtype == QTI_PHONECARD){ + if(j->flags.pcmciascp){ + if(val == -1) + return j->sidac.bits.txg; + + if(val < 0 || val > 0x1F) + return -1; + + j->sidac.bits.srm = 1; /* Speaker Right Mute */ + j->sidac.bits.slm = 1; /* Speaker Left Mute */ + j->sidac.bits.txg = val; /* (0xC000 - 0x45E4) / 0x5D3; TX PGA Gain */ + j->psccr.bits.addr = 7; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(j->sidac.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + return j->sidac.bits.txg; + } + } + return -1; +} + static int ixj_pcmcia_cable_check(IXJ *j) { j->pccr1.byte = inb_p(j->XILINXbase + 0x03); @@ -1058,8 +1891,8 @@ } else if (j->flags.pcmciastate == 3) { j->pccr2.bits.pwr = 0; j->pccr2.bits.rstc = 1; - outb_p(j->pccr2.byte, j->XILINXbase + 0x02); - j->checkwait = jiffies + hertz * 2; + outb(j->pccr2.byte, j->XILINXbase + 0x02); + j->checkwait = jiffies + (hertz * 2); j->flags.incheck = 1; j->flags.pcmciastate = 2; return 0; @@ -1083,9 +1916,9 @@ j->psccr.bits.rw = 1; outb_p(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); - j->flags.pcmciascp = 1; // Set Cable Present Flag + j->flags.pcmciascp = 1; /* Set Cable Present Flag */ - j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03; // Get Cable Type + j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03; /* Get Cable Type */ if (j->flags.pcmciasct == 3) { j->flags.pcmciastate = 4; @@ -1098,113 +1931,63 @@ } else { j->port = PORT_POTS; } - j->sic1.bits.cpd = 0; // Chip Power Down - - j->sic1.bits.mpd = 0; // MIC Bias Power Down - - j->sic1.bits.hpd = 0; // Handset Bias Power Down - - j->sic1.bits.lpd = 0; // Line Bias Power Down - - j->sic1.bits.spd = 1; // Speaker Drive Power Down - - j->psccr.bits.addr = 1; // R/W Smart Cable Register Address - - j->psccr.bits.rw = 0; // Read / Write flag - - j->psccr.bits.dev = 0; - outb(j->sic1.byte, j->XILINXbase + 0x00); - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - j->sic2.bits.al = 0; // Analog Loopback DAC analog -> ADC analog - - j->sic2.bits.dl2 = 0; // Digital Loopback DAC -> ADC one bit - - j->sic2.bits.dl1 = 0; // Digital Loopback ADC -> DAC one bit - - j->sic2.bits.pll = 0; // 1 = div 10, 0 = div 5 - - j->sic2.bits.hpd = 0; // HPF disable - - j->psccr.bits.addr = 2; // R/W Smart Cable Register Address - - j->psccr.bits.rw = 0; // Read / Write flag - - j->psccr.bits.dev = 0; - outb(j->sic2.byte, j->XILINXbase + 0x00); - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - j->psccr.bits.addr = 3; // R/W Smart Cable Register Address - - j->psccr.bits.rw = 0; // Read / Write flag - + j->sic1.bits.cpd = 0; /* Chip Power Down */ + j->sic1.bits.mpd = 0; /* MIC Bias Power Down */ + j->sic1.bits.hpd = 0; /* Handset Bias Power Down */ + j->sic1.bits.lpd = 0; /* Line Bias Power Down */ + j->sic1.bits.spd = 1; /* Speaker Drive Power Down */ + j->psccr.bits.addr = 1; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; - outb(0x00, j->XILINXbase + 0x00); // PLL Divide N1 - + outb(j->sic1.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); - j->psccr.bits.addr = 4; // R/W Smart Cable Register Address - - j->psccr.bits.rw = 0; // Read / Write flag + j->sic2.bits.al = 0; /* Analog Loopback DAC analog -> ADC analog */ + j->sic2.bits.dl2 = 0; /* Digital Loopback DAC -> ADC one bit */ + j->sic2.bits.dl1 = 0; /* Digital Loopback ADC -> DAC one bit */ + j->sic2.bits.pll = 0; /* 1 = div 10, 0 = div 5 */ + j->sic2.bits.hpd = 0; /* HPF disable */ + j->psccr.bits.addr = 2; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; - outb(0x09, j->XILINXbase + 0x00); // PLL Multiply M1 - + outb(j->sic2.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); - j->sirxg.bits.lig = 1; // Line In Gain - - j->sirxg.bits.lim = 1; // Line In Mute - - j->sirxg.bits.mcg = 0; // MIC In Gain // was 3 - - j->sirxg.bits.mcm = 0; // MIC In Mute - - j->sirxg.bits.him = 0; // Handset In Mute - - j->sirxg.bits.iir = 1; // IIR - - j->psccr.bits.addr = 5; // R/W Smart Cable Register Address - - j->psccr.bits.rw = 0; // Read / Write flag + j->psccr.bits.addr = 3; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; - outb(j->sirxg.byte, j->XILINXbase + 0x00); + outb(0x00, j->XILINXbase + 0x00); /* PLL Divide N1 */ outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); - j->siadc.bits.hom = 0; // Handset Out Mute - - j->siadc.bits.lom = 0; // Line Out Mute - - j->siadc.bits.rxg = 23; //(0xC000 - 0x41C8) / 0x4EF; // RX PGA Gain - - j->psccr.bits.addr = 6; // R/W Smart Cable Register Address - - j->psccr.bits.rw = 0; // Read / Write flag + j->psccr.bits.addr = 4; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; - outb(j->siadc.byte, j->XILINXbase + 0x00); + outb(0x09, j->XILINXbase + 0x00); /* PLL Multiply M1 */ outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); - j->sidac.bits.srm = 1; // Speaker Right Mute - - j->sidac.bits.slm = 1; // Speaker Left Mute - - j->sidac.bits.txg = (0xC000 - 0x45E4) / 0x5D3; // TX PGA Gain - - j->psccr.bits.addr = 7; // R/W Smart Cable Register Address - - j->psccr.bits.rw = 0; // Read / Write flag + j->sirxg.bits.lig = 1; /* Line In Gain */ + j->sirxg.bits.lim = 1; /* Line In Mute */ + j->sirxg.bits.mcg = 0; /* MIC In Gain was 3 */ + j->sirxg.bits.mcm = 0; /* MIC In Mute */ + j->sirxg.bits.him = 0; /* Handset In Mute */ + j->sirxg.bits.iir = 1; /* IIR */ + j->psccr.bits.addr = 5; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; - outb(j->sidac.byte, j->XILINXbase + 0x00); + outb(j->sirxg.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); ixj_PCcontrol_wait(j); - j->siaatt.bits.sot = 0; - j->psccr.bits.addr = 9; // R/W Smart Cable Register Address - j->psccr.bits.rw = 0; // Read / Write flag + ixj_siadc(j, 0x17); + ixj_sidac(j, 0x1D); + j->siaatt.bits.sot = 0; + j->psccr.bits.addr = 9; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ j->psccr.bits.dev = 0; outb(j->siaatt.byte, j->XILINXbase + 0x00); outb(j->psccr.byte, j->XILINXbase + 0x01); @@ -1241,26 +2024,42 @@ case QTI_PHONEJACK_LITE: case QTI_PHONEJACK_PCI: SLIC_GetState(j); - if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE || - j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) { - if (j->flags.ringing) { - if (!in_interrupt()) { - det = jiffies + (hertz / 50); - while (time_before(jiffies, det)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } + if(j->cardtype == QTI_LINEJACK && j->flags.pots_pstn == 1 && (j->readers || j->writers)) { + fOffHook = j->pld_slicr.bits.potspstn ? 1 : 0; + if(fOffHook != j->p_hook) { + if(!j->checkwait) { + j->checkwait = jiffies; + } + if(time_before(jiffies, j->checkwait + 2)) { + fOffHook ^= 1; + } else { + j->checkwait = 0; } - SLIC_GetState(j); - if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) { - ixj_ring_on(j); + j->p_hook = fOffHook; + printk("IXJ : /dev/phone%d pots-pstn hookstate check %d at %ld\n", j->board, fOffHook, jiffies); + } + } else { + if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE || + j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) { + if (j->flags.ringing || j->flags.cringing) { + if (!in_interrupt()) { + det = jiffies + (hertz / 50); + while (time_before(jiffies, det)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + } + SLIC_GetState(j); + if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) { + ixj_ring_on(j); + } } + if (j->cardtype == QTI_PHONEJACK_PCI) { + j->pld_scrr.byte = inb_p(j->XILINXbase); + fOffHook = j->pld_scrr.pcib.det ? 1 : 0; + } else + fOffHook = j->pld_slicr.bits.det ? 1 : 0; } - if (j->cardtype == QTI_PHONEJACK_PCI) { - j->pld_scrr.byte = inb_p(j->XILINXbase); - fOffHook = j->pld_scrr.pcib.det ? 1 : 0; - } else - fOffHook = j->pld_slicr.bits.det ? 1 : 0; } break; case QTI_PHONECARD: @@ -1269,34 +2068,49 @@ } if (j->r_hook != fOffHook) { j->r_hook = fOffHook; - if (j->port != PORT_POTS) { + if (j->port == PORT_SPEAKER || j->port == PORT_HANDSET) { // || (j->port == PORT_PSTN && j->flags.pots_pstn == 0)) { j->ex.bits.hookstate = 1; - ixj_kill_fasync(j, POLL_PRI); + ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); } else if (!fOffHook) { - j->flash_end = jiffies + (hertz / 10 * 6); + j->flash_end = jiffies + ((60 * hertz) / 100); + } + } + if (fOffHook) { + if(time_before(jiffies, j->flash_end)) { + j->ex.bits.flash = 1; + j->flash_end = 0; + ixj_kill_fasync(j, SIG_FLASH, POLL_IN); + } + } else { + if(time_before(jiffies, j->flash_end)) { + fOffHook = 1; } } + if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION) fOffHook |= 2; - if (j->port == PORT_SPEAKER) - fOffHook |= 2; + if (j->port == PORT_SPEAKER) { + if(j->cardtype == QTI_PHONECARD) { + if(j->flags.pcmciascp && j->flags.pcmciasct) { + fOffHook |= 2; + } + } else { + fOffHook |= 2; + } + } if (j->port == PORT_HANDSET) fOffHook |= 2; - if (fOffHook && time_before(jiffies, j->flash_end)) - return 0; - else - return fOffHook; + return fOffHook; } static void ixj_ring_off(IXJ *j) { - - if (j->dsp.low == 0x20) // Internet PhoneJACK + if (j->dsp.low == 0x20) /* Internet PhoneJACK */ { - if (ixjdebug > 0) + if (ixjdebug & 0x0004) printk(KERN_INFO "IXJ Ring Off\n"); j->gpio.bytes.high = 0x0B; j->gpio.bytes.low = 0x00; @@ -1304,12 +2118,13 @@ j->gpio.bits.gpio2 = 1; j->gpio.bits.gpio5 = 0; ixj_WriteDSPCommand(j->gpio.word, j); - } else // Internet LineJACK - { - if (ixjdebug > 0) + } else /* Internet LineJACK */ + { + if (ixjdebug & 0x0004) printk(KERN_INFO "IXJ Ring Off\n"); - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); + if(!j->flags.cidplay) + SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); SLIC_GetState(j); } @@ -1318,10 +2133,20 @@ static void ixj_ring_start(IXJ *j) { j->flags.cringing = 1; + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Cadence Ringing Start /dev/phone%d\n", j->board); if (ixj_hookstate(j) & 1) { if (j->port == PORT_POTS) ixj_ring_off(j); j->flags.cringing = 0; + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Cadence Ringing Stopped /dev/phone%d off hook\n", j->board); + } else if(j->cadence_f[5].enable && (!j->cadence_f[5].en_filter)) { + j->ring_cadence_jif = jiffies; + j->flags.cidsent = j->flags.cidring = 0; + j->cadence_f[5].state = 0; + if(j->cadence_f[5].on1) + ixj_ring_on(j); } else { j->ring_cadence_jif = jiffies; j->ring_cadence_t = 15; @@ -1330,6 +2155,7 @@ } else { ixj_ring_off(j); } + j->flags.cidsent = j->flags.cidring = j->flags.firstring = 0; } } @@ -1386,12 +2212,10 @@ return 0; } -int ixj_open(struct phone_device *p, struct file *file_p) +static int ixj_open(struct phone_device *p, struct file *file_p) { - IXJ *j = file_p->private_data = ixj[p->board]; - - if (j == NULL) - return -ENODEV; + IXJ *j = get_ixj(p->board); + file_p->private_data = j; if (!j->DSPbase) return -ENODEV; @@ -1423,7 +2247,12 @@ ixj_PCcontrol_wait(j); } - if (ixjdebug > 0) + j->flags.cidplay = 0; + j->flags.cidcw_ack = 0; + + MOD_INC_USE_COUNT; + + if (ixjdebug & 0x0002) printk(KERN_INFO "Opening board %d\n", p->board); j->framesread = j->frameswritten = 0; @@ -1435,14 +2264,24 @@ IXJ_TONE ti; int cnt; IXJ *j = file_p->private_data; + int board = j->p.board; - if (ixjdebug > 0) + /* + * Set up locks to ensure that only one process is talking to the DSP at a time. + * This is necessary to keep the DSP from locking up. + */ + while(test_and_set_bit(board, (void *)&j->busyflags) != 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + if (ixjdebug & 0x0002) printk(KERN_INFO "Closing board %d\n", NUM(inode->i_rdev)); if (j->cardtype == QTI_PHONECARD) ixj_set_port(j, PORT_SPEAKER); else ixj_set_port(j, PORT_POTS); + aec_stop(j); ixj_play_stop(j); ixj_record_stop(j); @@ -1450,22 +2289,25 @@ set_rec_volume(j, 0x100); ixj_ring_off(j); - // Restore the tone table to default settings. + /* Restore the tone table to default settings. */ ti.tone_index = 10; ti.gain0 = 1; ti.freq0 = hz941; ti.gain1 = 0; ti.freq1 = hz1209; + ixj_init_tone(j, &ti); ti.tone_index = 11; ti.gain0 = 1; ti.freq0 = hz941; ti.gain1 = 0; ti.freq1 = hz1336; + ixj_init_tone(j, &ti); ti.tone_index = 12; ti.gain0 = 1; ti.freq0 = hz941; ti.gain1 = 0; ti.freq1 = hz1477; + ixj_init_tone(j, &ti); ti.tone_index = 13; ti.gain0 = 1; ti.freq0 = hz800; @@ -1557,9 +2399,9 @@ ti.freq1 = hz620; ixj_init_tone(j, &ti); - set_rec_depth(j, 2); // Set Record Channel Limit to 2 frames + set_rec_depth(j, 2); /* Set Record Channel Limit to 2 frames */ - set_play_depth(j, 2); // Set Playback Channel Limit to 2 frames + set_play_depth(j, 2); /* Set Playback Channel Limit to 2 frames */ j->ex.bits.dtmf_ready = 0; j->dtmf_state = 0; @@ -1568,6 +2410,9 @@ j->flags.ringing = 0; j->maxrings = MAXRINGS; j->ring_cadence = USA_RING_CADENCE; + if(j->cadence_f[5].enable) { + j->cadence_f[5].enable = j->cadence_f[5].en_filter = j->cadence_f[5].state = 0; + } j->drybuffer = 0; j->winktime = 320; j->flags.dtmf_oob = 0; @@ -1598,27 +2443,42 @@ j->rec_codec = j->play_codec = 0; j->rec_frame_size = j->play_frame_size = 0; j->flags.cidsent = j->flags.cidring = 0; - ixj_fasync(-1, file_p, 0); // remove from list of async notification + ixj_fasync(-1, file_p, 0); /* remove from list of async notification */ if(j->cardtype == QTI_LINEJACK && !j->readers && !j->writers) { ixj_set_port(j, PORT_PSTN); daa_set_mode(j, SOP_PU_SLEEP); ixj_set_pots(j, 1); } - ixj_WriteDSPCommand(0x0FE3, j); // Put the DSP in 1/5 power mode. + ixj_WriteDSPCommand(0x0FE3, j); /* Put the DSP in 1/5 power mode. */ + + /* Set up the default signals for events */ + for (cnt = 0; cnt < 35; cnt++) + j->ixj_signals[cnt] = SIGIO; + + /* Set the excetion signal enable flags */ + j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring = + j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 = + j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1; file_p->private_data = NULL; + clear_bit(board, &j->busyflags); + MOD_DEC_USE_COUNT; return 0; } static int read_filters(IXJ *j) { - unsigned short fc, cnt; + unsigned short fc, cnt, trg; int var; - if (ixj_WriteDSPCommand(0x5144, j)) + trg = 0; + if (ixj_WriteDSPCommand(0x5144, j)) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Read Frame Counter failed!\n"); + } return -1; - + } fc = j->ssr.high << 8 | j->ssr.low; if (fc == j->frame_count) return 1; @@ -1631,65 +2491,97 @@ var = 10; for (cnt = 0; cnt < 4; cnt++) { - if (ixj_WriteDSPCommand(0x5154 + cnt, j)) + if (ixj_WriteDSPCommand(0x5154 + cnt, j)) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Select Filter %d failed!\n", cnt); + } return -1; - - if (ixj_WriteDSPCommand(0x515C, j)) + } + if (ixj_WriteDSPCommand(0x515C, j)) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Read Filter History %d failed!\n", cnt); + } return -1; - + } j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low; if (j->cadence_f[cnt].enable) { if (j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) { if (j->cadence_f[cnt].state == 0) { j->cadence_f[cnt].state = 1; - j->cadence_f[cnt].on1min = jiffies + (j->cadence_f[cnt].on1 * hertz * (100 - var) / 10000); - j->cadence_f[cnt].on1dot = jiffies + (j->cadence_f[cnt].on1 * hertz * (100) / 10000); - j->cadence_f[cnt].on1max = jiffies + (j->cadence_f[cnt].on1 * hertz * (100 + var) / 10000); + j->cadence_f[cnt].on1min = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].on1dot = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].on1max = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100 + var)) / 10000)); } else if (j->cadence_f[cnt].state == 2 && (time_after(jiffies, j->cadence_f[cnt].off1min) && time_before(jiffies, j->cadence_f[cnt].off1max))) { if (j->cadence_f[cnt].on2) { j->cadence_f[cnt].state = 3; - j->cadence_f[cnt].on2min = jiffies + (j->cadence_f[cnt].on2 * hertz * (100 - var) / 10000); - j->cadence_f[cnt].on2dot = jiffies + (j->cadence_f[cnt].on2 * hertz * (100) / 10000); - j->cadence_f[cnt].on2max = jiffies + (j->cadence_f[cnt].on2 * hertz * (100 + var) / 10000); + j->cadence_f[cnt].on2min = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].on2dot = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].on2max = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100 + var)) / 10000)); } else { - j->cadence_f[cnt].state = 6; + j->cadence_f[cnt].state = 7; } } else if (j->cadence_f[cnt].state == 4 && (time_after(jiffies, j->cadence_f[cnt].off2min) && time_before(jiffies, j->cadence_f[cnt].off2max))) { - if (j->cadence_f[cnt].on2) { + if (j->cadence_f[cnt].on3) { j->cadence_f[cnt].state = 5; - j->cadence_f[cnt].on3min = jiffies + (j->cadence_f[cnt].on3 * hertz * (100 - var) / 10000); - j->cadence_f[cnt].on3dot = jiffies + (j->cadence_f[cnt].on3 * hertz * (100) / 10000); - j->cadence_f[cnt].on3max = jiffies + (j->cadence_f[cnt].on3 * hertz * (100 + var) / 10000); + j->cadence_f[cnt].on3min = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].on3dot = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].on3max = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100 + var)) / 10000)); } else { - j->cadence_f[cnt].state = 6; + j->cadence_f[cnt].state = 7; } } else { j->cadence_f[cnt].state = 0; } } else if (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)) { - if (j->cadence_f[cnt].state == 1 && - (time_after(jiffies, j->cadence_f[cnt].on1min) && - time_before(jiffies, j->cadence_f[cnt].on1max))) { - j->cadence_f[cnt].state = 2; - j->cadence_f[cnt].off1min = jiffies + (j->cadence_f[cnt].off1 * hertz * (100 - var) / 10000); - j->cadence_f[cnt].off1max = jiffies + (j->cadence_f[cnt].off1 * hertz * (100 + var) / 10000); - } else if (j->cadence_f[cnt].state == 3 && - (time_after(jiffies, j->cadence_f[cnt].on2min) && + if (j->cadence_f[cnt].state == 1) { + if(!j->cadence_f[cnt].on1) { + j->cadence_f[cnt].state = 7; + } else if((time_after(jiffies, j->cadence_f[cnt].on1min) && + time_before(jiffies, j->cadence_f[cnt].on1max))) { + if(j->cadence_f[cnt].off1) { + j->cadence_f[cnt].state = 2; + j->cadence_f[cnt].off1min = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].off1dot = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].off1max = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[cnt].state = 7; + } + } else { + j->cadence_f[cnt].state = 0; + } + } else if (j->cadence_f[cnt].state == 3) { + if((time_after(jiffies, j->cadence_f[cnt].on2min) && time_before(jiffies, j->cadence_f[cnt].on2max))) { - j->cadence_f[cnt].state = 4; - j->cadence_f[cnt].off2min = jiffies + (j->cadence_f[cnt].off2 * hertz * (100 - var) / 10000); - j->cadence_f[cnt].off2max = jiffies + (j->cadence_f[cnt].off2 * hertz * (100 + var) / 10000); - } else if (j->cadence_f[cnt].state == 5 && - (time_after(jiffies, j->cadence_f[cnt].on3min) && + if(j->cadence_f[cnt].off2) { + j->cadence_f[cnt].state = 4; + j->cadence_f[cnt].off2min = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].off2dot = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].off2max = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[cnt].state = 7; + } + } else { + j->cadence_f[cnt].state = 0; + } + } else if (j->cadence_f[cnt].state == 5) { + if ((time_after(jiffies, j->cadence_f[cnt].on3min) && time_before(jiffies, j->cadence_f[cnt].on3max))) { - j->cadence_f[cnt].state = 6; - j->cadence_f[cnt].off3min = jiffies + (j->cadence_f[cnt].off3 * hertz * (100 - var) / 10000); - j->cadence_f[cnt].off3max = jiffies + (j->cadence_f[cnt].off3 * hertz * (100 + var) / 10000); + if(j->cadence_f[cnt].off3) { + j->cadence_f[cnt].state = 6; + j->cadence_f[cnt].off3min = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].off3dot = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].off3max = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[cnt].state = 7; + } + } else { + j->cadence_f[cnt].state = 0; + } } else { j->cadence_f[cnt].state = 0; } @@ -1700,58 +2592,128 @@ !j->cadence_f[cnt].off1 && !j->cadence_f[cnt].on2 && !j->cadence_f[cnt].off2 && !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) { - j->cadence_f[cnt].state = 6; + j->cadence_f[cnt].state = 7; } break; case 3: if(time_after(jiffies, j->cadence_f[cnt].on2dot) && !j->cadence_f[cnt].off2 && !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) { - j->cadence_f[cnt].state = 6; + j->cadence_f[cnt].state = 7; } break; case 5: if(time_after(jiffies, j->cadence_f[cnt].on3dot) && !j->cadence_f[cnt].off3) { - j->cadence_f[cnt].state = 6; + j->cadence_f[cnt].state = 7; } break; } } + + if (ixjdebug & 0x0040) { + printk(KERN_INFO "IXJ Tone Cadence state = %d /dev/phone%d at %ld\n", j->cadence_f[cnt].state, j->board, jiffies); + switch(j->cadence_f[cnt].state) { + case 0: + printk(KERN_INFO "IXJ /dev/phone%d No Tone detected\n", j->board); + break; + case 1: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %u %ld - %ld - %ld\n", j->board, + j->cadence_f[cnt].on1, j->cadence_f[cnt].on1min, j->cadence_f[cnt].on1dot, j->cadence_f[cnt].on1max); + break; + case 2: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off1min, + j->cadence_f[cnt].off1max); + break; + case 3: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on2min, + j->cadence_f[cnt].on2max); + break; + case 4: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off2min, + j->cadence_f[cnt].off2max); + break; + case 5: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on3min, + j->cadence_f[cnt].on3max); + break; + case 6: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off3min, + j->cadence_f[cnt].off3max); + break; + } + } } - if (j->cadence_f[cnt].state == 6) { + if (j->cadence_f[cnt].state == 7) { j->cadence_f[cnt].state = 0; if (j->cadence_f[cnt].enable == 1) j->cadence_f[cnt].enable = 0; switch (cnt) { case 0: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter Cadence 0 triggered %ld\n", jiffies); + } j->ex.bits.fc0 = 1; + ixj_kill_fasync(j, SIG_FC0, POLL_IN); break; case 1: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter Cadence 1 triggered %ld\n", jiffies); + } j->ex.bits.fc1 = 1; + ixj_kill_fasync(j, SIG_FC1, POLL_IN); break; case 2: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter Cadence 2 triggered %ld\n", jiffies); + } j->ex.bits.fc2 = 1; + ixj_kill_fasync(j, SIG_FC2, POLL_IN); break; case 3: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter Cadence 3 triggered %ld\n", jiffies); + } j->ex.bits.fc3 = 1; + ixj_kill_fasync(j, SIG_FC3, POLL_IN); break; } } if (j->filter_en[cnt] && ((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) || (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)))) { + if((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12))) { + trg = 1; + } else if((j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3))) { + trg = 0; + } switch (cnt) { case 0: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter 0 triggered %d at %ld\n", trg, jiffies); + } j->ex.bits.f0 = 1; + ixj_kill_fasync(j, SIG_F0, POLL_IN); break; case 1: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter 1 triggered %d at %ld\n", trg, jiffies); + } j->ex.bits.f1 = 1; + ixj_kill_fasync(j, SIG_F1, POLL_IN); break; case 2: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter 2 triggered %d at %ld\n", trg, jiffies); + } j->ex.bits.f2 = 1; + ixj_kill_fasync(j, SIG_F2, POLL_IN); break; case 3: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter 3 triggered %d at %ld\n", trg, jiffies); + } j->ex.bits.f3 = 1; + ixj_kill_fasync(j, SIG_F3, POLL_IN); break; } } @@ -1766,7 +2728,7 @@ } j->dtmf_proc = 1; - if (ixj_WriteDSPCommand(0x7000, j)) // Line Monitor + if (ixj_WriteDSPCommand(0x7000, j)) /* Line Monitor */ return -1; j->dtmf.bytes.high = j->ssr.high; @@ -1775,16 +2737,22 @@ j->dtmf_state = 1; j->dtmf_current = j->dtmf.bits.digit; } - if (j->dtmf_state && !j->dtmf.bits.dtmf_valid) // && j->dtmf_wp != j->dtmf_rp) + if (j->dtmf_state && !j->dtmf.bits.dtmf_valid) /* && j->dtmf_wp != j->dtmf_rp) */ { - if(!j->flags.cidplay) { + if(!j->cidcw_wait) { j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current; j->dtmf_wp++; if (j->dtmf_wp == 79) j->dtmf_wp = 0; j->ex.bits.dtmf_ready = 1; + if(j->ex_sig.bits.dtmf_ready) { + ixj_kill_fasync(j, SIG_DTMF_READY, POLL_IN); + } } - else if(j->dtmf_current == 25 || j->dtmf_current == 31) { + else if(j->dtmf_current == 0x00 || j->dtmf_current == 0x0D) { + if(ixjdebug & 0x0020) { + printk("IXJ phone%d saw CIDCW Ack DTMF %d from display at %ld\n", j->board, j->dtmf_current, jiffies); + } j->flags.cidcw_ack = 1; } j->dtmf_state = 0; @@ -1794,14 +2762,102 @@ return 0; } -ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos) +/************************************************************************ +* +* Functions to allow alaw <-> ulaw conversions. +* +************************************************************************/ + +static void ulaw2alaw(unsigned char *buff, unsigned long len) +{ + static unsigned char table_ulaw2alaw[] = + { + 0x2A, 0x2B, 0x28, 0x29, 0x2E, 0x2F, 0x2C, 0x2D, + 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25, + 0x3A, 0x3B, 0x38, 0x39, 0x3E, 0x3F, 0x3C, 0x3D, + 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35, + 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, 0x02, + 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1A, + 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, 0x12, + 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6B, + 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, 0x62, 0x63, + 0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7B, 0x79, + 0x7E, 0x7F, 0x7C, 0x7D, 0x72, 0x73, 0x70, 0x71, + 0x76, 0x77, 0x74, 0x75, 0x4B, 0x49, 0x4F, 0x4D, + 0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45, + 0x5A, 0x5B, 0x58, 0x59, 0x5E, 0x5F, 0x5C, 0x5D, + 0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51, + 0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xD5, + 0xAA, 0xAB, 0xA8, 0xA9, 0xAE, 0xAF, 0xAC, 0xAD, + 0xA2, 0xA3, 0xA0, 0xA1, 0xA6, 0xA7, 0xA4, 0xA5, + 0xBA, 0xBB, 0xB8, 0xB9, 0xBE, 0xBF, 0xBC, 0xBD, + 0xB2, 0xB3, 0xB0, 0xB1, 0xB6, 0xB7, 0xB4, 0xB5, + 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, 0x82, + 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9A, + 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, 0x92, + 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xEB, + 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, 0xE2, 0xE3, + 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, 0xFB, 0xF9, + 0xFE, 0xFF, 0xFC, 0xFD, 0xF2, 0xF3, 0xF0, 0xF1, + 0xF6, 0xF7, 0xF4, 0xF5, 0xCB, 0xC9, 0xCF, 0xCD, + 0xC2, 0xC3, 0xC0, 0xC1, 0xC6, 0xC7, 0xC4, 0xC5, + 0xDA, 0xDB, 0xD8, 0xD9, 0xDE, 0xDF, 0xDC, 0xDD, + 0xD2, 0xD2, 0xD3, 0xD3, 0xD0, 0xD0, 0xD1, 0xD1, + 0xD6, 0xD6, 0xD7, 0xD7, 0xD4, 0xD4, 0xD5, 0xD5 + }; + + while (len--) + *buff++ = table_ulaw2alaw[*(unsigned char *)buff]; +} + +static void alaw2ulaw(unsigned char *buff, unsigned long len) +{ + static unsigned char table_alaw2ulaw[] = + { + 0x29, 0x2A, 0x27, 0x28, 0x2D, 0x2E, 0x2B, 0x2C, + 0x21, 0x22, 0x1F, 0x20, 0x25, 0x26, 0x23, 0x24, + 0x39, 0x3A, 0x37, 0x38, 0x3D, 0x3E, 0x3B, 0x3C, + 0x31, 0x32, 0x2F, 0x30, 0x35, 0x36, 0x33, 0x34, + 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, + 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, + 0x1A, 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, + 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, + 0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65, + 0x5D, 0x5D, 0x5C, 0x5C, 0x5F, 0x5F, 0x5E, 0x5E, + 0x74, 0x76, 0x70, 0x72, 0x7C, 0x7E, 0x78, 0x7A, + 0x6A, 0x6B, 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, + 0x48, 0x49, 0x46, 0x47, 0x4C, 0x4D, 0x4A, 0x4B, + 0x40, 0x41, 0x3F, 0x3F, 0x44, 0x45, 0x42, 0x43, + 0x56, 0x57, 0x54, 0x55, 0x5A, 0x5B, 0x58, 0x59, + 0x4F, 0x4F, 0x4E, 0x4E, 0x52, 0x53, 0x50, 0x51, + 0xA9, 0xAA, 0xA7, 0xA8, 0xAD, 0xAE, 0xAB, 0xAC, + 0xA1, 0xA2, 0x9F, 0xA0, 0xA5, 0xA6, 0xA3, 0xA4, + 0xB9, 0xBA, 0xB7, 0xB8, 0xBD, 0xBE, 0xBB, 0xBC, + 0xB1, 0xB2, 0xAF, 0xB0, 0xB5, 0xB6, 0xB3, 0xB4, + 0x8A, 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, + 0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, + 0x9A, 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, + 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, + 0xE2, 0xE3, 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, + 0xDD, 0xDD, 0xDC, 0xDC, 0xDF, 0xDF, 0xDE, 0xDE, + 0xF4, 0xF6, 0xF0, 0xF2, 0xFC, 0xFE, 0xF8, 0xFA, + 0xEA, 0xEB, 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, + 0xC8, 0xC9, 0xC6, 0xC7, 0xCC, 0xCD, 0xCA, 0xCB, + 0xC0, 0xC1, 0xBF, 0xBF, 0xC4, 0xC5, 0xC2, 0xC3, + 0xD6, 0xD7, 0xD4, 0xD5, 0xDA, 0xDB, 0xD8, 0xD9, + 0xCF, 0xCF, 0xCE, 0xCE, 0xD2, 0xD3, 0xD0, 0xD1 + }; + + while (len--) + *buff++ = table_alaw2ulaw[*(unsigned char *)buff]; +} + +static ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos) { unsigned long i = *ppos; - IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)]; - DECLARE_WAITQUEUE(wait, current); + IXJ * j = get_ixj(NUM(file_p->f_dentry->d_inode->i_rdev)); - if (j == NULL) /* shouldn't happen! */ - return -ENODEV; + DECLARE_WAITQUEUE(wait, current); if (j->flags.inread) return -EALREADY; @@ -1814,12 +2870,6 @@ while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) { ++j->read_wait; - if(j->tone_state) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->read_q, &wait); - j->flags.inread = 0; - return -EAGAIN; - } if (file_p->f_flags & O_NONBLOCK) { set_current_state(TASK_RUNNING); remove_wait_queue(&j->read_q, &wait); @@ -1844,27 +2894,25 @@ remove_wait_queue(&j->read_q, &wait); set_current_state(TASK_RUNNING); /* Don't ever copy more than the user asks */ - i = copy_to_user(buf, j->read_buffer, - min(unsigned int, length, j->read_buffer_size)); + if(j->rec_codec == ALAW) + ulaw2alaw(j->read_buffer, min(length, j->read_buffer_size)); + i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size)); j->read_buffer_ready = 0; if (i) { j->flags.inread = 0; return -EFAULT; } else { j->flags.inread = 0; - return min(unsigned int, length, j->read_buffer_size); + return min(length, j->read_buffer_size); } } -ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length, +static ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length, loff_t * ppos) { int pre_retval; ssize_t read_retval = 0; - IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)]; - - if (j == NULL) /* shouldn't happen! */ - return -ENODEV; + IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode->i_rdev)); pre_retval = ixj_PreRead(j, 0L); switch (pre_retval) { @@ -1884,14 +2932,12 @@ return read_retval; } -ssize_t ixj_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos) +static ssize_t ixj_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos) { unsigned long i = *ppos; IXJ *j = file_p->private_data; - DECLARE_WAITQUEUE(wait, current); - if (j == NULL) /* shouldn't happen! */ - return -ENODEV; + DECLARE_WAITQUEUE(wait, current); if (j->flags.inwrite) return -EALREADY; @@ -1905,12 +2951,6 @@ while (!j->write_buffers_empty) { ++j->write_wait; - if(j->tone_state) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->write_q, &wait); - j->flags.inwrite = 0; - return -EAGAIN; - } if (file_p->f_flags & O_NONBLOCK) { set_current_state(TASK_RUNNING); remove_wait_queue(&j->write_q, &wait); @@ -1935,30 +2975,29 @@ remove_wait_queue(&j->write_q, &wait); if (j->write_buffer_wp + count >= j->write_buffer_end) j->write_buffer_wp = j->write_buffer; - i = copy_from_user(j->write_buffer_wp, buf, - min(unsigned int, count, j->write_buffer_size)); + i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size)); if (i) { j->flags.inwrite = 0; return -EFAULT; } + if(j->play_codec == ALAW) + alaw2ulaw(j->write_buffer_wp, min(count, j->write_buffer_size)); j->flags.inwrite = 0; - return min(unsigned int, count, j->write_buffer_size); + return min(count, j->write_buffer_size); } -ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos) +static ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos) { int pre_retval; ssize_t write_retval = 0; - IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)]; - if (j == NULL) /* shouldn't happen! */ - return -ENODEV; + IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode->i_rdev)); pre_retval = ixj_PreWrite(j, 0L); switch (pre_retval) { case NORMAL: write_retval = ixj_write(file_p, buf, count, ppos); - if (write_retval != -EFAULT) { + if (write_retval > 0) { ixj_PostWrite(j, 0L); j->write_buffer_wp += write_retval; j->write_buffers_empty--; @@ -1966,7 +3005,7 @@ break; case NOPOST: write_retval = ixj_write(file_p, buf, count, ppos); - if (write_retval != -EFAULT) { + if (write_retval > 0) { j->write_buffer_wp += write_retval; j->write_buffers_empty--; } @@ -1996,8 +3035,8 @@ udelay(10); } } - // Throw away word 0 of the 8021 compressed format to get standard G.729. - if (j->rec_codec == G729 && (cnt == 0 || cnt == 5 || cnt == 10)) { + /* Throw away word 0 of the 8021 compressed format to get standard G.729. */ + if (j->rec_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { inb_p(j->DSPbase + 0x0E); inb_p(j->DSPbase + 0x0F); } @@ -2006,15 +3045,7 @@ } ++j->framesread; if (j->intercom != -1) { - IXJ *icom = ixj[j->intercom]; - - if (icom == NULL) { /* shouldn't happen! */ - printk(KERN_ERR "ixj_read_frame(): j->intercom = %d = NULL!", - j->intercom); - return; - } - - if (IsTxReady(icom)) { + if (IsTxReady(get_ixj(j->intercom))) { for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) { if (!(cnt % 16) && !IsTxReady(j)) { dly = 0; @@ -2026,18 +3057,19 @@ udelay(10); } } - outb_p(*(j->read_buffer + cnt), icom->DSPbase + 0x0C); - outb_p(*(j->read_buffer + cnt + 1), icom->DSPbase + 0x0D); + outb_p(*(j->read_buffer + cnt), get_ixj(j->intercom)->DSPbase + 0x0C); + outb_p(*(j->read_buffer + cnt + 1), get_ixj(j->intercom)->DSPbase + 0x0D); } - ++icom->frameswritten; + get_ixj(j->intercom)->frameswritten++; } } else { j->read_buffer_ready = 1; - wake_up_interruptible(&j->read_q); // Wake any blocked readers + wake_up_interruptible(&j->read_q); /* Wake any blocked readers */ - wake_up_interruptible(&j->poll_q); // Wake any blocked selects + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ - ixj_kill_fasync(j, POLL_IN); + if(j->ixj_signals[SIG_READ_READY]) + ixj_kill_fasync(j, SIG_READ_READY, POLL_OUT); } } } @@ -2101,25 +3133,10 @@ static void ixj_write_cid_bit(IXJ *j, int bit) { - int dly; - IXJ_WORD dat; - while (j->fskcnt < 20) { - if (!IsTxReady(j)) { - dly = 0; - while (!IsTxReady(j)) { - if (dly++ > 5) { - dly = 0; - // break; - // printk("CID delay\n"); - } - udelay(10); - } - } - dat.word = j->fskdata[j->fskdcnt++] = - fsk[bit][j->fskz][j->fskcnt]; - outb_p(dat.bytes.low, j->DSPbase + 0x0C); - outb_p(dat.bytes.high, j->DSPbase + 0x0D); + if(j->fskdcnt < (j->fsksize - 1)) + j->fskdata[j->fskdcnt++] = fsk[bit][j->fskz][j->fskcnt]; + j->fskcnt += 3; } j->fskcnt %= 20; @@ -2131,52 +3148,51 @@ } -static void ixj_write_cid_byte(IXJ *board, char byte) +static void ixj_write_cid_byte(IXJ *j, char byte) { IXJ_CBYTE cb; -// printk("Writing CID data %x - %c\n", byte, byte); - cb.cbyte = byte; - ixj_write_cid_bit(board, 0); - ixj_write_cid_bit(board, cb.cbits.b0 ? 1 : 0); - ixj_write_cid_bit(board, cb.cbits.b1 ? 1 : 0); - ixj_write_cid_bit(board, cb.cbits.b2 ? 1 : 0); - ixj_write_cid_bit(board, cb.cbits.b3 ? 1 : 0); - ixj_write_cid_bit(board, cb.cbits.b4 ? 1 : 0); - ixj_write_cid_bit(board, cb.cbits.b5 ? 1 : 0); - ixj_write_cid_bit(board, cb.cbits.b6 ? 1 : 0); - ixj_write_cid_bit(board, cb.cbits.b7 ? 1 : 0); - ixj_write_cid_bit(board, 1); + cb.cbyte = byte; + ixj_write_cid_bit(j, 0); + ixj_write_cid_bit(j, cb.cbits.b0 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b1 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b2 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b3 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b4 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b5 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b6 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b7 ? 1 : 0); + ixj_write_cid_bit(j, 1); } -static void ixj_write_cid_seize(IXJ *board) +static void ixj_write_cid_seize(IXJ *j) { int cnt; for (cnt = 0; cnt < 150; cnt++) { - ixj_write_cid_bit(board, 0); - ixj_write_cid_bit(board, 1); + ixj_write_cid_bit(j, 0); + ixj_write_cid_bit(j, 1); } for (cnt = 0; cnt < 180; cnt++) { - ixj_write_cid_bit(board, 1); + ixj_write_cid_bit(j, 1); } } -static void ixj_write_cidcw_seize(IXJ *board) +static void ixj_write_cidcw_seize(IXJ *j) { int cnt; for (cnt = 0; cnt < 80; cnt++) { - ixj_write_cid_bit(board, 1); + ixj_write_cid_bit(j, 1); } } -static int ixj_write_cid_string(IXJ *board, char *s, int checksum) +static int ixj_write_cid_string(IXJ *j, char *s, int checksum) { int cnt; for (cnt = 0; cnt < strlen(s); cnt++) { - ixj_write_cid_byte(board, s[cnt]); + ixj_write_cid_byte(j, s[cnt]); checksum = (checksum + s[cnt]); } return checksum; @@ -2184,33 +3200,85 @@ static void ixj_pad_fsk(IXJ *j, int pad) { - int cnt, dly; + int cnt; for (cnt = 0; cnt < pad; cnt++) { - if (!IsTxReady(j)) { - dly = 0; - while (!IsTxReady(j)) { - if (dly++ > 5) { - dly = 0; - } - udelay(10); - } - } - outb_p(0x00, j->DSPbase + 0x0C); - outb_p(0x00, j->DSPbase + 0x0D); + if(j->fskdcnt < (j->fsksize - 1)) + j->fskdata[j->fskdcnt++] = 0x0000; } for (cnt = 0; cnt < 720; cnt++) { - if (!IsTxReady(j)) { - dly = 0; - while (!IsTxReady(j)) { - if (dly++ > 5) { - dly = 0; - } - udelay(10); - } - } - outb_p(0x00, j->DSPbase + 0x0C); - outb_p(0x00, j->DSPbase + 0x0D); + if(j->fskdcnt < (j->fsksize - 1)) + j->fskdata[j->fskdcnt++] = 0x0000; + } +} + +static void ixj_pre_cid(IXJ *j) +{ + j->cid_play_codec = j->play_codec; + j->cid_play_frame_size = j->play_frame_size; + j->cid_play_volume = get_play_volume(j); + j->cid_play_flag = j->flags.playing; + + j->cid_rec_codec = j->rec_codec; + j->cid_rec_volume = get_rec_volume(j); + j->cid_rec_flag = j->flags.recording; + + j->cid_play_aec_level = j->aec_level; + + switch(j->baseframe.low) { + case 0xA0: + j->cid_base_frame_size = 20; + break; + case 0x50: + j->cid_base_frame_size = 10; + break; + case 0xF0: + j->cid_base_frame_size = 30; + break; + } + + ixj_play_stop(j); + ixj_cpt_stop(j); + + j->flags.cidplay = 1; + + set_base_frame(j, 30); + set_play_codec(j, LINEAR16); + set_play_volume(j, 0x1B); + ixj_play_start(j); +} + +static void ixj_post_cid(IXJ *j) +{ + ixj_play_stop(j); + + if(j->cidsize > 5000) { + SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); + } + j->flags.cidplay = 0; + if(ixjdebug & 0x0200) { + printk("IXJ phone%d Finished Playing CallerID data %ld\n", j->board, jiffies); + } + + ixj_fsk_free(j); + + j->fskdcnt = 0; + set_base_frame(j, j->cid_base_frame_size); + set_play_codec(j, j->cid_play_codec); + ixj_aec_start(j, j->cid_play_aec_level); + set_play_volume(j, j->cid_play_volume); + + set_rec_codec(j, j->cid_rec_codec); + set_rec_volume(j, j->cid_rec_volume); + + if(j->cid_rec_flag) + ixj_record_start(j); + + if(j->cid_play_flag) + ixj_play_start(j); + + if(j->cid_play_flag) { + wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ } } @@ -2224,13 +3292,13 @@ int checksum = 0; - if (j->dsp.low == 0x20) + if (j->dsp.low == 0x20 || j->flags.cidplay) return; - j->fskz = j->fskphase = j->fskcnt = - j->fskdcnt = 0; + j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; + j->cidsize = j->cidcnt = 0; - j->flags.cidplay = 1; + ixj_fsk_alloc(j); strcpy(sdmf1, j->cid_send.month); strcat(sdmf1, j->cid_send.day); @@ -2244,54 +3312,53 @@ len3 = strlen(sdmf3); mdmflen = len1 + len2 + len3 + 6; - set_base_frame(j, 30); - set_play_codec(j, LINEAR16); - - if (j->port == PORT_POTS) - if(!j->r_hook) - SLIC_SetState(PLD_SLIC_STATE_OHT, j); - - set_play_volume(j, 0x1B); - ixj_play_start(j); - ixj_write_cid_seize(j); + while(1){ + ixj_write_cid_seize(j); - ixj_write_cid_byte(j, 0x80); - checksum = 0x80; - ixj_write_cid_byte(j, mdmflen); - checksum = checksum + mdmflen; + ixj_write_cid_byte(j, 0x80); + checksum = 0x80; + ixj_write_cid_byte(j, mdmflen); + checksum = checksum + mdmflen; - ixj_write_cid_byte(j, 0x01); - checksum = checksum + 0x01; - ixj_write_cid_byte(j, len1); - checksum = checksum + len1; - checksum = ixj_write_cid_string(j, sdmf1, checksum); + ixj_write_cid_byte(j, 0x01); + checksum = checksum + 0x01; + ixj_write_cid_byte(j, len1); + checksum = checksum + len1; + checksum = ixj_write_cid_string(j, sdmf1, checksum); + if(ixj_hookstate(j) & 1) + break; - ixj_write_cid_byte(j, 0x02); - checksum = checksum + 0x02; - ixj_write_cid_byte(j, len2); - checksum = checksum + len2; - checksum = ixj_write_cid_string(j, sdmf2, checksum); + ixj_write_cid_byte(j, 0x02); + checksum = checksum + 0x02; + ixj_write_cid_byte(j, len2); + checksum = checksum + len2; + checksum = ixj_write_cid_string(j, sdmf2, checksum); + if(ixj_hookstate(j) & 1) + break; - ixj_write_cid_byte(j, 0x07); - checksum = checksum + 0x07; - ixj_write_cid_byte(j, len3); - checksum = checksum + len3; - checksum = ixj_write_cid_string(j, sdmf3, checksum); + ixj_write_cid_byte(j, 0x07); + checksum = checksum + 0x07; + ixj_write_cid_byte(j, len3); + checksum = checksum + len3; + checksum = ixj_write_cid_string(j, sdmf3, checksum); + if(ixj_hookstate(j) & 1) + break; - checksum %= 256; - checksum ^= 0xFF; - checksum += 1; + checksum %= 256; + checksum ^= 0xFF; + checksum += 1; - ixj_write_cid_byte(j, (char) checksum); + ixj_write_cid_byte(j, (char) checksum); - pad = j->fskdcnt % 240; - if (pad) { - pad = 240 - pad; + pad = j->fskdcnt % 240; + if (pad) { + pad = 240 - pad; + } + ixj_pad_fsk(j, pad); + break; } - ixj_pad_fsk(j, pad); - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); - j->flags.cidplay = 0; - ixj_play_stop(j); + + ixj_write_frame(j); } static void ixj_write_cidcw(IXJ *j) @@ -2306,12 +3373,15 @@ int checksum = 0; - if (j->dsp.low == 0x20) + if (j->dsp.low == 0x20 || j->flags.cidplay) return; j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; + j->cidsize = j->cidcnt = 0; - j->flags.cidplay = 1; + ixj_fsk_alloc(j); + + j->flags.cidcw_ack = 0; ti.tone_index = 23; ti.gain0 = 1; @@ -2320,6 +3390,26 @@ ti.freq1 = 0; ixj_init_tone(j, &ti); + ixj_set_tone_on(1500, j); + ixj_set_tone_off(32, j); + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d first tone start at %ld\n", j->board, jiffies); + } + ixj_play_tone(j, 23); + + clear_bit(j->board, &j->busyflags); + while(j->tone_state) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d first tone end at %ld\n", j->board, jiffies); + } + ti.tone_index = 24; ti.gain0 = 1; ti.freq0 = hz2130; @@ -2327,33 +3417,51 @@ ti.freq1 = hz2750; ixj_init_tone(j, &ti); - ixj_set_tone_on(1200, j); - ixj_play_tone(j, 23); + ixj_set_tone_off(10, j); + ixj_set_tone_on(600, j); + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d second tone start at %ld\n", j->board, jiffies); + } + ixj_play_tone(j, 24); + clear_bit(j->board, &j->busyflags); while(j->tone_state) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } - - ixj_set_tone_on(320, j); - ixj_play_tone(j, 24); - - while(j->tone_state) { + while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d sent second tone at %ld\n", j->board, jiffies); + } - j->cidcw_wait = jiffies + (200 * hertz / 100000); + j->cidcw_wait = jiffies + ((50 * hertz) / 100); + clear_bit(j->board, &j->busyflags); while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait)) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } - + while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + j->cidcw_wait = 0; if(!j->flags.cidcw_ack) { + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d did not recieve ACK from display %ld\n", j->board, jiffies); + } + ixj_post_cid(j); + if(j->cid_play_flag) { + wake_up_interruptible(&j->write_q); /* Wake any blocked readers */ + } return; + } else { + ixj_pre_cid(j); } - + j->flags.cidcw_ack = 0; strcpy(sdmf1, j->cid_send.month); strcat(sdmf1, j->cid_send.day); strcat(sdmf1, j->cid_send.hour); @@ -2366,25 +3474,6 @@ len3 = strlen(sdmf3); mdmflen = len1 + len2 + len3 + 6; - j->cid_play_codec = j->play_codec; - ixj_play_stop(j); - - switch(j->baseframe.low) { - case 0xA0: - j->cid_base_frame_size = 20; - break; - case 0x50: - j->cid_base_frame_size = 10; - break; - default: - j->cid_base_frame_size = 30; - break; - } - set_base_frame(j, 30); - set_play_codec(j, LINEAR16); - - set_play_volume(j, 0x1B); - ixj_play_start(j); ixj_write_cidcw_seize(j); ixj_write_cid_byte(j, 0x80); @@ -2421,11 +3510,9 @@ pad = 240 - pad; } ixj_pad_fsk(j, pad); - j->flags.cidplay = 0; - ixj_play_stop(j); - - set_base_frame(j, j->cid_base_frame_size); - set_play_codec(j, j->cid_play_codec); + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d sent FSK data at %ld\n", j->board, jiffies); + } } static void ixj_write_vmwi(IXJ *j, int msg) @@ -2435,23 +3522,19 @@ int checksum = 0; - if (j->dsp.low == 0x20) + if (j->dsp.low == 0x20 || j->flags.cidplay) return; j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; + j->cidsize = j->cidcnt = 0; - j->flags.cidplay = 1; + ixj_fsk_alloc(j); mdmflen = 3; - set_base_frame(j, 30); - set_play_codec(j, LINEAR16); - if (j->port == PORT_POTS) SLIC_SetState(PLD_SLIC_STATE_OHT, j); - set_play_volume(j, 0x1B); - ixj_play_start(j); ixj_write_cid_seize(j); ixj_write_cid_byte(j, 0x82); @@ -2484,18 +3567,49 @@ pad = 240 - pad; } ixj_pad_fsk(j, pad); - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); - j->flags.cidplay = 0; - ixj_play_stop(j); } static void ixj_write_frame(IXJ *j) { int cnt, frame_count, dly; + IXJ_WORD dat; BYTES blankword; frame_count = 0; - if (j->write_buffer && j->write_buffers_empty < 2) { + if(j->flags.cidplay) { + for(cnt = 0; cnt < 480; cnt++) { + if (!(cnt % 16) && !IsTxReady(j)) { + dly = 0; + while (!IsTxReady(j)) { + if (dly++ > 5) { + dly = 0; + break; + } + udelay(10); + } + } + dat.word = j->fskdata[j->cidcnt++]; + outb_p(dat.bytes.low, j->DSPbase + 0x0C); + outb_p(dat.bytes.high, j->DSPbase + 0x0D); + cnt++; + } + if(j->cidcnt >= j->fskdcnt) { + ixj_post_cid(j); + } + /* This may seem rude, but if we just played one frame of FSK data for CallerID + and there is real audio data in the buffer, we need to throw it away because + we just used it's time slot */ + if (j->write_buffer_rp > j->write_buffer_wp) { + j->write_buffer_rp += j->cid_play_frame_size * 2; + if (j->write_buffer_rp >= j->write_buffer_end) { + j->write_buffer_rp = j->write_buffer; + } + j->write_buffers_empty++; + wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ + + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ + } + } else if (j->write_buffer && j->write_buffers_empty < 1) { if (j->write_buffer_wp > j->write_buffer_rp) { frame_count = (j->write_buffer_wp - j->write_buffer_rp) / (j->play_frame_size * 2); @@ -2535,6 +3649,29 @@ outb_p((blankword.high), j->DSPbase + 0x0D); } j->flags.play_first_frame = 0; + } else if (j->play_codec == G723_63 && j->flags.play_first_frame) { + for (cnt = 0; cnt < 24; cnt++) { + if(cnt == 12) { + blankword.low = 0x02; + blankword.high = 0x00; + } + else { + blankword.low = blankword.high = 0x00; + } + if (!(cnt % 16) && !IsTxReady(j)) { + dly = 0; + while (!IsTxReady(j)) { + if (dly++ > 5) { + dly = 0; + break; + } + udelay(10); + } + } + outb_p((blankword.low), j->DSPbase + 0x0C); + outb_p((blankword.high), j->DSPbase + 0x0D); + } + j->flags.play_first_frame = 0; } for (cnt = 0; cnt < j->play_frame_size * 2; cnt += 2) { if (!(cnt % 16) && !IsTxReady(j)) { @@ -2547,11 +3684,20 @@ udelay(10); } } -// Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG - // so all frames are type 1. - if (j->play_codec == G729 && (cnt == 0 || cnt == 5 || cnt == 10)) { - outb_p(0x01, j->DSPbase + 0x0C); - outb_p(0x00, j->DSPbase + 0x0D); + /* Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG */ + if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { + if(j->write_buffer_rp + cnt == 0 && j->write_buffer_rp + cnt + 1 == 0 && j->write_buffer_rp + cnt + 2 == 0 && + j->write_buffer_rp + cnt + 3 == 0 && j->write_buffer_rp + cnt + 4 == 0 && j->write_buffer_rp + cnt + 5 == 0 && + j->write_buffer_rp + cnt + 6 == 0 && j->write_buffer_rp + cnt + 7 == 0 && j->write_buffer_rp + cnt + 8 == 0 && + j->write_buffer_rp + cnt + 9 == 0) { + /* someone is trying to write silence lets make this a type 0 frame. */ + outb_p(0x00, j->DSPbase + 0x0C); + outb_p(0x00, j->DSPbase + 0x0D); + } else { + /* so all other frames are type 1. */ + outb_p(0x01, j->DSPbase + 0x0C); + outb_p(0x00, j->DSPbase + 0x0D); + } } outb_p(*(j->write_buffer_rp + cnt), j->DSPbase + 0x0C); outb_p(*(j->write_buffer_rp + cnt + 1), j->DSPbase + 0x0D); @@ -2563,27 +3709,35 @@ j->write_buffer_rp = j->write_buffer; } j->write_buffers_empty++; - wake_up_interruptible(&j->write_q); // Wake any blocked writers + wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ - wake_up_interruptible(&j->poll_q); // Wake any blocked selects + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ - ixj_kill_fasync(j, POLL_OUT); ++j->frameswritten; } } else { j->drybuffer++; } + if(j->ixj_signals[SIG_WRITE_READY]) { + ixj_kill_fasync(j, SIG_WRITE_READY, POLL_OUT); + } } static int idle(IXJ *j) { - if (ixj_WriteDSPCommand(0x0000, j)) // DSP Idle + if (ixj_WriteDSPCommand(0x0000, j)) /* DSP Idle */ return 0; - if (j->ssr.high || j->ssr.low) + + if (j->ssr.high || j->ssr.low) { return 0; - else + } else { + j->play_mode = -1; + j->flags.playing = 0; + j->rec_mode = -1; + j->flags.recording = 0; return 1; + } } static int set_base_frame(IXJ *j, int size) @@ -2591,6 +3745,8 @@ unsigned short cmd; int cnt; + idle(j); + j->cid_play_aec_level = j->aec_level; aec_stop(j); for (cnt = 0; cnt < 10; cnt++) { if (idle(j)) @@ -2627,7 +3783,12 @@ } else { j->baseframe.high = j->ssr.high; j->baseframe.low = j->ssr.low; + /* If the status returned is 0x0000 (pg9-9 8021) the call failed */ + if(j->baseframe.high == 0x00 && j->baseframe.low == 0x00) { + return -1; + } } + ixj_aec_start(j, j->cid_play_aec_level); return size; } @@ -2708,6 +3869,28 @@ retval = 1; } break; + case G729B: + if (j->dsp.low != 0x20) { + if (!j->flags.g729_loaded) { + retval = 1; + break; + } + switch (j->baseframe.low) { + case 0xA0: + j->rec_frame_size = 12; + break; + case 0x50: + j->rec_frame_size = 6; + break; + default: + j->rec_frame_size = 18; + break; + } + j->rec_mode = 0; + } else { + retval = 1; + } + break; case ULAW: switch (j->baseframe.low) { case 0xA0: @@ -2800,7 +3983,10 @@ ixj_record_stop(j); } j->flags.recording = 1; - ixj_WriteDSPCommand(0x0FE0, j); // Put the DSP in full power mode. + ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ + + if(ixjdebug & 0x0002) + printk("IXJ %d Starting Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies); if (!j->rec_mode) { switch (j->rec_codec) { @@ -2811,21 +3997,22 @@ cmd = 0x5132; break; case TS85: - cmd = 0x5130; // TrueSpeech 8.5 + cmd = 0x5130; /* TrueSpeech 8.5 */ break; case TS48: - cmd = 0x5133; // TrueSpeech 4.8 + cmd = 0x5133; /* TrueSpeech 4.8 */ break; case TS41: - cmd = 0x5134; // TrueSpeech 4.1 + cmd = 0x5134; /* TrueSpeech 4.1 */ break; case G728: cmd = 0x5135; break; case G729: + case G729B: cmd = 0x5136; break; default: @@ -2838,67 +4025,70 @@ if (!j->read_buffer) j->read_buffer = kmalloc(j->rec_frame_size * 2, GFP_ATOMIC); if (!j->read_buffer) { - printk("Read buffer allocation for ixj board %d failed!\n", - j->p.board); + printk("Read buffer allocation for ixj board %d failed!\n", j->board); return -ENOMEM; } } j->read_buffer_size = j->rec_frame_size * 2; - if (ixj_WriteDSPCommand(0x5102, j)) // Set Poll sync mode + if (ixj_WriteDSPCommand(0x5102, j)) /* Set Poll sync mode */ return -1; switch (j->rec_mode) { case 0: - cmd = 0x1C03; // Record C1 + cmd = 0x1C03; /* Record C1 */ break; case 4: if (j->ver.low == 0x12) { - cmd = 0x1E03; // Record C1 + cmd = 0x1E03; /* Record C1 */ } else { - cmd = 0x1E01; // Record C1 + cmd = 0x1E01; /* Record C1 */ } break; case 5: if (j->ver.low == 0x12) { - cmd = 0x1E83; // Record C1 + cmd = 0x1E83; /* Record C1 */ } else { - cmd = 0x1E81; // Record C1 + cmd = 0x1E81; /* Record C1 */ } break; case 6: if (j->ver.low == 0x12) { - cmd = 0x1F03; // Record C1 + cmd = 0x1F03; /* Record C1 */ } else { - cmd = 0x1F01; // Record C1 + cmd = 0x1F01; /* Record C1 */ } break; case 7: if (j->ver.low == 0x12) { - cmd = 0x1F83; // Record C1 - + cmd = 0x1F83; /* Record C1 */ } else { - cmd = 0x1F81; // Record C1 - + cmd = 0x1F81; /* Record C1 */ } break; } if (ixj_WriteDSPCommand(cmd, j)) return -1; + if (j->flags.playing) { + ixj_aec_start(j, j->aec_level); + } return 0; } static void ixj_record_stop(IXJ *j) { + if(ixjdebug & 0x0002) + printk("IXJ %d Stopping Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies); + if (j->read_buffer) { kfree(j->read_buffer); j->read_buffer = NULL; @@ -2909,9 +4099,6 @@ j->rec_mode = -1; } j->flags.recording = 0; - if (!j->flags.playing) - ixj_WriteDSPCommand(0x0FE3, j); // Put the DSP in 1/5 power mode. - } static void ixj_vad(IXJ *j, int arg) { @@ -2930,18 +4117,118 @@ ixj_WriteDSPCommand(0x5180 + depth, j); } -static void set_rec_volume(IXJ *j, int volume) +static void set_dtmf_prescale(IXJ *j, int volume) { - ixj_WriteDSPCommand(0xCF03, j); + ixj_WriteDSPCommand(0xCF07, j); ixj_WriteDSPCommand(volume, j); } -static int get_rec_volume(IXJ *j) +static int get_dtmf_prescale(IXJ *j) { - ixj_WriteDSPCommand(0xCF01, j); + ixj_WriteDSPCommand(0xCF05, j); return j->ssr.high << 8 | j->ssr.low; } +static void set_rec_volume(IXJ *j, int volume) +{ + if(j->aec_level == AEC_AGC) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone%d Setting AGC Threshold to 0x%4.4x\n", j->board, volume); + ixj_WriteDSPCommand(0xCF96, j); + ixj_WriteDSPCommand(volume, j); + } else { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone %d Setting Record Volume to 0x%4.4x\n", j->board, volume); + ixj_WriteDSPCommand(0xCF03, j); + ixj_WriteDSPCommand(volume, j); + } +} + +static int set_rec_volume_linear(IXJ *j, int volume) +{ + int newvolume, dsprecmax; + + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Record Volume to 0x%4.4x\n", j->board, volume); + if(volume > 100 || volume < 0) { + return -1; + } + + /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ + switch (j->cardtype) { + case QTI_PHONEJACK: + dsprecmax = 0x440; + break; + case QTI_LINEJACK: + dsprecmax = 0x180; + ixj_mixer(0x0203, j); /*Voice Left Volume unmute 6db */ + ixj_mixer(0x0303, j); /*Voice Right Volume unmute 6db */ + ixj_mixer(0x0C00, j); /*Mono1 unmute 12db */ + break; + case QTI_PHONEJACK_LITE: + dsprecmax = 0x4C0; + break; + case QTI_PHONEJACK_PCI: + dsprecmax = 0x100; + break; + case QTI_PHONECARD: + dsprecmax = 0x400; + break; + default: + return -1; + } + newvolume = (dsprecmax * volume) / 100; + set_rec_volume(j, newvolume); + return 0; +} + +static int get_rec_volume(IXJ *j) +{ + if(j->aec_level == AEC_AGC) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "Getting AGC Threshold\n"); + ixj_WriteDSPCommand(0xCF86, j); + if (ixjdebug & 0x0002) + printk(KERN_INFO "AGC Threshold is 0x%2.2x%2.2x\n", j->ssr.high, j->ssr.low); + return j->ssr.high << 8 | j->ssr.low; + } else { + if (ixjdebug & 0x0002) + printk(KERN_INFO "Getting Record Volume\n"); + ixj_WriteDSPCommand(0xCF01, j); + return j->ssr.high << 8 | j->ssr.low; + } +} + +static int get_rec_volume_linear(IXJ *j) +{ + int volume, newvolume, dsprecmax; + + switch (j->cardtype) { + case QTI_PHONEJACK: + dsprecmax = 0x440; + break; + case QTI_LINEJACK: + dsprecmax = 0x180; + break; + case QTI_PHONEJACK_LITE: + dsprecmax = 0x4C0; + break; + case QTI_PHONEJACK_PCI: + dsprecmax = 0x100; + break; + case QTI_PHONECARD: + dsprecmax = 0x400; + break; + default: + return -1; + } + volume = get_rec_volume(j); + newvolume = (volume * 100) / dsprecmax; + if(newvolume > 100) + newvolume = 100; + return newvolume; +} + static int get_rec_level(IXJ *j) { int retval; @@ -2956,52 +4243,117 @@ static void ixj_aec_start(IXJ *j, int level) { j->aec_level = level; + if (ixjdebug & 0x0002) + printk(KERN_INFO "AGC set = 0x%2.2x\n", j->aec_level); if (!level) { aec_stop(j); } else { - if (j->rec_codec == G729 || j->play_codec == G729) { - ixj_WriteDSPCommand(0xE022, j); // Move AEC filter buffer + if (j->rec_codec == G729 || j->play_codec == G729 || j->rec_codec == G729B || j->play_codec == G729B) { + ixj_WriteDSPCommand(0xE022, j); /* Move AEC filter buffer */ ixj_WriteDSPCommand(0x0300, j); } - ixj_WriteDSPCommand(0xB001, j); // AEC On + ixj_WriteDSPCommand(0xB001, j); /* AEC On */ - ixj_WriteDSPCommand(0xE013, j); // Advanced AEC C1 + ixj_WriteDSPCommand(0xE013, j); /* Advanced AEC C1 */ switch (level) { case AEC_LOW: - ixj_WriteDSPCommand(0x0000, j); // Advanced AEC C2 = off + ixj_WriteDSPCommand(0x0000, j); /* Advanced AEC C2 = off */ ixj_WriteDSPCommand(0xE011, j); ixj_WriteDSPCommand(0xFFFF, j); + + ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ + ixj_WriteDSPCommand(0x0000, j); /* to off */ + break; case AEC_MED: - ixj_WriteDSPCommand(0x0600, j); // Advanced AEC C2 = on medium + ixj_WriteDSPCommand(0x0600, j); /* Advanced AEC C2 = on medium */ ixj_WriteDSPCommand(0xE011, j); ixj_WriteDSPCommand(0x0080, j); + + ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ + ixj_WriteDSPCommand(0x0000, j); /* to off */ + break; case AEC_HIGH: - ixj_WriteDSPCommand(0x0C00, j); // Advanced AEC C2 = on high + ixj_WriteDSPCommand(0x0C00, j); /* Advanced AEC C2 = on high */ ixj_WriteDSPCommand(0xE011, j); ixj_WriteDSPCommand(0x0080, j); + + ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ + ixj_WriteDSPCommand(0x0000, j); /* to off */ + + break; + + case AEC_AGC: + /* First we have to put the AEC into advance auto mode so that AGC will not conflict with it */ + ixj_WriteDSPCommand(0x0002, j); /* Attenuation scaling factor of 2 */ + + ixj_WriteDSPCommand(0xE011, j); + ixj_WriteDSPCommand(0x0100, j); /* Higher Threshold Floor */ + + ixj_WriteDSPCommand(0xE012, j); /* Set Train and Lock */ + + if(j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONECARD) + ixj_WriteDSPCommand(0x0224, j); + else + ixj_WriteDSPCommand(0x1224, j); + + ixj_WriteDSPCommand(0xE014, j); + ixj_WriteDSPCommand(0x0003, j); /* Lock threashold at 3dB */ + + ixj_WriteDSPCommand(0xE338, j); /* Set Echo Suppresser Attenuation to 0dB */ + + /* Now we can set the AGC initial parameters and turn it on */ + ixj_WriteDSPCommand(0xCF90, j); /* Set AGC Minumum gain */ + ixj_WriteDSPCommand(0x0020, j); /* to 0.125 (-18dB) */ + + ixj_WriteDSPCommand(0xCF91, j); /* Set AGC Maximum gain */ + ixj_WriteDSPCommand(0x1000, j); /* to 16 (24dB) */ + + ixj_WriteDSPCommand(0xCF92, j); /* Set AGC start gain */ + ixj_WriteDSPCommand(0x0800, j); /* to 8 (+18dB) */ + + ixj_WriteDSPCommand(0xCF93, j); /* Set AGC hold time */ + ixj_WriteDSPCommand(0x1F40, j); /* to 2 seconds (units are 250us) */ + + ixj_WriteDSPCommand(0xCF94, j); /* Set AGC Attack Time Constant */ + ixj_WriteDSPCommand(0x0005, j); /* to 8ms */ + + ixj_WriteDSPCommand(0xCF95, j); /* Set AGC Decay Time Constant */ + ixj_WriteDSPCommand(0x000D, j); /* to 4096ms */ + + ixj_WriteDSPCommand(0xCF96, j); /* Set AGC Attack Threshold */ + ixj_WriteDSPCommand(0x1200, j); /* to 25% */ + + ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ + ixj_WriteDSPCommand(0x0001, j); /* to on */ + break; case AEC_AUTO: - ixj_WriteDSPCommand(0x0002, j); // Attenuation scaling factor of 2 + ixj_WriteDSPCommand(0x0002, j); /* Attenuation scaling factor of 2 */ ixj_WriteDSPCommand(0xE011, j); - ixj_WriteDSPCommand(0x0100, j); // Higher Threshold Floor + ixj_WriteDSPCommand(0x0100, j); /* Higher Threshold Floor */ - ixj_WriteDSPCommand(0xE012, j); // Set Train and Lock + ixj_WriteDSPCommand(0xE012, j); /* Set Train and Lock */ - ixj_WriteDSPCommand(0x0023, j); + if(j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONECARD) + ixj_WriteDSPCommand(0x0224, j); + else + ixj_WriteDSPCommand(0x1224, j); ixj_WriteDSPCommand(0xE014, j); - ixj_WriteDSPCommand(0x0003, j); // Lock threashold at 3dB + ixj_WriteDSPCommand(0x0003, j); /* Lock threashold at 3dB */ + + ixj_WriteDSPCommand(0xE338, j); /* Set Echo Suppresser Attenuation to 0dB */ break; } @@ -3010,15 +4362,15 @@ static void aec_stop(IXJ *j) { - if (j->rec_codec == G729 || j->play_codec == G729) { - ixj_WriteDSPCommand(0xE022, j); // Move AEC filter buffer back + j->aec_level = AEC_OFF; + if (j->rec_codec == G729 || j->play_codec == G729 || j->rec_codec == G729B || j->play_codec == G729B) { + ixj_WriteDSPCommand(0xE022, j); /* Move AEC filter buffer back */ ixj_WriteDSPCommand(0x0700, j); } if (j->play_mode != -1 && j->rec_mode != -1) { - ixj_WriteDSPCommand(0xB002, j); // AEC Stop - + ixj_WriteDSPCommand(0xB002, j); /* AEC Stop */ } } @@ -3099,6 +4451,28 @@ retval = 1; } break; + case G729B: + if (j->dsp.low != 0x20) { + if (!j->flags.g729_loaded) { + retval = 1; + break; + } + switch (j->baseframe.low) { + case 0xA0: + j->play_frame_size = 12; + break; + case 0x50: + j->play_frame_size = 6; + break; + default: + j->play_frame_size = 18; + break; + } + j->play_mode = 0; + } else { + retval = 1; + } + break; case ULAW: switch (j->baseframe.low) { case 0xA0: @@ -3190,8 +4564,12 @@ if (j->write_buffer) { ixj_play_stop(j); } + + if(ixjdebug & 0x0002) + printk("IXJ %d Starting Play Codec %d at %ld\n", j->board, j->play_codec, jiffies); + j->flags.playing = 1; - ixj_WriteDSPCommand(0x0FE0, j); // Put the DSP in full power mode. + ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ j->flags.play_first_frame = 1; j->drybuffer = 0; @@ -3205,21 +4583,22 @@ cmd = 0x5232; break; case TS85: - cmd = 0x5230; // TrueSpeech 8.5 + cmd = 0x5230; /* TrueSpeech 8.5 */ break; case TS48: - cmd = 0x5233; // TrueSpeech 4.8 + cmd = 0x5233; /* TrueSpeech 4.8 */ break; case TS41: - cmd = 0x5234; // TrueSpeech 4.1 + cmd = 0x5234; /* TrueSpeech 4.1 */ break; case G728: cmd = 0x5235; break; case G729: + case G729B: cmd = 0x5236; break; default: @@ -3230,16 +4609,16 @@ } j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC); if (!j->write_buffer) { - printk("Write buffer allocation for ixj board %d failed!\n", - j->p.board); + printk("Write buffer allocation for ixj board %d failed!\n", j->board); return -ENOMEM; } - j->write_buffers_empty = 2; +/* j->write_buffers_empty = 2; */ + j->write_buffers_empty = 1; j->write_buffer_size = j->play_frame_size * 2; j->write_buffer_end = j->write_buffer + j->play_frame_size * 2; j->write_buffer_rp = j->write_buffer_wp = j->write_buffer; - if (ixj_WriteDSPCommand(0x5202, j)) // Set Poll sync mode + if (ixj_WriteDSPCommand(0x5202, j)) /* Set Poll sync mode */ return -1; @@ -3279,42 +4658,42 @@ if (ixj_WriteDSPCommand(cmd, j)) return -1; - if (ixj_WriteDSPCommand(0x2000, j)) // Playback C2 - + if (ixj_WriteDSPCommand(0x2000, j)) /* Playback C2 */ return -1; - if (ixj_WriteDSPCommand(0x2000 + j->play_frame_size, j)) // Playback C3 - + if (ixj_WriteDSPCommand(0x2000 + j->play_frame_size, j)) /* Playback C3 */ return -1; + if (j->flags.recording) { + ixj_aec_start(j, j->aec_level); + } - ixj_kill_fasync(j, POLL_OUT); return 0; } static void ixj_play_stop(IXJ *j) { + if(ixjdebug & 0x0002) + printk("IXJ %d Stopping Play Codec %d at %ld\n", j->board, j->play_codec, jiffies); + if (j->write_buffer) { kfree(j->write_buffer); j->write_buffer = NULL; j->write_buffer_size = 0; } if (j->play_mode > -1) { - ixj_WriteDSPCommand(0x5221, j); // Stop playback and flush buffers. 8022 reference page 9-40 + ixj_WriteDSPCommand(0x5221, j); /* Stop playback and flush buffers. 8022 reference page 9-40 */ j->play_mode = -1; } j->flags.playing = 0; - if (!j->flags.recording) - ixj_WriteDSPCommand(0x0FE3, j); // Put the DSP in 1/5 power mode. - } -extern __inline__ int get_play_level(IXJ *j) +static inline int get_play_level(IXJ *j) { int retval; - ixj_WriteDSPCommand(0xCF8F, j); // 8022 Reference page 9-38 + ixj_WriteDSPCommand(0xCF8F, j); /* 8022 Reference page 9-38 */ return j->ssr.high << 8 | j->ssr.low; retval = j->ssr.high << 8 | j->ssr.low; retval = (retval * 256) / 240; @@ -3324,10 +4703,8 @@ static unsigned int ixj_poll(struct file *file_p, poll_table * wait) { unsigned int mask = 0; - IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)]; - if (j == NULL) /* shouldn't happen! */ - return -ENODEV; + IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode->i_rdev)); poll_wait(file_p, &(j->poll_q), wait); if (j->read_buffer_ready > 0) @@ -3340,19 +4717,23 @@ } static int ixj_play_tone(IXJ *j, char tone) -{ - if (!j->tone_state && j->dsp.low == 0x20) - idle(j); - - j->tone_index = tone; - if (ixj_WriteDSPCommand(0x6000 + j->tone_index, j)) - return -1; - +{ if (!j->tone_state) { + if(ixjdebug & 0x0002) { + printk("IXJ %d starting tone %d at %ld\n", j->board, tone, jiffies); + } + if (j->dsp.low == 0x20) { + idle(j); + } j->tone_start_jif = jiffies; j->tone_state = 1; } + + j->tone_index = tone; + if (ixj_WriteDSPCommand(0x6000 + j->tone_index, j)) + return -1; + return 0; } @@ -3360,7 +4741,7 @@ { j->tone_on_time = arg; - if (ixj_WriteDSPCommand(0x6E04, j)) // Set Tone On Period + if (ixj_WriteDSPCommand(0x6E04, j)) /* Set Tone On Period */ return -1; @@ -3383,7 +4764,7 @@ if ((j->pld_scrr.bits.sci)) return 1; } - if (ixjdebug > 1) + if (ixjdebug & 0x0001) printk(KERN_INFO "SCI Wait High failed %x\n", j->pld_scrr.byte); return 0; } else @@ -3403,7 +4784,7 @@ if (!(j->pld_scrr.bits.sci)) return 1; } - if (ixjdebug > 1) + if (ixjdebug & 0x0001) printk(KERN_INFO "SCI Wait Low failed %x\n", j->pld_scrr.byte); return 0; } else @@ -3414,27 +4795,27 @@ { switch (control) { case SCI_End: - j->pld_scrw.bits.c0 = 0; // Set PLD Serial control interface + j->pld_scrw.bits.c0 = 0; /* Set PLD Serial control interface */ - j->pld_scrw.bits.c1 = 0; // to no selection + j->pld_scrw.bits.c1 = 0; /* to no selection */ break; case SCI_Enable_DAA: - j->pld_scrw.bits.c0 = 1; // Set PLD Serial control interface + j->pld_scrw.bits.c0 = 1; /* Set PLD Serial control interface */ - j->pld_scrw.bits.c1 = 0; // to write to DAA + j->pld_scrw.bits.c1 = 0; /* to write to DAA */ break; case SCI_Enable_Mixer: - j->pld_scrw.bits.c0 = 0; // Set PLD Serial control interface + j->pld_scrw.bits.c0 = 0; /* Set PLD Serial control interface */ - j->pld_scrw.bits.c1 = 1; // to write to mixer + j->pld_scrw.bits.c1 = 1; /* to write to mixer */ break; case SCI_Enable_EEPROM: - j->pld_scrw.bits.c0 = 1; // Set PLD Serial control interface + j->pld_scrw.bits.c0 = 1; /* Set PLD Serial control interface */ - j->pld_scrw.bits.c1 = 1; // to write to EEPROM + j->pld_scrw.bits.c1 = 1; /* to write to EEPROM */ break; default: @@ -3471,16 +4852,25 @@ return 1; } +static int ixj_get_mixer(long val, IXJ *j) +{ + int reg = (val & 0x1F00) >> 8; + return j->mix.vol[reg]; +} + static int ixj_mixer(long val, IXJ *j) { BYTES bytes; - bytes.high = (val & 0xFF00) >> 8; + bytes.high = (val & 0x1F00) >> 8; bytes.low = val & 0x00FF; - outb_p(bytes.high & 0x1F, j->XILINXbase + 0x03); // Load Mixer Address + /* save mixer value so we can get back later on */ + j->mix.vol[bytes.high] = bytes.low; + + outb_p(bytes.high & 0x1F, j->XILINXbase + 0x03); /* Load Mixer Address */ - outb_p(bytes.low, j->XILINXbase + 0x02); // Load Mixer Data + outb_p(bytes.low, j->XILINXbase + 0x02); /* Load Mixer Data */ SCI_Control(j, SCI_Enable_Mixer); @@ -3564,7 +4954,7 @@ bytes.high = inb_p(j->XILINXbase + 0x03); bytes.low = inb_p(j->XILINXbase + 0x02); if (bytes.low != ALISDAA_ID_BYTE) { - if (ixjdebug > 0) + if (ixjdebug & 0x0001) printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); return 0; } @@ -3577,6 +4967,77 @@ bytes.low = inb_p(j->XILINXbase + 0x02); j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg = bytes.high; + + return 1; +} + +static char daa_CR_read(IXJ *j, int cr) +{ + IXJ_WORD wdata; + BYTES bytes; + + if (!SCI_Prepare(j)) + return 0; + + switch (j->daa_mode) { + case SOP_PU_SLEEP: + bytes.high = 0x30 + cr; + break; + case SOP_PU_RINGING: + bytes.high = 0x70 + cr; + break; + case SOP_PU_CONVERSATION: + bytes.high = 0xB0 + cr; + break; + case SOP_PU_PULSEDIALING: + bytes.high = 0xF0 + cr; + break; + } + + bytes.low = 0x00; + + outb_p(bytes.high, j->XILINXbase + 0x03); + outb_p(bytes.low, j->XILINXbase + 0x02); + + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + bytes.high = inb_p(j->XILINXbase + 0x03); + bytes.low = inb_p(j->XILINXbase + 0x02); + if (bytes.low != ALISDAA_ID_BYTE) { + if (ixjdebug & 0x0001) + printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); + return 0; + } + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + if (!SCI_Control(j, SCI_End)) + return 0; + + wdata.word = inw_p(j->XILINXbase + 0x02); + + switch(cr){ + case 5: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = wdata.bytes.high; + break; + case 4: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = wdata.bytes.high; + break; + case 3: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = wdata.bytes.high; + break; + case 2: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = wdata.bytes.high; + break; + case 1: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = wdata.bytes.high; + break; + case 0: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = wdata.bytes.high; + break; + default: + return 0; + } return 1; } @@ -3585,6 +5046,9 @@ int i; BYTES bytes; + if (ixjdebug & 0x0002) + printk("DAA Clearing CID ram\n"); + if (!SCI_Prepare(j)) return 0; @@ -3617,6 +5081,9 @@ if (!SCI_Control(j, SCI_End)) return 0; + if (ixjdebug & 0x0002) + printk("DAA CID ram cleared\n"); + return 1; } @@ -3644,7 +5111,7 @@ bytes.high = inb_p(j->XILINXbase + 0x03); bytes.low = inb_p(j->XILINXbase + 0x02); if (bytes.low != ALISDAA_ID_BYTE) { - if (ixjdebug > 0) + if (ixjdebug & 0x0001) printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); return 0; } @@ -3727,7 +5194,7 @@ bytes.high = inb_p(j->XILINXbase + 0x03); bytes.low = inb_p(j->XILINXbase + 0x02); if (bytes.low != ALISDAA_ID_BYTE) { - if (ixjdebug > 0) + if (ixjdebug & 0x0001) printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); return 0; } @@ -3739,7 +5206,7 @@ bytes.high = inb_p(j->XILINXbase + 0x03); bytes.low = inb_p(j->XILINXbase + 0x02); - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk("DAA CR5 Byte high = 0x%x low = 0x%x\n", bytes.high, bytes.low); j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = bytes.high; return bytes.high; @@ -3747,30 +5214,52 @@ static int daa_set_mode(IXJ *j, int mode) { - // NOTE: - // The DAA *MUST* be in the conversation mode if the - // PSTN line is to be seized (PSTN line off-hook). - // Taking the PSTN line off-hook while the DAA is in - // a mode other than conversation mode will cause a - // hardware failure of the ALIS-A part. - - // NOTE: - // The DAA can only go to SLEEP, RINGING or PULSEDIALING modes - // if the PSTN line is on-hook. Failure to have the PSTN line - // in the on-hook state WILL CAUSE A HARDWARE FAILURE OF THE - // ALIS-A part. - // + /* NOTE: + The DAA *MUST* be in the conversation mode if the + PSTN line is to be seized (PSTN line off-hook). + Taking the PSTN line off-hook while the DAA is in + a mode other than conversation mode will cause a + hardware failure of the ALIS-A part. + + NOTE: + The DAA can only go to SLEEP, RINGING or PULSEDIALING modes + if the PSTN line is on-hook. Failure to have the PSTN line + in the on-hook state WILL CAUSE A HARDWARE FAILURE OF THE + ALIS-A part. + */ BYTES bytes; + j->flags.pstn_rmr = 0; + if (!SCI_Prepare(j)) return 0; switch (mode) { + case SOP_PU_RESET: + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly2 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + bytes.high = 0x10; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + daa_load(&bytes, j); + if (!SCI_Prepare(j)) + return 0; + + j->daa_mode = SOP_PU_SLEEP; + break; case SOP_PU_SLEEP: - if(j->daa_mode == SOP_PU_CONVERSATION) + if(j->daa_mode == SOP_PU_SLEEP) + { + break; + } + if (ixjdebug & 0x0008) + printk(KERN_INFO "phone DAA: SOP_PU_SLEEP at %ld\n", jiffies); +/* if(j->daa_mode == SOP_PU_CONVERSATION) */ { - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ outb_p(j->pld_scrw.byte, j->XILINXbase); j->pld_slicw.bits.rly2 = 0; @@ -3781,7 +5270,7 @@ if (!SCI_Prepare(j)) return 0; } - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ outb_p(j->pld_scrw.byte, j->XILINXbase); j->pld_slicw.bits.rly2 = 0; @@ -3795,13 +5284,15 @@ j->daa_mode = SOP_PU_SLEEP; j->flags.pstn_ringing = 0; j->ex.bits.pstn_ring = 0; - j->pstn_sleeptil = jiffies + (hertz / 2); - wake_up_interruptible(&j->read_q); // Wake any blocked readers - wake_up_interruptible(&j->write_q); // Wake any blocked writers - wake_up_interruptible(&j->poll_q); // Wake any blocked selects + j->pstn_sleeptil = jiffies + (hertz / 4); + wake_up_interruptible(&j->read_q); /* Wake any blocked readers */ + wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ break; case SOP_PU_RINGING: - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + if (ixjdebug & 0x0008) + printk(KERN_INFO "phone DAA: SOP_PU_RINGING at %ld\n", jiffies); + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ outb_p(j->pld_scrw.byte, j->XILINXbase); j->pld_slicw.bits.rly2 = 0; @@ -3814,6 +5305,8 @@ j->daa_mode = SOP_PU_RINGING; break; case SOP_PU_CONVERSATION: + if (ixjdebug & 0x0008) + printk(KERN_INFO "phone DAA: SOP_PU_CONVERSATION at %ld\n", jiffies); bytes.high = 0x90; bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; daa_load(&bytes, j); @@ -3821,17 +5314,19 @@ return 0; j->pld_slicw.bits.rly2 = 1; outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->pld_scrw.bits.led1 = 0; - j->pld_scrw.bits.led2 = 1; - j->pld_scrw.bits.daafsyncen = 1; // Turn on DAA Frame Sync + j->pld_scrw.bits.daafsyncen = 1; /* Turn on DAA Frame Sync */ outb_p(j->pld_scrw.byte, j->XILINXbase); j->daa_mode = SOP_PU_CONVERSATION; j->flags.pstn_ringing = 0; j->ex.bits.pstn_ring = 0; + j->pstn_sleeptil = jiffies; + j->pstn_ring_start = j->pstn_ring_stop = j->pstn_ring_int = 0; break; case SOP_PU_PULSEDIALING: - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + if (ixjdebug & 0x0008) + printk(KERN_INFO "phone DAA: SOP_PU_PULSEDIALING at %ld\n", jiffies); + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ outb_p(j->pld_scrw.byte, j->XILINXbase); j->pld_slicw.bits.rly2 = 0; @@ -3853,9 +5348,15 @@ { BYTES bytes; + j->flags.pstncheck = 1; + + daa_set_mode(j, SOP_PU_SLEEP); + if (!SCI_Prepare(j)) return 0; + outb_p(j->pld_scrw.byte, j->XILINXbase); + bytes.high = 0x14; bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg; if (!daa_load(&bytes, j)) @@ -4332,13 +5833,19 @@ if (!SCI_Control(j, SCI_End)) return 0; + outb_p(j->pld_scrw.byte, j->XILINXbase); + + if (ixjdebug & 0x0002) + printk("DAA Coefficients Loaded\n"); + + j->flags.pstncheck = 0; return 1; } int ixj_set_tone_off(unsigned short arg, IXJ *j) { j->tone_off_time = arg; - if (ixj_WriteDSPCommand(0x6E05, j)) // Set Tone Off Period + if (ixj_WriteDSPCommand(0x6E05, j)) /* Set Tone Off Period */ return -1; if (ixj_WriteDSPCommand(arg, j)) @@ -4348,7 +5855,7 @@ static int ixj_get_tone_on(IXJ *j) { - if (ixj_WriteDSPCommand(0x6E06, j)) // Get Tone On Period + if (ixj_WriteDSPCommand(0x6E06, j)) /* Get Tone On Period */ return -1; return 0; @@ -4356,7 +5863,8 @@ static int ixj_get_tone_off(IXJ *j) { - if (ixj_WriteDSPCommand(0x6E07, j)) // Get Tone Off Period + if (ixj_WriteDSPCommand(0x6E07, j)) /* Get Tone Off Period */ + return -1; return 0; } @@ -4387,7 +5895,7 @@ static void ixj_cpt_stop(IXJ *j) { - if(j->tone_state) + if(j->tone_state || j->tone_cadence_state) { j->flags.dialtone = 0; j->flags.busytone = 0; @@ -4395,7 +5903,7 @@ ixj_set_tone_on(0x0001, j); ixj_set_tone_off(0x0000, j); ixj_play_tone(j, 0); - j->tone_state = 0; + j->tone_state = j->tone_cadence_state = 0; if (j->cadence_t) { if (j->cadence_t->ce) { kfree(j->cadence_t->ce); @@ -4436,12 +5944,11 @@ lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL); if (lcp == NULL) return -ENOMEM; - if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)) || - (unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE) ) - { - kfree(lcp); - return -EFAULT; - } + if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)) || (unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE) ) + { + kfree(lcp); + return -EFAULT; + } lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL); if (lcep == NULL) { kfree(lcp); @@ -4477,18 +5984,23 @@ static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * cp) { IXJ_FILTER_CADENCE *lcp; - lcp = kmalloc(sizeof(IXJ_FILTER_CADENCE), GFP_KERNEL); - if (lcp == NULL) + if (lcp == NULL) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Could not allocate memory for cadence\n"); + } return -ENOMEM; - if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE))) - { - kfree(lcp); + } + if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE))) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Could not copy cadence to kernel\n"); + } return -EFAULT; } - if (lcp->filter >= 4) - { - kfree(lcp); + if (lcp->filter > 5) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Cadence out of range\n"); + } return -1; } j->cadence_f[lcp->filter].state = 0; @@ -4513,6 +6025,9 @@ j->cadence_f[lcp->filter].off3min = 0; j->cadence_f[lcp->filter].off3max = 0; kfree(lcp); + if(ixjdebug & 0x0002) { + printk(KERN_INFO "Cadence %d loaded\n", lcp->filter); + } return 0; } @@ -4548,7 +6063,7 @@ j->caplist[j->caps].cap = pots; j->caplist[j->caps].handle = j->caps++; - // add devices that can do speaker/mic + /* add devices that can do speaker/mic */ switch (j->cardtype) { case QTI_PHONEJACK: case QTI_LINEJACK: @@ -4562,7 +6077,7 @@ break; } - // add devices that can do handset + /* add devices that can do handset */ switch (j->cardtype) { case QTI_PHONEJACK: strcpy(j->caplist[j->caps].desc, "HANDSET"); @@ -4574,7 +6089,7 @@ break; } - // add devices that can do PSTN + /* add devices that can do PSTN */ switch (j->cardtype) { case QTI_LINEJACK: strcpy(j->caplist[j->caps].desc, "PSTN"); @@ -4586,7 +6101,7 @@ break; } - // add codecs - all cards can do uLaw, linear 8/16, and Windows sound system + /* add codecs - all cards can do uLaw, linear 8/16, and Windows sound system */ strcpy(j->caplist[j->caps].desc, "ULAW"); j->caplist[j->caps].captype = codec; j->caplist[j->caps].cap = ULAW; @@ -4607,66 +6122,73 @@ j->caplist[j->caps].cap = WSS; j->caplist[j->caps].handle = j->caps++; - // version 12 of the 8020 does the following codecs in a broken way + /* software ALAW codec, made from ULAW */ + strcpy(j->caplist[j->caps].desc, "ALAW"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = ALAW; + j->caplist[j->caps].handle = j->caps++; + + /* version 12 of the 8020 does the following codecs in a broken way */ if (j->dsp.low != 0x20 || j->ver.low != 0x12) { - strcpy(j->caplist[j->caps].desc, "G.723.1 6.3Kbps"); + strcpy(j->caplist[j->caps].desc, "G.723.1 6.3kbps"); j->caplist[j->caps].captype = codec; j->caplist[j->caps].cap = G723_63; j->caplist[j->caps].handle = j->caps++; - strcpy(j->caplist[j->caps].desc, "G.723.1 5.3Kbps"); + strcpy(j->caplist[j->caps].desc, "G.723.1 5.3kbps"); j->caplist[j->caps].captype = codec; j->caplist[j->caps].cap = G723_53; j->caplist[j->caps].handle = j->caps++; - strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.8Kbps"); + strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.8kbps"); j->caplist[j->caps].captype = codec; j->caplist[j->caps].cap = TS48; j->caplist[j->caps].handle = j->caps++; - strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.1Kbps"); + strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.1kbps"); j->caplist[j->caps].captype = codec; j->caplist[j->caps].cap = TS41; j->caplist[j->caps].handle = j->caps++; } - // 8020 chips can do TS8.5 native, and 8021/8022 can load it + /* 8020 chips can do TS8.5 native, and 8021/8022 can load it */ if (j->dsp.low == 0x20 || j->flags.ts85_loaded) { - strcpy(j->caplist[j->caps].desc, "TrueSpeech 8.5Kbps"); + strcpy(j->caplist[j->caps].desc, "TrueSpeech 8.5kbps"); j->caplist[j->caps].captype = codec; j->caplist[j->caps].cap = TS85; j->caplist[j->caps].handle = j->caps++; } - // 8021 chips can do G728 + /* 8021 chips can do G728 */ if (j->dsp.low == 0x21) { - strcpy(j->caplist[j->caps].desc, "G.728 16Kbps"); + strcpy(j->caplist[j->caps].desc, "G.728 16kbps"); j->caplist[j->caps].captype = codec; j->caplist[j->caps].cap = G728; j->caplist[j->caps].handle = j->caps++; } - // 8021/8022 chips can do G729 if loaded + /* 8021/8022 chips can do G729 if loaded */ if (j->dsp.low != 0x20 && j->flags.g729_loaded) { - strcpy(j->caplist[j->caps].desc, "G.729A/B"); + strcpy(j->caplist[j->caps].desc, "G.729A 8kbps"); j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = G728; + j->caplist[j->caps].cap = G729; + j->caplist[j->caps].handle = j->caps++; + } + if (j->dsp.low != 0x20 && j->flags.g729_loaded) { + strcpy(j->caplist[j->caps].desc, "G.729B 8kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = G729B; j->caplist[j->caps].handle = j->caps++; } } -static int capabilities_check(IXJ *j, struct phone_capability *u_pcreq) +static int capabilities_check(IXJ *j, struct phone_capability *pcreq) { int cnt; int retval = 0; - struct phone_capability pcreq; - - if(copy_from_user(&pcreq, u_pcreq, sizeof(struct phone_capability))) - return -EFAULT; - for (cnt = 0; cnt < j->caps; cnt++) { - if (pcreq.captype == j->caplist[cnt].captype - && pcreq.cap == j->caplist[cnt].cap) { + if (pcreq->captype == j->caplist[cnt].captype + && pcreq->cap == j->caplist[cnt].cap) { retval = 1; break; } @@ -4674,31 +6196,42 @@ return retval; } -int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg) +static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg) { IXJ_TONE ti; IXJ_FILTER jf; + IXJ_FILTER_RAW jfr; + + unsigned int raise, mant; unsigned int minor = MINOR(inode->i_rdev); - unsigned int board = NUM(inode->i_rdev); - IXJ *j = ixj[board]; - int retval = 0; + int board = NUM(inode->i_rdev); - if (ixjdebug > 1) - printk(KERN_DEBUG "phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); - if (minor >= IXJMAX) - return -ENODEV; + IXJ *j = get_ixj(NUM(inode->i_rdev)); - if (j == NULL) /* shouldn't happen! */ - return -ENODEV; + int retval = 0; /* + * Set up locks to ensure that only one process is talking to the DSP at a time. + * This is necessary to keep the DSP from locking up. + */ + while(test_and_set_bit(board, (void *)&j->busyflags) != 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + if (ixjdebug & 0x0040) + printk("phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); + if (minor >= IXJMAX) { + clear_bit(board, &j->busyflags); + return -ENODEV; + } + /* * Check ioctls only root can use. */ if (!capable(CAP_SYS_ADMIN)) { switch (cmd) { case IXJCTL_TESTRAM: case IXJCTL_HZ: - return -EPERM; + retval = -EPERM; } } switch (cmd) { @@ -4713,12 +6246,11 @@ retval = j->serial; break; case IXJCTL_VERSION: - if (copy_to_user((char *) arg, ixj_c_revision, strlen(ixj_c_revision))) - return -EFAULT; + if (copy_to_user((char *) arg, ixj_c_revision, strlen(ixj_c_revision))) + retval = -EFAULT; break; case PHONE_RING_CADENCE: - if(get_user(j->ring_cadence, (int *)arg)) - return -EFAULT; + j->ring_cadence = arg; break; case IXJCTL_CIDCW: if(arg) { @@ -4729,13 +6261,18 @@ } ixj_write_cidcw(j); break; - /* Binary compatbility */ - case OLD_PHONE_RING_START: - arg = 0; - /* Fall through */ - case PHONE_RING_START: + /* Binary compatbility */ + case OLD_PHONE_RING_START: + arg = 0; + /* Fall through */ + case PHONE_RING_START: if(arg) { - copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID)); + if(copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) + { + retval = -EFAULT; + break; + } + ixj_write_cid(j); } else { memset(&j->cid_send, 0, sizeof(PHONE_CID)); @@ -4744,6 +6281,9 @@ break; case PHONE_RING_STOP: j->flags.cringing = 0; + if(j->cadence_f[5].enable) { + j->cadence_f[5].state = 0; + } ixj_ring_off(j); break; case PHONE_RING: @@ -4751,7 +6291,10 @@ break; case PHONE_EXCEPTION: retval = j->ex.bytes; - j->ex.bits.flash = 0; + if(j->ex.bits.flash) { + j->flash_end = 0; + j->ex.bits.flash = 0; + } j->ex.bits.pstn_ring = 0; j->ex.bits.caller_id = 0; j->ex.bits.pstn_wink = 0; @@ -4767,7 +6310,7 @@ break; case PHONE_HOOKSTATE: j->ex.bits.hookstate = 0; - retval = j->r_hook; + retval = j->hookstate; //j->r_hook; break; case IXJCTL_SET_LED: LED_SetState(arg, j); @@ -4799,9 +6342,33 @@ retval = arg; } break; + case PHONE_REC_VOLUME_LINEAR: + if(arg == -1) { + retval = get_rec_volume_linear(j); + } + else { + set_rec_volume_linear(j, arg); + retval = arg; + } + break; + case IXJCTL_DTMF_PRESCALE: + if(arg == -1) { + retval = get_dtmf_prescale(j); + } + else { + set_dtmf_prescale(j, arg); + retval = arg; + } + break; case PHONE_REC_LEVEL: retval = get_rec_level(j); break; + case IXJCTL_SC_RXG: + retval = ixj_siadc(j, arg); + break; + case IXJCTL_SC_TXG: + retval = ixj_sidac(j, arg); + break; case IXJCTL_AEC_START: ixj_aec_start(j, arg); break; @@ -4832,6 +6399,15 @@ retval = arg; } break; + case PHONE_PLAY_VOLUME_LINEAR: + if(arg == -1) { + retval = get_play_volume_linear(j); + } + else { + set_play_volume_linear(j, arg); + retval = arg; + } + break; case PHONE_PLAY_LEVEL: retval = get_play_level(j); break; @@ -4921,31 +6497,31 @@ if (j->dtmf_rp != j->dtmf_wp) { switch (j->dtmfbuffer[j->dtmf_rp]) { case 10: - retval = 42; //'*'; + retval = 42; /* '*'; */ break; case 11: - retval = 48; //'0'; + retval = 48; /*'0'; */ break; case 12: - retval = 35; //'#'; + retval = 35; /*'#'; */ break; case 28: - retval = 65; //'A'; + retval = 65; /*'A'; */ break; case 29: - retval = 66; //'B'; + retval = 66; /*'B'; */ break; case 30: - retval = 67; //'C'; + retval = 67; /*'C'; */ break; case 31: - retval = 68; //'D'; + retval = 68; /*'D'; */ break; default: @@ -4955,7 +6531,7 @@ j->dtmf_rp++; if (j->dtmf_rp == 79) j->dtmf_rp = 0; -// if(j->dtmf_rp == j->dtmf_wp) + if(j->dtmf_rp == j->dtmf_wp) { j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0; } @@ -4974,40 +6550,53 @@ case PHONE_RINGBACK: ixj_ringback(j); break; + case PHONE_WINK: + if(j->cardtype == QTI_PHONEJACK) + retval = -1; + else + retval = ixj_wink(j); + break; case PHONE_CPT_STOP: ixj_cpt_stop(j); break; - case PHONE_QUERY_CODEC: - { - struct phone_codec_data pd; - int val; - int proto_size[] = { - -1, - 12, 10, 16, 9, 8, 48, 5, - 40, 40, 80, 40, 40 - }; - if(copy_from_user(&pd, (void *)arg, sizeof(pd))) - return -EFAULT; - if(pd.type<1 || pd.type>12) - return -EPROTONOSUPPORT; - if(pd.typebaseframe.low) - { - case 0xA0:val=2*proto_size[pd.type];break; - case 0x50:val=proto_size[pd.type];break; - default:val=proto_size[pd.type]*3;break; - } - pd.buf_min=pd.buf_max=pd.buf_opt=val; - if(copy_to_user((void *)arg, &pd, sizeof(pd))) - return -EFAULT; - return 0; - } + case PHONE_QUERY_CODEC: + { + struct phone_codec_data pd; + int val; + int proto_size[] = { + -1, + 12, 10, 16, 9, 8, 48, 5, + 40, 40, 80, 40, 40, 6 + }; + if(copy_from_user(&pd, (void *)arg, sizeof(pd))) { + retval = -EFAULT; + break; + } + if(pd.type<1 || pd.type>13) { + retval = -EPROTONOSUPPORT; + break; + } + if(pd.typebaseframe.low) + { + case 0xA0:val=2*proto_size[pd.type];break; + case 0x50:val=proto_size[pd.type];break; + default:val=proto_size[pd.type]*3;break; + } + pd.buf_min=pd.buf_max=pd.buf_opt=val; + if(copy_to_user((void *)arg, &pd, sizeof(pd))) + retval = -EFAULT; + break; + } case IXJCTL_DSP_IDLE: idle(j); break; case IXJCTL_MIXER: - ixj_mixer(arg, j); + if ((arg & 0xff) == 0xff) + retval = ixj_get_mixer(arg, j); + else + ixj_mixer(arg, j); break; case IXJCTL_DAA_COEFF_SET: switch (arg) { @@ -5039,7 +6628,6 @@ retval = 1; break; } - j->country = arg; break; case IXJCTL_DAA_AGAIN: ixj_daa_cr4(j, arg | 0x02); @@ -5051,8 +6639,8 @@ ixj_write_vmwi(j, arg); break; case IXJCTL_CID: - if (copy_to_user((char *) arg, &j->cid, sizeof(PHONE_CID))) - return -EFAULT; + if (copy_to_user((char *) arg, &j->cid, sizeof(PHONE_CID))) + retval = -EFAULT; j->ex.bits.caller_id = 0; break; case IXJCTL_WINK_DURATION: @@ -5068,14 +6656,24 @@ retval = ixj_set_pots(j, arg); break; case PHONE_CAPABILITIES: + add_caps(j); retval = j->caps; break; case PHONE_CAPABILITIES_LIST: - if (copy_to_user((char *) arg, j->caplist, sizeof(struct phone_capability) * j->caps)) - return -EFAULT; + add_caps(j); + if (copy_to_user((char *) arg, j->caplist, sizeof(struct phone_capability) * j->caps)) + retval = -EFAULT; break; case PHONE_CAPABILITIES_CHECK: - retval = capabilities_check(j, (struct phone_capability *) arg); + { + struct phone_capability cap; + if (copy_from_user(&cap, (char *) arg, sizeof(cap))) + retval = -EFAULT; + else { + add_caps(j); + retval = capabilities_check(j, &cap); + } + } break; case PHONE_PSTN_SET_STATE: daa_set_mode(j, arg); @@ -5085,10 +6683,15 @@ j->ex.bits.pstn_ring = 0; break; case IXJCTL_SET_FILTER: - if (copy_from_user(&jf, (char *) arg, sizeof(jf))) - return -EFAULT; + if (copy_from_user(&jf, (char *) arg, sizeof(jf))) + retval = -EFAULT; retval = ixj_init_filter(j, &jf); break; + case IXJCTL_SET_FILTER_RAW: + if (copy_from_user(&jfr, (char *) arg, sizeof(jfr))) + retval = -EFAULT; + retval = ixj_init_filter_raw(j, &jfr); + break; case IXJCTL_GET_FILTER_HIST: retval = j->filter_hist[arg]; break; @@ -5102,117 +6705,123 @@ case IXJCTL_FILTER_CADENCE: retval = ixj_build_filter_cadence(j, (IXJ_FILTER_CADENCE *) arg); break; + case IXJCTL_SIGCTL: + if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF))) + retval = -EFAULT; + j->ixj_signals[j->sigdef.event] = j->sigdef.signal; + if(j->sigdef.event < 33) { + raise = 1; + for(mant = 0; mant < j->sigdef.event; mant++){ + raise *= 2; + } + if(j->sigdef.signal) + j->ex_sig.bytes |= raise; + else + j->ex_sig.bytes &= (raise^0xffff); + } + break; case IXJCTL_INTERCOM_STOP: - if (arg != j->intercom - || ixj[arg]->intercom != board) + if(arg < 0 || arg >= IXJMAX) return -EINVAL; - j->intercom = -1; - ixj[arg]->intercom = -1; ixj_record_stop(j); - ixj_record_stop(ixj[arg]); ixj_play_stop(j); - ixj_play_stop(ixj[arg]); idle(j); - idle(ixj[arg]); + get_ixj(arg)->intercom = -1; + ixj_record_stop(get_ixj(arg)); + ixj_play_stop(get_ixj(arg)); + idle(get_ixj(arg)); break; case IXJCTL_INTERCOM_START: - if (ixj[arg] == NULL) - return -ENODEV; - + if(arg < 0 || arg >= IXJMAX) + return -EINVAL; j->intercom = arg; - ixj[arg]->intercom = board; - ixj_play_start(ixj[arg]); ixj_record_start(j); ixj_play_start(j); - ixj_record_start(ixj[arg]); - idle(j); - idle(ixj[arg]); + get_ixj(arg)->intercom = board; + ixj_play_start(get_ixj(arg)); + ixj_record_start(get_ixj(arg)); break; } + if (ixjdebug & 0x0040) + printk("phone%d ioctl end, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); + clear_bit(board, &j->busyflags); return retval; } static int ixj_fasync(int fd, struct file *file_p, int mode) { - IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)]; - - if (j == NULL) /* shouldn't happen! */ - return -ENODEV; + IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode->i_rdev)); return fasync_helper(fd, file_p, mode, &j->async_queue); } struct file_operations ixj_fops = { - owner: THIS_MODULE, - read: ixj_enhanced_read, - write: ixj_enhanced_write, - poll: ixj_poll, - ioctl: ixj_ioctl, - release: ixj_release, - fasync: ixj_fasync + owner: THIS_MODULE, + read: ixj_enhanced_read, + write: ixj_enhanced_write, + poll: ixj_poll, + ioctl: ixj_ioctl, + release: ixj_release, + fasync: ixj_fasync }; static int ixj_linetest(IXJ *j) { unsigned long jifwait; - j->flags.incheck = 1; // Testing - if (!j->flags.pots_correct) { - j->flags.pots_correct = 1; - - daa_int_read(j); //Clear DAA Interrupt flags - // - // Hold all relays in the normally de-energized position. - // + j->flags.pstncheck = 1; /* Testing */ + j->flags.pstn_present = 0; /* Assume the line is not there */ + + daa_int_read(j); /*Clear DAA Interrupt flags */ + /* */ + /* Hold all relays in the normally de-energized position. */ + /* */ + j->pld_slicw.bits.rly1 = 0; + j->pld_slicw.bits.rly2 = 0; + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01); + if (j->pld_slicr.bits.potspstn) { + j->flags.pots_pstn = 1; + j->flags.pots_correct = 0; + LED_SetState(0x4, j); + } else { + j->flags.pots_pstn = 0; j->pld_slicw.bits.rly1 = 0; j->pld_slicw.bits.rly2 = 0; - j->pld_slicw.bits.rly3 = 0; + j->pld_slicw.bits.rly3 = 1; outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01); - if (j->pld_slicr.bits.potspstn) { - j->flags.pots_pstn = 1; - j->flags.pots_correct = 0; + daa_set_mode(j, SOP_PU_CONVERSATION); + jifwait = jiffies + hertz; + while (time_before(jiffies, jifwait)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + daa_int_read(j); + daa_set_mode(j, SOP_PU_RESET); + if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { + j->flags.pots_correct = 0; /* Should not be line voltage on POTS port. */ LED_SetState(0x4, j); + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); } else { - j->flags.pots_pstn = 0; - j->pld_slicw.bits.rly1 = 0; + j->flags.pots_correct = 1; + LED_SetState(0x8, j); + j->pld_slicw.bits.rly1 = 1; j->pld_slicw.bits.rly2 = 0; - j->pld_slicw.bits.rly3 = 1; + j->pld_slicw.bits.rly3 = 0; outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync - - outb_p(j->pld_scrw.byte, j->XILINXbase); - daa_set_mode(j, SOP_PU_CONVERSATION); - jifwait = jiffies + hertz; - while (time_before(jiffies, jifwait)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - daa_int_read(j); - daa_set_mode(j, SOP_PU_SLEEP); - if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { - j->flags.pots_correct = 0; // Should not be line voltage on POTS port. - - LED_SetState(0x4, j); - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - } else { - j->flags.pots_correct = 1; - LED_SetState(0x8, j); - j->pld_slicw.bits.rly1 = 1; - j->pld_slicw.bits.rly2 = 0; - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - } } } -// if (!j->flags.pstn_present) { j->pld_slicw.bits.rly3 = 0; outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); daa_set_mode(j, SOP_PU_CONVERSATION); @@ -5222,13 +6831,13 @@ schedule_timeout(1); } daa_int_read(j); - daa_set_mode(j, SOP_PU_SLEEP); + daa_set_mode(j, SOP_PU_RESET); if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { + j->pstn_sleeptil = jiffies + (hertz / 4); j->flags.pstn_present = 1; } else { j->flags.pstn_present = 0; } -// } if (j->flags.pstn_present) { if (j->flags.pots_correct) { LED_SetState(0xA, j); @@ -5242,36 +6851,39 @@ LED_SetState(0x5, j); } } - j->flags.incheck = 0; // Testing + j->flags.pstncheck = 0; /* Testing */ return j->flags.pstn_present; } -static int ixj_selfprobe(IXJ *j, int cnt) +static int ixj_selfprobe(IXJ *j) { unsigned short cmd; unsigned long jif; - int i; + int cnt; BYTES bytes; - - init_waitqueue_head(&j->poll_q); - init_waitqueue_head(&j->read_q); - init_waitqueue_head(&j->write_q); - if (ixjdebug > 0) + + init_waitqueue_head(&j->poll_q); + init_waitqueue_head(&j->read_q); + init_waitqueue_head(&j->write_q); + + while(atomic_read(&j->DSPWrite) > 0) + atomic_dec(&j->DSPWrite); + if (ixjdebug & 0x0002) printk(KERN_INFO "Write IDLE to Software Control Register\n"); - ixj_WriteDSPCommand(0x0FE0, j); // Put the DSP in full power mode. + ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ if (ixj_WriteDSPCommand(0x0000, j)) /* Write IDLE to Software Control Register */ return -1; -// The read values of the SSR should be 0x00 for the IDLE command +/* The read values of the SSR should be 0x00 for the IDLE command */ if (j->ssr.low || j->ssr.high) return -1; - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk(KERN_INFO "Get Device ID Code\n"); if (ixj_WriteDSPCommand(0x3400, j)) /* Get Device ID Code */ return -1; j->dsp.low = j->ssr.low; j->dsp.high = j->ssr.high; - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk(KERN_INFO "Get Device Version Code\n"); if (ixj_WriteDSPCommand(0x3800, j)) /* Get Device Version Code */ return -1; @@ -5279,13 +6891,12 @@ j->ver.high = j->ssr.high; if (!j->cardtype) { if (j->dsp.low == 0x21) { -// j->XILINXbase = j->DSPbase + 0x10; bytes.high = bytes.low = inb_p(j->XILINXbase + 0x02); outb_p(bytes.low ^ 0xFF, j->XILINXbase + 0x02); -// Test for Internet LineJACK or Internet PhoneJACK Lite +/* Test for Internet LineJACK or Internet PhoneJACK Lite */ bytes.low = inb_p(j->XILINXbase + 0x02); - if (bytes.low == bytes.high) // Register is read only on - // Internet PhoneJack Lite + if (bytes.low == bytes.high) /* Register is read only on */ + /* Internet PhoneJack Lite */ { j->cardtype = QTI_PHONEJACK_LITE; if (check_region(j->XILINXbase, 4)) { @@ -5343,14 +6954,12 @@ break; } } - if (j->dsp.low == 0x20 - || j->cardtype == QTI_PHONEJACK_LITE - || j->cardtype == QTI_PHONEJACK_PCI) { - if (ixjdebug > 0) + if (j->dsp.low == 0x20 || j->cardtype == QTI_PHONEJACK_LITE || j->cardtype == QTI_PHONEJACK_PCI) { + if (ixjdebug & 0x0002) printk(KERN_INFO "Write CODEC config to Software Control Register\n"); if (ixj_WriteDSPCommand(0xC462, j)) /* Write CODEC config to Software Control Register */ return -1; - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk(KERN_INFO "Write CODEC timing to Software Control Register\n"); if (j->cardtype == QTI_PHONEJACK) { cmd = 0x9FF2; @@ -5362,7 +6971,7 @@ } else { if (set_base_frame(j, 30) != 30) return -1; - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk(KERN_INFO "Write CODEC config to Software Control Register\n"); if (j->cardtype == QTI_PHONECARD) { if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to Software Control Register */ @@ -5371,7 +6980,7 @@ if (j->cardtype == QTI_LINEJACK) { if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to Software Control Register */ return -1; - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk(KERN_INFO "Turn on the PLD Clock at 8Khz\n"); j->pld_clock.byte = 0; outb_p(j->pld_clock.byte, j->XILINXbase + 0x04); @@ -5379,7 +6988,7 @@ } if (j->dsp.low == 0x20) { - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk(KERN_INFO "Configure GPIO pins\n"); j->gpio.bytes.high = 0x09; /* bytes.low = 0xEF; 0xF7 */ @@ -5391,7 +7000,7 @@ j->gpio.bits.gpio6 = 1; j->gpio.bits.gpio7 = 1; ixj_WriteDSPCommand(j->gpio.word, j); /* Set GPIO pin directions */ - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk(KERN_INFO "Enable SLIC\n"); j->gpio.bytes.high = 0x0B; j->gpio.bytes.low = 0x00; @@ -5428,51 +7037,86 @@ } LED_SetState(0x0, j); daa_get_version(j); - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk("Loading DAA Coefficients\n"); DAA_Coeff_US(j); - if (!ixj_daa_write(j)) - printk("DAA write failed on board %d\n", - j->p.board); - ixj_daa_cid_reset(j); + if (!ixj_daa_write(j)) { + printk("DAA write failed on board %d\n", j->board); + return -1; + } + if(!ixj_daa_cid_reset(j)) { + printk("DAA CID reset failed on board %d\n", j->board); + return -1; + } j->flags.pots_correct = 0; j->flags.pstn_present = 0; ixj_linetest(j); if (j->flags.pots_correct) { - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ outb_p(j->pld_scrw.byte, j->XILINXbase); j->pld_slicw.bits.rly1 = 1; j->pld_slicw.bits.spken = 1; outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); +/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ j->port = PORT_POTS; } ixj_set_port(j, PORT_PSTN); ixj_set_pots(j, 1); - if (ixjdebug > 0) + if (ixjdebug & 0x0002) printk(KERN_INFO "Enable Mixer\n"); - ixj_mixer(0x0000, j); //Master Volume Left unmute 0db + ixj_mixer(0x0000, j); /*Master Volume Left unmute 0db */ + ixj_mixer(0x0100, j); /*Master Volume Right unmute 0db */ + + ixj_mixer(0x0203, j); /*Voice Left Volume unmute 6db */ + ixj_mixer(0x0303, j); /*Voice Right Volume unmute 6db */ - ixj_mixer(0x0100, j); //Master Volume Right unmute 0db + ixj_mixer(0x0480, j); /*FM Left mute */ + ixj_mixer(0x0580, j); /*FM Right mute */ - ixj_mixer(0x0F00, j); //Mono Out Volume unmute 0db + ixj_mixer(0x0680, j); /*CD Left mute */ + ixj_mixer(0x0780, j); /*CD Right mute */ - ixj_mixer(0x0C00, j); //Mono1 Volume unmute 0db + ixj_mixer(0x0880, j); /*Line Left mute */ + ixj_mixer(0x0980, j); /*Line Right mute */ - ixj_mixer(0x0200, j); //Voice Left Volume unmute 0db + ixj_mixer(0x0A80, j); /*Aux left mute */ + ixj_mixer(0x0B80, j); /*Aux right mute */ - ixj_mixer(0x0300, j); //Voice Right Volume unmute 0db + ixj_mixer(0x0C00, j); /*Mono1 unmute 12db */ + ixj_mixer(0x0D80, j); /*Mono2 mute */ - ixj_mixer(0x110C, j); //Voice Left and Right out + ixj_mixer(0x0E80, j); /*Mic mute */ - ixj_mixer(0x1401, j); //Mono1 switch on mixer left + ixj_mixer(0x0F00, j); /*Mono Out Volume unmute 0db */ - ixj_mixer(0x1501, j); //Mono1 switch on mixer right + ixj_mixer(0x1000, j); /*Voice Left and Right out only */ + ixj_mixer(0x110C, j); - ixj_mixer(0x1700, j); //Clock select - ixj_mixer(0x1800, j); //ADC Source select + ixj_mixer(0x1200, j); /*Mono1 switch on mixer left */ + ixj_mixer(0x1401, j); + + ixj_mixer(0x1300, j); /*Mono1 switch on mixer right */ + ixj_mixer(0x1501, j); + + ixj_mixer(0x1700, j); /*Clock select */ + + ixj_mixer(0x1800, j); /*ADC input from mixer */ + + ixj_mixer(0x1901, j); /*Mic gain 30db */ + + if (ixjdebug & 0x0002) + printk(KERN_INFO "Setting Default US Ring Cadence Detection\n"); + j->cadence_f[4].state = 0; + j->cadence_f[4].on1 = 0; /*Cadence Filter 4 is used for PSTN ring cadence */ + j->cadence_f[4].off1 = 0; + j->cadence_f[4].on2 = 0; + j->cadence_f[4].off2 = 0; + j->cadence_f[4].on3 = 0; + j->cadence_f[4].off3 = 0; /* These should represent standard US ring pulse. */ + j->pstn_last_rmr = jiffies; } else { if (j->cardtype == QTI_PHONECARD) { @@ -5482,6 +7126,7 @@ } else { ixj_set_port(j, PORT_POTS); SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); +/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ } } } @@ -5490,31 +7135,43 @@ j->framesread = j->frameswritten = 0; j->read_wait = j->write_wait = 0; j->rxreadycheck = j->txreadycheck = 0; + + /* initialise the DTMF prescale to a sensible value */ + if (j->cardtype == QTI_LINEJACK) { + set_dtmf_prescale(j, 0x10); + } else { + set_dtmf_prescale(j, 0x40); + } set_play_volume(j, 0x100); set_rec_volume(j, 0x100); + if (ixj_WriteDSPCommand(0x0000, j)) /* Write IDLE to Software Control Register */ return -1; -// The read values of the SSR should be 0x00 for the IDLE command +/* The read values of the SSR should be 0x00 for the IDLE command */ if (j->ssr.low || j->ssr.high) return -1; - if (ixjdebug > 0) + + if (ixjdebug & 0x0002) printk(KERN_INFO "Enable Line Monitor\n"); - if (ixjdebug > 0) + + if (ixjdebug & 0x0002) printk(KERN_INFO "Set Line Monitor to Asyncronous Mode\n"); - if (ixj_WriteDSPCommand(0x7E01, j)) // Asynchronous Line Monitor + if (ixj_WriteDSPCommand(0x7E01, j)) /* Asynchronous Line Monitor */ return -1; - if (ixjdebug > 0) + + if (ixjdebug & 0x002) printk(KERN_INFO "Enable DTMF Detectors\n"); - if (ixj_WriteDSPCommand(0x5151, j)) // Enable DTMF detection + if (ixj_WriteDSPCommand(0x5151, j)) /* Enable DTMF detection */ return -1; - if (ixj_WriteDSPCommand(0x6E01, j)) // Set Asyncronous Tone Generation + if (ixj_WriteDSPCommand(0x6E01, j)) /* Set Asyncronous Tone Generation */ return -1; - set_rec_depth(j, 2); // Set Record Channel Limit to 2 frames - set_play_depth(j, 2); // Set Playback Channel Limit to 2 frames + set_rec_depth(j, 2); /* Set Record Channel Limit to 2 frames */ + + set_play_depth(j, 2); /* Set Playback Channel Limit to 2 frames */ j->ex.bits.dtmf_ready = 0; j->dtmf_state = 0; @@ -5526,34 +7183,74 @@ j->drybuffer = 0; j->winktime = 320; j->flags.dtmf_oob = 0; - for (i = 0; i < 4; i++) - j->cadence_f[i].enable = 0; + for (cnt = 0; cnt < 4; cnt++) + j->cadence_f[cnt].enable = 0; /* must be a device on the specified address */ - ixj_WriteDSPCommand(0x0FE3, j); // Put the DSP in 1/5 power mode. + ixj_WriteDSPCommand(0x0FE3, j); /* Put the DSP in 1/5 power mode. */ + + /* Set up the default signals for events */ + for (cnt = 0; cnt < 35; cnt++) + j->ixj_signals[cnt] = SIGIO; + + /* Set the excetion signal enable flags */ + j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring = + j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 = + j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1; +#ifdef IXJ_DYN_ALLOC + j->fskdata = NULL; +#endif + j->fskdcnt = 0; + j->cidcw_wait = 0; + /* Register with the Telephony for Linux subsystem */ j->p.f_op = &ixj_fops; j->p.open = ixj_open; - j->p.board = cnt; + j->p.board = j->board; phone_register_device(&j->p, PHONE_UNIT_ANY); - add_caps(j); + + ixj_init_timer(j); + ixj_add_timer(j); return 0; } -int ixj_get_status_proc(char *buf) +/* + * Exported service for pcmcia card handling + */ + +IXJ *ixj_pcmcia_probe(unsigned long dsp, unsigned long xilinx) +{ + IXJ *j = ixj_alloc(); + + j->board = 0; + + j->DSPbase = dsp; + j->XILINXbase = xilinx; + j->cardtype = QTI_PHONECARD; + ixj_selfprobe(j); + return j; +} + +EXPORT_SYMBOL(ixj_pcmcia_probe); /* Fpr PCMCIA */ + +static int ixj_get_status_proc(char *buf) { int len; int cnt; IXJ *j; len = 0; - len += sprintf(buf + len, "\n%s", ixj_c_rcsid); + len += sprintf(buf + len, "%s", ixj_c_rcsid); len += sprintf(buf + len, "\n%s", ixj_h_rcsid); len += sprintf(buf + len, "\n%s", ixjuser_h_rcsid); - for (cnt = 0; cnt < IXJMAX; cnt++) { - j = ixj[cnt]; + len += sprintf(buf + len, "\nDriver version %i.%i.%i", IXJ_VER_MAJOR, IXJ_VER_MINOR, IXJ_BLD_VER); + len += sprintf(buf + len, "\nsizeof IXJ struct %d bytes", sizeof(IXJ)); + len += sprintf(buf + len, "\nsizeof DAA struct %d bytes", sizeof(DAA_REGS)); + len += sprintf(buf + len, "\nUsing old telephony API"); + len += sprintf(buf + len, "\nDebug Level %d\n", ixjdebug); - if (j == NULL) + for (cnt = 0; cnt < IXJMAX; cnt++) { + j = get_ixj(cnt); + if(j==NULL) continue; - if (j->DSPbase) { len += sprintf(buf + len, "\nCard Num %d", cnt); len += sprintf(buf + len, "\nDSP Base Address 0x%4.4x", j->DSPbase); @@ -5570,7 +7267,7 @@ len += sprintf(buf + len, "\nCard Type = Internet LineJACK"); if (j->flags.g729_loaded) len += sprintf(buf + len, " w/G.729 A/B"); - len += sprintf(buf + len, " Country = %d", j->country); + len += sprintf(buf + len, " Country = %d", j->daa_country); break; case (QTI_PHONEJACK_LITE): len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK Lite"); @@ -5597,8 +7294,7 @@ } len += sprintf(buf + len, "\nReaders %d", j->readers); len += sprintf(buf + len, "\nWriters %d", j->writers); - /* FIXME: This makes no sense! */ - len += sprintf(buf + len, "\nFSK words %d", ixj[2] ? ixj[2]->fskdcnt : 0); + add_caps(j); len += sprintf(buf + len, "\nCapabilities %d", j->caps); if (j->dsp.low != 0x20) len += sprintf(buf + len, "\nDSP Processor load %d", j->proc_load); @@ -5607,11 +7303,6 @@ else len += sprintf(buf + len, "\nCaller ID data not sent"); - len += sprintf(buf + len, "\nCaller ID Date %s%s", j->cid_send.month, j->cid_send.day); - len += sprintf(buf + len, "\nCaller ID Time %s%s", j->cid_send.hour, j->cid_send.min); - len += sprintf(buf + len, "\nCaller ID Name %s", j->cid_send.name); - len += sprintf(buf + len, "\nCaller ID Number %s", j->cid_send.number); - len += sprintf(buf + len, "\nPlay CODEC "); switch (j->play_codec) { case G723_63: @@ -5635,6 +7326,9 @@ case G729: len += sprintf(buf + len, "G.729"); break; + case G729B: + len += sprintf(buf + len, "G.729B"); + break; case ULAW: len += sprintf(buf + len, "uLaw"); break; @@ -5677,6 +7371,9 @@ case G729: len += sprintf(buf + len, "G.729"); break; + case G729B: + len += sprintf(buf + len, "G.729B"); + break; case ULAW: len += sprintf(buf + len, "uLaw"); break; @@ -5696,33 +7393,49 @@ len += sprintf(buf + len, "NO CODEC CHOSEN"); break; } + len += sprintf(buf + len, "\nAEC "); switch (j->aec_level) { case AEC_OFF: - len += sprintf(buf + len, "\n AEC OFF"); + len += sprintf(buf + len, "Off"); break; case AEC_LOW: - len += sprintf(buf + len, "\n AEC LOW"); + len += sprintf(buf + len, "Low"); break; case AEC_MED: - len += sprintf(buf + len, "\n AEC MED"); + len += sprintf(buf + len, "Med"); break; case AEC_HIGH: - len += sprintf(buf + len, "\n AEC HIGH"); + len += sprintf(buf + len, "High"); + break; + case AEC_AUTO: + len += sprintf(buf + len, "Auto"); + break; + case AEC_AGC: + len += sprintf(buf + len, "AEC/AGC"); + break; + default: + len += sprintf(buf + len, "unknown(%i)", j->aec_level); break; } - len += sprintf(buf + len, "\nHook state %d", j->r_hook); // ixj_hookstate(cnt)); + + len += sprintf(buf + len, "\nRec volume 0x%x", get_rec_volume(j)); + len += sprintf(buf + len, "\nPlay volume 0x%x", get_play_volume(j)); + len += sprintf(buf + len, "\nDTMF prescale 0x%x", get_dtmf_prescale(j)); + + len += sprintf(buf + len, "\nHook state %d", j->hookstate); /* j->r_hook); */ if (j->cardtype == QTI_LINEJACK) { len += sprintf(buf + len, "\nPOTS Correct %d", j->flags.pots_correct); len += sprintf(buf + len, "\nPSTN Present %d", j->flags.pstn_present); + len += sprintf(buf + len, "\nPSTN Check %d", j->flags.pstncheck); len += sprintf(buf + len, "\nPOTS to PSTN %d", j->flags.pots_pstn); - len += sprintf(buf + len, "\nPSTN sleeptil %ld - jiffies %ld", j->pstn_sleeptil, jiffies); switch (j->daa_mode) { case SOP_PU_SLEEP: len += sprintf(buf + len, "\nDAA PSTN On Hook"); break; case SOP_PU_RINGING: len += sprintf(buf + len, "\nDAA PSTN Ringing"); + len += sprintf(buf + len, "\nRinging state = %d", j->cadence_f[4].state); break; case SOP_PU_CONVERSATION: len += sprintf(buf + len, "\nDAA PSTN Off Hook"); @@ -5731,6 +7444,16 @@ len += sprintf(buf + len, "\nDAA PSTN Pulse Dialing"); break; } + len += sprintf(buf + len, "\nDAA RMR = %d", j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR); + len += sprintf(buf + len, "\nDAA VDD OK = %d", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK); + len += sprintf(buf + len, "\nDAA CR0 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg); + len += sprintf(buf + len, "\nDAA CR1 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg); + len += sprintf(buf + len, "\nDAA CR2 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg); + len += sprintf(buf + len, "\nDAA CR3 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg); + len += sprintf(buf + len, "\nDAA CR4 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg); + len += sprintf(buf + len, "\nDAA CR5 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg); + len += sprintf(buf + len, "\nDAA XR0 = 0x%02x", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg); + len += sprintf(buf + len, "\nDAA ringstop %ld - jiffies %ld", j->pstn_ring_stop, jiffies); } switch (j->port) { case PORT_POTS: @@ -5758,8 +7481,7 @@ case PLD_SLIC_STATE_ACTIVE: len += sprintf(buf + len, "ACTIVE"); break; - case PLD_SLIC_STATE_OHT: // On-hook transmit - + case PLD_SLIC_STATE_OHT: /* On-hook transmit */ len += sprintf(buf + len, "OHT"); break; case PLD_SLIC_STATE_TIPOPEN: @@ -5768,12 +7490,10 @@ case PLD_SLIC_STATE_STANDBY: len += sprintf(buf + len, "STANDBY"); break; - case PLD_SLIC_STATE_APR: // Active polarity reversal - + case PLD_SLIC_STATE_APR: /* Active polarity reversal */ len += sprintf(buf + len, "APR"); break; - case PLD_SLIC_STATE_OHTPR: // OHT polarity reversal - + case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ len += sprintf(buf + len, "OHTPR"); break; default: @@ -5781,16 +7501,24 @@ break; } } + len += sprintf(buf + len, "\nBase Frame %2.2x.%2.2x", j->baseframe.high, j->baseframe.low); + len += sprintf(buf + len, "\nCID Base Frame %2d", j->cid_base_frame_size); #ifdef PERFMON_STATS len += sprintf(buf + len, "\nTimer Checks %ld", j->timerchecks); len += sprintf(buf + len, "\nRX Ready Checks %ld", j->rxreadycheck); len += sprintf(buf + len, "\nTX Ready Checks %ld", j->txreadycheck); - len += sprintf(buf + len, "\nBase Frame %2.2x.%2.2x", j->baseframe.high, j->baseframe.low); len += sprintf(buf + len, "\nFrames Read %ld", j->framesread); len += sprintf(buf + len, "\nFrames Written %ld", j->frameswritten); len += sprintf(buf + len, "\nDry Buffer %ld", j->drybuffer); len += sprintf(buf + len, "\nRead Waits %ld", j->read_wait); len += sprintf(buf + len, "\nWrite Waits %ld", j->write_wait); + len += sprintf(buf + len, "\nStatus Waits %ld", j->statuswait); + len += sprintf(buf + len, "\nStatus Wait Fails %ld", j->statuswaitfail); + len += sprintf(buf + len, "\nPControl Waits %ld", j->pcontrolwait); + len += sprintf(buf + len, "\nPControl Wait Fails %ld", j->pcontrolwaitfail); + len += sprintf(buf + len, "\nIs Control Ready Checks %ld", j->iscontrolready); + len += sprintf(buf + len, "\nIs Control Ready Check failures %ld", j->iscontrolreadyfail); + #endif len += sprintf(buf + len, "\n"); } @@ -5798,19 +7526,6 @@ return len; } -int ixj_get_status_proc_fsk(char *buf) -{ - int len; - len = 0; - - /* This makes no sense - why is ixj[2] special? */ - if (ixj[2] != NULL && ixj[2]->fskdcnt) { - memcpy(buf, &ixj[2]->fskdata, (ixj[2]->fskdcnt) * 2); - len += ixj[2]->fskdcnt * 2; - } - return len; -} - static int ixj_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -5823,409 +7538,92 @@ return len; } -static int ixj_read_proc_fsk(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = ixj_get_status_proc_fsk(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; -} - -MODULE_DESCRIPTION("Internet Phone/Internet LineJack module - www.quicknet.net"); -MODULE_AUTHOR("Ed Okerson "); - -#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -#else -#define DEBUG(n, args...) -#endif /* PCMCIA_DEBUG */ - -typedef struct ixj_info_t { - int ndev; - dev_node_t node; - struct ixj *port; -} ixj_info_t; -static dev_link_t *ixj_attach(void); -static void ixj_detach(dev_link_t *); -static void ixj_config(dev_link_t * link); -static void ixj_cs_release(u_long arg); -static int ixj_event(event_t event, int priority, event_callback_args_t * args); -static dev_info_t dev_info = "ixj_cs"; -static dev_link_t *dev_list = NULL; -static void cs_error(client_handle_t handle, int func, int ret) -{ - error_info_t err = - { - func, ret - }; - CardServices(ReportError, handle, &err); -} - -static dev_link_t *ixj_attach(void) -{ - client_reg_t client_reg; - dev_link_t *link; - int ret; - DEBUG(0, "ixj_attach()\n"); - /* Create new ixj device */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) - return NULL; - memset(link, 0, sizeof(struct dev_link_t)); - link->release.function = &ixj_cs_release; - link->release.data = (u_long) link; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); - if (!link->priv) - return NULL; - memset(link->priv, 0, sizeof(struct ixj_info_t)); - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ixj_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - ixj_detach(link); - return NULL; - } - return link; -} - -static void ixj_detach(dev_link_t * link) -{ - dev_link_t **linkp; - long flags; - int ret; - DEBUG(0, "ixj_detach(0x%p)\n", link); - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) - break; - if (*linkp == NULL) - return; - save_flags(flags); - cli(); - if (link->state & DEV_RELEASE_PENDING) { - del_timer(&link->release); - link->state &= ~DEV_RELEASE_PENDING; - } - restore_flags(flags); - if (link->state & DEV_CONFIG) - ixj_cs_release((u_long) link); - if (link->handle) { - ret = CardServices(DeregisterClient, link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - /* Unlink device structure, free bits */ - *linkp = link->next; - kfree(link->priv); - kfree(link); -} - -#define CS_CHECK(fn, args...) \ -while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed - -#define CFG_CHECK(fn, args...) \ -if (CardServices(fn, args) != 0) goto next_entry - -void ixj_get_serial(dev_link_t * link, IXJ * j) -{ - client_handle_t handle; - tuple_t tuple; - u_short buf[128]; - char *str; - int last_ret, last_fn, i, place; - handle = link->handle; - DEBUG(0, "ixj_get_serial(0x%p)\n", link); - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 80; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_VERS_1; - CS_CHECK(GetFirstTuple, handle, &tuple); - CS_CHECK(GetTupleData, handle, &tuple); - str = (char *) buf; - printk("PCMCIA Version %d.%d\n", str[0], str[1]); - str += 2; - printk("%s", str); - str = str + strlen(str) + 1; - printk(" %s", str); - str = str + strlen(str) + 1; - place = 1; - for (i = strlen(str) - 1; i >= 0; i--) { - switch (str[i]) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - j->serial += (str[i] - 48) * place; - break; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - j->serial += (str[i] - 55) * place; - break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - j->serial += (str[i] - 87) * place; - break; - } - place = place * 0x10; - } - str = str + strlen(str) + 1; - printk(" version %s\n", str); - cs_failed: - return; -} - -void ixj_config(dev_link_t * link) -{ - IXJ *j; - client_handle_t handle; - ixj_info_t *info; - tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = - { - 0 - }; - int last_ret, last_fn; - handle = link->handle; - info = link->priv; - DEBUG(0, "ixj_config(0x%p)\n", link); - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, handle, &tuple); - CS_CHECK(GetTupleData, handle, &tuple); - CS_CHECK(ParseTuple, handle, &tuple, &parse); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - link->state |= DEV_CONFIG; - CS_CHECK(GetConfigurationInfo, handle, &conf); - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, handle, &tuple); - while (1) { - CFG_CHECK(GetTupleData, handle, &tuple); - CFG_CHECK(ParseTuple, handle, &tuple, &parse); - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->conf.ConfigIndex = cfg->index; - link->io.BasePort1 = io->win[0].base; - link->io.NumPorts1 = io->win[0].len; - if (io->nwin == 2) { - link->io.BasePort2 = io->win[1].base; - link->io.NumPorts2 = io->win[1].len; - } - CFG_CHECK(RequestIO, link->handle, &link->io); - /* If we've got this far, we're done */ - break; - } - next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) - dflt = *cfg; - CS_CHECK(GetNextTuple, handle, &tuple); - } - - CS_CHECK(RequestConfiguration, handle, &link->conf); - - - if ((j = kmalloc(sizeof(*j), GFP_KERNEL)) == NULL) - goto cs_failed; - - ixj[0] = j; - - j->DSPbase = link->io.BasePort1; - j->XILINXbase = link->io.BasePort1 + 0x10; - j->cardtype = QTI_PHONECARD; - ixj_selfprobe(j, 0); - - info->ndev = 1; - info->node.major = PHONE_MAJOR; - link->dev = &info->node; - ixj_get_serial(link, j); - link->state &= ~DEV_CONFIG_PENDING; - return; - - cs_failed: - cs_error(link->handle, last_fn, last_ret); - ixj_cs_release((u_long) link); -} - -void ixj_cs_release(u_long arg) -{ - dev_link_t *link = (dev_link_t *) arg; - ixj_info_t *info = link->priv; - DEBUG(0, "ixj_cs_release(0x%p)\n", link); - info->ndev = 0; - link->dev = NULL; - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - link->state &= ~DEV_CONFIG; - - kfree(ixj[0]); - ixj[0] = NULL; -} - -int ixj_event(event_t event, int priority, event_callback_args_t * args) -{ - dev_link_t *link = args->client_data; - DEBUG(1, "ixj_event(0x%06x)\n", event); - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) { - link->release.expires = jiffies + (HZ / 20); - link->state |= DEV_RELEASE_PENDING; - add_timer(&link->release); - } - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ixj_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - CardServices(ReleaseConfiguration, link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link)) - CardServices(RequestConfiguration, link->handle, &link->conf); - break; - } - return 0; -} - -#endif /* CONFIG_PCMCIA */ static void cleanup(void) { int cnt; - del_timer(&ixj_timer); - for (cnt = 0; cnt < IXJMAX; cnt++) { - IXJ *j = ixj[cnt]; - - if (j == NULL) - continue; + IXJ *j; - if (j->cardtype == QTI_LINEJACK) { - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + for (cnt = 0; cnt < IXJMAX; cnt++) { + j = get_ixj(cnt); + if(j != NULL && j->DSPbase) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Deleting timer for /dev/phone%d\n", cnt); + del_timer(&j->timer); + if (j->cardtype == QTI_LINEJACK) { + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicw.bits.rly1 = 0; - j->pld_slicw.bits.rly2 = 0; - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - LED_SetState(0x0, j); - release_region(j->XILINXbase, 8); - } - if (j->cardtype == QTI_PHONEJACK_LITE - || j->cardtype == QTI_PHONEJACK_PCI) { - release_region(j->XILINXbase, 4); - } - if (j->DSPbase) { - release_region(j->DSPbase, 16); + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly1 = 0; + j->pld_slicw.bits.rly2 = 0; + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + LED_SetState(0x0, j); + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt); + release_region(j->XILINXbase, 8); + } else if (j->cardtype == QTI_PHONEJACK_LITE || j->cardtype == QTI_PHONEJACK_PCI) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt); + release_region(j->XILINXbase, 4); + } + if (j->read_buffer) + kfree(j->read_buffer); + if (j->write_buffer) + kfree(j->write_buffer); + if (j->dev && j->dev->deactivate) + j->dev->deactivate(j->dev); + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Unregistering /dev/phone%d from LTAPI\n", cnt); phone_unregister_device(&j->p); - } - if (j->read_buffer) - kfree(j->read_buffer); - if (j->write_buffer) - kfree(j->write_buffer); -#ifdef CONFIG_ISAPNP - if (j->dev) - j->dev->deactivate(j->dev); -#endif -#ifdef CONFIG_PCMCIA - DEBUG(0, "ixj_cs: unloading\n"); - unregister_pcmcia_driver(&dev_info); - while (dev_list != NULL) - ixj_detach(dev_list); + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Releasing DSP address for /dev/phone%d\n", cnt); + release_region(j->DSPbase, 16); +#ifdef IXJ_DYN_ALLOC + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Freeing memory for /dev/phone%d\n", cnt); + kfree(j); + ixj[cnt] = NULL; #endif - - kfree(j); - ixj[cnt] = NULL; + } } + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Removing /proc/ixj\n"); remove_proc_entry ("ixj", NULL); - remove_proc_entry ("ixjfsk", NULL); } -// Typedefs +/* Typedefs */ typedef struct { BYTE length; DWORD bits; } DATABLOCK; + static void PCIEE_WriteBit(WORD wEEPROMAddress, BYTE lastLCC, BYTE byData) { lastLCC = lastLCC & 0xfb; lastLCC = lastLCC | (byData ? 4 : 0); - outb(lastLCC, wEEPROMAddress); //set data out bit as appropriate + outb(lastLCC, wEEPROMAddress); /*set data out bit as appropriate */ - udelay(1000); + mdelay(1); lastLCC = lastLCC | 0x01; - outb(lastLCC, wEEPROMAddress); //SK rising edge + outb(lastLCC, wEEPROMAddress); /*SK rising edge */ byData = byData << 1; lastLCC = lastLCC & 0xfe; - udelay(1000); - outb(lastLCC, wEEPROMAddress); //after delay, SK falling edge + mdelay(1); + outb(lastLCC, wEEPROMAddress); /*after delay, SK falling edge */ } static BYTE PCIEE_ReadBit(WORD wEEPROMAddress, BYTE lastLCC) { - udelay(1000); + mdelay(1); lastLCC = lastLCC | 0x01; - outb(lastLCC, wEEPROMAddress); //SK rising edge + outb(lastLCC, wEEPROMAddress); /*SK rising edge */ lastLCC = lastLCC & 0xfe; - udelay(1000); - outb(lastLCC, wEEPROMAddress); //after delay, SK falling edge + mdelay(1); + outb(lastLCC, wEEPROMAddress); /*after delay, SK falling edge */ return ((inb(wEEPROMAddress) >> 3) & 1); } @@ -6240,9 +7638,9 @@ lastLCC = inb(wEEPROMAddress); lastLCC = lastLCC | 0x02; lastLCC = lastLCC & 0xfe; - outb(lastLCC, wEEPROMAddress); // CS hi, SK lo + outb(lastLCC, wEEPROMAddress); /* CS hi, SK lo */ - udelay(1000); // delay + mdelay(1); /* delay */ PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1); PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1); @@ -6257,10 +7655,10 @@ *pwResult = (*pwResult << 1) | byResult; } - udelay(1000); // another delay + mdelay(1); /* another delay */ lastLCC = lastLCC & 0xfd; - outb(lastLCC, wEEPROMAddress); // negate CS + outb(lastLCC, wEEPROMAddress); /* negate CS */ return 0; } @@ -6275,51 +7673,31 @@ return (((DWORD) wHi << 16) | wLo); } -#ifndef CONFIG_ISAPNP -static int dspio[IXJMAX + 1]; -static int xio[IXJMAX + 1]; +static int dspio[IXJMAX + 1] = +{ + 0, +}; +static int xio[IXJMAX + 1] = +{ + 0, +}; MODULE_PARM(dspio, "1-" __MODULE_STRING(IXJMAX) "i"); MODULE_PARM(xio, "1-" __MODULE_STRING(IXJMAX) "i"); -#endif +MODULE_DESCRIPTION("Quicknet VoIP Telephony card module - www.quicknet.net"); +MODULE_AUTHOR("Ed Okerson "); +MODULE_LICENSE("GPL"); void ixj_exit(void) { - cleanup(); -} - -#if defined(CONFIG_PCMCIA) -int __init ixj_register_pcmcia(void) -{ - servinfo_t serv; - - DEBUG(0, "%s\n", version); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "ixj_cs: Card Services release does not match!\n"); - return -EINVAL; - } - register_pcmcia_driver(&dev_info, &ixj_attach, &ixj_detach); - return 0; -} -#else -extern __inline__ int ixj_register_pcmcia(void) -{ - return 0; -} -#endif /* CONFIG_PCMCIA */ - -#if defined(CONFIG_ISAPNP) -extern __inline__ int ixj_probe_isa(int *cnt) -{ - return 0; + cleanup(); } int __init ixj_probe_isapnp(int *cnt) -{ +{ int probe = 0; int func = 0x110; - struct pci_dev *dev = NULL, *old_dev = NULL; + struct pci_dev *dev = NULL, *old_dev = NULL; while (1) { do { @@ -6328,7 +7706,7 @@ old_dev = dev; dev = isapnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'), - ISAPNP_FUNCTION(func), old_dev); + ISAPNP_FUNCTION(func), old_dev); if (!dev) break; result = dev->prepare(dev); @@ -6348,28 +7726,17 @@ return -ENOMEM; } - /* DSP base */ - if ((result = check_region(dev->resource[0].start, 16)) < 0) { - printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", - dev->resource[0].start); - cleanup(); - return result; - } - - if ((j = kmalloc(sizeof(*j), GFP_KERNEL)) == NULL) { - cleanup(); - return -ENOMEM; + result = check_region(dev->resource[0].start, 16); + if (result) { + printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", dev->resource[0].start); + break; } - ixj[*cnt] = j; - - j->DSPbase = dev->resource[0].start; - - /* XXX is this racy? */ + j = ixj_alloc(); request_region(j->DSPbase, 16, "ixj DSP"); if (func != 0x110) - j->XILINXbase = dev->resource[1].start; + j->XILINXbase = dev->resource[1].start; /* get real port */ switch (func) { case (0x110): @@ -6382,23 +7749,22 @@ j->cardtype = QTI_PHONEJACK_LITE; break; } - probe = ixj_selfprobe(j, *cnt); - - j->serial = dev->bus->serial; - j->dev = dev; - switch (func) { - case 0x110: - printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n", - j->DSPbase); - break; - case 0x310: - printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n", - j->DSPbase); - break; - case 0x410: - printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n", - j->DSPbase); - break; + j->board = *cnt; + probe = ixj_selfprobe(j); + if(!probe) { + j->serial = dev->bus->serial; + j->dev = dev; + switch (func) { + case 0x110: + printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n", j->DSPbase); + break; + case 0x310: + printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n", j->DSPbase); + break; + case 0x410: + printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n", j->DSPbase); + break; + } } ++*cnt; } while (dev); @@ -6410,15 +7776,9 @@ func = 0x310; dev = NULL; } - return probe; } -#else -extern __inline__ int ixj_probe_isapnp(int *cnt) -{ - return 0; -} - + int __init ixj_probe_isa(int *cnt) { int i, result, probe; @@ -6428,17 +7788,12 @@ if (dspio[i]) { IXJ *j; - if ((result = check_region(dspio[i], 16)) < 0) { - printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", dspio[i]); - cleanup(); - return result; + if ((result = check_region(ixj[*cnt].DSPbase, 16)) < 0) { + printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[*cnt].DSPbase); + break; } - if ((j = kmalloc(sizeof(*j), GFP_KERNEL)) == NULL) { - cleanup(); - return -ENOMEM; - } - ixj[*cnt] = j; + j = ixj_alloc(); j->DSPbase = dspio[i]; request_region(j->DSPbase, 16, "ixj DSP"); @@ -6446,78 +7801,64 @@ j->XILINXbase = xio[i]; j->cardtype = 0; - probe = ixj_selfprobe(j, *cnt); + j->board = *cnt; + probe = ixj_selfprobe(j); j->dev = NULL; - ++*cnt; } } - return 0; } -#endif /* CONFIG_ISAPNP */ -#if defined(CONFIG_PCI) int __init ixj_probe_pci(int *cnt) { - struct pci_dev *pci = NULL; + struct pci_dev *pci = NULL; int i, probe = 0; + IXJ *j = NULL; + int result; + + if(!pci_present()) + return 0; for (i = 0; i < IXJMAX - *cnt; i++) { pci = pci_find_device(0x15E2, 0x0500, pci); if (!pci) break; + if (pci_enable_device(pci)) break; - { - IXJ *j; - int result; - - if ((result = check_region(pci_resource_start(pci, 0), 16)) < 0) { - printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", - pci_resource_start(pci, 0)); - cleanup(); - return result; - } - - if ((j = kmalloc(sizeof(*j), GFP_KERNEL)) == NULL) { - cleanup(); - return -ENOMEM; - } - ixj[*cnt] = j; - - j->DSPbase = pci_resource_start(pci, 0); - request_region(j->DSPbase, 16, "ixj DSP"); - - j->XILINXbase = j->DSPbase + 0x10; - j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2); - j->cardtype = QTI_PHONEJACK_PCI; - - probe = ixj_selfprobe(j, *cnt); - if (probe) - printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", j->DSPbase); - ++*cnt; + if ((result = check_region(pci_resource_start(pci, 0), 16)) < 0) { + printk(KERN_INFO "ixj: can't get I/O address\n"); + break; } - } + /* Grab a device slot */ + j = ixj_alloc(); + if(j == NULL) + break; + + j->DSPbase = pci_resource_start(pci, 0); + j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2); + j->XILINXbase = j->DSPbase + 0x10; + request_region(j->DSPbase, 16, "ixj DSP"); + j->cardtype = QTI_PHONEJACK_PCI; + j->board = *cnt; + probe = ixj_selfprobe(j); + if (!probe) + printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", j->DSPbase); + ++*cnt; + } return probe; } -#else -extern __inline__ int ixj_probe_pci(int *cnt) -{ - return 0; -} -#endif /* CONFIG_PCI */ int __init ixj_init(void) { int cnt = 0; - int probe = 0; + int probe = 0; + + cnt = 0; /* These might be no-ops, see above. */ - if ((probe = ixj_register_pcmcia()) < 0) { - return probe; - } if ((probe = ixj_probe_isapnp(&cnt)) < 0) { return probe; } @@ -6528,16 +7869,9 @@ if ((probe = ixj_probe_pci(&cnt)) < 0) { return probe; } - } - + } printk("%s\n", ixj_c_rcsid); - create_proc_read_entry ("ixj", 0, NULL, ixj_read_proc, NULL); - create_proc_read_entry ("ixjfsk", 0, NULL, ixj_read_proc_fsk, NULL); - - ixj_init_timer(); - ixj_add_timer(); - return probe; } @@ -6549,112 +7883,138 @@ int i; j->daa_country = DAA_US; - //----------------------------------------------- - // CAO + /*----------------------------------------------- */ + /* CAO */ for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } -// Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00 - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2F; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xC2; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xC0; +/* Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x03; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0x4B; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x5D; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xCD; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0x24; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xC5; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -// Bytes for IM-filter part 2 (05): 72,85,00,0E,2B,3A,D0,08 - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x72; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x85; +/* Bytes for IM-filter part 2 (05): 72,85,00,0E,2B,3A,D0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x71; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x1A; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x2B; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0A; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -// Bytes for FRX-filter (08): 03,8F,48,F2,8F,48,70,08 - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x03; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x48; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0xF2; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x8F; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x48; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x70; +/* Bytes for FRX-filter (08): 03,8F,48,F2,8F,48,70,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x05; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x72; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x3F; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x3B; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -// Bytes for FRR-filter (07): 04,8F,38,7F,9B,EA,B0,08 - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x04; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0x38; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x7F; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x9B; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA; +/* Bytes for FRR-filter (07): 04,8F,38,7F,9B,EA,B0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x05; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF9; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x3E; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xDA; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -// Bytes for AX-filter (0A): 16,55,DD,CA - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x55; +/* Bytes for AX-filter (0A): 16,55,DD,CA */ + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x41; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -// Bytes for AR-filter (09): 52,D3,11,42 - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xD3; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x11; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x42; -// Bytes for TH-filter part 1 (00): 00,42,48,81,B3,80,00,98 +/* Bytes for AR-filter (09): 52,D3,11,42 */ + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; +/* Bytes for TH-filter part 1 (00): 00,42,48,81,B3,80,00,98 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xA5; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -// Bytes for TH-filter part 2 (01): 02,F2,33,A0,68,AB,8A,AD +/* Bytes for TH-filter part 2 (01): 02,F2,33,A0,68,AB,8A,AD */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xF2; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x33; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xA0; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x68; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xB0; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0xE8; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAB; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAD; -// Bytes for TH-filter part 3 (02): 00,88,DA,54,A4,BA,2D,BB + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xCC; +/* Bytes for TH-filter part 3 (02): 00,88,DA,54,A4,BA,2D,BB */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x54; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0xA4; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2D; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBB; -// ; (10K, 0.68uF) - // - // Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xD2; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x24; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xA9; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x3B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xA6; +/* ; (10K, 0.68uF) */ + /* */ + /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x9B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0xD4; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -// Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42; + /* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0xD4; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -// - // Levelmetering Ringing (0D):B2,45,0F,8E - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; + + /* Levelmetering Ringing (0D):B2,45,0F,8E */ + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; -// Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 + + /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1C; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0xB3; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0xAB; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0xAB; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x54; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x2D; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0x62; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x2D; */ + /* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x2D; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x62; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBB; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x2A; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7D; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD4; */ +/* */ + /* Levelmetering Ringing (0D):B2,45,0F,8E */ +/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x05; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; */ + + /* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; @@ -6663,7 +8023,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -// Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; @@ -6672,56 +8032,56 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -// - // ;CR Registers - // Config. Reg. 0 (filters) (cr0):FE ; CLK gen. by crystal +/* */ + /* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FE ; CLK gen. by crystal */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; -// Config. Reg. 1 (dialing) (cr1):05 +/* Config. Reg. 1 (dialing) (cr1):05 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -// Config. Reg. 2 (caller ID) (cr2):04 +/* Config. Reg. 2 (caller ID) (cr2):04 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -// Config. Reg. 3 (testloops) (cr3):03 ; SEL Bit==0, HP-disabled - j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x03; -// Config. Reg. 4 (analog gain) (cr4):01 - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - // Config. Reg. 5 (Version) (cr5):02 - // Config. Reg. 6 (Reserved) (cr6):00 - // Config. Reg. 7 (Reserved) (cr7):00 - // - // ;xr Registers - // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 +/* Config. Reg. 3 (testloops) (cr3):03 ; SEL Bit==0, HP-disabled */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. - // Ext. Reg. 1 (Interrupt enable) (xr1):1C // Cadence, RING, Caller ID, VDD_OK + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):3C Cadence, RING, Caller ID, VDD_OK */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x3C; -// Ext. Reg. 2 (Cadence Time Out) (xr2):7D +/* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -// Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off == 1 - j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x12; //0x32; - // Ext. Reg. 4 (Cadence) (xr4):00 +/* Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off == 1 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x3B; /*0x32; */ + /* Ext. Reg. 4 (Cadence) (xr4):00 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -// Ext. Reg. 5 (Ring timer) (xr5):22 +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -// Ext. Reg. 6 (Power State) (xr6):00 +/* Ext. Reg. 6 (Power State) (xr6):00 */ j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -// Ext. Reg. 7 (Vdd) (xr7):40 - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; // 0x40 ??? Should it be 0x00? - // - // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz - // 12,33,5A,C3 ; 770 Hz - // 13,3C,5B,32 ; 852 Hz - // 1D,1B,5C,CC ; 941 Hz +/* Ext. Reg. 7 (Vdd) (xr7):40 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ + /* */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -// DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz - // EC,1D,52,22 ; 1336 Hz - // AA,AC,51,D2 ; 1477 Hz - // 9B,3B,51,25 ; 1633 Hz +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; @@ -6733,13 +8093,13 @@ int i; j->daa_country = DAA_UK; - //----------------------------------------------- - // CAO + /*----------------------------------------------- */ + /* CAO */ for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } -// Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00 +/* Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xC2; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB; @@ -6748,7 +8108,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -// Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08 +/* Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x40; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; @@ -6757,7 +8117,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -// Bytes for FRX-filter (08): 07,9B,ED,24,B2,A2,A0,08 +/* Bytes for FRX-filter (08): 07,9B,ED,24,B2,A2,A0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9B; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xED; @@ -6766,7 +8126,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -// Bytes for FRR-filter (07): 0F,92,F2,B2,87,D2,30,08 +/* Bytes for FRR-filter (07): 0F,92,F2,B2,87,D2,30,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x92; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF2; @@ -6775,17 +8135,17 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xD2; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x30; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -// Bytes for AX-filter (0A): 1B,A5,DD,CA +/* Bytes for AX-filter (0A): 1B,A5,DD,CA */ j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xA5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -// Bytes for AR-filter (09): E2,27,10,D6 +/* Bytes for AR-filter (09): E2,27,10,D6 */ j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x27; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -// Bytes for TH-filter part 1 (00): 80,2D,38,8B,D0,00,00,98 +/* Bytes for TH-filter part 1 (00): 80,2D,38,8B,D0,00,00,98 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x2D; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x38; @@ -6794,7 +8154,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -// Bytes for TH-filter part 2 (01): 02,5A,53,F0,0B,5F,84,D4 +/* Bytes for TH-filter part 2 (01): 02,5A,53,F0,0B,5F,84,D4 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x53; @@ -6803,7 +8163,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5F; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x84; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xD4; -// Bytes for TH-filter part 3 (02): 00,88,6A,A4,8F,52,F5,32 +/* Bytes for TH-filter part 3 (02): 00,88,6A,A4,8F,52,F5,32 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x6A; @@ -6812,8 +8172,8 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xF5; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x32; -// ; idle - // Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 +/* ; idle */ + /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; @@ -6822,7 +8182,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -// Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 +/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; @@ -6831,12 +8191,12 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -// Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V less possible? +/* Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V less possible? */ j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; -// Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; @@ -6845,7 +8205,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -// Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; @@ -6854,53 +8214,53 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -// ;CR Registers - // Config. Reg. 0 (filters) (cr0):FF - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; -// Config. Reg. 1 (dialing) (cr1):05 +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -// Config. Reg. 2 (caller ID) (cr2):04 +/* Config. Reg. 2 (caller ID) (cr2):04 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -// Config. Reg. 3 (testloops) (cr3):00 ; +/* Config. Reg. 3 (testloops) (cr3):00 ; */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -// Config. Reg. 4 (analog gain) (cr4):01 - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - // Config. Reg. 5 (Version) (cr5):02 - // Config. Reg. 6 (Reserved) (cr6):00 - // Config. Reg. 7 (Reserved) (cr7):00 - // ;xr Registers - // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. - // Ext. Reg. 1 (Interrupt enable) (xr1):1C + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK - // Ext. Reg. 2 (Cadence Time Out) (xr2):7D + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -// Ext. Reg. 3 (DC Char) (xr3):36 ; +/* Ext. Reg. 3 (DC Char) (xr3):36 ; */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36; -// Ext. Reg. 4 (Cadence) (xr4):00 +/* Ext. Reg. 4 (Cadence) (xr4):00 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -// Ext. Reg. 5 (Ring timer) (xr5):22 +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -// Ext. Reg. 6 (Power State) (xr6):00 +/* Ext. Reg. 6 (Power State) (xr6):00 */ j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -// Ext. Reg. 7 (Vdd) (xr7):46 - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; // 0x46 ??? Should it be 0x00? - // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz - // 12,33,5A,C3 ; 770 Hz - // 13,3C,5B,32 ; 852 Hz - // 1D,1B,5C,CC ; 941 Hz +/* Ext. Reg. 7 (Vdd) (xr7):46 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; /* 0x46 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -// DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz - // EC,1D,52,22 ; 1336 Hz - // AA,AC,51,D2 ; 1477 Hz - // 9B,3B,51,25 ; 1633 Hz +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; @@ -6913,13 +8273,13 @@ int i; j->daa_country = DAA_FRANCE; - //----------------------------------------------- - // CAO + /*----------------------------------------------- */ + /* CAO */ for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } -// Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00 +/* Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x43; @@ -6928,7 +8288,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xAF; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -// Bytes for IM-filter part 2 (05): 67,CE,00,0C,22,33,E0,08 +/* Bytes for IM-filter part 2 (05): 67,CE,00,0C,22,33,E0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x67; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xCE; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; @@ -6937,7 +8297,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -// Bytes for FRX-filter (08): 07,9A,28,F6,23,4A,B0,08 +/* Bytes for FRX-filter (08): 07,9A,28,F6,23,4A,B0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9A; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x28; @@ -6946,7 +8306,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x4A; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xB0; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -// Bytes for FRR-filter (07): 03,8F,F9,2F,9E,FA,20,08 +/* Bytes for FRR-filter (07): 03,8F,F9,2F,9E,FA,20,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF9; @@ -6955,17 +8315,17 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xFA; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -// Bytes for AX-filter (0A): 16,B5,DD,CA +/* Bytes for AX-filter (0A): 16,B5,DD,CA */ j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -// Bytes for AR-filter (09): 52,C7,10,D6 +/* Bytes for AR-filter (09): 52,C7,10,D6 */ j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -// Bytes for TH-filter part 1 (00): 00,42,48,81,A6,80,00,98 +/* Bytes for TH-filter part 1 (00): 00,42,48,81,A6,80,00,98 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; @@ -6974,7 +8334,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -// Bytes for TH-filter part 2 (01): 02,AC,2A,30,78,AC,8A,2C +/* Bytes for TH-filter part 2 (01): 02,AC,2A,30,78,AC,8A,2C */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAC; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2A; @@ -6983,7 +8343,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAC; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x2C; -// Bytes for TH-filter part 3 (02): 00,88,DA,A5,22,BA,2C,45 +/* Bytes for TH-filter part 3 (02): 00,88,DA,A5,22,BA,2C,45 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA; @@ -6992,8 +8352,8 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2C; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x45; -// ; idle - // Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 +/* ; idle */ + /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; @@ -7002,7 +8362,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -// Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 +/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; @@ -7011,12 +8371,12 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -// Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V +/* Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V */ j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84; -// Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; @@ -7025,7 +8385,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -// Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; @@ -7034,53 +8394,53 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -// ;CR Registers - // Config. Reg. 0 (filters) (cr0):FF - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; -// Config. Reg. 1 (dialing) (cr1):05 +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -// Config. Reg. 2 (caller ID) (cr2):04 +/* Config. Reg. 2 (caller ID) (cr2):04 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -// Config. Reg. 3 (testloops) (cr3):00 ; +/* Config. Reg. 3 (testloops) (cr3):00 ; */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -// Config. Reg. 4 (analog gain) (cr4):01 - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - // Config. Reg. 5 (Version) (cr5):02 - // Config. Reg. 6 (Reserved) (cr6):00 - // Config. Reg. 7 (Reserved) (cr7):00 - // ;xr Registers - // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. - // Ext. Reg. 1 (Interrupt enable) (xr1):1C + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK - // Ext. Reg. 2 (Cadence Time Out) (xr2):7D + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -// Ext. Reg. 3 (DC Char) (xr3):36 ; +/* Ext. Reg. 3 (DC Char) (xr3):36 ; */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36; -// Ext. Reg. 4 (Cadence) (xr4):00 +/* Ext. Reg. 4 (Cadence) (xr4):00 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -// Ext. Reg. 5 (Ring timer) (xr5):22 +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -// Ext. Reg. 6 (Power State) (xr6):00 +/* Ext. Reg. 6 (Power State) (xr6):00 */ j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -// Ext. Reg. 7 (Vdd) (xr7):46 - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; // 0x46 ??? Should it be 0x00? - // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz - // 12,33,5A,C3 ; 770 Hz - // 13,3C,5B,32 ; 852 Hz - // 1D,1B,5C,CC ; 941 Hz +/* Ext. Reg. 7 (Vdd) (xr7):46 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; /* 0x46 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -// DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz - // EC,1D,52,22 ; 1336 Hz - // AA,AC,51,D2 ; 1477 Hz - // 9B,3B,51,25 ; 1633 Hz +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; @@ -7093,13 +8453,13 @@ int i; j->daa_country = DAA_GERMANY; - //----------------------------------------------- - // CAO + /*----------------------------------------------- */ + /* CAO */ for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } -// Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00 +/* Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xCE; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB; @@ -7108,7 +8468,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xB0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -// Bytes for IM-filter part 2 (05): 45,8F,00,0C,D2,3A,D0,08 +/* Bytes for IM-filter part 2 (05): 45,8F,00,0C,D2,3A,D0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x8F; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; @@ -7117,7 +8477,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -// Bytes for FRX-filter (08): 07,AA,E2,34,24,89,20,08 +/* Bytes for FRX-filter (08): 07,AA,E2,34,24,89,20,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xAA; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xE2; @@ -7126,7 +8486,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x89; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x20; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -// Bytes for FRR-filter (07): 02,87,FA,37,9A,CA,B0,08 +/* Bytes for FRR-filter (07): 02,87,FA,37,9A,CA,B0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xFA; @@ -7135,17 +8495,17 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -// Bytes for AX-filter (0A): 72,D5,DD,CA +/* Bytes for AX-filter (0A): 72,D5,DD,CA */ j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x72; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xD5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -// Bytes for AR-filter (09): 72,42,13,4B +/* Bytes for AR-filter (09): 72,42,13,4B */ j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x72; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x42; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x13; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x4B; -// Bytes for TH-filter part 1 (00): 80,52,48,81,AD,80,00,98 +/* Bytes for TH-filter part 1 (00): 80,52,48,81,AD,80,00,98 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; @@ -7154,7 +8514,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -// Bytes for TH-filter part 2 (01): 02,42,5A,20,E8,1A,81,27 +/* Bytes for TH-filter part 2 (01): 02,42,5A,20,E8,1A,81,27 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x42; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x5A; @@ -7163,7 +8523,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x1A; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x27; -// Bytes for TH-filter part 3 (02): 00,88,63,26,BD,4B,A3,C2 +/* Bytes for TH-filter part 3 (02): 00,88,63,26,BD,4B,A3,C2 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x63; @@ -7172,8 +8532,8 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x4B; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xC2; -// ; (10K, 0.68uF) - // Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 +/* ; (10K, 0.68uF) */ + /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x9B; @@ -7182,7 +8542,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -// Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 +/* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; @@ -7191,12 +8551,12 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -// Levelmetering Ringing (0D):B2,45,0F,8E +/* Levelmetering Ringing (0D):B2,45,0F,8E */ j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; -// Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; @@ -7205,7 +8565,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -// Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; @@ -7214,53 +8574,53 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -// ;CR Registers - // Config. Reg. 0 (filters) (cr0):FF ; all Filters enabled, CLK from ext. source - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; -// Config. Reg. 1 (dialing) (cr1):05 ; Manual Ring, Ring metering enabled +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF ; all Filters enabled, CLK from ext. source */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 ; Manual Ring, Ring metering enabled */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -// Config. Reg. 2 (caller ID) (cr2):04 ; Analog Gain 0dB, FSC internal +/* Config. Reg. 2 (caller ID) (cr2):04 ; Analog Gain 0dB, FSC internal */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -// Config. Reg. 3 (testloops) (cr3):00 ; SEL Bit==0, HP-enabled +/* Config. Reg. 3 (testloops) (cr3):00 ; SEL Bit==0, HP-enabled */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -// Config. Reg. 4 (analog gain) (cr4):01 - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - // Config. Reg. 5 (Version) (cr5):02 - // Config. Reg. 6 (Reserved) (cr6):00 - // Config. Reg. 7 (Reserved) (cr7):00 - // ;xr Registers - // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. - // Ext. Reg. 1 (Interrupt enable) (xr1):1C ; Ring, CID, VDDOK Interrupts enabled + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C ; Ring, CID, VDDOK Interrupts enabled */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK - // Ext. Reg. 2 (Cadence Time Out) (xr2):7D + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -// Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off==1, U0=3.5V, R=200Ohm +/* Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off==1, U0=3.5V, R=200Ohm */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x32; -// Ext. Reg. 4 (Cadence) (xr4):00 +/* Ext. Reg. 4 (Cadence) (xr4):00 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -// Ext. Reg. 5 (Ring timer) (xr5):22 +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -// Ext. Reg. 6 (Power State) (xr6):00 +/* Ext. Reg. 6 (Power State) (xr6):00 */ j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -// Ext. Reg. 7 (Vdd) (xr7):40 ; VDD=4.25 V - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; // 0x40 ??? Should it be 0x00? - // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz - // 12,33,5A,C3 ; 770 Hz - // 13,3C,5B,32 ; 852 Hz - // 1D,1B,5C,CC ; 941 Hz +/* Ext. Reg. 7 (Vdd) (xr7):40 ; VDD=4.25 V */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -// DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz - // EC,1D,52,22 ; 1336 Hz - // AA,AC,51,D2 ; 1477 Hz - // 9B,3B,51,25 ; 1633 Hz +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; @@ -7273,13 +8633,13 @@ int i; j->daa_country = DAA_AUSTRALIA; - //----------------------------------------------- - // CAO + /*----------------------------------------------- */ + /* CAO */ for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } -// Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00 +/* Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xAA; @@ -7288,7 +8648,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x82; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xD0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -// Bytes for IM-filter part 2 (05): 70,96,00,09,32,6B,C0,08 +/* Bytes for IM-filter part 2 (05): 70,96,00,09,32,6B,C0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x70; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x96; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; @@ -7297,7 +8657,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x6B; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xC0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -// Bytes for FRX-filter (08): 07,96,E2,34,32,9B,30,08 +/* Bytes for FRX-filter (08): 07,96,E2,34,32,9B,30,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x96; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xE2; @@ -7306,7 +8666,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x9B; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -// Bytes for FRR-filter (07): 0F,9A,E9,2F,22,CC,A0,08 +/* Bytes for FRR-filter (07): 0F,9A,E9,2F,22,CC,A0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x9A; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xE9; @@ -7315,17 +8675,17 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCC; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -// Bytes for AX-filter (0A): CB,45,DD,CA +/* Bytes for AX-filter (0A): CB,45,DD,CA */ j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0xCB; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -// Bytes for AR-filter (09): 1B,67,10,D6 +/* Bytes for AR-filter (09): 1B,67,10,D6 */ j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x67; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -// Bytes for TH-filter part 1 (00): 80,52,48,81,AF,80,00,98 +/* Bytes for TH-filter part 1 (00): 80,52,48,81,AF,80,00,98 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; @@ -7334,7 +8694,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -// Bytes for TH-filter part 2 (01): 02,DB,52,B0,38,01,82,AC +/* Bytes for TH-filter part 2 (01): 02,DB,52,B0,38,01,82,AC */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xDB; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x52; @@ -7343,7 +8703,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x01; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x82; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAC; -// Bytes for TH-filter part 3 (02): 00,88,4A,3E,2C,3B,24,46 +/* Bytes for TH-filter part 3 (02): 00,88,4A,3E,2C,3B,24,46 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x4A; @@ -7352,8 +8712,8 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x3B; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x24; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x46; -// ; idle - // Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 +/* ; idle */ + /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; @@ -7362,7 +8722,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -// Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 +/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; @@ -7371,12 +8731,12 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -// Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V +/* Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V */ j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84; -// Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; @@ -7385,7 +8745,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -// Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; @@ -7394,53 +8754,54 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -// ;CR Registers - // Config. Reg. 0 (filters) (cr0):FF +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; -// Config. Reg. 1 (dialing) (cr1):05 +/* Config. Reg. 1 (dialing) (cr1):05 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -// Config. Reg. 2 (caller ID) (cr2):04 +/* Config. Reg. 2 (caller ID) (cr2):04 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -// Config. Reg. 3 (testloops) (cr3):00 ; +/* Config. Reg. 3 (testloops) (cr3):00 ; */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -// Config. Reg. 4 (analog gain) (cr4):01 - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - // Config. Reg. 5 (Version) (cr5):02 - // Config. Reg. 6 (Reserved) (cr6):00 - // Config. Reg. 7 (Reserved) (cr7):00 - // ;xr Registers - // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. - // Ext. Reg. 1 (Interrupt enable) (xr1):1C + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK - // Ext. Reg. 2 (Cadence Time Out) (xr2):7D + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -// Ext. Reg. 3 (DC Char) (xr3):2B ; +/* Ext. Reg. 3 (DC Char) (xr3):2B ; */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x2B; -// Ext. Reg. 4 (Cadence) (xr4):00 +/* Ext. Reg. 4 (Cadence) (xr4):00 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -// Ext. Reg. 5 (Ring timer) (xr5):22 +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -// Ext. Reg. 6 (Power State) (xr6):00 +/* Ext. Reg. 6 (Power State) (xr6):00 */ j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -// Ext. Reg. 7 (Vdd) (xr7):40 - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; // 0x40 ??? Should it be 0x00? - // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz - // 12,33,5A,C3 ; 770 Hz - // 13,3C,5B,32 ; 852 Hz - // 1D,1B,5C,CC ; 941 Hz +/* Ext. Reg. 7 (Vdd) (xr7):40 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -// DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz - // EC,1D,52,22 ; 1336 Hz - // AA,AC,51,D2 ; 1477 Hz - // 9B,3B,51,25 ; 1633 Hz + + /* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; @@ -7452,13 +8813,13 @@ int i; j->daa_country = DAA_JAPAN; - //----------------------------------------------- - // CAO + /*----------------------------------------------- */ + /* CAO */ for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } -// Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00 +/* Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x06; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xBD; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2; @@ -7467,7 +8828,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xF9; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -// Bytes for IM-filter part 2 (05): 6F,F7,00,0E,34,33,E0,08 +/* Bytes for IM-filter part 2 (05): 6F,F7,00,0E,34,33,E0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x6F; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xF7; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; @@ -7476,7 +8837,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -// Bytes for FRX-filter (08): 02,8F,68,77,9C,58,F0,08 +/* Bytes for FRX-filter (08): 02,8F,68,77,9C,58,F0,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x68; @@ -7485,7 +8846,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x58; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xF0; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -// Bytes for FRR-filter (07): 03,8F,38,73,87,EA,20,08 +/* Bytes for FRR-filter (07): 03,8F,38,73,87,EA,20,08 */ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0x38; @@ -7494,17 +8855,17 @@ j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -// Bytes for AX-filter (0A): 51,C5,DD,CA +/* Bytes for AX-filter (0A): 51,C5,DD,CA */ j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x51; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xC5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -// Bytes for AR-filter (09): 25,A7,10,D6 +/* Bytes for AR-filter (09): 25,A7,10,D6 */ j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xA7; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -// Bytes for TH-filter part 1 (00): 00,42,48,81,AE,80,00,98 +/* Bytes for TH-filter part 1 (00): 00,42,48,81,AE,80,00,98 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; @@ -7513,7 +8874,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -// Bytes for TH-filter part 2 (01): 02,AB,2A,20,99,5B,89,28 +/* Bytes for TH-filter part 2 (01): 02,AB,2A,20,99,5B,89,28 */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAB; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2A; @@ -7522,7 +8883,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5B; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x89; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x28; -// Bytes for TH-filter part 3 (02): 00,88,DA,25,34,C5,4C,BA +/* Bytes for TH-filter part 3 (02): 00,88,DA,25,34,C5,4C,BA */ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA; @@ -7531,8 +8892,8 @@ j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xC5; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x4C; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBA; -// ; idle - // Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 +/* ; idle */ + /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; @@ -7541,7 +8902,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -// Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 +/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; @@ -7550,12 +8911,12 @@ j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -// Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V ????????? +/* Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V ????????? */ j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; -// Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; @@ -7564,7 +8925,7 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -// Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; @@ -7573,53 +8934,53 @@ j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -// ;CR Registers - // Config. Reg. 0 (filters) (cr0):FF - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; -// Config. Reg. 1 (dialing) (cr1):05 +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -// Config. Reg. 2 (caller ID) (cr2):04 +/* Config. Reg. 2 (caller ID) (cr2):04 */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -// Config. Reg. 3 (testloops) (cr3):00 ; +/* Config. Reg. 3 (testloops) (cr3):00 ; */ j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -// Config. Reg. 4 (analog gain) (cr4):01 - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - // Config. Reg. 5 (Version) (cr5):02 - // Config. Reg. 6 (Reserved) (cr6):00 - // Config. Reg. 7 (Reserved) (cr7):00 - // ;xr Registers - // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. - // Ext. Reg. 1 (Interrupt enable) (xr1):1C + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK - // Ext. Reg. 2 (Cadence Time Out) (xr2):7D + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -// Ext. Reg. 3 (DC Char) (xr3):22 ; +/* Ext. Reg. 3 (DC Char) (xr3):22 ; */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x22; -// Ext. Reg. 4 (Cadence) (xr4):00 +/* Ext. Reg. 4 (Cadence) (xr4):00 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -// Ext. Reg. 5 (Ring timer) (xr5):22 +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -// Ext. Reg. 6 (Power State) (xr6):00 +/* Ext. Reg. 6 (Power State) (xr6):00 */ j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -// Ext. Reg. 7 (Vdd) (xr7):40 - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; // 0x40 ??? Should it be 0x00? - // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz - // 12,33,5A,C3 ; 770 Hz - // 13,3C,5B,32 ; 852 Hz - // 1D,1B,5C,CC ; 941 Hz +/* Ext. Reg. 7 (Vdd) (xr7):40 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -// DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz - // EC,1D,52,22 ; 1336 Hz - // AA,AC,51,D2 ; 1477 Hz - // 9B,3B,51,25 ; 1633 Hz +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; @@ -7628,1538 +8989,1562 @@ static s16 tone_table[][19] = { - { // f20_50[] 11 - 32538, // A1 = 1.985962 - -32325, // A2 = -0.986511 - -343, // B2 = -0.010493 - 0, // B1 = 0 - 343, // B0 = 0.010493 - 32619, // A1 = 1.990906 - -32520, // A2 = -0.992462 - 19179, // B2 = 0.585327 - -19178, // B1 = -1.170593 - 19179, // B0 = 0.585327 - 32723, // A1 = 1.997314 - -32686, // A2 = -0.997528 - 9973, // B2 = 0.304352 - -9955, // B1 = -0.607605 - 9973, // B0 = 0.304352 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f133_200[] 12 - 32072, // A1 = 1.95752 - -31896, // A2 = -0.973419 - -435, // B2 = -0.013294 - 0, // B1 = 0 - 435, // B0 = 0.013294 - 32188, // A1 = 1.9646 - -32400, // A2 = -0.98877 - 15139, // B2 = 0.462036 - -14882, // B1 = -0.908356 - 15139, // B0 = 0.462036 - 32473, // A1 = 1.981995 - -32524, // A2 = -0.992584 - 23200, // B2 = 0.708008 - -23113, // B1 = -1.410706 - 23200, // B0 = 0.708008 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 300.txt 13 - 31769, // A1 = -1.939026 - -32584, // A2 = 0.994385 - -475, // B2 = -0.014522 - 0, // B1 = 0.000000 - 475, // B0 = 0.014522 - 31789, // A1 = -1.940247 - -32679, // A2 = 0.997284 - 17280, // B2 = 0.527344 - -16865, // B1 = -1.029358 - 17280, // B0 = 0.527344 - 31841, // A1 = -1.943481 - -32681, // A2 = 0.997345 - 543, // B2 = 0.016579 - -525, // B1 = -0.032097 - 543, // B0 = 0.016579 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f300_420[] 14 - 30750, // A1 = 1.876892 - -31212, // A2 = -0.952515 - -804, // B2 = -0.024541 - 0, // B1 = 0 - 804, // B0 = 0.024541 - 30686, // A1 = 1.872925 - -32145, // A2 = -0.980988 - 14747, // B2 = 0.450043 - -13703, // B1 = -0.836395 - 14747, // B0 = 0.450043 - 31651, // A1 = 1.931824 - -32321, // A2 = -0.986389 - 24425, // B2 = 0.745422 - -23914, // B1 = -1.459595 - 24427, // B0 = 0.745483 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 330.txt 15 - 31613, // A1 = -1.929565 - -32646, // A2 = 0.996277 - -185, // B2 = -0.005657 - 0, // B1 = 0.000000 - 185, // B0 = 0.005657 - 31620, // A1 = -1.929932 - -32713, // A2 = 0.998352 - 19253, // B2 = 0.587585 - -18566, // B1 = -1.133179 - 19253, // B0 = 0.587585 - 31674, // A1 = -1.933228 - -32715, // A2 = 0.998413 - 2575, // B2 = 0.078590 - -2495, // B1 = -0.152283 - 2575, // B0 = 0.078590 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f300_425[] 16 - 30741, // A1 = 1.876282 - -31475, // A2 = -0.960541 - -703, // B2 = -0.021484 - 0, // B1 = 0 - 703, // B0 = 0.021484 - 30688, // A1 = 1.873047 - -32248, // A2 = -0.984161 - 14542, // B2 = 0.443787 - -13523, // B1 = -0.825439 - 14542, // B0 = 0.443817 - 31494, // A1 = 1.922302 - -32366, // A2 = -0.987762 - 21577, // B2 = 0.658508 - -21013, // B1 = -1.282532 - 21577, // B0 = 0.658508 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f330_440[] 17 - 30627, // A1 = 1.869324 - -31338, // A2 = -0.95636 - -843, // B2 = -0.025749 - 0, // B1 = 0 - 843, // B0 = 0.025749 - 30550, // A1 = 1.864685 - -32221, // A2 = -0.983337 - 13594, // B2 = 0.414886 - -12589, // B1 = -0.768402 - 13594, // B0 = 0.414886 - 31488, // A1 = 1.921936 - -32358, // A2 = -0.987518 - 24684, // B2 = 0.753296 - -24029, // B1 = -1.466614 - 24684, // B0 = 0.753296 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 340.txt 18 - 31546, // A1 = -1.925476 - -32646, // A2 = 0.996277 - -445, // B2 = -0.013588 - 0, // B1 = 0.000000 - 445, // B0 = 0.013588 - 31551, // A1 = -1.925781 - -32713, // A2 = 0.998352 - 23884, // B2 = 0.728882 - -22979, // B1 = -1.402527 - 23884, // B0 = 0.728882 - 31606, // A1 = -1.929138 - -32715, // A2 = 0.998413 - 863, // B2 = 0.026367 - -835, // B1 = -0.050985 - 863, // B0 = 0.026367 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f350_400[] 19 - 31006, // A1 = 1.892517 - -32029, // A2 = -0.977448 - -461, // B2 = -0.014096 - 0, // B1 = 0 - 461, // B0 = 0.014096 - 30999, // A1 = 1.892029 - -32487, // A2 = -0.991455 - 11325, // B2 = 0.345612 - -10682, // B1 = -0.651978 - 11325, // B0 = 0.345612 - 31441, // A1 = 1.919067 - -32526, // A2 = -0.992615 - 24324, // B2 = 0.74231 - -23535, // B1 = -1.436523 - 24324, // B0 = 0.74231 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f350_440[] - 30634, // A1 = 1.869751 - -31533, // A2 = -0.962341 - -680, // B2 = -0.020782 - 0, // B1 = 0 - 680, // B0 = 0.020782 - 30571, // A1 = 1.865906 - -32277, // A2 = -0.985016 - 12894, // B2 = 0.393524 - -11945, // B1 = -0.729065 - 12894, // B0 = 0.393524 - 31367, // A1 = 1.91449 - -32379, // A2 = -0.988129 - 23820, // B2 = 0.726929 - -23104, // B1 = -1.410217 - 23820, // B0 = 0.726929 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f350_450[] - 30552, // A1 = 1.864807 - -31434, // A2 = -0.95929 - -690, // B2 = -0.021066 - 0, // B1 = 0 - 690, // B0 = 0.021066 - 30472, // A1 = 1.859924 - -32248, // A2 = -0.984161 - 13385, // B2 = 0.408478 - -12357, // B1 = -0.754242 - 13385, // B0 = 0.408478 - 31358, // A1 = 1.914001 - -32366, // A2 = -0.987732 - 26488, // B2 = 0.80835 - -25692, // B1 = -1.568176 - 26490, // B0 = 0.808411 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 360.txt - 31397, // A1 = -1.916321 - -32623, // A2 = 0.995605 - -117, // B2 = -0.003598 - 0, // B1 = 0.000000 - 117, // B0 = 0.003598 - 31403, // A1 = -1.916687 - -32700, // A2 = 0.997925 - 3388, // B2 = 0.103401 - -3240, // B1 = -0.197784 - 3388, // B0 = 0.103401 - 31463, // A1 = -1.920410 - -32702, // A2 = 0.997986 - 13346, // B2 = 0.407288 - -12863, // B1 = -0.785126 - 13346, // B0 = 0.407288 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f380_420[] - 30831, // A1 = 1.881775 - -32064, // A2 = -0.978546 - -367, // B2 = -0.01122 - 0, // B1 = 0 - 367, // B0 = 0.01122 - 30813, // A1 = 1.880737 - -32456, // A2 = -0.990509 - 11068, // B2 = 0.337769 - -10338, // B1 = -0.631042 - 11068, // B0 = 0.337769 - 31214, // A1 = 1.905212 - -32491, // A2 = -0.991577 - 16374, // B2 = 0.499695 - -15781, // B1 = -0.963196 - 16374, // B0 = 0.499695 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 392.txt - 31152, // A1 = -1.901428 - -32613, // A2 = 0.995300 - -314, // B2 = -0.009605 - 0, // B1 = 0.000000 - 314, // B0 = 0.009605 - 31156, // A1 = -1.901672 - -32694, // A2 = 0.997742 - 28847, // B2 = 0.880371 - -2734, // B1 = -0.166901 - 28847, // B0 = 0.880371 - 31225, // A1 = -1.905823 - -32696, // A2 = 0.997803 - 462, // B2 = 0.014108 - -442, // B1 = -0.027019 - 462, // B0 = 0.014108 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f400_425[] - 30836, // A1 = 1.882141 - -32296, // A2 = -0.985596 - -324, // B2 = -0.009903 - 0, // B1 = 0 - 324, // B0 = 0.009903 - 30825, // A1 = 1.881409 - -32570, // A2 = -0.993958 - 16847, // B2 = 0.51416 - -15792, // B1 = -0.963898 - 16847, // B0 = 0.51416 - 31106, // A1 = 1.89856 - -32584, // A2 = -0.994415 - 9579, // B2 = 0.292328 - -9164, // B1 = -0.559357 - 9579, // B0 = 0.292328 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f400_440[] - 30702, // A1 = 1.873962 - -32134, // A2 = -0.980682 - -517, // B2 = -0.015793 - 0, // B1 = 0 - 517, // B0 = 0.015793 - 30676, // A1 = 1.872375 - -32520, // A2 = -0.992462 - 8144, // B2 = 0.24855 - -7596, // B1 = -0.463684 - 8144, // B0 = 0.24855 - 31084, // A1 = 1.897217 - -32547, // A2 = -0.993256 - 22713, // B2 = 0.693176 - -21734, // B1 = -1.326599 - 22713, // B0 = 0.693176 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f400_450[] - 30613, // A1 = 1.86853 - -32031, // A2 = -0.977509 - -618, // B2 = -0.018866 - 0, // B1 = 0 - 618, // B0 = 0.018866 - 30577, // A1 = 1.866272 - -32491, // A2 = -0.991577 - 9612, // B2 = 0.293335 - -8935, // B1 = -0.54541 - 9612, // B0 = 0.293335 - 31071, // A1 = 1.896484 - -32524, // A2 = -0.992584 - 21596, // B2 = 0.659058 - -20667, // B1 = -1.261414 - 21596, // B0 = 0.659058 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 420.txt - 30914, // A1 = -1.886841 - -32584, // A2 = 0.994385 - -426, // B2 = -0.013020 - 0, // B1 = 0.000000 - 426, // B0 = 0.013020 - 30914, // A1 = -1.886841 - -32679, // A2 = 0.997314 - 17520, // B2 = 0.534668 - -16471, // B1 = -1.005310 - 17520, // B0 = 0.534668 - 31004, // A1 = -1.892334 - -32683, // A2 = 0.997406 - 819, // B2 = 0.025023 - -780, // B1 = -0.047619 - 819, // B0 = 0.025023 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 425.txt - 30881, // A1 = -1.884827 - -32603, // A2 = 0.994965 - -496, // B2 = -0.015144 - 0, // B1 = 0.000000 - 496, // B0 = 0.015144 - 30880, // A1 = -1.884766 - -32692, // A2 = 0.997711 - 24767, // B2 = 0.755859 - -23290, // B1 = -1.421509 - 24767, // B0 = 0.755859 - 30967, // A1 = -1.890076 - -32694, // A2 = 0.997772 - 728, // B2 = 0.022232 - -691, // B1 = -0.042194 - 728, // B0 = 0.022232 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f425_450[] - 30646, // A1 = 1.870544 - -32327, // A2 = -0.986572 - -287, // B2 = -0.008769 - 0, // B1 = 0 - 287, // B0 = 0.008769 - 30627, // A1 = 1.869324 - -32607, // A2 = -0.995087 - 13269, // B2 = 0.404968 - -12376, // B1 = -0.755432 - 13269, // B0 = 0.404968 - 30924, // A1 = 1.887512 - -32619, // A2 = -0.995453 - 19950, // B2 = 0.608826 - -18940, // B1 = -1.156006 - 19950, // B0 = 0.608826 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f425_475[] - 30396, // A1 = 1.855225 - -32014, // A2 = -0.97699 - -395, // B2 = -0.012055 - 0, // B1 = 0 - 395, // B0 = 0.012055 - 30343, // A1 = 1.85199 - -32482, // A2 = -0.991302 - 17823, // B2 = 0.543945 - -16431, // B1 = -1.002869 - 17823, // B0 = 0.543945 - 30872, // A1 = 1.884338 - -32516, // A2 = -0.99231 - 18124, // B2 = 0.553101 - -17246, // B1 = -1.052673 - 18124, // B0 = 0.553101 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 435.txt - 30796, // A1 = -1.879639 - -32603, // A2 = 0.994965 - -254, // B2 = -0.007762 - 0, // B1 = 0.000000 - 254, // B0 = 0.007762 - 30793, // A1 = -1.879456 - -32692, // A2 = 0.997711 - 18934, // B2 = 0.577820 - -17751, // B1 = -1.083496 - 18934, // B0 = 0.577820 - 30882, // A1 = -1.884888 - -32694, // A2 = 0.997772 - 1858, // B2 = 0.056713 - -1758, // B1 = -0.107357 - 1858, // B0 = 0.056713 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f440_450[] - 30641, // A1 = 1.870239 - -32458, // A2 = -0.99057 - -155, // B2 = -0.004735 - 0, // B1 = 0 - 155, // B0 = 0.004735 - 30631, // A1 = 1.869568 - -32630, // A2 = -0.995789 - 11453, // B2 = 0.349548 - -10666, // B1 = -0.651001 - 11453, // B0 = 0.349548 - 30810, // A1 = 1.880554 - -32634, // A2 = -0.995941 - 12237, // B2 = 0.373474 - -11588, // B1 = -0.707336 - 12237, // B0 = 0.373474 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f440_480[] - 30367, // A1 = 1.853455 - -32147, // A2 = -0.981079 - -495, // B2 = -0.015113 - 0, // B1 = 0 - 495, // B0 = 0.015113 - 30322, // A1 = 1.850769 - -32543, // A2 = -0.993134 - 10031, // B2 = 0.306152 - -9252, // B1 = -0.564728 - 10031, // B0 = 0.306152 - 30770, // A1 = 1.878052 - -32563, // A2 = -0.993774 - 22674, // B2 = 0.691956 - -21465, // B1 = -1.31012 - 22674, // B0 = 0.691956 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 445.txt - 30709, // A1 = -1.874329 - -32603, // A2 = 0.994965 - -83, // B2 = -0.002545 - 0, // B1 = 0.000000 - 83, // B0 = 0.002545 - 30704, // A1 = -1.874084 - -32692, // A2 = 0.997711 - 10641, // B2 = 0.324738 - -9947, // B1 = -0.607147 - 10641, // B0 = 0.324738 - 30796, // A1 = -1.879639 - -32694, // A2 = 0.997772 - 10079, // B2 = 0.307587 - 9513, // B1 = 0.580688 - 10079, // B0 = 0.307587 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 450.txt - 30664, // A1 = -1.871643 - -32603, // A2 = 0.994965 - -164, // B2 = -0.005029 - 0, // B1 = 0.000000 - 164, // B0 = 0.005029 - 30661, // A1 = -1.871399 - -32692, // A2 = 0.997711 - 15294, // B2 = 0.466736 - -14275, // B1 = -0.871307 - 15294, // B0 = 0.466736 - 30751, // A1 = -1.876953 - -32694, // A2 = 0.997772 - 3548, // B2 = 0.108284 - -3344, // B1 = -0.204155 - 3548, // B0 = 0.108284 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 452.txt - 30653, // A1 = -1.870911 - -32615, // A2 = 0.995361 - -209, // B2 = -0.006382 - 0, // B1 = 0.000000 - 209, // B0 = 0.006382 - 30647, // A1 = -1.870605 - -32702, // A2 = 0.997986 - 18971, // B2 = 0.578979 - -17716, // B1 = -1.081299 - 18971, // B0 = 0.578979 - 30738, // A1 = -1.876099 - -32702, // A2 = 0.998016 - 2967, // B2 = 0.090561 - -2793, // B1 = -0.170502 - 2967, // B0 = 0.090561 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 475.txt - 30437, // A1 = -1.857727 - -32603, // A2 = 0.994965 - -264, // B2 = -0.008062 - 0, // B1 = 0.000000 - 264, // B0 = 0.008062 - 30430, // A1 = -1.857300 - -32692, // A2 = 0.997711 - 21681, // B2 = 0.661682 - -20082, // B1 = -1.225708 - 21681, // B0 = 0.661682 - 30526, // A1 = -1.863220 - -32694, // A2 = 0.997742 - 1559, // B2 = 0.047600 - -1459, // B1 = -0.089096 - 1559, // B0 = 0.047600 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f480_620[] - 28975, // A1 = 1.768494 - -30955, // A2 = -0.944672 - -1026, // B2 = -0.03133 - 0, // B1 = 0 - 1026, // B0 = 0.03133 - 28613, // A1 = 1.746399 - -32089, // A2 = -0.979309 - 14214, // B2 = 0.433807 - -12202, // B1 = -0.744812 - 14214, // B0 = 0.433807 - 30243, // A1 = 1.845947 - -32238, // A2 = -0.983856 - 24825, // B2 = 0.757629 - -23402, // B1 = -1.428345 - 24825, // B0 = 0.757629 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 494.txt - 30257, // A1 = -1.846741 - -32605, // A2 = 0.995056 - -249, // B2 = -0.007625 - 0, // B1 = 0.000000 - 249, // B0 = 0.007625 - 30247, // A1 = -1.846191 - -32694, // A2 = 0.997772 - 18088, // B2 = 0.552002 - -16652, // B1 = -1.016418 - 18088, // B0 = 0.552002 - 30348, // A1 = -1.852295 - -32696, // A2 = 0.997803 - 2099, // B2 = 0.064064 - -1953, // B1 = -0.119202 - 2099, // B0 = 0.064064 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 500.txt - 30202, // A1 = -1.843431 - -32624, // A2 = 0.995622 - -413, // B2 = -0.012622 - 0, // B1 = 0.000000 - 413, // B0 = 0.012622 - 30191, // A1 = -1.842721 - -32714, // A2 = 0.998364 - 25954, // B2 = 0.792057 - -23890, // B1 = -1.458131 - 25954, // B0 = 0.792057 - 30296, // A1 = -1.849172 - -32715, // A2 = 0.998397 - 2007, // B2 = 0.061264 - -1860, // B1 = -0.113568 - 2007, // B0 = 0.061264 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 520.txt - 30001, // A1 = -1.831116 - -32613, // A2 = 0.995270 - -155, // B2 = -0.004750 - 0, // B1 = 0.000000 - 155, // B0 = 0.004750 - 29985, // A1 = -1.830200 - -32710, // A2 = 0.998260 - 6584, // B2 = 0.200928 - -6018, // B1 = -0.367355 - 6584, // B0 = 0.200928 - 30105, // A1 = -1.837524 - -32712, // A2 = 0.998291 - 23812, // B2 = 0.726685 - -21936, // B1 = -1.338928 - 23812, // B0 = 0.726685 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 523.txt - 29964, // A1 = -1.828918 - -32601, // A2 = 0.994904 - -101, // B2 = -0.003110 - 0, // B1 = 0.000000 - 101, // B0 = 0.003110 - 29949, // A1 = -1.827942 - -32700, // A2 = 0.997925 - 11041, // B2 = 0.336975 - -10075, // B1 = -0.614960 - 11041, // B0 = 0.336975 - 30070, // A1 = -1.835388 - -32702, // A2 = 0.997986 - 16762, // B2 = 0.511536 - -15437, // B1 = -0.942230 - 16762, // B0 = 0.511536 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 525.txt - 29936, // A1 = -1.827209 - -32584, // A2 = 0.994415 - -91, // B2 = -0.002806 - 0, // B1 = 0.000000 - 91, // B0 = 0.002806 - 29921, // A1 = -1.826233 - -32688, // A2 = 0.997559 - 11449, // B2 = 0.349396 - -10426, // B1 = -0.636383 - 11449, // B0 = 0.349396 - 30045, // A1 = -1.833862 - -32688, // A2 = 0.997589 - 13055, // B2 = 0.398407 - -12028, // B1 = -0.734161 - 13055, // B0 = 0.398407 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f540_660[] - 28499, // A1 = 1.739441 - -31129, // A2 = -0.949982 - -849, // B2 = -0.025922 - 0, // B1 = 0 - 849, // B0 = 0.025922 - 28128, // A1 = 1.716797 - -32130, // A2 = -0.98056 - 14556, // B2 = 0.444214 - -12251, // B1 = -0.747772 - 14556, // B0 = 0.444244 - 29667, // A1 = 1.81073 - -32244, // A2 = -0.984039 - 23038, // B2 = 0.703064 - -21358, // B1 = -1.303589 - 23040, // B0 = 0.703125 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 587.txt - 29271, // A1 = -1.786560 - -32599, // A2 = 0.994873 - -490, // B2 = -0.014957 - 0, // B1 = 0.000000 - 490, // B0 = 0.014957 - 29246, // A1 = -1.785095 - -32700, // A2 = 0.997925 - 28961, // B2 = 0.883850 - -25796, // B1 = -1.574463 - 28961, // B0 = 0.883850 - 29383, // A1 = -1.793396 - -32700, // A2 = 0.997955 - 1299, // B2 = 0.039650 - -1169, // B1 = -0.071396 - 1299, // B0 = 0.039650 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 590.txt - 29230, // A1 = -1.784058 - -32584, // A2 = 0.994415 - -418, // B2 = -0.012757 - 0, // B1 = 0.000000 - 418, // B0 = 0.012757 - 29206, // A1 = -1.782593 - -32688, // A2 = 0.997559 - 36556, // B2 = 1.115601 - -32478, // B1 = -1.982300 - 36556, // B0 = 1.115601 - 29345, // A1 = -1.791077 - -32688, // A2 = 0.997589 - 897, // B2 = 0.027397 - -808, // B1 = -0.049334 - 897, // B0 = 0.027397 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 600.txt - 29116, // A1 = -1.777100 - -32603, // A2 = 0.994965 - -165, // B2 = -0.005039 - 0, // B1 = 0.000000 - 165, // B0 = 0.005039 - 29089, // A1 = -1.775452 - -32708, // A2 = 0.998199 - 6963, // B2 = 0.212494 - -6172, // B1 = -0.376770 - 6963, // B0 = 0.212494 - 29237, // A1 = -1.784485 - -32710, // A2 = 0.998230 - 24197, // B2 = 0.738464 - -21657, // B1 = -1.321899 - 24197, // B0 = 0.738464 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 660.txt - 28376, // A1 = -1.731934 - -32567, // A2 = 0.993896 - -363, // B2 = -0.011102 - 0, // B1 = 0.000000 - 363, // B0 = 0.011102 - 28337, // A1 = -1.729614 - -32683, // A2 = 0.997434 - 21766, // B2 = 0.664246 - -18761, // B1 = -1.145081 - 21766, // B0 = 0.664246 - 28513, // A1 = -1.740356 - -32686, // A2 = 0.997498 - 2509, // B2 = 0.076584 - -2196, // B1 = -0.134041 - 2509, // B0 = 0.076584 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 700.txt - 27844, // A1 = -1.699463 - -32563, // A2 = 0.993744 - -366, // B2 = -0.011187 - 0, // B1 = 0.000000 - 366, // B0 = 0.011187 - 27797, // A1 = -1.696655 - -32686, // A2 = 0.997498 - 22748, // B2 = 0.694214 - -19235, // B1 = -1.174072 - 22748, // B0 = 0.694214 - 27995, // A1 = -1.708740 - -32688, // A2 = 0.997559 - 2964, // B2 = 0.090477 - -2546, // B1 = -0.155449 - 2964, // B0 = 0.090477 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 740.txt - 27297, // A1 = -1.666077 - -32551, // A2 = 0.993408 - -345, // B2 = -0.010540 - 0, // B1 = 0.000000 - 345, // B0 = 0.010540 - 27240, // A1 = -1.662598 - -32683, // A2 = 0.997406 - 22560, // B2 = 0.688477 - -18688, // B1 = -1.140625 - 22560, // B0 = 0.688477 - 27461, // A1 = -1.676147 - -32684, // A2 = 0.997467 - 3541, // B2 = 0.108086 - -2985, // B1 = -0.182220 - 3541, // B0 = 0.108086 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 750.txt - 27155, // A1 = -1.657410 - -32551, // A2 = 0.993408 - -462, // B2 = -0.014117 - 0, // B1 = 0.000000 - 462, // B0 = 0.014117 - 27097, // A1 = -1.653870 - -32683, // A2 = 0.997406 - 32495, // B2 = 0.991699 - -26776, // B1 = -1.634338 - 32495, // B0 = 0.991699 - 27321, // A1 = -1.667542 - -32684, // A2 = 0.997467 - 1835, // B2 = 0.056007 - -1539, // B1 = -0.093948 - 1835, // B0 = 0.056007 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f750_1450[] - 19298, // A1 = 1.177917 - -24471, // A2 = -0.746796 - -4152, // B2 = -0.126709 - 0, // B1 = 0 - 4152, // B0 = 0.126709 - 12902, // A1 = 0.787476 - -29091, // A2 = -0.887817 - 12491, // B2 = 0.38121 - -1794, // B1 = -0.109528 - 12494, // B0 = 0.381317 - 26291, // A1 = 1.604736 - -30470, // A2 = -0.929901 - 28859, // B2 = 0.880737 - -26084, // B1 = -1.592102 - 28861, // B0 = 0.880798 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 770.txt - 26867, // A1 = -1.639832 - -32551, // A2 = 0.993408 - -123, // B2 = -0.003755 - 0, // B1 = 0.000000 - 123, // B0 = 0.003755 - 26805, // A1 = -1.636108 - -32683, // A2 = 0.997406 - 17297, // B2 = 0.527863 - -14096, // B1 = -0.860382 - 17297, // B0 = 0.527863 - 27034, // A1 = -1.650085 - -32684, // A2 = 0.997467 - 12958, // B2 = 0.395477 - -10756, // B1 = -0.656525 - 12958, // B0 = 0.395477 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 800.txt - 26413, // A1 = -1.612122 - -32547, // A2 = 0.993286 - -223, // B2 = -0.006825 - 0, // B1 = 0.000000 - 223, // B0 = 0.006825 - 26342, // A1 = -1.607849 - -32686, // A2 = 0.997498 - 6391, // B2 = 0.195053 - -5120, // B1 = -0.312531 - 6391, // B0 = 0.195053 - 26593, // A1 = -1.623108 - -32688, // A2 = 0.997559 - 23681, // B2 = 0.722717 - -19328, // B1 = -1.179688 - 23681, // B0 = 0.722717 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 816.txt - 26168, // A1 = -1.597209 - -32528, // A2 = 0.992706 - -235, // B2 = -0.007182 - 0, // B1 = 0.000000 - 235, // B0 = 0.007182 - 26092, // A1 = -1.592590 - -32675, // A2 = 0.997192 - 20823, // B2 = 0.635498 - -16510, // B1 = -1.007751 - 20823, // B0 = 0.635498 - 26363, // A1 = -1.609070 - -32677, // A2 = 0.997253 - 6739, // B2 = 0.205688 - -5459, // B1 = -0.333206 - 6739, // B0 = 0.205688 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 850.txt - 25641, // A1 = -1.565063 - -32536, // A2 = 0.992950 - -121, // B2 = -0.003707 - 0, // B1 = 0.000000 - 121, // B0 = 0.003707 - 25560, // A1 = -1.560059 - -32684, // A2 = 0.997437 - 18341, // B2 = 0.559753 - -14252, // B1 = -0.869904 - 18341, // B0 = 0.559753 - 25837, // A1 = -1.577026 - -32684, // A2 = 0.997467 - 16679, // B2 = 0.509003 - -13232, // B1 = -0.807648 - 16679, // B0 = 0.509003 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f857_1645[] - 16415, // A1 = 1.001953 - -23669, // A2 = -0.722321 - -4549, // B2 = -0.138847 - 0, // B1 = 0 - 4549, // B0 = 0.138847 - 8456, // A1 = 0.516174 - -28996, // A2 = -0.884918 - 13753, // B2 = 0.419724 - -12, // B1 = -0.000763 - 13757, // B0 = 0.419846 - 24632, // A1 = 1.503418 - -30271, // A2 = -0.923828 - 29070, // B2 = 0.887146 - -25265, // B1 = -1.542114 - 29073, // B0 = 0.887268 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 900.txt - 24806, // A1 = -1.514099 - -32501, // A2 = 0.991852 - -326, // B2 = -0.009969 - 0, // B1 = 0.000000 - 326, // B0 = 0.009969 - 24709, // A1 = -1.508118 - -32659, // A2 = 0.996674 - 20277, // B2 = 0.618835 - -15182, // B1 = -0.926636 - 20277, // B0 = 0.618835 - 25022, // A1 = -1.527222 - -32661, // A2 = 0.996735 - 4320, // B2 = 0.131836 - -3331, // B1 = -0.203339 - 4320, // B0 = 0.131836 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f900_1300[] - 19776, // A1 = 1.207092 - -27437, // A2 = -0.837341 - -2666, // B2 = -0.081371 - 0, // B1 = 0 - 2666, // B0 = 0.081371 - 16302, // A1 = 0.995026 - -30354, // A2 = -0.926361 - 10389, // B2 = 0.317062 - -3327, // B1 = -0.203064 - 10389, // B0 = 0.317062 - 24299, // A1 = 1.483154 - -30930, // A2 = -0.943909 - 25016, // B2 = 0.763428 - -21171, // B1 = -1.292236 - 25016, // B0 = 0.763428 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f935_1215[] - 20554, // A1 = 1.254517 - -28764, // A2 = -0.877838 - -2048, // B2 = -0.062515 - 0, // B1 = 0 - 2048, // B0 = 0.062515 - 18209, // A1 = 1.11145 - -30951, // A2 = -0.94458 - 9390, // B2 = 0.286575 - -3955, // B1 = -0.241455 - 9390, // B0 = 0.286575 - 23902, // A1 = 1.458923 - -31286, // A2 = -0.954803 - 23252, // B2 = 0.709595 - -19132, // B1 = -1.167725 - 23252, // B0 = 0.709595 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f941_1477[] - 17543, // A1 = 1.07074 - -26220, // A2 = -0.800201 - -3298, // B2 = -0.100647 - 0, // B1 = 0 - 3298, // B0 = 0.100647 - 12423, // A1 = 0.75827 - -30036, // A2 = -0.916626 - 12651, // B2 = 0.386078 - -2444, // B1 = -0.14917 - 12653, // B0 = 0.386154 - 23518, // A1 = 1.435425 - -30745, // A2 = -0.938293 - 27282, // B2 = 0.832581 - -22529, // B1 = -1.375122 - 27286, // B0 = 0.832703 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 942.txt - 24104, // A1 = -1.471252 - -32507, // A2 = 0.992065 - -351, // B2 = -0.010722 - 0, // B1 = 0.000000 - 351, // B0 = 0.010722 - 23996, // A1 = -1.464600 - -32671, // A2 = 0.997040 - 22848, // B2 = 0.697266 - -16639, // B1 = -1.015564 - 22848, // B0 = 0.697266 - 24332, // A1 = -1.485168 - -32673, // A2 = 0.997101 - 4906, // B2 = 0.149727 - -3672, // B1 = -0.224174 - 4906, // B0 = 0.149727 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 950.txt - 23967, // A1 = -1.462830 - -32507, // A2 = 0.992065 - -518, // B2 = -0.015821 - 0, // B1 = 0.000000 - 518, // B0 = 0.015821 - 23856, // A1 = -1.456055 - -32671, // A2 = 0.997040 - 26287, // B2 = 0.802246 - -19031, // B1 = -1.161560 - 26287, // B0 = 0.802246 - 24195, // A1 = -1.476746 - -32673, // A2 = 0.997101 - 2890, // B2 = 0.088196 - -2151, // B1 = -0.131317 - 2890, // B0 = 0.088196 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f950_1400[] - 18294, // A1 = 1.116638 - -26962, // A2 = -0.822845 - -2914, // B2 = -0.088936 - 0, // B1 = 0 - 2914, // B0 = 0.088936 - 14119, // A1 = 0.861786 - -30227, // A2 = -0.922455 - 11466, // B2 = 0.349945 - -2833, // B1 = -0.172943 - 11466, // B0 = 0.349945 - 23431, // A1 = 1.430115 - -30828, // A2 = -0.940796 - 25331, // B2 = 0.773071 - -20911, // B1 = -1.276367 - 25331, // B0 = 0.773071 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 975.txt - 23521, // A1 = -1.435608 - -32489, // A2 = 0.991516 - -193, // B2 = -0.005915 - 0, // B1 = 0.000000 - 193, // B0 = 0.005915 - 23404, // A1 = -1.428467 - -32655, // A2 = 0.996582 - 17740, // B2 = 0.541412 - -12567, // B1 = -0.767029 - 17740, // B0 = 0.541412 - 23753, // A1 = -1.449829 - -32657, // A2 = 0.996613 - 9090, // B2 = 0.277405 - -6662, // B1 = -0.406647 - 9090, // B0 = 0.277405 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1000.txt - 23071, // A1 = -1.408203 - -32489, // A2 = 0.991516 - -293, // B2 = -0.008965 - 0, // B1 = 0.000000 - 293, // B0 = 0.008965 - 22951, // A1 = -1.400818 - -32655, // A2 = 0.996582 - 5689, // B2 = 0.173645 - -3951, // B1 = -0.241150 - 5689, // B0 = 0.173645 - 23307, // A1 = -1.422607 - -32657, // A2 = 0.996613 - 18692, // B2 = 0.570435 - -13447, // B1 = -0.820770 - 18692, // B0 = 0.570435 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1020.txt - 22701, // A1 = -1.385620 - -32474, // A2 = 0.991058 - -292, // B2 = -0.008933 - 0, //163840 , // B1 = 10.000000 - 292, // B0 = 0.008933 - 22564, // A1 = -1.377258 - -32655, // A2 = 0.996552 - 20756, // B2 = 0.633423 - -14176, // B1 = -0.865295 - 20756, // B0 = 0.633423 - 22960, // A1 = -1.401428 - -32657, // A2 = 0.996613 - 6520, // B2 = 0.198990 - -4619, // B1 = -0.281937 - 6520, // B0 = 0.198990 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1050.txt - 22142, // A1 = -1.351501 - -32474, // A2 = 0.991058 - -147, // B2 = -0.004493 - 0, // B1 = 0.000000 - 147, // B0 = 0.004493 - 22000, // A1 = -1.342834 - -32655, // A2 = 0.996552 - 15379, // B2 = 0.469360 - -10237, // B1 = -0.624847 - 15379, // B0 = 0.469360 - 22406, // A1 = -1.367554 - -32657, // A2 = 0.996613 - 17491, // B2 = 0.533783 - -12096, // B1 = -0.738312 - 17491, // B0 = 0.533783 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f1100_1750[] - 12973, // A1 = 0.79184 - -24916, // A2 = -0.760376 - 6655, // B2 = 0.203102 - 367, // B1 = 0.0224 - 6657, // B0 = 0.203171 - 5915, // A1 = 0.361053 - -29560, // A2 = -0.90213 - -7777, // B2 = -0.23735 - 0, // B1 = 0 - 7777, // B0 = 0.23735 - 20510, // A1 = 1.251892 - -30260, // A2 = -0.923462 - 26662, // B2 = 0.81366 - -20573, // B1 = -1.255737 - 26668, // B0 = 0.813843 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1140.txt - 20392, // A1 = -1.244629 - -32460, // A2 = 0.990601 - -270, // B2 = -0.008240 - 0, // B1 = 0.000000 - 270, // B0 = 0.008240 - 20218, // A1 = -1.234009 - -32655, // A2 = 0.996582 - 21337, // B2 = 0.651154 - -13044, // B1 = -0.796143 - 21337, // B0 = 0.651154 - 20684, // A1 = -1.262512 - -32657, // A2 = 0.996643 - 8572, // B2 = 0.261612 - -5476, // B1 = -0.334244 - 8572, // B0 = 0.261612 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1200.txt - 19159, // A1 = -1.169373 - -32456, // A2 = 0.990509 - -335, // B2 = -0.010252 - 0, // B1 = 0.000000 - 335, // B0 = 0.010252 - 18966, // A1 = -1.157593 - -32661, // A2 = 0.996735 - 6802, // B2 = 0.207588 - -3900, // B1 = -0.238098 - 6802, // B0 = 0.207588 - 19467, // A1 = -1.188232 - -32661, // A2 = 0.996765 - 25035, // B2 = 0.764008 - -15049, // B1 = -0.918579 - 25035, // B0 = 0.764008 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1209.txt - 18976, // A1 = -1.158264 - -32439, // A2 = 0.989990 - -183, // B2 = -0.005588 - 0, // B1 = 0.000000 - 183, // B0 = 0.005588 - 18774, // A1 = -1.145874 - -32650, // A2 = 0.996429 - 15468, // B2 = 0.472076 - -8768, // B1 = -0.535217 - 15468, // B0 = 0.472076 - 19300, // A1 = -1.177979 - -32652, // A2 = 0.996490 - 19840, // B2 = 0.605499 - -11842, // B1 = -0.722809 - 19840, // B0 = 0.605499 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1330.txt - 16357, // A1 = -0.998413 - -32368, // A2 = 0.987793 - -217, // B2 = -0.006652 - 0, // B1 = 0.000000 - 217, // B0 = 0.006652 - 16107, // A1 = -0.983126 - -32601, // A2 = 0.994904 - 11602, // B2 = 0.354065 - -5555, // B1 = -0.339111 - 11602, // B0 = 0.354065 - 16722, // A1 = -1.020630 - -32603, // A2 = 0.994965 - 15574, // B2 = 0.475311 - -8176, // B1 = -0.499069 - 15574, // B0 = 0.475311 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1336.txt - 16234, // A1 = -0.990875 - 32404, // A2 = -0.988922 - -193, // B2 = -0.005908 - 0, // B1 = 0.000000 - 193, // B0 = 0.005908 - 15986, // A1 = -0.975769 - -32632, // A2 = 0.995880 - 18051, // B2 = 0.550903 - -8658, // B1 = -0.528473 - 18051, // B0 = 0.550903 - 16591, // A1 = -1.012695 - -32634, // A2 = 0.995941 - 15736, // B2 = 0.480240 - -8125, // B1 = -0.495926 - 15736, // B0 = 0.480240 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1366.txt - 15564, // A1 = -0.949982 - -32404, // A2 = 0.988922 - -269, // B2 = -0.008216 - 0, // B1 = 0.000000 - 269, // B0 = 0.008216 - 15310, // A1 = -0.934479 - -32632, // A2 = 0.995880 - 10815, // B2 = 0.330063 - -4962, // B1 = -0.302887 - 10815, // B0 = 0.330063 - 15924, // A1 = -0.971924 - -32634, // A2 = 0.995941 - 18880, // B2 = 0.576172 - -9364, // B1 = -0.571594 - 18880, // B0 = 0.576172 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1380.txt - 15247, // A1 = -0.930603 - -32397, // A2 = 0.988708 - -244, // B2 = -0.007451 - 0, // B1 = 0.000000 - 244, // B0 = 0.007451 - 14989, // A1 = -0.914886 - -32627, // A2 = 0.995697 - 18961, // B2 = 0.578644 - -8498, // B1 = -0.518707 - 18961, // B0 = 0.578644 - 15608, // A1 = -0.952667 - -32628, // A2 = 0.995758 - 11145, // B2 = 0.340134 - -5430, // B1 = -0.331467 - 11145, // B0 = 0.340134 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1400.txt - 14780, // A1 = -0.902130 - -32393, // A2 = 0.988586 - -396, // B2 = -0.012086 - 0, // B1 = 0.000000 - 396, // B0 = 0.012086 - 14510, // A1 = -0.885651 - -32630, // A2 = 0.995819 - 6326, // B2 = 0.193069 - -2747, // B1 = -0.167671 - 6326, // B0 = 0.193069 - 15154, // A1 = -0.924957 - -32632, // A2 = 0.995850 - 23235, // B2 = 0.709076 - -10983, // B1 = -0.670380 - 23235, // B0 = 0.709076 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1477.txt - 13005, // A1 = -0.793793 - -32368, // A2 = 0.987823 - -500, // B2 = -0.015265 - 0, // B1 = 0.000000 - 500, // B0 = 0.015265 - 12708, // A1 = -0.775665 - -32615, // A2 = 0.995331 - 11420, // B2 = 0.348526 - -4306, // B1 = -0.262833 - 11420, // B0 = 0.348526 - 13397, // A1 = -0.817688 - -32615, // A2 = 0.995361 - 9454, // B2 = 0.288528 - -3981, // B1 = -0.243027 - 9454, // B0 = 0.288528 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1600.txt - 10046, // A1 = -0.613190 - -32331, // A2 = 0.986694 - -455, // B2 = -0.013915 - 0, // B1 = 0.000000 - 455, // B0 = 0.013915 - 9694, // A1 = -0.591705 - -32601, // A2 = 0.994934 - 6023, // B2 = 0.183815 - -1708, // B1 = -0.104279 - 6023, // B0 = 0.183815 - 10478, // A1 = -0.639587 - -32603, // A2 = 0.994965 - 22031, // B2 = 0.672333 - -7342, // B1 = -0.448151 - 22031, // B0 = 0.672333 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // f1633_1638[] - 9181, // A1 = 0.560394 - -32256, // A2 = -0.984375 - -556, // B2 = -0.016975 - 0, // B1 = 0 - 556, // B0 = 0.016975 - 8757, // A1 = 0.534515 - -32574, // A2 = -0.99408 - 8443, // B2 = 0.25769 - -2135, // B1 = -0.130341 - 8443, // B0 = 0.25769 - 9691, // A1 = 0.591522 - -32574, // A2 = -0.99411 - 15446, // B2 = 0.471375 - -4809, // B1 = -0.293579 - 15446, // B0 = 0.471375 - 7, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1800.txt - 5076, // A1 = -0.309875 - -32304, // A2 = 0.985840 - -508, // B2 = -0.015503 - 0, // B1 = 0.000000 - 508, // B0 = 0.015503 - 4646, // A1 = -0.283600 - -32605, // A2 = 0.995026 - 6742, // B2 = 0.205780 - -878, // B1 = -0.053635 - 6742, // B0 = 0.205780 - 5552, // A1 = -0.338928 - -32605, // A2 = 0.995056 - 23667, // B2 = 0.722260 - -4297, // B1 = -0.262329 - 23667, // B0 = 0.722260 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - }, - { // 1860.txt - 3569, // A1 = -0.217865 - -32292, // A2 = 0.985504 - -239, // B2 = -0.007322 - 0, // B1 = 0.000000 - 239, // B0 = 0.007322 - 3117, // A1 = -0.190277 - -32603, // A2 = 0.994965 - 18658, // B2 = 0.569427 - -1557, // B1 = -0.095032 - 18658, // B0 = 0.569427 - 4054, // A1 = -0.247437 - -32603, // A2 = 0.994965 - 18886, // B2 = 0.576385 - -2566, // B1 = -0.156647 - 18886, // B0 = 0.576385 - 5, // Internal filter scaling - 159, // Minimum in-band energy threshold - 21, // 21/32 in-band to broad-band ratio - 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 + { /* f20_50[] 11 */ + 32538, /* A1 = 1.985962 */ + -32325, /* A2 = -0.986511 */ + -343, /* B2 = -0.010493 */ + 0, /* B1 = 0 */ + 343, /* B0 = 0.010493 */ + 32619, /* A1 = 1.990906 */ + -32520, /* A2 = -0.992462 */ + 19179, /* B2 = 0.585327 */ + -19178, /* B1 = -1.170593 */ + 19179, /* B0 = 0.585327 */ + 32723, /* A1 = 1.997314 */ + -32686, /* A2 = -0.997528 */ + 9973, /* B2 = 0.304352 */ + -9955, /* B1 = -0.607605 */ + 9973, /* B0 = 0.304352 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f133_200[] 12 */ + 32072, /* A1 = 1.95752 */ + -31896, /* A2 = -0.973419 */ + -435, /* B2 = -0.013294 */ + 0, /* B1 = 0 */ + 435, /* B0 = 0.013294 */ + 32188, /* A1 = 1.9646 */ + -32400, /* A2 = -0.98877 */ + 15139, /* B2 = 0.462036 */ + -14882, /* B1 = -0.908356 */ + 15139, /* B0 = 0.462036 */ + 32473, /* A1 = 1.981995 */ + -32524, /* A2 = -0.992584 */ + 23200, /* B2 = 0.708008 */ + -23113, /* B1 = -1.410706 */ + 23200, /* B0 = 0.708008 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f300 13 */ + 31769, /* A1 = -1.939026 */ + -32584, /* A2 = 0.994385 */ + -475, /* B2 = -0.014522 */ + 0, /* B1 = 0.000000 */ + 475, /* B0 = 0.014522 */ + 31789, /* A1 = -1.940247 */ + -32679, /* A2 = 0.997284 */ + 17280, /* B2 = 0.527344 */ + -16865, /* B1 = -1.029358 */ + 17280, /* B0 = 0.527344 */ + 31841, /* A1 = -1.943481 */ + -32681, /* A2 = 0.997345 */ + 543, /* B2 = 0.016579 */ + -525, /* B1 = -0.032097 */ + 543, /* B0 = 0.016579 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f300_420[] 14 */ + 30750, /* A1 = 1.876892 */ + -31212, /* A2 = -0.952515 */ + -804, /* B2 = -0.024541 */ + 0, /* B1 = 0 */ + 804, /* B0 = 0.024541 */ + 30686, /* A1 = 1.872925 */ + -32145, /* A2 = -0.980988 */ + 14747, /* B2 = 0.450043 */ + -13703, /* B1 = -0.836395 */ + 14747, /* B0 = 0.450043 */ + 31651, /* A1 = 1.931824 */ + -32321, /* A2 = -0.986389 */ + 24425, /* B2 = 0.745422 */ + -23914, /* B1 = -1.459595 */ + 24427, /* B0 = 0.745483 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f330 15 */ + 31613, /* A1 = -1.929565 */ + -32646, /* A2 = 0.996277 */ + -185, /* B2 = -0.005657 */ + 0, /* B1 = 0.000000 */ + 185, /* B0 = 0.005657 */ + 31620, /* A1 = -1.929932 */ + -32713, /* A2 = 0.998352 */ + 19253, /* B2 = 0.587585 */ + -18566, /* B1 = -1.133179 */ + 19253, /* B0 = 0.587585 */ + 31674, /* A1 = -1.933228 */ + -32715, /* A2 = 0.998413 */ + 2575, /* B2 = 0.078590 */ + -2495, /* B1 = -0.152283 */ + 2575, /* B0 = 0.078590 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f300_425[] 16 */ + 30741, /* A1 = 1.876282 */ + -31475, /* A2 = -0.960541 */ + -703, /* B2 = -0.021484 */ + 0, /* B1 = 0 */ + 703, /* B0 = 0.021484 */ + 30688, /* A1 = 1.873047 */ + -32248, /* A2 = -0.984161 */ + 14542, /* B2 = 0.443787 */ + -13523, /* B1 = -0.825439 */ + 14542, /* B0 = 0.443817 */ + 31494, /* A1 = 1.922302 */ + -32366, /* A2 = -0.987762 */ + 21577, /* B2 = 0.658508 */ + -21013, /* B1 = -1.282532 */ + 21577, /* B0 = 0.658508 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f330_440[] 17 */ + 30627, /* A1 = 1.869324 */ + -31338, /* A2 = -0.95636 */ + -843, /* B2 = -0.025749 */ + 0, /* B1 = 0 */ + 843, /* B0 = 0.025749 */ + 30550, /* A1 = 1.864685 */ + -32221, /* A2 = -0.983337 */ + 13594, /* B2 = 0.414886 */ + -12589, /* B1 = -0.768402 */ + 13594, /* B0 = 0.414886 */ + 31488, /* A1 = 1.921936 */ + -32358, /* A2 = -0.987518 */ + 24684, /* B2 = 0.753296 */ + -24029, /* B1 = -1.466614 */ + 24684, /* B0 = 0.753296 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f340 18 */ + 31546, /* A1 = -1.925476 */ + -32646, /* A2 = 0.996277 */ + -445, /* B2 = -0.013588 */ + 0, /* B1 = 0.000000 */ + 445, /* B0 = 0.013588 */ + 31551, /* A1 = -1.925781 */ + -32713, /* A2 = 0.998352 */ + 23884, /* B2 = 0.728882 */ + -22979, /* B1 = -1.402527 */ + 23884, /* B0 = 0.728882 */ + 31606, /* A1 = -1.929138 */ + -32715, /* A2 = 0.998413 */ + 863, /* B2 = 0.026367 */ + -835, /* B1 = -0.050985 */ + 863, /* B0 = 0.026367 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f350_400[] 19 */ + 31006, /* A1 = 1.892517 */ + -32029, /* A2 = -0.977448 */ + -461, /* B2 = -0.014096 */ + 0, /* B1 = 0 */ + 461, /* B0 = 0.014096 */ + 30999, /* A1 = 1.892029 */ + -32487, /* A2 = -0.991455 */ + 11325, /* B2 = 0.345612 */ + -10682, /* B1 = -0.651978 */ + 11325, /* B0 = 0.345612 */ + 31441, /* A1 = 1.919067 */ + -32526, /* A2 = -0.992615 */ + 24324, /* B2 = 0.74231 */ + -23535, /* B1 = -1.436523 */ + 24324, /* B0 = 0.74231 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f350_440[] */ + 30634, /* A1 = 1.869751 */ + -31533, /* A2 = -0.962341 */ + -680, /* B2 = -0.020782 */ + 0, /* B1 = 0 */ + 680, /* B0 = 0.020782 */ + 30571, /* A1 = 1.865906 */ + -32277, /* A2 = -0.985016 */ + 12894, /* B2 = 0.393524 */ + -11945, /* B1 = -0.729065 */ + 12894, /* B0 = 0.393524 */ + 31367, /* A1 = 1.91449 */ + -32379, /* A2 = -0.988129 */ + 23820, /* B2 = 0.726929 */ + -23104, /* B1 = -1.410217 */ + 23820, /* B0 = 0.726929 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f350_450[] */ + 30552, /* A1 = 1.864807 */ + -31434, /* A2 = -0.95929 */ + -690, /* B2 = -0.021066 */ + 0, /* B1 = 0 */ + 690, /* B0 = 0.021066 */ + 30472, /* A1 = 1.859924 */ + -32248, /* A2 = -0.984161 */ + 13385, /* B2 = 0.408478 */ + -12357, /* B1 = -0.754242 */ + 13385, /* B0 = 0.408478 */ + 31358, /* A1 = 1.914001 */ + -32366, /* A2 = -0.987732 */ + 26488, /* B2 = 0.80835 */ + -25692, /* B1 = -1.568176 */ + 26490, /* B0 = 0.808411 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f360 */ + 31397, /* A1 = -1.916321 */ + -32623, /* A2 = 0.995605 */ + -117, /* B2 = -0.003598 */ + 0, /* B1 = 0.000000 */ + 117, /* B0 = 0.003598 */ + 31403, /* A1 = -1.916687 */ + -32700, /* A2 = 0.997925 */ + 3388, /* B2 = 0.103401 */ + -3240, /* B1 = -0.197784 */ + 3388, /* B0 = 0.103401 */ + 31463, /* A1 = -1.920410 */ + -32702, /* A2 = 0.997986 */ + 13346, /* B2 = 0.407288 */ + -12863, /* B1 = -0.785126 */ + 13346, /* B0 = 0.407288 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f380_420[] */ + 30831, /* A1 = 1.881775 */ + -32064, /* A2 = -0.978546 */ + -367, /* B2 = -0.01122 */ + 0, /* B1 = 0 */ + 367, /* B0 = 0.01122 */ + 30813, /* A1 = 1.880737 */ + -32456, /* A2 = -0.990509 */ + 11068, /* B2 = 0.337769 */ + -10338, /* B1 = -0.631042 */ + 11068, /* B0 = 0.337769 */ + 31214, /* A1 = 1.905212 */ + -32491, /* A2 = -0.991577 */ + 16374, /* B2 = 0.499695 */ + -15781, /* B1 = -0.963196 */ + 16374, /* B0 = 0.499695 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f392 */ + 31152, /* A1 = -1.901428 */ + -32613, /* A2 = 0.995300 */ + -314, /* B2 = -0.009605 */ + 0, /* B1 = 0.000000 */ + 314, /* B0 = 0.009605 */ + 31156, /* A1 = -1.901672 */ + -32694, /* A2 = 0.997742 */ + 28847, /* B2 = 0.880371 */ + -2734, /* B1 = -0.166901 */ + 28847, /* B0 = 0.880371 */ + 31225, /* A1 = -1.905823 */ + -32696, /* A2 = 0.997803 */ + 462, /* B2 = 0.014108 */ + -442, /* B1 = -0.027019 */ + 462, /* B0 = 0.014108 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f400_425[] */ + 30836, /* A1 = 1.882141 */ + -32296, /* A2 = -0.985596 */ + -324, /* B2 = -0.009903 */ + 0, /* B1 = 0 */ + 324, /* B0 = 0.009903 */ + 30825, /* A1 = 1.881409 */ + -32570, /* A2 = -0.993958 */ + 16847, /* B2 = 0.51416 */ + -15792, /* B1 = -0.963898 */ + 16847, /* B0 = 0.51416 */ + 31106, /* A1 = 1.89856 */ + -32584, /* A2 = -0.994415 */ + 9579, /* B2 = 0.292328 */ + -9164, /* B1 = -0.559357 */ + 9579, /* B0 = 0.292328 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f400_440[] */ + 30702, /* A1 = 1.873962 */ + -32134, /* A2 = -0.980682 */ + -517, /* B2 = -0.015793 */ + 0, /* B1 = 0 */ + 517, /* B0 = 0.015793 */ + 30676, /* A1 = 1.872375 */ + -32520, /* A2 = -0.992462 */ + 8144, /* B2 = 0.24855 */ + -7596, /* B1 = -0.463684 */ + 8144, /* B0 = 0.24855 */ + 31084, /* A1 = 1.897217 */ + -32547, /* A2 = -0.993256 */ + 22713, /* B2 = 0.693176 */ + -21734, /* B1 = -1.326599 */ + 22713, /* B0 = 0.693176 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f400_450[] */ + 30613, /* A1 = 1.86853 */ + -32031, /* A2 = -0.977509 */ + -618, /* B2 = -0.018866 */ + 0, /* B1 = 0 */ + 618, /* B0 = 0.018866 */ + 30577, /* A1 = 1.866272 */ + -32491, /* A2 = -0.991577 */ + 9612, /* B2 = 0.293335 */ + -8935, /* B1 = -0.54541 */ + 9612, /* B0 = 0.293335 */ + 31071, /* A1 = 1.896484 */ + -32524, /* A2 = -0.992584 */ + 21596, /* B2 = 0.659058 */ + -20667, /* B1 = -1.261414 */ + 21596, /* B0 = 0.659058 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f420 */ + 30914, /* A1 = -1.886841 */ + -32584, /* A2 = 0.994385 */ + -426, /* B2 = -0.013020 */ + 0, /* B1 = 0.000000 */ + 426, /* B0 = 0.013020 */ + 30914, /* A1 = -1.886841 */ + -32679, /* A2 = 0.997314 */ + 17520, /* B2 = 0.534668 */ + -16471, /* B1 = -1.005310 */ + 17520, /* B0 = 0.534668 */ + 31004, /* A1 = -1.892334 */ + -32683, /* A2 = 0.997406 */ + 819, /* B2 = 0.025023 */ + -780, /* B1 = -0.047619 */ + 819, /* B0 = 0.025023 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, +#if 0 + { /* f425 */ + 30881, /* A1 = -1.884827 */ + -32603, /* A2 = 0.994965 */ + -496, /* B2 = -0.015144 */ + 0, /* B1 = 0.000000 */ + 496, /* B0 = 0.015144 */ + 30880, /* A1 = -1.884766 */ + -32692, /* A2 = 0.997711 */ + 24767, /* B2 = 0.755859 */ + -23290, /* B1 = -1.421509 */ + 24767, /* B0 = 0.755859 */ + 30967, /* A1 = -1.890076 */ + -32694, /* A2 = 0.997772 */ + 728, /* B2 = 0.022232 */ + -691, /* B1 = -0.042194 */ + 728, /* B0 = 0.022232 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, +#else + { + 30850, + -32534, + -504, + 0, + 504, + 30831, + -32669, + 24303, + -22080, + 24303, + 30994, + -32673, + 1905, + -1811, + 1905, + 5, + 129, + 17, + 0xff5 + }, +#endif + { /* f425_450[] */ + 30646, /* A1 = 1.870544 */ + -32327, /* A2 = -0.986572 */ + -287, /* B2 = -0.008769 */ + 0, /* B1 = 0 */ + 287, /* B0 = 0.008769 */ + 30627, /* A1 = 1.869324 */ + -32607, /* A2 = -0.995087 */ + 13269, /* B2 = 0.404968 */ + -12376, /* B1 = -0.755432 */ + 13269, /* B0 = 0.404968 */ + 30924, /* A1 = 1.887512 */ + -32619, /* A2 = -0.995453 */ + 19950, /* B2 = 0.608826 */ + -18940, /* B1 = -1.156006 */ + 19950, /* B0 = 0.608826 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f425_475[] */ + 30396, /* A1 = 1.855225 */ + -32014, /* A2 = -0.97699 */ + -395, /* B2 = -0.012055 */ + 0, /* B1 = 0 */ + 395, /* B0 = 0.012055 */ + 30343, /* A1 = 1.85199 */ + -32482, /* A2 = -0.991302 */ + 17823, /* B2 = 0.543945 */ + -16431, /* B1 = -1.002869 */ + 17823, /* B0 = 0.543945 */ + 30872, /* A1 = 1.884338 */ + -32516, /* A2 = -0.99231 */ + 18124, /* B2 = 0.553101 */ + -17246, /* B1 = -1.052673 */ + 18124, /* B0 = 0.553101 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f435 */ + 30796, /* A1 = -1.879639 */ + -32603, /* A2 = 0.994965 */ + -254, /* B2 = -0.007762 */ + 0, /* B1 = 0.000000 */ + 254, /* B0 = 0.007762 */ + 30793, /* A1 = -1.879456 */ + -32692, /* A2 = 0.997711 */ + 18934, /* B2 = 0.577820 */ + -17751, /* B1 = -1.083496 */ + 18934, /* B0 = 0.577820 */ + 30882, /* A1 = -1.884888 */ + -32694, /* A2 = 0.997772 */ + 1858, /* B2 = 0.056713 */ + -1758, /* B1 = -0.107357 */ + 1858, /* B0 = 0.056713 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f440_450[] */ + 30641, /* A1 = 1.870239 */ + -32458, /* A2 = -0.99057 */ + -155, /* B2 = -0.004735 */ + 0, /* B1 = 0 */ + 155, /* B0 = 0.004735 */ + 30631, /* A1 = 1.869568 */ + -32630, /* A2 = -0.995789 */ + 11453, /* B2 = 0.349548 */ + -10666, /* B1 = -0.651001 */ + 11453, /* B0 = 0.349548 */ + 30810, /* A1 = 1.880554 */ + -32634, /* A2 = -0.995941 */ + 12237, /* B2 = 0.373474 */ + -11588, /* B1 = -0.707336 */ + 12237, /* B0 = 0.373474 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f440_480[] */ + 30367, /* A1 = 1.853455 */ + -32147, /* A2 = -0.981079 */ + -495, /* B2 = -0.015113 */ + 0, /* B1 = 0 */ + 495, /* B0 = 0.015113 */ + 30322, /* A1 = 1.850769 */ + -32543, /* A2 = -0.993134 */ + 10031, /* B2 = 0.306152 */ + -9252, /* B1 = -0.564728 */ + 10031, /* B0 = 0.306152 */ + 30770, /* A1 = 1.878052 */ + -32563, /* A2 = -0.993774 */ + 22674, /* B2 = 0.691956 */ + -21465, /* B1 = -1.31012 */ + 22674, /* B0 = 0.691956 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f445 */ + 30709, /* A1 = -1.874329 */ + -32603, /* A2 = 0.994965 */ + -83, /* B2 = -0.002545 */ + 0, /* B1 = 0.000000 */ + 83, /* B0 = 0.002545 */ + 30704, /* A1 = -1.874084 */ + -32692, /* A2 = 0.997711 */ + 10641, /* B2 = 0.324738 */ + -9947, /* B1 = -0.607147 */ + 10641, /* B0 = 0.324738 */ + 30796, /* A1 = -1.879639 */ + -32694, /* A2 = 0.997772 */ + 10079, /* B2 = 0.307587 */ + 9513, /* B1 = 0.580688 */ + 10079, /* B0 = 0.307587 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f450 */ + 30664, /* A1 = -1.871643 */ + -32603, /* A2 = 0.994965 */ + -164, /* B2 = -0.005029 */ + 0, /* B1 = 0.000000 */ + 164, /* B0 = 0.005029 */ + 30661, /* A1 = -1.871399 */ + -32692, /* A2 = 0.997711 */ + 15294, /* B2 = 0.466736 */ + -14275, /* B1 = -0.871307 */ + 15294, /* B0 = 0.466736 */ + 30751, /* A1 = -1.876953 */ + -32694, /* A2 = 0.997772 */ + 3548, /* B2 = 0.108284 */ + -3344, /* B1 = -0.204155 */ + 3548, /* B0 = 0.108284 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f452 */ + 30653, /* A1 = -1.870911 */ + -32615, /* A2 = 0.995361 */ + -209, /* B2 = -0.006382 */ + 0, /* B1 = 0.000000 */ + 209, /* B0 = 0.006382 */ + 30647, /* A1 = -1.870605 */ + -32702, /* A2 = 0.997986 */ + 18971, /* B2 = 0.578979 */ + -17716, /* B1 = -1.081299 */ + 18971, /* B0 = 0.578979 */ + 30738, /* A1 = -1.876099 */ + -32702, /* A2 = 0.998016 */ + 2967, /* B2 = 0.090561 */ + -2793, /* B1 = -0.170502 */ + 2967, /* B0 = 0.090561 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f475 */ + 30437, /* A1 = -1.857727 */ + -32603, /* A2 = 0.994965 */ + -264, /* B2 = -0.008062 */ + 0, /* B1 = 0.000000 */ + 264, /* B0 = 0.008062 */ + 30430, /* A1 = -1.857300 */ + -32692, /* A2 = 0.997711 */ + 21681, /* B2 = 0.661682 */ + -20082, /* B1 = -1.225708 */ + 21681, /* B0 = 0.661682 */ + 30526, /* A1 = -1.863220 */ + -32694, /* A2 = 0.997742 */ + 1559, /* B2 = 0.047600 */ + -1459, /* B1 = -0.089096 */ + 1559, /* B0 = 0.047600 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f480_620[] */ + 28975, /* A1 = 1.768494 */ + -30955, /* A2 = -0.944672 */ + -1026, /* B2 = -0.03133 */ + 0, /* B1 = 0 */ + 1026, /* B0 = 0.03133 */ + 28613, /* A1 = 1.746399 */ + -32089, /* A2 = -0.979309 */ + 14214, /* B2 = 0.433807 */ + -12202, /* B1 = -0.744812 */ + 14214, /* B0 = 0.433807 */ + 30243, /* A1 = 1.845947 */ + -32238, /* A2 = -0.983856 */ + 24825, /* B2 = 0.757629 */ + -23402, /* B1 = -1.428345 */ + 24825, /* B0 = 0.757629 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f494 */ + 30257, /* A1 = -1.846741 */ + -32605, /* A2 = 0.995056 */ + -249, /* B2 = -0.007625 */ + 0, /* B1 = 0.000000 */ + 249, /* B0 = 0.007625 */ + 30247, /* A1 = -1.846191 */ + -32694, /* A2 = 0.997772 */ + 18088, /* B2 = 0.552002 */ + -16652, /* B1 = -1.016418 */ + 18088, /* B0 = 0.552002 */ + 30348, /* A1 = -1.852295 */ + -32696, /* A2 = 0.997803 */ + 2099, /* B2 = 0.064064 */ + -1953, /* B1 = -0.119202 */ + 2099, /* B0 = 0.064064 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f500 */ + 30202, /* A1 = -1.843431 */ + -32624, /* A2 = 0.995622 */ + -413, /* B2 = -0.012622 */ + 0, /* B1 = 0.000000 */ + 413, /* B0 = 0.012622 */ + 30191, /* A1 = -1.842721 */ + -32714, /* A2 = 0.998364 */ + 25954, /* B2 = 0.792057 */ + -23890, /* B1 = -1.458131 */ + 25954, /* B0 = 0.792057 */ + 30296, /* A1 = -1.849172 */ + -32715, /* A2 = 0.998397 */ + 2007, /* B2 = 0.061264 */ + -1860, /* B1 = -0.113568 */ + 2007, /* B0 = 0.061264 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f520 */ + 30001, /* A1 = -1.831116 */ + -32613, /* A2 = 0.995270 */ + -155, /* B2 = -0.004750 */ + 0, /* B1 = 0.000000 */ + 155, /* B0 = 0.004750 */ + 29985, /* A1 = -1.830200 */ + -32710, /* A2 = 0.998260 */ + 6584, /* B2 = 0.200928 */ + -6018, /* B1 = -0.367355 */ + 6584, /* B0 = 0.200928 */ + 30105, /* A1 = -1.837524 */ + -32712, /* A2 = 0.998291 */ + 23812, /* B2 = 0.726685 */ + -21936, /* B1 = -1.338928 */ + 23812, /* B0 = 0.726685 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f523 */ + 29964, /* A1 = -1.828918 */ + -32601, /* A2 = 0.994904 */ + -101, /* B2 = -0.003110 */ + 0, /* B1 = 0.000000 */ + 101, /* B0 = 0.003110 */ + 29949, /* A1 = -1.827942 */ + -32700, /* A2 = 0.997925 */ + 11041, /* B2 = 0.336975 */ + -10075, /* B1 = -0.614960 */ + 11041, /* B0 = 0.336975 */ + 30070, /* A1 = -1.835388 */ + -32702, /* A2 = 0.997986 */ + 16762, /* B2 = 0.511536 */ + -15437, /* B1 = -0.942230 */ + 16762, /* B0 = 0.511536 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f525 */ + 29936, /* A1 = -1.827209 */ + -32584, /* A2 = 0.994415 */ + -91, /* B2 = -0.002806 */ + 0, /* B1 = 0.000000 */ + 91, /* B0 = 0.002806 */ + 29921, /* A1 = -1.826233 */ + -32688, /* A2 = 0.997559 */ + 11449, /* B2 = 0.349396 */ + -10426, /* B1 = -0.636383 */ + 11449, /* B0 = 0.349396 */ + 30045, /* A1 = -1.833862 */ + -32688, /* A2 = 0.997589 */ + 13055, /* B2 = 0.398407 */ + -12028, /* B1 = -0.734161 */ + 13055, /* B0 = 0.398407 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f540_660[] */ + 28499, /* A1 = 1.739441 */ + -31129, /* A2 = -0.949982 */ + -849, /* B2 = -0.025922 */ + 0, /* B1 = 0 */ + 849, /* B0 = 0.025922 */ + 28128, /* A1 = 1.716797 */ + -32130, /* A2 = -0.98056 */ + 14556, /* B2 = 0.444214 */ + -12251, /* B1 = -0.747772 */ + 14556, /* B0 = 0.444244 */ + 29667, /* A1 = 1.81073 */ + -32244, /* A2 = -0.984039 */ + 23038, /* B2 = 0.703064 */ + -21358, /* B1 = -1.303589 */ + 23040, /* B0 = 0.703125 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f587 */ + 29271, /* A1 = -1.786560 */ + -32599, /* A2 = 0.994873 */ + -490, /* B2 = -0.014957 */ + 0, /* B1 = 0.000000 */ + 490, /* B0 = 0.014957 */ + 29246, /* A1 = -1.785095 */ + -32700, /* A2 = 0.997925 */ + 28961, /* B2 = 0.883850 */ + -25796, /* B1 = -1.574463 */ + 28961, /* B0 = 0.883850 */ + 29383, /* A1 = -1.793396 */ + -32700, /* A2 = 0.997955 */ + 1299, /* B2 = 0.039650 */ + -1169, /* B1 = -0.071396 */ + 1299, /* B0 = 0.039650 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f590 */ + 29230, /* A1 = -1.784058 */ + -32584, /* A2 = 0.994415 */ + -418, /* B2 = -0.012757 */ + 0, /* B1 = 0.000000 */ + 418, /* B0 = 0.012757 */ + 29206, /* A1 = -1.782593 */ + -32688, /* A2 = 0.997559 */ + 36556, /* B2 = 1.115601 */ + -32478, /* B1 = -1.982300 */ + 36556, /* B0 = 1.115601 */ + 29345, /* A1 = -1.791077 */ + -32688, /* A2 = 0.997589 */ + 897, /* B2 = 0.027397 */ + -808, /* B1 = -0.049334 */ + 897, /* B0 = 0.027397 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f600 */ + 29116, /* A1 = -1.777100 */ + -32603, /* A2 = 0.994965 */ + -165, /* B2 = -0.005039 */ + 0, /* B1 = 0.000000 */ + 165, /* B0 = 0.005039 */ + 29089, /* A1 = -1.775452 */ + -32708, /* A2 = 0.998199 */ + 6963, /* B2 = 0.212494 */ + -6172, /* B1 = -0.376770 */ + 6963, /* B0 = 0.212494 */ + 29237, /* A1 = -1.784485 */ + -32710, /* A2 = 0.998230 */ + 24197, /* B2 = 0.738464 */ + -21657, /* B1 = -1.321899 */ + 24197, /* B0 = 0.738464 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f660 */ + 28376, /* A1 = -1.731934 */ + -32567, /* A2 = 0.993896 */ + -363, /* B2 = -0.011102 */ + 0, /* B1 = 0.000000 */ + 363, /* B0 = 0.011102 */ + 28337, /* A1 = -1.729614 */ + -32683, /* A2 = 0.997434 */ + 21766, /* B2 = 0.664246 */ + -18761, /* B1 = -1.145081 */ + 21766, /* B0 = 0.664246 */ + 28513, /* A1 = -1.740356 */ + -32686, /* A2 = 0.997498 */ + 2509, /* B2 = 0.076584 */ + -2196, /* B1 = -0.134041 */ + 2509, /* B0 = 0.076584 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f700 */ + 27844, /* A1 = -1.699463 */ + -32563, /* A2 = 0.993744 */ + -366, /* B2 = -0.011187 */ + 0, /* B1 = 0.000000 */ + 366, /* B0 = 0.011187 */ + 27797, /* A1 = -1.696655 */ + -32686, /* A2 = 0.997498 */ + 22748, /* B2 = 0.694214 */ + -19235, /* B1 = -1.174072 */ + 22748, /* B0 = 0.694214 */ + 27995, /* A1 = -1.708740 */ + -32688, /* A2 = 0.997559 */ + 2964, /* B2 = 0.090477 */ + -2546, /* B1 = -0.155449 */ + 2964, /* B0 = 0.090477 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f740 */ + 27297, /* A1 = -1.666077 */ + -32551, /* A2 = 0.993408 */ + -345, /* B2 = -0.010540 */ + 0, /* B1 = 0.000000 */ + 345, /* B0 = 0.010540 */ + 27240, /* A1 = -1.662598 */ + -32683, /* A2 = 0.997406 */ + 22560, /* B2 = 0.688477 */ + -18688, /* B1 = -1.140625 */ + 22560, /* B0 = 0.688477 */ + 27461, /* A1 = -1.676147 */ + -32684, /* A2 = 0.997467 */ + 3541, /* B2 = 0.108086 */ + -2985, /* B1 = -0.182220 */ + 3541, /* B0 = 0.108086 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f750 */ + 27155, /* A1 = -1.657410 */ + -32551, /* A2 = 0.993408 */ + -462, /* B2 = -0.014117 */ + 0, /* B1 = 0.000000 */ + 462, /* B0 = 0.014117 */ + 27097, /* A1 = -1.653870 */ + -32683, /* A2 = 0.997406 */ + 32495, /* B2 = 0.991699 */ + -26776, /* B1 = -1.634338 */ + 32495, /* B0 = 0.991699 */ + 27321, /* A1 = -1.667542 */ + -32684, /* A2 = 0.997467 */ + 1835, /* B2 = 0.056007 */ + -1539, /* B1 = -0.093948 */ + 1835, /* B0 = 0.056007 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f750_1450[] */ + 19298, /* A1 = 1.177917 */ + -24471, /* A2 = -0.746796 */ + -4152, /* B2 = -0.126709 */ + 0, /* B1 = 0 */ + 4152, /* B0 = 0.126709 */ + 12902, /* A1 = 0.787476 */ + -29091, /* A2 = -0.887817 */ + 12491, /* B2 = 0.38121 */ + -1794, /* B1 = -0.109528 */ + 12494, /* B0 = 0.381317 */ + 26291, /* A1 = 1.604736 */ + -30470, /* A2 = -0.929901 */ + 28859, /* B2 = 0.880737 */ + -26084, /* B1 = -1.592102 */ + 28861, /* B0 = 0.880798 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f770 */ + 26867, /* A1 = -1.639832 */ + -32551, /* A2 = 0.993408 */ + -123, /* B2 = -0.003755 */ + 0, /* B1 = 0.000000 */ + 123, /* B0 = 0.003755 */ + 26805, /* A1 = -1.636108 */ + -32683, /* A2 = 0.997406 */ + 17297, /* B2 = 0.527863 */ + -14096, /* B1 = -0.860382 */ + 17297, /* B0 = 0.527863 */ + 27034, /* A1 = -1.650085 */ + -32684, /* A2 = 0.997467 */ + 12958, /* B2 = 0.395477 */ + -10756, /* B1 = -0.656525 */ + 12958, /* B0 = 0.395477 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f800 */ + 26413, /* A1 = -1.612122 */ + -32547, /* A2 = 0.993286 */ + -223, /* B2 = -0.006825 */ + 0, /* B1 = 0.000000 */ + 223, /* B0 = 0.006825 */ + 26342, /* A1 = -1.607849 */ + -32686, /* A2 = 0.997498 */ + 6391, /* B2 = 0.195053 */ + -5120, /* B1 = -0.312531 */ + 6391, /* B0 = 0.195053 */ + 26593, /* A1 = -1.623108 */ + -32688, /* A2 = 0.997559 */ + 23681, /* B2 = 0.722717 */ + -19328, /* B1 = -1.179688 */ + 23681, /* B0 = 0.722717 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f816 */ + 26168, /* A1 = -1.597209 */ + -32528, /* A2 = 0.992706 */ + -235, /* B2 = -0.007182 */ + 0, /* B1 = 0.000000 */ + 235, /* B0 = 0.007182 */ + 26092, /* A1 = -1.592590 */ + -32675, /* A2 = 0.997192 */ + 20823, /* B2 = 0.635498 */ + -16510, /* B1 = -1.007751 */ + 20823, /* B0 = 0.635498 */ + 26363, /* A1 = -1.609070 */ + -32677, /* A2 = 0.997253 */ + 6739, /* B2 = 0.205688 */ + -5459, /* B1 = -0.333206 */ + 6739, /* B0 = 0.205688 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f850 */ + 25641, /* A1 = -1.565063 */ + -32536, /* A2 = 0.992950 */ + -121, /* B2 = -0.003707 */ + 0, /* B1 = 0.000000 */ + 121, /* B0 = 0.003707 */ + 25560, /* A1 = -1.560059 */ + -32684, /* A2 = 0.997437 */ + 18341, /* B2 = 0.559753 */ + -14252, /* B1 = -0.869904 */ + 18341, /* B0 = 0.559753 */ + 25837, /* A1 = -1.577026 */ + -32684, /* A2 = 0.997467 */ + 16679, /* B2 = 0.509003 */ + -13232, /* B1 = -0.807648 */ + 16679, /* B0 = 0.509003 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f857_1645[] */ + 16415, /* A1 = 1.001953 */ + -23669, /* A2 = -0.722321 */ + -4549, /* B2 = -0.138847 */ + 0, /* B1 = 0 */ + 4549, /* B0 = 0.138847 */ + 8456, /* A1 = 0.516174 */ + -28996, /* A2 = -0.884918 */ + 13753, /* B2 = 0.419724 */ + -12, /* B1 = -0.000763 */ + 13757, /* B0 = 0.419846 */ + 24632, /* A1 = 1.503418 */ + -30271, /* A2 = -0.923828 */ + 29070, /* B2 = 0.887146 */ + -25265, /* B1 = -1.542114 */ + 29073, /* B0 = 0.887268 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f900 */ + 24806, /* A1 = -1.514099 */ + -32501, /* A2 = 0.991852 */ + -326, /* B2 = -0.009969 */ + 0, /* B1 = 0.000000 */ + 326, /* B0 = 0.009969 */ + 24709, /* A1 = -1.508118 */ + -32659, /* A2 = 0.996674 */ + 20277, /* B2 = 0.618835 */ + -15182, /* B1 = -0.926636 */ + 20277, /* B0 = 0.618835 */ + 25022, /* A1 = -1.527222 */ + -32661, /* A2 = 0.996735 */ + 4320, /* B2 = 0.131836 */ + -3331, /* B1 = -0.203339 */ + 4320, /* B0 = 0.131836 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f900_1300[] */ + 19776, /* A1 = 1.207092 */ + -27437, /* A2 = -0.837341 */ + -2666, /* B2 = -0.081371 */ + 0, /* B1 = 0 */ + 2666, /* B0 = 0.081371 */ + 16302, /* A1 = 0.995026 */ + -30354, /* A2 = -0.926361 */ + 10389, /* B2 = 0.317062 */ + -3327, /* B1 = -0.203064 */ + 10389, /* B0 = 0.317062 */ + 24299, /* A1 = 1.483154 */ + -30930, /* A2 = -0.943909 */ + 25016, /* B2 = 0.763428 */ + -21171, /* B1 = -1.292236 */ + 25016, /* B0 = 0.763428 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f935_1215[] */ + 20554, /* A1 = 1.254517 */ + -28764, /* A2 = -0.877838 */ + -2048, /* B2 = -0.062515 */ + 0, /* B1 = 0 */ + 2048, /* B0 = 0.062515 */ + 18209, /* A1 = 1.11145 */ + -30951, /* A2 = -0.94458 */ + 9390, /* B2 = 0.286575 */ + -3955, /* B1 = -0.241455 */ + 9390, /* B0 = 0.286575 */ + 23902, /* A1 = 1.458923 */ + -31286, /* A2 = -0.954803 */ + 23252, /* B2 = 0.709595 */ + -19132, /* B1 = -1.167725 */ + 23252, /* B0 = 0.709595 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f941_1477[] */ + 17543, /* A1 = 1.07074 */ + -26220, /* A2 = -0.800201 */ + -3298, /* B2 = -0.100647 */ + 0, /* B1 = 0 */ + 3298, /* B0 = 0.100647 */ + 12423, /* A1 = 0.75827 */ + -30036, /* A2 = -0.916626 */ + 12651, /* B2 = 0.386078 */ + -2444, /* B1 = -0.14917 */ + 12653, /* B0 = 0.386154 */ + 23518, /* A1 = 1.435425 */ + -30745, /* A2 = -0.938293 */ + 27282, /* B2 = 0.832581 */ + -22529, /* B1 = -1.375122 */ + 27286, /* B0 = 0.832703 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f942 */ + 24104, /* A1 = -1.471252 */ + -32507, /* A2 = 0.992065 */ + -351, /* B2 = -0.010722 */ + 0, /* B1 = 0.000000 */ + 351, /* B0 = 0.010722 */ + 23996, /* A1 = -1.464600 */ + -32671, /* A2 = 0.997040 */ + 22848, /* B2 = 0.697266 */ + -16639, /* B1 = -1.015564 */ + 22848, /* B0 = 0.697266 */ + 24332, /* A1 = -1.485168 */ + -32673, /* A2 = 0.997101 */ + 4906, /* B2 = 0.149727 */ + -3672, /* B1 = -0.224174 */ + 4906, /* B0 = 0.149727 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f950 */ + 23967, /* A1 = -1.462830 */ + -32507, /* A2 = 0.992065 */ + -518, /* B2 = -0.015821 */ + 0, /* B1 = 0.000000 */ + 518, /* B0 = 0.015821 */ + 23856, /* A1 = -1.456055 */ + -32671, /* A2 = 0.997040 */ + 26287, /* B2 = 0.802246 */ + -19031, /* B1 = -1.161560 */ + 26287, /* B0 = 0.802246 */ + 24195, /* A1 = -1.476746 */ + -32673, /* A2 = 0.997101 */ + 2890, /* B2 = 0.088196 */ + -2151, /* B1 = -0.131317 */ + 2890, /* B0 = 0.088196 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f950_1400[] */ + 18294, /* A1 = 1.116638 */ + -26962, /* A2 = -0.822845 */ + -2914, /* B2 = -0.088936 */ + 0, /* B1 = 0 */ + 2914, /* B0 = 0.088936 */ + 14119, /* A1 = 0.861786 */ + -30227, /* A2 = -0.922455 */ + 11466, /* B2 = 0.349945 */ + -2833, /* B1 = -0.172943 */ + 11466, /* B0 = 0.349945 */ + 23431, /* A1 = 1.430115 */ + -30828, /* A2 = -0.940796 */ + 25331, /* B2 = 0.773071 */ + -20911, /* B1 = -1.276367 */ + 25331, /* B0 = 0.773071 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f975 */ + 23521, /* A1 = -1.435608 */ + -32489, /* A2 = 0.991516 */ + -193, /* B2 = -0.005915 */ + 0, /* B1 = 0.000000 */ + 193, /* B0 = 0.005915 */ + 23404, /* A1 = -1.428467 */ + -32655, /* A2 = 0.996582 */ + 17740, /* B2 = 0.541412 */ + -12567, /* B1 = -0.767029 */ + 17740, /* B0 = 0.541412 */ + 23753, /* A1 = -1.449829 */ + -32657, /* A2 = 0.996613 */ + 9090, /* B2 = 0.277405 */ + -6662, /* B1 = -0.406647 */ + 9090, /* B0 = 0.277405 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1000 */ + 23071, /* A1 = -1.408203 */ + -32489, /* A2 = 0.991516 */ + -293, /* B2 = -0.008965 */ + 0, /* B1 = 0.000000 */ + 293, /* B0 = 0.008965 */ + 22951, /* A1 = -1.400818 */ + -32655, /* A2 = 0.996582 */ + 5689, /* B2 = 0.173645 */ + -3951, /* B1 = -0.241150 */ + 5689, /* B0 = 0.173645 */ + 23307, /* A1 = -1.422607 */ + -32657, /* A2 = 0.996613 */ + 18692, /* B2 = 0.570435 */ + -13447, /* B1 = -0.820770 */ + 18692, /* B0 = 0.570435 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1020 */ + 22701, /* A1 = -1.385620 */ + -32474, /* A2 = 0.991058 */ + -292, /* B2 = -0.008933 */ + 0, /*163840 , B1 = 10.000000 */ + 292, /* B0 = 0.008933 */ + 22564, /* A1 = -1.377258 */ + -32655, /* A2 = 0.996552 */ + 20756, /* B2 = 0.633423 */ + -14176, /* B1 = -0.865295 */ + 20756, /* B0 = 0.633423 */ + 22960, /* A1 = -1.401428 */ + -32657, /* A2 = 0.996613 */ + 6520, /* B2 = 0.198990 */ + -4619, /* B1 = -0.281937 */ + 6520, /* B0 = 0.198990 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1050 */ + 22142, /* A1 = -1.351501 */ + -32474, /* A2 = 0.991058 */ + -147, /* B2 = -0.004493 */ + 0, /* B1 = 0.000000 */ + 147, /* B0 = 0.004493 */ + 22000, /* A1 = -1.342834 */ + -32655, /* A2 = 0.996552 */ + 15379, /* B2 = 0.469360 */ + -10237, /* B1 = -0.624847 */ + 15379, /* B0 = 0.469360 */ + 22406, /* A1 = -1.367554 */ + -32657, /* A2 = 0.996613 */ + 17491, /* B2 = 0.533783 */ + -12096, /* B1 = -0.738312 */ + 17491, /* B0 = 0.533783 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1100_1750[] */ + 12973, /* A1 = 0.79184 */ + -24916, /* A2 = -0.760376 */ + 6655, /* B2 = 0.203102 */ + 367, /* B1 = 0.0224 */ + 6657, /* B0 = 0.203171 */ + 5915, /* A1 = 0.361053 */ + -29560, /* A2 = -0.90213 */ + -7777, /* B2 = -0.23735 */ + 0, /* B1 = 0 */ + 7777, /* B0 = 0.23735 */ + 20510, /* A1 = 1.251892 */ + -30260, /* A2 = -0.923462 */ + 26662, /* B2 = 0.81366 */ + -20573, /* B1 = -1.255737 */ + 26668, /* B0 = 0.813843 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1140 */ + 20392, /* A1 = -1.244629 */ + -32460, /* A2 = 0.990601 */ + -270, /* B2 = -0.008240 */ + 0, /* B1 = 0.000000 */ + 270, /* B0 = 0.008240 */ + 20218, /* A1 = -1.234009 */ + -32655, /* A2 = 0.996582 */ + 21337, /* B2 = 0.651154 */ + -13044, /* B1 = -0.796143 */ + 21337, /* B0 = 0.651154 */ + 20684, /* A1 = -1.262512 */ + -32657, /* A2 = 0.996643 */ + 8572, /* B2 = 0.261612 */ + -5476, /* B1 = -0.334244 */ + 8572, /* B0 = 0.261612 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1200 */ + 19159, /* A1 = -1.169373 */ + -32456, /* A2 = 0.990509 */ + -335, /* B2 = -0.010252 */ + 0, /* B1 = 0.000000 */ + 335, /* B0 = 0.010252 */ + 18966, /* A1 = -1.157593 */ + -32661, /* A2 = 0.996735 */ + 6802, /* B2 = 0.207588 */ + -3900, /* B1 = -0.238098 */ + 6802, /* B0 = 0.207588 */ + 19467, /* A1 = -1.188232 */ + -32661, /* A2 = 0.996765 */ + 25035, /* B2 = 0.764008 */ + -15049, /* B1 = -0.918579 */ + 25035, /* B0 = 0.764008 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1209 */ + 18976, /* A1 = -1.158264 */ + -32439, /* A2 = 0.989990 */ + -183, /* B2 = -0.005588 */ + 0, /* B1 = 0.000000 */ + 183, /* B0 = 0.005588 */ + 18774, /* A1 = -1.145874 */ + -32650, /* A2 = 0.996429 */ + 15468, /* B2 = 0.472076 */ + -8768, /* B1 = -0.535217 */ + 15468, /* B0 = 0.472076 */ + 19300, /* A1 = -1.177979 */ + -32652, /* A2 = 0.996490 */ + 19840, /* B2 = 0.605499 */ + -11842, /* B1 = -0.722809 */ + 19840, /* B0 = 0.605499 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1330 */ + 16357, /* A1 = -0.998413 */ + -32368, /* A2 = 0.987793 */ + -217, /* B2 = -0.006652 */ + 0, /* B1 = 0.000000 */ + 217, /* B0 = 0.006652 */ + 16107, /* A1 = -0.983126 */ + -32601, /* A2 = 0.994904 */ + 11602, /* B2 = 0.354065 */ + -5555, /* B1 = -0.339111 */ + 11602, /* B0 = 0.354065 */ + 16722, /* A1 = -1.020630 */ + -32603, /* A2 = 0.994965 */ + 15574, /* B2 = 0.475311 */ + -8176, /* B1 = -0.499069 */ + 15574, /* B0 = 0.475311 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1336 */ + 16234, /* A1 = -0.990875 */ + 32404, /* A2 = -0.988922 */ + -193, /* B2 = -0.005908 */ + 0, /* B1 = 0.000000 */ + 193, /* B0 = 0.005908 */ + 15986, /* A1 = -0.975769 */ + -32632, /* A2 = 0.995880 */ + 18051, /* B2 = 0.550903 */ + -8658, /* B1 = -0.528473 */ + 18051, /* B0 = 0.550903 */ + 16591, /* A1 = -1.012695 */ + -32634, /* A2 = 0.995941 */ + 15736, /* B2 = 0.480240 */ + -8125, /* B1 = -0.495926 */ + 15736, /* B0 = 0.480240 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1366 */ + 15564, /* A1 = -0.949982 */ + -32404, /* A2 = 0.988922 */ + -269, /* B2 = -0.008216 */ + 0, /* B1 = 0.000000 */ + 269, /* B0 = 0.008216 */ + 15310, /* A1 = -0.934479 */ + -32632, /* A2 = 0.995880 */ + 10815, /* B2 = 0.330063 */ + -4962, /* B1 = -0.302887 */ + 10815, /* B0 = 0.330063 */ + 15924, /* A1 = -0.971924 */ + -32634, /* A2 = 0.995941 */ + 18880, /* B2 = 0.576172 */ + -9364, /* B1 = -0.571594 */ + 18880, /* B0 = 0.576172 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1380 */ + 15247, /* A1 = -0.930603 */ + -32397, /* A2 = 0.988708 */ + -244, /* B2 = -0.007451 */ + 0, /* B1 = 0.000000 */ + 244, /* B0 = 0.007451 */ + 14989, /* A1 = -0.914886 */ + -32627, /* A2 = 0.995697 */ + 18961, /* B2 = 0.578644 */ + -8498, /* B1 = -0.518707 */ + 18961, /* B0 = 0.578644 */ + 15608, /* A1 = -0.952667 */ + -32628, /* A2 = 0.995758 */ + 11145, /* B2 = 0.340134 */ + -5430, /* B1 = -0.331467 */ + 11145, /* B0 = 0.340134 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1400 */ + 14780, /* A1 = -0.902130 */ + -32393, /* A2 = 0.988586 */ + -396, /* B2 = -0.012086 */ + 0, /* B1 = 0.000000 */ + 396, /* B0 = 0.012086 */ + 14510, /* A1 = -0.885651 */ + -32630, /* A2 = 0.995819 */ + 6326, /* B2 = 0.193069 */ + -2747, /* B1 = -0.167671 */ + 6326, /* B0 = 0.193069 */ + 15154, /* A1 = -0.924957 */ + -32632, /* A2 = 0.995850 */ + 23235, /* B2 = 0.709076 */ + -10983, /* B1 = -0.670380 */ + 23235, /* B0 = 0.709076 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1477 */ + 13005, /* A1 = -0.793793 */ + -32368, /* A2 = 0.987823 */ + -500, /* B2 = -0.015265 */ + 0, /* B1 = 0.000000 */ + 500, /* B0 = 0.015265 */ + 12708, /* A1 = -0.775665 */ + -32615, /* A2 = 0.995331 */ + 11420, /* B2 = 0.348526 */ + -4306, /* B1 = -0.262833 */ + 11420, /* B0 = 0.348526 */ + 13397, /* A1 = -0.817688 */ + -32615, /* A2 = 0.995361 */ + 9454, /* B2 = 0.288528 */ + -3981, /* B1 = -0.243027 */ + 9454, /* B0 = 0.288528 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1600 */ + 10046, /* A1 = -0.613190 */ + -32331, /* A2 = 0.986694 */ + -455, /* B2 = -0.013915 */ + 0, /* B1 = 0.000000 */ + 455, /* B0 = 0.013915 */ + 9694, /* A1 = -0.591705 */ + -32601, /* A2 = 0.994934 */ + 6023, /* B2 = 0.183815 */ + -1708, /* B1 = -0.104279 */ + 6023, /* B0 = 0.183815 */ + 10478, /* A1 = -0.639587 */ + -32603, /* A2 = 0.994965 */ + 22031, /* B2 = 0.672333 */ + -7342, /* B1 = -0.448151 */ + 22031, /* B0 = 0.672333 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1633_1638[] */ + 9181, /* A1 = 0.560394 */ + -32256, /* A2 = -0.984375 */ + -556, /* B2 = -0.016975 */ + 0, /* B1 = 0 */ + 556, /* B0 = 0.016975 */ + 8757, /* A1 = 0.534515 */ + -32574, /* A2 = -0.99408 */ + 8443, /* B2 = 0.25769 */ + -2135, /* B1 = -0.130341 */ + 8443, /* B0 = 0.25769 */ + 9691, /* A1 = 0.591522 */ + -32574, /* A2 = -0.99411 */ + 15446, /* B2 = 0.471375 */ + -4809, /* B1 = -0.293579 */ + 15446, /* B0 = 0.471375 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1800 */ + 5076, /* A1 = -0.309875 */ + -32304, /* A2 = 0.985840 */ + -508, /* B2 = -0.015503 */ + 0, /* B1 = 0.000000 */ + 508, /* B0 = 0.015503 */ + 4646, /* A1 = -0.283600 */ + -32605, /* A2 = 0.995026 */ + 6742, /* B2 = 0.205780 */ + -878, /* B1 = -0.053635 */ + 6742, /* B0 = 0.205780 */ + 5552, /* A1 = -0.338928 */ + -32605, /* A2 = 0.995056 */ + 23667, /* B2 = 0.722260 */ + -4297, /* B1 = -0.262329 */ + 23667, /* B0 = 0.722260 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1860 */ + 3569, /* A1 = -0.217865 */ + -32292, /* A2 = 0.985504 */ + -239, /* B2 = -0.007322 */ + 0, /* B1 = 0.000000 */ + 239, /* B0 = 0.007322 */ + 3117, /* A1 = -0.190277 */ + -32603, /* A2 = 0.994965 */ + 18658, /* B2 = 0.569427 */ + -1557, /* B1 = -0.095032 */ + 18658, /* B0 = 0.569427 */ + 4054, /* A1 = -0.247437 */ + -32603, /* A2 = 0.994965 */ + 18886, /* B2 = 0.576385 */ + -2566, /* B1 = -0.156647 */ + 18886, /* B0 = 0.576385 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ }, }; static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf) @@ -9170,33 +10555,33 @@ if (jf->filter > 3) { return -1; } - if (ixj_WriteDSPCommand(0x5154 + jf->filter, j)) // Select Filter + if (ixj_WriteDSPCommand(0x5154 + jf->filter, j)) /* Select Filter */ return -1; if (!jf->enable) { - if (ixj_WriteDSPCommand(0x5152, j)) // Disable Filter + if (ixj_WriteDSPCommand(0x5152, j)) /* Disable Filter */ return -1; else return 0; } else { - if (ixj_WriteDSPCommand(0x5153, j)) // Enable Filter + if (ixj_WriteDSPCommand(0x5153, j)) /* Enable Filter */ return -1; - // Select the filter (f0 - f3) to use. + /* Select the filter (f0 - f3) to use. */ if (ixj_WriteDSPCommand(0x5154 + jf->filter, j)) return -1; } if (jf->freq < 12 && jf->freq > 3) { - // Select the frequency for the selected filter. + /* Select the frequency for the selected filter. */ if (ixj_WriteDSPCommand(0x5170 + jf->freq, j)) return -1; } else if (jf->freq > 11) { - // We need to load a programmable filter set for undefined - // frequencies. So we will point the filter to a programmable set. - // Since there are only 4 filters and 4 programmable sets, we will - // just point the filter to the same number set and program it for the - // frequency we want. + /* We need to load a programmable filter set for undefined */ + /* frequencies. So we will point the filter to a programmable set. */ + /* Since there are only 4 filters and 4 programmable sets, we will */ + /* just point the filter to the same number set and program it for the */ + /* frequency we want. */ if (ixj_WriteDSPCommand(0x5170 + jf->filter, j)) return -1; if (j->ver.low != 0x12) { @@ -9217,6 +10602,52 @@ return 0; } +static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr) +{ + unsigned short cmd; + int cnt, max; + if (jfr->filter > 3) { + return -1; + } + if (ixj_WriteDSPCommand(0x5154 + jfr->filter, j)) /* Select Filter */ + return -1; + + if (!jfr->enable) { + if (ixj_WriteDSPCommand(0x5152, j)) /* Disable Filter */ + return -1; + else + return 0; + } else { + if (ixj_WriteDSPCommand(0x5153, j)) /* Enable Filter */ + return -1; + /* Select the filter (f0 - f3) to use. */ + if (ixj_WriteDSPCommand(0x5154 + jfr->filter, j)) + return -1; + } + /* We need to load a programmable filter set for undefined */ + /* frequencies. So we will point the filter to a programmable set. */ + /* Since there are only 4 filters and 4 programmable sets, we will */ + /* just point the filter to the same number set and program it for the */ + /* frequency we want. */ + if (ixj_WriteDSPCommand(0x5170 + jfr->filter, j)) + return -1; + if (j->ver.low != 0x12) { + cmd = 0x515B; + max = 19; + } else { + cmd = 0x515E; + max = 15; + } + if (ixj_WriteDSPCommand(cmd, j)) + return -1; + for (cnt = 0; cnt < max; cnt++) { + if (ixj_WriteDSPCommand(jfr->coeff[cnt], j)) + return -1; + } + j->filter_en[jfr->filter] = jfr->enable; + return 0; +} + static int ixj_init_tone(IXJ *j, IXJ_TONE * ti) { int freq0, freq1; @@ -9237,7 +10668,7 @@ { if (ixj_WriteDSPCommand(0x6800 + ti->tone_index, j)) return -1; - if (ixj_WriteDSPCommand(0x6000 + (ti->gain0 << 4) + ti->gain1, j)) + if (ixj_WriteDSPCommand(0x6000 + (ti->gain1 << 4) + ti->gain0, j)) return -1; data = freq0; if (ixj_WriteDSPCommand(data, j)) @@ -9248,3 +10679,4 @@ } return freq0; } + diff -u --recursive --new-file v2.4.9/linux/drivers/telephony/ixj.h linux/drivers/telephony/ixj.h --- v2.4.9/linux/drivers/telephony/ixj.h Mon Aug 27 12:41:45 2001 +++ linux/drivers/telephony/ixj.h Fri Sep 7 09:28:37 2001 @@ -1,10 +1,13 @@ /****************************************************************************** * ixj.h * - * Device Driver for the Internet PhoneJACK and - * Internet LineJACK Telephony Cards. * - * (c) Copyright 1999 Quicknet Technologies, Inc. + * Device Driver for Quicknet Technologies, Inc.'s Telephony cards + * including the Internet PhoneJACK, Internet PhoneJACK Lite, + * Internet PhoneJACK PCI, Internet LineJACK, Internet PhoneCARD and + * SmartCABLE + * + * (c) Copyright 1999-2001 Quicknet Technologies, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -35,11 +38,11 @@ * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * *****************************************************************************/ -static char ixj_h_rcsid[] = "$Id: ixj.h,v 3.14 2000/03/30 22:06:48 eokerson Exp $"; +static char ixj_h_rcsid[] = "$Id: ixj.h,v 4.1 2001/08/04 14:49:27 craigs Exp $"; -#ifndef _I386_TYPES_H -#include -#endif +#define IXJ_VERSION 3031 + +#include #include #include @@ -49,11 +52,20 @@ typedef __u8 BYTE; typedef __u8 BOOL; +#ifndef IXJMAX #define IXJMAX 16 +#endif #define TRUE 1 #define FALSE 0 +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + /****************************************************************************** * * This structure when unioned with the structures below makes simple byte @@ -225,13 +237,13 @@ unsigned int led2:1; unsigned int led3:1; unsigned int led4:1; -} PSCRWI; // Internet LineJACK and Internet PhoneJACK Lite +} PSCRWI; /* Internet LineJACK and Internet PhoneJACK Lite */ typedef struct { unsigned int eidp:1; unsigned int eisd:1; unsigned int x:6; -} PSCRWP; // Internet PhoneJACK PCI +} PSCRWP; /* Internet PhoneJACK PCI */ typedef union { PSCRWI bits; @@ -355,15 +367,15 @@ * ******************************************************************************/ typedef struct { - unsigned int x0:4; // unused bits + unsigned int x0:4; /* unused bits */ - unsigned int ed:1; // Event Detect + unsigned int ed:1; /* Event Detect */ - unsigned int drf:1; // Smart Cable Removal Flag 1=no cable + unsigned int drf:1; /* SmartCABLE Removal Flag 1=no cable */ - unsigned int dspf:1; // DSP Flag 1=DSP Ready + unsigned int dspf:1; /* DSP Flag 1=DSP Ready */ - unsigned int crr:1; // Control Register Ready + unsigned int crr:1; /* Control Register Ready */ } COMMAND_REG1; @@ -373,13 +385,13 @@ } PCMCIA_CR1; typedef struct { - unsigned int x0:4; // unused bits + unsigned int x0:4; /* unused bits */ - unsigned int rstc:1; // Smart Cable Reset + unsigned int rstc:1; /* SmartCABLE Reset */ - unsigned int pwr:1; // Smart Cable Power + unsigned int pwr:1; /* SmartCABLE Power */ - unsigned int x1:2; // unused bits + unsigned int x1:2; /* unused bits */ } COMMAND_REG2; @@ -389,11 +401,11 @@ } PCMCIA_CR2; typedef struct { - unsigned int addr:5; // R/W Smart Cable Register Address + unsigned int addr:5; /* R/W SmartCABLE Register Address */ - unsigned int rw:1; // Read / Write flag + unsigned int rw:1; /* Read / Write flag */ - unsigned int dev:2; // 2 bit Smart Cable Device Address + unsigned int dev:2; /* 2 bit SmartCABLE Device Address */ } CONTROL_REG; @@ -419,19 +431,19 @@ } PCMCIA_SLIC; typedef struct { - unsigned int cpd:1; // Chip Power Down + unsigned int cpd:1; /* Chip Power Down */ - unsigned int mpd:1; // MIC Bias Power Down + unsigned int mpd:1; /* MIC Bias Power Down */ - unsigned int hpd:1; // Handset Drive Power Down + unsigned int hpd:1; /* Handset Drive Power Down */ - unsigned int lpd:1; // Line Drive Power Down + unsigned int lpd:1; /* Line Drive Power Down */ - unsigned int spd:1; // Speaker Drive Power Down + unsigned int spd:1; /* Speaker Drive Power Down */ - unsigned int x:2; // unused bits + unsigned int x:2; /* unused bits */ - unsigned int sr:1; // Software Reset + unsigned int sr:1; /* Software Reset */ } Si3CONTROL1; @@ -441,17 +453,17 @@ } Si3C1; typedef struct { - unsigned int al:1; // Analog Loopback DAC analog -> ADC analog + unsigned int al:1; /* Analog Loopback DAC analog -> ADC analog */ - unsigned int dl2:1; // Digital Loopback DAC -> ADC one bit + unsigned int dl2:1; /* Digital Loopback DAC -> ADC one bit */ - unsigned int dl1:1; // Digital Loopback ADC -> DAC one bit + unsigned int dl1:1; /* Digital Loopback ADC -> DAC one bit */ - unsigned int pll:1; // 1 = div 10, 0 = div 5 + unsigned int pll:1; /* 1 = div 10, 0 = div 5 */ - unsigned int hpd:1; // HPF disable + unsigned int hpd:1; /* HPF disable */ - unsigned int x:3; // unused bits + unsigned int x:3; /* unused bits */ } Si3CONTROL2; @@ -461,17 +473,17 @@ } Si3C2; typedef struct { - unsigned int iir:1; // 1 enables IIR, 0 enables FIR + unsigned int iir:1; /* 1 enables IIR, 0 enables FIR */ - unsigned int him:1; // Handset Input Mute + unsigned int him:1; /* Handset Input Mute */ - unsigned int mcm:1; // MIC In Mute + unsigned int mcm:1; /* MIC In Mute */ - unsigned int mcg:2; // MIC In Gain + unsigned int mcg:2; /* MIC In Gain */ - unsigned int lim:1; // Line In Mute + unsigned int lim:1; /* Line In Mute */ - unsigned int lig:2; // Line In Gain + unsigned int lig:2; /* Line In Gain */ } Si3RXGAIN; @@ -481,13 +493,13 @@ } Si3RXG; typedef struct { - unsigned int hom:1; // Handset Out Mute + unsigned int hom:1; /* Handset Out Mute */ - unsigned int lom:1; // Line Out Mute + unsigned int lom:1; /* Line Out Mute */ - unsigned int rxg:5; // RX PGA Gain + unsigned int rxg:5; /* RX PGA Gain */ - unsigned int x:1; // unused bit + unsigned int x:1; /* unused bit */ } Si3ADCVOLUME; @@ -497,13 +509,13 @@ } Si3ADC; typedef struct { - unsigned int srm:1; // Speaker Right Mute + unsigned int srm:1; /* Speaker Right Mute */ - unsigned int slm:1; // Speaker Left Mute + unsigned int slm:1; /* Speaker Left Mute */ - unsigned int txg:5; // TX PGA Gain + unsigned int txg:5; /* TX PGA Gain */ - unsigned int x:1; // unused bit + unsigned int x:1; /* unused bit */ } Si3DACVOLUME; @@ -513,13 +525,13 @@ } Si3DAC; typedef struct { - unsigned int x:5; // unused bit + unsigned int x:5; /* unused bit */ - unsigned int losc:1; // Line Out Short Circuit + unsigned int losc:1; /* Line Out Short Circuit */ - unsigned int srsc:1; // Speaker Right Short Circuit + unsigned int srsc:1; /* Speaker Right Short Circuit */ - unsigned int slsc:1; // Speaker Left Short Circuit + unsigned int slsc:1; /* Speaker Left Short Circuit */ } Si3STATUSREPORT; @@ -529,11 +541,11 @@ } Si3STAT; typedef struct { - unsigned int sot:2; // Speaker Out Attenuation + unsigned int sot:2; /* Speaker Out Attenuation */ - unsigned int lot:2; // Line Out Attenuation + unsigned int lot:2; /* Line Out Attenuation */ - unsigned int x:4; // unused bits + unsigned int x:4; /* unused bits */ } Si3ANALOGATTN; @@ -549,149 +561,149 @@ ******************************************************************************/ typedef struct _DAA_REGS { - //----------------------------------------------- - // SOP Registers - // + /*----------------------------------------------- */ + /* SOP Registers */ + /* */ BYTE bySOP; union _SOP_REGS { struct _SOP { - union // SOP - CR0 Register + union /* SOP - CR0 Register */ { BYTE reg; struct _CR0_BITREGS { - BYTE CLK_EXT:1; // cr0[0:0] + BYTE CLK_EXT:1; /* cr0[0:0] */ - BYTE RIP:1; // cr0[1:1] + BYTE RIP:1; /* cr0[1:1] */ - BYTE AR:1; // cr0[2:2] + BYTE AR:1; /* cr0[2:2] */ - BYTE AX:1; // cr0[3:3] + BYTE AX:1; /* cr0[3:3] */ - BYTE FRR:1; // cr0[4:4] + BYTE FRR:1; /* cr0[4:4] */ - BYTE FRX:1; // cr0[5:5] + BYTE FRX:1; /* cr0[5:5] */ - BYTE IM:1; // cr0[6:6] + BYTE IM:1; /* cr0[6:6] */ - BYTE TH:1; // cr0[7:7] + BYTE TH:1; /* cr0[7:7] */ } bitreg; } cr0; - union // SOP - CR1 Register + union /* SOP - CR1 Register */ { BYTE reg; struct _CR1_REGS { - BYTE RM:1; // cr1[0:0] + BYTE RM:1; /* cr1[0:0] */ - BYTE RMR:1; // cr1[1:1] + BYTE RMR:1; /* cr1[1:1] */ - BYTE No_auto:1; // cr1[2:2] + BYTE No_auto:1; /* cr1[2:2] */ - BYTE Pulse:1; // cr1[3:3] + BYTE Pulse:1; /* cr1[3:3] */ - BYTE P_Tone1:1; // cr1[4:4] + BYTE P_Tone1:1; /* cr1[4:4] */ - BYTE P_Tone2:1; // cr1[5:5] + BYTE P_Tone2:1; /* cr1[5:5] */ - BYTE E_Tone1:1; // cr1[6:6] + BYTE E_Tone1:1; /* cr1[6:6] */ - BYTE E_Tone2:1; // cr1[7:7] + BYTE E_Tone2:1; /* cr1[7:7] */ } bitreg; } cr1; - union // SOP - CR2 Register + union /* SOP - CR2 Register */ { BYTE reg; struct _CR2_REGS { - BYTE Call_II:1; // CR2[0:0] + BYTE Call_II:1; /* CR2[0:0] */ - BYTE Call_I:1; // CR2[1:1] + BYTE Call_I:1; /* CR2[1:1] */ - BYTE Call_en:1; // CR2[2:2] + BYTE Call_en:1; /* CR2[2:2] */ - BYTE Call_pon:1; // CR2[3:3] + BYTE Call_pon:1; /* CR2[3:3] */ - BYTE IDR:1; // CR2[4:4] + BYTE IDR:1; /* CR2[4:4] */ - BYTE COT_R:3; // CR2[5:7] + BYTE COT_R:3; /* CR2[5:7] */ } bitreg; } cr2; - union // SOP - CR3 Register + union /* SOP - CR3 Register */ { BYTE reg; struct _CR3_REGS { - BYTE DHP_X:1; // CR3[0:0] + BYTE DHP_X:1; /* CR3[0:0] */ - BYTE DHP_R:1; // CR3[1:1] + BYTE DHP_R:1; /* CR3[1:1] */ - BYTE Cal_pctl:1; // CR3[2:2] + BYTE Cal_pctl:1; /* CR3[2:2] */ - BYTE SEL:1; // CR3[3:3] + BYTE SEL:1; /* CR3[3:3] */ - BYTE TestLoops:4; // CR3[4:7] + BYTE TestLoops:4; /* CR3[4:7] */ } bitreg; } cr3; - union // SOP - CR4 Register + union /* SOP - CR4 Register */ { BYTE reg; struct _CR4_REGS { - BYTE Fsc_en:1; // CR4[0:0] + BYTE Fsc_en:1; /* CR4[0:0] */ - BYTE Int_en:1; // CR4[1:1] + BYTE Int_en:1; /* CR4[1:1] */ - BYTE AGX:2; // CR4[2:3] + BYTE AGX:2; /* CR4[2:3] */ - BYTE AGR_R:2; // CR4[4:5] + BYTE AGR_R:2; /* CR4[4:5] */ - BYTE AGR_Z:2; // CR4[6:7] + BYTE AGR_Z:2; /* CR4[6:7] */ } bitreg; } cr4; - union // SOP - CR5 Register + union /* SOP - CR5 Register */ { BYTE reg; struct _CR5_REGS { - BYTE V_0:1; // CR5[0:0] + BYTE V_0:1; /* CR5[0:0] */ - BYTE V_1:1; // CR5[1:1] + BYTE V_1:1; /* CR5[1:1] */ - BYTE V_2:1; // CR5[2:2] + BYTE V_2:1; /* CR5[2:2] */ - BYTE V_3:1; // CR5[3:3] + BYTE V_3:1; /* CR5[3:3] */ - BYTE V_4:1; // CR5[4:4] + BYTE V_4:1; /* CR5[4:4] */ - BYTE V_5:1; // CR5[5:5] + BYTE V_5:1; /* CR5[5:5] */ - BYTE V_6:1; // CR5[6:6] + BYTE V_6:1; /* CR5[6:6] */ - BYTE V_7:1; // CR5[7:7] + BYTE V_7:1; /* CR5[7:7] */ } bitreg; } cr5; - union // SOP - CR6 Register + union /* SOP - CR6 Register */ { BYTE reg; struct _CR6_REGS { - BYTE reserved:8; // CR6[0:7] + BYTE reserved:8; /* CR6[0:7] */ } bitreg; } cr6; - union // SOP - CR7 Register + union /* SOP - CR7 Register */ { BYTE reg; struct _CR7_REGS { - BYTE reserved:8; // CR7[0:7] + BYTE reserved:8; /* CR7[0:7] */ } bitreg; } cr7; @@ -701,184 +713,184 @@ } SOP_REGS; - // DAA_REGS.SOP_REGS.SOP.CR5.reg - // DAA_REGS.SOP_REGS.SOP.CR5.bitreg - // DAA_REGS.SOP_REGS.SOP.CR5.bitreg.V_2 - // DAA_REGS.SOP_REGS.ByteRegs[5] - - //----------------------------------------------- - // XOP Registers - // + /* DAA_REGS.SOP_REGS.SOP.CR5.reg */ + /* DAA_REGS.SOP_REGS.SOP.CR5.bitreg */ + /* DAA_REGS.SOP_REGS.SOP.CR5.bitreg.V_2 */ + /* DAA_REGS.SOP_REGS.ByteRegs[5] */ + + /*----------------------------------------------- */ + /* XOP Registers */ + /* */ BYTE byXOP; union _XOP_REGS { struct _XOP { - union // XOP - XR0 Register - Read values + union XOPXR0/* XOP - XR0 Register - Read values */ { BYTE reg; struct _XR0_BITREGS { - BYTE SI_0:1; // XR0[0:0] - Read + BYTE SI_0:1; /* XR0[0:0] - Read */ - BYTE SI_1:1; // XR0[1:1] - Read + BYTE SI_1:1; /* XR0[1:1] - Read */ - BYTE VDD_OK:1; // XR0[2:2] - Read + BYTE VDD_OK:1; /* XR0[2:2] - Read */ - BYTE Caller_ID:1; // XR0[3:3] - Read + BYTE Caller_ID:1; /* XR0[3:3] - Read */ - BYTE RING:1; // XR0[4:4] - Read + BYTE RING:1; /* XR0[4:4] - Read */ - BYTE Cadence:1; // XR0[5:5] - Read + BYTE Cadence:1; /* XR0[5:5] - Read */ - BYTE Wake_up:1; // XR0[6:6] - Read + BYTE Wake_up:1; /* XR0[6:6] - Read */ - BYTE unused:1; // XR0[7:7] - Read + BYTE RMR:1; /* XR0[7:7] - Read */ } bitreg; } xr0; - union // XOP - XR1 Register + union /* XOP - XR1 Register */ { BYTE reg; struct _XR1_BITREGS { - BYTE M_SI_0:1; // XR1[0:0] + BYTE M_SI_0:1; /* XR1[0:0] */ - BYTE M_SI_1:1; // XR1[1:1] + BYTE M_SI_1:1; /* XR1[1:1] */ - BYTE M_VDD_OK:1; // XR1[2:2] + BYTE M_VDD_OK:1; /* XR1[2:2] */ - BYTE M_Caller_ID:1; // XR1[3:3] + BYTE M_Caller_ID:1; /* XR1[3:3] */ - BYTE M_RING:1; // XR1[4:4] + BYTE M_RING:1; /* XR1[4:4] */ - BYTE M_Cadence:1; // XR1[5:5] + BYTE M_Cadence:1; /* XR1[5:5] */ - BYTE M_Wake_up:1; // XR1[6:6] + BYTE M_Wake_up:1; /* XR1[6:6] */ - BYTE unused:1; // XR1[7:7] + BYTE unused:1; /* XR1[7:7] */ } bitreg; } xr1; - union // XOP - XR2 Register + union /* XOP - XR2 Register */ { BYTE reg; struct _XR2_BITREGS { - BYTE CTO0:1; // XR2[0:0] + BYTE CTO0:1; /* XR2[0:0] */ - BYTE CTO1:1; // XR2[1:1] + BYTE CTO1:1; /* XR2[1:1] */ - BYTE CTO2:1; // XR2[2:2] + BYTE CTO2:1; /* XR2[2:2] */ - BYTE CTO3:1; // XR2[3:3] + BYTE CTO3:1; /* XR2[3:3] */ - BYTE CTO4:1; // XR2[4:4] + BYTE CTO4:1; /* XR2[4:4] */ - BYTE CTO5:1; // XR2[5:5] + BYTE CTO5:1; /* XR2[5:5] */ - BYTE CTO6:1; // XR2[6:6] + BYTE CTO6:1; /* XR2[6:6] */ - BYTE CTO7:1; // XR2[7:7] + BYTE CTO7:1; /* XR2[7:7] */ } bitreg; } xr2; - union // XOP - XR3 Register + union /* XOP - XR3 Register */ { BYTE reg; struct _XR3_BITREGS { - BYTE DCR0:1; // XR3[0:0] + BYTE DCR0:1; /* XR3[0:0] */ - BYTE DCR1:1; // XR3[1:1] + BYTE DCR1:1; /* XR3[1:1] */ - BYTE DCI:1; // XR3[2:2] + BYTE DCI:1; /* XR3[2:2] */ - BYTE DCU0:1; // XR3[3:3] + BYTE DCU0:1; /* XR3[3:3] */ - BYTE DCU1:1; // XR3[4:4] + BYTE DCU1:1; /* XR3[4:4] */ - BYTE B_off:1; // XR3[5:5] + BYTE B_off:1; /* XR3[5:5] */ - BYTE AGB0:1; // XR3[6:6] + BYTE AGB0:1; /* XR3[6:6] */ - BYTE AGB1:1; // XR3[7:7] + BYTE AGB1:1; /* XR3[7:7] */ } bitreg; } xr3; - union // XOP - XR4 Register + union /* XOP - XR4 Register */ { BYTE reg; struct _XR4_BITREGS { - BYTE C_0:1; // XR4[0:0] + BYTE C_0:1; /* XR4[0:0] */ - BYTE C_1:1; // XR4[1:1] + BYTE C_1:1; /* XR4[1:1] */ - BYTE C_2:1; // XR4[2:2] + BYTE C_2:1; /* XR4[2:2] */ - BYTE C_3:1; // XR4[3:3] + BYTE C_3:1; /* XR4[3:3] */ - BYTE C_4:1; // XR4[4:4] + BYTE C_4:1; /* XR4[4:4] */ - BYTE C_5:1; // XR4[5:5] + BYTE C_5:1; /* XR4[5:5] */ - BYTE C_6:1; // XR4[6:6] + BYTE C_6:1; /* XR4[6:6] */ - BYTE C_7:1; // XR4[7:7] + BYTE C_7:1; /* XR4[7:7] */ } bitreg; } xr4; - union // XOP - XR5 Register + union /* XOP - XR5 Register */ { BYTE reg; struct _XR5_BITREGS { - BYTE T_0:1; // XR5[0:0] + BYTE T_0:1; /* XR5[0:0] */ - BYTE T_1:1; // XR5[1:1] + BYTE T_1:1; /* XR5[1:1] */ - BYTE T_2:1; // XR5[2:2] + BYTE T_2:1; /* XR5[2:2] */ - BYTE T_3:1; // XR5[3:3] + BYTE T_3:1; /* XR5[3:3] */ - BYTE T_4:1; // XR5[4:4] + BYTE T_4:1; /* XR5[4:4] */ - BYTE T_5:1; // XR5[5:5] + BYTE T_5:1; /* XR5[5:5] */ - BYTE T_6:1; // XR5[6:6] + BYTE T_6:1; /* XR5[6:6] */ - BYTE T_7:1; // XR5[7:7] + BYTE T_7:1; /* XR5[7:7] */ } bitreg; } xr5; - union // XOP - XR6 Register - Read Values + union /* XOP - XR6 Register - Read Values */ { BYTE reg; struct _XR6_BITREGS { - BYTE CPS0:1; // XR6[0:0] + BYTE CPS0:1; /* XR6[0:0] */ - BYTE CPS1:1; // XR6[1:1] + BYTE CPS1:1; /* XR6[1:1] */ - BYTE unused1:2; // XR6[2:3] + BYTE unused1:2; /* XR6[2:3] */ - BYTE CLK_OFF:1; // XR6[4:4] + BYTE CLK_OFF:1; /* XR6[4:4] */ - BYTE unused2:3; // XR6[5:7] + BYTE unused2:3; /* XR6[5:7] */ } bitreg; } xr6; - union // XOP - XR7 Register + union /* XOP - XR7 Register */ { BYTE reg; struct _XR7_BITREGS { - BYTE unused1:1; // XR7[0:0] + BYTE unused1:1; /* XR7[0:0] */ - BYTE Vdd0:1; // XR7[1:1] + BYTE Vdd0:1; /* XR7[1:1] */ - BYTE Vdd1:1; // XR7[2:2] + BYTE Vdd1:1; /* XR7[2:2] */ - BYTE unused2:5; // XR7[3:7] + BYTE unused2:5; /* XR7[3:7] */ } bitreg; } xr7; @@ -888,49 +900,49 @@ } XOP_REGS; - // DAA_REGS.XOP_REGS.XOP.XR7.reg - // DAA_REGS.XOP_REGS.XOP.XR7.bitreg - // DAA_REGS.XOP_REGS.XOP.XR7.bitreg.Vdd0 - // DAA_REGS.XOP_REGS.ByteRegs[7] - - //----------------------------------------------- - // COP Registers - // + /* DAA_REGS.XOP_REGS.XOP.XR7.reg */ + /* DAA_REGS.XOP_REGS.XOP.XR7.bitreg */ + /* DAA_REGS.XOP_REGS.XOP.XR7.bitreg.Vdd0 */ + /* DAA_REGS.XOP_REGS.ByteRegs[7] */ + + /*----------------------------------------------- */ + /* COP Registers */ + /* */ BYTE byCOP; union _COP_REGS { struct _COP { - BYTE THFilterCoeff_1[8]; // COP - TH Filter Coefficients, CODE=0, Part 1 + BYTE THFilterCoeff_1[8]; /* COP - TH Filter Coefficients, CODE=0, Part 1 */ - BYTE THFilterCoeff_2[8]; // COP - TH Filter Coefficients, CODE=1, Part 2 + BYTE THFilterCoeff_2[8]; /* COP - TH Filter Coefficients, CODE=1, Part 2 */ - BYTE THFilterCoeff_3[8]; // COP - TH Filter Coefficients, CODE=2, Part 3 + BYTE THFilterCoeff_3[8]; /* COP - TH Filter Coefficients, CODE=2, Part 3 */ - BYTE RingerImpendance_1[8]; // COP - Ringer Impendance Coefficients, CODE=3, Part 1 + BYTE RingerImpendance_1[8]; /* COP - Ringer Impendance Coefficients, CODE=3, Part 1 */ - BYTE IMFilterCoeff_1[8]; // COP - IM Filter Coefficients, CODE=4, Part 1 + BYTE IMFilterCoeff_1[8]; /* COP - IM Filter Coefficients, CODE=4, Part 1 */ - BYTE IMFilterCoeff_2[8]; // COP - IM Filter Coefficients, CODE=5, Part 2 + BYTE IMFilterCoeff_2[8]; /* COP - IM Filter Coefficients, CODE=5, Part 2 */ - BYTE RingerImpendance_2[8]; // COP - Ringer Impendance Coefficients, CODE=6, Part 2 + BYTE RingerImpendance_2[8]; /* COP - Ringer Impendance Coefficients, CODE=6, Part 2 */ - BYTE FRRFilterCoeff[8]; // COP - FRR Filter Coefficients, CODE=7 + BYTE FRRFilterCoeff[8]; /* COP - FRR Filter Coefficients, CODE=7 */ - BYTE FRXFilterCoeff[8]; // COP - FRX Filter Coefficients, CODE=8 + BYTE FRXFilterCoeff[8]; /* COP - FRX Filter Coefficients, CODE=8 */ - BYTE ARFilterCoeff[4]; // COP - AR Filter Coefficients, CODE=9 + BYTE ARFilterCoeff[4]; /* COP - AR Filter Coefficients, CODE=9 */ - BYTE AXFilterCoeff[4]; // COP - AX Filter Coefficients, CODE=10 + BYTE AXFilterCoeff[4]; /* COP - AX Filter Coefficients, CODE=10 */ - BYTE Tone1Coeff[4]; // COP - Tone1 Coefficients, CODE=11 + BYTE Tone1Coeff[4]; /* COP - Tone1 Coefficients, CODE=11 */ - BYTE Tone2Coeff[4]; // COP - Tone2 Coefficients, CODE=12 + BYTE Tone2Coeff[4]; /* COP - Tone2 Coefficients, CODE=12 */ - BYTE LevelmeteringRinging[4]; // COP - Levelmetering Ringing, CODE=13 + BYTE LevelmeteringRinging[4]; /* COP - Levelmetering Ringing, CODE=13 */ - BYTE CallerID1stTone[8]; // COP - Caller ID 1st Tone, CODE=14 + BYTE CallerID1stTone[8]; /* COP - Caller ID 1st Tone, CODE=14 */ - BYTE CallerID2ndTone[8]; // COP - Caller ID 2nd Tone, CODE=15 + BYTE CallerID2ndTone[8]; /* COP - Caller ID 2nd Tone, CODE=15 */ } COP; @@ -938,49 +950,49 @@ } COP_REGS; - // DAA_REGS.COP_REGS.COP.XR7.Tone1Coeff[3] - // DAA_REGS.COP_REGS.COP.XR7.bitreg - // DAA_REGS.COP_REGS.COP.XR7.bitreg.Vdd0 - // DAA_REGS.COP_REGS.ByteRegs[57] - - //----------------------------------------------- - // CAO Registers - // + /* DAA_REGS.COP_REGS.COP.XR7.Tone1Coeff[3] */ + /* DAA_REGS.COP_REGS.COP.XR7.bitreg */ + /* DAA_REGS.COP_REGS.COP.XR7.bitreg.Vdd0 */ + /* DAA_REGS.COP_REGS.ByteRegs[57] */ + + /*----------------------------------------------- */ + /* CAO Registers */ + /* */ BYTE byCAO; union _CAO_REGS { struct _CAO { - BYTE CallerID[512]; // CAO - Caller ID Bytes + BYTE CallerID[512]; /* CAO - Caller ID Bytes */ } CAO; BYTE ByteRegs[sizeof(struct _CAO)]; } CAO_REGS; - union // XOP - XR0 Register - Write values + union /* XOP - XR0 Register - Write values */ { BYTE reg; struct _XR0_BITREGSW { - BYTE SO_0:1; // XR1[0:0] - Write + BYTE SO_0:1; /* XR1[0:0] - Write */ - BYTE SO_1:1; // XR1[1:1] - Write + BYTE SO_1:1; /* XR1[1:1] - Write */ - BYTE SO_2:1; // XR1[2:2] - Write + BYTE SO_2:1; /* XR1[2:2] - Write */ - BYTE unused:5; // XR1[3:7] - Write + BYTE unused:5; /* XR1[3:7] - Write */ } bitreg; } XOP_xr0_W; - union // XOP - XR6 Register - Write values + union /* XOP - XR6 Register - Write values */ { BYTE reg; struct _XR6_BITREGSW { - BYTE unused1:4; // XR6[0:3] + BYTE unused1:4; /* XR6[0:3] */ - BYTE CLK_OFF:1; // XR6[4:4] + BYTE CLK_OFF:1; /* XR6[4:4] */ - BYTE unused2:3; // XR6[5:7] + BYTE unused2:3; /* XR6[5:7] */ } bitreg; } XOP_xr6_W; @@ -990,35 +1002,36 @@ #define ALISDAA_ID_BYTE 0x81 #define ALISDAA_CALLERID_SIZE 512 -//------------------------------ -// -// Misc definitions -// +/*------------------------------ */ +/* */ +/* Misc definitions */ +/* */ -// Power Up Operation +/* Power Up Operation */ #define SOP_PU_SLEEP 0 #define SOP_PU_RINGING 1 #define SOP_PU_CONVERSATION 2 #define SOP_PU_PULSEDIALING 3 +#define SOP_PU_RESET 4 #define ALISDAA_CALLERID_SIZE 512 -#define PLAYBACK_MODE_COMPRESSED 0 // Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 -#define PLAYBACK_MODE_TRUESPEECH_V40 0 // Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps -#define PLAYBACK_MODE_TRUESPEECH 8 // Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps Version 5.1 -#define PLAYBACK_MODE_ULAW 2 // Selects: 64 Kbit/sec MuA-law PCM -#define PLAYBACK_MODE_ALAW 10 // Selects: 64 Kbit/sec A-law PCM -#define PLAYBACK_MODE_16LINEAR 6 // Selects: 128 Kbit/sec 16-bit linear -#define PLAYBACK_MODE_8LINEAR 4 // Selects: 64 Kbit/sec 8-bit signed linear -#define PLAYBACK_MODE_8LINEAR_WSS 5 // Selects: 64 Kbit/sec WSS 8-bit unsigned linear - -#define RECORD_MODE_COMPRESSED 0 // Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 -#define RECORD_MODE_TRUESPEECH 0 // Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps -#define RECORD_MODE_ULAW 4 // Selects: 64 Kbit/sec Mu-law PCM -#define RECORD_MODE_ALAW 12 // Selects: 64 Kbit/sec A-law PCM -#define RECORD_MODE_16LINEAR 5 // Selects: 128 Kbit/sec 16-bit linear -#define RECORD_MODE_8LINEAR 6 // Selects: 64 Kbit/sec 8-bit signed linear -#define RECORD_MODE_8LINEAR_WSS 7 // Selects: 64 Kbit/sec WSS 8-bit unsigned linear +#define PLAYBACK_MODE_COMPRESSED 0 /* Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 */ +#define PLAYBACK_MODE_TRUESPEECH_V40 0 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps */ +#define PLAYBACK_MODE_TRUESPEECH 8 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps Version 5.1 */ +#define PLAYBACK_MODE_ULAW 2 /* Selects: 64 Kbit/sec MuA-law PCM */ +#define PLAYBACK_MODE_ALAW 10 /* Selects: 64 Kbit/sec A-law PCM */ +#define PLAYBACK_MODE_16LINEAR 6 /* Selects: 128 Kbit/sec 16-bit linear */ +#define PLAYBACK_MODE_8LINEAR 4 /* Selects: 64 Kbit/sec 8-bit signed linear */ +#define PLAYBACK_MODE_8LINEAR_WSS 5 /* Selects: 64 Kbit/sec WSS 8-bit unsigned linear */ + +#define RECORD_MODE_COMPRESSED 0 /* Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 */ +#define RECORD_MODE_TRUESPEECH 0 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps */ +#define RECORD_MODE_ULAW 4 /* Selects: 64 Kbit/sec Mu-law PCM */ +#define RECORD_MODE_ALAW 12 /* Selects: 64 Kbit/sec A-law PCM */ +#define RECORD_MODE_16LINEAR 5 /* Selects: 128 Kbit/sec 16-bit linear */ +#define RECORD_MODE_8LINEAR 6 /* Selects: 64 Kbit/sec 8-bit signed linear */ +#define RECORD_MODE_8LINEAR_WSS 7 /* Selects: 64 Kbit/sec WSS 8-bit unsigned linear */ enum SLIC_STATES { PLD_SLIC_STATE_OC = 0, @@ -1074,36 +1087,39 @@ char enable; char en_filter; unsigned int filter; - unsigned int state; // State 0 when cadence has not started. + unsigned int state; /* State 0 when cadence has not started. */ - unsigned int on1; // State 1 + unsigned int on1; /* State 1 */ - unsigned long on1min; // State 1 - 10% + jiffies - unsigned long on1dot; // State 1 + jiffies + unsigned long on1min; /* State 1 - 10% + jiffies */ + unsigned long on1dot; /* State 1 + jiffies */ - unsigned long on1max; // State 1 + 10% + jiffies + unsigned long on1max; /* State 1 + 10% + jiffies */ - unsigned int off1; // State 2 + unsigned int off1; /* State 2 */ unsigned long off1min; + unsigned long off1dot; /* State 2 + jiffies */ unsigned long off1max; - unsigned int on2; // State 3 + unsigned int on2; /* State 3 */ unsigned long on2min; unsigned long on2dot; unsigned long on2max; - unsigned int off2; // State 4 + unsigned int off2; /* State 4 */ unsigned long off2min; + unsigned long off2dot; /* State 4 + jiffies */ unsigned long off2max; - unsigned int on3; // State 5 + unsigned int on3; /* State 5 */ unsigned long on3min; unsigned long on3dot; unsigned long on3max; - unsigned int off3; // State 6 + unsigned int off3; /* State 6 */ unsigned long off3min; + unsigned long off3dot; /* State 6 + jiffies */ unsigned long off3max; } IXJ_CADENCE_F; @@ -1122,68 +1138,92 @@ unsigned int pots_pstn:1; unsigned int g729_loaded:1; unsigned int ts85_loaded:1; - unsigned int dtmf_oob:1; // DTMF Out-Of-Band + unsigned int dtmf_oob:1; /* DTMF Out-Of-Band */ - unsigned int pcmciascp:1; // Smart Cable Present + unsigned int pcmciascp:1; /* SmartCABLE Present */ - unsigned int pcmciasct:2; // Smart Cable Type + unsigned int pcmciasct:2; /* SmartCABLE Type */ - unsigned int pcmciastate:3; // Smart Cable Init State + unsigned int pcmciastate:3; /* SmartCABLE Init State */ - unsigned int inwrite:1; // Currently writing + unsigned int inwrite:1; /* Currently writing */ - unsigned int inread:1; // Currently reading + unsigned int inread:1; /* Currently reading */ - unsigned int incheck:1; // Currently checking the smart cable + unsigned int incheck:1; /* Currently checking the SmartCABLE */ - unsigned int cidplay:1; // Currently playing Caller ID + unsigned int cidplay:1; /* Currently playing Caller ID */ - unsigned int cidring:1; // This is the ring for Caller ID + unsigned int cidring:1; /* This is the ring for Caller ID */ - unsigned int cidsent:1; // Caller ID has been sent + unsigned int cidsent:1; /* Caller ID has been sent */ - unsigned int cidcw_ack:1; // Caller ID CW ACK (from CPE) - - unsigned int x:6; // unsed bits + unsigned int cidcw_ack:1; /* Caller ID CW ACK (from CPE) */ + unsigned int firstring:1; /* First ring cadence is complete */ + unsigned int pstncheck:1; /* Currently checking the PSTN Line */ + unsigned int pstn_rmr:1; + unsigned int x:3; /* unsed bits */ } IXJ_FLAGS; /****************************************************************************** * -* This structure represents the Internet PhoneJACK and Internet LineJACK +* This structure holds the state of all of the Quicknet cards * ******************************************************************************/ typedef struct { struct phone_device p; + struct timer_list timer; unsigned int board; unsigned int DSPbase; unsigned int XILINXbase; unsigned int serial; + atomic_t DSPWrite; struct phone_capability caplist[30]; unsigned int caps; - unsigned int country; +#if LINUX_VERSION_CODE < 0x020400 + struct pnp_dev *dev; +#else struct pci_dev *dev; +#endif unsigned int cardtype; unsigned int rec_codec; + unsigned int cid_rec_codec; + unsigned int cid_rec_volume; + unsigned char cid_rec_flag; char rec_mode; unsigned int play_codec; unsigned int cid_play_codec; + unsigned int cid_play_volume; + unsigned char cid_play_flag; char play_mode; IXJ_FLAGS flags; + unsigned int busyflags; unsigned int rec_frame_size; unsigned int play_frame_size; + unsigned int cid_play_frame_size; unsigned int cid_base_frame_size; unsigned long cidcw_wait; int aec_level; + int cid_play_aec_level; int readers, writers; - wait_queue_head_t poll_q; - wait_queue_head_t read_q; +#if LINUX_VERSION_CODE < 0x020400 + struct wait_queue *poll_q; + struct wait_queue *read_q; +#else + wait_queue_head_t poll_q; + wait_queue_head_t read_q; +#endif char *read_buffer, *read_buffer_end; char *read_convert_buffer; unsigned int read_buffer_size; unsigned int read_buffer_ready; - wait_queue_head_t write_q; +#if LINUX_VERSION_CODE < 0x020400 + struct wait_queue *write_q; +#else + wait_queue_head_t write_q; +#endif char *write_buffer, *write_buffer_end; char *write_convert_buffer; unsigned int write_buffer_size; @@ -1200,8 +1240,9 @@ char tone_state; char maxrings; IXJ_CADENCE *cadence_t; + IXJ_CADENCE *cadence_r; int tone_cadence_state; - IXJ_CADENCE_F cadence_f[4]; + IXJ_CADENCE_F cadence_f[6]; DTMF dtmf; CPTF cptf; BYTES dsp; @@ -1236,21 +1277,32 @@ int intercom; int m_hook; int r_hook; + int p_hook; char pstn_envelope; char pstn_cid_intr; unsigned char fskz; unsigned char fskphase; unsigned char fskcnt; + unsigned int cidsize; + unsigned int cidcnt; unsigned pstn_cid_received; PHONE_CID cid; PHONE_CID cid_send; + unsigned long pstn_ring_int; unsigned long pstn_ring_start; unsigned long pstn_ring_stop; unsigned long pstn_winkstart; + unsigned long pstn_last_rmr; + unsigned long pstn_prev_rmr; + unsigned long pots_winkstart; unsigned int winktime; unsigned long flash_end; char port; + char hookstate; union telephony_exception ex; + union telephony_exception ex_sig; + int ixj_signals[35]; + IXJ_SIGDEF sigdef; char daa_mode; char daa_country; unsigned long pstn_sleeptil; @@ -1268,13 +1320,23 @@ unsigned long timerchecks; unsigned long txreadycheck; unsigned long rxreadycheck; + unsigned long statuswait; + unsigned long statuswaitfail; + unsigned long pcontrolwait; + unsigned long pcontrolwaitfail; + unsigned long iscontrolready; + unsigned long iscontrolreadyfail; + unsigned long pstnstatecheck; +#ifdef IXJ_DYN_ALLOC + short *fskdata; +#else short fskdata[8000]; +#endif + int fsksize; int fskdcnt; } IXJ; -int ixj_WriteDSPCommand(unsigned short, IXJ *); - typedef int (*IXJ_REGFUNC) (IXJ * j, unsigned long arg); -int ixj_register(int index, IXJ_REGFUNC regfunc); -int ixj_unregister(int index); +extern IXJ *ixj_pcmcia_probe(unsigned long, unsigned long); + diff -u --recursive --new-file v2.4.9/linux/drivers/telephony/ixj_pcmcia.c linux/drivers/telephony/ixj_pcmcia.c --- v2.4.9/linux/drivers/telephony/ixj_pcmcia.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/telephony/ixj_pcmcia.c Fri Sep 7 09:28:37 2001 @@ -0,0 +1,343 @@ +#include "ixj-ver.h" + +#include + +#include +#include +#include /* printk() */ +#include /* everything... */ +#include /* error codes */ +#include + +#include +#include +#include +#include +#include + +#include "ixj.h" + +/* + * PCMCIA service support for Quicknet cards + */ + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +#else +#define DEBUG(n, args...) +#endif + +typedef struct ixj_info_t { + int ndev; + dev_node_t node; + struct ixj *port; +} ixj_info_t; + +static dev_link_t *ixj_attach(void); +static void ixj_detach(dev_link_t *); +static void ixj_config(dev_link_t * link); +static void ixj_cs_release(u_long arg); +static int ixj_event(event_t event, int priority, event_callback_args_t * args); +static dev_info_t dev_info = "ixj_cs"; +static dev_link_t *dev_list = NULL; + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = + { + func, ret + }; + CardServices(ReportError, handle, &err); +} + +static dev_link_t *ixj_attach(void) +{ + client_reg_t client_reg; + dev_link_t *link; + int ret; + DEBUG(0, "ixj_attach()\n"); + /* Create new ixj device */ + link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + if (!link) + return NULL; + memset(link, 0, sizeof(struct dev_link_t)); + link->release.function = &ixj_cs_release; + link->release.data = (u_long) link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = 3; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); + if (!link->priv) + return NULL; + memset(link->priv, 0, sizeof(struct ixj_info_t)); + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &ixj_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + ixj_detach(link); + return NULL; + } + return link; +} + +static void ixj_detach(dev_link_t * link) +{ + dev_link_t **linkp; + long flags; + int ret; + DEBUG(0, "ixj_detach(0x%p)\n", link); + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + if (*linkp == NULL) + return; + save_flags(flags); + cli(); + if (link->state & DEV_RELEASE_PENDING) { + del_timer(&link->release); + link->state &= ~DEV_RELEASE_PENDING; + } + restore_flags(flags); + if (link->state & DEV_CONFIG) + ixj_cs_release((u_long) link); + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + /* Unlink device structure, free bits */ + *linkp = link->next; + kfree(link->priv); + kfree(link); +} + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed + +#define CFG_CHECK(fn, args...) \ +if (CardServices(fn, args) != 0) goto next_entry + +static void ixj_get_serial(dev_link_t * link, IXJ * j) +{ + client_handle_t handle; + tuple_t tuple; + u_short buf[128]; + char *str; + int last_ret, last_fn, i, place; + handle = link->handle; + DEBUG(0, "ixj_get_serial(0x%p)\n", link); + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 80; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_VERS_1; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + str = (char *) buf; + printk("PCMCIA Version %d.%d\n", str[0], str[1]); + str += 2; + printk("%s", str); + str = str + strlen(str) + 1; + printk(" %s", str); + str = str + strlen(str) + 1; + place = 1; + for (i = strlen(str) - 1; i >= 0; i--) { + switch (str[i]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + j->serial += (str[i] - 48) * place; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + j->serial += (str[i] - 55) * place; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + j->serial += (str[i] - 87) * place; + break; + } + place = place * 0x10; + } + str = str + strlen(str) + 1; + printk(" version %s\n", str); + cs_failed: + return; +} + +static void ixj_config(dev_link_t * link) +{ + IXJ *j; + client_handle_t handle; + ixj_info_t *info; + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + config_info_t conf; + cistpl_cftable_entry_t *cfg = &parse.cftable_entry; + cistpl_cftable_entry_t dflt = + { + 0 + }; + int last_ret, last_fn; + handle = link->handle; + info = link->priv; + DEBUG(0, "ixj_config(0x%p)\n", link); + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CONFIG; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + CS_CHECK(ParseTuple, handle, &tuple, &parse); + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + link->state |= DEV_CONFIG; + CS_CHECK(GetConfigurationInfo, handle, &conf); + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple.Attributes = 0; + CS_CHECK(GetFirstTuple, handle, &tuple); + while (1) { + CFG_CHECK(GetTupleData, handle, &tuple); + CFG_CHECK(ParseTuple, handle, &tuple, &parse); + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->conf.ConfigIndex = cfg->index; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin == 2) { + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + CFG_CHECK(RequestIO, link->handle, &link->io); + /* If we've got this far, we're done */ + break; + } + next_entry: + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + CS_CHECK(GetNextTuple, handle, &tuple); + } + + CS_CHECK(RequestConfiguration, handle, &link->conf); + + /* + * Register the card with the core. + */ + j=ixj_pcmcia_probe(link->io.BasePort1,link->io.BasePort1 + 0x10); + + info->ndev = 1; + info->node.major = PHONE_MAJOR; + link->dev = &info->node; + ixj_get_serial(link, j); + link->state &= ~DEV_CONFIG_PENDING; + return; + cs_failed: + cs_error(link->handle, last_fn, last_ret); + ixj_cs_release((u_long) link); +} + +static void ixj_cs_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *) arg; + ixj_info_t *info = link->priv; + DEBUG(0, "ixj_cs_release(0x%p)\n", link); + info->ndev = 0; + link->dev = NULL; + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + link->state &= ~DEV_CONFIG; +} + +static int ixj_event(event_t event, int priority, event_callback_args_t * args) +{ + dev_link_t *link = args->client_data; + DEBUG(1, "ixj_event(0x%06x)\n", event); + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + link->release.expires = jiffies + (HZ / 20); + link->state |= DEV_RELEASE_PENDING; + add_timer(&link->release); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + ixj_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + return 0; +} + +int __init ixj_register_pcmcia(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "ixj_cs: Card Services release does not match!\n"); + return -EINVAL; + } + register_pcmcia_driver(&dev_info, &ixj_attach, &ixj_detach); + return 0; +} + +static void ixj_pcmcia_unload(void) +{ + DEBUG(0, "ixj_cs: unloading\n"); + unregister_pcmcia_driver(&dev_info); + while (dev_list != NULL) + ixj_detach(dev_list); +} + +module_init(ixj_register_pcmcia); +module_exit(ixj_pcmcia_unload); + +MODULE_LICENSE("GPL"); + diff -u --recursive --new-file v2.4.9/linux/drivers/telephony/phonedev.c linux/drivers/telephony/phonedev.c --- v2.4.9/linux/drivers/telephony/phonedev.c Tue Sep 19 08:31:53 2000 +++ linux/drivers/telephony/phonedev.c Fri Sep 7 09:28:37 2001 @@ -167,5 +167,7 @@ module_init(telephony_init); module_exit(telephony_exit); +MODULE_LICENSE("GPL"); + EXPORT_SYMBOL(phone_register_device); EXPORT_SYMBOL(phone_unregister_device); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.4.9/linux/drivers/usb/Config.in Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/Config.in Sun Sep 2 10:34:36 2001 @@ -32,7 +32,12 @@ if [ "$CONFIG_USB_STORAGE" != "n" ]; then bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG bool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM - bool ' Microtech CompactFlash/SmartMedia reader' CONFIG_USB_STORAGE_DPCM + bool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 + bool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e + bool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 + fi fi dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB @@ -64,10 +69,10 @@ dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB comment 'USB Network adaptors' - dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB CATC NetMate-based Ethernet driver (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL - dep_tristate ' NetChip 1080-based USB Host-to-Host Link (EXPERIMENTAL)' CONFIG_USB_NET1080 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB-to-USB Networking (NetChip, Prolific, ...) (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL comment 'USB port drivers' dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT diff -u --recursive --new-file v2.4.9/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.4.9/linux/drivers/usb/Makefile Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/Makefile Sat Sep 1 11:01:28 2001 @@ -60,16 +60,16 @@ obj-$(CONFIG_USB_MDC800) += mdc800.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_DABUSB) += dabusb.o -obj-$(CONFIG_USB_PLUSB) += plusb.o obj-$(CONFIG_USB_OV511) += ov511.o obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_PEGASUS) += pegasus.o obj-$(CONFIG_USB_CATC) += catc.o +obj-$(CONFIG_USB_KAWETH) += kaweth.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_MICROTEK) += microtek.o obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o -obj-$(CONFIG_USB_NET1080) += net1080.o +obj-$(CONFIG_USB_USBNET) += usbnet.o # Object files in subdirectories diff -u --recursive --new-file v2.4.9/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c --- v2.4.9/linux/drivers/usb/bluetooth.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/usb/bluetooth.c Tue Aug 28 11:21:02 2001 @@ -159,7 +159,6 @@ #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) #define CHAR2INT16(c1,c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff)) -#define MIN(a,b) (((a)<(b))?(a):(b)) #define NUM_BULK_URBS 24 #define NUM_CONTROL_URBS 16 @@ -518,7 +517,7 @@ } - buffer_size = MIN (count, bluetooth->bulk_out_buffer_size); + buffer_size = min (int, count, bluetooth->bulk_out_buffer_size); memcpy (urb->transfer_buffer, current_position, buffer_size); /* build up our urb */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c --- v2.4.9/linux/drivers/usb/dc2xx.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/dc2xx.c Tue Aug 28 11:21:02 2001 @@ -63,6 +63,7 @@ #include #include #include +#include #ifdef CONFIG_USB_DEBUG #define DEBUG @@ -72,6 +73,9 @@ #include +/* /dev/usb dir. */ +extern devfs_handle_t usb_devfs_handle; + /* * Version Information */ @@ -137,11 +141,12 @@ /* this is non-null iff the device is open */ char *buf; /* buffer for I/O */ + devfs_handle_t devfs; /* devfs device */ + /* always valid */ wait_queue_head_t wait; /* for timed waits */ }; - /* Support multiple cameras, possibly of different types. */ static struct camera_state *minor_data [MAX_CAMERAS]; @@ -368,8 +373,10 @@ struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; int direction, ep; + char name[8]; struct camera_state *camera = NULL; + /* these have one config, one interface */ if (dev->descriptor.bNumConfigurations != 1 || dev->config[0].bNumInterfaces != 1) { @@ -446,6 +453,15 @@ camera->dev = dev; usb_inc_dev_use (dev); + + /* If we have devfs, register the device */ + sprintf(name, "dc2xx%d", camera->subminor); + camera->devfs = devfs_register(usb_devfs_handle, name, + DEVFS_FL_DEFAULT, USB_MAJOR, + USB_CAMERA_MINOR_BASE + camera->subminor, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | + S_IWGRP, &usb_camera_fops, NULL); + goto bye; error: @@ -464,6 +480,8 @@ down (&state_table_mutex); down (&camera->sem); + + devfs_unregister(camera->devfs); /* If camera's not opened, we can clean up right away. * Else apps see a disconnect on next I/O; the release cleans. diff -u --recursive --new-file v2.4.9/linux/drivers/usb/devices.c linux/drivers/usb/devices.c --- v2.4.9/linux/drivers/usb/devices.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/usb/devices.c Fri Sep 7 10:56:50 2001 @@ -384,7 +384,7 @@ int chix; int ret, cnt = 0; int parent_devnum = 0; - char *pages_start, *data_end; + char *pages_start, *data_end, *speed; unsigned int length; ssize_t total_written = 0; @@ -404,8 +404,21 @@ * So the root hub's parent is 0 and any device that is * plugged into the root hub has a parent of 0. */ - data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, index, count, - usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild); + switch (usbdev->speed) { + case USB_SPEED_LOW: + speed = "1.5"; break; + case USB_SPEED_UNKNOWN: /* usb 1.1 root hub code */ + case USB_SPEED_FULL: + speed = "12 "; break; + case USB_SPEED_HIGH: + speed = "480"; break; + default: + speed = "?? "; + } + data_end = pages_start + sprintf(pages_start, format_topo, + bus->busnum, level, parent_devnum, + index, count, usbdev->devnum, + speed, usbdev->maxchild); /* * level = topology-tier level; * parent_devnum = parent device number; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/devio.c linux/drivers/usb/devio.c --- v2.4.9/linux/drivers/usb/devio.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/devio.c Fri Sep 7 10:56:50 2001 @@ -684,7 +684,7 @@ struct usbdevfs_connectinfo ci; ci.devnum = ps->dev->devnum; - ci.slow = ps->dev->slow; + ci.slow = ps->dev->speed == USB_SPEED_LOW; if (copy_to_user(arg, &ci, sizeof(ci))) return -EFAULT; return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.4.9/linux/drivers/usb/hub.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/hub.c Fri Sep 7 10:56:50 2001 @@ -39,6 +39,18 @@ static int khubd_pid = 0; /* PID of khubd */ static DECLARE_COMPLETION(khubd_exited); +#ifdef DEBUG +static inline char *portspeed (int portstatus) +{ + if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) + return "480 Mb/s"; + else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED)) + return "1.5 Mb/s"; + else + return "12 Mb/s"; +} +#endif + static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), @@ -113,7 +125,7 @@ /* Enable power to the ports */ dbg("enabling power on all ports"); - for (i = 0; i < hub->nports; i++) + for (i = 0; i < hub->descriptor->bNbrPorts; i++) usb_set_port_feature(hub->dev, i + 1, USB_PORT_FEAT_POWER); /* Wait for power to be enabled */ @@ -128,14 +140,14 @@ unsigned int pipe; int i, maxp, ret; - hub->descriptor = kmalloc(HUB_DESCRIPTOR_MAX_SIZE, GFP_KERNEL); + hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { - err("Unable to kmalloc %d bytes for hub descriptor", HUB_DESCRIPTOR_MAX_SIZE); + err("Unable to kmalloc %d bytes for hub descriptor", sizeof(*hub->descriptor)); return -1; } /* Request the entire hub descriptor. */ - ret = usb_get_hub_descriptor(dev, hub->descriptor, HUB_DESCRIPTOR_MAX_SIZE); + ret = usb_get_hub_descriptor(dev, hub->descriptor, sizeof(*hub->descriptor)); /* descriptor> is large enough for a hub with 127 ports; * the hub can/will return fewer bytes here. */ if (ret < 0) { @@ -144,10 +156,10 @@ return -1; } - le16_to_cpus(&hub->descriptor->wHubCharacteristics); + dev->maxchild = hub->descriptor->bNbrPorts; + info("%d port%s detected", hub->descriptor->bNbrPorts, (hub->descriptor->bNbrPorts == 1) ? "" : "s"); - hub->nports = dev->maxchild = hub->descriptor->bNbrPorts; - info("%d port%s detected", hub->nports, (hub->nports == 1) ? "" : "s"); + le16_to_cpus(&hub->descriptor->wHubCharacteristics); if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) dbg("part of a compound device"); @@ -180,6 +192,40 @@ break; } + switch (dev->descriptor.bDeviceProtocol) { + case 0: + break; + case 1: + dbg("Single TT"); + break; + case 2: + dbg("Multiple TT"); + break; + default: + dbg("Unrecognized hub protocol %d", + dev->descriptor.bDeviceProtocol); + break; + } + + switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { + case 0x00: + if (dev->descriptor.bDeviceProtocol != 0) + dbg("TT requires at most 8 FS bit times"); + break; + case 0x20: + dbg("TT requires at most 16 FS bit times"); + break; + case 0x40: + dbg("TT requires at most 24 FS bit times"); + break; + case 0x60: + dbg("TT requires at most 32 FS bit times"); + break; + } + + dbg("Port indicators are %s supported", + (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) ? "" : "not"); + dbg("power on to power good time: %dms", hub->descriptor->bPwrOn2PwrGood * 2); dbg("hub controller current requirement: %dmA", hub->descriptor->bHubContrCurrent); @@ -397,7 +443,7 @@ int i; /* Disconnect any attached devices */ - for (i = 0; i < hub->nports; i++) { + for (i = 0; i < hub->descriptor->bNbrPorts; i++) { if (dev->children[i]) usb_disconnect(&dev->children[i]); } @@ -444,6 +490,7 @@ #define HUB_LONG_RESET_TIME 200 #define HUB_RESET_TIMEOUT 500 +/* return: -1 on error, 0 on success, 1 on disconnect. */ static int usb_hub_port_wait_reset(struct usb_device *hub, int port, struct usb_device *dev, unsigned int delay) { @@ -465,18 +512,25 @@ portstatus = le16_to_cpu(portsts.wPortStatus); portchange = le16_to_cpu(portsts.wPortChange); dbg("port %d, portstatus %x, change %x, %s", port + 1, - portstatus, portchange, - portstatus & (1 << USB_PORT_FEAT_LOWSPEED) ? "1.5 Mb/s" : "12 Mb/s"); + portstatus, portchange, portspeed (portstatus)); + + /* Device went away? */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) + return 1; /* bomb out completely if something weird happened */ - if ((portchange & USB_PORT_STAT_C_CONNECTION) || - !(portstatus & USB_PORT_STAT_CONNECTION)) + if ((portchange & USB_PORT_STAT_C_CONNECTION)) return -1; /* if we`ve finished resetting, then break out of the loop */ if (!(portstatus & USB_PORT_STAT_RESET) && (portstatus & USB_PORT_STAT_ENABLE)) { - dev->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0; + if (portstatus & USB_PORT_STAT_HIGH_SPEED) + dev->speed = USB_SPEED_HIGH; + else if (portstatus & USB_PORT_STAT_LOW_SPEED) + dev->speed = USB_SPEED_LOW; + else + dev->speed = USB_SPEED_FULL; return 0; } @@ -491,19 +545,21 @@ return -1; } +/* return: -1 on error, 0 on success, 1 on disconnect. */ static int usb_hub_port_reset(struct usb_device *hub, int port, struct usb_device *dev, unsigned int delay) { - int i; + int i, status; /* Reset the port */ for (i = 0; i < HUB_RESET_TRIES; i++) { usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET); - /* return success if the port reset OK */ - if (!usb_hub_port_wait_reset(hub, port, dev, delay)) { + /* return on disconnect or reset */ + status = usb_hub_port_wait_reset(hub, port, dev, delay); + if (status != -1) { usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_RESET); - return 0; + return status; } dbg("port %d of hub %d not enabled, trying reset again...", @@ -539,8 +595,8 @@ portstatus = le16_to_cpu(portsts->wPortStatus); portchange = le16_to_cpu(portsts->wPortChange); - dbg("port %d, portstatus %x, change %x, %s", port + 1, portstatus, - portchange, portstatus & (1 << USB_PORT_FEAT_LOWSPEED) ? "1.5 Mb/s" : "12 Mb/s"); + dbg("port %d, portstatus %x, change %x, %s", + port + 1, portstatus, portchange, portspeed (portstatus)); /* Clear the connection change status */ usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); @@ -686,7 +742,7 @@ hub->error = 0; } - for (i = 0; i < hub->nports; i++) { + for (i = 0; i < hub->descriptor->bNbrPorts; i++) { struct usb_port_status portsts; unsigned short portstatus, portchange; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/hub.h linux/drivers/usb/hub.h --- v2.4.9/linux/drivers/usb/hub.h Tue Apr 17 17:23:06 2001 +++ linux/drivers/usb/hub.h Fri Sep 7 10:56:50 2001 @@ -26,37 +26,61 @@ #define USB_PORT_FEAT_RESET 4 #define USB_PORT_FEAT_POWER 8 #define USB_PORT_FEAT_LOWSPEED 9 +#define USB_PORT_FEAT_HIGHSPEED 10 #define USB_PORT_FEAT_C_CONNECTION 16 #define USB_PORT_FEAT_C_ENABLE 17 #define USB_PORT_FEAT_C_SUSPEND 18 #define USB_PORT_FEAT_C_OVER_CURRENT 19 #define USB_PORT_FEAT_C_RESET 20 +#define USB_PORT_FEAT_TEST 21 +#define USB_PORT_FEAT_INDICATOR 22 +/* + * Hub Status and Hub Change results + * See USB 2.0 spec Table 11-19 and Table 11-20 + */ struct usb_port_status { __u16 wPortStatus; __u16 wPortChange; } __attribute__ ((packed)); -/* wPortStatus bits */ +/* + * wPortStatus bit field + * See USB 2.0 spec Table 11-21 + */ #define USB_PORT_STAT_CONNECTION 0x0001 #define USB_PORT_STAT_ENABLE 0x0002 #define USB_PORT_STAT_SUSPEND 0x0004 #define USB_PORT_STAT_OVERCURRENT 0x0008 #define USB_PORT_STAT_RESET 0x0010 +/* bits 5 for 7 are reserved */ #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_LOW_SPEED 0x0200 - -/* wPortChange bits */ +#define USB_PORT_STAT_HIGH_SPEED 0x0400 +#define USB_PORT_STAT_TEST 0x0800 +#define USB_PORT_STAT_INDICATOR 0x1000 +/* bits 13 to 15 are reserved */ + +/* + * wPortChange bit field + * See USB 2.0 spec Table 11-22 + * Bits 0 to 4 shown, bits 5 to 15 are reserved + */ #define USB_PORT_STAT_C_CONNECTION 0x0001 #define USB_PORT_STAT_C_ENABLE 0x0002 #define USB_PORT_STAT_C_SUSPEND 0x0004 #define USB_PORT_STAT_C_OVERCURRENT 0x0008 #define USB_PORT_STAT_C_RESET 0x0010 -/* wHubCharacteristics (masks) */ -#define HUB_CHAR_LPSM 0x0003 -#define HUB_CHAR_COMPOUND 0x0004 -#define HUB_CHAR_OCPM 0x0018 +/* + * wHubCharacteristics (masks) + * See USB 2.0 spec Table 11-13, offset 3 + */ +#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ +#define HUB_CHAR_COMPOUND 0x0004 /* D2 */ +#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ +#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ +#define HUB_CHAR_PORTIND 0x0080 /* D7 */ struct usb_hub_status { __u16 wHubStatus; @@ -64,28 +88,28 @@ } __attribute__ ((packed)); /* - *Hub Status & Hub Change bit masks + * Hub Status & Hub Change bit masks + * See USB 2.0 spec Table 11-19 and Table 11-20 + * Bits 0 and 1 for wHubStatus and wHubChange + * Bits 2 to 15 are reserved for both */ #define HUB_STATUS_LOCAL_POWER 0x0001 #define HUB_STATUS_OVERCURRENT 0x0002 - #define HUB_CHANGE_LOCAL_POWER 0x0001 #define HUB_CHANGE_OVERCURRENT 0x0002 -#define HUB_DESCRIPTOR_MAX_SIZE 39 /* enough for 127 ports on a hub */ /* Hub descriptor */ struct usb_hub_descriptor { - __u8 bLength; + __u8 bDescLength; __u8 bDescriptorType; __u8 bNbrPorts; __u16 wHubCharacteristics; __u8 bPwrOn2PwrGood; __u8 bHubContrCurrent; - /* DeviceRemovable and PortPwrCtrlMask want to be variable-length bitmaps that hold max 256 entries, but for now they're ignored */ - __u8 bitmap[0]; + __u8 bitmap[2 * ((USB_MAXCHILDREN + 1 + 7) / 8)]; } __attribute__ ((packed)); struct usb_device; @@ -103,9 +127,6 @@ struct list_head hub_list; struct list_head event_list; - - /* Number of ports on the hub */ - int nports; struct usb_hub_descriptor *descriptor; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/inode.c linux/drivers/usb/inode.c --- v2.4.9/linux/drivers/usb/inode.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/usb/inode.c Tue Aug 28 10:56:06 2001 @@ -751,7 +751,6 @@ usb_deregister(&usbdevfs_driver); return ret; } - kern_mount(&usbdevice_fs_type); #ifdef CONFIG_PROC_FS /* create mount point for usbdevfs */ usbdir = proc_mkdir("usb", proc_bus); @@ -763,7 +762,6 @@ { usb_deregister(&usbdevfs_driver); unregister_filesystem(&usbdevice_fs_type); - kern_umount(usbdevice_fs_type.kern_mnt); #ifdef CONFIG_PROC_FS if (usbdir) remove_proc_entry("usb", proc_bus); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/kaweth.c linux/drivers/usb/kaweth.c --- v2.4.9/linux/drivers/usb/kaweth.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/kaweth.c Tue Aug 28 11:21:02 2001 @@ -248,9 +248,9 @@ dr->requesttype = requesttype; dr->request = request; - dr->value = value; - dr->index = index; - dr->length = size; + dr->value = cpu_to_le16p(&value); + dr->index = cpu_to_le16p(&index); + dr->length = cpu_to_le16p(&size); return kaweth_internal_control_msg(kaweth->dev, pipe, @@ -370,6 +370,9 @@ kaweth->firmware_buf[4] = type; kaweth->firmware_buf[5] = interrupt; + kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3], + kaweth->firmware_buf[2]); + kaweth_dbg("Downloading firmware at %x to kaweth device at %x", (int)data, (int)kaweth); @@ -476,7 +479,7 @@ int count = urb->actual_length; int count2 = urb->transfer_buffer_length; - __u16 pkt_len = *(__u16 *)kaweth->rx_buf; + __u16 pkt_len = le16_to_cpup(kaweth->rx_buf); struct sk_buff *skb; @@ -608,7 +611,7 @@ kaweth_async_set_rx_mode(kaweth); netif_stop_queue(net); - *((__u16 *)kaweth->tx_buf) = skb->len; + *((__u16 *)kaweth->tx_buf) = cpu_to_le16(skb->len); memcpy(kaweth->tx_buf + 2, skb->data, skb->len); @@ -719,8 +722,6 @@ net->trans_start = jiffies; usb_unlink_urb(kaweth->tx_urb); - - netif_wake_queue(net); } /**************************************************************** @@ -836,7 +837,7 @@ kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask); kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); - kaweth_info("MTU: %d", kaweth->configuration.segment_size); + kaweth_info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size)); kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", (int)kaweth->configuration.hw_addr[0], (int)kaweth->configuration.hw_addr[1], @@ -879,6 +880,10 @@ kaweth->rx_urb = usb_alloc_urb(0); kaweth->net = init_etherdev(0, 0); + if (!kaweth->net) { + kaweth_err("Error calling init_etherdev."); + return kaweth; + } memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr)); memcpy(kaweth->net->dev_addr, @@ -896,7 +901,7 @@ kaweth->net->hard_start_xmit = kaweth_start_xmit; kaweth->net->set_multicast_list = kaweth_set_rx_mode; kaweth->net->get_stats = kaweth_netdev_stats; - kaweth->net->mtu = kaweth->configuration.segment_size; + kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size); memset(&kaweth->stats, 0, sizeof(kaweth->stats)); @@ -1051,4 +1056,11 @@ module_init(kaweth_init); module_exit(kaweth_exit); + + + + + + + diff -u --recursive --new-file v2.4.9/linux/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c --- v2.4.9/linux/drivers/usb/mdc800.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/usb/mdc800.c Tue Aug 28 11:21:02 2001 @@ -610,16 +610,18 @@ spin_lock (&mdc800->io_lock); if (mdc800->open && (mdc800->state != NOT_CONNECTED)) { - mdc800->open=0; + spin_unlock(&mdc800->io_lock); usb_unlink_urb (mdc800->irq_urb); usb_unlink_urb (mdc800->write_urb); usb_unlink_urb (mdc800->download_urb); + mdc800->open=0; } else { + spin_unlock (&mdc800->io_lock); retval=-EIO; } - spin_unlock (&mdc800->io_lock); + return retval; } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/net1080.c linux/drivers/usb/net1080.c --- v2.4.9/linux/drivers/usb/net1080.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/net1080.c Wed Dec 31 16:00:00 1969 @@ -1,1128 +0,0 @@ -/* - * NetChip 1080 Driver (USB Host-to-Host Link) - * Copyright (C) 2000 by David Brownell - */ - -/* - * This talks to the NetChip 1080, which can appear in "network cables" - * and other designs. This driver interoperates with the Win32 network - * drivers from NetChip, using the NetChip reference design. - * - * The IP-over-USB protocol here may be of interest. Embedded devices - * could implement it at the cost of two bulk endpoints, and whatever - * other system resources the desired IP-based applications need. - * Some Linux palmtops could support that today. (Devices that don't - * support the TTL-driven data mangling of the net1080 chip won't need - * the header/trailer support though.) - * - * STATUS: - * - * 13-sept-2000 experimental, new - * - * This doesn't yet do any network hotplugging, and there's no matching - * ifup policy script ... it should arrange bridging with "brctl", and - * should handle static and dynamic ("pump") setups. - * - * RX/TX queue sizes currently fixed at one due to URB unlink problems. - * - * 10-oct-2000 - * usb_device_id table created. - * - * 28-oct-2000 - * misc fixes; mostly, discard more TTL-mangled rx packets. - * - * 01-nov-2000 - * usb_device_id table support added by Adam J. Richter . - * - * 08-apr-2001 gb - * Identify version on module load. - * - *-------------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG // error path messages -// #define VERBOSE // more; success messages -#define USE_TTL // timeout our reads - -#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) -# define DEBUG -#endif -#include - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.0.0" -#define DRIVER_AUTHOR "David Brownell " -#define DRIVER_DESC "NetChip 1080 Driver (USB Host-to-Host Link)" - - -static const struct usb_device_id products [] = { - // reference design - { USB_DEVICE(0x1080, 0x525), - driver_info: (unsigned long) "NetChip TurboCONNECT" }, - // Belkin, ... - { }, // END -}; - -MODULE_DEVICE_TABLE (usb, products); - -static u8 node_id [ETH_ALEN]; - - -/*------------------------------------------------------------------------- - * - * NetChip protocol: ethernet framing, and only use bulk endpoints (01/81; - * not mailboxes 02/82 or status interrupt 83). Expects Ethernet bridging. - * Odd USB length == always short read. - * - nc_header - * - payload, in Ethernet framing (14 byte header etc) - * - (optional padding byte, if needed so length is odd) - * - nc_trailer - */ - -struct nc_header { - u16 hdr_len; // sizeof nc_header (LE, all) - u16 packet_len; // packet size - u16 packet_id; // detects dropped packets -#define NC_MIN_HEADER 6 - - // all else is optional, and must start with: - // u16 vendorId; // from usb-if - // u16 productId; -}; - -#define NC_PAD_BYTE ((unsigned char)0xAC) - -struct nc_trailer { - u16 packet_id; -}; - -// packetsize == f(mtu setting), with upper limit -#define NC_MAX_PACKET(mtu) (sizeof (struct nc_header) \ - + (mtu) \ - + 1 \ - + sizeof (struct nc_trailer)) -#define MAX_PACKET 8191 - -// zero means no timeout; else, how long a 64 byte bulk -// read may be queued before HW flushes it. -#define NC_READ_TTL ((u8)255) // ms - - -/*-------------------------------------------------------------------------*/ - -// list of all devices we manage -static DECLARE_MUTEX (net1080_mutex); -static LIST_HEAD (net1080_list); - - -// Nineteen USB 1.1 max size bulk transactions per frame, max. -#if 0 -#define RX_QLEN 4 -#define TX_QLEN 4 - -#else -// unlink_urbs() has probs on OHCI without test8-pre patches. -#define RX_QLEN 1 -#define TX_QLEN 1 -#endif - -enum skb_state { - illegal = 0, - tx_start, tx_done, - rx_start, rx_done, rx_cleanup -}; - -struct skb_data { // skb->cb is one of these - struct urb *urb; - struct net1080 *dev; - enum skb_state state; - size_t length; -}; - - -struct net1080 { - // housekeeping - struct usb_device *udev; - const struct usb_device_id *prod_info; - struct semaphore mutex; - struct list_head dev_list; - wait_queue_head_t *wait; - - // protocol/interface state - struct net_device net; - struct net_device_stats stats; - u16 packet_id; - - // various kinds of pending driver work - struct sk_buff_head rxq; - struct sk_buff_head txq; - struct sk_buff_head done; - struct tasklet_struct bh; -}; - -#define mutex_lock(x) down(x) -#define mutex_unlock(x) up(x) - -static void defer_bh (struct net1080 *dev, struct sk_buff *skb) -{ - unsigned long flags; - - skb_unlink (skb); - spin_lock_irqsave (&dev->done.lock, flags); - __skb_queue_tail (&dev->done, skb); - if (dev->done.qlen == 1) - tasklet_schedule (&dev->bh); - spin_unlock_irqrestore (&dev->done.lock, flags); -} - -/*------------------------------------------------------------------------- - * - * We ignore most registers and EEPROM contents. - */ - -#define REG_USBCTL ((u8)0x04) -#define REG_TTL ((u8)0x10) -#define REG_STATUS ((u8)0x11) - -/* - * Vendor specific requests to read/write data - */ - -#define REQUEST_REGISTER ((u8)0x10) -#define REQUEST_EEPROM ((u8)0x11) - -#define CONTROL_TIMEOUT (500) /* msec */ - -static int -vendor_read (struct net1080 *dev, u8 req, u8 regnum, u16 *retval_ptr) -{ - int status = usb_control_msg (dev->udev, - usb_rcvctrlpipe (dev->udev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, regnum, - retval_ptr, sizeof *retval_ptr, - CONTROL_TIMEOUT); - if (status > 0) - status = 0; - if (!status) - le16_to_cpus (retval_ptr); - return status; -} - -static inline int -register_read (struct net1080 *dev, u8 regnum, u16 *retval_ptr) -{ - return vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr); -} - -// without retval, this can become fully async (usable in_interrupt) -static void -vendor_write (struct net1080 *dev, u8 req, u8 regnum, u16 value) -{ - usb_control_msg (dev->udev, - usb_sndctrlpipe (dev->udev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, regnum, - 0, 0, // data is in setup packet - CONTROL_TIMEOUT); -} - -static inline void -register_write (struct net1080 *dev, u8 regnum, u16 value) -{ - vendor_write (dev, REQUEST_REGISTER, regnum, value); -} - - -#if 0 -static void dump_registers (struct net1080 *dev) -{ - u8 reg; - u16 value; - - dbg ("%s registers:", dev->net.name); - for (reg = 0; reg < 0x20; reg++) { - int retval; - - // reading some registers is trouble - if (reg >= 0x08 && reg <= 0xf) - continue; - if (reg >= 0x12 && reg <= 0x1e) - continue; - - retval = register_read (dev, reg, &value); - if (retval < 0) - dbg ("%s reg [0x%x] ==> error %d", - dev->net.name, reg, retval); - else - dbg ("%s reg [0x%x] = 0x%x", - dev->net.name, reg, value); - } -} -#endif - - -/*------------------------------------------------------------------------- - * - * Control register - */ - -#define USBCTL_WRITABLE_MASK 0x1f0f -// bits 15-13 reserved, r/o -#define USBCTL_ENABLE_LANG (1 << 12) -#define USBCTL_ENABLE_MFGR (1 << 11) -#define USBCTL_ENABLE_PROD (1 << 10) -#define USBCTL_ENABLE_SERIAL (1 << 9) -#define USBCTL_ENABLE_DEFAULTS (1 << 8) -// bits 7-4 reserved, r/o -#define USBCTL_FLUSH_OTHER (1 << 3) -#define USBCTL_FLUSH_THIS (1 << 2) -#define USBCTL_DISCONN_OTHER (1 << 1) -#define USBCTL_DISCONN_THIS (1 << 0) - -#ifdef DEBUG -static void dump_usbctl (struct net1080 *dev, u16 usbctl) -{ - dbg ("%s: USB %d dev %d usbctl 0x%x:%s%s%s%s%s;" - " this%s%s;" - " other%s%s; r/o 0x%x", - dev->net.name, - dev->udev->bus->busnum, dev->udev->devnum, - usbctl, - (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", - (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", - (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", - (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", - (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", - - (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", - (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", - usbctl & ~USBCTL_WRITABLE_MASK - ); -} -#else -static inline void dump_usbctl (struct net1080 *dev, u16 usbctl) {} -#endif - -/*------------------------------------------------------------------------- - * - * Status register - */ - -#define STATUS_PORT_A (1 << 15) - -#define STATUS_CONN_OTHER (1 << 14) -#define STATUS_SUSPEND_OTHER (1 << 13) -#define STATUS_MAILBOX_OTHER (1 << 12) -#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03) - -#define STATUS_CONN_THIS (1 << 6) -#define STATUS_SUSPEND_THIS (1 << 5) -#define STATUS_MAILBOX_THIS (1 << 4) -#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03) - -#define STATUS_UNSPEC_MASK 0x0c8c -#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK)) - - -#ifdef DEBUG -static void dump_status (struct net1080 *dev, u16 status) -{ - dbg ("%s: USB %d dev %d status 0x%x:" - " this (%c) PKT=%d%s%s%s;" - " other PKT=%d%s%s%s; unspec 0x%x", - dev->net.name, - dev->udev->bus->busnum, dev->udev->devnum, - status, - - // XXX the packet counts don't seem right - // (1 at reset, not 0); maybe UNSPEC too - - (status & STATUS_PORT_A) ? 'A' : 'B', - STATUS_PACKETS_THIS (status), - (status & STATUS_CONN_THIS) ? " CON" : "", - (status & STATUS_SUSPEND_THIS) ? " SUS" : "", - (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", - - STATUS_PACKETS_OTHER (status), - (status & STATUS_CONN_OTHER) ? " CON" : "", - (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", - (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", - - status & STATUS_UNSPEC_MASK - ); -} -#else -static inline void dump_status (struct net1080 *dev, u16 status) {} -#endif - -/*------------------------------------------------------------------------- - * - * TTL register - */ - -#define TTL_THIS(ttl) (0x00ff & ttl) -#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8)) -#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this)))) - -#ifdef DEBUG -static void dump_ttl (struct net1080 *dev, u16 ttl) -{ - dbg ("%s: USB %d dev %d ttl 0x%x this = %d, other = %d", - dev->net.name, - dev->udev->bus->busnum, dev->udev->devnum, - ttl, - - TTL_THIS (ttl), - TTL_OTHER (ttl) - ); -} -#else -static inline void dump_ttl (struct net1080 *dev, u16 ttl) {} -#endif - -#define RUN_CONTEXT (in_irq () ? "in_irq" \ - : (in_interrupt () ? "in_interrupt" : "can sleep")) - -/*-------------------------------------------------------------------------*/ - -// ensure that the device is in a known state before using it. - -// preconditions: -// caller owns the device mutex -// caller has a process context - -static int net1080_reset (struct net1080 *dev) -{ - u16 usbctl, status, ttl; - int retval; - - if ((retval = register_read (dev, REG_STATUS, &status)) < 0) { - dbg ("can't read dev %d status: %d", dev->udev->devnum, retval); - goto done; - } - dump_status (dev, status); - - if ((retval = register_read (dev, REG_USBCTL, &usbctl)) < 0) { - dbg ("can't read USBCTL, %d", retval); - goto done; - } - dump_usbctl (dev, usbctl); - - register_write (dev, REG_USBCTL, - USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER); - - if ((retval = register_read (dev, REG_TTL, &ttl)) < 0) { - dbg ("can't read TTL, %d", retval); - goto done; - } - dump_ttl (dev, ttl); - -#ifdef USE_TTL - // Have the chip flush reads that seem to be starving for read - // bandwidth ... or we're otherwise reading. Note, Win32 drivers - // may change our read TTL for us. - - register_write (dev, REG_TTL, - MK_TTL (NC_READ_TTL, TTL_OTHER (ttl)) ); - dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL); -#endif - - info ("%s: %s, port %c on USB %d dev %d, peer %sconnected", - dev->net.name, (char *) dev->prod_info->driver_info, - (status & STATUS_PORT_A) ? 'A' : 'B', - dev->udev->bus->busnum, - dev->udev->devnum, - (status & STATUS_CONN_OTHER) ? "" : "dis" - ); - retval = 0; - -done: - return retval; -} - - -/*------------------------------------------------------------------------- - * - * Network Device Driver support (peer link to USB Host) - * - --------------------------------------------------------------------------*/ - -static int net1080_change_mtu (struct net_device *net, int new_mtu) -{ - if ((new_mtu < 0) || NC_MAX_PACKET (new_mtu) > MAX_PACKET) - return -EINVAL; - net->mtu = new_mtu; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static struct net_device_stats *net1080_get_stats (struct net_device *net) -{ - return &((struct net1080 *) net->priv)->stats; -} - -/*-------------------------------------------------------------------------*/ - -static void rx_complete (struct urb *urb); - -static void rx_submit (struct net1080 *dev, struct urb *urb, int flags) -{ - struct sk_buff *skb; - struct skb_data *entry; - int retval = 0; - unsigned long lockflags; - - if ((skb = alloc_skb (NC_MAX_PACKET (dev->net.mtu), flags)) == 0) { - err ("no rx skb"); - tasklet_schedule (&dev->bh); - usb_free_urb (urb); - return; - } - - entry = (struct skb_data *) skb->cb; - entry->urb = urb; - entry->dev = dev; - entry->state = rx_start; - entry->length = 0; - - FILL_BULK_URB (urb, dev->udev, usb_rcvbulkpipe (dev->udev, 1), - skb->data, skb->truesize, rx_complete, skb); - urb->transfer_flags |= USB_QUEUE_BULK; - - spin_lock_irqsave (&dev->rxq.lock, lockflags); - if (!netif_queue_stopped (&dev->net)) { - if ((retval = usb_submit_urb (urb)) != 0) { - err ("%s rx submit, %d", dev->net.name, retval); - tasklet_schedule (&dev->bh); - } else { - __skb_queue_tail (&dev->rxq, skb); - } - } else { - dbg ("rx: stopped"); - retval = -ENOLINK; - } - spin_unlock_irqrestore (&dev->rxq.lock, lockflags); - if (retval) { - dev_kfree_skb_any (skb); - usb_free_urb (urb); - } -} - - -/*-------------------------------------------------------------------------*/ - -static void rx_complete (struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct skb_data *entry = (struct skb_data *) skb->cb; - struct net1080 *dev = entry->dev; - int urb_status = urb->status; - - urb->dev = 0; - skb->len = urb->actual_length; - entry->state = rx_done; - entry->urb = 0; - - if ((urb->transfer_flags & USB_ASYNC_UNLINK) != 0) { - dbg ("rx ... shutting down"); - usb_free_urb (urb); - urb = 0; - } - - switch (urb_status) { - // success - case 0: - if (!(skb->len & 0x01)) { - entry->state = rx_cleanup; - dev->stats.rx_errors++; - dev->stats.rx_length_errors++; - dbg ("even rx len %d", skb->len); - } else if (skb->len > MAX_PACKET) { - entry->state = rx_cleanup; - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; - dbg ("rx too big, %d", skb->len); - } - break; - - // hardware-reported interface shutdown ... which we - // typically see before khubd calls disconnect() - case -ETIMEDOUT: // usb-ohci - case -EILSEQ: // *uhci ... "crc"/timeout error - // netif_device_detach (&dev->net); - // FALLTHROUGH - - // software-driven interface shutdown - case -ECONNRESET: - entry->state = rx_cleanup; - usb_free_urb (urb); - urb = 0; - dbg ("%s ... shutdown rx (%d)", dev->net.name, urb_status); - break; - - // data overrun ... flush fifo? - case -EOVERFLOW: - dev->stats.rx_over_errors++; - // FALLTHROUGH - - default: - entry->state = rx_cleanup; - dev->stats.rx_errors++; - err ("%s rx: status %d", dev->net.name, urb_status); - break; - } - defer_bh (dev, skb); - - if (urb) { - if (!netif_queue_stopped (&dev->net)) { - rx_submit (dev, urb, GFP_ATOMIC); - return; - } else - usb_free_urb (urb); - } -#ifdef VERBOSE - dbg ("no read resubmitted"); -#endif /* VERBOSE */ -} - -/*-------------------------------------------------------------------------*/ - -// unlink pending rx/tx; completion handlers do all other cleanup - -static int unlink_urbs (struct sk_buff_head *q) -{ - unsigned long flags; - struct sk_buff *skb; - struct skb_data *entry; - int retval; - int count = 0; - - spin_lock_irqsave (&q->lock, flags); - for (skb = q->next; skb != (struct sk_buff *) q; skb = skb->next) { - entry = (struct skb_data *) skb->cb; - entry->urb->transfer_flags |= USB_ASYNC_UNLINK; - retval = usb_unlink_urb (entry->urb); - if (retval < 0) - dbg ("unlink urb err, %d", retval); - else - count++; - } - spin_unlock_irqrestore (&q->lock, flags); - return count; -} - - -/*-------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -static int net1080_stop (struct net_device *net) -{ - struct net1080 *dev = (struct net1080 *) net->priv; - int temp; - DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); - DECLARE_WAITQUEUE (wait, current); - - mutex_lock (&dev->mutex); - - dbg ("%s stop stats: rx/tx %ld/%ld, errs %ld/%ld", net->name, - dev->stats.rx_packets, dev->stats.tx_packets, - dev->stats.rx_errors, dev->stats.tx_errors - ); - - netif_stop_queue(net); - - // ensure there are no more active urbs - add_wait_queue (&unlink_wakeup, &wait); - dev->wait = &unlink_wakeup; - temp = unlink_urbs (&dev->txq) + unlink_urbs (&dev->rxq); - - // maybe wait for deletions to finish. - if (temp) { - current->state = TASK_UNINTERRUPTIBLE; - schedule (); - dbg ("waited for %d urb completions", temp); - } - dev->wait = 0; - current->state = TASK_RUNNING; - remove_wait_queue (&unlink_wakeup, &wait); - - mutex_unlock (&dev->mutex); - MOD_DEC_USE_COUNT; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -// posts a read, and enables write queing - -// precondition: never called in_interrupt - -static int net1080_open (struct net_device *net) -{ - struct net1080 *dev = (struct net1080 *) net->priv; - int retval; - u16 status; - int i; - - MOD_INC_USE_COUNT; - mutex_lock (&dev->mutex); - - // insist peer be connected -- is this the best place? - if ((retval = register_read (dev, REG_STATUS, &status)) != 0) { - dbg ("%s open: status read failed - %d", net->name, retval); - goto done; - } - if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER) { - retval = -ENOLINK; - dbg ("%s open: peer not connected", net->name); - goto done; - } - - MOD_INC_USE_COUNT; - netif_start_queue (net); - for (i = 0; i < RX_QLEN; i++) - rx_submit (dev, usb_alloc_urb (0), GFP_KERNEL); - - dbg ("%s open: started queueing (rx %d, tx %d)", - net->name, RX_QLEN, TX_QLEN); -done: - mutex_unlock (&dev->mutex); - MOD_DEC_USE_COUNT; - return retval; -} - -/*-------------------------------------------------------------------------*/ - -static void tx_complete (struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct skb_data *entry = (struct skb_data *) skb->cb; - struct net1080 *dev = entry->dev; - - urb->dev = 0; - entry->state = tx_done; - defer_bh (dev, skb); - netif_wake_queue (&dev->net); -} - -/*-------------------------------------------------------------------------*/ - -static struct sk_buff *fixup_skb (struct sk_buff *skb) -{ - int padlen; - struct sk_buff *skb2; - - padlen = ((skb->len + sizeof (struct nc_header) - + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1; - if (!skb_cloned (skb)) { - int headroom = skb_headroom (skb); - int tailroom = skb_tailroom (skb); - - if ((padlen + sizeof (struct nc_trailer)) <= tailroom - && sizeof (struct nc_header) <= headroom) - return skb; - - if ((sizeof (struct nc_header) + padlen - + sizeof (struct nc_trailer)) < - (headroom + tailroom)) { - skb->data = memmove (skb->head - + sizeof (struct nc_header), - skb->data, skb->len); - skb->tail = skb->data + skb->len; - return skb; - } - } - skb2 = skb_copy_expand (skb, - sizeof (struct nc_header), - sizeof (struct nc_trailer) + padlen, - in_interrupt () ? GFP_ATOMIC : GFP_KERNEL); - dev_kfree_skb_any (skb); - return skb2; -} - -/*-------------------------------------------------------------------------*/ - -static int net1080_start_xmit (struct sk_buff *skb, struct net_device *net) -{ - struct net1080 *dev = (struct net1080 *) net->priv; - int length = skb->len; - int retval = 0; - struct urb *urb = 0; - struct skb_data *entry; - struct nc_header *header; - struct nc_trailer *trailer; - unsigned long flags; - - if ((skb = fixup_skb (skb)) == 0) { - dbg ("can't fixup skb"); - goto drop; - } - if ((urb = usb_alloc_urb (0)) == 0) { - dbg ("no urb"); - goto drop; - } - - entry = (struct skb_data *) skb->cb; - entry->urb = urb; - entry->dev = dev; - entry->state = tx_start; - entry->length = length; - - header = (struct nc_header *) skb_push (skb, sizeof *header); - header->hdr_len = cpu_to_le16 (sizeof (*header)); - header->packet_len = cpu_to_le16 (length); - if (!((skb->len + sizeof *trailer) & 0x01)) - *skb_put (skb, 1) = NC_PAD_BYTE; - trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer); - - FILL_BULK_URB (urb, dev->udev, - usb_sndbulkpipe (dev->udev, 1), - skb->data, skb->len, tx_complete, skb); - urb->transfer_flags |= USB_QUEUE_BULK; - // FIXME urb->timeout = ...; - - spin_lock_irqsave (&dev->txq.lock, flags); - if (!netif_queue_stopped (&dev->net)) { - header->packet_id = cpu_to_le16 (dev->packet_id++); - put_unaligned (header->packet_id, &trailer->packet_id); - - netif_stop_queue (net); - if ((retval = usb_submit_urb (urb)) != 0) { - netif_start_queue (net); - dbg ("%s tx: submit urb err %d", net->name, retval); - } else { - net->trans_start = jiffies; - __skb_queue_tail (&dev->txq, skb); - if (dev->txq.qlen < TX_QLEN) - netif_start_queue (net); - } - } else - retval = -ENOLINK; - spin_unlock_irqrestore (&dev->txq.lock, flags); - - if (retval) { - dbg ("drop"); -drop: - dev->stats.tx_dropped++; - dev_kfree_skb_any (skb); - usb_free_urb (urb); -#ifdef VERBOSE - } else { - dbg ("%s: tx %p len %d", net->name, skb, length); -#endif - } - return retval; -} - - -/*-------------------------------------------------------------------------*/ - -static void rx_process (struct net1080 *dev, struct sk_buff *skb) -{ - struct nc_header *header; - struct nc_trailer *trailer; - - header = (struct nc_header *) skb->data; - le16_to_cpus (&header->hdr_len); - le16_to_cpus (&header->packet_len); - if (header->packet_len > MAX_PACKET) { - dev->stats.rx_frame_errors++; - dbg ("packet too big, %d", header->packet_len); - goto error; - } else if (header->hdr_len < NC_MIN_HEADER) { - dev->stats.rx_frame_errors++; - dbg ("header too short, %d", header->hdr_len); - goto error; - } else if (header->hdr_len > header->packet_len) { - dev->stats.rx_frame_errors++; - dbg ("header too big, %d packet %d", header->hdr_len, header->packet_len); - goto error; - } else if (header->hdr_len != sizeof *header) { - // out of band data for us? - dbg ("header OOB, %d bytes", header->hdr_len - NC_MIN_HEADER); - // switch (vendor/product ids) { ... } - } - skb_pull (skb, header->hdr_len); - - trailer = (struct nc_trailer *) - (skb->data + skb->len - sizeof *trailer); - skb_trim (skb, skb->len - sizeof *trailer); - - if ((header->packet_len & 0x01) == 0) { - if (skb->data [header->packet_len] != NC_PAD_BYTE) { - dev->stats.rx_frame_errors++; - dbg ("bad pad"); - goto error; - } - skb_trim (skb, skb->len - 1); - } - if (skb->len != header->packet_len) { - dev->stats.rx_length_errors++; - dbg ("bad packet len %d (expected %d)", - skb->len, header->packet_len); - goto error; - } - if (header->packet_id != get_unaligned (&trailer->packet_id)) { - dev->stats.rx_fifo_errors++; - dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x", - header->packet_id, trailer->packet_id); - goto error; - } - - if (skb->len) { - skb->dev = &dev->net; - skb->protocol = eth_type_trans (skb, &dev->net); - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - -#ifdef VERBOSE - dbg ("%s: rx %p len %d, type 0x%x, id 0x%x", - dev->net.name, skb, skb->len, skb->protocol, - le16_to_cpu (header->packet_id)); -#endif - netif_rx (skb); - } else { - dbg ("drop"); -error: - dev->stats.rx_errors++; - dev_kfree_skb (skb); - } -} - -/*-------------------------------------------------------------------------*/ - -// tasklet - -// We can have a state machine in this tasklet monitor the link state, -// using async control messaging and calling attach/detach routines. - -// But then some listener ought to respond to the changes; do those -// network attach/detach notifications get to userland somehow, such -// as by calling "ifup usb0" and "ifdown usb0"? - -static void net1080_bh (unsigned long param) -{ - struct net1080 *dev = (struct net1080 *) param; - struct sk_buff *skb; - struct skb_data *entry; - - while ((skb = skb_dequeue (&dev->done))) { - entry = (struct skb_data *) skb->cb; - switch (entry->state) { - case rx_done: - rx_process (dev, skb); - continue; - case tx_done: - if (entry->urb->status) { - // can this statistic become more specific? - dev->stats.tx_errors++; - dbg ("%s tx: err %d", dev->net.name, - entry->urb->status); - } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += entry->length; - } - // FALLTHROUGH: - case rx_cleanup: - usb_free_urb (entry->urb); - dev_kfree_skb (skb); - continue; - default: - dbg ("%s: bogus skb state %d", - dev->net.name, entry->state); - } - } - - // waiting for all pending urbs to complete? - if (dev->wait) { - if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { - wake_up (dev->wait); - } - - // or are we maybe short a few urbs? - } else if (!netif_queue_stopped (&dev->net)) { - if (dev->rxq.qlen < TX_QLEN) { - struct urb *urb; - int i; - for (i = 0; i < 3 && dev->rxq.qlen < TX_QLEN; i++) { - if ((urb = usb_alloc_urb (0)) != 0) - rx_submit (dev, urb, GFP_ATOMIC); - } - dbg ("%s: rxqlen now %d", - dev->net.name, dev->rxq.qlen); - } - } -} - -/*------------------------------------------------------------------------- - * - * USB Device Driver support - * - --------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -static void net1080_disconnect (struct usb_device *udev, void *ptr) -{ - struct net1080 *dev = (struct net1080 *) ptr; - - info ("%s: USB %d dev %d, %s, disconnected", - dev->net.name, - udev->bus->busnum, udev->devnum, - (char *) dev->prod_info->driver_info); - - unregister_netdev (&dev->net); - - mutex_lock (&net1080_mutex); - mutex_lock (&dev->mutex); - list_del (&dev->dev_list); - mutex_unlock (&net1080_mutex); - -#ifdef DEBUG - memset (dev, 0x55, sizeof *dev); -#endif - kfree (dev); - usb_dec_dev_use (udev); -} - - -/*-------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -static void * -net1080_probe (struct usb_device *udev, unsigned ifnum, const struct usb_device_id *prod) -{ - struct net1080 *dev; - struct net_device *net; - struct usb_interface_descriptor *interface; - int retval; - - // sanity check; expect dedicated interface/devices for now. - interface = &udev->actconfig->interface [ifnum].altsetting[0]; - if (udev->descriptor.bNumConfigurations != 1 - || udev->config[0].bNumInterfaces != 1 - || udev->config[0].bNumInterfaces != 1 - || interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC - || interface->bNumEndpoints != 5 - ) { - dbg ("Bogus config info"); - return 0; - } - - // set up our own records - if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) { - dbg ("can't kmalloc dev"); - return 0; - } - memset (dev, 0, sizeof *dev); - - init_MUTEX_LOCKED (&dev->mutex); - usb_inc_dev_use (udev); - dev->udev = udev; - dev->prod_info = prod; - INIT_LIST_HEAD (&dev->dev_list); - skb_queue_head_init (&dev->rxq); - skb_queue_head_init (&dev->txq); - skb_queue_head_init (&dev->done); - dev->bh.func = net1080_bh; - dev->bh.data = (unsigned long) dev; - - // set up network interface records - net = &dev->net; - net->priv = dev; - strcpy (net->name, "usb%d"); - memcpy (net->dev_addr, node_id, sizeof node_id); - - ether_setup (net); - // net->flags |= IFF_POINTOPOINT; - - net->change_mtu = net1080_change_mtu; - net->get_stats = net1080_get_stats; - net->hard_start_xmit = net1080_start_xmit; - net->open = net1080_open; - net->stop = net1080_stop; - - register_netdev (&dev->net); - - // ... talk to the device - // dump_registers (dev); - - if ((retval = net1080_reset (dev)) < 0) { - err ("%s: init reset fail on USB %d dev %d - %d", - dev->net.name, udev->bus->busnum, udev->devnum, retval); - mutex_unlock (&dev->mutex); - net1080_disconnect (udev, dev); - return 0; - } - - // ok, it's ready to go. - mutex_lock (&net1080_mutex); - list_add (&dev->dev_list, &net1080_list); - mutex_unlock (&dev->mutex); - - // start as if the link is up - netif_device_attach (&dev->net); - - mutex_unlock (&net1080_mutex); - - return dev; -} - - -/*-------------------------------------------------------------------------*/ - -static struct usb_driver net1080_driver = { - name: "net1080", - id_table: products, - probe: net1080_probe, - disconnect: net1080_disconnect, -}; - -/*-------------------------------------------------------------------------*/ - -static int __init net1080_init (void) -{ - // compiler should optimize this out - if (sizeof (((struct sk_buff *)0)->cb) < sizeof (struct skb_data)) - BUG (); - - if (usb_register (&net1080_driver) < 0) - return -1; - - get_random_bytes (node_id, sizeof node_id); - node_id [0] &= 0x7f; - - info(DRIVER_VERSION ":" DRIVER_DESC); - - return 0; -} -module_init (net1080_init); - -static void __exit net1080_exit (void) -{ - usb_deregister (&net1080_driver); -} -module_exit (net1080_exit); - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); - diff -u --recursive --new-file v2.4.9/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c --- v2.4.9/linux/drivers/usb/pegasus.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/pegasus.c Tue Aug 28 07:09:44 2001 @@ -1,7 +1,7 @@ /* ** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller ** -** Copyright (c) 1999,2000 Petko Manolov - Petkan (petkan@dce.bg) +** Copyright (c) 1999-2001 Petko Manolov (pmanolov@lnxw.com) ** ** ** ChangeLog: @@ -53,9 +53,9 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.4.19 2001/06/07 (C) 1999-2001" +#define DRIVER_VERSION "v0.4.21 (2001/08/27)" #define DRIVER_AUTHOR "Petko Manolov " -#define DRIVER_DESC "ADMtek AN986 Pegasus USB Ethernet driver" +#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" #define PEGASUS_USE_INTR #define PEGASUS_WRITE_EEPROM @@ -117,9 +117,7 @@ warn( __FUNCTION__ " status %d", urb->status); } pegasus->flags &= ~ETH_REGS_CHANGED; - if ( waitqueue_active(&pegasus->ctrl_wait) ) { - wake_up_interruptible( &pegasus->ctrl_wait ); - } + wake_up(&pegasus->ctrl_wait ); } @@ -135,9 +133,13 @@ return 0; } memcpy(buffer,data,size); - + + add_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); while ( pegasus->flags & ETH_REGS_CHANGED ) - interruptible_sleep_on( &pegasus->ctrl_wait ); + schedule(); + remove_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_RUNNING); pegasus->dr.requesttype = PEGASUS_REQT_READ; pegasus->dr.request = PEGASUS_REQ_GET_REGS; @@ -152,7 +154,7 @@ buffer, size, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); - set_current_state( TASK_INTERRUPTIBLE ); + set_current_state( TASK_UNINTERRUPTIBLE ); if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRLs %d", ret); @@ -182,8 +184,12 @@ } memcpy(buffer, data, size); + add_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); while ( pegasus->flags & ETH_REGS_CHANGED ) - interruptible_sleep_on( &pegasus->ctrl_wait ); + schedule(); + remove_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_RUNNING); pegasus->dr.requesttype = PEGASUS_REQT_WRITE; pegasus->dr.request = PEGASUS_REQ_SET_REGS; @@ -198,7 +204,7 @@ buffer, size, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); - set_current_state( TASK_INTERRUPTIBLE ); + set_current_state( TASK_UNINTERRUPTIBLE ); if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); @@ -228,8 +234,12 @@ } memcpy(buffer, &data, 1); + add_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); while ( pegasus->flags & ETH_REGS_CHANGED ) - interruptible_sleep_on( &pegasus->ctrl_wait ); + schedule(); + remove_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_RUNNING); pegasus->dr.requesttype = PEGASUS_REQT_WRITE; pegasus->dr.request = PEGASUS_REQ_SET_REG; @@ -244,7 +254,7 @@ buffer, 1, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); - set_current_state( TASK_INTERRUPTIBLE ); + set_current_state( TASK_UNINTERRUPTIBLE ); if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); @@ -620,7 +630,6 @@ } #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,48) static void pegasus_tx_timeout( struct net_device *net ) { pegasus_t *pegasus = net->priv; @@ -633,7 +642,6 @@ usb_unlink_urb( &pegasus->tx_urb ); pegasus->stats.tx_errors++; } -#endif static int pegasus_start_xmit( struct sk_buff *skb, struct net_device *net ) @@ -861,10 +869,8 @@ net->priv = pegasus; net->open = pegasus_open; net->stop = pegasus_close; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,48) net->watchdog_timeo = PEGASUS_TX_TIMEOUT; net->tx_timeout = pegasus_tx_timeout; -#endif net->do_ioctl = pegasus_ioctl; net->hard_start_xmit = pegasus_start_xmit; net->set_multicast_list = pegasus_set_multicast; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/plusb.c linux/drivers/usb/plusb.c --- v2.4.9/linux/drivers/usb/plusb.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/plusb.c Wed Dec 31 16:00:00 1969 @@ -1,1060 +0,0 @@ -/*****************************************************************************/ - -/* - * plusb.c -- prolific pl-2301/pl-2302 driver. - * - * Copyright (C) 2000 Deti Fliegl (deti@fliegl.de) - * Copyright (C) 2000 Pavel Machek (pavel@suse.cz) - * Copyright (C) 2000 Eric Z. Ayers (eric@compgen.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * This driver creates a network interface (plusb0, plusb1, ...) that will - * send messages over a USB host-host cable based on the Prolific ASIC. - * It works a lot like plip or PP over an RS-232C null modem cable. - * - * Expect speeds of around 330Kbytes/second over a UHCI host controller. - * OHCI should be faster. Increase the MTU for faster transfers of large - * files (up-to 800Kbytes/second). (16384 is a good size) - * - * $Id: plusb.c,v 1.18 2000/02/14 10:38:58 fliegl Exp $ - * - * Changelog: - * - * v0.1 deti - * Original Version of driver. - * v0.2 15 Sep 2000 pavel - * Patches to decrease latency by rescheduling the bottom half of - * interrupt code. - * v0.3 10 Oct 2000 eric - * Patches to work in v2.2 backport (v2.4 changes the way net_dev.name - * is allocated) - * v0.4 19 Oct 2000 eric - * Some more performance fixes. Lock re-submitting urbs. - * Lower the number of sk_buff's to queue. - * v0.5 25 Oct 2000 eric - * Removed use of usb_bulk_msg() all together. This caused - * the driver to block in an interrupt context. - * Consolidate read urb submission into read_urb_submit(). - * Performance is the same as v0.4. - * v0.5.1 27 Oct 2000 eric - * Extra debugging messages to help diagnose problem with uchi.o stack. - * v0.5.2 27 Oct 2000 eric - * Set the 'start' flag for the network device in plusb_net_start() - * and plusb_net_stop() (doesn't help) - * v0.5.3 27 Oct 2000 pavel - * Commented out handlers when -EPIPE is received, - * (remove calls to usb_clear_halt()) Since the callback is in - * an interrupt context, it doesn't help, it just panics - * the kernel. (what do we do?) - * Under high load, dev_alloc_skb() fails, the read URB must - * be re-submitted. - * Added plusb_change_mtu() and increased the size of _BULK_DATA_LEN - * v0.5.4 31 Oct 2000 eric - * Fix race between plusb_net_xmit() and plusb_bulk_write_complete() - * v0.5.5 1 Nov 2000 eric - * Remove dev->start field, otherwise, it won't compile in 2.4 - * Use dev_kfree_skb_any(). (important in 2.4 kernel) - * v0.5.6 2 Nov 2000 pavel,eric - * Add calls to netif_stop_queue() and netif_start_queue() - * Drop packets that come in while the free list is empty. - * (This version is being submitted after the release of 2.4-test10) - * v0.5.7 6 Nov 2000 - * Fix to not re-submit the urb on error to help when cables - * are yanked (not tested) - * - * - * KNOWN PROBLEMS: (Any suggestions greatfully accepted!) - * - * 2 Nov 2000 - * - The shutdown for this may not be entirely clean. Sometimes, the - * kernel will Oops when the cable is unplugged, or - * if the plusb module is removed. - * - If you ifdown a device and then ifup it again, the link will not - * always work. You have to 'rmmod plusb ; modprobe plusb' on - * both machines to get it to work again. Something must be wrong with - * plusb_net_open() and plusb_net_start() ? Maybe - * the 'suspend' and 'resume' entry points need to be - * implemented? - * - Needs to handle -EPIPE correctly in bulk complete handlers. - * (replace usb_clear_halt() function with async urbs?) - * - I think this code relies too much on one spinlock and does - * too much in the interrupt handler. The net1080 code is - * much more elegant, and should work for this chip. Its - * only drawback is that it is going to be tough to backport - * it to v2.2. - * - Occasionally the device will hang under the 'uhci.o' - * driver. The workaround is to ifdown the device and - * remove the modules, then re-insert them. You may have - * better luck with the 'usb-uhci.o' driver. - * - After using ifconfig down ; ifconfig up, sometimes packets - * continue to be received, but there is a framing problem. - * - * FUTURE DIRECTIONS: - * - * - Fix the known problems. - * - There isn't much functional difference between the net1080 - * driver and this one. It would be neat if the same driver - * could handle both types of chips. Or if both drivers - * could handle both types of chips - this one is easier to - * backport to the 2.2 kernel. - * - Get rid of plusb_add_buf_tail and the single spinlock. - * Use a separate spinlock for the 2 lists, and use atomic - * operators for writeurb_submitted and readurb_submitted members. - * - * - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#define DEBUG 1 -#include - -#if (LINUX_VERSION_CODE < 0x020300) -#define dev_kfree_skb_any dev_kfree_skb -#endif - -/* - * Version Information - */ -#define DRIVER_VERSION "v0.5.7" -#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de" -#define DRIVER_DESC "PL-2302 USB Interface Driver for Linux (c)2000" - -/* Definitions formerly in plusb.h relocated. No need to export them -EZA */ - -#define _PLUSB_INTPIPE 0x1 -#define _PLUSB_BULKOUTPIPE 0x2 -#define _PLUSB_BULKINPIPE 0x3 - -#define _SKB_NUM 32 - -/* increase size of BULK_DATA_LEN so we can use bigger MTU's*/ -#define _BULK_DATA_LEN 32768 - - -typedef struct -{ - int connected; /* indicates if this structure is active */ - struct usb_device *usbdev; - /* keep track of USB structure */ - int status; /* Prolific status byte returned from interrupt */ - int in_bh; /* flag to indicate that we are in the bulk handler */ - int opened; /* flag to indicate that network dev is open */ - - spinlock_t lock; /* Lock for the buffer list. re-used for - locking around submitting the readurb member. - */ - urb_t *inturb; /* Read buffer for the interrupt callback */ - unsigned char * interrupt_in_buffer; - /* holds data for the inturb*/ - urb_t *readurb; /* Read buffer for the bulk data callback */ - unsigned char * bulk_in_buffer; - /* kmalloc'ed data for the readurb */ - int readurb_submitted; - /* Flag to indicate that readurb already sent */ - urb_t *writeurb; /* Write buffer for the bulk data callback */ - int writeurb_submitted; - /* Flag to indicate that writeurb already sent */ - - struct list_head tx_skb_list; - /* sk_buff's read from net device */ - struct list_head free_skb_list; - /* free sk_buff list */ - struct net_device net_dev; - /* handle to linux network device */ - struct net_device_stats net_stats; - /* stats to return for ifconfig output */ -} plusb_t,*pplusb_t; - -/* - * skb_list - queue of packets from the network driver to be delivered to USB - */ -typedef struct -{ - struct list_head skb_list; - struct sk_buff *skb; - int state; - plusb_t *s; -} skb_list_t,*pskb_list_t; - - -/* --------------------------------------------------------------------- */ - -#define NRPLUSB 4 - -/* - * Interrupt endpoint status byte, from Prolific PL-2301 docs - * Check the 'download' link at www.prolifictech.com - */ -#define _PL_INT_RES1 0x80 /* reserved */ -#define _PL_INT_RES2 0x40 /* reserved */ -#define _PL_INT_RXD _PL_INT_RES2 /* Read data ready - Not documented by Prolific, but seems to work! */ -#define _PL_INT_TX_RDY 0x20 /* OK to transmit data */ -#define _PL_INT_RESET_O 0x10 /* reset output pipe */ -#define _PL_INT_RESET_I 0x08 /* reset input pipe */ -#define _PL_INT_TX_C 0x04 /* transmission complete */ -#define _PL_INT_TX_REQ 0x02 /* transmission received */ -#define _PL_INT_PEER_E 0x01 /* peer exists */ - -/*-------------------------------------------------------------------*/ - -static plusb_t plusb[NRPLUSB]; - -static void plusb_write_bulk_complete(urb_t *purb); -static void plusb_read_bulk_complete(urb_t *purb); -static void plusb_int_complete(urb_t *purb); - -/* --------------------------------------------------------------------- */ - -/* - * plusb_add_buf_tail - Take the head of the src list and append it to - * the tail of the dest list - */ -static int plusb_add_buf_tail (plusb_t *s, struct list_head *dst, struct list_head *src) -{ - unsigned long flags = 0; - struct list_head *tmp; - int ret = 0; - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (src)) { - // no elements in source buffer - ret = -1; - goto err; - } - tmp = src->next; - list_del (tmp); - list_add_tail (tmp, dst); - - err: spin_unlock_irqrestore (&s->lock, flags); - return ret; -} -/*-------------------------------------------------------------------*/ - -/* - * dequeue_next_skb - submit the first thing on the tx_skb_list to the - * USB stack. This function should be called each time we get a new - * message to send to the other host, or each time a message is successfully - * sent. - */ -static void dequeue_next_skb(char * func, plusb_t * s) -{ - skb_list_t * skb_list; - unsigned long flags = 0; - - if (!s->connected) - return; - - spin_lock_irqsave (&s->lock, flags); - - if (!list_empty (&s->tx_skb_list) && !s->writeurb_submitted) { - int submit_ret; - skb_list = list_entry (s->tx_skb_list.next, skb_list_t, skb_list); - - if (skb_list->skb) { - s->writeurb_submitted = 1; - - /* Use the buffer inside the sk_buff directly. why copy? */ - FILL_BULK_URB_TO(s->writeurb, s->usbdev, - usb_sndbulkpipe(s->usbdev, _PLUSB_BULKOUTPIPE), - skb_list->skb->data, skb_list->skb->len, - plusb_write_bulk_complete, skb_list, 500); - - dbg ("%s: %s: submitting urb. skb_list %p", s->net_dev.name, func, skb_list); - - submit_ret = usb_submit_urb(s->writeurb); - if (submit_ret) { - s->writeurb_submitted = 0; - printk (KERN_CRIT "%s: %s: can't submit writeurb: %d\n", - s->net_dev.name, func, submit_ret); - } - } /* end if the skb value has been filled in */ - } - - spin_unlock_irqrestore (&s->lock, flags); -} - -/* - * submit_read_urb - re-submit the read URB to the stack - */ -void submit_read_urb(char * func, plusb_t * s) -{ - unsigned long flags=0; - - if (!s->connected) - return; - - spin_lock_irqsave (&s->lock, flags); - - if (!s->readurb_submitted) { - int ret; - s->readurb_submitted=1; - s->readurb->dev=s->usbdev; - ret = usb_submit_urb(s->readurb); - if (ret) { - printk (KERN_CRIT "%s: %s: error %d submitting read URB\n", - s->net_dev.name, func, ret); - s->readurb_submitted=0; - } - } - - spin_unlock_irqrestore (&s->lock, flags); - -} -/* --------------------------------------------------------------------- */ - -/* - * plusb_net_xmit - callback from the network device driver for outgoing data - * - * Data has arrived to the network device from the local machine and needs - * to be sent over the USB cable. This is in an interrupt, so we don't - * want to spend too much time in this function. - * - */ -static int plusb_net_xmit(struct sk_buff *skb, struct net_device *dev) -{ - plusb_t *s=dev->priv; - skb_list_t *skb_list; - unsigned int flags; - - dbg("plusb_net_xmit: len:%d i:%d",skb->len,in_interrupt()); - - if(!s->connected || !s->opened) { - /* - NOTE: If we get to this point, you'll return the error - kernel: virtual device plusb0 asks to queue packet - - Other things we could do: - 1) just drop this packet - 2) drop other packets in the queue - */ - return 1; - } - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty(&s->free_skb_list) - || plusb_add_buf_tail (s, &s->tx_skb_list, &s->free_skb_list)) { - /* The buffers on this side are full. DROP the packet - I think that this shouldn't happen with the correct - use of the netif_XXX functions -EZA - */ - dbg ("plusb: Free list is empty."); - kfree_skb(skb); - s->net_stats.tx_dropped++; - spin_unlock_irqrestore (&s->lock, flags); - return 0; - } - - skb_list = list_entry (s->tx_skb_list.prev, skb_list_t, skb_list); - skb_list->skb=skb; - skb_list->state=1; - skb_list->s=s; - - if (list_empty(&s->free_skb_list)) { - /* apply "backpressure". Tell the net layer to stop sending - the driver packets. - */ - netif_stop_queue(dev); - } - - spin_unlock_irqrestore (&s->lock, flags); - - /* If there is no write urb outstanding, pull the first thing - off of the list and submit it to the USB stack - */ - dequeue_next_skb("plusb_net_xmit", s); - - return 0; -} - -/* --------------------------------------------------------------------- */ - -/* - * plusb_write_bulk_complete () - callback after the data has been - * sent to the USB device, or a timeout occurred. - */ -static void plusb_write_bulk_complete(urb_t *purb) -{ - skb_list_t * skb_list=purb->context; - plusb_t *s=skb_list->s; - - dbg ("%s: plusb_write_bulk_complete: status:%d skb_list:%p\n", - s->net_dev.name, purb->status, skb_list); - - skb_list->state=0; - - if( purb->status == -EPIPE ) - printk(KERN_CRIT "%s: plusb_write_bulk_complete: got -EPIPE and don't know what to do!\n", - s->net_dev.name); - - if(!purb->status) { - s->net_stats.tx_packets++; - s->net_stats.tx_bytes+=skb_list->skb->len; - } - else { - err ("%s: plusb_write_bulk_complete: returned ERROR status:%d\n", - s->net_dev.name, purb->status); - - s->net_stats.tx_errors++; - s->net_stats.tx_aborted_errors++; - } - - dbg("plusb_bh: dev_kfree_skb"); - - /* NOTE: In 2.4 it's a problem to call dev_kfree_skb() in a hard IRQ: - Oct 28 23:42:14 bug kernel: Warning: kfree_skb on hard IRQ c023329a - */ - dev_kfree_skb_any(skb_list->skb); - - skb_list->skb = NULL; - if (plusb_add_buf_tail (s, &s->free_skb_list, &s->tx_skb_list)) { - err ("plusb: tx list empty. This shouldn't happen."); - } - - purb->status = 0; - s->writeurb_submitted = 0; - - netif_wake_queue((&s->net_dev)); - - dequeue_next_skb("plusb_write_bulk_complete", s); - - -} - -/* - * plusb_read_bulk_complete - Callback for data arriving from the USB device - * - * This gets called back when a full 'urb' is received from the remote system. - * This urb was allocated by this driver and is kept in the member: s->readurb - * - */ -static void plusb_read_bulk_complete(urb_t *purb) -{ - - plusb_t *s=purb->context; - - dbg("plusb_read_bulk_complete: status:%d length:%d", purb->status,purb->actual_length); - - if(!s->connected) - return; - - if( purb->status == -EPIPE ) - printk(KERN_CRIT "%s: plusb_read_bulk_complete: got -EPIPE and I don't know what to do!\n", - s->net_dev.name); - else if (!purb->status) { - struct sk_buff *skb; - unsigned char *dst; - int len=purb->transfer_buffer_length; - struct net_device_stats *stats=&s->net_stats; - - skb=dev_alloc_skb(len); - - if(!skb) { - printk (KERN_CRIT "%s: plusb_read_bulk_complete: dev_alloc_skb(%d)=NULL, dropping frame\n", s->net_dev.name, len); - stats->rx_dropped++; - } else { - dst=(char *)skb_put(skb, len); - memcpy( dst, purb->transfer_buffer, len); - - skb->dev=&s->net_dev; - skb->protocol=eth_type_trans(skb, skb->dev); - stats->rx_packets++; - stats->rx_bytes+=len; - netif_rx(skb); - } - - } - - s->readurb_submitted = 0; - - if (purb->status) { - /* Give the system a chance to "catch its breath". Shortcut - re-submitting the read URB> It will be re-submitted if - another interrupt comes back. The problem scenario is that - the plub is pulled and the read returns an error. - You don't want to resumbit in this case. - */ - err ("%s: plusb_read_bulk_complete: returned status %d\n", - s->net_dev.name, purb->status); - return; - } - - - purb->status=0; - - /* Keep it coming! resubmit the URB for reading.. Make sure - we aren't in contention with the interrupt callback. - */ - submit_read_urb("plusb_read_bulk_complete", s); -} - -/* --------------------------------------------------------------------- */ -/* - * plusb_int_complete - USB driver callback for interrupt msg from the device - * - * Interrupts are scheduled to go off on a periodic basis (see FILL_INT_URB) - * For the prolific device, this is basically just returning a register - * filled with bits. See the macro definitions for _PL_INT_XXX above. - * Most of these bits are for implementing a machine-machine protocol - * and can be set with a special message (described as the "Quicklink" - * feature in the prolific documentation.) - * - * I don't think we need any of that to work as a network device. If a - * message is lost, big deal - that's what UNIX networking expects from - * the physical layer. - * - */ -static void plusb_int_complete(urb_t *purb) -{ - plusb_t *s=purb->context; - s->status=((unsigned char*)purb->transfer_buffer)[0]&255; - -#if 0 - /* This isn't right because 0x20 is TX_RDY and - sometimes will not be set - */ - if((s->status&0x3f)!=0x20) { - warn("invalid device status %02X", s->status); - return; - } -#endif - if(!s->connected) - return; - - /* Don't turn this on unless you want to see the log flooded. */ -#if 0 - printk("plusb_int_complete: PEER_E:%d TX_REQ:%d TX_C:%d RESET_IN:%d RESET_O: %d TX_RDY:%d RES1:%d RES2:%d\n", - s->status & _PL_INT_PEER_E ? 1 : 0, - s->status & _PL_INT_TX_REQ ? 1 : 0, - s->status & _PL_INT_TX_C ? 1 : 0, - s->status & _PL_INT_RESET_I ? 1 : 0, - s->status & _PL_INT_RESET_O ? 1 : 0, - s->status & _PL_INT_TX_RDY ? 1 : 0, - s->status & _PL_INT_RES1 ? 1 : 0, - s->status & _PL_INT_RES2 ? 1 : 0); -#endif - -#if 1 - /* At first glance, this logic appears to not really be needed, but - it can help recover from intermittent problems where the - usb_submit_urb() fails in the read callback. -EZA - */ - - /* Try to submit the read URB again. Make sure - we aren't in contention with the bulk read callback - */ - submit_read_urb ("plusb_int_complete", s); - - /* While we are at it, why not check to see if the - write urb should be re-submitted? - */ - dequeue_next_skb("plusb_int_complete", s); - -#endif - -} - -/* --------------------------------------------------------------------- */ -/* - * plusb_free_all - deallocate all memory kept for an instance of the device. - */ -static void plusb_free_all(plusb_t *s) -{ - struct list_head *skb; - skb_list_t *skb_list; - - dbg("plusb_free_all"); - - /* set a flag to tell all callbacks to cease and desist */ - s->connected = 0; - - /* If the interrupt handler is about to fire, let it finish up */ - run_task_queue(&tq_immediate); - - if(s->inturb) { - dbg("unlink inturb"); - usb_unlink_urb(s->inturb); - dbg("free_urb inturb"); - usb_free_urb(s->inturb); - s->inturb=NULL; - } - - if(s->interrupt_in_buffer) { - dbg("kfree s->interrupt_in_buffer"); - kfree(s->interrupt_in_buffer); - s->interrupt_in_buffer=NULL; - } - - if(s->readurb) { - dbg("unlink readurb"); - usb_unlink_urb(s->readurb); - dbg("free_urb readurb:"); - usb_free_urb(s->readurb); - s->readurb=NULL; - } - - if(s->bulk_in_buffer) { - dbg("kfree s->bulk_in_buffer"); - kfree(s->bulk_in_buffer); - s->bulk_in_buffer=NULL; - } - - s->readurb_submitted = 0; - - if(s->writeurb) { - dbg("unlink writeurb"); - usb_unlink_urb(s->writeurb); - dbg("free_urb writeurb:"); - usb_free_urb(s->writeurb); - s->writeurb=NULL; - } - - s->writeurb_submitted = 0; - - while(!list_empty(&s->free_skb_list)) { - skb=s->free_skb_list.next; - list_del(skb); - skb_list = list_entry (skb, skb_list_t, skb_list); - kfree(skb_list); - } - - while(!list_empty(&s->tx_skb_list)) { - skb=s->tx_skb_list.next; - list_del(skb); - skb_list = list_entry (skb, skb_list_t, skb_list); - if (skb_list->skb) { - dbg ("Freeing SKB in queue"); - dev_kfree_skb_any(skb_list->skb); - skb_list->skb = NULL; - } - kfree(skb_list); - } - - s->in_bh=0; - - dbg("plusb_free_all: finished"); -} - -/*-------------------------------------------------------------------*/ -/* - * plusb_alloc - allocate memory associated with one instance of the device - */ -static int plusb_alloc(plusb_t *s) -{ - int i; - skb_list_t *skb; - - dbg("plusb_alloc"); - - for(i=0 ; i < _SKB_NUM ; i++) { - skb=kmalloc(sizeof(skb_list_t), GFP_KERNEL); - if(!skb) { - err("kmalloc for skb_list failed"); - goto reject; - } - memset(skb, 0, sizeof(skb_list_t)); - list_add(&skb->skb_list, &s->free_skb_list); - } - - dbg("inturb allocation:"); - s->inturb=usb_alloc_urb(0); - if(!s->inturb) { - err("alloc_urb failed"); - goto reject; - } - - dbg("bulk read urb allocation:"); - s->readurb=usb_alloc_urb(0); - if(!s->readurb) { - err("alloc_urb failed"); - goto reject; - } - - dbg("bulk write urb allocation:"); - s->writeurb=usb_alloc_urb(0); - if(!s->writeurb) { - err("alloc_urb for writeurb failed"); - goto reject; - } - - dbg("readurb/inturb init:"); - s->interrupt_in_buffer=kmalloc(64, GFP_KERNEL); - if(!s->interrupt_in_buffer) { - err("kmalloc failed"); - goto reject; - } - - /* The original value of '10' makes this interrupt fire off a LOT. - It was set so low because the callback determined when to - sumbit the buld read URB. I've lowered it to 100 - the driver - doesn't depend on that logic anymore. -EZA - */ - FILL_INT_URB(s->inturb, s->usbdev, - usb_rcvintpipe (s->usbdev, _PLUSB_INTPIPE), - s->interrupt_in_buffer, 1, - plusb_int_complete, s, HZ); - - dbg("inturb submission:"); - if(usb_submit_urb(s->inturb)<0) { - err("usb_submit_urb failed"); - goto reject; - } - - dbg("readurb init:"); - s->bulk_in_buffer = kmalloc(_BULK_DATA_LEN, GFP_KERNEL); - if (!s->bulk_in_buffer) { - err("kmalloc %d bytes for bulk in buffer failed", _BULK_DATA_LEN); - } - - FILL_BULK_URB(s->readurb, s->usbdev, - usb_rcvbulkpipe(s->usbdev, _PLUSB_BULKINPIPE), - s->bulk_in_buffer, _BULK_DATA_LEN, - plusb_read_bulk_complete, s); - - /* The write urb will be initialized inside the network - interrupt. - */ - - /* get the bulk read going */ - submit_read_urb("plusb_alloc", s); - - dbg ("plusb_alloc: finished. readurb=%p writeurb=%p inturb=%p", - s->readurb, s->writeurb, s->inturb); - - return 0; - - reject: - dbg("plusb_alloc: failed"); - - plusb_free_all(s); - return -ENOMEM; -} - -/*-------------------------------------------------------------------*/ - -static int plusb_net_open(struct net_device *dev) -{ - plusb_t *s=dev->priv; - - dbg("plusb_net_open"); - - if(plusb_alloc(s)) - return -ENOMEM; - - s->opened=1; - - MOD_INC_USE_COUNT; - - netif_start_queue(dev); - - dbg("plusb_net_open: success"); - - return 0; - -} - -/* --------------------------------------------------------------------- */ - -static int plusb_net_stop(struct net_device *dev) -{ - plusb_t *s=dev->priv; - - netif_stop_queue(dev); - - dbg("plusb_net_stop"); - - s->opened=0; - plusb_free_all(s); - - MOD_DEC_USE_COUNT; - dbg("plusb_net_stop:finished"); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static struct net_device_stats *plusb_net_get_stats(struct net_device *dev) -{ - plusb_t *s=dev->priv; - - dbg("net_device_stats"); - - return &s->net_stats; -} - -/* --------------------------------------------------------------------- */ - -static plusb_t *plusb_find_struct (void) -{ - int u; - - for (u = 0; u < NRPLUSB; u++) { - plusb_t *s = &plusb[u]; - if (!s->connected) - return s; - } - return NULL; -} - -/* --------------------------------------------------------------------- */ - -static void plusb_disconnect (struct usb_device *usbdev, void *ptr) -{ - plusb_t *s = ptr; - - dbg("plusb_disconnect"); - - plusb_free_all(s); - - if(!s->opened && s->net_dev.name) { - dbg("unregistering netdev: %s",s->net_dev.name); - unregister_netdev(&s->net_dev); - s->net_dev.name[0] = '\0'; -#if (LINUX_VERSION_CODE < 0x020300) - dbg("plusb_disconnect: About to free name"); - kfree (s->net_dev.name); - s->net_dev.name = NULL; -#endif - } - - dbg("plusb_disconnect: finished"); - MOD_DEC_USE_COUNT; -} - -/* --------------------------------------------------------------------- */ - -static int plusb_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > _BULK_DATA_LEN)) - return -EINVAL; - - printk("plusb: changing mtu to %d\n", new_mtu); - dev->mtu = new_mtu; - - /* NOTE: Could we change the size of the READ URB here dynamically - to save kernel memory? - */ - return 0; -} - -/* --------------------------------------------------------------------- */ - -int plusb_net_init(struct net_device *dev) -{ - dbg("plusb_net_init"); - - dev->open=plusb_net_open; - dev->stop=plusb_net_stop; - dev->hard_start_xmit=plusb_net_xmit; - dev->get_stats = plusb_net_get_stats; - ether_setup(dev); - dev->change_mtu = plusb_change_mtu; - /* Setting the default MTU to 16K gives good performance for - me, and keeps the ping latency low too. Setting it up - to 32K made performance go down. -EZA - Pavel says it would be best not to do this... - */ - /*dev->mtu=16384; */ - dev->tx_queue_len = 0; - dev->flags = IFF_POINTOPOINT|IFF_NOARP; - - - dbg("plusb_net_init: finished"); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void *plusb_probe (struct usb_device *usbdev, unsigned int ifnum, const struct usb_device_id *id) -{ - plusb_t *s; - - dbg("plusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d", - usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum); - - if (usbdev->descriptor.idVendor != 0x067b || usbdev->descriptor.idProduct > 0x1) - return NULL; - - /* We don't handle multiple configurations */ - if (usbdev->descriptor.bNumConfigurations != 1) - return NULL; - - s = plusb_find_struct (); - if (!s) - return NULL; - - s->usbdev = usbdev; - - if (usb_set_configuration (s->usbdev, usbdev->config[0].bConfigurationValue) < 0) { - err("set_configuration failed"); - return NULL; - } - - if (usb_set_interface (s->usbdev, 0, 0) < 0) { - err("set_interface failed"); - return NULL; - } - -#if (LINUX_VERSION_CODE < 0x020300) - { - int i; - - /* For Kernel version 2.2, the driver is responsible for - allocating this memory. For version 2.4, the rules - have apparently changed, but there is a nifty function - 'init_netdev' that might make this easier... It's in - ../net/net_init.c - but can we get there from here? (no) - -EZA - */ - - /* Find the device number... we seem to have lost it... -EZA */ - for (i=0; inet_dev.name) { - s->net_dev.name = kmalloc(strlen("plusbXXXX"), GFP_KERNEL); - sprintf (s->net_dev.name, "plusb%d", i); - s->net_dev.init=plusb_net_init; - s->net_dev.priv=s; - - printk ("plusb_probe: Registering Device\n"); - if(!register_netdev(&s->net_dev)) - info("registered: %s", s->net_dev.name); - else { - err("register_netdev failed"); - s->net_dev.name[0] = '\0'; - } - dbg ("plusb_probe: Connected!"); - } - } -#else - /* Kernel version 2.3+ works a little bit differently than 2.2 */ - if(!s->net_dev.name[0]) { - strcpy(s->net_dev.name, "plusb%d"); - s->net_dev.init=plusb_net_init; - s->net_dev.priv=s; - if(!register_netdev(&s->net_dev)) - info("registered: %s", s->net_dev.name); - else { - err("register_netdev failed"); - s->net_dev.name[0] = '\0'; - } - } -#endif - - s->connected = 1; - - if(s->opened) { - dbg("net device already allocated, restarting USB transfers"); - plusb_alloc(s); - } - - info("bound to interface: %d dev: %p", ifnum, usbdev); - MOD_INC_USE_COUNT; - return s; -} -/* --------------------------------------------------------------------- */ - -static struct usb_driver plusb_driver = -{ - name: "plusb", - probe: plusb_probe, - disconnect: plusb_disconnect, -}; - -/* --------------------------------------------------------------------- */ - -static int __init plusb_init (void) -{ - unsigned u; - dbg("plusb_init"); - - /* initialize struct */ - for (u = 0; u < NRPLUSB; u++) { - plusb_t *s = &plusb[u]; - memset (s, 0, sizeof (plusb_t)); - INIT_LIST_HEAD (&s->tx_skb_list); - INIT_LIST_HEAD (&s->free_skb_list); - spin_lock_init (&s->lock); - } - - /* register misc device */ - usb_register (&plusb_driver); - - dbg("plusb_init: driver registered"); - - info(DRIVER_VERSION ":" DRIVER_DESC); - - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void __exit plusb_cleanup (void) -{ - unsigned u; - - dbg("plusb_cleanup"); - for (u = 0; u < NRPLUSB; u++) { - plusb_t *s = &plusb[u]; -#if (LINUX_VERSION_CODE < 0x020300) - if(s->net_dev.name) { - dbg("unregistering netdev: %s",s->net_dev.name); - unregister_netdev(&s->net_dev); - s->net_dev.name[0] = '\0'; - kfree (s->net_dev.name); - s->net_dev.name = NULL; - } -#else - if(s->net_dev.name[0]) { - dbg("unregistering netdev: %s",s->net_dev.name); - unregister_netdev(&s->net_dev); - s->net_dev.name[0] = '\0'; - } -#endif - } - usb_deregister (&plusb_driver); - dbg("plusb_cleanup: finished"); -} - -/* --------------------------------------------------------------------- */ - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); - - -module_init (plusb_init); -module_exit (plusb_cleanup); - -/* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.4.9/linux/drivers/usb/printer.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/printer.c Tue Aug 28 14:36:18 2001 @@ -230,7 +230,7 @@ goto out; } #else - retval = 0; + retval = 0; #endif usblp->used = 1; @@ -242,7 +242,11 @@ if (usblp->bidir) { usblp->readcount = 0; usblp->readurb.dev = usblp->dev; - usb_submit_urb(&usblp->readurb); + if (usb_submit_urb(&usblp->readurb) < 0) { + retval = -EIO; + usblp->used = 0; + file->private_data = NULL; + } } out: unlock_kernel(); @@ -265,6 +269,7 @@ struct usblp *usblp = file->private_data; down (&usblp->sem); + lock_kernel(); usblp->used = 0; if (usblp->dev) { if (usblp->bidir) @@ -273,6 +278,7 @@ up(&usblp->sem); } else /* finish cleanup from disconnect */ usblp_cleanup (usblp); + unlock_kernel(); return 0; } @@ -299,7 +305,7 @@ } if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */ - + switch (_IOC_NR(cmd)) { case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */ @@ -658,7 +664,7 @@ #endif sprintf(name, "lp%d", minor); - + /* if we have devfs, create with perms=660 */ usblp->devfs = devfs_register(usb_devfs_handle, name, DEVFS_FL_DEFAULT, USB_MAJOR, @@ -682,6 +688,7 @@ } down (&usblp->sem); + lock_kernel(); usblp->dev = NULL; usb_unlink_urb(&usblp->writeurb); @@ -692,6 +699,7 @@ usblp_cleanup (usblp); else /* cleanup later, on close */ up (&usblp->sem); + unlock_kernel(); } static struct usb_device_id usblp_ids [] = { diff -u --recursive --new-file v2.4.9/linux/drivers/usb/pwc-if.c linux/drivers/usb/pwc-if.c --- v2.4.9/linux/drivers/usb/pwc-if.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/pwc-if.c Fri Sep 7 09:28:37 2001 @@ -312,13 +312,13 @@ /* create frame buffers, and make circular ring */ for (i = 0; i < default_fbufs; i++) { if (pdev->fbuf[i].data == NULL) { - kbuf = vmalloc(FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ + kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ if (kbuf == NULL) { Err("Failed to allocate frame buffer %d.\n", i); return -ENOMEM; } pdev->fbuf[i].data = kbuf; - memset(kbuf, 0, FRAME_SIZE); + memset(kbuf, 0, PWC_FRAME_SIZE); } } @@ -1807,6 +1807,7 @@ MODULE_DESCRIPTION("Philips USB webcam driver"); MODULE_AUTHOR("Nemosoft Unv. "); +MODULE_LICENSE("GPL"); static int __init usb_pwc_init(void) { diff -u --recursive --new-file v2.4.9/linux/drivers/usb/pwc.h linux/drivers/usb/pwc.h --- v2.4.9/linux/drivers/usb/pwc.h Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/pwc.h Fri Sep 7 09:28:37 2001 @@ -77,7 +77,7 @@ /* Frame buffers: contains compressed or uncompressed video data. */ #define MAX_FRAMES 5 /* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */ -#define FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE) +#define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE) /* Absolute maximum number of buffers available for mmap() */ #define MAX_IMAGES 4 diff -u --recursive --new-file v2.4.9/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c --- v2.4.9/linux/drivers/usb/rio500.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/rio500.c Tue Aug 28 11:21:02 2001 @@ -120,13 +120,17 @@ unsigned char *buffer; int result, requesttype; int retries; - int retval; + int retval=0; + down(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || rio->rio_dev == NULL ) - return -1; + { + retval = -ENODEV; + goto err_out; + } switch (cmd) { case RIO_RECV_COMMAND: @@ -142,8 +146,10 @@ goto err_out; } buffer = (unsigned char *) __get_free_page(GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; + if (buffer == NULL) { + retval = -ENOMEM; + goto err_out; + } if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) { retval = -EFAULT; free_page((unsigned long) buffer); @@ -158,7 +164,6 @@ rio_cmd.index, rio_cmd.length); /* Send rio control message */ retries = 3; - down(&(rio->lock)); while (retries) { result = usb_control_msg(rio->rio_dev, usb_rcvctrlpipe(rio-> rio_dev, 0), @@ -180,7 +185,6 @@ le32_to_cpu(*((long *) buffer))); if (copy_to_user(rio_cmd.buffer, buffer, rio_cmd.length)) { - up(&(rio->lock)); free_page((unsigned long) buffer); retval = -EFAULT; goto err_out; @@ -196,7 +200,6 @@ be swapped at the app level */ } - up(&(rio->lock)); free_page((unsigned long) buffer); break; @@ -204,16 +207,23 @@ data = (void *) arg; if (data == NULL) break; - if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) - return -EFAULT; - if (rio_cmd.length > PAGE_SIZE) - return -EINVAL; + if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) { + retval = -EFAULT; + goto err_out; + } + if (rio_cmd.length > PAGE_SIZE) { + retval = -EINVAL; + goto err_out; + } buffer = (unsigned char *) __get_free_page(GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; + if (buffer == NULL) { + retval = -ENOMEM; + goto err_out; + } if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) { free_page((unsigned long)buffer); - return -EFAULT; + retval = -EFAULT; + goto err_out; } requesttype = rio_cmd.requesttype | USB_DIR_OUT | @@ -223,7 +233,6 @@ rio_cmd.index, rio_cmd.length); /* Send rio control message */ retries = 3; - down(&(rio->lock)); while (retries) { result = usb_control_msg(rio->rio_dev, usb_sndctrlpipe(rio-> rio_dev, 0), @@ -247,16 +256,14 @@ } } - up(&(rio->lock)); free_page((unsigned long) buffer); break; default: - return -ENOIOCTLCMD; + retval = -ENOTTY; break; } - return 0; err_out: up(&(rio->lock)); @@ -277,13 +284,17 @@ int maxretry; int errn = 0; + down(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || rio->rio_dev == NULL ) - return -1; + { + up(&(rio->lock)); + return -ENODEV; + } + - down(&(rio->lock)); do { unsigned long thistime; @@ -356,17 +367,20 @@ int maxretry = 10; char *ibuf; - /* Sanity check to make sure rio is connected, powered, etc */ + down(&(rio->lock)); + /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || rio->rio_dev == NULL ) - return -1; + { + up(&(rio->lock)); + return -ENODEV; + } ibuf = rio->ibuf; read_count = 0; - down(&(rio->lock)); while (count > 0) { if (signal_pending(current)) { @@ -461,7 +475,7 @@ S_IWGRP, &usb_rio_fops, NULL); if (rio->devfs == NULL) dbg("probe_rio: device node registration failed"); - + init_MUTEX(&(rio->lock)); return rio; @@ -473,10 +487,12 @@ devfs_unregister(rio->devfs); + down(&(rio->lock)); if (rio->isopen) { rio->isopen = 0; /* better let it finish - the release will do whats needed */ rio->rio_dev = NULL; + up(&(rio->lock)); return; } kfree(rio->ibuf); @@ -485,6 +501,7 @@ info("USB Rio disconnected."); rio->present = 0; + up(&(rio->lock)); } static struct usb_device_id rio_table [] = { diff -u --recursive --new-file v2.4.9/linux/drivers/usb/se401.c linux/drivers/usb/se401.c --- v2.4.9/linux/drivers/usb/se401.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/se401.c Fri Sep 7 10:59:04 2001 @@ -25,7 +25,7 @@ * - Jeroen Vreeken */ -static const char version[] = "0.22"; +static const char version[] = "0.23"; #include #include @@ -1034,8 +1034,8 @@ } } } - - if (se401->frame[framenr].grabstate==FRAME_DONE) + + if (se401->frame[framenr].grabstate==FRAME_DONE) if (se401->enhance) enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3); return 0; @@ -1054,32 +1054,27 @@ struct usb_se401 *se401 = (struct usb_se401 *)dev; int err = 0; + /* we are called with the BKL held */ MOD_INC_USE_COUNT; - down(&se401->lock); + se401->user=1; se401->fbuf=rvmalloc(se401->maxframesize * SE401_NUMFRAMES); if(!se401->fbuf) err=-ENOMEM; if (err) { MOD_DEC_USE_COUNT; - up(&se401->lock); - return err; + se401->user = 0; } - - se401->user=1; - up(&se401->lock); - - return 0; + return err; } static void se401_close(struct video_device *dev) { + /* called with BKL held */ struct usb_se401 *se401 = (struct usb_se401 *)dev; int i; - down(&se401->lock); - for (i=0; iframe[i].grabstate=FRAME_UNUSED; if (se401->streaming) @@ -1087,9 +1082,8 @@ rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); se401->user=0; - up(&se401->lock); - if (!se401->dev) { + if (se401->removed) { video_unregister_device(&se401->vdev); kfree(se401->width); kfree(se401->height); @@ -1205,7 +1199,7 @@ return -EINVAL; if (se401_set_size(se401, vw.width, vw.height)) return -EINVAL; - + return 0; } case VIDIOCGWIN: @@ -1280,7 +1274,7 @@ if(frame <0 || frame >= SE401_NUMFRAMES) return -EINVAL; - + ret=se401_newframe(se401, frame); se401->frame[frame].grabstate=FRAME_UNUSED; return ret; @@ -1350,12 +1344,12 @@ ret=se401_newframe(se401, 0); - if (!ret) { - copy_to_user(buf, se401->frame[0].data, realcount); - } else { - realcount=ret; - } se401->frame[0].grabstate=FRAME_UNUSED; + if (ret) + return ret; + if (copy_to_user(buf, se401->frame[0].data, realcount)) + return -EFAULT; + return realcount; return realcount; } @@ -1368,7 +1362,7 @@ unsigned long page, pos; down(&se401->lock); - + if (se401->dev == NULL) { up(&se401->lock); return -EIO; @@ -1487,7 +1481,7 @@ info("int urb burned down"); return 1; } - + /* Flash the led */ se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); @@ -1555,33 +1549,45 @@ info("firmware version: %02x", dev->descriptor.bcdDevice & 255); - if (se401_init(se401)) + if (se401_init(se401)) { + kfree(se401); return NULL; + } + memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); + init_waitqueue_head(&se401->wq); + init_MUTEX(&se401->lock); + wmb(); + if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + kfree(se401); err("video_register_device failed"); return NULL; } info("registered new video device: video%d", se401->vdev.minor); - init_waitqueue_head(&se401->wq); - init_MUTEX(&se401->lock); - return se401; } static void se401_disconnect(struct usb_device *dev, void *ptr) { - int i; struct usb_se401 *se401 = (struct usb_se401 *) ptr; + lock_kernel(); /* We don't want people trying to open up the device */ - if (!se401->user) - video_unregister_device(&se401->vdev); + if (!se401->user){ + video_unregister_device(&se401->vdev); + usb_se401_remove_disconnected(se401); + } else { + se401->removed = 1; + } + unlock_kernel(); +} - usb_driver_release_interface(&se401_driver, - &se401->dev->actconfig->interface[se401->iface]); +static inline void usb_se401_remove_disconnected (struct usb_se401 *se401) +{ + int i; se401->dev = NULL; se401->frame[0].grabstate = FRAME_ERROR; @@ -1589,8 +1595,7 @@ se401->streaming = 0; - if (waitqueue_active(&se401->wq)) - wake_up_interruptible(&se401->wq); + wake_up_interruptible(&se401->wq); for (i=0; iurb[i]) { se401->urb[i]->next = NULL; @@ -1613,14 +1618,10 @@ #endif /* Free the memory */ - if (!se401->user) { - kfree(se401->width); - kfree(se401->height); - kfree(se401); - se401 = NULL; - } + kfree(se401->width); + kfree(se401->height); + kfree(se401); } - static struct usb_driver se401_driver = { name: "se401", diff -u --recursive --new-file v2.4.9/linux/drivers/usb/se401.h linux/drivers/usb/se401.h --- v2.4.9/linux/drivers/usb/se401.h Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/se401.h Fri Sep 7 10:59:04 2001 @@ -191,6 +191,7 @@ struct semaphore lock; int user; /* user count for exclusive use */ + int removed; /* device disconnected */ int streaming; /* Are we streaming video? */ @@ -228,6 +229,8 @@ int nullpackets; }; + +static inline void usb_se401_remove_disconnected (struct usb_se401 *se401); #endif diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in --- v2.4.9/linux/drivers/usb/serial/Config.in Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/serial/Config.in Tue Aug 28 11:21:02 2001 @@ -15,7 +15,7 @@ dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL - dep_tristate ' USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL + dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL dep_tristate ' USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/belkin_sa.c linux/drivers/usb/serial/belkin_sa.c --- v2.4.9/linux/drivers/usb/serial/belkin_sa.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/belkin_sa.c Tue Aug 28 11:21:02 2001 @@ -551,7 +551,8 @@ case TIOCMSET: /* Turns on and off the lines as specified by the mask */ case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ - if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (get_user(mask, (unsigned long *) arg)) + return -EFAULT; if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { /* RTS needs set */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/cyberjack.c linux/drivers/usb/serial/cyberjack.c --- v2.4.9/linux/drivers/usb/serial/cyberjack.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/cyberjack.c Tue Aug 28 11:21:02 2001 @@ -241,7 +241,8 @@ /* Copy data */ if (from_user) { - copy_from_user(priv->wrbuf+priv->wrfilled, buf, count); + if (copy_from_user(priv->wrbuf+priv->wrfilled, buf, count)) + return -EFAULT; } else { memcpy (priv->wrbuf+priv->wrfilled, buf, count); } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c --- v2.4.9/linux/drivers/usb/serial/digi_acceleport.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/digi_acceleport.c Tue Aug 28 11:21:02 2001 @@ -409,11 +409,6 @@ #define DIGI_READ_INPUT_SIGNALS_DCD 128 -/* macros */ -#define MAX(a,b) (((a)>(b))?(a):(b)) -#define MIN(a,b) (((a)<(b))?(a):(b)) - - /* Structures */ typedef struct digi_serial { @@ -675,7 +670,7 @@ } /* len must be a multiple of 4, so commands are not split */ - len = MIN( count, oob_port->bulk_out_size ); + len = min(int, count, oob_port->bulk_out_size ); if( len > 4 ) len &= ~3; @@ -752,7 +747,7 @@ /* len must be a multiple of 4 and small enough to */ /* guarantee the write will send buffered data first, */ /* so commands are in order with data and not split */ - len = MIN( count, port->bulk_out_size-2-priv->dp_out_buf_len ); + len = min(int, count, port->bulk_out_size-2-priv->dp_out_buf_len ); if( len > 4 ) len &= ~3; @@ -956,7 +951,7 @@ spin_lock_irqsave( &priv->dp_port_lock, flags ); /* send any buffered chars from throttle time on to tty subsystem */ - len = MIN( priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count ); + len = min(int, priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count ); if( len > 0 ) { memcpy( tty->flip.char_buf_ptr, priv->dp_in_buf, len ); memcpy( tty->flip.flag_buf_ptr, priv->dp_in_flag_buf, len ); @@ -1277,7 +1272,7 @@ priv->dp_port_num, count, from_user, in_interrupt() ); /* copy user data (which can sleep) before getting spin lock */ - count = MIN( 64, MIN( count, port->bulk_out_size-2 ) ); + count = min(int, 64, min(int, count, port->bulk_out_size-2 ) ); if( from_user && copy_from_user( user_buf, buf, count ) ) { return( -EFAULT ); } @@ -1308,7 +1303,7 @@ /* allow space for any buffered data and for new data, up to */ /* transfer buffer size - 2 (for command and length bytes) */ - new_len = MIN( count, port->bulk_out_size-2-priv->dp_out_buf_len ); + new_len = min(int, count, port->bulk_out_size-2-priv->dp_out_buf_len ); data_len = new_len + priv->dp_out_buf_len; if( data_len == 0 ) { @@ -1934,7 +1929,7 @@ if( throttled ) { - len = MIN( len, + len = min( int, len, DIGI_IN_BUF_SIZE - priv->dp_in_buf_len ); if( len > 0 ) { @@ -1947,7 +1942,7 @@ } else { - len = MIN( len, TTY_FLIPBUF_SIZE - tty->flip.count ); + len = min( int, len, TTY_FLIPBUF_SIZE - tty->flip.count ); if( len > 0 ) { memcpy( tty->flip.char_buf_ptr, data, len ); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c --- v2.4.9/linux/drivers/usb/serial/empeg.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/serial/empeg.c Tue Aug 28 11:21:02 2001 @@ -85,8 +85,6 @@ #define EMPEG_VENDOR_ID 0x084f #define EMPEG_PRODUCT_ID 0x0001 -#define MIN(a,b) (((a)<(b))?(a):(b)) - /* function prototypes for an empeg-car player */ static int empeg_open (struct usb_serial_port *port, struct file *filp); static void empeg_close (struct usb_serial_port *port, struct file *filp); @@ -278,10 +276,13 @@ } } - transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE); + transfer_size = min (int, count, URB_TRANSFER_BUFFER_SIZE); if (from_user) { - copy_from_user (urb->transfer_buffer, current_position, transfer_size); + if (copy_from_user (urb->transfer_buffer, current_position, transfer_size)) { + bytes_sent = -EFAULT; + break; + } } else { memcpy (urb->transfer_buffer, current_position, transfer_size); } @@ -301,8 +302,11 @@ /* send it down the pipe */ status = usb_submit_urb(urb); - if (status) - dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + if (status) { + err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + bytes_sent = status; + break; + } current_position += transfer_size; bytes_sent += transfer_size; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c --- v2.4.9/linux/drivers/usb/serial/ftdi_sio.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/serial/ftdi_sio.c Tue Aug 28 11:21:02 2001 @@ -470,8 +470,9 @@ /* Copy in the data to send */ if (from_user) { - copy_from_user(port->write_urb->transfer_buffer + data_offset , - buf, count - data_offset ); + if (copy_from_user(port->write_urb->transfer_buffer + data_offset, + buf, count - data_offset )) + return -EFAULT; } else { memcpy(port->write_urb->transfer_buffer + data_offset, diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/io_edgeport.c linux/drivers/usb/serial/io_edgeport.c --- v2.4.9/linux/drivers/usb/serial/io_edgeport.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/serial/io_edgeport.c Tue Aug 28 11:21:02 2001 @@ -236,7 +236,7 @@ #include #include #include -#include +#include #include #include #include @@ -1311,7 +1311,7 @@ fifo = &edge_port->txfifo; // calculate number of bytes to put in fifo - copySize = MIN(count, (edge_port->txCredits - fifo->count)); + copySize = min (int, count, (edge_port->txCredits - fifo->count)); dbg(__FUNCTION__"(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", port->number, count, edge_port->txCredits - fifo->count, copySize); @@ -1329,12 +1329,13 @@ // then copy the reset from the start of the buffer bytesleft = fifo->size - fifo->head; - firsthalf = MIN(bytesleft,copySize); + firsthalf = min (int, bytesleft, copySize); dbg (__FUNCTION__" - copy %d bytes of %d into fifo ", firsthalf, bytesleft); /* now copy our data */ if (from_user) { - copy_from_user(&fifo->fifo[fifo->head], data, firsthalf); + if (copy_from_user(&fifo->fifo[fifo->head], data, firsthalf)) + return -EFAULT; } else { memcpy(&fifo->fifo[fifo->head], data, firsthalf); } @@ -1353,7 +1354,8 @@ if (secondhalf) { dbg (__FUNCTION__" - copy rest of data %d", secondhalf); if (from_user) { - copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); + if (copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf)) + return -EFAULT; } else { memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); } @@ -1452,7 +1454,7 @@ /* now copy our data */ bytesleft = fifo->size - fifo->tail; - firsthalf = MIN(bytesleft,count); + firsthalf = min (int, bytesleft, count); memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf); fifo->tail += firsthalf; fifo->count -= firsthalf; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/io_edgeport.h linux/drivers/usb/serial/io_edgeport.h --- v2.4.9/linux/drivers/usb/serial/io_edgeport.h Mon Mar 19 17:21:54 2001 +++ linux/drivers/usb/serial/io_edgeport.h Tue Aug 28 11:21:02 2001 @@ -25,16 +25,6 @@ #ifndef FALSE #define FALSE (0) #endif -#ifndef MIN - #define MIN(a,b) (((a)<(b))?(a):(b)) -#endif -#ifndef MAX - #define MAX(a,b) (((a)>(b))?(a):(b)) -#endif -#ifndef max - #define max MAX -#endif - #ifndef LOW8 #define LOW8(a) ((unsigned char)(a & 0xff)) #endif diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c --- v2.4.9/linux/drivers/usb/serial/keyspan.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/keyspan.c Tue Aug 28 11:21:02 2001 @@ -349,7 +349,8 @@ ((char *)this_urb->transfer_buffer)[0] = 0; if (from_user) { - copy_from_user(this_urb->transfer_buffer + 1, buf, todo); + if (copy_from_user(this_urb->transfer_buffer + 1, buf, todo)) + return -EFAULT; } else { memcpy (this_urb->transfer_buffer + 1, buf, todo); } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/mct_u232.c linux/drivers/usb/serial/mct_u232.c --- v2.4.9/linux/drivers/usb/serial/mct_u232.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/mct_u232.c Tue Aug 28 11:21:02 2001 @@ -94,7 +94,7 @@ */ #undef FIX_WRITE_RETURN_CODE_PROBLEM #ifdef FIX_WRITE_RETURN_CODE_PROBLEM -static int write_blocking = 0; /* disabled by default */ +static int write_blocking; /* disabled by default */ #endif /* @@ -524,7 +524,10 @@ usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf); if (from_user) { - copy_from_user(port->write_urb->transfer_buffer, buf, size); + if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) { + up (&port->sem); + return -EFAULT; + } } else { memcpy (port->write_urb->transfer_buffer, buf, size); @@ -815,7 +818,7 @@ { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = (struct mct_u232_private *)port->private; - int ret, mask; + int mask; dbg (__FUNCTION__ "cmd=0x%x", cmd); @@ -828,7 +831,8 @@ case TIOCMSET: /* Turns on and off the lines as specified by the mask */ case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ - if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (get_user(mask, (unsigned long *) arg)) + return -EFAULT; if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { /* RTS needs set */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/pl2303.c linux/drivers/usb/serial/pl2303.c --- v2.4.9/linux/drivers/usb/serial/pl2303.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/pl2303.c Fri Sep 7 10:59:04 2001 @@ -12,6 +12,13 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * 2001_Aug_30 gkh + * fixed oops in write_bulk_callback. + * + * 2001_Aug_28 gkh + * reworked buffer logic to be like other usb-serial drivers. Hopefully + * removing some reported problems. + * * 2001_Jun_06 gkh * finished porting to 2.4 format. * @@ -46,26 +53,10 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.5" +#define DRIVER_VERSION "v0.7" #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - - -#define PL2303_LOCK(port,flags) \ - do { \ - spin_lock_irqsave(&((struct pl2303_private *)(port->private))->lock, flags); \ - } while (0) - -#define PL2303_UNLOCK(port,flags) \ - do { \ - spin_unlock_irqrestore(&((struct pl2303_private *)(port->private))->lock, flags); \ - } while (0) - - static __devinitdata struct usb_device_id id_table [] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, @@ -75,33 +66,20 @@ MODULE_DEVICE_TABLE (usb, id_table); -struct pl2303_private { - spinlock_t lock; - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; -}; /* function prototypes for a PL2303 serial converter */ -static int pl2303_startup (struct usb_serial *serial); static int pl2303_open (struct usb_serial_port *port, struct file *filp); static void pl2303_close (struct usb_serial_port *port, struct file *filp); static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old); static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); -static void pl2303_throttle (struct usb_serial_port *port); -static void pl2303_unthrottle (struct usb_serial_port *port); static void pl2303_read_int_callback (struct urb *urb); static void pl2303_read_bulk_callback (struct urb *urb); static void pl2303_write_bulk_callback (struct urb *urb); static int pl2303_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); -static int pl2303_write_room(struct usb_serial_port *port); -static int pl2303_chars_in_buffer(struct usb_serial_port *port); static void pl2303_break_ctl(struct usb_serial_port *port,int break_state); -static void start_xmit (struct usb_serial_port *port); /* All of the device info needed for the PL2303 SIO serial converter */ @@ -117,172 +95,54 @@ num_ports: 1, open: pl2303_open, close: pl2303_close, - throttle: pl2303_throttle, - unthrottle: pl2303_unthrottle, write: pl2303_write, ioctl: pl2303_ioctl, - write_room: pl2303_write_room, - chars_in_buffer: pl2303_chars_in_buffer, break_ctl: pl2303_break_ctl, set_termios: pl2303_set_termios, read_bulk_callback: pl2303_read_bulk_callback, read_int_callback: pl2303_read_int_callback, write_bulk_callback: pl2303_write_bulk_callback, - startup: pl2303_startup, }; -#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ -static unsigned char *tmp_buf; -static DECLARE_MUTEX (tmp_buf_sem); - - - -static int -pl2303_write (struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count) -{ /* pl2303_write */ - struct pl2303_private *info = (struct pl2303_private *)port->private; - unsigned long flags; - int c,ret=0; - struct tty_struct *tty=port->tty; +static int pl2303_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +{ + int result; - dbg ("pl2303_write port %d, %d bytes", port->number, count); + dbg (__FUNCTION__ " - port %d, %d bytes", port->number, count); - if (!info) { - return -ENODEV; + if (!port->tty) { + err (__FUNCTION__ " - no tty???"); + return 0; } - if (!tty || !info->xmit_buf || !tmp_buf) { + if (port->write_urb->status == -EINPROGRESS) { + dbg (__FUNCTION__ " - already writing"); return 0; } - - PL2303_LOCK(port,flags); - - + count = (count > port->bulk_out_size) ? port->bulk_out_size : count; if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) { - ret = -EFAULT; - } - break; - } - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); + if (copy_from_user (port->write_urb->transfer_buffer, buf, count)) + return -EFAULT; } else { - while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - buf += c; - count -= c; - ret += c; - } - } - PL2303_UNLOCK(port, flags); - - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { - start_xmit(port); + memcpy (port->write_urb->transfer_buffer, buf, count); } - return ret; -} - -static int pl2303_write_room(struct usb_serial_port *port) -{ - struct pl2303_private *info = (struct pl2303_private *)port->private; - int ret; - - if (!info) - return 0; + + usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer); - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} - -static int pl2303_chars_in_buffer(struct usb_serial_port *port) -{ - struct pl2303_private *info = (struct pl2303_private *)port->private; - - if (!info) - return 0; + port->write_urb->transfer_buffer_length = count; + port->write_urb->dev = port->serial->dev; + result = usb_submit_urb (port->write_urb); + if (result) + err(__FUNCTION__ " - failed submitting write urb, error %d", result); + else + result = count; - return info->xmit_cnt; + return result; } -static void pl2303_throttle(struct usb_serial_port *port) -{ -#if 0 - //struct usb_serial *serial = port->serial; - struct tty_struct *tty=port->tty; - unsigned long flags; - - - char buf[64]; - - dbg("throttle %s: %d....", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); - -//FIXME FIXME FIXME - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); - - PL2303_LOCK(port,flags); - //Should remove read request if one is present - PL2303_UNLOCK(port,flags); -#endif -} - -static void pl2303_unthrottle(struct usb_serial_port *port) -{ -#if 0 - //struct usb_serial *serial = port->serial; - struct tty_struct *tty=port->tty; - unsigned long flags; - - - char buf[64]; - - dbg("unthrottle %s: %d....", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); - - //FIXME FIXME FIXME FIXME FIXME - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - rs_send_xchar(tty, START_CHAR(tty)); - } - - PL2303_LOCK(port,flags); - //Should add read request if one is not present - PL2303_UNLOCK(fport,flags); -#endif -} static void @@ -314,6 +174,10 @@ if (cflag & CSIZE) { switch (cflag & CSIZE) { + case CS5: + buf[6] = 5; + dbg ("Setting CS5"); + break; case CS6: buf[6] = 6; dbg ("Setting CS6"); @@ -327,47 +191,29 @@ dbg ("Setting CS8"); break; default: - err ("CSIZE was set but not CS6-CS8"); + err ("CSIZE was set but not CS5-CS8"); } } baud = 0; switch (cflag & CBAUD) { - case B0: - err ("Can't do B0 yet"); //FIXME - break; - case B300: - baud = 300; - break; - case B600: - baud = 600; - break; - case B1200: - baud = 1200; - break; - case B2400: - baud = 2400; - break; - case B4800: - baud = 4800; - break; - case B9600: - baud = 9600; - break; - case B19200: - baud = 19200; - break; - case B38400: - baud = 38400; - break; - case B57600: - baud = 57600; - break; - case B115200: - baud = 115200; - break; + case B75: baud = 75; break; + case B150: baud = 150; break; + case B300: baud = 300; break; + case B600: baud = 600; break; + case B1200: baud = 1200; break; + case B1800: baud = 1800; break; + case B2400: baud = 2400; break; + case B4800: baud = 4800; break; + case B9600: baud = 9600; break; + case B19200: baud = 19200; break; + case B38400: baud = 38400; break; + case B57600: baud = 57600; break; + case B115200: baud = 115200; break; + case B230400: baud = 230400; break; + case B460800: baud = 460800; break; default: - dbg ("pl2303 driver does not support the baudrate requested (fix it)"); + err ("pl2303 driver does not support the baudrate requested (fix it)"); break; } @@ -379,7 +225,9 @@ } + /* For reference buf[4]=0 is 1 stop bits */ /* For reference buf[4]=1 is 1.5 stop bits */ + /* For reference buf[4]=2 is 2 stop bits */ if (cflag & CSTOPB) { buf[4] = 2; @@ -387,6 +235,9 @@ if (cflag & PARENB) { + /* For reference buf[5]=0 is none parity */ + /* For reference buf[5]=1 is odd parity */ + /* For reference buf[5]=2 is even parity */ /* For reference buf[5]=3 is mark parity */ /* For reference buf[5]=4 is space parity */ if (cflag & PARODD) { @@ -433,169 +284,108 @@ } -static int -pl2303_open (struct usb_serial_port *port, struct file *filp) -{ /* pl2303_open */ +static int pl2303_open (struct usb_serial_port *port, struct file *filp) +{ struct termios tmp_termios; struct usb_serial *serial = port->serial; unsigned char buf[10]; - int i; + int result; - dbg ("pl2303_open port %d", port->number); + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; + + dbg (__FUNCTION__ "- port %d", port->number); - port->active++; + down (&port->sem); -#define FISH(a,b,c,d) \ - i=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \ - b, a,c , d, buf, 1, 100); \ - dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,i,buf[0]); - -#define SOUP(a,b,c,d) \ - i=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \ - b, a,c , d, NULL, 0, 100); \ - dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,i); - - - FISH (0xc0, 1, 0x8484, 0); - SOUP (0x40, 1, 0x0404, 0); - FISH (0xc0, 1, 0x8484, 0); - FISH (0xc0, 1, 0x8383, 0); - FISH (0xc0, 1, 0x8484, 0); - SOUP (0x40, 1, 0x0404, 1); - FISH (0xc0, 1, 0x8484, 0); - FISH (0xc0, 1, 0x8383, 0); - SOUP (0x40, 1, 0, 1); - SOUP (0x40, 1, 1, 0xc0); - SOUP (0x40, 1, 2, 4); + ++port->open_count; + MOD_INC_USE_COUNT; - /* Setup termios */ + if (!port->active) { + port->active = 1; + +#define FISH(a,b,c,d) \ + result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \ + b, a, c, d, buf, 1, 100); \ + dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,result,buf[0]); + +#define SOUP(a,b,c,d) \ + result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \ + b, a, c , d, NULL, 0, 100); \ + dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,result); + + FISH (0xc0, 1, 0x8484, 0); + SOUP (0x40, 1, 0x0404, 0); + FISH (0xc0, 1, 0x8484, 0); + FISH (0xc0, 1, 0x8383, 0); + FISH (0xc0, 1, 0x8484, 0); + SOUP (0x40, 1, 0x0404, 1); + FISH (0xc0, 1, 0x8484, 0); + FISH (0xc0, 1, 0x8383, 0); + SOUP (0x40, 1, 0, 1); + SOUP (0x40, 1, 1, 0xc0); + SOUP (0x40, 1, 2, 4); - if (port->active == 1) { + /* Setup termios */ *(port->tty->termios) = tty_std_termios; port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - } - - - pl2303_set_termios (port, &tmp_termios); - - //FIXME: need to assert RTS and DTR if CRTSCTS off - - - if (port->active == 1) { - struct pl2303_private *info; - unsigned long flags,page; - int i; - - info = (struct pl2303_private *)kmalloc (sizeof(struct pl2303_private), GFP_KERNEL); - if (info == NULL) { - err(__FUNCTION__ " - out of memory"); - pl2303_close (port, NULL); - return -ENOMEM; - } - spin_lock_init(&info->lock); - port->private = info; - - - page = get_free_page(GFP_KERNEL); - if (!page) { - pl2303_close (port, NULL); - return -ENOMEM; - } - - PL2303_LOCK(port,flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + pl2303_set_termios (port, &tmp_termios); - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; + //FIXME: need to assert RTS and DTR if CRTSCTS off - PL2303_UNLOCK(port,flags); - - page = get_free_page(GFP_KERNEL); - if (!page) { - pl2303_close (port, NULL); - return -ENOMEM; - } - - PL2303_LOCK(port,flags); - - if (info->xmit_buf) - free_page(page); - else - info->xmit_buf=(unsigned char *) page; - - PL2303_UNLOCK(port,flags); - - - if ((i = usb_submit_urb (port->read_urb))) { - err ("usb_submit_urb(read bulk 1) failed"); - dbg ("i=%d", i); + port->read_urb->dev = serial->dev; + result = usb_submit_urb (port->read_urb); + if (result) { + err(__FUNCTION__ " - failed submitting read urb, error %d", result); + up (&port->sem); pl2303_close (port, NULL); return -EPROTO; - } - if ((i = usb_submit_urb (port->interrupt_in_urb))) { - err ("usb_submit_urb(interrupt ink) failed"); - dbg ("i=%d", i); + port->interrupt_in_urb->dev = serial->dev; + result = usb_submit_urb (port->interrupt_in_urb); + if (result) { + err(__FUNCTION__ " - failed submitting interrupt urb, error %d", result); + up (&port->sem); pl2303_close (port, NULL); - return -EPROTO; } } + up (&port->sem); + return 0; +} - return(0); -} /* pl2303_open */ +static void pl2303_close (struct usb_serial_port *port, struct file *filp) +{ + unsigned int c_cflag; -static void -pl2303_close (struct usb_serial_port *port, struct file *filp) -{ /* pl2303_close */ - struct pl2303_private *info; - unsigned int c_cflag = port->tty->termios->c_cflag; - unsigned long flags; + if (port_paranoia_check (port, __FUNCTION__)) + return; - dbg ("pl2303_close port %d", port->number); + dbg (__FUNCTION__ " - port %d", port->number); - /* shutdown our bulk reads and writes */ - if (port->active == 1) { + down (&port->sem); + --port->open_count; + if (port->open_count <= 0) { + c_cflag = port->tty->termios->c_cflag; if (c_cflag & HUPCL) { //FIXME: Do drop DTR //FIXME: Do drop RTS } + /* shutdown our urbs */ usb_unlink_urb (port->write_urb); usb_unlink_urb (port->read_urb); usb_unlink_urb (port->interrupt_in_urb); - info = (struct pl2303_private *)port->private; - if (info) { - PL2303_LOCK(port,flags); - if (info->xmit_buf) { - unsigned char * temp; - temp = info->xmit_buf; - info->xmit_buf = 0; - free_page((unsigned long) temp); - } - PL2303_UNLOCK(port,flags); - } - - //FIXME: tmp_buf memory leak - - + port->active = 0; + port->open_count = 0; } - port->active--; -} /* pl2303_close */ - -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int -pl2303_startup (struct usb_serial *serial) -{ - return(0); + up (&port->sem); } @@ -664,166 +454,105 @@ return; } - + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer); #if 0 //FIXME need to update state of terminal lines variable - if (urb->actual_length) { - printk (KERN_DEBUG __FILE__ ": INT data read - length = %d, data = ", - urb->actual_length); - for (i = 0; i < urb->actual_length; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); - } #endif return; } -static void -pl2303_read_bulk_callback (struct urb *urb) + +static void pl2303_read_bulk_callback (struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *) urb->context; - struct usb_serial *serial = get_usb_serial (port, "pl2303_read_bulk_callback"); + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int i; + int result; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); return; } -// PL2303 mysteriously fails with -EPROTO reschedule the read + /* PL2303 mysteriously fails with -EPROTO reschedule the read */ if (urb->status) { urb->status = 0; - if (usb_submit_urb (urb)) - dbg ("failed resubmitting read bulk urb"); + urb->dev = serial->dev; + result = usb_submit_urb(urb); + if (result) + err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); return; } - if (debug) { - if (urb->actual_length) { - printk (KERN_DEBUG __FILE__ ": BULK data read - length = %d, data = ", - urb->actual_length); - for (i = 0; i < urb->actual_length; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); - } - } + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); tty = port->tty; if (urb->actual_length) { for (i = 0; i < urb->actual_length; ++i) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - dbg ("ARGH ------------ Flip buffer overrun..."); - - break; + tty_flip_buffer_push(tty); } tty_insert_flip_char (tty, data[i], 0); } tty_flip_buffer_push (tty); } - /* Schedule the next read*/ - if (usb_submit_urb (urb)) - dbg ("failed submitting read bulk urb"); + urb->dev = serial->dev; + result = usb_submit_urb(urb); + if (result) + err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); return; } -static void -pl2303_write_bulk_callback (struct urb *urb) +static void pl2303_write_bulk_callback (struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *) urb->context; - struct usb_serial *serial; - struct tty_struct *tty = port->tty; - - dbg ("pl2303_write_bulk_callback"); - - - if (port_paranoia_check (port, "pl2303_write_bulk_callback")) { - return; - } + int result; - serial = port->serial; - if (serial_paranoia_check (serial, "pl2303_write_bulk_callback")) { + if (port_paranoia_check (port, __FUNCTION__)) return; - } - - + + dbg(__FUNCTION__ " - port %d", port->number); + if (urb->status) { - dbg ("Overflow in write"); - dbg ("nonzero write bulk status received: %d", urb->status); - //need to resubmit frame; - + /* error in the urb, so we have to resubmit it */ + if (serial_paranoia_check (port->serial, __FUNCTION__)) { + return; + } + dbg (__FUNCTION__ " - Overflow in write"); + dbg (__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); port->write_urb->transfer_buffer_length = 1; - - //Resubmit ourselves - - if (usb_submit_urb (port->write_urb)) - err ("usb_submit_urb(write bulk) failed"); + port->write_urb->dev = port->serial->dev; + result = usb_submit_urb (port->write_urb); + if (result) + err(__FUNCTION__ " - failed resubmitting write urb, error %d", result); return; } - wake_up_interruptible (&port->write_wait); - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - - wake_up_interruptible (&tty->write_wait); - - start_xmit(port); + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); return; } - -static void -start_xmit (struct usb_serial_port *port) -{ - struct usb_serial *serial; - struct pl2303_private *info; - unsigned long flags; - - serial = port->serial; - info = (struct pl2303_private *)port->private; - - if (info) { - PL2303_LOCK(port,flags); - - if (port->write_urb->status != -EINPROGRESS) { - if (info->xmit_tail != info->xmit_head) { - - memcpy (port->write_urb->transfer_buffer, &info->xmit_buf[info->xmit_tail],1); - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); - - - port->write_urb->transfer_buffer_length = 1; - - - if (usb_submit_urb (port->write_urb)) - err ("usb_submit_urb(write bulk) failed"); - - - } - } - - PL2303_UNLOCK(port,flags); - } -} - - static int __init pl2303_init (void) { usb_serial_register (&pl2303_device); - info(DRIVER_VERSION " : " DRIVER_DESC); + info(DRIVER_DESC " " DRIVER_VERSION); return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- v2.4.9/linux/drivers/usb/serial/usbserial.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/serial/usbserial.c Tue Aug 28 11:21:02 2001 @@ -307,8 +307,6 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/" #define DRIVER_DESC "USB Serial Driver core" -#define MAX(a,b) (((a)>(b))?(a):(b)) - /* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */ /* need to always compile these in, as some of the other devices use these functions as their own. */ /* if a driver does not provide a function pointer, the generic function will be called. */ @@ -852,7 +850,8 @@ count = (count > port->bulk_out_size) ? port->bulk_out_size : count; if (from_user) { - copy_from_user(port->write_urb->transfer_buffer, buf, count); + if (copy_from_user(port->write_urb->transfer_buffer, buf, count)) + return -EFAULT; } else { memcpy (port->write_urb->transfer_buffer, buf, count); @@ -1260,9 +1259,9 @@ /* initialize some parts of the port structures */ /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */ - max_endpoints = MAX(num_bulk_in, num_bulk_out); - max_endpoints = MAX(max_endpoints, num_interrupt_in); - max_endpoints = MAX(max_endpoints, serial->num_ports); + max_endpoints = max(int, num_bulk_in, num_bulk_out); + max_endpoints = max(int, max_endpoints, num_interrupt_in); + max_endpoints = max(int, max_endpoints, serial->num_ports); dbg (__FUNCTION__ " - setting up %d port structures for this device", max_endpoints); for (i = 0; i < max_endpoints; ++i) { port = &serial->port[i]; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.4.9/linux/drivers/usb/serial/visor.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/visor.c Fri Sep 7 10:59:04 2001 @@ -1,5 +1,6 @@ /* - * USB HandSpring Visor driver + * USB HandSpring Visor, Palm m50x, and Sony Clie driver + * (supports all of the Palm OS USB devices) * * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) @@ -11,6 +12,13 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (08/30/2001) gkh + * Added support for the Clie devices, both the 3.5 and 4.0 os versions. + * Many thanks to Daniel Burke, and Bryan Payne for helping with this. + * + * (08/23/2001) gkh + * fixed a few potential bugs pointed out by Oliver Neukum. + * * (05/30/2001) gkh * switched from using spinlock to a semaphore, which fixes lots of problems. * @@ -115,11 +123,9 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.2" +#define DRIVER_VERSION "v1.4" #define DRIVER_AUTHOR "Greg Kroah-Hartman " -#define DRIVER_DESC "USB HandSpring Visor driver" - -#define MIN(a,b) (((a)<(b))?(a):(b)) +#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clie driver" /* function prototypes for a handspring visor */ static int visor_open (struct usb_serial_port *port, struct file *filp); @@ -152,11 +158,22 @@ { } /* Terminating entry */ }; +static __devinitdata struct usb_device_id clie_id_3_5_table [] = { + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id clie_id_4_0_table [] = { + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, + { } /* Terminating entry */ +}; static __devinitdata struct usb_device_id id_table [] = { { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, { } /* Terminating entry */ }; @@ -242,6 +259,56 @@ read_bulk_callback: visor_read_bulk_callback, }; +/* device info for the Sony Clie OS version 3.5 */ +static struct usb_serial_device_type clie_3_5_device = { + name: "Sony Clie 3.5", + id_table: clie_id_3_5_table, + needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ + num_interrupt_in: 0, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: visor_open, + close: visor_close, + throttle: visor_throttle, + unthrottle: visor_unthrottle, + ioctl: visor_ioctl, + set_termios: visor_set_termios, + write: visor_write, + write_room: visor_write_room, + chars_in_buffer: visor_chars_in_buffer, + write_bulk_callback: visor_write_bulk_callback, + read_bulk_callback: visor_read_bulk_callback, +}; + +/* device info for the Sony Clie OS version 4.0 */ +static struct usb_serial_device_type clie_4_0_device = { + name: "Sony Clie 4.0", + id_table: clie_id_4_0_table, + needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ + num_interrupt_in: 0, + num_bulk_in: 2, + num_bulk_out: 2, + num_ports: 2, + open: visor_open, + close: visor_close, + throttle: visor_throttle, + unthrottle: visor_unthrottle, + startup: visor_startup, + shutdown: visor_shutdown, + ioctl: visor_ioctl, + set_termios: visor_set_termios, + write: visor_write, + write_room: visor_write_room, + chars_in_buffer: visor_chars_in_buffer, + write_bulk_callback: visor_write_bulk_callback, + read_bulk_callback: visor_read_bulk_callback, +}; + #define NUM_URBS 24 #define URB_TRANSFER_BUFFER_SIZE 768 static struct urb *write_urb_pool[NUM_URBS]; @@ -351,8 +418,6 @@ dbg(__FUNCTION__ " - port %d", port->number); - usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf); - while (count > 0) { /* try to find a free urb in our list of them */ urb = NULL; @@ -376,12 +441,18 @@ } } - transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE); - if (from_user) - copy_from_user (urb->transfer_buffer, current_position, transfer_size); - else + transfer_size = min (int, count, URB_TRANSFER_BUFFER_SIZE); + if (from_user) { + if (copy_from_user (urb->transfer_buffer, current_position, transfer_size)) { + bytes_sent = -EFAULT; + break; + } + } else { memcpy (urb->transfer_buffer, current_position, transfer_size); - + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, transfer_size, urb->transfer_buffer); + /* build up our urb */ FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), urb->transfer_buffer, transfer_size, visor_write_bulk_callback, port); @@ -389,8 +460,11 @@ /* send it down the pipe */ status = usb_submit_urb(urb); - if (status) - dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + if (status) { + err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + bytes_sent = status; + break; + } current_position += transfer_size; bytes_sent += transfer_size; @@ -567,10 +641,6 @@ return -ENOMEM; } - /* force debugging on for the palm devices for now */ - if (serial->dev->descriptor.idVendor == PALM_VENDOR_ID) - debug = 1; - dbg(__FUNCTION__); dbg(__FUNCTION__ " - Set config to 1"); @@ -612,8 +682,9 @@ } } - if (serial->dev->descriptor.idVendor == PALM_VENDOR_ID) { - /* Palm USB Hack */ + if ((serial->dev->descriptor.idVendor == PALM_VENDOR_ID) || + (serial->dev->descriptor.idVendor == SONY_VENDOR_ID)) { + /* Palm OS 4.0 Hack */ response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), PALM_GET_SOME_UNKNOWN_INFORMATION, 0xc2, 0x0000, 0x0000, transfer_buffer, @@ -674,10 +745,16 @@ /* This function is all nice and good, but we don't change anything based on it :) */ static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios) { - unsigned int cflag = port->tty->termios->c_cflag; + unsigned int cflag; dbg(__FUNCTION__ " - port %d", port->number); + if ((!port->tty) || (!port->tty->termios)) { + dbg(__FUNCTION__" - no tty structures"); + return; + } + + cflag = port->tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { if ((cflag == old_termios->c_cflag) && @@ -687,11 +764,6 @@ } } - if ((!port->tty) || (!port->tty->termios)) { - dbg(__FUNCTION__" - no tty structures"); - return; - } - /* get the byte size */ switch (cflag & CSIZE) { case CS5: dbg(__FUNCTION__ " - data bits = 5"); break; @@ -744,6 +816,8 @@ usb_serial_register (&handspring_device); usb_serial_register (&palm_m500_device); usb_serial_register (&palm_m505_device); + usb_serial_register (&clie_3_5_device); + usb_serial_register (&clie_4_0_device); /* create our write urb pool and transfer buffers */ spin_lock_init (&write_urb_pool_lock); @@ -763,7 +837,7 @@ } } - info(DRIVER_VERSION ":" DRIVER_DESC); + info(DRIVER_DESC " " DRIVER_VERSION); return 0; } @@ -777,6 +851,8 @@ usb_serial_deregister (&handspring_device); usb_serial_deregister (&palm_m500_device); usb_serial_deregister (&palm_m505_device); + usb_serial_deregister (&clie_3_5_device); + usb_serial_deregister (&clie_4_0_device); spin_lock_irqsave (&write_urb_pool_lock, flags); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/visor.h linux/drivers/usb/serial/visor.h --- v2.4.9/linux/drivers/usb/serial/visor.h Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/visor.h Fri Sep 7 10:59:04 2001 @@ -24,6 +24,10 @@ #define PALM_M500_ID 0x0001 #define PALM_M505_ID 0x0002 +#define SONY_VENDOR_ID 0x054C +#define SONY_CLIE_3_5_ID 0x0038 +#define SONY_CLIE_4_0_ID 0x0066 + /**************************************************************************** * Handspring Visor Vendor specific request codes (bRequest values) * A big thank you to Handspring for providing the following information. diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c --- v2.4.9/linux/drivers/usb/serial/whiteheat.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/whiteheat.c Tue Aug 28 11:21:02 2001 @@ -412,12 +412,19 @@ static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios) { - unsigned int cflag = port->tty->termios->c_cflag; + unsigned int cflag; struct whiteheat_port_settings port_settings; dbg(__FUNCTION__ " -port %d", port->number); down (&port->sem); + + if ((!port->tty) || (!port->tty->termios)) { + dbg(__FUNCTION__" - no tty structures"); + goto exit; + } + + cflag = port->tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { if ((cflag == old_termios->c_cflag) && @@ -427,11 +434,6 @@ } } - if ((!port->tty) || (!port->tty->termios)) { - dbg(__FUNCTION__" - no tty structures"); - goto exit; - } - /* set the port number */ /* firmware uses 1 based port numbering */ port_settings.port = port->number + 1; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c --- v2.4.9/linux/drivers/usb/storage/scsiglue.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/storage/scsiglue.c Sun Sep 2 07:26:19 2001 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * SCSI layer glue code * - * $Id: scsiglue.c,v 1.21 2001/07/29 23:41:52 mdharm Exp $ + * $Id: scsiglue.c,v 1.22 2001/09/02 04:29:27 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) diff -u --recursive --new-file v2.4.9/linux/drivers/usb/storage/sddr09.c linux/drivers/usb/storage/sddr09.c --- v2.4.9/linux/drivers/usb/storage/sddr09.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/storage/sddr09.c Sun Sep 2 07:26:19 2001 @@ -1,6 +1,6 @@ /* Driver for SanDisk SDDR-09 SmartMedia reader * - * $Id: sddr09.c,v 1.18 2001/06/11 02:54:25 mdharm Exp $ + * $Id: sddr09.c,v 1.19 2001/09/02 06:07:20 mdharm Exp $ * * SDDR09 driver v0.1: * @@ -693,7 +693,7 @@ // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) for (i=0; i>11].address+(i<<6); + ptr = sg[i>>11].address+((i&0x7ff)<<6); if (ptr[0]!=0xFF || ptr[1]!=0xFF || ptr[2]!=0xFF || ptr[3]!=0xFF || ptr[4]!=0xFF || ptr[5]!=0xFF) { US_DEBUGP("PBA %04X has no logical mapping: reserved area = " diff -u --recursive --new-file v2.4.9/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c --- v2.4.9/linux/drivers/usb/storage/transport.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/storage/transport.c Sun Sep 2 07:26:19 2001 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: transport.c,v 1.39 2001/03/10 16:46:28 zagor Exp $ + * $Id: transport.c,v 1.40 2001/08/18 08:37:46 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -371,10 +371,9 @@ */ static void usb_stor_blocking_completion(urb_t *urb) { - wait_queue_head_t *wqh_ptr = (wait_queue_head_t *)urb->context; + struct completion *urb_done_ptr = (struct completion *)urb->context; - if (waitqueue_active(wqh_ptr)) - wake_up(wqh_ptr); + complete(urb_done_ptr); } /* This is our function to emulate usb_control_msg() but give us enough @@ -384,8 +383,7 @@ u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size) { - wait_queue_head_t wqh; - wait_queue_t wait; + struct completion urb_done; int status; devrequest *dr; @@ -402,9 +400,7 @@ dr->length = cpu_to_le16(size); /* set up data structures for the wakeup system */ - init_waitqueue_head(&wqh); - init_waitqueue_entry(&wait, current); - add_wait_queue(&wqh, &wait); + init_completion(&urb_done); /* lock the URB */ down(&(us->current_urb_sem)); @@ -412,33 +408,25 @@ /* fill the URB */ FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, (unsigned char*) dr, data, size, - usb_stor_blocking_completion, &wqh); + usb_stor_blocking_completion, &urb_done); us->current_urb->actual_length = 0; us->current_urb->error_count = 0; us->current_urb->transfer_flags = USB_ASYNC_UNLINK; /* submit the URB */ - set_current_state(TASK_UNINTERRUPTIBLE); status = usb_submit_urb(us->current_urb); if (status) { /* something went wrong */ up(&(us->current_urb_sem)); - set_current_state(TASK_RUNNING); - remove_wait_queue(&wqh, &wait); kfree(dr); return status; } /* wait for the completion of the URB */ up(&(us->current_urb_sem)); - while (us->current_urb->status == -EINPROGRESS) - schedule(); + wait_for_completion(&urb_done); down(&(us->current_urb_sem)); - /* we either timed out or got woken up -- clean up either way */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&wqh, &wait); - /* return the actual length of the data transferred if no error*/ status = us->current_urb->status; if (status >= 0) @@ -456,45 +444,34 @@ int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, unsigned int len, unsigned int *act_len) { - wait_queue_head_t wqh; - wait_queue_t wait; + struct completion urb_done; int status; /* set up data structures for the wakeup system */ - init_waitqueue_head(&wqh); - init_waitqueue_entry(&wait, current); - add_wait_queue(&wqh, &wait); + init_completion(&urb_done); /* lock the URB */ down(&(us->current_urb_sem)); /* fill the URB */ FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len, - usb_stor_blocking_completion, &wqh); + usb_stor_blocking_completion, &urb_done); us->current_urb->actual_length = 0; us->current_urb->error_count = 0; us->current_urb->transfer_flags = USB_ASYNC_UNLINK; /* submit the URB */ - set_current_state(TASK_UNINTERRUPTIBLE); status = usb_submit_urb(us->current_urb); if (status) { /* something went wrong */ up(&(us->current_urb_sem)); - set_current_state(TASK_RUNNING); - remove_wait_queue(&wqh, &wait); return status; } /* wait for the completion of the URB */ up(&(us->current_urb_sem)); - while (us->current_urb->status == -EINPROGRESS) - schedule(); + wait_for_completion(&urb_done); down(&(us->current_urb_sem)); - - /* we either timed out or got woken up -- clean up either way */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&wqh, &wait); /* return the actual length of the data transferred */ *act_len = us->current_urb->actual_length; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/storage/unusual_devs.h linux/drivers/usb/storage/unusual_devs.h --- v2.4.9/linux/drivers/usb/storage/unusual_devs.h Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/storage/unusual_devs.h Sat Sep 8 18:59:24 2001 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * Ununsual Devices File * - * $Id: unusual_devs.h,v 1.16 2001/07/30 00:27:59 mdharm Exp $ + * $Id: unusual_devs.h,v 1.20 2001/09/02 05:12:57 mdharm Exp $ * * Current development and maintenance by: * (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -68,6 +68,19 @@ US_FL_START_STOP ), #endif +/* Made with the help of Edd Dumbill */ +UNUSUAL_DEV( 0x0451, 0x5409, 0x0001, 0x0001, + "Frontier Labs", + "Nex II Digital", + US_SC_SCSI, US_PR_BULK, NULL, US_FL_START_STOP), + +/* Reported by Paul Stewart + * This entry is needed because the device reports Sub=ff */ +UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, + "Hitachi", + "DVD-CAM DZ-MV100A Camcorder", + US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), + UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, "Fujifilm", "FinePix 1400Zoom", @@ -96,7 +109,7 @@ #endif /* This entry is from Andries.Brouwer@cwi.nl */ -UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0205, +UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB SmartMedia / CompactFlash Adapter", US_SC_SCSI, US_PR_DPCM_USB, NULL, @@ -155,13 +168,20 @@ US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ), +/* Reported by win@geeks.nl */ +UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, + "Sony", + "Memorystick NW-MS7", + US_SC_UFI, US_PR_CB, NULL, + US_FL_SINGLE_LUN | US_FL_START_STOP ), + UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, "Sony", "Memorystick MSAC-US1", US_SC_UFI, US_PR_CB, NULL, US_FL_SINGLE_LUN | US_FL_START_STOP ), -/* Submitted by Klaus Mueller */ +/* Submitted by Klaus Mueller */ UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310, "Sony", "Handycam", @@ -195,12 +215,6 @@ UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, "In-System", "USB/IDE Bridge (ATA/ATAPI)", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x0060, 0x0100, 0x0110, - "In-System", - "USB 2.0/IDE Bridge (ATA/ATAPI)", US_SC_ISD200, US_PR_BULK, isd200_Initialization, 0 ), diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb-skeleton.c linux/drivers/usb/usb-skeleton.c --- v2.4.9/linux/drivers/usb/usb-skeleton.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/usb-skeleton.c Tue Aug 28 11:21:02 2001 @@ -1,5 +1,5 @@ /* - * USB Skeleton driver + * USB Skeleton driver - 0.4 * * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) * @@ -22,6 +22,7 @@ * * History: * + * 2001_08_21 - 0.4 - more small bug fixes. * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people * 2001_05_01 - 0.1 - first version @@ -56,7 +57,7 @@ /* Version Information */ -#define DRIVER_VERSION "v0.3" +#define DRIVER_VERSION "v0.4" #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com" #define DRIVER_DESC "USB Skeleton Driver" @@ -179,6 +180,22 @@ /** + * skel_delete + */ +static inline void skel_delete (struct usb_skel *dev) +{ + minor_table[dev->minor] = NULL; + if (dev->bulk_in_buffer != NULL) + kfree (dev->bulk_in_buffer); + if (dev->bulk_out_buffer != NULL) + kfree (dev->bulk_out_buffer); + if (dev->write_urb != NULL) + usb_free_urb (dev->write_urb); + kfree (dev); +} + + +/** * skel_open */ static int skel_open (struct inode *inode, struct file *file) @@ -256,27 +273,21 @@ if (dev->udev == NULL) { /* the device was unplugged before the file was released */ - minor_table[dev->minor] = NULL; - if (dev->bulk_in_buffer != NULL) - kfree (dev->bulk_in_buffer); - if (dev->bulk_out_buffer != NULL) - kfree (dev->bulk_out_buffer); - if (dev->write_urb != NULL) - usb_free_urb (dev->write_urb); - kfree (dev); - goto exit; + up (&dev->sem); + skel_delete (dev); + MOD_DEC_USE_COUNT; + up (&minor_table_mutex); + return 0; } /* decrement our usage count for the device */ --dev->open_count; if (dev->open_count <= 0) { /* shutdown any bulk writes that might be going on */ - dev->write_urb->transfer_flags |= USB_ASYNC_UNLINK; usb_unlink_urb (dev->write_urb); dev->open_count = 0; } -exit: /* decrement our usage count for the module */ MOD_DEC_USE_COUNT; @@ -453,9 +464,12 @@ } - - - +/** + * skel_probe + * + * Called by the usb core when a new device is connected that it thinks + * this driver might be interested in. + */ static void * skel_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_skel *dev = NULL; @@ -476,7 +490,7 @@ /* select a "subminor" number (part of a minor number) */ down (&minor_table_mutex); - for (minor = 0; minor < MAX_DEVICES; i++) { + for (minor = 0; minor < MAX_DEVICES; ++minor) { if (minor_table[minor] == NULL) break; } @@ -558,14 +572,7 @@ goto exit; error: - minor_table [dev->minor] = NULL; - if (dev->bulk_in_buffer != NULL) - kfree (dev->bulk_in_buffer); - if (dev->bulk_out_buffer != NULL) - kfree (dev->bulk_out_buffer); - if (dev->write_urb != NULL) - usb_free_urb (dev->write_urb); - kfree (dev); + skel_delete (dev); dev = NULL; exit: @@ -576,6 +583,8 @@ /** * skel_disconnect + * + * Called by the usb core when the device is removed from the system. */ static void skel_disconnect(struct usb_device *udev, void *ptr) { @@ -591,14 +600,7 @@ /* if the device is not opened, then we clean up right now */ if (!dev->open_count) { - minor_table[dev->minor] = NULL; - if (dev->bulk_in_buffer != NULL) - kfree (dev->bulk_in_buffer); - if (dev->bulk_out_buffer != NULL) - kfree (dev->bulk_out_buffer); - if (dev->write_urb != NULL) - usb_free_urb (dev->write_urb); - kfree (dev); + skel_delete (dev); } else { dev->udev = NULL; up (&dev->sem); @@ -628,8 +630,7 @@ return -1; } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_DESC " " DRIVER_VERSION); return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c --- v2.4.9/linux/drivers/usb/usb-uhci.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/usb-uhci.c Fri Sep 7 11:01:21 2001 @@ -1,7 +1,7 @@ /* * Universal Host Controller Interface driver for USB (take II). * - * (c) 1999-2000 Georg Acher, acher@in.tum.de (executive slave) (base guitar) + * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar) * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) @@ -16,7 +16,7 @@ * (C) Copyright 1999 Randy Dunlap * (C) Copyright 1999 Gregory P. Smith * - * $Id: usb-uhci.c,v 1.259 2001/03/30 14:51:59 acher Exp $ + * $Id: usb-uhci.c,v 1.268 2001/08/29 14:08:43 acher Exp $ */ #include @@ -52,7 +52,7 @@ /* This enables an extra UHCI slab for memory debugging */ #define DEBUG_SLAB -#define VERSTR "$Revision: 1.259 $ time " __TIME__ " " __DATE__ +#define VERSTR "$Revision: 1.268 $ time " __TIME__ " " __DATE__ #include #include "usb-uhci.h" @@ -61,7 +61,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.251" +#define DRIVER_VERSION "v1.268" #define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" #define DRIVER_DESC "USB Universal Host Controller Interface driver" @@ -88,13 +88,34 @@ #define SLAB_FLAG (in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL) #define KMALLOC_FLAG (in_interrupt ()? GFP_ATOMIC : GFP_KERNEL) +/* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth + * Reclamation: feature that puts loop on descriptor loop when + * there's some transfer going on. With FSBR, USB performance + * is optimal, but PCI can be slowed down up-to 5 times, slowing down + * system performance (eg. framebuffer devices). + */ #define CONFIG_USB_UHCI_HIGH_BANDWIDTH + +/* *_DEPTH_FIRST puts descriptor in depth-first mode. This has + * somehow similar effect to FSBR (higher speed), but does not + * slow PCI down. OTOH USB performace is slightly slower than + * in FSBR case and single device could hog whole USB, starving + * other devices. + */ #define USE_CTRL_DEPTH_FIRST 0 // 0: Breadth first, 1: Depth first #define USE_BULK_DEPTH_FIRST 0 // 0: Breadth first, 1: Depth first +/* Turning off both CONFIG_USB_UHCI_HIGH_BANDWITH and *_DEPTH_FIRST + * will lead to <64KB/sec performance over USB for bulk transfers targeting + * one device's endpoint. You probably do not want to do that. + */ + // stop bandwidth reclamation after (roughly) 50ms #define IDLE_TIMEOUT (HZ/20) +// Suppress HC interrupt error messages for 5s +#define ERROR_SUPPRESSION_TIME (HZ*5) + _static int rh_submit_urb (urb_t *urb); _static int rh_unlink_urb (urb_t *urb); _static int delete_qh (uhci_t *s, uhci_desc_t *qh); @@ -133,20 +154,15 @@ _static void uhci_switch_timer_int(uhci_t *s) { - if (!list_empty(&s->urb_unlinked)) { - s->td1ms->hw.td.status |= cpu_to_le32(TD_CTRL_IOC); - } - else { - s->td1ms->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC); - } - - if (s->timeout_urbs) { - s->td32ms->hw.td.status |= cpu_to_le32(TD_CTRL_IOC); - } - else { - s->td32ms->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC); - } + if (!list_empty(&s->urb_unlinked)) + set_td_ioc(s->td1ms); + else + clr_td_ioc(s->td1ms); + if (s->timeout_urbs) + set_td_ioc(s->td32ms); + else + clr_td_ioc(s->td32ms); wmb(); } /*-------------------------------------------------------------------*/ @@ -199,6 +215,7 @@ enable_desc_loop(s, urb); } #endif + urb->status = -EINPROGRESS; ((urb_priv_t*)urb->hcpriv)->started=jiffies; list_add (p, &s->urb_list); if (urb->timeout) @@ -241,7 +258,7 @@ return -ENOMEM; memset (*new, 0, sizeof (uhci_desc_t)); (*new)->dma_addr = dma_handle; - (*new)->hw.td.link = cpu_to_le32(UHCI_PTR_TERM | (flags & UHCI_PTR_BITS)); // last by default + set_td_link((*new), UHCI_PTR_TERM | (flags & UHCI_PTR_BITS)); // last by default (*new)->type = TD_TYPE; mb(); INIT_LIST_HEAD (&(*new)->vertical); @@ -257,7 +274,7 @@ spin_lock_irqsave (&s->td_lock, xxx); - td->hw.td.link = cpu_to_le32(qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH); + set_td_link(td, qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH); mb(); spin_unlock_irqrestore (&s->td_lock, xxx); @@ -277,11 +294,11 @@ if (qh == prev ) { // virgin qh without any tds - qh->hw.qh.element = cpu_to_le32(new->dma_addr | UHCI_PTR_TERM); + set_qh_element(qh, new->dma_addr | UHCI_PTR_TERM); } else { // already tds inserted, implicitely remove TERM bit of prev - prev->hw.td.link = cpu_to_le32(new->dma_addr | (flags & UHCI_PTR_DEPTH)); + set_td_link(prev, new->dma_addr | (flags & UHCI_PTR_DEPTH)); } mb(); spin_unlock_irqrestore (&s->td_lock, xxx); @@ -300,7 +317,7 @@ next = list_entry (td->horizontal.next, uhci_desc_t, horizontal); list_add (&new->horizontal, &td->horizontal); new->hw.td.link = td->hw.td.link; - td->hw.td.link = cpu_to_le32(new->dma_addr); + set_td_link(td, new->dma_addr); mb(); spin_unlock_irqrestore (&s->td_lock, flags); @@ -361,8 +378,8 @@ return -ENOMEM; memset (*new, 0, sizeof (uhci_desc_t)); (*new)->dma_addr = dma_handle; - (*new)->hw.qh.head = cpu_to_le32(UHCI_PTR_TERM); - (*new)->hw.qh.element = cpu_to_le32(UHCI_PTR_TERM); + set_qh_head(*new, UHCI_PTR_TERM); + set_qh_element(*new, UHCI_PTR_TERM); (*new)->type = QH_TYPE; mb(); @@ -387,16 +404,16 @@ // (OLD) (POS) -> (OLD) (NEW) (POS) old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal); list_add_tail (&new->horizontal, &pos->horizontal); - new->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (pos)) ; + set_qh_head(new, MAKE_QH_ADDR (pos)) ; if (!(old->hw.qh.head & cpu_to_le32(UHCI_PTR_TERM))) - old->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (new)) ; + set_qh_head(old, MAKE_QH_ADDR (new)) ; } else { // (POS) (OLD) -> (POS) (NEW) (OLD) old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal); list_add (&new->horizontal, &pos->horizontal); - new->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (old)); - pos->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (new)) ; + set_qh_head(new, MAKE_QH_ADDR (old)); + set_qh_head(pos, MAKE_QH_ADDR (new)) ; } mb (); @@ -522,7 +539,7 @@ if (s->ls_control_chain) delete_desc (s, s->ls_control_chain); if (s->control_chain) - delete_desc(s, s->control_chain); + delete_desc (s, s->control_chain); if (s->bulk_chain) delete_desc (s, s->bulk_chain); if (s->chain_end) @@ -576,24 +593,20 @@ dbg("allocating iso descs"); for (n = 0; n < 1024; n++) { // allocate skeleton iso/irq-tds - ret = alloc_td (s, &td, 0); - if (ret) + if (alloc_td (s, &td, 0)) goto init_skel_cleanup; + s->iso_td[n] = td; s->framelist[n] = cpu_to_le32((__u32) td->dma_addr); } dbg("allocating qh: chain_end"); - ret = alloc_qh (s, &qh); - - if (ret) + if (alloc_qh (s, &qh)) goto init_skel_cleanup; s->chain_end = qh; - ret = alloc_td (s, &td, 0); - - if (ret) + if (alloc_td (s, &td, 0)) goto init_skel_cleanup; fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand) @@ -602,8 +615,7 @@ s->td1ms=td; dbg("allocating qh: bulk_chain"); - ret = alloc_qh (s, &qh); - if (ret) + if (alloc_qh (s, &qh)) goto init_skel_cleanup; insert_qh (s, s->chain_end, qh, 0); @@ -619,12 +631,11 @@ #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH // disabled reclamation loop - s->chain_end->hw.qh.head = cpu_to_le32(s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM); + set_qh_head(s->chain_end, s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM); #endif dbg("allocating qh: ls_control_chain"); - ret = alloc_qh (s, &qh); - if (ret) + if (alloc_qh (s, &qh)) goto init_skel_cleanup; insert_qh (s, s->control_chain, qh, 0); @@ -638,15 +649,15 @@ for (n = 0; n < 8; n++) { uhci_desc_t *td; - alloc_td (s, &td, 0); - if (!td) + if (alloc_td (s, &td, 0)) goto init_skel_cleanup; + s->int_chain[n] = td; if (n == 0) { - s->int_chain[0]->hw.td.link = cpu_to_le32(s->ls_control_chain->dma_addr | UHCI_PTR_QH); + set_td_link(s->int_chain[0], s->ls_control_chain->dma_addr | UHCI_PTR_QH); } else { - s->int_chain[n]->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr); + set_td_link(s->int_chain[n], s->int_chain[0]->dma_addr); } } @@ -661,16 +672,13 @@ else for (o = 1, m = 2; m <= 128; o++, m += m) if ((n & (m - 1)) == ((m - 1) / 2)) - ((uhci_desc_t*) s->iso_td[n])->hw.td.link = - cpu_to_le32(s->int_chain[o]->dma_addr); + set_td_link(((uhci_desc_t*) s->iso_td[n]), s->int_chain[o]->dma_addr); } - ret = alloc_td (s, &td, 0); - - if (ret) + if (alloc_td (s, &td, 0)) goto init_skel_cleanup; - fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt + fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt (activated later) s->td32ms=td; insert_td_horizontal (s, s->int_chain[5], td); @@ -700,20 +708,12 @@ char *data; int depth_first=USE_CTRL_DEPTH_FIRST; // UHCI descriptor chasing method - if (!maxsze) { - err("uhci_submit_control_urb: pipesize for pipe %x is zero", urb->pipe); - return -EINVAL; - } - dbg("uhci_submit_control start"); - alloc_qh (s, &qh); // alloc qh for this request - - if (!qh) + if (alloc_qh (s, &qh)) // alloc qh for this request return -ENOMEM; - alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first); // get td for setup stage - - if (!td) { + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) // get td for setup stage + { delete_qh (s, qh); return -ENOMEM; } @@ -749,8 +749,7 @@ while (len > 0) { int pktsze = len; - alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first); - if (!td) + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) goto fail_unmap_enomem; if (pktsze > maxsze) @@ -768,7 +767,7 @@ len -= pktsze; } - /* Build the final TD for control status */ + /* Build the final TD for control status */ /* It's only IN if the pipe is out AND we aren't expecting data */ destination &= ~UHCI_PID; @@ -780,9 +779,7 @@ destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ - alloc_td (s, &td, UHCI_PTR_DEPTH); - - if (!td) + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) goto fail_unmap_enomem; status &=~TD_CTRL_SPD; @@ -795,7 +792,6 @@ list_add (&qh->desc_list, &urb_priv->desc_list); - urb->status = -EINPROGRESS; queue_urb (s, urb); // queue before inserting in desc chain qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); @@ -821,7 +817,7 @@ _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb) { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; - urb_priv_t *urb_priv = urb->hcpriv; + urb_priv_t *urb_priv = urb->hcpriv, *upriv, *bpriv=NULL; uhci_desc_t *qh, *td, *nqh=NULL, *bqh=NULL, *first_td=NULL; unsigned long destination, status; char *data; @@ -829,33 +825,22 @@ int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); int info, len, last; int depth_first=USE_BULK_DEPTH_FIRST; // UHCI descriptor chasing method - urb_priv_t *upriv, *bpriv=NULL; if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) return -EPIPE; - if (urb->transfer_buffer_length < 0) { - err("Negative transfer length in submit_bulk"); - return -EINVAL; - } - - if (!maxsze) - return -EMSGSIZE; - queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i", urb,bulk_urb,urb->pipe,urb->transfer_buffer_length); upriv = (urb_priv_t*)urb->hcpriv; if (!bulk_urb) { - alloc_qh (s, &qh); // get qh for this request - - if (!qh) + if (alloc_qh (s, &qh)) // get qh for this request return -ENOMEM; if (urb->transfer_flags & USB_QUEUE_BULK) { - alloc_qh(s, &nqh); // placeholder for clean unlink - if (!nqh) { + if (alloc_qh(s, &nqh)) // placeholder for clean unlink + { delete_desc (s, qh); return -ENOMEM; } @@ -872,17 +857,16 @@ } if (urb->transfer_flags & USB_QUEUE_BULK) { - alloc_qh (s, &bqh); // "bottom" QH, - - if (!bqh) { + if (alloc_qh (s, &bqh)) // "bottom" QH + { if (!bulk_urb) { delete_desc(s, qh); delete_desc(s, nqh); } return -ENOMEM; } - bqh->hw.qh.element = cpu_to_le32(UHCI_PTR_TERM); - bqh->hw.qh.head = cpu_to_le32(nqh->dma_addr | UHCI_PTR_QH); // element + set_qh_element(bqh, UHCI_PTR_TERM); + set_qh_head(bqh, nqh->dma_addr | UHCI_PTR_QH); // element upriv->bottom_qh = bqh; } queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh); @@ -901,9 +885,8 @@ do { // TBD: Really allow zero-length packets? int pktsze = len; - alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first); - - if (!td) { + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) + { delete_qh (s, qh); return -ENOMEM; } @@ -924,7 +907,7 @@ last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_ZERO_PACKET))); if (last) - td->hw.td.status |= cpu_to_le32(TD_CTRL_IOC); // last one generates INT + set_td_ioc(td); // last one generates INT insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); if (!first_td) @@ -941,11 +924,10 @@ if (urb->transfer_flags & USB_QUEUE_BULK) append_qh(s, td, bqh, UHCI_PTR_DEPTH * depth_first); - urb->status = -EINPROGRESS; queue_urb_unlocked (s, urb); if (urb->transfer_flags & USB_QUEUE_BULK) - qh->hw.qh.element = cpu_to_le32(first_td->dma_addr); + set_qh_element(qh, first_td->dma_addr); else qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // arm QH @@ -988,10 +970,11 @@ } } /*-------------------------------------------------------------------*/ -// mode: 0: unlink but no deletion mark (step 1 of async_unlink) -// 1: regular (unlink/delete-mark) -// 2: deletion mark for QH (step 2 of async_unlink) -// looks a bit complicated because of all the bulk queueing goodies +/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink) + CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark) + CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink) + looks a bit complicated because of all the bulk queueing goodies +*/ _static void uhci_clean_transfer (uhci_t *s, urb_t *urb, uhci_desc_t *qh, int mode) { @@ -1005,18 +988,16 @@ if (!priv->next_queued_urb) { // no more appended bulk queues - queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p",urb, qh, bqh, priv->next_qh); + queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p", urb, qh, bqh, priv->next_qh); - if (priv->prev_queued_urb) { // qh not top of the queue - urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; + if (priv->prev_queued_urb && mode != CLEAN_TRANSFER_DELETION_MARK) { // qh not top of the queue + unsigned long flags; + urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; - if (mode != 2) { - unsigned long flags; - spin_lock_irqsave (&s->qh_lock, flags); prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical); - prevtd->hw.td.link = cpu_to_le32(priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh + set_td_link(prevtd, priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh mb(); queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd); spin_unlock_irqrestore (&s->qh_lock, flags); @@ -1024,19 +1005,18 @@ ppriv->bottom_qh = priv->bottom_qh; ppriv->next_queued_urb = NULL; } - } else { // queue is dead, qh is top of the queue - if (mode!=2) + if (mode != CLEAN_TRANSFER_DELETION_MARK) unlink_qh(s, qh); // remove qh from horizontal chain if (bqh) { // remove remainings of bulk queue nqh=priv->next_qh; - if (mode != 2) + if (mode != CLEAN_TRANSFER_DELETION_MARK) unlink_qh(s, nqh); // remove nqh from horizontal chain - if (mode) { + if (mode != CLEAN_TRANSFER_NO_DELETION) { // add helper QHs to free desc list nqh->last_used = bqh->last_used = now; list_add_tail (&nqh->horizontal, &s->free_desc); list_add_tail (&bqh->horizontal, &s->free_desc); @@ -1049,7 +1029,7 @@ queue_dbg("uhci_clean_transfer: urb %p, prevurb %p, nexturb %p, qh %p, bqh %p, nqh %p", urb, priv->prev_queued_urb, priv->next_queued_urb, qh, bqh, priv->next_qh); - if (mode !=2) { // no work for cleanup at unlink-completion + if (mode != CLEAN_TRANSFER_DELETION_MARK) { // no work for cleanup at unlink-completion urb_t *nurb; unsigned long flags; @@ -1059,7 +1039,7 @@ if (!priv->prev_queued_urb) { // top QH prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal); - prevqh->hw.qh.head = cpu_to_le32(bqh->dma_addr | UHCI_PTR_QH); + set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH); list_del (&qh->horizontal); // remove this qh form horizontal chain list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain } @@ -1072,18 +1052,18 @@ ppriv->bottom_qh = bnqh; ppriv->next_queued_urb = nurb; prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); - prevqh->hw.qh.head = cpu_to_le32(bqh->dma_addr | UHCI_PTR_QH); + set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH); } mb(); - spin_unlock_irqrestore (&s->qh_lock, flags); ((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb; + spin_unlock_irqrestore (&s->qh_lock, flags); } } - if (mode) { + if (mode != CLEAN_TRANSFER_NO_DELETION) { qh->last_used = now; - list_add_tail (&qh->horizontal, &s->free_desc); // mark for later deletion/kfree + list_add_tail (&qh->horizontal, &s->free_desc); // mark qh for later deletion/kfree } } /*-------------------------------------------------------------------*/ @@ -1134,9 +1114,56 @@ urb_priv->transfer_buffer_dma = 0; } } +/*-------------------------------------------------------------------*/ +/* needs urb_list_lock! + mode: UNLINK_ASYNC_STORE_URB: unlink and move URB into unlinked list + UNLINK_ASYNC_DONT_STORE: unlink, don't move URB into unlinked list +*/ +_static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb, int mode) +{ + uhci_desc_t *qh; + urb_priv_t *urb_priv; + + async_dbg("unlink_urb_async called %p",urb); + + if ((urb->status == -EINPROGRESS) || + ((usb_pipetype (urb->pipe) == PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags)) + { + ((urb_priv_t*)urb->hcpriv)->started = ~0; // mark + dequeue_urb (s, urb); + + if (mode==UNLINK_ASYNC_STORE_URB) + list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb + + uhci_switch_timer_int(s); + s->unlink_urb_done = 1; + uhci_release_bandwidth(urb); + + urb->status = -ECONNABORTED; // mark urb as "waiting to be killed" + urb_priv = (urb_priv_t*)urb->hcpriv; + + switch (usb_pipetype (urb->pipe)) { + case PIPE_INTERRUPT: + usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + case PIPE_ISOCHRONOUS: + uhci_clean_iso_step1 (s, urb_priv); + break; + + case PIPE_BULK: + case PIPE_CONTROL: + qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); + uhci_clean_transfer (s, urb, qh, CLEAN_TRANSFER_NO_DELETION); + break; + } + ((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s); + return -EINPROGRESS; // completion will follow + } + + return 0; // URB already dead +} /*-------------------------------------------------------------------*/ -// unlinks an urb by dequeuing its qh, waits some frames and forgets it +// kills an urb by unlinking descriptors and waiting for at least one frame _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb) { uhci_desc_t *qh; @@ -1146,45 +1173,31 @@ spin_lock_irqsave (&s->urb_list_lock, flags); - if (!in_interrupt()) // shouldn't be called from interrupt at all... - spin_lock(&urb->lock); - if (urb->status == -EINPROGRESS) { - // URB probably still in work - dequeue_urb (s, urb); - uhci_switch_timer_int(s); - s->unlink_urb_done=1; - uhci_release_bandwidth(urb); - urb->status = -ENOENT; // mark urb as killed + // move descriptors out the the running chains, dequeue urb + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_DONT_STORE); - if (!in_interrupt()) - spin_unlock(&urb->lock); - - spin_unlock_irqrestore (&s->urb_list_lock, flags); - urb_priv = urb->hcpriv; - + urb->status = -ENOENT; // prevent from double deletion after unlock + spin_unlock_irqrestore (&s->urb_list_lock, flags); + + // cleanup the rest switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - case PIPE_ISOCHRONOUS: - uhci_clean_iso_step1(s, urb_priv); uhci_wait_ms(1); uhci_clean_iso_step2(s, urb_priv); break; case PIPE_BULK: case PIPE_CONTROL: - spin_lock_irqsave (&s->urb_list_lock, flags); qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); - uhci_clean_transfer(s, urb, qh, 1); - spin_unlock_irqrestore (&s->urb_list_lock, flags); + uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK); uhci_wait_ms(1); } - + urb->status = -ENOENT; // mark urb as killed + uhci_urb_dma_unmap(s, urb, urb->hcpriv); #ifdef DEBUG_SLAB @@ -1200,11 +1213,8 @@ } usb_dec_dev_use (usb_dev); } - else { - if (!in_interrupt()) - spin_unlock(&urb->lock); + else spin_unlock_irqrestore (&s->urb_list_lock, flags); - } return 0; } @@ -1219,7 +1229,7 @@ struct list_head *q; urb_t *urb; struct usb_device *dev; - int pipe,now; + int now, type; urb_priv_t *urb_priv; q=s->urb_unlinked.next; @@ -1235,21 +1245,22 @@ if (!urb_priv) // avoid crash when URB is corrupted break; - if (force || - ((urb_priv->started != 0xffffffff) && (urb_priv->started != now))) { + if (force || ((urb_priv->started != ~0) && (urb_priv->started != now))) { async_dbg("async cleanup %p",urb); - switch (usb_pipetype (urb->pipe)) { // process descriptors + type=usb_pipetype (urb->pipe); + + switch (type) { // process descriptors case PIPE_CONTROL: - process_transfer (s, urb, 2); // 2: don't unlink (already done) + process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done) break; case PIPE_BULK: if (!s->avoid_bulk.counter) - process_transfer (s, urb, 2); // don't unlink (already done) + process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done) else continue; break; case PIPE_ISOCHRONOUS: - process_iso (s, urb, 1); // force, don't unlink + process_iso (s, urb, PROCESS_ISO_FORCE); // force, don't unlink break; case PIPE_INTERRUPT: process_interrupt (s, urb); @@ -1259,8 +1270,7 @@ if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) urb->status = -ECONNRESET; // mark as asynchronously killed - pipe = urb->pipe; // completion may destroy all... - dev = urb->dev; + dev = urb->dev; // completion may destroy all... urb_priv = urb->hcpriv; list_del (&urb->urb_list); @@ -1274,7 +1284,8 @@ if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) urb->status = -ENOENT; // now the urb is really dead - switch (usb_pipetype (pipe)) { + + switch (type) { case PIPE_ISOCHRONOUS: case PIPE_INTERRUPT: uhci_clean_iso_step2(s, urb_priv); @@ -1293,50 +1304,7 @@ } } } - -/*-------------------------------------------------------------------*/ -// needs urb_list_lock! -_static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb) -{ - uhci_desc_t *qh; - urb_priv_t *urb_priv; - - async_dbg("unlink_urb_async called %p",urb); - - if ((urb->status == -EINPROGRESS) || - ((usb_pipetype (urb->pipe) == PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags)) - { - ((urb_priv_t*)urb->hcpriv)->started = ~0; - - dequeue_urb (s, urb); - list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb - uhci_switch_timer_int(s); - - s->unlink_urb_done = 1; - - urb->status = -ECONNABORTED; // mark urb as "waiting to be killed" - urb_priv = (urb_priv_t*)urb->hcpriv; - - switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - - case PIPE_ISOCHRONOUS: - uhci_clean_iso_step1 (s, urb_priv); - break; - - case PIPE_BULK: - case PIPE_CONTROL: - qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); - uhci_clean_transfer (s, urb, qh, 0); - break; - } - ((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s); - return -EINPROGRESS; // completion will follow - } - - return 0; // URB already dead -} + /*-------------------------------------------------------------------*/ _static int uhci_unlink_urb (urb_t *urb) { @@ -1356,22 +1324,12 @@ if (urb->transfer_flags & USB_ASYNC_UNLINK) { int ret; - spin_lock_irqsave (&s->urb_list_lock, flags); - - // The URB needs to be locked if called outside completion context - - if (!in_interrupt()) - spin_lock(&urb->lock); - + uhci_release_bandwidth(urb); - ret = uhci_unlink_urb_async(s, urb); - - if (!in_interrupt()) - spin_unlock(&urb->lock); + ret = uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); spin_unlock_irqrestore (&s->urb_list_lock, flags); - return ret; } else @@ -1477,7 +1435,7 @@ { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; urb_priv_t *urb_priv = urb->hcpriv; - int nint, n, ret; + int nint, n; uhci_desc_t *td; int status, destination; int info; @@ -1509,9 +1467,7 @@ if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe))) return -EINVAL; - ret = alloc_td (s, &td, UHCI_PTR_DEPTH); - - if (ret) + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) return -ENOMEM; status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | @@ -1526,7 +1482,6 @@ fill_td (td, status, info, urb_priv->transfer_buffer_dma); list_add_tail (&td->desc_list, &urb_priv->desc_list); - urb->status = -EINPROGRESS; queue_urb (s, urb); insert_td_horizontal (s, s->int_chain[nint], td); // store in INT-TDs @@ -1563,27 +1518,27 @@ goto err; } - // First try to get all TDs + memset(tdm, 0, urb->number_of_packets * sizeof (uhci_desc_t*)); + + // First try to get all TDs. Cause: Removing already inserted TDs can only be done + // racefree in three steps: unlink TDs, wait one frame, delete TDs. + // So, this solutions seems simpler... + for (n = 0; n < urb->number_of_packets; n++) { dbg("n:%d urb->iso_frame_desc[n].length:%d", n, urb->iso_frame_desc[n].length); - if (!urb->iso_frame_desc[n].length) { - // allows ISO striping by setting length to zero in iso_descriptor - tdm[n] = 0; - continue; - } + if (!urb->iso_frame_desc[n].length) + continue; // allows ISO striping by setting length to zero in iso_descriptor + #ifdef ISO_SANITY_CHECK if(urb->iso_frame_desc[n].length > maxsze) { err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze); - tdm[n] = 0; ret=-EINVAL; } else #endif - ret = alloc_td (s, &td, UHCI_PTR_DEPTH); - - if (ret) { + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) { int i; // Cleanup allocated TDs for (i = 0; i < n; n++) @@ -1596,31 +1551,26 @@ tdm[n] = td; } - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; //| (urb->transfer_flags&USB_DISABLE_SPD?0:TD_CTRL_SPD); + status = TD_CTRL_ACTIVE | TD_CTRL_IOS; destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe); - // Queue all allocated TDs for (n = 0; n < urb->number_of_packets; n++) { td = tdm[n]; if (!td) continue; - if (n == last) + if (n == last) { status |= TD_CTRL_IOC; + queue_urb (s, urb); + } fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21), urb_priv->transfer_buffer_dma + urb->iso_frame_desc[n].offset); list_add_tail (&td->desc_list, &urb_priv->desc_list); - if (n == last) { - urb->status = -EINPROGRESS; - queue_urb (s, urb); - } insert_td_horizontal (s, s->iso_td[(urb->start_frame + n) & 1023], td); // store in iso-tds - //uhci_show_td(td); - } kfree (tdm); @@ -1630,7 +1580,6 @@ err: __restore_flags(flags); return ret; - } /*-------------------------------------------------------------------*/ // returns: 0 (no transfer queued), urb* (this urb already queued) @@ -1663,7 +1612,7 @@ { uhci_t *s; urb_priv_t *urb_priv; - int ret = 0; + int ret = 0, type; unsigned long flags; urb_t *queued_urb=NULL; int bustime; @@ -1676,10 +1625,23 @@ if (!s->running) return -ENODEV; - + + type = usb_pipetype (urb->pipe); + if (usb_pipedevice (urb->pipe) == s->rh.devnum) return rh_submit_urb (urb); /* virtual root hub */ + // Sanity checks + if (usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)) <= 0) { + err("uhci_submit_urb: pipesize for pipe %x is zero", urb->pipe); + return -EMSGSIZE; + } + + if (urb->transfer_buffer_length < 0 && type != PIPE_ISOCHRONOUS) { + err("uhci_submit_urb: Negative transfer length for urb %p", urb); + return -EINVAL; + } + usb_inc_dev_use (urb->dev); spin_lock_irqsave (&s->urb_list_lock, flags); @@ -1690,8 +1652,8 @@ queue_dbg("found bulk urb %p\n", queued_urb); - if ((usb_pipetype (urb->pipe) != PIPE_BULK) || - ((usb_pipetype (urb->pipe) == PIPE_BULK) && + if (( type != PIPE_BULK) || + ((type == PIPE_BULK) && (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) { spin_unlock_irqrestore (&s->urb_list_lock, flags); usb_dec_dev_use (urb->dev); @@ -1711,20 +1673,15 @@ return -ENOMEM; } + memset(urb_priv, 0, sizeof(urb_priv_t)); urb->hcpriv = urb_priv; INIT_LIST_HEAD (&urb_priv->desc_list); - urb_priv->flags = 0; + dbg("submit_urb: scheduling %p", urb); - urb_priv->next_queued_urb = NULL; - urb_priv->prev_queued_urb = NULL; - urb_priv->bottom_qh = NULL; - urb_priv->next_qh = NULL; - if (usb_pipetype (urb->pipe) == PIPE_CONTROL) + if (type == PIPE_CONTROL) urb_priv->setup_packet_dma = pci_map_single(s->uhci_pci, urb->setup_packet, sizeof(devrequest), PCI_DMA_TODEVICE); - else - urb_priv->setup_packet_dma = 0; if (urb->transfer_buffer_length) urb_priv->transfer_buffer_dma = pci_map_single(s->uhci_pci, @@ -1733,10 +1690,8 @@ usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - else - urb_priv->transfer_buffer_dma = 0; - if (usb_pipetype (urb->pipe) == PIPE_BULK) { + if (type == PIPE_BULK) { if (queued_urb) { while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb) // find last queued bulk @@ -1751,7 +1706,7 @@ } else { spin_unlock_irqrestore (&s->urb_list_lock, flags); - switch (usb_pipetype (urb->pipe)) { + switch (type) { case PIPE_ISOCHRONOUS: if (urb->bandwidth == 0) { /* not yet checked/allocated */ if (urb->number_of_packets <= 0) { @@ -1760,14 +1715,13 @@ } bustime = usb_check_bandwidth (urb->dev, urb); - if (bustime < 0) { + if (bustime < 0) ret = bustime; - break; + else { + ret = uhci_submit_iso_urb(urb); + if (ret == 0) + usb_claim_bandwidth (urb->dev, urb, bustime, 1); } - - ret = uhci_submit_iso_urb(urb); - if (ret == 0) - usb_claim_bandwidth (urb->dev, urb, bustime, 1); } else { /* bandwidth is already set */ ret = uhci_submit_iso_urb(urb); } @@ -1810,8 +1764,7 @@ return 0; } -// Checks for URB timeout and removes bandwidth reclamation -// if URB idles too long +// Checks for URB timeout and removes bandwidth reclamation if URB idles too long _static void uhci_check_timeouts(uhci_t *s) { struct list_head *p,*p2; @@ -1834,7 +1787,7 @@ ((hcpriv->started + urb->timeout) < jiffies)) { urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK; async_dbg("uhci_check_timeout: timeout for %p",urb); - uhci_unlink_urb_async(s, urb); + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); } #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH else if (((type == PIPE_BULK) || (type == PIPE_CONTROL)) && @@ -1973,7 +1926,6 @@ /*-------------------------------------------------------------------------*/ /* Root Hub INTs are polled by this timer, polling interval 20ms */ -/* This time is also used for URB-timeout checking */ _static int rh_init_int_timer (urb_t *urb) { @@ -2284,7 +2236,7 @@ spin_unlock_irqrestore (&s->urb_list_lock, flags); warn("forced removing of queued URB %p due to disconnect",urb); uhci_unlink_urb(urb); - urb->dev = NULL; // avoid further processing of this UR + urb->dev = NULL; // avoid further processing of this URB spin_lock_irqsave (&s->urb_list_lock, flags); p = s->urb_list.prev; } @@ -2325,13 +2277,34 @@ uhci_unlink_urb }; +_static void correct_data_toggles(urb_t *urb) +{ + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), + !usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe))); + + while(urb) { + urb_priv_t *priv=urb->hcpriv; + uhci_desc_t *qh = list_entry (priv->desc_list.next, uhci_desc_t, desc_list); + struct list_head *p = qh->vertical.next; + uhci_desc_t *td; + dbg("URB to correct %p\n", urb); + + for (; p != &qh->vertical; p = p->next) { + td = list_entry (p, uhci_desc_t, vertical); + td->hw.td.info^=cpu_to_le32(1<next_queued_urb; + } +} + /* * For IN-control transfers, process_transfer gets a bit more complicated, * since there are devices that return less data (eg. strings) than they * have announced. This leads to a queue abort due to the short packet, * the status stage is not executed. If this happens, the status stage * is manually re-executed. - * mode: 1: regular (unlink QH), 2: QHs already unlinked (for async unlink_urb) + * mode: PROCESS_TRANSFER_REGULAR: regular (unlink QH) + * PROCESS_TRANSFER_DONT_UNLINK: QHs already unlinked (for async unlink_urb) */ _static int process_transfer (uhci_t *s, urb_t *urb, int mode) @@ -2356,7 +2329,7 @@ */ if (urb_priv->flags && - ((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) ||(!(last_desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE))))) + ((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) || !is_td_active(desc))) goto transfer_finished; urb->actual_length=0; @@ -2364,13 +2337,13 @@ for (; p != &qh->vertical; p = p->next) { desc = list_entry (p, uhci_desc_t, vertical); - if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) { // do not process active TDs - if (mode==2) // if called from async_unlink - uhci_clean_transfer(s, urb, qh, mode); + if (is_td_active(desc)) { // do not process active TDs + if (mode == CLEAN_TRANSFER_DELETION_MARK) // if called from async_unlink + uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK); return ret; } - actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff; // extract transfer parameters from TD + actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); // extract transfer parameters from TD maxlength = (((le32_to_cpu(desc->hw.td.info) >> 21) & 0x7ff) + 1) & 0x7ff; status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); @@ -2401,10 +2374,8 @@ if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) { if (uhci_packetid(le32_to_cpu(last_desc->hw.td.info)) == USB_PID_OUT) { - qh->hw.qh.element = cpu_to_le32(last_desc->dma_addr); // re-trigger status stage + set_qh_element(qh, last_desc->dma_addr); // re-trigger status stage dbg("short packet during control transfer, retrigger status stage @ %p",last_desc); - //uhci_show_td (desc); - //uhci_show_td (last_desc); urb_priv->flags = 1; // mark as short control packet return 0; } @@ -2421,7 +2392,24 @@ } - usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle); + if (usb_pipetype (urb->pipe) == PIPE_BULK ) { /* toggle correction for short bulk transfers (nonqueued/queued) */ + + urb_priv_t *priv=(urb_priv_t*)urb->hcpriv; + urb_t *next_queued_urb=priv->next_queued_urb; + + if (next_queued_urb) { + urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->hcpriv; + uhci_desc_t *qh = list_entry (next_priv->desc_list.next, uhci_desc_t, desc_list); + uhci_desc_t *first_td=list_entry (qh->vertical.next, uhci_desc_t, vertical); + + if (data_toggle == uhci_toggle (le32_to_cpu(first_td->hw.td.info))) { + err("process_transfer: fixed toggle"); + correct_data_toggles(next_queued_urb); + } + } + else + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle); + } transfer_finished: @@ -2454,7 +2442,7 @@ { desc = list_entry (p, uhci_desc_t, desc_list); - if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) { + if (is_td_active(desc)) { // do not process active TDs //dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status)); break; @@ -2466,7 +2454,7 @@ } // extract transfer parameters from TD - actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff; + actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); // see if EP is stalled @@ -2523,8 +2511,8 @@ mb(); } else { - uhci_unlink_urb_async(s, urb); - desc->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC); // inactivate TD + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); + clr_td_ioc(desc); // inactivate TD } } } @@ -2532,7 +2520,9 @@ return ret; } -// mode: 1: force processing, don't unlink tds (already unlinked) +// mode: PROCESS_ISO_REGULAR: processing only for done TDs, unlink TDs +// mode: PROCESS_ISO_FORCE: force processing, don't unlink TDs (already unlinked) + _static int process_iso (uhci_t *s, urb_t *urb, int mode) { int i; @@ -2542,7 +2532,7 @@ uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); dbg("urb contains iso request"); - if ((desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) && !mode) + if (is_td_active(desc) && mode==PROCESS_ISO_REGULAR) return -EXDEV; // last TD not finished urb->error_count = 0; @@ -2555,7 +2545,7 @@ desc = list_entry (p, uhci_desc_t, desc_list); //uhci_show_td(desc); - if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) { + if (is_td_active(desc)) { // means we have completed the last TD, but not the TDs before desc->hw.td.status &= cpu_to_le32(~TD_CTRL_ACTIVE); dbg("TD still active (%x)- grrr. paranoia!", le32_to_cpu(desc->hw.td.status)); @@ -2566,7 +2556,7 @@ goto err; } - if (!mode) + if (mode == PROCESS_ISO_REGULAR) unlink_td (s, desc, 1); if (urb->number_of_packets <= i) { @@ -2575,7 +2565,7 @@ goto err; } - urb->iso_frame_desc[i].actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff; + urb->iso_frame_desc[i].actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); urb->actual_length += urb->iso_frame_desc[i].actual_length; @@ -2608,16 +2598,16 @@ switch (usb_pipetype (urb->pipe)) { case PIPE_CONTROL: - ret = process_transfer (s, urb, 1); + ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR); break; case PIPE_BULK: if (!s->avoid_bulk.counter) - ret = process_transfer (s, urb, 1); + ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR); else return 0; break; case PIPE_ISOCHRONOUS: - ret = process_iso (s, urb, 0); + ret = process_iso (s, urb, PROCESS_ISO_REGULAR); break; case PIPE_INTERRUPT: ret = process_interrupt (s, urb); @@ -2673,9 +2663,7 @@ if (next_urb == urb) is_ring=1; - } - - spin_lock(&urb->lock); + } // Submit idle/non-killed URBs linked with urb->next // Stop before the current URB @@ -2712,19 +2700,18 @@ int was_unlinked = (urb->status == -ENOENT); urb->dev = NULL; spin_unlock(&s->urb_list_lock); + urb->complete ((struct urb *) urb); + // Re-submit the URB if ring-linked if (is_ring && !was_unlinked && !contains_killed) { urb->dev=usb_dev; uhci_submit_urb (urb); - } else - urb = 0; + } spin_lock(&s->urb_list_lock); } usb_dec_dev_use (usb_dev); - if (urb) - spin_unlock(&urb->lock); } } @@ -2752,11 +2739,16 @@ dbg("interrupt"); if (status != 1) { - warn("interrupt, status %x, frame# %i", status, - UHCI_GET_CURRENT_FRAME(s)); - + // Avoid too much error messages at a time + if ((jiffies - s->last_error_time > ERROR_SUPPRESSION_TIME)) { + warn("interrupt, status %x, frame# %i", status, + UHCI_GET_CURRENT_FRAME(s)); + s->last_error_time = jiffies; + } + // remove host controller halted state if ((status&0x20) && (s->running)) { + err("Host controller halted, trying to restart."); outw (USBCMD_RS | inw(io_addr + USBCMD), io_addr + USBCMD); } //uhci_show_status (s); @@ -2799,8 +2791,8 @@ if ((jiffies - s->timeout_check) > (HZ/30)) uhci_check_timeouts(s); - clean_descs(s,0); - uhci_cleanup_unlink(s, 0); + clean_descs(s, CLEAN_NOT_FORCED); + uhci_cleanup_unlink(s, CLEAN_NOT_FORCED); uhci_switch_timer_int(s); spin_unlock (&s->urb_list_lock); @@ -2869,8 +2861,8 @@ reset_hc (s); wait_ms (1); - uhci_unlink_urbs (s, 0, 1); // Forced unlink of remaining URBs - uhci_cleanup_unlink (s, 1); // force cleanup of async killed URBs + uhci_unlink_urbs (s, 0, CLEAN_FORCED); // Forced unlink of remaining URBs + uhci_cleanup_unlink (s, CLEAN_FORCED); // force cleanup of async killed URBs usb_deregister_bus (s->bus); @@ -2943,11 +2935,9 @@ spin_lock_init (&s->qh_lock); spin_lock_init (&s->td_lock); atomic_set(&s->avoid_bulk, 0); - s->timeout_urbs = 0; s->irq = -1; s->io_addr = io_addr; s->io_size = io_size; - s->timeout_check = 0; s->uhci_pci=dev; bus = usb_alloc_bus (&uhci_device_operations); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h --- v2.4.9/linux/drivers/usb/usb-uhci.h Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/usb-uhci.h Tue Aug 28 11:21:02 2001 @@ -2,7 +2,7 @@ #define __LINUX_UHCI_H /* - $Id: usb-uhci.h,v 1.55 2000/05/13 12:50:30 acher Exp $ + $Id: usb-uhci.h,v 1.58 2001/08/28 16:45:00 acher Exp $ */ #define MODNAME "usb-uhci" #define UHCI_LATENCY_TIMER 0 @@ -218,12 +218,35 @@ int timeout_urbs; struct pci_dev *uhci_pci; struct pci_pool *desc_pool; + long last_error_time; // last error output in uhci_interrupt() } uhci_t, *puhci_t; #define MAKE_TD_ADDR(a) ((a)->dma_addr&~UHCI_PTR_QH) #define MAKE_QH_ADDR(a) ((a)->dma_addr|UHCI_PTR_QH) #define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM)) + +#define CLEAN_TRANSFER_NO_DELETION 0 +#define CLEAN_TRANSFER_REGULAR 1 +#define CLEAN_TRANSFER_DELETION_MARK 2 + +#define CLEAN_NOT_FORCED 0 +#define CLEAN_FORCED 1 + +#define PROCESS_ISO_REGULAR 0 +#define PROCESS_ISO_FORCE 1 + +#define UNLINK_ASYNC_STORE_URB 0 +#define UNLINK_ASYNC_DONT_STORE 1 + +#define is_td_active(desc) (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) + +#define set_qh_head(desc,val) (desc)->hw.qh.head=cpu_to_le32(val) +#define set_qh_element(desc,val) (desc)->hw.qh.element=cpu_to_le32(val) +#define set_td_link(desc,val) (desc)->hw.td.link=cpu_to_le32(val) +#define set_td_ioc(desc) (desc)->hw.td.status |= cpu_to_le32(TD_CTRL_IOC) +#define clr_td_ioc(desc) (desc)->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC) + /* ------------------------------------------------------------------------------------ Virtual Root HUB diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.4.9/linux/drivers/usb/usb.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/usb.c Tue Aug 28 11:22:21 2001 @@ -459,7 +459,7 @@ list_del(&bus->bus_list); write_unlock_irq (&usb_bus_list_lock); - usbdevfs_remove_bus(bus); + usbdevfs_remove_bus(bus); clear_bit(bus->busnum, busmap.busmap); @@ -707,7 +707,6 @@ private = NULL; for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) { - driver = list_entry(tmp, struct usb_driver, driver_list); tmp = tmp->next; @@ -725,17 +724,19 @@ break; } } + /* if driver not bound, leave defaults unchanged */ if (private == NULL) interface->act_altsetting = 0; - } - else /* "old style" driver */ - { + } else { /* "old style" driver */ down(&driver->serialize); private = driver->probe(dev, ifnum, NULL); up(&driver->serialize); } + /* probe() may have changed the config on us */ + interface = dev->actconfig->interface + ifnum; + if (private) { usb_driver_claim_interface(driver, interface, private); up(&dev->serialize); @@ -1178,7 +1179,7 @@ * @pipe: endpoint "pipe" to send the message to * @data: pointer to the data to send * @len: length in bytes of the data to send - * @actual_length: pointer to a location to put the actual length transfered in bytes + * @actual_length: pointer to a location to put the actual length transferred in bytes * @timeout: time to wait for the message to complete before timing out (if 0 the wait is forever) * * This function sends a simple bulk message to a specified endpoint @@ -1222,7 +1223,7 @@ } /*-------------------------------------------------------------------*/ -static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size) +static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size) { struct usb_descriptor_header *header; unsigned char *begin; @@ -1266,8 +1267,7 @@ return -1; } - /* If we find another descriptor which is at or below us */ - /* in the descriptor heirarchy then we're done */ + /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_CONFIG) || @@ -1308,7 +1308,7 @@ return parsed; } -static int usb_parse_interface(struct usb_device *dev, struct usb_interface *interface, unsigned char *buffer, int size) +static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size) { int i, len, numskipped, retval, parsed = 0; struct usb_descriptor_header *header; @@ -1373,8 +1373,7 @@ return -1; } - /* If we find another descriptor which is at or below */ - /* us in the descriptor heirarchy then return */ + /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_CONFIG) || @@ -1440,7 +1439,7 @@ return -1; } - retval = usb_parse_endpoint(dev, ifp->endpoint + i, buffer, size); + retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); if (retval < 0) return retval; @@ -1460,7 +1459,7 @@ return parsed; } -int usb_parse_configuration(struct usb_device *dev, struct usb_config_descriptor *config, char *buffer) +int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer) { int i, retval, size; struct usb_descriptor_header *header; @@ -1489,6 +1488,9 @@ buffer += config->bLength; size -= config->bLength; + config->extra = NULL; + config->extralen = 0; + for (i = 0; i < config->bNumInterfaces; i++) { int numskipped, len; char *begin; @@ -1505,8 +1507,7 @@ return -1; } - /* If we find another descriptor which is at or below */ - /* us in the descriptor heirarchy then we're done */ + /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_CONFIG) || @@ -1525,22 +1526,23 @@ /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ len = (int)(buffer - begin); - if (!len) { - config->extra = NULL; - config->extralen = 0; - } else { - config->extra = kmalloc(len, GFP_KERNEL); - if (!config->extra) { - err("couldn't allocate memory for config extra descriptors"); - config->extralen = 0; - return -1; - } + if (len) { + if (config->extralen) { + warn("extra config descriptor"); + } else { + config->extra = kmalloc(len, GFP_KERNEL); + if (!config->extra) { + err("couldn't allocate memory for config extra descriptors"); + config->extralen = 0; + return -1; + } - memcpy(config->extra, begin, len); - config->extralen = len; + memcpy(config->extra, begin, len); + config->extralen = len; + } } - retval = usb_parse_interface(dev, config->interface + i, buffer, size); + retval = usb_parse_interface(config->interface + i, buffer, size); if (retval < 0) return retval; @@ -2081,7 +2083,7 @@ dev->rawdescriptors[cfgno] = bigbuffer; - result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer); + result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); if (result > 0) dbg("descriptor data left"); else if (result < 0) { diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usbnet.c linux/drivers/usb/usbnet.c --- v2.4.9/linux/drivers/usb/usbnet.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/usbnet.c Tue Aug 28 11:21:02 2001 @@ -0,0 +1,1567 @@ +/* + * USB Host-to-Host Links + * Copyright (C) 2000-2001 by David Brownell + */ + +/* + * This is used for "USB networking", connecting USB hosts as peers. + * + * It can be used with USB "network cables", for IP-over-USB communications; + * Ethernet speeds without the Ethernet. USB devices (including some PDAs) + * can support such links directly, replacing device-specific protocols + * with Internet standard ones. + * + * The links can be bridged using the Ethernet bridging (net/bridge) + * support as appropriate. Devices currently supported include: + * + * - AnchorChip 2720 + * - Belkin F5U104 (custom) + * - "Linux Devices" (like iPaq and similar SA-1100 based PDAs) + * - NetChip 1080 (interoperates with NetChip Win32 drivers) + * - Prolific PL-2301/2302 (replaces "plusb" driver) + * + * USB devices can implement their side of this protocol at the cost + * of two bulk endpoints; it's not restricted to "cable" applications. + * See the LINUXDEV support. + * + * + * TODO: + * + * This needs to be retested for bulk queuing problems ... earlier versions + * seemed to find different types of problems in each HCD. Once they're fixed, + * re-enable queues to get higher bandwidth utilization (without needing + * to tweak MTU for larger packets). + * + * Add support for more "network cable" chips; interop with their Win32 + * drivers may be a good thing. Test the AnchorChip 2720 support.. + * Figure out the initialization protocol used by the Prolific chips, + * for better robustness ... there's some powerup/reset handshake that's + * needed when only one end reboots. + * + * Use interrupt on PL230x to detect peer connect/disconnect, and call + * netif_carrier_{on,off} (?) appropriately. For Net1080, detect peer + * connect/disconnect with async control messages. + * + * Find some way to report "peer connected" network hotplug events; it'll + * likely mean updating the networking layer. (This has been discussed + * on the netdev list...) + * + * Craft smarter hotplug policy scripts ... ones that know how to arrange + * bridging with "brctl", and can handle static and dynamic ("pump") setups. + * Use those "peer connected" events. + * + * + * CHANGELOG: + * + * 13-sep-2000 experimental, new + * 10-oct-2000 usb_device_id table created. + * 28-oct-2000 misc fixes; mostly, discard more TTL-mangled rx packets. + * 01-nov-2000 usb_device_id table and probing api update by + * Adam J. Richter . + * 18-dec-2000 (db) tx watchdog, "net1080" renaming to "usbnet", device_info + * and prolific support, isolate net1080-specific bits, cleanup. + * fix unlink_urbs oops in D3 PM resume code path. + * 02-feb-2001 (db) fix tx skb sharing, packet length, match_flags, ... + * 08-feb-2001 stubbed in "linuxdev", maybe the SA-1100 folk can use it; + * AnchorChips 2720 support (from spec) for testing; + * fix bit-ordering problem with ethernet multicast addr + * 19-feb-2001 Support for clearing halt conditions. SA1100 UDC support + * updates. Oleg Drokin (green@iXcelerator.com) + * 25-mar-2001 More SA-1100 updates, including workaround for ip problem + * expecting cleared skb->cb and framing change to match latest + * handhelds.org version (Oleg). Enable device IDs from the + * Win32 Belkin driver; other cleanups (db). + * 16-jul-2001 Bugfixes for uhci oops-on-unplug, Belkin support, various + * cleanups for problems not yet seen in the field. (db) + * + *-------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #define DEBUG // error path messages, extra info +// #define VERBOSE // more; success messages +// #define REALLY_QUEUE + +#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) +# define DEBUG +#endif +#include + + +#define CONFIG_USB_AN2720 +#define CONFIG_USB_BELKIN_F5U104 +#define CONFIG_USB_LINUXDEV +#define CONFIG_USB_NET1080 +#define CONFIG_USB_PL2301 + + +/*-------------------------------------------------------------------------*/ + +/* + * Nineteen USB 1.1 max size bulk transactions per frame (ms), max. + * Several dozen bytes of IPv4 data can fit in two such transactions. + * One maximum size Ethernet packet takes twenty four of them. + */ +#ifdef REALLY_QUEUE +#define RX_QLEN 4 +#define TX_QLEN 4 +#else +#define RX_QLEN 1 +#define TX_QLEN 1 +#endif + +// packets are always ethernet inside +// ... except they can be bigger (up to 64K with this framing) +#define MIN_PACKET sizeof(struct ethhdr) +#define MAX_PACKET 32768 + +// reawaken network queue this soon after stopping; else watchdog barks +#define TX_TIMEOUT_JIFFIES (5*HZ) + +// for vendor-specific control operations +#define CONTROL_TIMEOUT_MS (500) /* msec */ +#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000) + +// between wakeups +#define UNLINK_TIMEOUT_JIFFIES ((3 /*ms*/ * HZ)/1000) + +/*-------------------------------------------------------------------------*/ + +// list of all devices we manage +static DECLARE_MUTEX (usbnet_mutex); +static LIST_HEAD (usbnet_list); + +// randomly generated ethernet address +static u8 node_id [ETH_ALEN]; + +// state we keep for each device we handle +struct usbnet { + // housekeeping + struct usb_device *udev; + struct driver_info *driver_info; + struct semaphore mutex; + struct list_head dev_list; + wait_queue_head_t *wait; + + // protocol/interface state + struct net_device net; + struct net_device_stats stats; + u16 packet_id; + + // various kinds of pending driver work + struct sk_buff_head rxq; + struct sk_buff_head txq; + struct sk_buff_head done; + struct tasklet_struct bh; + struct tq_struct ctrl_task; +}; + +// device-specific info used by the driver +struct driver_info { + char *description; + + int flags; +#define FLAG_FRAMING 0x0001 /* guard against device dropouts */ + + /* reset device ... can sleep */ + int (*reset)(struct usbnet *); + + /* see if peer is connected ... can sleep */ + int (*check_connect)(struct usbnet *); + + // FIXME -- also an interrupt mechanism + + /* framework currently "knows" bulk EPs talk packets */ + int in; /* rx endpoint */ + int out; /* tx endpoint */ + int epsize; +}; + +#define EP_SIZE(usbnet) ((usbnet)->driver_info->epsize) + +// we record the state for each of our queued skbs +enum skb_state { + illegal = 0, + tx_start, tx_done, + rx_start, rx_done, rx_cleanup +}; + +struct skb_data { // skb->cb is one of these + struct urb *urb; + struct usbnet *dev; + enum skb_state state; + size_t length; +}; + + +#define mutex_lock(x) down(x) +#define mutex_unlock(x) up(x) + +#define RUN_CONTEXT (in_irq () ? "in_irq" \ + : (in_interrupt () ? "in_interrupt" : "can sleep")) + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +#define devdbg(usbnet, fmt, arg...) \ + printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net.name, ## arg) +#else +#define devdbg(usbnet, fmt, arg...) do {} while(0) +#endif + +#define devinfo(usbnet, fmt, arg...) \ + printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg) + +/*------------------------------------------------------------------------- + * + * NetChip framing of ethernet packets, supporting additional error + * checks for links that may drop bulk packets from inside messages. + * Odd USB length == always short read for last usb packet. + * - nc_header + * - Ethernet header (14 bytes) + * - payload + * - (optional padding byte, if needed so length becomes odd) + * - nc_trailer + * + * This framing is to be avoided for non-NetChip devices. + */ + +struct nc_header { // packed: + u16 hdr_len; // sizeof nc_header (LE, all) + u16 packet_len; // payload size (including ethhdr) + u16 packet_id; // detects dropped packets +#define MIN_HEADER 6 + + // all else is optional, and must start with: + // u16 vendorId; // from usb-if + // u16 productId; +} __attribute__((__packed__)); + +#define PAD_BYTE ((unsigned char)0xAC) + +struct nc_trailer { + u16 packet_id; +} __attribute__((__packed__)); + +// packets may use FLAG_FRAMING and optional pad +#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \ + + sizeof (struct ethhdr) \ + + (mtu) \ + + 1 \ + + sizeof (struct nc_trailer)) + +#define MIN_FRAMED FRAMED_SIZE(0) + + + +#ifdef CONFIG_USB_AN2720 + +/*------------------------------------------------------------------------- + * + * AnchorChips 2720 driver ... http://www.cypress.com + * + * This doesn't seem to have a way to detect whether the peer is + * connected, or need any reset handshaking. It's got pretty big + * internal buffers (handles most of a frame's worth of data). + * Chip data sheets don't describe any vendor control messages. + * + *-------------------------------------------------------------------------*/ + +static const struct driver_info an2720_info = { + description: "AnchorChips/Cypress 2720", + // no reset available! + // no check_connect available! + + in: 2, out: 2, // direction distinguishes these + epsize: 64, +}; + +#endif /* CONFIG_USB_AN2720 */ + + + +#ifdef CONFIG_USB_BELKIN_F5U104 + +/*------------------------------------------------------------------------- + * + * Belkin F5U104 ... two NetChip 2280 devices + Atmel microcontroller + * + *-------------------------------------------------------------------------*/ + +static const struct driver_info belkin_info = { + description: "Belkin USB Direct Connect (F5U104)", + + in: 1, out: 1, // direction distinguishes these + epsize: 64, +}; + +#endif /* CONFIG_USB_BELKIN_F5U104 */ + + + +#ifdef CONFIG_USB_LINUXDEV + +/*------------------------------------------------------------------------- + * + * This could talk to a device that uses Linux, such as a PDA or + * an embedded system, or in fact to any "smart" device using this + * particular mapping of USB and Ethernet. + * + * Such a Linux host would need a "USB Device Controller" hardware + * (not "USB Host Controller"), and a network driver talking to that + * hardware. + * + * One example is Intel's SA-1100 chip, which integrates basic USB + * support (arch/arm/sa1100/usb-eth.c); it's used in the iPaq PDA. + * + *-------------------------------------------------------------------------*/ + + +static const struct driver_info linuxdev_info = { + description: "Linux Device", + // no reset defined (yet?) + // no check_connect needed! + in: 2, out: 1, + epsize: 64, +}; + +#endif /* CONFIG_USB_LINUXDEV */ + + + +#ifdef CONFIG_USB_NET1080 + +/*------------------------------------------------------------------------- + * + * Netchip 1080 driver ... http://www.netchip.com + * + *-------------------------------------------------------------------------*/ + +/* + * Zero means no timeout; else, how long a 64 byte bulk packet may be queued + * before the hardware drops it. If that's done, the driver will need to + * frame network packets to guard against the dropped USB packets. The win32 + * driver sets this for both sides of the link. + */ +#define NC_READ_TTL_MS ((u8)255) // ms + +/* + * We ignore most registers and EEPROM contents. + */ +#define REG_USBCTL ((u8)0x04) +#define REG_TTL ((u8)0x10) +#define REG_STATUS ((u8)0x11) + +/* + * Vendor specific requests to read/write data + */ +#define REQUEST_REGISTER ((u8)0x10) +#define REQUEST_EEPROM ((u8)0x11) + +static int +nc_vendor_read (struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr) +{ + int status = usb_control_msg (dev->udev, + usb_rcvctrlpipe (dev->udev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, regnum, + retval_ptr, sizeof *retval_ptr, + CONTROL_TIMEOUT_JIFFIES); + if (status > 0) + status = 0; + if (!status) + le16_to_cpus (retval_ptr); + return status; +} + +static inline int +nc_register_read (struct usbnet *dev, u8 regnum, u16 *retval_ptr) +{ + return nc_vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr); +} + +// no retval ... can become async, usable in_interrupt() +static void +nc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value) +{ + usb_control_msg (dev->udev, + usb_sndctrlpipe (dev->udev, 0), + req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, regnum, + 0, 0, // data is in setup packet + CONTROL_TIMEOUT_JIFFIES); +} + +static inline void +nc_register_write (struct usbnet *dev, u8 regnum, u16 value) +{ + nc_vendor_write (dev, REQUEST_REGISTER, regnum, value); +} + + +#if 0 +static void nc_dump_registers (struct usbnet *dev) +{ + u8 reg; + u16 *vp = kmalloc (sizeof (u16)); + + if (!vp) { + dbg ("no memory?"); + return; + } + + dbg ("%s registers:", dev->net.name); + for (reg = 0; reg < 0x20; reg++) { + int retval; + + // reading some registers is trouble + if (reg >= 0x08 && reg <= 0xf) + continue; + if (reg >= 0x12 && reg <= 0x1e) + continue; + + retval = nc_register_read (dev, reg, vp); + if (retval < 0) + dbg ("%s reg [0x%x] ==> error %d", + dev->net.name, reg, retval); + else + dbg ("%s reg [0x%x] = 0x%x", + dev->net.name, reg, *vp); + } + kfree (vp); +} +#endif + + +/*-------------------------------------------------------------------------*/ + +/* + * Control register + */ + +#define USBCTL_WRITABLE_MASK 0x1f0f +// bits 15-13 reserved, r/o +#define USBCTL_ENABLE_LANG (1 << 12) +#define USBCTL_ENABLE_MFGR (1 << 11) +#define USBCTL_ENABLE_PROD (1 << 10) +#define USBCTL_ENABLE_SERIAL (1 << 9) +#define USBCTL_ENABLE_DEFAULTS (1 << 8) +// bits 7-4 reserved, r/o +#define USBCTL_FLUSH_OTHER (1 << 3) +#define USBCTL_FLUSH_THIS (1 << 2) +#define USBCTL_DISCONN_OTHER (1 << 1) +#define USBCTL_DISCONN_THIS (1 << 0) + +static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl) +{ +#ifdef DEBUG + devdbg (dev, "net1080 %03d/%03d usbctl 0x%x:%s%s%s%s%s;" + " this%s%s;" + " other%s%s; r/o 0x%x", + dev->udev->bus->busnum, dev->udev->devnum, + usbctl, + (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", + (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", + (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", + (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", + (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", + + (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", + (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", + (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", + (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", + usbctl & ~USBCTL_WRITABLE_MASK + ); +#endif +} + +/*-------------------------------------------------------------------------*/ + +/* + * Status register + */ + +#define STATUS_PORT_A (1 << 15) + +#define STATUS_CONN_OTHER (1 << 14) +#define STATUS_SUSPEND_OTHER (1 << 13) +#define STATUS_MAILBOX_OTHER (1 << 12) +#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03) + +#define STATUS_CONN_THIS (1 << 6) +#define STATUS_SUSPEND_THIS (1 << 5) +#define STATUS_MAILBOX_THIS (1 << 4) +#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03) + +#define STATUS_UNSPEC_MASK 0x0c8c +#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK)) + + +static inline void nc_dump_status (struct usbnet *dev, u16 status) +{ +#ifdef DEBUG + devdbg (dev, "net1080 %03d/%03d status 0x%x:" + " this (%c) PKT=%d%s%s%s;" + " other PKT=%d%s%s%s; unspec 0x%x", + dev->udev->bus->busnum, dev->udev->devnum, + status, + + // XXX the packet counts don't seem right + // (1 at reset, not 0); maybe UNSPEC too + + (status & STATUS_PORT_A) ? 'A' : 'B', + STATUS_PACKETS_THIS (status), + (status & STATUS_CONN_THIS) ? " CON" : "", + (status & STATUS_SUSPEND_THIS) ? " SUS" : "", + (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", + + STATUS_PACKETS_OTHER (status), + (status & STATUS_CONN_OTHER) ? " CON" : "", + (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", + (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", + + status & STATUS_UNSPEC_MASK + ); +#endif +} + +/*-------------------------------------------------------------------------*/ + +/* + * TTL register + */ + +#define TTL_THIS(ttl) (0x00ff & ttl) +#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8)) +#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this)))) + +static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl) +{ +#ifdef DEBUG + devdbg (dev, "net1080 %03d/%03d ttl 0x%x this = %d, other = %d", + dev->udev->bus->busnum, dev->udev->devnum, + ttl, + + TTL_THIS (ttl), + TTL_OTHER (ttl) + ); +#endif +} + +/*-------------------------------------------------------------------------*/ + +static int net1080_reset (struct usbnet *dev) +{ + u16 usbctl, status, ttl; + u16 *vp = kmalloc (sizeof (u16), GFP_KERNEL); + int retval; + + if (!vp) + return -ENOMEM; + + // nc_dump_registers (dev); + + if ((retval = nc_register_read (dev, REG_STATUS, vp)) < 0) { + dbg ("can't read dev %d status: %d", dev->udev->devnum, retval); + goto done; + } + status = *vp; + // nc_dump_status (dev, status); + + if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) { + dbg ("can't read USBCTL, %d", retval); + goto done; + } + usbctl = *vp; + // nc_dump_usbctl (dev, usbctl); + + nc_register_write (dev, REG_USBCTL, + USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER); + + if ((retval = nc_register_read (dev, REG_TTL, vp)) < 0) { + dbg ("can't read TTL, %d", retval); + goto done; + } + ttl = *vp; + // nc_dump_ttl (dev, ttl); + + nc_register_write (dev, REG_TTL, + MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) ); + dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL_MS); + + devdbg (dev, "port %c, peer %sconnected", + (status & STATUS_PORT_A) ? 'A' : 'B', + (status & STATUS_CONN_OTHER) ? "" : "dis" + ); + retval = 0; + +done: + kfree (vp); + return retval; +} + +static int net1080_check_connect (struct usbnet *dev) +{ + int retval; + u16 status; + u16 *vp = kmalloc (sizeof (u16), GFP_KERNEL); + + if (!vp) + return -ENOMEM; + retval = nc_register_read (dev, REG_STATUS, vp); + status = *vp; + kfree (vp); + if (retval != 0) { + dbg ("%s net1080_check_conn read - %d", dev->net.name, retval); + return retval; + } + if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER) + return -ENOLINK; + return 0; +} + +static const struct driver_info net1080_info = { + description: "NetChip TurboCONNECT", + flags: FLAG_FRAMING, + reset: net1080_reset, + check_connect: net1080_check_connect, + + in: 1, out: 1, // direction distinguishes these + epsize: 64, +}; + +#endif /* CONFIG_USB_NET1080 */ + + + +#ifdef CONFIG_USB_PL2301 + +/*------------------------------------------------------------------------- + * + * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com + * + *-------------------------------------------------------------------------*/ + +/* + * Bits 0-4 can be used for software handshaking; they're set from + * one end, cleared from the other, "read" with the interrupt byte. + */ +#define PL_S_EN (1<<7) /* (feature only) suspend enable */ +/* reserved bit -- rx ready (6) ? */ +#define PL_TX_READY (1<<5) /* (interrupt only) transmit ready */ +#define PL_RESET_OUT (1<<4) /* reset output pipe */ +#define PL_RESET_IN (1<<3) /* reset input pipe */ +#define PL_TX_C (1<<2) /* transmission complete */ +#define PL_TX_REQ (1<<1) /* transmission received */ +#define PL_PEER_E (1<<0) /* peer exists */ + +static inline int +pl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index) +{ + return usb_control_msg (dev->udev, + usb_rcvctrlpipe (dev->udev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + val, index, + 0, 0, + CONTROL_TIMEOUT_JIFFIES); +} + +static inline int +pl_clear_QuickLink_features (struct usbnet *dev, int val) +{ + return pl_vendor_req (dev, 1, (u8) val, 0); +} + +static inline int +pl_set_QuickLink_features (struct usbnet *dev, int val) +{ + return pl_vendor_req (dev, 3, (u8) val, 0); +} + +/*-------------------------------------------------------------------------*/ + +static int pl_reset (struct usbnet *dev) +{ + return pl_set_QuickLink_features (dev, + PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E); +} + +static int pl_check_connect (struct usbnet *dev) +{ + // FIXME test interrupt data PL_PEER_E bit + // plus, there's some handshake done by + // the prolific win32 driver... + dbg ("%s: assuming peer is connected", dev->net.name); + return 0; +} + +static const struct driver_info prolific_info = { + description: "Prolific PL-2301/PL-2302", + reset: pl_reset, + check_connect: pl_check_connect, + + in: 3, out: 2, + epsize: 64, +}; + +#endif /* CONFIG_USB_PL2301 */ + + + +/*------------------------------------------------------------------------- + * + * Network Device Driver (peer link to "Host Device", from USB host) + * + *-------------------------------------------------------------------------*/ + +static int usbnet_change_mtu (struct net_device *net, int new_mtu) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + + if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET) + return -EINVAL; + if (((dev->driver_info->flags) & FLAG_FRAMING)) { + if (FRAMED_SIZE (new_mtu) > MAX_PACKET) + return -EINVAL; + // no second zero-length packet read wanted after mtu-sized packets + } else if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0) + return -EDOM; + net->mtu = new_mtu; + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct net_device_stats *usbnet_get_stats (struct net_device *net) +{ + return &((struct usbnet *) net->priv)->stats; +} + +/*-------------------------------------------------------------------------*/ + +/* urb completions are currently in_irq; avoid doing real work then. */ + +static void defer_bh (struct usbnet *dev, struct sk_buff *skb) +{ + struct sk_buff_head *list = skb->list; + unsigned long flags; + + spin_lock_irqsave (&list->lock, flags); + __skb_unlink (skb, list); + spin_unlock (&list->lock); + spin_lock (&dev->done.lock); + __skb_queue_tail (&dev->done, skb); + if (dev->done.qlen == 1) + tasklet_schedule (&dev->bh); + spin_unlock_irqrestore (&dev->done.lock, flags); +} + +/*-------------------------------------------------------------------------*/ + +static void rx_complete (struct urb *urb); + +static void rx_submit (struct usbnet *dev, struct urb *urb, int flags) +{ + struct sk_buff *skb; + struct skb_data *entry; + int retval = 0; + unsigned long lockflags; + size_t size; + + size = (dev->driver_info->flags & FLAG_FRAMING) + ? FRAMED_SIZE (dev->net.mtu) + : (sizeof (struct ethhdr) + dev->net.mtu); + if ((skb = alloc_skb (size, flags)) == 0) { + dbg ("no rx skb"); + tasklet_schedule (&dev->bh); + usb_free_urb (urb); + return; + } + + entry = (struct skb_data *) skb->cb; + entry->urb = urb; + entry->dev = dev; + entry->state = rx_start; + entry->length = 0; + + FILL_BULK_URB (urb, dev->udev, + usb_rcvbulkpipe (dev->udev, dev->driver_info->in), + skb->data, size, rx_complete, skb); +#ifdef REALLY_QUEUE + urb->transfer_flags |= USB_QUEUE_BULK; +#endif + + spin_lock_irqsave (&dev->rxq.lock, lockflags); + + if (netif_running (&dev->net)) { + if ((retval = usb_submit_urb (urb)) != 0) { + dbg ("%s rx submit, %d", dev->net.name, retval); + tasklet_schedule (&dev->bh); + } else { + __skb_queue_tail (&dev->rxq, skb); + } + } else { + dbg ("rx: stopped"); + retval = -ENOLINK; + } + spin_unlock_irqrestore (&dev->rxq.lock, lockflags); + if (retval) { + dev_kfree_skb_any (skb); + usb_free_urb (urb); + } +} + + +/*-------------------------------------------------------------------------*/ + +static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) +{ + if (dev->driver_info->flags & FLAG_FRAMING) { + struct nc_header *header; + struct nc_trailer *trailer; + + if (!(skb->len & 0x01) + || MIN_FRAMED > skb->len + || skb->len > FRAMED_SIZE (dev->net.mtu)) { + dev->stats.rx_frame_errors++; + dbg ("rx framesize %d range %d..%d mtu %d", skb->len, + MIN_FRAMED, FRAMED_SIZE (dev->net.mtu), + dev->net.mtu + ); + goto error; + } + + header = (struct nc_header *) skb->data; + le16_to_cpus (&header->hdr_len); + le16_to_cpus (&header->packet_len); + if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) { + dev->stats.rx_frame_errors++; + dbg ("packet too big, %d", header->packet_len); + goto error; + } else if (header->hdr_len < MIN_HEADER) { + dev->stats.rx_frame_errors++; + dbg ("header too short, %d", header->hdr_len); + goto error; + } else if (header->hdr_len > MIN_HEADER) { + // out of band data for us? + dbg ("header OOB, %d bytes", + header->hdr_len - MIN_HEADER); + // switch (vendor/product ids) { ... } + } + skb_pull (skb, header->hdr_len); + + trailer = (struct nc_trailer *) + (skb->data + skb->len - sizeof *trailer); + skb_trim (skb, skb->len - sizeof *trailer); + + if ((header->packet_len & 0x01) == 0) { + if (skb->data [header->packet_len] != PAD_BYTE) { + dev->stats.rx_frame_errors++; + dbg ("bad pad"); + goto error; + } + skb_trim (skb, skb->len - 1); + } + if (skb->len != header->packet_len) { + dev->stats.rx_frame_errors++; + dbg ("bad packet len %d (expected %d)", + skb->len, header->packet_len); + goto error; + } + if (header->packet_id != get_unaligned (&trailer->packet_id)) { + dev->stats.rx_fifo_errors++; + dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x", + header->packet_id, trailer->packet_id); + goto error; + } +#if 0 + devdbg (dev, "frame hdr_len, + header->packet_len, header->packet_id); +#endif + } else { + // we trust the network stack to remove + // the extra byte we may have appended + } + + if (skb->len) { + int status; + +// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ? + + skb->dev = &dev->net; + skb->protocol = eth_type_trans (skb, &dev->net); + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + +#ifdef VERBOSE + devdbg (dev, "< rx, len %d, type 0x%x", + skb->len + sizeof (struct ethhdr), skb->protocol); +#endif + memset (skb->cb,0,sizeof(struct skb_data)); + status = netif_rx (skb); + if (status != NET_RX_SUCCESS) + devdbg (dev, "netif_rx status %d", status); + } else { + dbg ("drop"); +error: + dev->stats.rx_errors++; + skb_queue_tail (&dev->done, skb); + } +} + +/*-------------------------------------------------------------------------*/ + +static void rx_complete (struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct skb_data *entry = (struct skb_data *) skb->cb; + struct usbnet *dev = entry->dev; + int urb_status = urb->status; + + skb_put (skb, urb->actual_length); + entry->state = rx_done; + entry->urb = 0; + + switch (urb_status) { + // success + case 0: + if (MIN_PACKET > skb->len || skb->len > MAX_PACKET) { + entry->state = rx_cleanup; + dev->stats.rx_errors++; + dev->stats.rx_length_errors++; + dbg ("rx length %d", skb->len); + } + break; + + // software-driven interface shutdown + case -ECONNRESET: // usb-ohci, usb-uhci + case -ECONNABORTED: // uhci ... for usb-uhci, INTR + dbg ("%s shutdown, code %d", dev->net.name, urb_status); + entry->state = rx_cleanup; + // do urb frees only in the tasklet + entry->urb = urb; + urb = 0; + break; + + // data overrun ... flush fifo? + case -EOVERFLOW: + dev->stats.rx_over_errors++; + // FALLTHROUGH + + default: + // on unplug we'll get a burst of ETIMEDOUT/EILSEQ + // till the khubd gets and handles its interrupt. + entry->state = rx_cleanup; + dev->stats.rx_errors++; + dbg ("%s rx: status %d", dev->net.name, urb_status); + break; + } + + defer_bh (dev, skb); + + if (urb) { + if (netif_running (&dev->net)) { + rx_submit (dev, urb, GFP_ATOMIC); + return; + } + } +#ifdef VERBOSE + dbg ("no read resubmitted"); +#endif /* VERBOSE */ +} + +/*-------------------------------------------------------------------------*/ + +// unlink pending rx/tx; completion handlers do all other cleanup + +static int unlink_urbs (struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb, *skbnext; + int count = 0; + + spin_lock_irqsave (&q->lock, flags); + for (skb = q->next; skb != (struct sk_buff *) q; skb = skbnext) { + struct skb_data *entry; + struct urb *urb; + int retval; + + entry = (struct skb_data *) skb->cb; + urb = entry->urb; + skbnext = skb->next; + + // during some PM-driven resume scenarios, + // these (async) unlinks complete immediately + retval = usb_unlink_urb (urb); + if (retval < 0) + dbg ("unlink urb err, %d", retval); + else + count++; + } + spin_unlock_irqrestore (&q->lock, flags); + return count; +} + + +/*-------------------------------------------------------------------------*/ + +// precondition: never called in_interrupt + +static int usbnet_stop (struct net_device *net) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + int temp; + DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); + DECLARE_WAITQUEUE (wait, current); + + mutex_lock (&dev->mutex); + netif_stop_queue(net); + + devdbg (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", + dev->stats.rx_packets, dev->stats.tx_packets, + dev->stats.rx_errors, dev->stats.tx_errors + ); + + // ensure there are no more active urbs + add_wait_queue (&unlink_wakeup, &wait); + dev->wait = &unlink_wakeup; + temp = unlink_urbs (&dev->txq) + unlink_urbs (&dev->rxq); + + // maybe wait for deletions to finish. + while (skb_queue_len (&dev->rxq) + && skb_queue_len (&dev->txq) + && skb_queue_len (&dev->done)) { + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout (UNLINK_TIMEOUT_JIFFIES); + dbg ("waited for %d urb completions", temp); + } + dev->wait = 0; + remove_wait_queue (&unlink_wakeup, &wait); + + mutex_unlock (&dev->mutex); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +// posts reads, and enables write queing + +// precondition: never called in_interrupt + +static int usbnet_open (struct net_device *net) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + int retval = 0; + struct driver_info *info = dev->driver_info; + + mutex_lock (&dev->mutex); + + // put into "known safe" state + if (info->reset && (retval = info->reset (dev)) < 0) { + devinfo (dev, "open reset fail (%d) usbnet %03d/%03d, %s", + retval, + dev->udev->bus->busnum, dev->udev->devnum, + info->description); + goto done; + } + + // insist peer be connected + if (info->check_connect && (retval = info->check_connect (dev)) < 0) { + devdbg (dev, "can't open; %d", retval); + goto done; + } + + netif_start_queue (net); + devdbg (dev, "open: enable queueing (rx %d, tx %d) mtu %d %sframed", + RX_QLEN, TX_QLEN, dev->net.mtu, + (info->flags & FLAG_FRAMING) ? "" : "un" + ); + + // delay posting reads until we're fully open + tasklet_schedule (&dev->bh); +done: + mutex_unlock (&dev->mutex); + return retval; +} + +/*-------------------------------------------------------------------------*/ + +/* usb_clear_halt cannot be called in interrupt context */ + +static void +tx_clear_halt(void *data) +{ + struct usbnet *dev = data; + + usb_clear_halt (dev->udev, + usb_sndbulkpipe (dev->udev, dev->driver_info->out)); + netif_wake_queue (&dev->net); +} + +/*-------------------------------------------------------------------------*/ + +static void tx_complete (struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct skb_data *entry = (struct skb_data *) skb->cb; + struct usbnet *dev = entry->dev; + + if (urb->status == USB_ST_STALL) { + if (dev->ctrl_task.sync == 0) { + dev->ctrl_task.routine = tx_clear_halt; + dev->ctrl_task.data = dev; + schedule_task(&dev->ctrl_task); + } else { + dbg ("Cannot clear TX stall"); + } + } + urb->dev = 0; + entry->state = tx_done; + defer_bh (dev, skb); +} + +/*-------------------------------------------------------------------------*/ + +static void usbnet_tx_timeout (struct net_device *net) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + + unlink_urbs (&dev->txq); + tasklet_schedule (&dev->bh); + + // FIXME: device recovery -- reset? +} + +/*-------------------------------------------------------------------------*/ + +static inline struct sk_buff *fixup_skb (struct sk_buff *skb, int flags) +{ + int padlen; + struct sk_buff *skb2; + + padlen = ((skb->len + sizeof (struct nc_header) + + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1; + if (!skb_cloned (skb)) { + int headroom = skb_headroom (skb); + int tailroom = skb_tailroom (skb); + + if ((padlen + sizeof (struct nc_trailer)) <= tailroom + && sizeof (struct nc_header) <= headroom) + return skb; + + if ((sizeof (struct nc_header) + padlen + + sizeof (struct nc_trailer)) < + (headroom + tailroom)) { + skb->data = memmove (skb->head + + sizeof (struct nc_header), + skb->data, skb->len); + skb->tail = skb->data + skb->len; + return skb; + } + } + skb2 = skb_copy_expand (skb, + sizeof (struct nc_header), + sizeof (struct nc_trailer) + padlen, + flags); + dev_kfree_skb_any (skb); + return skb2; +} + +/*-------------------------------------------------------------------------*/ + +static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + int length = skb->len; + int retval = NET_XMIT_SUCCESS; + struct urb *urb = 0; + struct skb_data *entry; + struct nc_header *header = 0; + struct nc_trailer *trailer = 0; + struct driver_info *info = dev->driver_info; + int flags; + + flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL; + + if (info->flags & FLAG_FRAMING) { + struct sk_buff *skb2; + skb2 = fixup_skb (skb, flags); + if (!skb2) { + dbg ("can't fixup skb"); + goto drop; + } + skb = skb2; + } + + if (!(urb = usb_alloc_urb (0))) { + dbg ("no urb"); + goto drop; + } + + entry = (struct skb_data *) skb->cb; + entry->urb = urb; + entry->dev = dev; + entry->state = tx_start; + entry->length = length; + + if (info->flags & FLAG_FRAMING) { + header = (struct nc_header *) skb_push (skb, sizeof *header); + header->hdr_len = cpu_to_le16 (sizeof (*header)); + header->packet_len = cpu_to_le16 (length); + if (!((skb->len + sizeof *trailer) & 0x01)) + *skb_put (skb, 1) = PAD_BYTE; + trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer); + } else if ((length % EP_SIZE (dev)) == 0) { + if (skb_shared (skb)) { + struct sk_buff *skb2; + skb2 = skb_unshare (skb, flags); + if (!skb2) { + dbg ("can't unshare skb"); + goto drop; + } + skb = skb2; + } + skb->len++; + } + + FILL_BULK_URB (urb, dev->udev, + usb_sndbulkpipe (dev->udev, info->out), + skb->data, skb->len, tx_complete, skb); + // Idle-but-posted reads with UHCI really chew up + // PCI bandwidth unless FSBR is disabled + urb->transfer_flags |= USB_ASYNC_UNLINK | USB_NO_FSBR; +#ifdef REALLY_QUEUE + urb->transfer_flags |= USB_QUEUE_BULK; +#endif + // FIXME urb->timeout = ... jiffies ... ; + + spin_lock_irqsave (&dev->txq.lock, flags); + if (info->flags & FLAG_FRAMING) { + header->packet_id = cpu_to_le16 (dev->packet_id++); + put_unaligned (header->packet_id, &trailer->packet_id); +#if 0 + devdbg (dev, "frame >tx h %d p %d id %d", + header->hdr_len, header->packet_len, + header->packet_id); +#endif + } + + netif_stop_queue (net); + if ((retval = usb_submit_urb (urb)) != 0) { + netif_start_queue (net); + dbg ("%s tx: submit urb err %d", net->name, retval); + } else { + net->trans_start = jiffies; + __skb_queue_tail (&dev->txq, skb); + if (dev->txq.qlen < TX_QLEN) + netif_start_queue (net); + } + spin_unlock_irqrestore (&dev->txq.lock, flags); + + if (retval) { + devdbg (dev, "drop, code %d", retval); +drop: + retval = NET_XMIT_DROP; + dev->stats.tx_dropped++; + dev_kfree_skb_any (skb); + usb_free_urb (urb); +#ifdef VERBOSE + } else { + devdbg (dev, "> tx, len %d, type 0x%x", + length, skb->protocol); +#endif + } + return retval; +} + + +/*-------------------------------------------------------------------------*/ + +// tasklet ... work that avoided running in_irq() + +static void usbnet_bh (unsigned long param) +{ + struct usbnet *dev = (struct usbnet *) param; + struct sk_buff *skb; + struct skb_data *entry; + + while ((skb = skb_dequeue (&dev->done))) { + entry = (struct skb_data *) skb->cb; + switch (entry->state) { + case rx_done: + entry->state = rx_cleanup; + rx_process (dev, skb); + continue; + case tx_done: + if (entry->urb->status) { + // can this statistic become more specific? + dev->stats.tx_errors++; + dbg ("%s tx: err %d", dev->net.name, + entry->urb->status); + } else { + dev->stats.tx_packets++; + dev->stats.tx_bytes += entry->length; + } + // FALLTHROUGH: + case rx_cleanup: + usb_free_urb (entry->urb); + dev_kfree_skb (skb); + continue; + default: + dbg ("%s: bogus skb state %d", + dev->net.name, entry->state); + } + } + + // waiting for all pending urbs to complete? + if (dev->wait) { + if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { + wake_up (dev->wait); + } + + // or are we maybe short a few urbs? + } else if (netif_running (&dev->net)) { + int temp = dev->rxq.qlen; + + if (temp < RX_QLEN) { + struct urb *urb; + int i; + for (i = 0; i < 3 && dev->rxq.qlen < RX_QLEN; i++) { + if ((urb = usb_alloc_urb (0)) != 0) + rx_submit (dev, urb, GFP_ATOMIC); + } + if (temp != dev->rxq.qlen) + devdbg (dev, "rxqlen %d --> %d", + temp, dev->rxq.qlen); + if (dev->rxq.qlen < RX_QLEN) + tasklet_schedule (&dev->bh); + } + if (dev->txq.qlen < TX_QLEN) + netif_wake_queue (&dev->net); + } +} + + + +/*------------------------------------------------------------------------- + * + * USB Device Driver support + * + *-------------------------------------------------------------------------*/ + +// precondition: never called in_interrupt + +static void usbnet_disconnect (struct usb_device *udev, void *ptr) +{ + struct usbnet *dev = (struct usbnet *) ptr; + + devinfo (dev, "unregister usbnet %03d/%03d, %s", + udev->bus->busnum, udev->devnum, + dev->driver_info->description); + + unregister_netdev (&dev->net); + + mutex_lock (&usbnet_mutex); + mutex_lock (&dev->mutex); + list_del (&dev->dev_list); + mutex_unlock (&usbnet_mutex); + + kfree (dev); + usb_dec_dev_use (udev); +} + + +/*-------------------------------------------------------------------------*/ + +// precondition: never called in_interrupt + +static void * +usbnet_probe (struct usb_device *udev, unsigned ifnum, + const struct usb_device_id *prod) +{ + struct usbnet *dev; + struct net_device *net; + struct usb_interface_descriptor *interface; + struct driver_info *info; + int altnum = 0; + + info = (struct driver_info *) prod->driver_info; + + // sanity check; expect dedicated interface/devices for now. + interface = &udev->actconfig->interface [ifnum].altsetting [altnum]; + if (udev->descriptor.bNumConfigurations != 1 + || udev->config[0].bNumInterfaces != 1 +// || interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC + ) { + dbg ("Bogus config info"); + return 0; + } + + if (usb_set_interface (udev, ifnum, altnum) < 0) { + err ("set_interface failed"); + return 0; + } + + // set up our own records + if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) { + dbg ("can't kmalloc dev"); + return 0; + } + memset (dev, 0, sizeof *dev); + + init_MUTEX_LOCKED (&dev->mutex); + usb_inc_dev_use (udev); + dev->udev = udev; + dev->driver_info = info; + INIT_LIST_HEAD (&dev->dev_list); + skb_queue_head_init (&dev->rxq); + skb_queue_head_init (&dev->txq); + skb_queue_head_init (&dev->done); + dev->bh.func = usbnet_bh; + dev->bh.data = (unsigned long) dev; + + // set up network interface records + net = &dev->net; + SET_MODULE_OWNER (net); + net->priv = dev; + strcpy (net->name, "usb%d"); + memcpy (net->dev_addr, node_id, sizeof node_id); + + // point-to-point link ... we always use Ethernet headers + // supports win32 interop and the bridge driver. + ether_setup (net); + + net->change_mtu = usbnet_change_mtu; + net->get_stats = usbnet_get_stats; + net->hard_start_xmit = usbnet_start_xmit; + net->open = usbnet_open; + net->stop = usbnet_stop; + net->watchdog_timeo = TX_TIMEOUT_JIFFIES; + net->tx_timeout = usbnet_tx_timeout; + + register_netdev (&dev->net); + devinfo (dev, "register usbnet %03d/%03d, %s", + udev->bus->busnum, udev->devnum, + dev->driver_info->description); + + // ok, it's ready to go. + mutex_lock (&usbnet_mutex); + list_add (&dev->dev_list, &usbnet_list); + mutex_unlock (&dev->mutex); + + // start as if the link is up + netif_device_attach (&dev->net); + + mutex_unlock (&usbnet_mutex); + return dev; +} + + +/*-------------------------------------------------------------------------*/ + +/* + * chip vendor names won't normally be on the cables, and + * may not be on the device. + */ + +static const struct usb_device_id products [] = { + +#ifdef CONFIG_USB_AN2720 +{ + USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults + driver_info: (unsigned long) &an2720_info, +}, +#endif + + +// GeneSys GL620USB (www.genesyslogic.com.tw) +// (patch exists against an older driver version) + + +#ifdef CONFIG_USB_LINUXDEV +/* + * for example, this can be a host side talk-to-PDA driver. + * this driver is NOT what runs _inside_ a Linux device !! + */ +{ + // 1183 = 0x049F, both used as hex values? + USB_DEVICE (0x049F, 0x505A), // Compaq "Itsy" + driver_info: (unsigned long) &linuxdev_info, +}, +#endif + +#ifdef CONFIG_USB_NET1080 +{ + USB_DEVICE (0x0525, 0x1080), // NetChip ref design + driver_info: (unsigned long) &net1080_info, +}, +#endif + +#ifdef CONFIG_USB_BELKIN_F5U104 +{ + USB_DEVICE (0x050d, 0x0004), // Belkin + driver_info: (unsigned long) &belkin_info, +}, { + USB_DEVICE (0x056c, 0x8100), // eTEK + driver_info: (unsigned long) &belkin_info, +}, +#endif + +#ifdef CONFIG_USB_PL2301 +{ + USB_DEVICE (0x067b, 0x0000), // PL-2301 + driver_info: (unsigned long) &prolific_info, +}, { + USB_DEVICE (0x067b, 0x0001), // PL-2302 + driver_info: (unsigned long) &prolific_info, +}, +#endif + + { }, // END +}; +MODULE_DEVICE_TABLE (usb, products); + +static struct usb_driver usbnet_driver = { + name: "usbnet", + id_table: products, + probe: usbnet_probe, + disconnect: usbnet_disconnect, +}; + +/*-------------------------------------------------------------------------*/ + +static int __init usbnet_init (void) +{ + // compiler should optimize this out + if (sizeof (((struct sk_buff *)0)->cb) < sizeof (struct skb_data)) + BUG (); + + get_random_bytes (node_id, sizeof node_id); + node_id [0] &= 0xfe; // clear multicast bit + + if (usb_register (&usbnet_driver) < 0) + return -1; + + return 0; +} +module_init (usbnet_init); + +static void __exit usbnet_exit (void) +{ + usb_deregister (&usbnet_driver); +} +module_exit (usbnet_exit); + +MODULE_AUTHOR ("David Brownell "); +MODULE_DESCRIPTION ("USB Host-to-Host Link Drivers (Belkin, Linux, NetChip, Prolific, ...)"); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usbvideo.c linux/drivers/usb/usbvideo.c --- v2.4.9/linux/drivers/usb/usbvideo.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/usbvideo.c Fri Sep 7 09:28:37 2001 @@ -0,0 +1,2474 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#define __NO_VERSION__ /* Temporary: usbvideo is not a module yet */ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "usbvideo.h" + +#if defined(MAP_NR) +#define virt_to_page(v) MAP_NR(v) /* Kernels 2.2.x */ +#endif + +static int video_nr = -1; +MODULE_PARM(video_nr, "i"); + +/* + * Local prototypes. + */ +#if USES_PROC_FS +static void usbvideo_procfs_level1_create(usbvideo_t *ut); +static void usbvideo_procfs_level1_destroy(usbvideo_t *ut); +static void usbvideo_procfs_level2_create(uvd_t *uvd); +static void usbvideo_procfs_level2_destroy(uvd_t *uvd); +static int usbvideo_default_procfs_read_proc( + char *page, char **start, off_t off, int count, + int *eof, void *data); +static int usbvideo_default_procfs_write_proc( + struct file *file, const char *buffer, + unsigned long count, void *data); +#endif + +/*******************************/ +/* Memory management functions */ +/*******************************/ + +#define MDEBUG(x) do { } while(0) /* Debug memory management */ + +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +unsigned long usbvideo_uvirt_to_kva(pgd_t *pgd, unsigned long adr) +{ + unsigned long ret = 0UL; + pmd_t *pmd; + pte_t *ptep, pte; + + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, adr); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, adr); + pte = *ptep; + if (pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE-1)); + } + } + } + MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); + return ret; +} + +unsigned long usbvideo_uvirt_to_bus(unsigned long adr) +{ + unsigned long kva, ret; + + kva = usbvideo_uvirt_to_kva(pgd_offset(current->mm, adr), adr); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +unsigned long usbvideo_kvirt_to_bus(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = usbvideo_uvirt_to_kva(pgd_offset_k(va), va); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +/* + * Here we want the physical address of the memory. + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +unsigned long usbvideo_kvirt_to_pa(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = usbvideo_uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); + return ret; +} + +void *usbvideo_rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr, page; + + /* Round it off to PAGE_SIZE */ + size += (PAGE_SIZE - 1); + size &= ~(PAGE_SIZE - 1); + + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + page = usbvideo_kvirt_to_pa(adr); + mem_map_reserve(virt_to_page(__va(page))); + adr += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return mem; +} + +void usbvideo_rvfree(void *mem, unsigned long size) +{ + unsigned long adr, page; + + if (!mem) + return; + + size += (PAGE_SIZE - 1); + size &= ~(PAGE_SIZE - 1); + + adr=(unsigned long) mem; + while (size > 0) { + page = usbvideo_kvirt_to_pa(adr); + mem_map_unreserve(virt_to_page(__va(page))); + adr += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + vfree(mem); +} + +void RingQueue_Initialize(RingQueue_t *rq) +{ + assert(rq != NULL); + init_waitqueue_head(&rq->wqh); +} + +void RingQueue_Allocate(RingQueue_t *rq, int rqLen) +{ + assert(rq != NULL); + assert(rqLen > 0); + rq->length = rqLen; + rq->queue = usbvideo_rvmalloc(rq->length); + assert(rq->queue != NULL); +} + +int RingQueue_IsAllocated(const RingQueue_t *rq) +{ + if (rq == NULL) + return 0; + return (rq->queue != NULL) && (rq->length > 0); +} + +void RingQueue_Free(RingQueue_t *rq) +{ + assert(rq != NULL); + if (RingQueue_IsAllocated(rq)) { + usbvideo_rvfree(rq->queue, rq->length); + rq->queue = NULL; + rq->length = 0; + } +} + +int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len) +{ + int i; + assert(rq != NULL); + assert(dst != NULL); + for (i=0; i < len; i++) { + dst[i] = rq->queue[rq->ri]; + RING_QUEUE_DEQUEUE_BYTES(rq,1); + } + return len; +} + +int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n) +{ + int enqueued = 0; + + assert(rq != NULL); + assert(cdata != NULL); + assert(rq->length > 0); + while (n > 0) { + int m, q_avail; + + /* Calculate the largest chunk that fits the tail of the ring */ + q_avail = rq->length - rq->wi; + if (q_avail <= 0) { + rq->wi = 0; + q_avail = rq->length; + } + m = n; + assert(q_avail > 0); + if (m > q_avail) + m = q_avail; + + memmove(rq->queue + rq->wi, cdata, m); + RING_QUEUE_ADVANCE_INDEX(rq, wi, m); + cdata += m; + enqueued += m; + n -= m; + } + return enqueued; +} + +int RingQueue_GetLength(const RingQueue_t *rq) +{ + int ri, wi; + + assert(rq != NULL); + + ri = rq->ri; + wi = rq->wi; + if (ri == wi) + return 0; + else if (ri < wi) + return wi - ri; + else + return wi + (rq->length - ri); +} + +void RingQueue_InterruptibleSleepOn(RingQueue_t *rq) +{ + assert(rq != NULL); + interruptible_sleep_on(&rq->wqh); +} + +void RingQueue_WakeUpInterruptible(RingQueue_t *rq) +{ + assert(rq != NULL); + if (waitqueue_active(&rq->wqh)) + wake_up_interruptible(&rq->wqh); +} + +/* + * usbvideo_VideosizeToString() + * + * This procedure converts given videosize value to readable string. + * + * History: + * 07-Aug-2000 Created. + * 19-Oct-2000 Reworked for usbvideo module. + */ +void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) +{ + char tmp[40]; + int n; + + n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs)); + assert(n < sizeof(tmp)); + if ((buf == NULL) || (bufLen < n)) + err("usbvideo_VideosizeToString: buffer is too small."); + else + memmove(buf, tmp, n); +} + +/* + * usbvideo_OverlayChar() + * + * History: + * 01-Feb-2000 Created. + */ +void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, + int x, int y, int ch) +{ + static const unsigned short digits[16] = { + 0xF6DE, /* 0 */ + 0x2492, /* 1 */ + 0xE7CE, /* 2 */ + 0xE79E, /* 3 */ + 0xB792, /* 4 */ + 0xF39E, /* 5 */ + 0xF3DE, /* 6 */ + 0xF492, /* 7 */ + 0xF7DE, /* 8 */ + 0xF79E, /* 9 */ + 0x77DA, /* a */ + 0xD75C, /* b */ + 0xF24E, /* c */ + 0xD6DC, /* d */ + 0xF34E, /* e */ + 0xF348 /* f */ + }; + unsigned short digit; + int ix, iy; + + if ((uvd == NULL) || (frame == NULL)) + return; + + if (ch >= '0' && ch <= '9') + ch -= '0'; + else if (ch >= 'A' && ch <= 'F') + ch = 10 + (ch - 'A'); + else if (ch >= 'a' && ch <= 'f') + ch = 10 + (ch - 'a'); + else + return; + digit = digits[ch]; + + for (iy=0; iy < 5; iy++) { + for (ix=0; ix < 3; ix++) { + if (digit & 0x8000) { + if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) { +/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF); + } + } + digit = digit << 1; + } + } +} + +/* + * usbvideo_OverlayString() + * + * History: + * 01-Feb-2000 Created. + */ +void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, + int x, int y, const char *str) +{ + while (*str) { + usbvideo_OverlayChar(uvd, frame, x, y, *str); + str++; + x += 4; /* 3 pixels character + 1 space */ + } +} + +/* + * usbvideo_OverlayStats() + * + * Overlays important debugging information. + * + * History: + * 01-Feb-2000 Created. + */ +void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame) +{ + const int y_diff = 8; + char tmp[16]; + int x = 10, y=10; + long i, j, barLength; + const int qi_x1 = 60, qi_y1 = 10; + const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10; + + /* Call the user callback, see if we may proceed after that */ + if (VALID_CALLBACK(uvd, overlayHook)) { + if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0) + return; + } + + /* + * We draw a (mostly) hollow rectangle with qi_xxx coordinates. + * Left edge symbolizes the queue index 0; right edge symbolizes + * the full capacity of the queue. + */ + barLength = qi_x2 - qi_x1 - 2; + if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) { +/* TODO */ long u_lo, u_hi, q_used; + long m_ri, m_wi, m_lo, m_hi; + + /* + * Determine fill zones (used areas of the queue): + * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length + * + * if u_lo < 0 then there is no first filler. + */ + + q_used = RingQueue_GetLength(&uvd->dp); + if ((uvd->dp.ri + q_used) >= uvd->dp.length) { + u_hi = uvd->dp.length; + u_lo = (q_used + uvd->dp.ri) % uvd->dp.length; + } else { + u_hi = (q_used + uvd->dp.ri); + u_lo = -1; + } + + /* Convert byte indices into screen units */ + m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length); + m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length); + m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1; + m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length); + + for (j=qi_y1; j < (qi_y1 + qi_h); j++) { + for (i=qi_x1; i < qi_x2; i++) { + /* Draw border lines */ + if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) || + (i == qi_x1) || (i == (qi_x2 - 1))) { + RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF); + continue; + } + /* For all other points the Y coordinate does not matter */ + if ((i >= m_ri) && (i <= (m_ri + 3))) { + RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00); + } else if ((i >= m_wi) && (i <= (m_wi + 3))) { + RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00); + } else if ((i < m_lo) || ((i > m_ri) && (i < m_hi))) + RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF); + } + } + } + + sprintf(tmp, "%8lx", uvd->stats.frame_num); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.urb_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.urb_length); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.data_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.header_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.iso_skip_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.iso_err_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.colour); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.hue); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.brightness >> 8); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.contrast >> 12); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; +} + +/* + * usbvideo_ReportStatistics() + * + * This procedure prints packet and transfer statistics. + * + * History: + * 14-Jan-2000 Corrected default multiplier. + */ +void usbvideo_ReportStatistics(const uvd_t *uvd) +{ + if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { + unsigned long allPackets, badPackets, goodPackets, percent; + allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES; + badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count; + goodPackets = allPackets - badPackets; + /* Calculate percentage wisely, remember integer limits */ + assert(allPackets != 0); + if (goodPackets < (((unsigned long)-1)/100)) + percent = (100 * goodPackets) / allPackets; + else + percent = goodPackets / (allPackets / 100); + info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%", + allPackets, badPackets, percent); + if (uvd->iso_packet_len > 0) { + unsigned long allBytes, xferBytes; + char multiplier = ' '; + allBytes = allPackets * uvd->iso_packet_len; + xferBytes = uvd->stats.data_count; + assert(allBytes != 0); + if (xferBytes < (((unsigned long)-1)/100)) + percent = (100 * xferBytes) / allBytes; + else + percent = xferBytes / (allBytes / 100); + /* Scale xferBytes for easy reading */ + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'K'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'M'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'G'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'T'; + } + } + } + } + info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%", + xferBytes, multiplier, percent); + } + } +} + +/* + * usbvideo_DrawLine() + * + * A standard implementation of Bresenham's line drawing algorithm. + * This procedure is provided primarily for debugging or demo + * purposes. + */ +void usbvideo_DrawLine( + usbvideo_frame_t *frame, + int x1, int y1, + int x2, int y2, + unsigned char cr, unsigned char cg, unsigned char cb) +{ + int i, dx, dy, np, d; + int dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2; + + if ((dx = x2 - x1) < 0) + dx = -dx; + if ((dy = y2 - y1) < 0) + dy = -dy; + if (dx >= dy) { + np = dx + 1; + d = (2 * dy) - dx; + dinc1 = dy << 1; + dinc2 = (dy - dx) << 1; + xinc1 = 1; + xinc2 = 1; + yinc1 = 0; + yinc2 = 1; + } else { + np = dy + 1; + d = (2 * dx) - dy; + dinc1 = dx << 1; + dinc2 = (dx - dy) << 1; + xinc1 = 0; + xinc2 = 1; + yinc1 = 1; + yinc2 = 1; + } + /* Make sure x and y move in the right directions */ + if (x1 > x2) { + xinc1 = -xinc1; + xinc2 = -xinc2; + } + if (y1 > y2) { + yinc1 = -yinc1; + yinc2 = -yinc2; + } + for (i=0, x=x1, y=y1; i < np; i++) { + if (frame->palette == VIDEO_PALETTE_RGB24) { +/* TODO */ RGB24_PUTPIXEL(frame, x, y, cr, cg, cb); + } + if (d < 0) { + d += dinc1; + x += xinc1; + y += yinc1; + } else { + d += dinc2; + x += xinc2; + y += yinc2; + } + } +} + +/* + * usbvideo_TestPattern() + * + * Procedure forms a test pattern (yellow grid on blue background). + * + * Parameters: + * fullframe: if TRUE then entire frame is filled, otherwise the procedure + * continues from the current scanline. + * pmode 0: fill the frame with solid blue color (like on VCR or TV) + * 1: Draw a colored grid + * + * History: + * 01-Feb-2000 Created. + */ +void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode) +{ + static const char proc[] = "usbvideo_TestPattern"; + usbvideo_frame_t *frame; + int num_cell = 0; + int scan_length = 0; + static int num_pass = 0; + + if (uvd == NULL) { + err("%s: uvd == NULL", proc); + return; + } + if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { + err("%s: uvd->curframe=%d.", proc, uvd->curframe); + return; + } + + /* Grab the current frame */ + frame = &uvd->frame[uvd->curframe]; + + /* Optionally start at the beginning */ + if (fullframe) { + frame->curline = 0; + frame->seqRead_Length = 0; + } +#if 0 + { /* For debugging purposes only */ + char tmp[20]; + usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); + info("testpattern: frame=%s", tmp); + } +#endif + /* Form every scan line */ + for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) { + int i; + unsigned char *f = frame->data + + (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline); + for (i=0; i < VIDEOSIZE_X(frame->request); i++) { + unsigned char cb=0x80; + unsigned char cg = 0; + unsigned char cr = 0; + + if (pmode == 1) { + if (frame->curline % 32 == 0) + cb = 0, cg = cr = 0xFF; + else if (i % 32 == 0) { + if (frame->curline % 32 == 1) + num_cell++; + cb = 0, cg = cr = 0xFF; + } else { + cb = ((num_cell*7) + num_pass) & 0xFF; + cg = ((num_cell*5) + num_pass*2) & 0xFF; + cr = ((num_cell*3) + num_pass*3) & 0xFF; + } + } else { + /* Just the blue screen */ + } + + *f++ = cb; + *f++ = cg; + *f++ = cr; + scan_length += 3; + } + } + + frame->frameState = FrameState_Done; + frame->seqRead_Length += scan_length; + ++num_pass; + + /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ + usbvideo_OverlayStats(uvd, frame); +} + +/* + * usbvideo_HexDump() + * + * A debugging tool. Prints hex dumps. + * + * History: + * 29-Jul-2000 Added printing of offsets. + */ +void usbvideo_HexDump(const unsigned char *data, int len) +{ + const int bytes_per_line = 32; + char tmp[128]; /* 32*3 + 5 */ + int i, k; + + for (i=k=0; len > 0; i++, len--) { + if (i > 0 && ((i % bytes_per_line) == 0)) { + printk("%s\n", tmp); + k=0; + } + if ((i % bytes_per_line) == 0) + k += sprintf(&tmp[k], "%04x: ", i); + k += sprintf(&tmp[k], "%02x ", data[i]); + } + if (k > 0) + printk("%s\n", tmp); +} + +/* Debugging aid */ +void usbvideo_SayAndWait(const char *what) +{ + wait_queue_head_t wq; + init_waitqueue_head(&wq); + info("Say: %s", what); + interruptible_sleep_on_timeout (&wq, HZ*3); /* Timeout */ +} + +/* ******************************************************************** */ + +static void usbvideo_ClientIncModCount(uvd_t *uvd) +{ + static const char proc[] = "usbvideo_ClientIncModCount"; + if (uvd == NULL) { + err("%s: uvd == NULL", proc); + return; + } + if (uvd->handle == NULL) { + err("%s: uvd->handle == NULL", proc); + return; + } + if (uvd->handle->md_module == NULL) { + err("%s: uvd->handle->md_module == NULL", proc); + return; + } + __MOD_INC_USE_COUNT(uvd->handle->md_module); +} + +static void usbvideo_ClientDecModCount(uvd_t *uvd) +{ + static const char proc[] = "usbvideo_ClientDecModCount"; + if (uvd == NULL) { + err("%s: uvd == NULL", proc); + return; + } + if (uvd->handle == NULL) { + err("%s: uvd->handle == NULL", proc); + return; + } + if (uvd->handle->md_module == NULL) { + err("%s: uvd->handle->md_module == NULL", proc); + return; + } + __MOD_DEC_USE_COUNT(uvd->handle->md_module); +} + +int usbvideo_register( + usbvideo_t **pCams, + const int num_cams, + const int num_extra, + const char *driverName, + const usbvideo_cb_t *cbTbl, + struct module *md ) +{ + static const char proc[] = "usbvideo_register"; + usbvideo_t *cams; + int i, base_size; + + /* Check parameters for sanity */ + if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { + err("%s: Illegal call", proc); + return -EINVAL; + } + + /* Check registration callback - must be set! */ + if (cbTbl->probe == NULL) { + err("%s: probe() is required!", proc); + return -EINVAL; + } + + base_size = num_cams * sizeof(uvd_t) + sizeof(usbvideo_t); + cams = (usbvideo_t *) kmalloc(base_size, GFP_KERNEL); + if (cams == NULL) { + err("Failed to allocate %d. bytes for usbvideo_t", base_size); + return -ENOMEM; + } + dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", + proc, cams, base_size, num_cams); + memset(cams, 0, base_size); + + /* Copy callbacks, apply defaults for those that are not set */ + memmove(&cams->cb, cbTbl, sizeof(cams->cb)); + if (cams->cb.getFrame == NULL) + cams->cb.getFrame = usbvideo_GetFrame; + if (cams->cb.disconnect == NULL) + cams->cb.disconnect = usbvideo_Disconnect; +#if USES_PROC_FS + /* + * If both /proc fs callbacks are NULL then we assume that the driver + * does not need procfs services at all. Leave them NULL. + */ + cams->uses_procfs = (cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL); + if (cams->uses_procfs) { + if (cams->cb.procfs_read == NULL) + cams->cb.procfs_read = usbvideo_default_procfs_read_proc; + if (cams->cb.procfs_write == NULL) + cams->cb.procfs_write = usbvideo_default_procfs_write_proc; + } +#else /* !USES_PROC_FS */ + /* Report a warning so that user knows why there is no /proc entries */ + if ((cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL)) { + dbg("%s: /proc fs support requested but not configured!", proc); + } +#endif + cams->num_cameras = num_cams; + cams->cam = (uvd_t *) &cams[1]; + cams->md_module = md; + if (cams->md_module == NULL) + warn("%s: module == NULL!", proc); + init_MUTEX(&cams->lock); /* to 1 == available */ + + for (i = 0; i < num_cams; i++) { + uvd_t *up = &cams->cam[i]; + + up->handle = cams; + + /* Allocate user_data separately because of kmalloc's limits */ + if (num_extra > 0) { + up->user_size = num_cams * num_extra; + up->user_data = (char *) kmalloc(up->user_size, GFP_KERNEL); + if (up->user_data == NULL) { + up->user_size = 0; + err("%s: Failed to allocate user_data (%d. bytes)", + proc, up->user_size); + return -ENOMEM; + } + dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", + proc, i, up->user_data, up->user_size); + } + } + + /* + * Register ourselves with USB stack. + */ + strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown"); + cams->usbdrv.name = cams->drvName; + cams->usbdrv.probe = cams->cb.probe; + cams->usbdrv.disconnect = cams->cb.disconnect; + +#if USES_PROC_FS + if (cams->uses_procfs) { + dbg("%s: Creating /proc filesystem entries.", proc); + usbvideo_procfs_level1_create(cams); + } +#endif + + /* + * Update global handle to usbvideo. This is very important + * because probe() can be called before usb_register() returns. + * If the handle is not yet updated then the probe() will fail. + */ + *pCams = cams; + usb_register(&cams->usbdrv); + + return 0; +} + +/* + * usbvideo_Deregister() + * + * Procedure frees all usbvideo and user data structures. Be warned that + * if you had some dynamically allocated components in ->user field then + * you should free them before calling here. + */ +void usbvideo_Deregister(usbvideo_t **pCams) +{ + static const char proc[] = "usbvideo_deregister"; + usbvideo_t *cams; + int i; + + if (pCams == NULL) { + err("%s: pCams == NULL", proc); + return; + } + cams = *pCams; + if (cams == NULL) { + err("%s: cams == NULL", proc); + return; + } + +#if USES_PROC_FS + if (cams->uses_procfs) { + dbg("%s: Deregistering filesystem entries.", proc); + usbvideo_procfs_level1_destroy(cams); + } +#endif + + dbg("%s: Deregistering %s driver.", proc, cams->drvName); + usb_deregister(&cams->usbdrv); + + dbg("%s: Deallocating cams=$%p (%d. cameras)", proc, cams, cams->num_cameras); + for (i=0; i < cams->num_cameras; i++) { + uvd_t *up = &cams->cam[i]; + int warning = 0; + + if (up->user_data != NULL) { + if (up->user_size <= 0) + ++warning; + } else { + if (up->user_size > 0) + ++warning; + } + if (warning) { + err("%s: Warning: user_data=$%p user_size=%d.", + proc, up->user_data, up->user_size); + } else { + dbg("%s: Freeing %d. $%p->user_data=$%p", + proc, i, up, up->user_data); + kfree(up->user_data); + } + } + /* Whole array was allocated in one chunk */ + dbg("%s: Freed %d uvd_t structures", + proc, cams->num_cameras); + kfree(cams); + *pCams = NULL; +} + +/* + * usbvideo_Disconnect() + * + * This procedure stops all driver activity. Deallocation of + * the interface-private structure (pointed by 'ptr') is done now + * (if we don't have any open files) or later, when those files + * are closed. After that driver should be removable. + * + * This code handles surprise removal. The uvd->user is a counter which + * increments on open() and decrements on close(). If we see here that + * this counter is not 0 then we have a client who still has us opened. + * We set uvd->remove_pending flag as early as possible, and after that + * all access to the camera will gracefully fail. These failures should + * prompt client to (eventually) close the video device, and then - in + * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter. + * + * History: + * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone. + * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close() + * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). + * 19-Oct-2000 Moved to usbvideo module. + */ +void usbvideo_Disconnect(struct usb_device *dev, void *ptr) +{ + static const char proc[] = "usbvideo_Disconnect"; + uvd_t *uvd = (uvd_t *) ptr; + int i; + + if ((dev == NULL) || (uvd == NULL)) { + err("%s($%p,$%p): Illegal call.", proc, dev, ptr); + return; + } + usbvideo_ClientIncModCount(uvd); + if (uvd->debug > 0) + info("%s(%p,%p.)", proc, dev, ptr); + + down(&uvd->lock); + uvd->remove_pending = 1; /* Now all ISO data will be ignored */ + + /* At this time we ask to cancel outstanding URBs */ + usbvideo_StopDataPump(uvd); + + for (i=0; i < USBVIDEO_NUMSBUF; i++) + usb_free_urb(uvd->sbuf[i].urb); + + usb_dec_dev_use(uvd->dev); + uvd->dev = NULL; /* USB device is no more */ + + if (uvd->user) + info("%s: In use, disconnect pending.", proc); + else + usbvideo_CameraRelease(uvd); + up(&uvd->lock); + info("USB camera disconnected."); + + usbvideo_ClientDecModCount(uvd); +} + +/* + * usbvideo_CameraRelease() + * + * This code does final release of uvd_t. This happens + * after the device is disconnected -and- all clients + * closed their files. + * + * History: + * 27-Jan-2000 Created. + */ +void usbvideo_CameraRelease(uvd_t *uvd) +{ + static const char proc[] = "usbvideo_CameraRelease"; + if (uvd == NULL) { + err("%s: Illegal call", proc); + return; + } + video_unregister_device(&uvd->vdev); + if (uvd->debug > 0) + info("%s: Video unregistered.", proc); + +#if USES_PROC_FS + assert(uvd->handle != NULL); + if (uvd->handle->uses_procfs) { + dbg("%s: Removing /proc/%s/ filesystem entries.", proc, uvd->handle->drvName); + usbvideo_procfs_level2_destroy(uvd); + } +#endif + + RingQueue_Free(&uvd->dp); + if (VALID_CALLBACK(uvd, userFree)) + GET_CALLBACK(uvd, userFree)(uvd); + uvd->uvd_used = 0; /* This is atomic, no need to take mutex */ +} + +/* + * usbvideo_find_struct() + * + * This code searches the array of preallocated (static) structures + * and returns index of the first one that isn't in use. Returns -1 + * if there are no free structures. + * + * History: + * 27-Jan-2000 Created. + */ +static int usbvideo_find_struct(usbvideo_t *cams) +{ + int u, rv = -1; + + if (cams == NULL) { + err("No usbvideo_t handle?"); + return -1; + } + down(&cams->lock); + for (u = 0; u < cams->num_cameras; u++) { + uvd_t *uvd = &cams->cam[u]; + if (!uvd->uvd_used) /* This one is free */ + { + uvd->uvd_used = 1; /* In use now */ + init_MUTEX(&uvd->lock); /* to 1 == available */ + uvd->dev = NULL; + rv = u; + break; + } + } + up(&cams->lock); + return rv; +} + +uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams) +{ + int i, devnum; + uvd_t *uvd = NULL; + + if (cams == NULL) { + err("No usbvideo_t handle?"); + return NULL; + } + + devnum = usbvideo_find_struct(cams); + if (devnum == -1) { + err("IBM USB camera driver: Too many devices!"); + return NULL; + } + uvd = &cams->cam[devnum]; + dbg("Device entry #%d. at $%p", devnum, uvd); + + /* Not relying upon caller we increase module counter ourselves */ + usbvideo_ClientIncModCount(uvd); + + down(&uvd->lock); + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC); + if (uvd->sbuf[i].urb == NULL) { + err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC); + uvd->uvd_used = 0; + uvd = NULL; + goto allocate_done; + } + } + uvd->user=0; + uvd->remove_pending = 0; + uvd->last_error = 0; + RingQueue_Initialize(&uvd->dp); + + /* Initialize video device structure */ + memset(&uvd->vdev, 0, sizeof(uvd->vdev)); + i = sprintf(uvd->vdev.name, "%s USB Camera", cams->drvName); + if (i >= sizeof(uvd->vdev.name)) { + err("Wrote too much into uvd->vdev.name, expect trouble!"); + } + uvd->vdev.type = VID_TYPE_CAPTURE; + uvd->vdev.hardware = VID_HARDWARE_CPIA; + uvd->vdev.open = usbvideo_v4l_open; + uvd->vdev.close = usbvideo_v4l_close; + uvd->vdev.read = usbvideo_v4l_read; + uvd->vdev.write = usbvideo_v4l_write; + uvd->vdev.ioctl = usbvideo_v4l_ioctl; + uvd->vdev.mmap = usbvideo_v4l_mmap; + uvd->vdev.initialize = usbvideo_v4l_initialize; + /* + * The client is free to overwrite those because we + * return control to the client's probe function right now. + */ +allocate_done: + up (&uvd->lock); + usbvideo_ClientDecModCount(uvd); + return uvd; +} + +int usbvideo_RegisterVideoDevice(uvd_t *uvd) +{ + static const char proc[] = "usbvideo_RegisterVideoDevice"; + char tmp1[20], tmp2[20]; /* Buffers for printing */ + + if (uvd == NULL) { + err("%s: Illegal call.", proc); + return -EINVAL; + } + if (uvd->video_endp == 0) { + info("%s: No video endpoint specified; data pump disabled.", proc); + } + if (uvd->paletteBits == 0) { + err("%s: No palettes specified!", proc); + return -EINVAL; + } + if (uvd->defaultPalette == 0) { + info("%s: No default palette!", proc); + } + + uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * + VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL; + usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize); + usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); + + if (uvd->debug > 0) { + info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", + proc, uvd->iface, uvd->video_endp, uvd->paletteBits); + } + if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + err("%s: video_register_device failed", proc); + return -EPIPE; + } + if (uvd->debug > 1) { + info("%s: video_register_device() successful", proc); + } + if (uvd->dev == NULL) { + err("%s: uvd->dev == NULL", proc); + return -EINVAL; + } + + info("%s on /dev/video%d: canvas=%s videosize=%s", + (uvd->handle != NULL) ? uvd->handle->drvName : "???", + uvd->vdev.minor, tmp2, tmp1); + +#if USES_PROC_FS + assert(uvd->handle != NULL); + if (uvd->handle->uses_procfs) { + if (uvd->debug > 0) { + info("%s: Creating /proc/%s/ filesystem entries.", + proc, uvd->handle->drvName); + } + usbvideo_procfs_level2_create(uvd); + } +#endif + + usb_inc_dev_use(uvd->dev); + return 0; +} + +/* ******************************************************************** */ + +int usbvideo_v4l_initialize(struct video_device *dev) +{ + return 0; +} + +long usbvideo_v4l_write(struct video_device *dev, const char *buf, + unsigned long count, int noblock) +{ + return -EINVAL; +} + +int usbvideo_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size) +{ + uvd_t *uvd = (uvd_t *) dev; + unsigned long start = (unsigned long) adr; + unsigned long page, pos; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return -EFAULT; + + if (size > (((2 * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) + return -EINVAL; + + pos = (unsigned long) uvd->fbuf; + while (size > 0) { + page = usbvideo_kvirt_to_pa(pos); + if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return 0; +} + +/* + * usbvideo_v4l_open() + * + * This is part of Video 4 Linux API. The driver can be opened by one + * client only (checks internal counter 'uvdser'). The procedure + * then allocates buffers needed for video processing. + * + * History: + * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the + * camera is also initialized here (once per connect), at + * expense of V4L client (it waits on open() call). + * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. + * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). + */ +int usbvideo_v4l_open(struct video_device *dev, int flags) +{ + static const char proc[] = "usbvideo_v4l_open"; + uvd_t *uvd = (uvd_t *) dev; + const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len; + int i, errCode = 0; + + if (uvd->debug > 1) + info("%s($%p,$%08x", proc, dev, flags); + + usbvideo_ClientIncModCount(uvd); + down(&uvd->lock); + + if (uvd->user) { + err("%s: Someone tried to open an already opened device!", proc); + errCode = -EBUSY; + } else { + /* Clear statistics */ + memset(&uvd->stats, 0, sizeof(uvd->stats)); + + /* Clean pointers so we know if we allocated something */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) + uvd->sbuf[i].data = NULL; + + /* Allocate memory for the frame buffers */ + uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; + uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size); + RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */ + if ((uvd->fbuf == NULL) || + (!RingQueue_IsAllocated(&uvd->dp))) { + err("%s: Failed to allocate fbuf or dp", proc); + errCode = -ENOMEM; + } else { + /* Allocate all buffers */ + for (i=0; i < USBVIDEO_NUMFRAMES; i++) { + uvd->frame[i].frameState = FrameState_Unused; + uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size); + /* + * Set default sizes in case IOCTL (VIDIOCMCAPTURE) + * is not used (using read() instead). + */ + uvd->frame[i].canvas = uvd->canvas; + uvd->frame[i].seqRead_Index = 0; + } + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL); + if (uvd->sbuf[i].data == NULL) { + errCode = -ENOMEM; + break; + } + } + } + if (errCode != 0) { + /* Have to free all that memory */ + if (uvd->fbuf != NULL) { + usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); + uvd->fbuf = NULL; + } + RingQueue_Free(&uvd->dp); + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + if (uvd->sbuf[i].data != NULL) { + kfree (uvd->sbuf[i].data); + uvd->sbuf[i].data = NULL; + } + } + } + } + + /* If so far no errors then we shall start the camera */ + if (errCode == 0) { + /* Start data pump if we have valid endpoint */ + if (uvd->video_endp != 0) + errCode = usbvideo_StartDataPump(uvd); + if (errCode == 0) { + if (VALID_CALLBACK(uvd, setupOnOpen)) { + if (uvd->debug > 1) + info("%s: setupOnOpen callback", proc); + errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); + if (errCode < 0) { + err("%s: setupOnOpen callback failed (%d.).", + proc, errCode); + } else if (uvd->debug > 1) { + info("%s: setupOnOpen callback successful", proc); + } + } + if (errCode == 0) { + uvd->settingsAdjusted = 0; + if (uvd->debug > 1) + info("%s: Open succeeded.", proc); + uvd->user++; + } + } + } + up(&uvd->lock); + if (errCode != 0) + usbvideo_ClientDecModCount(uvd); + if (uvd->debug > 0) + info("%s: Returning %d.", proc, errCode); + return errCode; +} + +/* + * usbvideo_v4l_close() + * + * This is part of Video 4 Linux API. The procedure + * stops streaming and deallocates all buffers that were earlier + * allocated in usbvideo_v4l_open(). + * + * History: + * 22-Jan-2000 Moved scratch buffer deallocation here. + * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. + * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. + */ +void usbvideo_v4l_close(struct video_device *dev) +{ + static const char proc[] = "usbvideo_v4l_close"; + uvd_t *uvd = (uvd_t *)dev; + int i; + + if (uvd->debug > 1) + info("%s($%p)", proc, dev); + + down(&uvd->lock); + usbvideo_StopDataPump(uvd); + usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); + uvd->fbuf = NULL; + RingQueue_Free(&uvd->dp); + + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + kfree(uvd->sbuf[i].data); + uvd->sbuf[i].data = NULL; + } + +#if USBVIDEO_REPORT_STATS + usbvideo_ReportStatistics(uvd); +#endif + + uvd->user--; + if (uvd->remove_pending) { + if (uvd->debug > 0) + info("usbvideo_v4l_close: Final disconnect."); + usbvideo_CameraRelease(uvd); + } + up(&uvd->lock); + usbvideo_ClientDecModCount(uvd); + + if (uvd->debug > 1) + info("%s: Completed.", proc); +} + +/* + * usbvideo_v4l_ioctl() + * + * This is part of Video 4 Linux API. The procedure handles ioctl() calls. + * + * History: + * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings. + */ +int usbvideo_v4l_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + uvd_t *uvd = (uvd_t *)dev; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return -EFAULT; + + switch (cmd) { + case VIDIOCGCAP: + { + if (copy_to_user(arg, &uvd->vcap, sizeof(uvd->vcap))) + return -EFAULT; + return 0; + } + case VIDIOCGCHAN: + { + if (copy_to_user(arg, &uvd->vchan, sizeof(uvd->vchan))) + return -EFAULT; + return 0; + } + case VIDIOCSCHAN: + { /* Not used but we return success */ + int v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCGPICT: + { + if (copy_to_user(arg, &uvd->vpic, sizeof(uvd->vpic))) + return -EFAULT; + return 0; + } + case VIDIOCSPICT: + { + struct video_picture tmp; + /* + * Use temporary 'video_picture' structure to preserve our + * own settings (such as color depth, palette) that we + * aren't allowing everyone (V4L client) to change. + */ + if (copy_from_user(&tmp, arg, sizeof(tmp))) + return -EFAULT; + uvd->vpic.brightness = tmp.brightness; + uvd->vpic.hue = tmp.hue; + uvd->vpic.colour = tmp.colour; + uvd->vpic.contrast = tmp.contrast; + uvd->settingsAdjusted = 0; /* Will force new settings */ + return 0; + } + case VIDIOCSWIN: + { + struct video_window vw; + + if (copy_from_user(&vw, arg, sizeof(vw))) + return -EFAULT; + if (vw.flags) + return -EINVAL; + if (vw.clipcount) + return -EINVAL; + if (vw.width != VIDEOSIZE_X(uvd->canvas)) + return -EINVAL; + if (vw.height != VIDEOSIZE_Y(uvd->canvas)) + return -EINVAL; + + return 0; + } + case VIDIOCGWIN: + { + struct video_window vw; + + vw.x = 0; + vw.y = 0; + vw.width = VIDEOSIZE_X(uvd->canvas); + vw.height = VIDEOSIZE_Y(uvd->canvas); + vw.chromakey = 0; + if (VALID_CALLBACK(uvd, getFPS)) + vw.flags = GET_CALLBACK(uvd, getFPS)(uvd); + else + vw.flags = 10; /* FIXME: do better! */ + + if (copy_to_user(arg, &vw, sizeof(vw))) + return -EFAULT; + + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf vm; + + memset(&vm, 0, sizeof(vm)); + vm.size = uvd->max_frame_size * 2; + vm.frames = 2; + vm.offsets[0] = 0; + vm.offsets[1] = uvd->max_frame_size; + + if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) + return -EFAULT; + + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + + if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) { + err("VIDIOCMCAPTURE: copy_from_user() failed."); + return -EFAULT; + } + if (uvd->debug >= 1) { + info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.", + vm.frame, vm.width, vm.height, vm.format); + } + /* + * Check if the requested size is supported. If the requestor + * requests too big a frame then we may be tricked into accessing + * outside of own preallocated frame buffer (in uvd->frame). + * This will cause oops or a security hole. Theoretically, we + * could only clamp the size down to acceptable bounds, but then + * we'd need to figure out how to insert our smaller buffer into + * larger caller's buffer... this is not an easy question. So we + * here just flatly reject too large requests, assuming that the + * caller will resubmit with smaller size. Callers should know + * what size we support (returned by VIDIOCGCAP). However vidcat, + * for one, does not care and allows to ask for any size. + */ + if ((vm.width > VIDEOSIZE_X(uvd->canvas)) || + (vm.height > VIDEOSIZE_Y(uvd->canvas))) { + if (uvd->debug > 0) { + info("VIDIOCMCAPTURE: Size=%dx%d too large; " + "allowed only up to %ldx%ld", vm.width, vm.height, + VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas)); + } + return -EINVAL; + } + /* Check if the palette is supported */ + if (((1L << vm.format) & uvd->paletteBits) == 0) { + if (uvd->debug > 0) { + info("VIDIOCMCAPTURE: format=%d. not supported" + " (paletteBits=$%08lx)", + vm.format, uvd->paletteBits); + } + return -EINVAL; + } + if ((vm.frame != 0) && (vm.frame != 1)) { + err("VIDIOCMCAPTURE: vm.frame=%d. !E [0,1]", vm.frame); + return -EINVAL; + } + if (uvd->frame[vm.frame].frameState == FrameState_Grabbing) { + /* Not an error - can happen */ + } + uvd->frame[vm.frame].request = VIDEOSIZE(vm.width, vm.height); + uvd->frame[vm.frame].palette = vm.format; + + /* Mark it as ready */ + uvd->frame[vm.frame].frameState = FrameState_Ready; + + return usbvideo_NewFrame(uvd, vm.frame); + } + case VIDIOCSYNC: + { + int frameNum, ret; + + if (copy_from_user((void *)&frameNum, arg, sizeof(frameNum))) { + err("VIDIOCSYNC: copy_from_user() failed."); + return -EFAULT; + } + if(frameNum < 0 || frameNum >= USBVIDEO_NUMFRAMES) + return -EINVAL; + + if (uvd->debug >= 1) + info("VIDIOCSYNC: syncing to frame %d.", frameNum); + if (uvd->flags & FLAGS_NO_DECODING) + ret = usbvideo_GetFrame(uvd, frameNum); + else if (VALID_CALLBACK(uvd, getFrame)) { + ret = GET_CALLBACK(uvd, getFrame)(uvd, frameNum); + if ((ret < 0) && (uvd->debug >= 1)) { + err("VIDIOCSYNC: getFrame() returned %d.", ret); + } + } else { + err("VIDIOCSYNC: getFrame is not set"); + ret = -EFAULT; + } + + /* + * The frame is in FrameState_Done_Hold state. Release it + * right now because its data is already mapped into + * the user space and it's up to the application to + * make use of it until it asks for another frame. + */ + uvd->frame[frameNum].frameState = FrameState_Unused; + return ret; + } + case VIDIOCGFBUF: + { + struct video_buffer vb; + + memset(&vb, 0, sizeof(vb)); + vb.base = NULL; /* frame buffer not supported, not used */ + + if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) + return -EFAULT; + + return 0; + } + case VIDIOCKEY: + return 0; + + case VIDIOCCAPTURE: + return -EINVAL; + + case VIDIOCSFBUF: + + case VIDIOCGTUNER: + case VIDIOCSTUNER: + + case VIDIOCGFREQ: + case VIDIOCSFREQ: + + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/* + * usbvideo_v4l_read() + * + * This is mostly boring stuff. We simply ask for a frame and when it + * arrives copy all the video data from it into user space. There is + * no obvious need to override this method. + * + * History: + * 20-Oct-2000 Created. + * 01-Nov-2000 Added mutex (uvd->lock). + */ +long usbvideo_v4l_read(struct video_device *dev, char *buf, unsigned long count, int noblock) +{ + static const char proc[] = "usbvideo_v4l_read"; + uvd_t *uvd = (uvd_t *) dev; + int frmx = -1; + usbvideo_frame_t *frame; + + if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL)) + return -EFAULT; + + if (uvd->debug >= 1) + info("%s: %ld. bytes, noblock=%d.", proc, count, noblock); + + down(&uvd->lock); + + /* See if a frame is completed, then use it. */ + if ((uvd->frame[0].frameState == FrameState_Done) || + (uvd->frame[0].frameState == FrameState_Done_Hold) || + (uvd->frame[0].frameState == FrameState_Error)) { + frmx = 0; + } else if ((uvd->frame[1].frameState >= FrameState_Done) || + (uvd->frame[1].frameState == FrameState_Done_Hold) || + (uvd->frame[1].frameState >= FrameState_Done)) { + frmx = 1; + } + + /* FIXME: If we don't start a frame here then who ever does? */ + if (noblock && (frmx == -1)) { + count = -EAGAIN; + goto read_done; + } + + /* + * If no FrameState_Done, look for a FrameState_Grabbing state. + * See if a frame is in process (grabbing), then use it. + * We will need to wait until it becomes cooked, of course. + */ + if (frmx == -1) { + if (uvd->frame[0].frameState == FrameState_Grabbing) + frmx = 0; + else if (uvd->frame[1].frameState == FrameState_Grabbing) + frmx = 1; + } + + /* + * If no frame is active, start one. We don't care which one + * it will be, so #0 is as good as any. + * In read access mode we don't have convenience of VIDIOCMCAPTURE + * to specify the requested palette (video format) on per-frame + * basis. This means that we have to return data in -some- format + * and just hope that the client knows what to do with it. + * The default format is configured in uvd->defaultPalette field + * as one of VIDEO_PALETTE_xxx values. We stuff it into the new + * frame and initiate the frame filling process. + */ + if (frmx == -1) { + if (uvd->defaultPalette == 0) { + err("%s: No default palette; don't know what to do!", proc); + count = -EFAULT; + goto read_done; + } + frmx = 0; + /* + * We have no per-frame control over video size. + * Therefore we only can use whatever size was + * specified as default. + */ + uvd->frame[frmx].request = uvd->videosize; + uvd->frame[frmx].palette = uvd->defaultPalette; + uvd->frame[frmx].frameState = FrameState_Ready; + usbvideo_NewFrame(uvd, frmx); + /* Now frame 0 is supposed to start filling... */ + } + + /* + * Get a pointer to the active frame. It is either previously + * completed frame or frame in progress but not completed yet. + */ + frame = &uvd->frame[frmx]; + + /* + * Sit back & wait until the frame gets filled and postprocessed. + * If we fail to get the picture [in time] then return the error. + * In this call we specify that we want the frame to be waited for, + * postprocessed and switched into FrameState_Done_Hold state. This + * state is used to hold the frame as "fully completed" between + * subsequent partial reads of the same frame. + */ + if (frame->frameState != FrameState_Done_Hold) { + long rv = -EFAULT; + if (uvd->flags & FLAGS_NO_DECODING) + rv = usbvideo_GetFrame(uvd, frmx); + else if (VALID_CALLBACK(uvd, getFrame)) + rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx); + else + err("getFrame is not set"); + if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) { + count = rv; + goto read_done; + } + } + + /* + * Copy bytes to user space. We allow for partial reads, which + * means that the user application can request read less than + * the full frame size. It is up to the application to issue + * subsequent calls until entire frame is read. + * + * First things first, make sure we don't copy more than we + * have - even if the application wants more. That would be + * a big security embarassment! + */ + if ((count + frame->seqRead_Index) > frame->seqRead_Length) + count = frame->seqRead_Length - frame->seqRead_Index; + + /* + * Copy requested amount of data to user space. We start + * copying from the position where we last left it, which + * will be zero for a new frame (not read before). + */ + if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) { + count = -EFAULT; + goto read_done; + } + + /* Update last read position */ + frame->seqRead_Index += count; + if (uvd->debug >= 1) { + err("%s: {copy} count used=%ld, new seqRead_Index=%ld", + proc, count, frame->seqRead_Index); + } + + /* Finally check if the frame is done with and "release" it */ + if (frame->seqRead_Index >= frame->seqRead_Length) { + /* All data has been read */ + frame->seqRead_Index = 0; + + /* Mark it as available to be used again. */ + uvd->frame[frmx].frameState = FrameState_Unused; + if (usbvideo_NewFrame(uvd, frmx ? 0 : 1)) { + err("%s: usbvideo_NewFrame failed.", proc); + } + } +read_done: + up(&uvd->lock); + return count; +} + +/* + * Make all of the blocks of data contiguous + */ +static int usbvideo_CompressIsochronous(uvd_t *uvd, urb_t *urb) +{ + char *cdata; + int i, totlen = 0; + + for (i = 0; i < urb->number_of_packets; i++) { + int n = urb->iso_frame_desc[i].actual_length; + int st = urb->iso_frame_desc[i].status; + + cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + + /* Detect and ignore errored packets */ + if (st < 0) { + if (uvd->debug >= 1) + err("Data error: packet=%d. len=%d. status=%d.", i, n, st); + uvd->stats.iso_err_count++; + continue; + } + + /* Detect and ignore empty packets */ + if (n <= 0) { + uvd->stats.iso_skip_count++; + continue; + } + totlen += n; /* Little local accounting */ + RingQueue_Enqueue(&uvd->dp, cdata, n); + } + return totlen; +} + +static void usbvideo_IsocIrq(struct urb *urb) +{ + int i, len; + uvd_t *uvd = urb->context; + + /* We don't want to do anything if we are about to be removed! */ + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; +#if 0 + if (urb->actual_length > 0) { + info("urb=$%p status=%d. errcount=%d. length=%d.", + urb, urb->status, urb->error_count, urb->actual_length); + } else { + static int c = 0; + if (c++ % 100 == 0) + info("No Isoc data"); + } +#endif + + if (!uvd->streaming) { + if (uvd->debug >= 1) + info("Not streaming, but interrupt!"); + return; + } + + uvd->stats.urb_count++; + if (urb->actual_length <= 0) + goto urb_done_with; + + /* Copy the data received into ring queue */ + len = usbvideo_CompressIsochronous(uvd, urb); + uvd->stats.urb_length = len; + if (len <= 0) + goto urb_done_with; + + /* Here we got some data */ + uvd->stats.data_count += len; + RingQueue_WakeUpInterruptible(&uvd->dp); + +urb_done_with: + for (i = 0; i < FRAMES_PER_DESC; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + return; +} + +/* + * usbvideo_StartDataPump() + * + * History: + * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead + * of hardcoded values. Simplified by using for loop, + * allowed any number of URBs. + */ +int usbvideo_StartDataPump(uvd_t *uvd) +{ + static const char proc[] = "usbvideo_StartDataPump"; + struct usb_device *dev = uvd->dev; + int i, errFlag; + + if (uvd->debug > 1) + info("%s($%p)", proc, uvd); + + if (!CAMERA_IS_OPERATIONAL(uvd)) { + err("%s: Camera is not operational",proc); + return -EFAULT; + } + uvd->curframe = -1; + + /* Alternate interface 1 is is the biggest frame size */ + i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); + if (i < 0) { + err("%s: usb_set_interface error", proc); + uvd->last_error = i; + return -EBUSY; + } + if (VALID_CALLBACK(uvd, videoStart)) + GET_CALLBACK(uvd, videoStart)(uvd); + else + err("%s: videoStart not set", proc); + + /* We double buffer the Iso lists */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + int j, k; + urb_t *urb = uvd->sbuf[i].urb; + urb->dev = dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); + urb->transfer_flags = USB_ISO_ASAP; + urb->transfer_buffer = uvd->sbuf[i].data; + urb->complete = usbvideo_IsocIrq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC; + for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = uvd->iso_packet_len; + } + } + + /* Link URBs into a ring so that they invoke each other infinitely */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + if ((i+1) < USBVIDEO_NUMSBUF) + uvd->sbuf[i].urb->next = uvd->sbuf[i+1].urb; + else + uvd->sbuf[i].urb->next = uvd->sbuf[0].urb; + } + + /* Submit all URBs */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + errFlag = usb_submit_urb(uvd->sbuf[i].urb); + if (errFlag) + err("%s: usb_submit_isoc(%d) ret %d", proc, i, errFlag); + } + + uvd->streaming = 1; + if (uvd->debug > 1) + info("%s: streaming=1 video_endp=$%02x", proc, uvd->video_endp); + return 0; +} + +/* + * usbvideo_StopDataPump() + * + * This procedure stops streaming and deallocates URBs. Then it + * activates zero-bandwidth alt. setting of the video interface. + * + * History: + * 22-Jan-2000 Corrected order of actions to work after surprise removal. + * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values. + */ +void usbvideo_StopDataPump(uvd_t *uvd) +{ + static const char proc[] = "usbvideo_StopDataPump"; + int i, j; + + if (uvd->debug > 1) + info("%s($%p)", proc, uvd); + + if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) + return; + + /* Unschedule all of the iso td's */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + j = usb_unlink_urb(uvd->sbuf[i].urb); + if (j < 0) + err("%s: usb_unlink_urb() error %d.", proc, j); + } + if (uvd->debug > 1) + info("%s: streaming=0", proc); + uvd->streaming = 0; + + if (!uvd->remove_pending) { + /* Invoke minidriver's magic to stop the camera */ + if (VALID_CALLBACK(uvd, videoStop)) + GET_CALLBACK(uvd, videoStop)(uvd); + else + err("%s: videoStop not set" ,proc); + + /* Set packet size to 0 */ + j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); + if (j < 0) { + err("%s: usb_set_interface() error %d.", proc, j); + uvd->last_error = j; + } + } +} + +/* + * usbvideo_NewFrame() + * + * History: + * 29-Mar-00 Added copying of previous frame into the current one. + * 6-Aug-00 Added model 3 video sizes, removed redundant width, height. + */ +int usbvideo_NewFrame(uvd_t *uvd, int framenum) +{ + usbvideo_frame_t *frame; + int n; + + if (uvd->debug > 1) + info("usbvideo_NewFrame($%p,%d.)", uvd, framenum); + + /* If we're not grabbing a frame right now and the other frame is */ + /* ready to be grabbed into, then use it instead */ + if (uvd->curframe != -1) + return 0; + + /* If necessary we adjust picture settings between frames */ + if (!uvd->settingsAdjusted) { + if (VALID_CALLBACK(uvd, adjustPicture)) + GET_CALLBACK(uvd, adjustPicture)(uvd); + uvd->settingsAdjusted = 1; + } + + n = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; + if (uvd->frame[n].frameState == FrameState_Ready) + framenum = n; + + frame = &uvd->frame[framenum]; + + frame->frameState = FrameState_Grabbing; + frame->scanstate = ScanState_Scanning; + frame->seqRead_Length = 0; /* Accumulated in xxx_parse_data() */ + frame->deinterlace = Deinterlace_None; + frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */ + uvd->curframe = framenum; + + /* + * Normally we would want to copy previous frame into the current one + * before we even start filling it with data; this allows us to stop + * filling at any moment; top portion of the frame will be new and + * bottom portion will stay as it was in previous frame. If we don't + * do that then missing chunks of video stream will result in flickering + * portions of old data whatever it was before. + * + * If we choose not to copy previous frame (to, for example, save few + * bus cycles - the frame can be pretty large!) then we have an option + * to clear the frame before using. If we experience losses in this + * mode then missing picture will be black (no flickering). + * + * Finally, if user chooses not to clean the current frame before + * filling it with data then the old data will be visible if we fail + * to refill entire frame with new data. + */ + if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) { + /* This copies previous frame into this one to mask losses */ + memmove(frame->data, uvd->frame[1-framenum].data, uvd->max_frame_size); + } else { + if (uvd->flags & FLAGS_CLEAN_FRAMES) { + /* This provides a "clean" frame but slows things down */ + memset(frame->data, 0, uvd->max_frame_size); + } + } + return 0; +} + +/* + * usbvideo_CollectRawData() + * + * This procedure can be used instead of 'processData' callback if you + * only want to dump the raw data from the camera into the output + * device (frame buffer). You can look at it with V4L client, but the + * image will be unwatchable. The main purpose of this code and of the + * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from + * new, unknown cameras. This procedure will be automatically invoked + * instead of the specified callback handler when uvd->flags has bit + * FLAGS_NO_DECODING set. Therefore, any regular build of any driver + * based on usbvideo can use this feature at any time. + */ +void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame) +{ + int n; + + assert(uvd != NULL); + assert(frame != NULL); + + /* Try to move data from queue into frame buffer */ + n = RingQueue_GetLength(&uvd->dp); + if (n > 0) { + int m; + /* See how much space we have left */ + m = uvd->max_frame_size - frame->seqRead_Length; + if (n > m) + n = m; + /* Now move that much data into frame buffer */ + RingQueue_Dequeue( + &uvd->dp, + frame->data + frame->seqRead_Length, + m); + frame->seqRead_Length += m; + } + /* See if we filled the frame */ + if (frame->seqRead_Length >= uvd->max_frame_size) { + frame->frameState = FrameState_Done; + uvd->curframe = -1; + uvd->stats.frame_num++; + } +} + +int usbvideo_GetFrame(uvd_t *uvd, int frameNum) +{ + static const char proc[] = "usbvideo_GetFrame"; + usbvideo_frame_t *frame = &uvd->frame[frameNum]; + + if (uvd->debug >= 2) + info("%s($%p,%d.)", proc, uvd, frameNum); + + switch (frame->frameState) { + case FrameState_Unused: + if (uvd->debug >= 2) + info("%s: FrameState_Unused", proc); + return -EINVAL; + case FrameState_Ready: + case FrameState_Grabbing: + case FrameState_Error: + { + int ntries, signalPending; + redo: + if (!CAMERA_IS_OPERATIONAL(uvd)) { + if (uvd->debug >= 2) + info("%s: Camera is not operational (1)", proc); + return -EIO; + } + ntries = 0; + do { + RingQueue_InterruptibleSleepOn(&uvd->dp); + signalPending = signal_pending(current); + if (!CAMERA_IS_OPERATIONAL(uvd)) { + if (uvd->debug >= 2) + info("%s: Camera is not operational (2)", proc); + return -EIO; + } + assert(uvd->fbuf != NULL); + if (signalPending) { + if (uvd->debug >= 2) + info("%s: Signal=$%08x", proc, signalPending); + if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { + usbvideo_TestPattern(uvd, 1, 0); + uvd->curframe = -1; + uvd->stats.frame_num++; + if (uvd->debug >= 2) + info("%s: Forced test pattern screen", proc); + return 0; + } else { + /* Standard answer: Interrupted! */ + if (uvd->debug >= 2) + info("%s: Interrupted!", proc); + return -EINTR; + } + } else { + /* No signals - we just got new data in dp queue */ + if (uvd->flags & FLAGS_NO_DECODING) + usbvideo_CollectRawData(uvd, frame); + else if (VALID_CALLBACK(uvd, processData)) + GET_CALLBACK(uvd, processData)(uvd, frame); + else + err("%s: processData not set", proc); + } + } while (frame->frameState == FrameState_Grabbing); + if (uvd->debug >= 2) { + info("%s: Grabbing done; state=%d. (%lu. bytes)", + proc, frame->frameState, frame->seqRead_Length); + } + if (frame->frameState == FrameState_Error) { + int ret = usbvideo_NewFrame(uvd, frameNum); + if (ret < 0) { + err("%s: usbvideo_NewFrame() failed (%d.)", proc, ret); + return ret; + } + goto redo; + } + /* Note that we fall through to meet our destiny below */ + } + case FrameState_Done: + /* + * Do all necessary postprocessing of data prepared in + * "interrupt" code and the collecting code above. The + * frame gets marked as FrameState_Done by queue parsing code. + * This status means that we collected enough data and + * most likely processed it as we went through. However + * the data may need postprocessing, such as deinterlacing + * or picture adjustments implemented in software (horror!) + * + * As soon as the frame becomes "final" it gets promoted to + * FrameState_Done_Hold status where it will remain until the + * caller consumed all the video data from the frame. Then + * the empty shell of ex-frame is thrown out for dogs to eat. + * But we, worried about pets, will recycle the frame! + */ + uvd->stats.frame_num++; + if ((uvd->flags & FLAGS_NO_DECODING) == 0) { + if (VALID_CALLBACK(uvd, postProcess)) + GET_CALLBACK(uvd, postProcess)(uvd, frame); + if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST) + usbvideo_SoftwareContrastAdjustment(uvd, frame); + } + frame->frameState = FrameState_Done_Hold; + if (uvd->debug >= 2) + info("%s: Entered FrameState_Done_Hold state.", proc); + return 0; + + case FrameState_Done_Hold: + /* + * We stay in this state indefinitely until someone external, + * like ioctl() or read() call finishes digesting the frame + * data. Then it will mark the frame as FrameState_Unused and + * it will be released back into the wild to roam freely. + */ + if (uvd->debug >= 2) + info("%s: FrameState_Done_Hold state.", proc); + return 0; + } + + /* Catch-all for other cases. We shall not be here. */ + err("%s: Invalid state %d.", proc, frame->frameState); + frame->frameState = FrameState_Unused; + return 0; +} + +/* + * usbvideo_DeinterlaceFrame() + * + * This procedure deinterlaces the given frame. Some cameras produce + * only half of scanlines - sometimes only even lines, sometimes only + * odd lines. The deinterlacing method is stored in frame->deinterlace + * variable. + * + * Here we scan the frame vertically and replace missing scanlines with + * average between surrounding ones - before and after. If we have no + * line above then we just copy next line. Similarly, if we need to + * create a last line then preceding line is used. + */ +void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame) +{ + if ((uvd == NULL) || (frame == NULL)) + return; + + if ((frame->deinterlace == Deinterlace_FillEvenLines) || + (frame->deinterlace == Deinterlace_FillOddLines)) + { + const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1; + + for (; i < VIDEOSIZE_Y(frame->request); i += 2) { + const unsigned char *fs1, *fs2; + unsigned char *fd; + int ip, in, j; /* Previous and next lines */ + + /* + * Need to average lines before and after 'i'. + * If we go out of bounds seeking those lines then + * we point back to existing line. + */ + ip = i - 1; /* First, get rough numbers */ + in = i + 1; + + /* Now validate */ + if (ip < 0) + ip = in; + if (in >= VIDEOSIZE_Y(frame->request)) + in = ip; + + /* Sanity check */ + if ((ip < 0) || (in < 0) || + (ip >= VIDEOSIZE_Y(frame->request)) || + (in >= VIDEOSIZE_Y(frame->request))) + { + err("Error: ip=%d. in=%d. req.height=%ld.", + ip, in, VIDEOSIZE_Y(frame->request)); + break; + } + + /* Now we need to average lines 'ip' and 'in' to produce line 'i' */ + fs1 = frame->data + (v4l_linesize * ip); + fs2 = frame->data + (v4l_linesize * in); + fd = frame->data + (v4l_linesize * i); + + /* Average lines around destination */ + for (j=0; j < v4l_linesize; j++) { + fd[j] = (unsigned char)((((unsigned) fs1[j]) + + ((unsigned)fs2[j])) >> 1); + } + } + } + + /* Optionally display statistics on the screen */ + if (uvd->flags & FLAGS_OVERLAY_STATS) + usbvideo_OverlayStats(uvd, frame); +} + +/* + * usbvideo_SoftwareContrastAdjustment() + * + * This code adjusts the contrast of the frame, assuming RGB24 format. + * As most software image processing, this job is CPU-intensive. + * Get a camera that supports hardware adjustment! + * + * History: + * 09-Feb-2001 Created. + */ +void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame) +{ + static const char proc[] = "usbvideo_SoftwareContrastAdjustment"; + int i, j, v4l_linesize; + signed long adj; + const int ccm = 128; /* Color correction median - see below */ + + if ((uvd == NULL) || (frame == NULL)) { + err("%s: Illegal call.", proc); + return; + } + adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ + RESTRICT_TO_RANGE(adj, -ccm, ccm+1); + if (adj == 0) { + /* In rare case of no adjustment */ + return; + } + v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + for (i=0; i < VIDEOSIZE_Y(frame->request); i++) { + unsigned char *fd = frame->data + (v4l_linesize * i); + for (j=0; j < v4l_linesize; j++) { + signed long v = (signed long) fd[j]; + /* Magnify up to 2 times, reduce down to zero */ + v = 128 + ((ccm + adj) * (v - 128)) / ccm; + RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */ + fd[j] = (unsigned char) v; + } + } +} + +/* + * /proc interface + * + * We will be creating directories and entries under /proc/video using + * external 'video_proc_entry' directory which is exported by videodev.o + * module. Within that directory we will create $driver/ directory to + * uniquely and uniformly refer to our specific $driver. Within that + * directory we will finally create an entry that is named after the + * video device node - video3, for example. The format of that file + * is determined by callbacks that the minidriver may provide. If no + * callbacks are provided (neither read nor write) then we don't create + * the entry. + * + * Here is a sample directory entry: /proc/video/ibmcam/video3 + * + * The "file" video3 (in example above) is readable and writeable, in + * theory. If the minidriver provides callbacks to do reading and + * writing then both those procedures are supported. However if the + * driver leaves callbacks in default (NULL) state the default + * read and write handlers are used. The default read handler reports + * that the driver does not support /proc fs. The default write handler + * returns error code on any write attempt. + */ + +#if USES_PROC_FS + +extern struct proc_dir_entry *video_proc_entry; + +static void usbvideo_procfs_level1_create(usbvideo_t *ut) +{ + static const char proc[] = "usbvideo_procfs_level1_create"; + + if (ut == NULL) { + err("%s: ut == NULL", proc); + return; + } + if (video_proc_entry == NULL) { + err("%s: /proc/video/ doesn't exist.", proc); + return; + } + ut->procfs_dEntry = create_proc_entry(ut->drvName, S_IFDIR, video_proc_entry); + if (ut->procfs_dEntry != NULL) { + if (ut->md_module != NULL) + ut->procfs_dEntry->owner = ut->md_module; + } else { + err("%s: Unable to initialize /proc/video/%s", proc, ut->drvName); + } +} + +static void usbvideo_procfs_level1_destroy(usbvideo_t *ut) +{ + static const char proc[] = "usbvideo_procfs_level1_destroy"; + + if (ut == NULL) { + err("%s: ut == NULL", proc); + return; + } + if (ut->procfs_dEntry != NULL) { + remove_proc_entry(ut->drvName, video_proc_entry); + ut->procfs_dEntry = NULL; + } +} + +static void usbvideo_procfs_level2_create(uvd_t *uvd) +{ + static const char proc[] = "usbvideo_procfs_level2_create"; + + if (uvd == NULL) { + err("%s: uvd == NULL", proc); + return; + } + assert(uvd->handle != NULL); + if (uvd->handle->procfs_dEntry == NULL) { + err("%s: uvd->handle->procfs_dEntry == NULL", proc); + return; + } + + sprintf(uvd->videoName, "video%d", uvd->vdev.minor); + uvd->procfs_vEntry = create_proc_entry( + uvd->videoName, + S_IFREG | S_IRUGO | S_IWUSR, + uvd->handle->procfs_dEntry); + if (uvd->procfs_vEntry != NULL) { + uvd->procfs_vEntry->data = uvd; + uvd->procfs_vEntry->read_proc = uvd->handle->cb.procfs_read; + uvd->procfs_vEntry->write_proc = uvd->handle->cb.procfs_write; + } else { + err("%s: Failed to create entry \"%s\"", proc, uvd->videoName); + } +} + +static void usbvideo_procfs_level2_destroy(uvd_t *uvd) +{ + static const char proc[] = "usbvideo_procfs_level2_destroy"; + + if (uvd == NULL) { + err("%s: uvd == NULL", proc); + return; + } + if (uvd->procfs_vEntry != NULL) { + remove_proc_entry(uvd->videoName, uvd->procfs_vEntry); + uvd->procfs_vEntry = NULL; + } +} + +static int usbvideo_default_procfs_read_proc( + char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + char *out = page; + int len; + + /* Stay under PAGE_SIZE or else */ + out += sprintf(out, "This driver does not support /proc services.\n"); + len = out - page; + len -= off; + if (len < count) { + *eof = 1; + if (len <= 0) + return 0; + } else + len = count; + *start = page + off; + return len; +} + +static int usbvideo_default_procfs_write_proc( + struct file *file, const char *buffer, + unsigned long count, void *data) +{ + return -EINVAL; +} + +#endif /* USES_PROC_FS */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usbvideo.h linux/drivers/usb/usbvideo.h --- v2.4.9/linux/drivers/usb/usbvideo.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/usbvideo.h Fri Sep 7 09:28:37 2001 @@ -0,0 +1,424 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef usbvideo_h +#define usbvideo_h + +#include +#include +#include +#include + +/* Most helpful debugging aid */ +#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) + +#define USES_PROC_FS (defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)) +#define USBVIDEO_REPORT_STATS 1 /* Set to 0 to block statistics on close */ + +/* Bit flags (options) */ +#define FLAGS_RETRY_VIDIOCSYNC (1 << 0) +#define FLAGS_MONOCHROME (1 << 1) +#define FLAGS_DISPLAY_HINTS (1 << 2) +#define FLAGS_OVERLAY_STATS (1 << 3) +#define FLAGS_FORCE_TESTPATTERN (1 << 4) +#define FLAGS_SEPARATE_FRAMES (1 << 5) +#define FLAGS_CLEAN_FRAMES (1 << 6) +#define FLAGS_NO_DECODING (1 << 7) + +/* Bit flags for frames (apply to the frame where they are specified) */ +#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST (1 << 0) + +/* Camera capabilities (maximum) */ +#define CAMERA_URB_FRAMES 32 +#define CAMERA_MAX_ISO_PACKET 1023 /* 1022 actually sent by camera */ +#define FRAMES_PER_DESC (CAMERA_URB_FRAMES) +#define FRAME_SIZE_PER_DESC (CAMERA_MAX_ISO_PACKET) + +/* This macro restricts an int variable to an inclusive range */ +#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } + +#define V4L_BYTES_PER_PIXEL 3 /* Because we produce RGB24 */ + +/* + * Use this macro to construct constants for different video sizes. + * We have to deal with different video sizes that have to be + * configured in the device or compared against when we receive + * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y + * #defines and that's the end of story. However this solution + * does not allow to convert between real pixel sizes and the + * constant (integer) value that may be used to tag a frame or + * whatever. The set of macros below constructs videosize constants + * from the pixel size and allows to reconstruct the pixel size + * from the combined value later. + */ +#define VIDEOSIZE(x,y) (((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16)) +#define VIDEOSIZE_X(vs) ((vs) & 0xFFFFL) +#define VIDEOSIZE_Y(vs) (((vs) >> 16) & 0xFFFFL) +typedef unsigned long videosize_t; + +/* + * This macro checks if the camera is still operational. The 'uvd' + * pointer must be valid, uvd->dev must be valid, we are not + * removing the device and the device has not erred on us. + */ +#define CAMERA_IS_OPERATIONAL(uvd) (\ + (uvd != NULL) && \ + ((uvd)->dev != NULL) && \ + ((uvd)->last_error == 0) && \ + (!(uvd)->remove_pending)) + +/* + * We use macros to do YUV -> RGB conversion because this is + * very important for speed and totally unimportant for size. + * + * YUV -> RGB Conversion + * --------------------- + * + * B = 1.164*(Y-16) + 2.018*(V-128) + * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) + * R = 1.164*(Y-16) + 1.596*(U-128) + * + * If you fancy integer arithmetics (as you should), hear this: + * + * 65536*B = 76284*(Y-16) + 132252*(V-128) + * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) + * 65536*R = 76284*(Y-16) + 104595*(U-128) + * + * Make sure the output values are within [0..255] range. + */ +#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) +#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ + int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ + mm_y = (my) - 16; \ + mm_u = (mu) - 128; \ + mm_v = (mv) - 128; \ + mm_yc= mm_y * 76284; \ + mm_b = (mm_yc + 132252*mm_v ) >> 16; \ + mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ + mm_r = (mm_yc + 104595*mm_u ) >> 16; \ + mb = LIMIT_RGB(mm_b); \ + mg = LIMIT_RGB(mm_g); \ + mr = LIMIT_RGB(mm_r); \ +} + +#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % (rq)->length +#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n) +#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % (rq)->length]) + +typedef struct { + unsigned char *queue; /* Data from the Isoc data pump */ + int length; /* How many bytes allocated for the queue */ + int wi; /* That's where we write */ + int ri; /* Read from here until you hit write index */ + wait_queue_head_t wqh; /* Processes waiting */ +} RingQueue_t; + +typedef enum { + ScanState_Scanning, /* Scanning for header */ + ScanState_Lines /* Parsing lines */ +} ScanState_t; + +/* Completion states of the data parser */ +typedef enum { + scan_Continue, /* Just parse next item */ + scan_NextFrame, /* Frame done, send it to V4L */ + scan_Out, /* Not enough data for frame */ + scan_EndParse /* End parsing */ +} ParseState_t; + +typedef enum { + FrameState_Unused, /* Unused (no MCAPTURE) */ + FrameState_Ready, /* Ready to start grabbing */ + FrameState_Grabbing, /* In the process of being grabbed into */ + FrameState_Done, /* Finished grabbing, but not been synced yet */ + FrameState_Done_Hold, /* Are syncing or reading */ + FrameState_Error, /* Something bad happened while processing */ +} FrameState_t; + +/* + * Some frames may contain only even or odd lines. This type + * specifies what type of deinterlacing is required. + */ +typedef enum { + Deinterlace_None=0, + Deinterlace_FillOddLines, + Deinterlace_FillEvenLines +} Deinterlace_t; + +struct usb_device; + +#define USBVIDEO_NUMFRAMES 2 /* How many frames we work with */ +#define USBVIDEO_NUMSBUF 2 /* How many URBs linked in a ring */ + +/* This structure represents one Isoc request - URB and buffer */ +typedef struct { + char *data; + urb_t *urb; +} usbvideo_sbuf_t; + +typedef struct { + char *data; /* Frame buffer */ + unsigned long header; /* Significant bits from the header */ + + videosize_t canvas; /* The canvas (max. image) allocated */ + videosize_t request; /* That's what the application asked for */ + unsigned short palette; /* The desired format */ + + FrameState_t frameState;/* State of grabbing */ + ScanState_t scanstate; /* State of scanning */ + Deinterlace_t deinterlace; + int flags; /* USBVIDEO_FRAME_FLAG_xxx bit flags */ + + int curline; /* Line of frame we're working on */ + + long seqRead_Length; /* Raw data length of frame */ + long seqRead_Index; /* Amount of data that has been already read */ + + void *user; /* Additional data that user may need */ +} usbvideo_frame_t; + +/* Statistics that can be overlaid on screen */ +typedef struct { + unsigned long frame_num; /* Sequential number of the frame */ + unsigned long urb_count; /* How many URBs we received so far */ + unsigned long urb_length; /* Length of last URB */ + unsigned long data_count; /* How many bytes we received */ + unsigned long header_count; /* How many frame headers we found */ + unsigned long iso_skip_count; /* How many empty ISO packets received */ + unsigned long iso_err_count; /* How many bad ISO packets received */ +} usbvideo_statistics_t; + +struct s_usbvideo_t; + +typedef struct { + struct video_device vdev; /* Must be the first field! */ + struct usb_device *dev; + struct s_usbvideo_t *handle; /* Points back to the usbvideo_t */ + void *user_data; /* Camera-dependent data */ + int user_size; /* Size of that camera-dependent data */ + int debug; /* Debug level for usbvideo */ + unsigned char iface; /* Video interface number */ + unsigned char video_endp; + unsigned char ifaceAltActive; + unsigned char ifaceAltInactive; /* Alt settings */ + unsigned long flags; /* FLAGS_USBVIDEO_xxx */ + unsigned long paletteBits; /* Which palettes we accept? */ + unsigned short defaultPalette; /* What palette to use for read() */ + struct semaphore lock; + int user; /* user count for exclusive use */ + + videosize_t videosize; /* Current setting */ + videosize_t canvas; /* This is the width,height of the V4L canvas */ + int max_frame_size; /* Bytes in one video frame */ + + int uvd_used; /* Is this structure in use? */ + int streaming; /* Are we streaming Isochronous? */ + int grabbing; /* Are we grabbing? */ + int settingsAdjusted; /* Have we adjusted contrast etc.? */ + int last_error; /* What calamity struck us? */ + + char *fbuf; /* Videodev buffer area */ + int fbuf_size; /* Videodev buffer size */ + + int curframe; + int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */ + + RingQueue_t dp; /* Isoc data pump */ + usbvideo_frame_t frame[USBVIDEO_NUMFRAMES]; + usbvideo_sbuf_t sbuf[USBVIDEO_NUMSBUF]; + + volatile int remove_pending; /* If set then about to exit */ + + struct video_picture vpic, vpic_old; /* Picture settings */ + struct video_capability vcap; /* Video capabilities */ + struct video_channel vchan; /* May be used for tuner support */ + usbvideo_statistics_t stats; + struct proc_dir_entry *procfs_vEntry; /* /proc/video/MYDRIVER/video2 */ + char videoName[32]; /* Holds name like "video7" */ +} uvd_t; + +/* + * usbvideo callbacks (virtual methods). They are set when usbvideo + * services are registered. All of these default to NULL, except those + * that default to usbvideo-provided methods. + */ +typedef struct { +#if defined(usb_device_id_ver) + /* New style probe (for 2.4.x kernels with hotplugging) */ + void *(*probe)(struct usb_device *, unsigned int,const struct usb_device_id *); +#else + /* Old style probe (for 2.2.x kernels) */ + void *(*probe)(struct usb_device *, unsigned int); +#endif + void (*userFree)(uvd_t *); + void (*disconnect)(struct usb_device *, void *); + int (*setupOnOpen)(uvd_t *); + void (*videoStart)(uvd_t *); + void (*videoStop)(uvd_t *); + void (*processData)(uvd_t *, usbvideo_frame_t *); + void (*postProcess)(uvd_t *, usbvideo_frame_t *); + void (*adjustPicture)(uvd_t *); + int (*getFPS)(uvd_t *); + int (*overlayHook)(uvd_t *, usbvideo_frame_t *); + int (*getFrame)(uvd_t *, int); + int (*procfs_read)(char *page,char **start,off_t off,int count,int *eof,void *data); + int (*procfs_write)(struct file *file,const char *buffer,unsigned long count,void *data); +} usbvideo_cb_t; + +struct s_usbvideo_t { + int num_cameras; /* As allocated */ + struct usb_driver usbdrv; /* Interface to the USB stack */ + char drvName[80]; /* Driver name */ + struct semaphore lock; /* Mutex protecting camera structures */ + usbvideo_cb_t cb; /* Table of callbacks (virtual methods) */ + struct video_device vdt; /* Video device template */ + uvd_t *cam; /* Array of camera structures */ + int uses_procfs; /* Non-zero if we create /proc entries */ + struct proc_dir_entry *procfs_dEntry; /* /proc/video/MYDRIVER */ + struct module *md_module; /* Minidriver module */ +}; +typedef struct s_usbvideo_t usbvideo_t; + +/* + * This macro retrieves callback address from the uvd_t object. + * No validity checks are done here, so be sure to check the + * callback beforehand with VALID_CALLBACK. + */ +#define GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName) + +/* + * This macro returns either callback pointer or NULL. This is safe + * macro, meaning that most of components of data structures involved + * may be NULL - this only results in NULL being returned. You may + * wish to use this macro to make sure that the callback is callable. + * However keep in mind that those checks take time. + */ +#define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \ + ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL) + +void RingQueue_Initialize(RingQueue_t *rq); +void RingQueue_Allocate(RingQueue_t *rq, int rqLen); +int RingQueue_IsAllocated(const RingQueue_t *rq); +void RingQueue_Free(RingQueue_t *rq); +int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len); +int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n); +int RingQueue_GetLength(const RingQueue_t *rq); +void RingQueue_InterruptibleSleepOn(RingQueue_t *rq); +void RingQueue_WakeUpInterruptible(RingQueue_t *rq); + +void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame); +void usbvideo_DrawLine( + usbvideo_frame_t *frame, + int x1, int y1, + int x2, int y2, + unsigned char cr, unsigned char cg, unsigned char cb); +void usbvideo_HexDump(const unsigned char *data, int len); +void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, int ch); +void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, const char *str); +void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame); +void usbvideo_ReportStatistics(const uvd_t *uvd); +void usbvideo_SayAndWait(const char *what); +void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode); +void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs); + +/* Memory allocation routines */ +unsigned long usbvideo_uvirt_to_kva(pgd_t *pgd, unsigned long adr); +unsigned long usbvideo_uvirt_to_bus(unsigned long adr); +unsigned long usbvideo_kvirt_to_bus(unsigned long adr); +unsigned long usbvideo_kvirt_to_pa(unsigned long adr); +void *usbvideo_rvmalloc(unsigned long size); +void usbvideo_rvfree(void *mem, unsigned long size); + +int usbvideo_register( + usbvideo_t **pCams, + const int num_cams, + const int num_extra, + const char *driverName, + const usbvideo_cb_t *cbTable, + struct module *md); +uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams); +int usbvideo_RegisterVideoDevice(uvd_t *uvd); +void usbvideo_Deregister(usbvideo_t **uvt); +void usbvideo_Disconnect(struct usb_device *dev, void *ptr); +void usbvideo_CameraRelease(uvd_t *uvd); + +void usbvideo_v4l_close(struct video_device *dev); +int usbvideo_v4l_initialize(struct video_device *dev); +int usbvideo_v4l_ioctl(struct video_device *dev, unsigned int cmd, void *arg); +int usbvideo_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size); +int usbvideo_v4l_open(struct video_device *dev, int flags); +long usbvideo_v4l_read(struct video_device *dev, char *buf, + unsigned long count, int noblock); +long usbvideo_v4l_write(struct video_device *dev, const char *buf, + unsigned long count, int noblock); + +int usbvideo_GetFrame(uvd_t *uvd, int frameNum); +int usbvideo_NewFrame(uvd_t *uvd, int framenum); +int usbvideo_StartDataPump(uvd_t *uvd); +void usbvideo_StopDataPump(uvd_t *uvd); +void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame); +void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame); + +/* + * This code performs bounds checking - use it when working with + * new formats, or else you may get oopses all over the place. + * If pixel falls out of bounds then it gets shoved back (as close + * to place of offence as possible) and is painted bright red. + * + * There are two important concepts: frame width, height and + * V4L canvas width, height. The former is the area requested by + * the application -for this very frame-. The latter is the largest + * possible frame that we can serve (we advertise that via V4L ioctl). + * The frame data is expected to be formatted as lines of length + * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines. + */ +static inline void RGB24_PUTPIXEL( + usbvideo_frame_t *fr, + int ix, int iy, + unsigned char vr, + unsigned char vg, + unsigned char vb) +{ + register unsigned char *pf; + int limiter = 0, mx, my; + mx = ix; + my = iy; + if (mx < 0) { + mx=0; + limiter++; + } else if (mx >= VIDEOSIZE_X((fr)->request)) { + mx= VIDEOSIZE_X((fr)->request) - 1; + limiter++; + } + if (my < 0) { + my = 0; + limiter++; + } else if (my >= VIDEOSIZE_Y((fr)->request)) { + my = VIDEOSIZE_Y((fr)->request) - 1; + limiter++; + } + pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix)); + if (limiter) { + *pf++ = 0; + *pf++ = 0; + *pf++ = 0xFF; + } else { + *pf++ = (vb); + *pf++ = (vg); + *pf++ = (vr); + } +} + +#endif /* usbvideo_h */ diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c --- v2.4.9/linux/drivers/video/fbcon.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/video/fbcon.c Fri Sep 7 09:28:37 2001 @@ -2206,6 +2206,10 @@ /* Some cards require 32bit access */ fb_writel (val, dst); dst += 4; + } else if (bdepth == 2 && !((long)dst & 1)) { + /* others require 16bit access */ + fb_writew (val,dst); + dst +=2; } else { #ifdef __LITTLE_ENDIAN for( i = 0; i < bdepth; ++i ) @@ -2280,6 +2284,10 @@ /* Some cards require 32bit access */ fb_writel (val, dst); dst += 4; + } else if (bdepth == 2 && !((long)dst & 1)) { + /* others require 16bit access */ + fb_writew (val,dst); + dst +=2; } else { #ifdef __LITTLE_ENDIAN for( i = 0; i < bdepth; ++i ) @@ -2493,3 +2501,5 @@ EXPORT_SYMBOL(fbcon_redraw_clear); EXPORT_SYMBOL(fbcon_dummy); EXPORT_SYMBOL(fb_con); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/radeon.h linux/drivers/video/radeon.h --- v2.4.9/linux/drivers/video/radeon.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/video/radeon.h Fri Sep 7 09:28:37 2001 @@ -0,0 +1,665 @@ +#ifndef _RADEON_H +#define _RADEON_H + + +/* radeon PCI ids */ +#define PCI_DEVICE_ID_RADEON_QD 0x5144 +#define PCI_DEVICE_ID_RADEON_QE 0x5145 +#define PCI_DEVICE_ID_RADEON_QF 0x5146 +#define PCI_DEVICE_ID_RADEON_QG 0x5147 + +#define RADEON_REGSIZE 0x4000 + + +#define MM_INDEX 0x0000 +#define MM_DATA 0x0004 +#define BUS_CNTL 0x0030 +#define HI_STAT 0x004C +#define BUS_CNTL1 0x0034 +#define I2C_CNTL_1 0x0094 +#define CONFIG_CNTL 0x00E0 +#define CONFIG_MEMSIZE 0x00F8 +#define CONFIG_APER_0_BASE 0x0100 +#define CONFIG_APER_1_BASE 0x0104 +#define CONFIG_APER_SIZE 0x0108 +#define CONFIG_REG_1_BASE 0x010C +#define CONFIG_REG_APER_SIZE 0x0110 +#define PAD_AGPINPUT_DELAY 0x0164 +#define PAD_CTLR_STRENGTH 0x0168 +#define PAD_CTLR_UPDATE 0x016C +#define AGP_CNTL 0x0174 +#define BM_STATUS 0x0160 +#define CAP0_TRIG_CNTL 0x0950 +#define VIPH_CONTROL 0x0C40 +#define VENDOR_ID 0x0F00 +#define DEVICE_ID 0x0F02 +#define COMMAND 0x0F04 +#define STATUS 0x0F06 +#define REVISION_ID 0x0F08 +#define REGPROG_INF 0x0F09 +#define SUB_CLASS 0x0F0A +#define BASE_CODE 0x0F0B +#define CACHE_LINE 0x0F0C +#define LATENCY 0x0F0D +#define HEADER 0x0F0E +#define BIST 0x0F0F +#define REG_MEM_BASE 0x0F10 +#define REG_IO_BASE 0x0F14 +#define REG_REG_BASE 0x0F18 +#define ADAPTER_ID 0x0F2C +#define BIOS_ROM 0x0F30 +#define CAPABILITIES_PTR 0x0F34 +#define INTERRUPT_LINE 0x0F3C +#define INTERRUPT_PIN 0x0F3D +#define MIN_GRANT 0x0F3E +#define MAX_LATENCY 0x0F3F +#define ADAPTER_ID_W 0x0F4C +#define PMI_CAP_ID 0x0F50 +#define PMI_NXT_CAP_PTR 0x0F51 +#define PMI_PMC_REG 0x0F52 +#define PM_STATUS 0x0F54 +#define PMI_DATA 0x0F57 +#define AGP_CAP_ID 0x0F58 +#define AGP_STATUS 0x0F5C +#define AGP_COMMAND 0x0F60 +#define AIC_CTRL 0x01D0 +#define AIC_STAT 0x01D4 +#define AIC_PT_BASE 0x01D8 +#define AIC_LO_ADDR 0x01DC +#define AIC_HI_ADDR 0x01E0 +#define AIC_TLB_ADDR 0x01E4 +#define AIC_TLB_DATA 0x01E8 +#define DAC_CNTL 0x0058 +#define CRTC_GEN_CNTL 0x0050 +#define MEM_CNTL 0x0140 +#define EXT_MEM_CNTL 0x0144 +#define MC_AGP_LOCATION 0x014C +#define MEM_IO_CNTL_A0 0x0178 +#define MEM_INIT_LATENCY_TIMER 0x0154 +#define MEM_SDRAM_MODE_REG 0x0158 +#define AGP_BASE 0x0170 +#define MEM_IO_CNTL_A1 0x017C +#define MEM_IO_CNTL_B0 0x0180 +#define MEM_IO_CNTL_B1 0x0184 +#define MC_DEBUG 0x0188 +#define MC_STATUS 0x0150 +#define MEM_IO_OE_CNTL 0x018C +#define MC_FB_LOCATION 0x0148 +#define HOST_PATH_CNTL 0x0130 +#define MEM_VGA_WP_SEL 0x0038 +#define MEM_VGA_RP_SEL 0x003C +#define HDP_DEBUG 0x0138 +#define SW_SEMAPHORE 0x013C +#define SURFACE_CNTL 0x0B00 +#define SURFACE0_LOWER_BOUND 0x0B04 +#define SURFACE1_LOWER_BOUND 0x0B14 +#define SURFACE2_LOWER_BOUND 0x0B24 +#define SURFACE3_LOWER_BOUND 0x0B34 +#define SURFACE4_LOWER_BOUND 0x0B44 +#define SURFACE5_LOWER_BOUND 0x0B54 +#define SURFACE6_LOWER_BOUND 0x0B64 +#define SURFACE7_LOWER_BOUND 0x0B74 +#define SURFACE0_UPPER_BOUND 0x0B08 +#define SURFACE1_UPPER_BOUND 0x0B18 +#define SURFACE2_UPPER_BOUND 0x0B28 +#define SURFACE3_UPPER_BOUND 0x0B38 +#define SURFACE4_UPPER_BOUND 0x0B48 +#define SURFACE5_UPPER_BOUND 0x0B58 +#define SURFACE6_UPPER_BOUND 0x0B68 +#define SURFACE7_UPPER_BOUND 0x0B78 +#define SURFACE0_INFO 0x0B0C +#define SURFACE1_INFO 0x0B1C +#define SURFACE2_INFO 0x0B2C +#define SURFACE3_INFO 0x0B3C +#define SURFACE4_INFO 0x0B4C +#define SURFACE5_INFO 0x0B5C +#define SURFACE6_INFO 0x0B6C +#define SURFACE7_INFO 0x0B7C +#define SURFACE_ACCESS_FLAGS 0x0BF8 +#define SURFACE_ACCESS_CLR 0x0BFC +#define GEN_INT_CNTL 0x0040 +#define GEN_INT_STATUS 0x0044 +#define CRTC_EXT_CNTL 0x0054 +#define RB3D_CNTL 0x1C3C +#define WAIT_UNTIL 0x1720 +#define ISYNC_CNTL 0x1724 +#define RBBM_GUICNTL 0x172C +#define RBBM_STATUS 0x0E40 +#define RBBM_STATUS_alt_1 0x1740 +#define RBBM_CNTL 0x00EC +#define RBBM_CNTL_alt_1 0x0E44 +#define RBBM_SOFT_RESET 0x00F0 +#define RBBM_SOFT_RESET_alt_1 0x0E48 +#define NQWAIT_UNTIL 0x0E50 +#define RBBM_DEBUG 0x0E6C +#define RBBM_CMDFIFO_ADDR 0x0E70 +#define RBBM_CMDFIFO_DATAL 0x0E74 +#define RBBM_CMDFIFO_DATAH 0x0E78 +#define RBBM_CMDFIFO_STAT 0x0E7C +#define CRTC_STATUS 0x005C +#define GPIO_VGA_DDC 0x0060 +#define GPIO_DVI_DDC 0x0064 +#define GPIO_MONID 0x0068 +#define PALETTE_INDEX 0x00B0 +#define PALETTE_DATA 0x00B4 +#define PALETTE_30_DATA 0x00B8 +#define CRTC_H_TOTAL_DISP 0x0200 +#define CRTC_H_SYNC_STRT_WID 0x0204 +#define CRTC_V_TOTAL_DISP 0x0208 +#define CRTC_V_SYNC_STRT_WID 0x020C +#define CRTC_VLINE_CRNT_VLINE 0x0210 +#define CRTC_CRNT_FRAME 0x0214 +#define CRTC_GUI_TRIG_VLINE 0x0218 +#define CRTC_DEBUG 0x021C +#define CRTC_OFFSET_RIGHT 0x0220 +#define CRTC_OFFSET 0x0224 +#define CRTC_OFFSET_CNTL 0x0228 +#define CRTC_PITCH 0x022C +#define OVR_CLR 0x0230 +#define OVR_WID_LEFT_RIGHT 0x0234 +#define OVR_WID_TOP_BOTTOM 0x0238 +#define DISPLAY_BASE_ADDR 0x023C +#define SNAPSHOT_VH_COUNTS 0x0240 +#define SNAPSHOT_F_COUNT 0x0244 +#define N_VIF_COUNT 0x0248 +#define SNAPSHOT_VIF_COUNT 0x024C +#define FP_CRTC_H_TOTAL_DISP 0x0250 +#define FP_CRTC_V_TOTAL_DISP 0x0254 +#define CRT_CRTC_H_SYNC_STRT_WID 0x0258 +#define CRT_CRTC_V_SYNC_STRT_WID 0x025C +#define CUR_OFFSET 0x0260 +#define CUR_HORZ_VERT_POSN 0x0264 +#define CUR_HORZ_VERT_OFF 0x0268 +#define CUR_CLR0 0x026C +#define CUR_CLR1 0x0270 +#define FP_HORZ_VERT_ACTIVE 0x0278 +#define CRTC_MORE_CNTL 0x027C +#define DAC_EXT_CNTL 0x0280 +#define FP_GEN_CNTL 0x0284 +#define FP_HORZ_STRETCH 0x028C +#define FP_VERT_STRETCH 0x0290 +#define FP_H_SYNC_STRT_WID 0x02C4 +#define FP_V_SYNC_STRT_WID 0x02C8 +#define AUX_WINDOW_HORZ_CNTL 0x02D8 +#define AUX_WINDOW_VERT_CNTL 0x02DC +#define DDA_CONFIG 0x02e0 +#define DDA_ON_OFF 0x02e4 +#define GRPH_BUFFER_CNTL 0x02F0 +#define VGA_BUFFER_CNTL 0x02F4 +#define OV0_Y_X_START 0x0400 +#define OV0_Y_X_END 0x0404 +#define OV0_PIPELINE_CNTL 0x0408 +#define OV0_REG_LOAD_CNTL 0x0410 +#define OV0_SCALE_CNTL 0x0420 +#define OV0_V_INC 0x0424 +#define OV0_P1_V_ACCUM_INIT 0x0428 +#define OV0_P23_V_ACCUM_INIT 0x042C +#define OV0_P1_BLANK_LINES_AT_TOP 0x0430 +#define OV0_P23_BLANK_LINES_AT_TOP 0x0434 +#define OV0_BASE_ADDR 0x043C +#define OV0_VID_BUF0_BASE_ADRS 0x0440 +#define OV0_VID_BUF1_BASE_ADRS 0x0444 +#define OV0_VID_BUF2_BASE_ADRS 0x0448 +#define OV0_VID_BUF3_BASE_ADRS 0x044C +#define OV0_VID_BUF4_BASE_ADRS 0x0450 +#define OV0_VID_BUF5_BASE_ADRS 0x0454 +#define OV0_VID_BUF_PITCH0_VALUE 0x0460 +#define OV0_VID_BUF_PITCH1_VALUE 0x0464 +#define OV0_AUTO_FLIP_CNTRL 0x0470 +#define OV0_DEINTERLACE_PATTERN 0x0474 +#define OV0_SUBMIT_HISTORY 0x0478 +#define OV0_H_INC 0x0480 +#define OV0_STEP_BY 0x0484 +#define OV0_P1_H_ACCUM_INIT 0x0488 +#define OV0_P23_H_ACCUM_INIT 0x048C +#define OV0_P1_X_START_END 0x0494 +#define OV0_P2_X_START_END 0x0498 +#define OV0_P3_X_START_END 0x049C +#define OV0_FILTER_CNTL 0x04A0 +#define OV0_FOUR_TAP_COEF_0 0x04B0 +#define OV0_FOUR_TAP_COEF_1 0x04B4 +#define OV0_FOUR_TAP_COEF_2 0x04B8 +#define OV0_FOUR_TAP_COEF_3 0x04BC +#define OV0_FOUR_TAP_COEF_4 0x04C0 +#define OV0_FLAG_CNTRL 0x04DC +#define OV0_SLICE_CNTL 0x04E0 +#define OV0_VID_KEY_CLR_LOW 0x04E4 +#define OV0_VID_KEY_CLR_HIGH 0x04E8 +#define OV0_GRPH_KEY_CLR_LOW 0x04EC +#define OV0_GRPH_KEY_CLR_HIGH 0x04F0 +#define OV0_KEY_CNTL 0x04F4 +#define OV0_TEST 0x04F8 +#define SUBPIC_CNTL 0x0540 +#define SUBPIC_DEFCOLCON 0x0544 +#define SUBPIC_Y_X_START 0x054C +#define SUBPIC_Y_X_END 0x0550 +#define SUBPIC_V_INC 0x0554 +#define SUBPIC_H_INC 0x0558 +#define SUBPIC_BUF0_OFFSET 0x055C +#define SUBPIC_BUF1_OFFSET 0x0560 +#define SUBPIC_LC0_OFFSET 0x0564 +#define SUBPIC_LC1_OFFSET 0x0568 +#define SUBPIC_PITCH 0x056C +#define SUBPIC_BTN_HLI_COLCON 0x0570 +#define SUBPIC_BTN_HLI_Y_X_START 0x0574 +#define SUBPIC_BTN_HLI_Y_X_END 0x0578 +#define SUBPIC_PALETTE_INDEX 0x057C +#define SUBPIC_PALETTE_DATA 0x0580 +#define SUBPIC_H_ACCUM_INIT 0x0584 +#define SUBPIC_V_ACCUM_INIT 0x0588 +#define DISP_MISC_CNTL 0x0D00 +#define DAC_MACRO_CNTL 0x0D04 +#define DISP_PWR_MAN 0x0D08 +#define DISP_TEST_DEBUG_CNTL 0x0D10 +#define DISP_HW_DEBUG 0x0D14 +#define DAC_CRC_SIG1 0x0D18 +#define DAC_CRC_SIG2 0x0D1C +#define OV0_LIN_TRANS_A 0x0D20 +#define OV0_LIN_TRANS_B 0x0D24 +#define OV0_LIN_TRANS_C 0x0D28 +#define OV0_LIN_TRANS_D 0x0D2C +#define OV0_LIN_TRANS_E 0x0D30 +#define OV0_LIN_TRANS_F 0x0D34 +#define OV0_GAMMA_0_F 0x0D40 +#define OV0_GAMMA_10_1F 0x0D44 +#define OV0_GAMMA_20_3F 0x0D48 +#define OV0_GAMMA_40_7F 0x0D4C +#define OV0_GAMMA_380_3BF 0x0D50 +#define OV0_GAMMA_3C0_3FF 0x0D54 +#define DISP_MERGE_CNTL 0x0D60 +#define DISP_OUTPUT_CNTL 0x0D64 +#define DISP_LIN_TRANS_GRPH_A 0x0D80 +#define DISP_LIN_TRANS_GRPH_B 0x0D84 +#define DISP_LIN_TRANS_GRPH_C 0x0D88 +#define DISP_LIN_TRANS_GRPH_D 0x0D8C +#define DISP_LIN_TRANS_GRPH_E 0x0D90 +#define DISP_LIN_TRANS_GRPH_F 0x0D94 +#define DISP_LIN_TRANS_VID_A 0x0D98 +#define DISP_LIN_TRANS_VID_B 0x0D9C +#define DISP_LIN_TRANS_VID_C 0x0DA0 +#define DISP_LIN_TRANS_VID_D 0x0DA4 +#define DISP_LIN_TRANS_VID_E 0x0DA8 +#define DISP_LIN_TRANS_VID_F 0x0DAC +#define RMX_HORZ_FILTER_0TAP_COEF 0x0DB0 +#define RMX_HORZ_FILTER_1TAP_COEF 0x0DB4 +#define RMX_HORZ_FILTER_2TAP_COEF 0x0DB8 +#define RMX_HORZ_PHASE 0x0DBC +#define DAC_EMBEDDED_SYNC_CNTL 0x0DC0 +#define DAC_BROAD_PULSE 0x0DC4 +#define DAC_SKEW_CLKS 0x0DC8 +#define DAC_INCR 0x0DCC +#define DAC_NEG_SYNC_LEVEL 0x0DD0 +#define DAC_POS_SYNC_LEVEL 0x0DD4 +#define DAC_BLANK_LEVEL 0x0DD8 +#define CLOCK_CNTL_INDEX 0x0008 +#define CLOCK_CNTL_DATA 0x000C +#define CP_RB_CNTL 0x0704 +#define CP_RB_BASE 0x0700 +#define CP_RB_RPTR_ADDR 0x070C +#define CP_RB_RPTR 0x0710 +#define CP_RB_WPTR 0x0714 +#define CP_RB_WPTR_DELAY 0x0718 +#define CP_IB_BASE 0x0738 +#define CP_IB_BUFSZ 0x073C +#define SCRATCH_REG0 0x15E0 +#define GUI_SCRATCH_REG0 0x15E0 +#define SCRATCH_REG1 0x15E4 +#define GUI_SCRATCH_REG1 0x15E4 +#define SCRATCH_REG2 0x15E8 +#define GUI_SCRATCH_REG2 0x15E8 +#define SCRATCH_REG3 0x15EC +#define GUI_SCRATCH_REG3 0x15EC +#define SCRATCH_REG4 0x15F0 +#define GUI_SCRATCH_REG4 0x15F0 +#define SCRATCH_REG5 0x15F4 +#define GUI_SCRATCH_REG5 0x15F4 +#define SCRATCH_UMSK 0x0770 +#define SCRATCH_ADDR 0x0774 +#define DP_BRUSH_FRGD_CLR 0x147C +#define DP_BRUSH_BKGD_CLR 0x1478 +#define DST_LINE_START 0x1600 +#define DST_LINE_END 0x1604 +#define SRC_OFFSET 0x15AC +#define SRC_PITCH 0x15B0 +#define SRC_TILE 0x1704 +#define SRC_PITCH_OFFSET 0x1428 +#define SRC_X 0x1414 +#define SRC_Y 0x1418 +#define SRC_X_Y 0x1590 +#define SRC_Y_X 0x1434 +#define DST_Y_X 0x1438 +#define DST_WIDTH_HEIGHT 0x1598 +#define DST_HEIGHT_WIDTH 0x143c +#define SRC_CLUT_ADDRESS 0x1780 +#define SRC_CLUT_DATA 0x1784 +#define SRC_CLUT_DATA_RD 0x1788 +#define HOST_DATA0 0x17C0 +#define HOST_DATA1 0x17C4 +#define HOST_DATA2 0x17C8 +#define HOST_DATA3 0x17CC +#define HOST_DATA4 0x17D0 +#define HOST_DATA5 0x17D4 +#define HOST_DATA6 0x17D8 +#define HOST_DATA7 0x17DC +#define HOST_DATA_LAST 0x17E0 +#define DP_SRC_ENDIAN 0x15D4 +#define DP_SRC_FRGD_CLR 0x15D8 +#define DP_SRC_BKGD_CLR 0x15DC +#define SC_LEFT 0x1640 +#define SC_RIGHT 0x1644 +#define SC_TOP 0x1648 +#define SC_BOTTOM 0x164C +#define SRC_SC_RIGHT 0x1654 +#define SRC_SC_BOTTOM 0x165C +#define DP_CNTL 0x16C0 +#define DP_CNTL_XDIR_YDIR_YMAJOR 0x16D0 +#define DP_DATATYPE 0x16C4 +#define DP_MIX 0x16C8 +#define DP_WRITE_MSK 0x16CC +#define DP_XOP 0x17F8 +#define CLR_CMP_CLR_SRC 0x15C4 +#define CLR_CMP_CLR_DST 0x15C8 +#define CLR_CMP_CNTL 0x15C0 +#define CLR_CMP_MSK 0x15CC +#define DSTCACHE_MODE 0x1710 +#define DSTCACHE_CTLSTAT 0x1714 +#define DEFAULT_PITCH_OFFSET 0x16E0 +#define DEFAULT_SC_BOTTOM_RIGHT 0x16E8 +#define DP_GUI_MASTER_CNTL 0x146C +#define SC_TOP_LEFT 0x16EC +#define SC_BOTTOM_RIGHT 0x16F0 +#define SRC_SC_BOTTOM_RIGHT 0x16F4 +#define RB2D_DSTCACHE_CTLSTAT 0x342C + + +#define CLK_PIN_CNTL 0x0001 +#define PPLL_CNTL 0x0002 +#define PPLL_REF_DIV 0x0003 +#define PPLL_DIV_0 0x0004 +#define PPLL_DIV_1 0x0005 +#define PPLL_DIV_2 0x0006 +#define PPLL_DIV_3 0x0007 +#define VCLK_ECP_CNTL 0x0008 +#define HTOTAL_CNTL 0x0009 +#define M_SPLL_REF_FB_DIV 0x000a +#define AGP_PLL_CNTL 0x000b +#define SPLL_CNTL 0x000c +#define SCLK_CNTL 0x000d +#define MPLL_CNTL 0x000e +#define MCLK_CNTL 0x0012 +#define AGP_PLL_CNTL 0x000b +#define PLL_TEST_CNTL 0x0013 + + +/* MCLK_CNTL bit constants */ +#define FORCEON_MCLKA (1 << 16) +#define FORCEON_MCLKB (1 << 17) +#define FORCEON_YCLKA (1 << 18) +#define FORCEON_YCLKB (1 << 19) +#define FORCEON_MC (1 << 20) +#define FORCEON_AIC (1 << 21) + + +/* BUS_CNTL bit constants */ +#define BUS_DBL_RESYNC 0x00000001 +#define BUS_MSTR_RESET 0x00000002 +#define BUS_FLUSH_BUF 0x00000004 +#define BUS_STOP_REQ_DIS 0x00000008 +#define BUS_ROTATION_DIS 0x00000010 +#define BUS_MASTER_DIS 0x00000040 +#define BUS_ROM_WRT_EN 0x00000080 +#define BUS_DIS_ROM 0x00001000 +#define BUS_PCI_READ_RETRY_EN 0x00002000 +#define BUS_AGP_AD_STEPPING_EN 0x00004000 +#define BUS_PCI_WRT_RETRY_EN 0x00008000 +#define BUS_MSTR_RD_MULT 0x00100000 +#define BUS_MSTR_RD_LINE 0x00200000 +#define BUS_SUSPEND 0x00400000 +#define LAT_16X 0x00800000 +#define BUS_RD_DISCARD_EN 0x01000000 +#define BUS_RD_ABORT_EN 0x02000000 +#define BUS_MSTR_WS 0x04000000 +#define BUS_PARKING_DIS 0x08000000 +#define BUS_MSTR_DISCONNECT_EN 0x10000000 +#define BUS_WRT_BURST 0x20000000 +#define BUS_READ_BURST 0x40000000 +#define BUS_RDY_READ_DLY 0x80000000 + + +/* CLOCK_CNTL_INDEX bit constants */ +#define PLL_WR_EN 0x00000080 + +/* CONFIG_CNTL bit constants */ +#define CFG_VGA_RAM_EN 0x00000100 + +/* CRTC_EXT_CNTL bit constants */ +#define VGA_ATI_LINEAR 0x00000008 +#define VGA_128KAP_PAGING 0x00000010 +#define XCRT_CNT_EN (1 << 6) +#define CRTC_HSYNC_DIS (1 << 8) +#define CRTC_VSYNC_DIS (1 << 9) +#define CRTC_DISPLAY_DIS (1 << 10) + + +/* DSTCACHE_CTLSTAT bit constants */ +#define RB2D_DC_FLUSH (3 << 0) +#define RB2D_DC_FLUSH_ALL 0xf +#define RB2D_DC_BUSY (1 << 31) + + +/* CRTC_GEN_CNTL bit constants */ +#define CRTC_DBL_SCAN_EN 0x00000001 +#define CRTC_CUR_EN 0x00010000 +#define CRTC_EXT_DISP_EN (1 << 24) +#define CRTC_EN (1 << 25) + +/* CRTC_STATUS bit constants */ +#define CRTC_VBLANK 0x00000001 + +/* CUR_OFFSET, CUR_HORZ_VERT_POSN, CUR_HORZ_VERT_OFF bit constants */ +#define CUR_LOCK 0x80000000 + +/* DAC_CNTL bit constants */ +#define DAC_8BIT_EN 0x00000100 +#define DAC_4BPP_PIX_ORDER 0x00000200 +#define DAC_CRC_EN 0x00080000 +#define DAC_MASK_ALL (0xff << 24) +#define DAC_VGA_ADR_EN (1 << 13) +#define DAC_RANGE_CNTL (3 << 0) +#define DAC_BLANKING (1 << 2) + +/* GEN_RESET_CNTL bit constants */ +#define SOFT_RESET_GUI 0x00000001 +#define SOFT_RESET_VCLK 0x00000100 +#define SOFT_RESET_PCLK 0x00000200 +#define SOFT_RESET_ECP 0x00000400 +#define SOFT_RESET_DISPENG_XCLK 0x00000800 + +/* MEM_CNTL bit constants */ +#define MEM_CTLR_STATUS_IDLE 0x00000000 +#define MEM_CTLR_STATUS_BUSY 0x00100000 +#define MEM_SEQNCR_STATUS_IDLE 0x00000000 +#define MEM_SEQNCR_STATUS_BUSY 0x00200000 +#define MEM_ARBITER_STATUS_IDLE 0x00000000 +#define MEM_ARBITER_STATUS_BUSY 0x00400000 +#define MEM_REQ_UNLOCK 0x00000000 +#define MEM_REQ_LOCK 0x00800000 + + +/* RBBM_SOFT_RESET bit constants */ +#define SOFT_RESET_CP (1 << 0) +#define SOFT_RESET_HI (1 << 1) +#define SOFT_RESET_SE (1 << 2) +#define SOFT_RESET_RE (1 << 3) +#define SOFT_RESET_PP (1 << 4) +#define SOFT_RESET_E2 (1 << 5) +#define SOFT_RESET_RB (1 << 6) +#define SOFT_RESET_HDP (1 << 7) + + +/* DEFAULT_SC_BOTTOM_RIGHT bit constants */ +#define DEFAULT_SC_RIGHT_MAX (0x1fff << 0) +#define DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) + +/* MM_INDEX bit constants */ +#define MM_APER 0x80000000 + +/* CLR_CMP_CNTL bit constants */ +#define COMPARE_SRC_FALSE 0x00000000 +#define COMPARE_SRC_TRUE 0x00000001 +#define COMPARE_SRC_NOT_EQUAL 0x00000004 +#define COMPARE_SRC_EQUAL 0x00000005 +#define COMPARE_SRC_EQUAL_FLIP 0x00000007 +#define COMPARE_DST_FALSE 0x00000000 +#define COMPARE_DST_TRUE 0x00000100 +#define COMPARE_DST_NOT_EQUAL 0x00000400 +#define COMPARE_DST_EQUAL 0x00000500 +#define COMPARE_DESTINATION 0x00000000 +#define COMPARE_SOURCE 0x01000000 +#define COMPARE_SRC_AND_DST 0x02000000 + + +/* DP_CNTL bit constants */ +#define DST_X_RIGHT_TO_LEFT 0x00000000 +#define DST_X_LEFT_TO_RIGHT 0x00000001 +#define DST_Y_BOTTOM_TO_TOP 0x00000000 +#define DST_Y_TOP_TO_BOTTOM 0x00000002 +#define DST_X_MAJOR 0x00000000 +#define DST_Y_MAJOR 0x00000004 +#define DST_X_TILE 0x00000008 +#define DST_Y_TILE 0x00000010 +#define DST_LAST_PEL 0x00000020 +#define DST_TRAIL_X_RIGHT_TO_LEFT 0x00000000 +#define DST_TRAIL_X_LEFT_TO_RIGHT 0x00000040 +#define DST_TRAP_FILL_RIGHT_TO_LEFT 0x00000000 +#define DST_TRAP_FILL_LEFT_TO_RIGHT 0x00000080 +#define DST_BRES_SIGN 0x00000100 +#define DST_HOST_BIG_ENDIAN_EN 0x00000200 +#define DST_POLYLINE_NONLAST 0x00008000 +#define DST_RASTER_STALL 0x00010000 +#define DST_POLY_EDGE 0x00040000 + + +/* DP_CNTL_YDIR_XDIR_YMAJOR bit constants (short version of DP_CNTL) */ +#define DST_X_MAJOR_S 0x00000000 +#define DST_Y_MAJOR_S 0x00000001 +#define DST_Y_BOTTOM_TO_TOP_S 0x00000000 +#define DST_Y_TOP_TO_BOTTOM_S 0x00008000 +#define DST_X_RIGHT_TO_LEFT_S 0x00000000 +#define DST_X_LEFT_TO_RIGHT_S 0x80000000 + + +/* DP_DATATYPE bit constants */ +#define DST_8BPP 0x00000002 +#define DST_15BPP 0x00000003 +#define DST_16BPP 0x00000004 +#define DST_24BPP 0x00000005 +#define DST_32BPP 0x00000006 +#define DST_8BPP_RGB332 0x00000007 +#define DST_8BPP_Y8 0x00000008 +#define DST_8BPP_RGB8 0x00000009 +#define DST_16BPP_VYUY422 0x0000000b +#define DST_16BPP_YVYU422 0x0000000c +#define DST_32BPP_AYUV444 0x0000000e +#define DST_16BPP_ARGB4444 0x0000000f +#define BRUSH_SOLIDCOLOR 0x00000d00 +#define SRC_MONO 0x00000000 +#define SRC_MONO_LBKGD 0x00010000 +#define SRC_DSTCOLOR 0x00030000 +#define BYTE_ORDER_MSB_TO_LSB 0x00000000 +#define BYTE_ORDER_LSB_TO_MSB 0x40000000 +#define DP_CONVERSION_TEMP 0x80000000 +#define HOST_BIG_ENDIAN_EN (1 << 29) + + +/* DP_GUI_MASTER_CNTL bit constants */ +#define GMC_SRC_PITCH_OFFSET_DEFAULT 0x00000000 +#define GMC_SRC_PITCH_OFFSET_LEAVE 0x00000001 +#define GMC_DST_PITCH_OFFSET_DEFAULT 0x00000000 +#define GMC_DST_PITCH_OFFSET_LEAVE 0x00000002 +#define GMC_SRC_CLIP_DEFAULT 0x00000000 +#define GMC_SRC_CLIP_LEAVE 0x00000004 +#define GMC_DST_CLIP_DEFAULT 0x00000000 +#define GMC_DST_CLIP_LEAVE 0x00000008 +#define GMC_BRUSH_8x8MONO 0x00000000 +#define GMC_BRUSH_8x8MONO_LBKGD 0x00000010 +#define GMC_BRUSH_8x1MONO 0x00000020 +#define GMC_BRUSH_8x1MONO_LBKGD 0x00000030 +#define GMC_BRUSH_1x8MONO 0x00000040 +#define GMC_BRUSH_1x8MONO_LBKGD 0x00000050 +#define GMC_BRUSH_32x1MONO 0x00000060 +#define GMC_BRUSH_32x1MONO_LBKGD 0x00000070 +#define GMC_BRUSH_32x32MONO 0x00000080 +#define GMC_BRUSH_32x32MONO_LBKGD 0x00000090 +#define GMC_BRUSH_8x8COLOR 0x000000a0 +#define GMC_BRUSH_8x1COLOR 0x000000b0 +#define GMC_BRUSH_1x8COLOR 0x000000c0 +#define GMC_BRUSH_SOLID_COLOR 0x000000d0 +#define GMC_DST_8BPP 0x00000200 +#define GMC_DST_15BPP 0x00000300 +#define GMC_DST_16BPP 0x00000400 +#define GMC_DST_24BPP 0x00000500 +#define GMC_DST_32BPP 0x00000600 +#define GMC_DST_8BPP_RGB332 0x00000700 +#define GMC_DST_8BPP_Y8 0x00000800 +#define GMC_DST_8BPP_RGB8 0x00000900 +#define GMC_DST_16BPP_VYUY422 0x00000b00 +#define GMC_DST_16BPP_YVYU422 0x00000c00 +#define GMC_DST_32BPP_AYUV444 0x00000e00 +#define GMC_DST_16BPP_ARGB4444 0x00000f00 +#define GMC_SRC_MONO 0x00000000 +#define GMC_SRC_MONO_LBKGD 0x00001000 +#define GMC_SRC_DSTCOLOR 0x00003000 +#define GMC_BYTE_ORDER_MSB_TO_LSB 0x00000000 +#define GMC_BYTE_ORDER_LSB_TO_MSB 0x00004000 +#define GMC_DP_CONVERSION_TEMP_9300 0x00008000 +#define GMC_DP_CONVERSION_TEMP_6500 0x00000000 +#define GMC_DP_SRC_RECT 0x02000000 +#define GMC_DP_SRC_HOST 0x03000000 +#define GMC_DP_SRC_HOST_BYTEALIGN 0x04000000 +#define GMC_3D_FCN_EN_CLR 0x00000000 +#define GMC_3D_FCN_EN_SET 0x08000000 +#define GMC_DST_CLR_CMP_FCN_LEAVE 0x00000000 +#define GMC_DST_CLR_CMP_FCN_CLEAR 0x10000000 +#define GMC_AUX_CLIP_LEAVE 0x00000000 +#define GMC_AUX_CLIP_CLEAR 0x20000000 +#define GMC_WRITE_MASK_LEAVE 0x00000000 +#define GMC_WRITE_MASK_SET 0x40000000 +#define GMC_CLR_CMP_CNTL_DIS (1 << 28) +#define GMC_SRC_DATATYPE_COLOR (3 << 12) +#define ROP3_S 0x00cc0000 +#define ROP3_SRCCOPY 0x00cc0000 +#define ROP3_P 0x00f00000 +#define ROP3_PATCOPY 0x00f00000 +#define DP_SRC_SOURCE_MASK (7 << 24) +#define GMC_BRUSH_NONE (15 << 4) +#define DP_SRC_SOURCE_MEMORY (2 << 24) +#define GMC_BRUSH_SOLIDCOLOR 0x000000d0 + +/* DP_MIX bit constants */ +#define DP_SRC_RECT 0x00000200 +#define DP_SRC_HOST 0x00000300 +#define DP_SRC_HOST_BYTEALIGN 0x00000400 + + +/* masks */ + +#define CONFIG_MEMSIZE_MASK 0x1f000000 +#define MEM_CFG_TYPE 0x40000000 +#define DST_OFFSET_MASK 0x003fffff +#define DST_PITCH_MASK 0x3fc00000 +#define DEFAULT_TILE_MASK 0xc0000000 +#define PPLL_DIV_SEL_MASK 0x00000300 +#define PPLL_RESET 0x00000001 +#define PPLL_ATOMIC_UPDATE_EN 0x00010000 +#define PPLL_REF_DIV_MASK 0x000003ff +#define PPLL_FB3_DIV_MASK 0x000007ff +#define PPLL_POST3_DIV_MASK 0x00070000 +#define PPLL_ATOMIC_UPDATE_R 0x00008000 +#define PPLL_ATOMIC_UPDATE_W 0x00008000 +#define PPLL_VGA_ATOMIC_UPDATE_EN 0x00020000 + +#define GUI_ACTIVE 0x80000000 + +#endif /* _RADEON_H */ + diff -u --recursive --new-file v2.4.9/linux/drivers/video/radeonfb.c linux/drivers/video/radeonfb.c --- v2.4.9/linux/drivers/video/radeonfb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/video/radeonfb.c Fri Sep 7 09:28:38 2001 @@ -0,0 +1,1907 @@ +/* + * drivers/video/radeonfb.c + * framebuffer driver for ATI Radeon chipset video boards + * + * Copyright 2000 Ani Joshi + * + * + * ChangeLog: + * 2000-08-03 initial version 0.0.1 + * 2000-09-10 more bug fixes, public release 0.0.5 + * 2001-02-19 mode bug fixes, 0.0.7 + * 2001-07-05 fixed scrolling issues, engine initialization, + * and minor mode tweaking, 0.0.9 + * + * + * Special thanks to ATI DevRel team for their hardware donations. + * + */ + + +#define RADEON_VERSION "0.0.9" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include