diff -u --recursive --new-file v2.4.9/linux/CREDITS linux/CREDITS --- v2.4.9/linux/CREDITS Mon Aug 27 12:41:37 2001 +++ linux/CREDITS Sun Sep 9 10:43:02 2001 @@ -400,13 +400,12 @@ S: USA N: Peter Braam -E: braam@cs.cmu.edu -W: http://coda.cs.cmu.edu/~braam -D: Coda Filesystem -S: Dept of Computer Science -S: 5000 Forbes Avenue -S: Pittsburgh, Pennsylvania 15213 -S: USA +E: braam@clusterfs.com +W: http://www.clusterfs.com/ +D: Coda & InterMezzo filesystems +S: 181 McNeil +S: Canmore, AB +S: Canada, T1W 2R9 N: Ryan Bradetich E: rbradetich@uswest.net @@ -535,6 +534,12 @@ S: Stanford, California 94305 S: USA +N: Randolph Chung +E: tausq@debian.org +D: Linux/PA-RISC hacker +S: Fremont, CA 94538 +S: USA + N: Juan Jose Ciarlante W: http://juanjox.kernelnotes.org/ E: jjciarla@raiz.uncu.edu.ar @@ -633,10 +638,11 @@ S: USA N: Frank Davis +E: fdavis@si.rr.com E: fdavis112@juno.com D: Various kernel patches S: 8 Lakeview Terr. -S: Kerhonskon, NY 12446 +S: Kerhonkson, NY 12446 S: USA N: Wayne Davison @@ -714,7 +720,7 @@ N: Oleg Drokin E: green@ccssu.crimea.ua W: http://www.ccssu.crimea.ua/~green -D: Cleaning up sound drivers. +D: Cleaning up sound drivers, SA1100 Watchdog. S: Skvoznoy per., 14a S: Evpatoria S: Crimea 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/Changes linux/Documentation/Changes --- v2.4.9/linux/Documentation/Changes Tue Jul 3 17:08:18 2001 +++ linux/Documentation/Changes Mon Sep 17 23:10:44 2001 @@ -48,7 +48,7 @@ Card) hardware, for example, you probably needn't concern yourself with pcmcia-cs. -o Gnu C 2.91.66 # gcc --version +o Gnu C 2.95.3 # gcc --version o Gnu make 3.77 # make --version o binutils 2.9.1.0.25 # ld -v o util-linux 2.10o # fdformat --version @@ -70,17 +70,23 @@ necessarily to users of other CPUs. Users of other CPUs should obtain information about their gcc version requirements from another source. -The recommended compiler for the kernel is egcs 1.1.2 (gcc 2.91.66), and it -should be used when you need absolute stability. You may use gcc 2.95.x -instead if you wish, although it may cause problems. Later versions of gcc -have not received much testing for Linux kernel compilation, and there are +The recommended compiler for the kernel is gcc 2.95.3 or .4, and it +should be used when you need absolute stability. You may use gcc 3.0.x +instead if you wish, although it may cause problems. Later versions of gcc +have not received much testing for Linux kernel compilation, and there are almost certainly bugs (mainly, but not exclusively, in the kernel) that will need to be fixed in order to use these compilers. In any case, using pgcc instead of egcs or plain gcc is just asking for trouble. Note that gcc 2.7.2.3 is no longer a supported kernel compiler. The kernel no longer works around bugs in gcc 2.7.2.3 and, in fact, will refuse to -be compiled with it. +be compiled with it. egcs-1.1.2 has register allocation problems in very +obscure cases. We have ensured the kernel does not trip these in any known +situation. The 2.5 tree is likely to drop egcs-1.1.2 workarounds. + +The Red Hat gcc 2.96 compiler subtree can also be used to build this tree. +You should ensure you use gcc-2.96-74 or later. gcc-2.96-54 will not build +the kernel correctly. In addition, please pay attention to compiler optimization. Anything greater than -O2 may not be wise. Similarly, if you choose to use gcc-2.95.x diff -u --recursive --new-file v2.4.9/linux/Documentation/CodingStyle linux/Documentation/CodingStyle --- v2.4.9/linux/Documentation/CodingStyle Wed Sep 29 13:59:12 1999 +++ linux/Documentation/CodingStyle Sun Sep 9 16:40:43 2001 @@ -233,3 +233,34 @@ stable. All options that are known to trash data (experimental write- support for file-systems, for instance) should be denoted (DANGEROUS), other Experimental options should be denoted (EXPERIMENTAL). + + + Chapter 8: Data structures + +Data structures that have visibility outside the single-threaded +environment they are created and destroyed in should always have +reference counts. In the kernel, garbage collection doesn't exist (and +outside the kernel garbage collection is slow and inefficient), which +means that you absolutely _have_ to reference count all your uses. + +Reference counting means that you can avoid locking, and allows multiple +users to have access to the data structure in parallel - and not having +to worry about the structure suddenly going away from under them just +because they slept or did something else for a while. + +Note that locking is _not_ a replacement for reference counting. +Locking is used to keep data structures coherent, while reference +counting is a memory management technique. Usually both are needed, and +they are not to be confused with each other. + +Many data structures can indeed have two levels of reference counting, +when there are users of different "classes". The subclass count counts +the number of subclass users, and decrements the global count just once +when the subclass count goes to zero. + +Examples of this kind of "multi-reference-counting" can be found in +memory management ("struct mm_struct": mm_users and mm_count), and in +filesystem code ("struct super_block": s_count and s_active). + +Remember: if another thread can find your data structure, and you don't +have a reference count on it, you almost certainly have a bug. 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 15 22:19:46 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 @@ -2551,7 +2581,7 @@ AMD Irongate support CONFIG_AGP_AMD This option gives you AGP support for the GLX component of the - XFree86 4.x on AMD Irongate chipset. + XFree86 4.x on AMD Irongate and 761 chipsets. For the moment, you should probably say N, unless you want to test the GLX component for XFree86 3.3.6, which can be downloaded from @@ -11220,6 +11250,17 @@ The module will be called keyspan_pda.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +USB Xircom / Entregra Single Port Serial Driver +CONFIG_USB_SERIAL_XIRCOM + Say Y here if you want to use a Xircom or Entregra single port USB to + serial converter device. This driver makes use of firmware + developed from scratch by Brian Warner. + + 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 keyspan_pda.o. If you want to compile it + as a module, say M here and read . + USB Keyspan USA-xxx Serial Driver CONFIG_USB_SERIAL_KEYSPAN Say Y here if you want to use Keyspan USB to serial converter @@ -11478,6 +11519,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 +11612,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 +11698,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 +15852,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 +17066,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 +17089,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 +17289,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 Sun Sep 16 21:23:15 2001 @@ -24,10 +24,10 @@ html: $(HTML) %.eps: %.fig - -fig2dev -Leps $< $@ + fig2dev -Leps $< $@ %.jpeg: %.fig - -fig2dev -Ljpeg $< $@ + fig2dev -Ljpeg $< $@ %.sgml: %.c echo "" > $@ @@ -88,6 +88,7 @@ $(TOPDIR)/arch/i386/kernel/mca.c \ $(TOPDIR)/arch/i386/kernel/mtrr.c \ $(TOPDIR)/drivers/char/misc.c \ + $(TOPDIR)/kernel/printk.c \ $(TOPDIR)/drivers/net/net_init.c \ $(TOPDIR)/drivers/net/8390.c \ $(TOPDIR)/drivers/char/serial.c \ @@ -129,7 +130,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/kernel-api.tmpl linux/Documentation/DocBook/kernel-api.tmpl --- v2.4.9/linux/Documentation/DocBook/kernel-api.tmpl Thu May 24 15:14:08 2001 +++ linux/Documentation/DocBook/kernel-api.tmpl Sun Sep 9 12:00:55 2001 @@ -187,6 +187,11 @@ !Edrivers/block/ll_rw_blk.c + + Partition Handling +!Edrivers/block/genhd.c + + Miscellaneous Devices !Edrivers/char/misc.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 Tue Sep 11 17:02:46 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,96 @@ ChangeLog ========= + +NTFS 1.1.19: + - Fixed ntfs_getdir_unsorted(), ntfs_readdir() and ntfs_printcb() to + cope with arbitrary cluster sizes. Very important for Win2k+. Also, + make them detect directories which are too large and truncate the + enumeration pretending end of directory was reached. Detect more + error conditions and overflows. All this fixes the problem where the + driver could end up in an infinite loop under certain circumstances. + - Fixed potential memory leaks in Unicode conversion functions and + setup correct NULL return values. + +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/input/cs461x.txt linux/Documentation/input/cs461x.txt --- v2.4.9/linux/Documentation/input/cs461x.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/input/cs461x.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,45 @@ +Preface. + +This is a new low-level driver to support analog joystick attached to +Crystal SoundFusion CS4610/CS4612/CS4615. This code is based upon +Vortex/Solo drivers as an example of decoration style, and ALSA +0.5.8a kernel drivers as an chipset documentation and samples. + +This version does not have cooked mode support; the basic code +is present here, but have not tested completely. The button analysis +is completed in this mode, but the axis movement is not. + +Raw mode works fine with analog joystick front-end driver and cs461x +driver as a backend. I've tested this driver with CS4610, 4-axis and +4-button joystick; I mean the jstest utility. Also I've tried to +play in xracer game using joystick, and the result is better than +keyboard only mode. + +The sensitivity and calibrate quality have not been tested; the two +reasons are performed: the same hardware cannot work under Win95 (blue +screen in VJOYD); I have no documentation on my chip; and the existing +behavior in my case was not raised the requirement of joystick calibration. +So the driver have no code to perform hardware related calibration. + +The patch contains minor changes of Config.in and Makefile files. All +needed code have been moved to one separate file cs461x.c like ns558.c +This driver have the basic support for PCI devices only; there is no +ISA or PnP ISA cards supported. AFAIK the ns558 have support for Crystal +ISA and PnP ISA series. + +The driver works witn ALSA drivers simultaneously. For exmple, the xracer +uses joystick as input device and PCM device as sound output in one time. +There are no sound or input collisions detected. The source code have +comments about them; but I've found the joystick can be initialized +separately of ALSA modules. So, you canm use only one joystick driver +without ALSA drivers. The ALSA drivers are not needed to compile or +run this driver. + +There are no debug information print have been placed in source, and no +specific options required to work this driver. The found chipset parameters +are printed via printk(KERN_INFO "..."), see the /var/log/messages to +inspect cs461x: prefixed messages to determine possible card detection +errors. + +Regards, +Viktor diff -u --recursive --new-file v2.4.9/linux/Documentation/input/ff.txt linux/Documentation/input/ff.txt --- v2.4.9/linux/Documentation/input/ff.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/input/ff.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,194 @@ +Force feedback for Linux. +By Johann Deneux on 2001/04/22. + +---------------------------------------------------------------------------- + +0. Introduction +~~~~~~~~~~~~~~~ +This document describes how to use force feedback devices under Linux. The +goal is not to support these devices as if they were simple input-only devices +(as it is already the case), but to really enable the rendering of force +effects. +At the moment, only I-Force devices are supported, and not officially. That +means I had to find out how the protocol works on my own. Of course, the +information I managed to grasp is far from being complete, and I can not +guarranty that this driver will work for you. +This document only describes the force feedback part of the driver for I-Force +devices. Please read joystick.txt before reading further this document. + +2. Instructions to the user +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Here are instructions on how to compile and use the driver. In fact, this +driver is the normal iforce.o, input.o and evdev.o drivers written by Vojtech +Pavlik, plus additions to support force feedback. + +Before you start, let me WARN you that some devices shake violently during the +initialisation phase. This happens for example with my "AVB Top Shot Pegasus". +To stop this annoying behaviour, move you joystick to its limits. Anyway, you +should keep a hand on your device, in order to avoid it to brake down if +something goes wrong. + +At the kernel's compilation: + - Enable IForce/Serial + - Enable Event interface + +Compile the modules, install them. + +You also need inputattach. + +You then need to insert the modules into the following order: +% modprobe joydev +% modprobe serport +% modprobe iforce +% modprobe evdev +% ./inputattach -ifor $2 & # Only for serial +For convenience, you may use the shell script named "ff" available from +the cvs tree of the Linux Console Project at sourceforge. You can also +retrieve it from http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/. +If you are using USB, you don't need the inputattach step. + +Please check that you have all the /dev/input entries needed: +cd /dev +rm js* +mkdir input +mknod input/js0 c 13 0 +mknod input/js1 c 13 1 +mknod input/js2 c 13 2 +mknod input/js3 c 13 3 +ln -s input/js0 js0 +ln -s input/js1 js1 +ln -s input/js2 js2 +ln -s input/js3 js3 + +mknod input/event0 c 13 64 +mknod input/event1 c 13 65 +mknod input/event2 c 13 66 +mknod input/event3 c 13 67 + +2.1 Does it work ? +~~~~~~~~~~~~~~~~~~ +There is an utility called fftest that will allow you to test the driver. +% fftest /dev/eventXX + +3. Instructions to the developper +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + All interactions are done using the event API. That is, you can use ioctl() +and write() on /dev/input/eventXX. + This information is subject to change. + +3.1 Querying device capabilities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#include +#include + +int ioctl(int file_descriptor, int request, unsigned long *features); + +"request" must be EVIOCGBIT(EV_FF, sizeof(unsigned long)) + +Returns the features supported by the device. features is a bitfield with the +following bits: +- FF_X has an X axis (should allways be the case) +- FF_Y has an Y axis (usually not the case for wheels) +- FF_CONSTANT can render constant force effects +- FF_PERIODIC can render periodic effects (sine, ramp, square...) +- FF_SPRING can simulate the presence of a spring +- FF_FRICTION can simulate friction (aka drag, damper effect...) +- FF_RUMBLE rumble effects (normally the only effect supported by rumble + pads) +- 8 bits from FF_N_EFFECTS_0 containing the number of effects that can be + simultaneously played. + +3.2 Uploading effects to the device +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#include +#include + +int ioctl(int file_descriptor, int request, struct ff_effect *effect); + +"request" must be EVIOCSFF. + +"effect" points to a structure describing the effect to upload. The effect is +uploaded, but not played. +The content of effect may be modified. In particular, its field "id" is set +to the unique id assigned by the driver. This data is required for performing +some operations (removing an effect, controlling the playback). +See for a description of the ff_effect stuct. + +3.3 Removing an effect from the device +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int ioctl(int fd, EVIOCRMFF, effect.id); + +This makes room for new effects in the device's memory. Please note this won't +stop the effect if it was playing. + +3.4 Controlling the playback of effects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Control of playing is done with write(). Below is an example: + +#include +#include + + struct input_event play; + struct input_event stop; + struct ff_effect effect; + int fd; +... + fd = open("/dev/input/eventXX", O_RDWR); +... + /* Play three times */ + play.type = EV_FF; + play.code = effect.id; + play.value = 3; + + write(fd, (const void*) &play, sizeof(play)); +... + /* Stop an effect */ + stop.type = EV_FF; + stop.code = effect.id; + stop.value = 0; + + write(fd, (const void*) &play, sizeof(stop)); + +3.5 Setting the gain +~~~~~~~~~~~~~~~~~~~~ +Not all devices have the same strength. Therefore, users should set a gain +factor depending on how strong they want effects to be. This setting is +persistent accross access to the driver, so you should not care about it if +you are writing games, as another utility probably already set this for you. + +/* Set the gain of the device +int gain; /* between 0 and 100 */ +struct input_event ie; /* structure used to communicate with the driver */ + +ie.type = EV_FF; +ie.code = FF_GAIN; +ie.value = 0xFFFFUL * gain / 100; + +if (write(fd, &ie, sizeof(ie)) == -1) + perror("set gain"); + +3.6 Enabling/Disabling autocenter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The autocenter feature quite disturbs the rendering of effects in my opinion, +and I think it should be an effect, which computation depends on the game +type. But you can enable it if you want. + +int autocenter; /* between 0 and 100 */ +struct input_event ie; + +ie.type = EV_FF; +ie.code = FF_AUTOCENTER; +ie.value = 0xFFFFUL * autocenter / 100; + +if (write(fd, &ie, sizeof(ie)) == -1) + perror("set auto-center"); + +A value of 0 means "no auto-center". + +3.7 Dynamic update of an effect +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This consists in changing some parameters of an effect while it's playing. The +driver currently does not support that. You still have the brute-force method, +which consists in erasing the effect and uploading the updated version. It +actually works pretty well. You don't need to stop-and-start the effect. + diff -u --recursive --new-file v2.4.9/linux/Documentation/input/gameport-programming.txt linux/Documentation/input/gameport-programming.txt --- v2.4.9/linux/Documentation/input/gameport-programming.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/input/gameport-programming.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,189 @@ +$Id: gameport-programming.txt,v 1.3 2001/04/24 13:51:37 vojtech Exp $ + +Programming gameport drivers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. A basic classic gameport +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the gameport doesn't provide more than the inb()/outb() functionality, +the code needed to register it with the joystick drivers is simple: + + struct gameport gameport; + + gameport.io = MY_IO_ADDRESS; + gameport_register_port(&gameport); + +Make sure struct gameport is initialized to 0 in all other fields. The +gameport generic code will take care of the rest. + +If your hardware supports more than one io address, and your driver can +choose which one program the hardware to, starting from the more exotic +addresses is preferred, because the likelyhood of clashing with the standard +0x201 address is smaller. + +Eg. if your driver supports addresses 0x200, 0x208, 0x210 and 0x218, then +0x218 would be the address of first choice. + +If your hardware supports a gameport address that is not mapped to ISA io +space (is above 0x1000), use that one, and don't map the ISA mirror. + +Also, always request_region() on the whole io space occupied by the +gameport. Although only one ioport is really used, the gameport usually +occupies from one to sixteen addresses in the io space. + +Please also consider enabling the gameport on the card in the ->open() +callback if the io is mapped to ISA space - this way it'll occupy the io +space only when something really is using it. Disable it again in the +->close() callback. You also can select the io address in the ->open() +callback, so that it doesn't fail if some of the possible addresses are +already occupied by other gameports. + +2. Memory mapped gameport +~~~~~~~~~~~~~~~~~~~~~~~~~ + +When a gameport can be accessed through MMIO, this way is preferred, because +it is faster, allowing more reads per second. Registering such a gameport +isn't as easy as a basic IO one, but not so much complex: + + struct gameport gameport; + + void my_trigger(struct gameport *gameport) + { + my_mmio = 0xff; + } + + unsigned char my_read(struct gameport *gameport) + { + return my_mmio; + } + + gameport.read = my_read; + gameport.trigger = my_trigger; + gameport_register_port(&gameport); + +3. Cooked mode gameport +~~~~~~~~~~~~~~~~~~~~~~~ + +There are gameports that can report the axis values as numbers, that means +the driver doesn't have to measure them the old way - an ADC is built into +the gameport. To register a cooked gameport: + + struct gameport gameport; + + int my_cooked_read(struct gameport *gameport, int *axes, int *buttons) + { + int i; + + for (i = 0; i < 4; i++) + axes[i] = my_mmio[i]; + buttons[i] = my_mmio[4]; + } + + int my_open(struct gameport *gameport, int mode) + { + return -(mode != GAMEPORT_MODE_COOKED); + } + + gameport.cooked_read = my_cooked_read; + gameport.open = my_open; + gameport.fuzz = 8; + gameport_register_port(&gameport); + +The only confusing thing here is the fuzz value. Best determined by +experimentation, it is the amount of noise in the ADC data. Perfect +gameports can set this to zero, most common have fuzz between 8 and 32. +See analog.c and input.c for handling of fuzz - the fuzz value determines +the size of a gaussian filter window that is used to eliminate the noise +in the data. + +4. More complex gameports +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Gameports can support both raw and cooked modes. In that case combine either +examples 1+2 or 1+3. Gameports can support internal calibration - see below, +and also lightning.c and analog.c on how that works. If your driver supports +more than one gameport instance simultaneously, use the ->private member of +the gameport struct to point to your data. + +5. Unregistering a gameport +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Simple: + +gameport_unregister_port(&gameport); + +6. The gameport structure +~~~~~~~~~~~~~~~~~~~~~~~~~ + +struct gameport { + + void *private; + +A private pointer for free use in the gameport driver. (Not the joystick +driver!) + + int number; + +Number assigned to the gameport when registered. Informational purpose only. + + int io; + +I/O address for use with raw mode. You have to either set this, or ->read() +to some value if your gameport supports raw mode. + + int speed; + +Raw mode speed of the gameport reads in thousands of reads per second. + + int fuzz; + +If the gameport supports cooked mode, this should be set to a value that +represents the amount of noise in the data. See section 3. + + void (*trigger)(struct gameport *); + +Trigger. This function should trigger the ns558 oneshots. If set to NULL, +outb(0xff, io) will be used. + + unsigned char (*read)(struct gameport *); + +Read the buttons and ns558 oneshot bits. If set to NULL, inb(io) will be +used instead. + + int (*cooked_read)(struct gameport *, int *axes, int *buttons); + +If the gameport supports cooked mode, it should point this to its cooked +read function. It should fill axes[0..3] with four values of the joystick axes +and buttons[0] with four bits representing the buttons. + + int (*calibrate)(struct gameport *, int *axes, int *max); + +Function for calibrating the ADC hardware. When called, axes[0..3] should be +pre-filled by cooked data by the caller, max[0..3] should be pre-filled with +expected maximums for each axis. The calibrate() function should set the +sensitivity of the ADC hardware so that the maximums fit in its range and +recompute the axes[] values to match the new sensitivity or re-read them from +the hardware so that they give valid values. + + int (*open)(struct gameport *, int mode); + +Open() serves two purposes. First a driver either opens the port in raw or +in cooked mode, the open() callback can decide which modes are supported. +Second, resource allocation can happen here. The port can also be enabled +here. Prior to this call, other fields of the gameport struct (namely the io +member) need not to be valid. + + void (*close)(struct gameport *); + +Close() should free the resources allocated by open, possibly disabling the +gameport. + + struct gameport_dev *dev; + struct gameport *next; + +For internal use by the gameport layer. + +}; + +Enjoy! diff -u --recursive --new-file v2.4.9/linux/Documentation/input/input-programming.txt linux/Documentation/input/input-programming.txt --- v2.4.9/linux/Documentation/input/input-programming.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/input/input-programming.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,271 @@ +$Id: input-programming.txt,v 1.4 2001/05/04 09:47:14 vojtech Exp $ + +Programming input drivers +~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Creating an input device driver +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1.0 The simplest example +~~~~~~~~~~~~~~~~~~~~~~~~ + +Here comes a very simple example of an input device driver. The device has +just one button and the button is accessible at i/o port BUTTON_PORT. When +pressed or released a BUTTON_IRQ happens. The driver could look like: + +#include +#include +#include + +#include +#include + +static void button_interrupt(int irq, void *dummy, struct pt_regs *fp) +{ + input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) & 1); +} + +static int __init button_init(void) +{ + if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) { + printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq); + return -EBUSY; + } + + button_dev.evbit[0] = BIT(EV_KEY); + button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0); + + input_register_device(&button_dev); +} + +static void __exit button_exit(void) +{ + input_unregister_device(&button_dev); + free_irq(BUTTON_IRQ, button_interrupt); +} + +module_init(button_init); +module_exit(button_exit); + +1.1 What the example does +~~~~~~~~~~~~~~~~~~~~~~~~~ + +First it has to include the file, which interfaces to the +input subsystem. This provides all the definitions needed. + +In the _init function, which is called either upon module load or when +booting the kernel, it grabs the required resources (it should also check +for the presence of the device). + +Then it sets the input bitfields. This way the device driver tells the other +parts of the input systems what it is - what events can be generated or +accepted by this input device. Our example device can only generate EV_KEY type +events, and from those only BTN_0 event code. Thus we only set these two +bits. We could have used + + set_bit(EV_KEY, button_dev.evbit); + set_bit(BTN_0, button_dev.keybit); + +as well, but with more than single bits the first approach tends to be +shorter. + +Then the example driver registers the input device structure by calling + + input_register_device(&button_dev); + +This adds the button_dev structure to linked lists of the input driver and +calls device handler modules _connect functions to tell them a new input +device has appeared. Because the _connect functions may call kmalloc(, +GFP_KERNEL), which can sleep, input_register_device() must not be called +from an interrupt or with a spinlock held. + +While in use, the only used function of the driver is + + button_interrupt() + +which upon every interrupt from the button checks its state and reports it +via the + + input_report_btn() + +call to the input system. There is no need to check whether the interrupt +routine isn't reporting two same value events (press, press for example) to +the input system, because the input_report_* functions check that +themselves. + +1.2 dev->open() and dev->close() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In case the driver has to repeatedly poll the device, because it doesn't +have an interrupt coming from it and the polling is too expensive to be done +all the time, or if the device uses a valuable resource (eg. interrupt), it +can use the open and close callback to know when it can stop polling or +release the interrupt and when it must resume polling or grab the interrupt +again. To do that, we would add this to our example driver: + +int button_used = 0; + +static int button_open(struct input_dev *dev) +{ + if (button_used++) + return 0; + + if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) { + printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq); + button_used--; + return -EBUSY; + } + + return 0; +} + +static void button_close(struct input_dev *dev) +{ + if (!--button_used) + free_irq(IRQ_AMIGA_VERTB, button_interrupt); +} + +static int __init button_init(void) +{ + ... + button_dev.open = button_open; + button_dev.close = button_close; + ... +} + +Note the button_used variable - we have to track how many times the open +function was called to know when exactly our device stops being used. + +The open() callback should return a 0 in case of succes or any nonzero value +in case of failure. The close() callback (which is void) must always succeed. + +1.3 Basic event types +~~~~~~~~~~~~~~~~~~~~~ + +The most simple event type is EV_KEY, which is used for keys and buttons. +It's reported to the input system via: + + input_report_key(struct input_dev *dev, int code, int value) + +See linux/input.h for the allowable values of code (from 0 to KEY_MAX). +Value is interpreted as a truth value, ie any nonzero value means key +pressed, zero value means key released. The input code generates events only +in case the value is different from before. + +In addition to EV_KEY, there are two more basic event types: EV_REL and +EV_ABS. They are used for relative and absolute values supplied by the +device. A relative value may be for example a mouse movement in the X axis. +The mouse reports it as a relative difference from the last position, +because it doesn't have any absolute coordinate system to work in. Absolute +events are namely for joysticks and digitizers - devices that do work in an +absolute coordinate systems. + +Having the device report EV_REL buttons is as simple as with EV_KEY, simply +set the corresponding bits and call the + + input_report_rel(struct input_dev *dev, int code, int value) + +function. Events are generated only for nonzero value. + +However EV_ABS requires a little special care. Before calling +input_register_devices, you have to fill additional fields in the input_dev +struct for each absolute axis your device has. If our button device had also +the ABS_X axis: + + button_dev.absmin[ABS_X] = 0; + button_dev.absmax[ABS_X] = 255; + button_dev.absfuzz[ABS_X] = 4; + button_dev.absflat[ABS_X] = 8; + +This setting would be appropriate for a joystick X axis, with the minimum of +0, maximum of 255 (which the joystick *must* be able to reach, no problem if +it sometimes reports more, but it must be able to always reach the min and +max values), with noise in the data up to +- 4, and with a center flat +position of size 8. + +If you don't need absfuzz and absflat, you can set them to zero, which mean +that the thing is precise and always returns to exactly the center position +(if it has any). + +1.4 The void *private field +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This field in the input structure can be used to point to any private data +structures in the input device driver, in case the driver handles more than +one device. You'll need it in the open and close callbacks. + +1.5 NBITS(), LONG(), BIT() +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These three macros frin input.h help some bitfield computations: + + NBITS(x) - returns the length of a bitfield array in longs for x bits + LONG(x) - returns the index in the array in longs for bit x + BIT(x) - returns the indes in a long for bit x + +1.6 The number, id* and name fields +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The dev->number is assigned by the input system to the input device when it +is registered. It has no use except for identifying the device to the user +in system messages. + +The dev->name should be set before registering the input device by the input +device driver. It's a string like 'Generic button device' containing an +user friendly name of the device. + +The id* fields contain the bus ID (PCI, USB, ...), vendor ID and device ID +of the device. The bus IDs are defined in input.h. The vendor and device ids +are defined in pci_ids.h, usb_ids.h and similar include files. These fields +should be set by the input device driver before registering it. + +The idtype field can be used for specific information for the input device +driver. + +The id and name fields can be passed to userland via the evdev interface. + +1.7 The keycode, keycodemax, keycodesize fields +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These two fields will be used for any inpur devices that report their data +as scancodes. If not all scancodes can be known by autodetection, they may +need to be set by userland utilities. The keycode array then is an array +used to map from scancodes to input system keycodes. The keycode max will +contain the size of the array and keycodesize the size of each entry in it +(in bytes). + +1.8 Key autorepeat +~~~~~~~~~~~~~~~~~~ + +... is simple. It is handled by the input.c module. Hardware autorepeat is +not used, because it's not present in many devices and even where it is +present, it is broken sometimes (at keyboards: Toshiba notebooks). To enable +autorepeat for your device, just set EV_REP in dev->evbit. All will be +handled by the input system. + +1.9 Other event types, handling output events +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The other event types up to now are: + +EV_LED - used for the keyboad LEDs. +EV_SND - used for keyboard beeps. + +They are very similar to for example key events, but they go in the other +direction - from the system to the input device driver. If your input device +driver can handle these events, it has to set the respective bits in evbit, +*and* also the callback routine: + + button_dev.event = button_event; + +int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); +{ + if (type == EV_SND && code == EV_BELL) { + outb(value, BUTTON_BELL); + return 0; + } + return -1; +} + +This callback routine can be called from an interrupt or a BH (although that +isn't a rule), and thus must not sleep, and must not take too long to finish. diff -u --recursive --new-file v2.4.9/linux/Documentation/input/input.txt linux/Documentation/input/input.txt --- v2.4.9/linux/Documentation/input/input.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/input/input.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,297 @@ + Linux Input drivers v1.0 + (c) 1999-2001 Vojtech Pavlik + Sponsored by SuSE + $Id: input.txt,v 1.5 2001/06/06 11:05:33 vojtech Exp $ +---------------------------------------------------------------------------- + +0. Disclaimer +~~~~~~~~~~~~~ + 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., 59 +Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Should you need to contact me, the author, you can do so either by e-mail +- mail your message to , or by paper mail: Vojtech Pavlik, +Simunkova 1594, Prague 8, 182 00 Czech Republic + + For your convenience, the GNU General Public License version 2 is included +in the package: See the file COPYING. + +1. Introduction +~~~~~~~~~~~~~~~ + This is a collection of drivers that is designed to support all input +devices under Linux. However, in the current kernels, although it's +possibilities are much bigger, it's limited to USB devices only. This is +also why it resides in the drivers/usb subdirectory. + + The center of the input drivers is the input.o module, which must be +loaded before any other of the input modules - it serves as a way of +communication between two groups of modules: + +1.1 Device drivers +~~~~~~~~~~~~~~~~~~ + These modules talk to the hardware (for example via USB), and provide +events (keystrokes, mouse movements) to the input.o module. + +1.2 Event handlers +~~~~~~~~~~~~~~~~~~ + These modules get events from input.o and pass them where needed via +various interfaces - keystrokes to the kernel, mouse movements via a +simulated PS/2 interface to GPM and X and so on. + +2. Simple Usage +~~~~~~~~~~~~~~~ + For the most usual configuration, with one USB mouse and one USB keyboard, +you'll have to load the following modules (or have them built in to the +kernel): + + input.o + mousedev.o + keybdev.o + usbcore.o + usb-[uo]hci.o + hid.o + + After this, the USB keyboard will work straight away, and the USB mouse +will be available as a character device on major 13, minor 63: + + crw-r--r-- 1 root root 13, 63 Mar 28 22:45 mice + + This device, has to be created, unless you use devfs, in which case it's +created automatically. The commands to do that are: + + cd /dev + mkdir input + mknod input/mice c 13 63 + + After that you have to point GPM (the textmode mouse cut&paste tool) and +XFree to this device to use it - GPM should be called like: + + gpm -t ps2 -m /dev/input/mice + + And in X: + + Section "Pointer" + Protocol "ImPS/2" + Device "/dev/input/mice" + ZAxisMapping 4 5 + EndSection + + When you do all of the above, you can use your USB mouse and keyboard. + +3. Detailed Description +~~~~~~~~~~~~~~~~~~~~~~~ +3.1 Device drivers +~~~~~~~~~~~~~~~~~~ + Device drivers are the modules that generate events. The events are +however not useful without being handled, so you also will need to use some +of the modules from section 3.2. + +3.1.1 hid.c +~~~~~~~~~~~ + Hid.c is the largest and most complex driver of the whole suite. It +handles all HID devices, and because there is a very wide variety of them, +and because the USB HID specification isn't simple, it needs to be this big. + + Currently, it handles USB mice, joysticks, gamepads, steering wheels +keyboards, trackballs and digitizers. + + However, USB uses HID also for monitor controls, speaker controls, UPSs, +LCDs and many other purposes. + + The monitor and speaker controls should be easy to add to the hid/input +interface, but for the UPSs and LCDs it doesn't make much sense. For this, +the hiddev interface was designed. See Documentation/usb/hiddev.txt +for more information about it. + + The usage of the hid.o module is very simple, it takes no parameters, +detects everything automatically and when a HID device is inserted, it +detects it appropriately. + + However, because the devices vary wildly, you might happen to have a +device that doesn't work well. In that case #define DEBUG at the beginning +of hid.c and send me the syslog traces. + +3.1.2 usbmouse.c +~~~~~~~~~~~~~~~~ + For embedded systems, for mice with broken HID descriptors and just any +other use when the big hid.c wouldn't be a good choice, there is the +usbmouse.c driver. It handles USB mice only. It uses a simpler HIDBP +protocol. This also means the mice must support this simpler protocol. Not +all do. If you don't have any strong reason to use this module, use hid.c +instead. + +3.1.3 usbkbd.c +~~~~~~~~~~~~~~ + Much like usbmouse.c, this module talks to keyboards with a simpplified +HIDBP protocol. It's smaller, but doesn't support any extra special keys. +Use hid.c instead if there isn't any special reason to use this. + +3.1.4 wacom.c +~~~~~~~~~~~~~ + This is a driver for Wacom Graphire and Intuos tablets. Not for Wacom +PenPartner, that one is handled by the HID driver. Although the Intuos and +Graphire tablets claim that they are HID tablets as well, they are not and +thus need this specific driver. + +3.1.5 iforce.c +~~~~~~~~~~~~~~~ + A driver for I-Force joysticks and wheels, both over USB and RS232. +It includes ForceFeedback support now, even though Immersion Corp. considers +the protocol a trade secret and won't disclose a word about it. + +3.2 Event handlers +~~~~~~~~~~~~~~~~~~ + Event handlers distrubite the events from the devices to userland and +kernel, as needed. + +3.2.1 keybdev.c +~~~~~~~~~~~~~~~ + Keybdev is currently a rather ugly hack that translates the input events +into architecture-specific keyboard raw mode (Xlated AT Set2 on x86), and +passes them into the handle_scancode function of the keyboard.c module. This +works well enough on all architectures that keybdev can generate rawmode on, +other architectures can be added to it. + + The right way would be to pass the events to keyboard.c directly, best if +keyboard.c would itself be an event handler. This is done in the input +patch, available on the webpage mentioned below. + +3.2.2 mousedev.c +~~~~~~~~~~~~~~~~ + Mousedev is also a hack to make programs that use mouse input work. It +takes events from either mice or digitizers/tablets and makes a PS/2-style +(a la /dev/psaux) mouse device available to the userland. Ideally, the +programs could use a more reasonable interface, for example evdev.c + + Mousedev devices in /dev/input (as shown above) are: + + crw-r--r-- 1 root root 13, 32 Mar 28 22:45 mouse0 + crw-r--r-- 1 root root 13, 33 Mar 29 00:41 mouse1 + crw-r--r-- 1 root root 13, 34 Mar 29 00:41 mouse2 + crw-r--r-- 1 root root 13, 35 Apr 1 10:50 mouse3 + ... + ... + crw-r--r-- 1 root root 13, 62 Apr 1 10:50 mouse30 + crw-r--r-- 1 root root 13, 63 Apr 1 10:50 mice + +Each 'mouse' device is assigned to a single mouse or digitizer, except the last +one - 'mice'. This single character device is shared by all mice and +digitizers, and even if none are connected, the device is present. This is +useful for hotplugging USB mice, so that programs can open the device even when +no mice are present. + + CONFIG_INPUT_MOUSEDEV_SCREEN_[XY] in the kernel configuration are the size +of your screen (in pixels) in XFree86. This is needed if you want to use +your digitizer in X, because it's movement is sent to X via a virtual PS/2 +mouse and thus needs to be scaled accordingly. These values won't be used if +you use a mouse only. + + Mousedev will generate either PS/2, ImPS/2 (Microsoft IntelliMouse) or +ExplorerPS/2 (IntelliMouse Explorer) protocols, depending on what the program +reading the data wishes. You can set GPM and X to any of these. You'll need +ImPS/2 if you want to make use of a wheel on a USB mouse and ExplorerPS/2 if you +want to use extra (up to 5) buttons. + +3.2.3 joydev.c +~~~~~~~~~~~~~~ + Joydev implements v0.x and v1.x Linux joystick api, much like +drivers/char/joystick/joystick.c used to in earlier versions. See +joystick-api.txt in the Documentation subdirectory for details. As soon as +any joystick is connected, it can be accessed in /dev/input on: + + crw-r--r-- 1 root root 13, 0 Apr 1 10:50 js0 + crw-r--r-- 1 root root 13, 1 Apr 1 10:50 js1 + crw-r--r-- 1 root root 13, 2 Apr 1 10:50 js2 + crw-r--r-- 1 root root 13, 3 Apr 1 10:50 js3 + ... + +And so on up to js31. + +3.2.4 evdev.c +~~~~~~~~~~~~~ + Evdev is the generic input event interface. It passes the events generated +in the kernel straight to the program, with timestamps. The API is still +evolving, but should be useable now. It's described in section 5. + + This should be the way for GPM and X to get keyboard and mouse mouse +events. It allows for multihead in X without any specific multihead kernel +support. The event codes are the same on all architectures and are hardware +independent. + + The devices are in /dev/input: + + crw-r--r-- 1 root root 13, 64 Apr 1 10:49 event0 + crw-r--r-- 1 root root 13, 65 Apr 1 10:50 event1 + crw-r--r-- 1 root root 13, 66 Apr 1 10:50 event2 + crw-r--r-- 1 root root 13, 67 Apr 1 10:50 event3 + ... + +3. Contacts +~~~~~~~~~~~ + This effort has it's home page at: + + http://www.suse.cz/development/input/ + +You'll find both the latest HID driver and the complete Input driver there +as well as information how to access the CVS repository for latest revisions +of the drivers. + + There is also a mailing list for this: + + majordomo@atrey.karlin.mff.cuni.cz + +Send "subscribe linux-input" to subscribe to it. + +4. Verifying if it works +~~~~~~~~~~~~~~~~~~~~~~~~ + Typing a couple keys on the keyboard should be enough to check that a USB +keyboard works and is correctly connected to the kernel keyboard driver. + + Doing a cat /dev/input/mouse0 (c, 13, 32) will verify that a mouse is also +emulated, characters should appear if you move it. + + You can test the joystick emulation with the 'jstest' utility, available +in the joystick package (see Documentation/joystick.txt). + + You can test the event devics with the 'evtest' utitily available on the +input driver homepage (see the URL above). + +5. Event interface +~~~~~~~~~~~~~~~~~~ + Should you want to add event device support into any application (X, gpm, +svgalib ...) I will be happy to provide you any help I +can. Here goes a description of the current state of things, which is going +to be extended, but not changed incompatibly as time goes: + + You can use blocking and nonblocking reads, also select() on the +/dev/input/eventX devices, and you'll always get a whole number of input +events on a read. Their layout is: + +struct input_event { + struct timeval time; + unsigned short type; + unsigned short code; + unsigned int value; +}; + + 'time' is the timestamp, it returns the time at which the event happened. +Type is for example EV_REL for relative momement, REL_KEY for a keypress or +release. More types are defined in include/linux/input.h. + + 'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete +list is in include/linux/input.h. + + 'value' is the value the event carries. Either a relative change for +EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for +release, 1 for keypress and 2 for autorepeat. diff -u --recursive --new-file v2.4.9/linux/Documentation/input/joystick-api.txt linux/Documentation/input/joystick-api.txt --- v2.4.9/linux/Documentation/input/joystick-api.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/input/joystick-api.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,316 @@ + Joystick API Documentation -*-Text-*- + + Ragnar Hojland Espinosa + + + 7 Aug 1998 + + $Id: joystick-api.txt,v 1.2 2001/05/08 21:21:23 vojtech Exp $ + +1. Initialization +~~~~~~~~~~~~~~~~~ + +Open the joystick device following the usual semantics (that is, with open). +Since the driver now reports events instead of polling for changes, +immediately after the open it will issue a series of synthetic events +(JS_EVENT_INIT) that you can read to check the initial state of the +joystick. + +By default, the device is opened in blocking mode. + + int fd = open ("/dev/js0", O_RDONLY); + + +2. Event Reading +~~~~~~~~~~~~~~~~ + + struct js_event e; + read (fd, &e, sizeof(struct js_event)); + +where js_event is defined as + + struct js_event { + __u32 time; /* event timestamp in milliseconds */ + __s16 value; /* value */ + __u8 type; /* event type */ + __u8 number; /* axis/button number */ + }; + +If the read is successful, it will return sizeof(struct js_event), unless +you wanted to read more than one event per read as described in section 3.1. + + +2.1 js_event.type +~~~~~~~~~~~~~~~~~ + +The possible values of ``type'' are + + #define JS_EVENT_BUTTON 0x01 /* button pressed/released */ + #define JS_EVENT_AXIS 0x02 /* joystick moved */ + #define JS_EVENT_INIT 0x80 /* initial state of device */ + +As mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed +events on open. That is, if it's issuing a INIT BUTTON event, the +current type value will be + + int type = JS_EVENT_BUTTON | JS_EVENT_INIT; /* 0x81 */ + +If you choose not to differentiate between synthetic or real events +you can turn off the JS_EVENT_INIT bits + + type &= ~JS_EVENT_INIT; /* 0x01 */ + + +2.2 js_event.number +~~~~~~~~~~~~~~~~~~~ + +The values of ``number'' correspond to the axis or button that +generated the event. Note that they carry separate numeration (that +is, you have both an axis 0 and a button 0). Generally, + + number + 1st Axis X 0 + 1st Axis Y 1 + 2nd Axis X 2 + 2nd Axis Y 3 + ...and so on + +Hats vary from one joystick type to another. Some can be moved in 8 +directions, some only in 4, The driver, however, always reports a hat as two +independent axis, even if the hardware doesn't allow independent movement. + + +2.3 js_event.value +~~~~~~~~~~~~~~~~~~ + +For an axis, ``value'' is a signed integer between -32767 and +32767 +representing the position of the joystick along that axis. If you +don't read a 0 when the joystick is `dead', or if it doesn't span the +full range, you should recalibrate it (with, for example, jscal). + +For a button, ``value'' for a press button event is 1 and for a release +button event is 0. + +Though this + + if (js_event.type == JS_EVENT_BUTTON) { + buttons_state ^= (1 << js_event.number); + } + +may work well if you handle JS_EVENT_INIT events separately, + + if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) { + if (js_event.value) + buttons_state |= (1 << js_event.number); + else + buttons_state &= ~(1 << js_event.number); + } + +is much safer since it can't lose sync with the driver. As you would +have to write a separate handler for JS_EVENT_INIT events in the first +snippet, this ends up being shorter. + + +2.4 js_event.time +~~~~~~~~~~~~~~~~~ + +The time an event was generated is stored in ``js_event.time''. It's a time +in milliseconds since ... well, since sometime in the past. This eases the +task of detecting double clicks, figuring out if movement of axis and button +presses happened at the same time, and similar. + + +3. Reading +~~~~~~~~~~ + +If you open the device in blocking mode, a read will block (that is, +wait) forever until an event is generated and effectively read. There +are two alternatives if you can't afford to wait forever (which is, +admittedly, a long time;) + + a) use select to wait until there's data to be read on fd, or + until it timeouts. There's a good example on the select(2) + man page. + + b) open the device in non-blocking mode (O_NONBLOCK) + + +3.1 O_NONBLOCK +~~~~~~~~~~~~~~ + +If read returns -1 when reading in O_NONBLOCK mode, this isn't +necessarily a "real" error (check errno(3)); it can just mean there +are no events pending to be read on the driver queue. You should read +all events on the queue (that is, until you get a -1). + +For example, + + while (1) { + while (read (fd, &e, sizeof(struct js_event)) > 0) { + process_event (e); + } + /* EAGAIN is returned when the queue is empty */ + if (errno != EAGAIN) { + /* error */ + } + /* do something interesting with processed events */ + } + +One reason for emptying the queue is that if it gets full you'll start +missing events since the queue is finite, and older events will get +overwritten. + +The other reason is that you want to know all what happened, and not +delay the processing till later. + +Why can get the queue full? Because you don't empty the queue as +mentioned, or because too much time elapses from one read to another +and too many events to store in the queue get generated. Note that +high system load may contribute to space those reads even more. + +If time between reads is enough to fill the queue and loose an event, +the driver will switch to startup mode and next time you read it, +synthetic events (JS_EVENT_INIT) will be generated to inform you of +the actual state of the joystick. + +[As for version 1.2.8, the queue is circular and able to hold 64 + events. You can increment this size bumping up JS_BUFF_SIZE in + joystick.h and recompiling the driver.] + + +In the above code, you might as well want to read more than one event +at a time using the typical read(2) functionality. For that, you would +replace the read above with something like + + struct js_event mybuffer[0xff]; + int i = read (fd, mybuffer, sizeof(struct mybuffer)); + +In this case, read would return -1 if the queue was empty, or some +other value in which the number of events read would be i / +sizeof(js_event) Again, if the buffer was full, it's a good idea to +process the events and keep reading it until you empty the driver queue. + + +4. IOCTLs +~~~~~~~~~ + +The joystick driver defines the following ioctl(2) operations. + + /* function 3rd arg */ + #define JSIOCGAXES /* get number of axes char */ + #define JSIOCGBUTTONS /* get number of buttons char */ + #define JSIOCGVERSION /* get driver version int */ + #define JSIOCGNAME(len) /* get identifier string char */ + #define JSIOCSCORR /* set correction values &js_corr */ + #define JSIOCGCORR /* get correction values &js_corr */ + +For example, to read the number of axes + + char number_of_axes; + ioctl (fd, JSIOCGAXES, &number_of_axes); + + +4.1 JSIOGCVERSION +~~~~~~~~~~~~~~~~~ + +JSIOGCVERSION is a good way to check in run-time whether the running +driver is 1.0+ and supports the event interface. If it is not, the +IOCTL will fail. For a compile-time decision, you can test the +JS_VERSION symbol + + #ifdef JS_VERSION + #if JS_VERSION > 0xsomething + + +4.2 JSIOCGNAME +~~~~~~~~~~~~~~ + +JSIOCGNAME(len) allows you to get the name string of the joystick - the same +as is being printed at boot time. The 'len' argument is the length of the +buffer provided by the application asking for the name. It is used to avoid +possible overrun should the name be too long. + + char name[128]; + if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0) + strncpy(name, "Unknown", sizeof(name)); + printf("Name: %s\n", name); + + +4.3 JSIOC[SG]CORR +~~~~~~~~~~~~~~~~~ + +For usage on JSIOC[SG]CORR I suggest you to look into jscal.c They are +not needed in a normal program, only in joystick calibration software +such as jscal or kcmjoy. These IOCTLs and data types aren't considered +to be in the stable part of the API, and therefore may change without +warning in following releases of the driver. + +Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold +information for all axis. That is, struct js_corr corr[MAX_AXIS]; + +struct js_corr is defined as + + struct js_corr { + __s32 coef[8]; + __u16 prec; + __u16 type; + }; + +and ``type'' + + #define JS_CORR_NONE 0x00 /* returns raw values */ + #define JS_CORR_BROKEN 0x01 /* broken line */ + + +5. Backward compatibility +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The 0.x joystick driver API is quite limited and its usage is deprecated. +The driver offers backward compatibility, though. Here's a quick summary: + + struct JS_DATA_TYPE js; + while (1) { + if (read (fd, &js, JS_RETURN) != JS_RETURN) { + /* error */ + } + usleep (1000); + } + +As you can figure out from the example, the read returns immediately, +with the actual state of the joystick. + + struct JS_DATA_TYPE { + int buttons; /* immediate button state */ + int x; /* immediate x axis value */ + int y; /* immediate y axis value */ + }; + +and JS_RETURN is defined as + + #define JS_RETURN sizeof(struct JS_DATA_TYPE) + +To test the state of the buttons, + + first_button_state = js.buttons & 1; + second_button_state = js.buttons & 2; + +The axis values do not have a defined range in the original 0.x driver, +except for that the values are non-negative. The 1.2.8+ drivers use a +fixed range for reporting the values, 1 being the minimum, 128 the +center, and 255 maximum value. + +The v0.8.0.2 driver also had an interface for 'digital joysticks', (now +called Multisystem joysticks in this driver), under /dev/djsX. This driver +doesn't try to be compatible with that interface. + + +6. Final Notes +~~~~~~~~~~~~~~ + +____/| Comments, additions, and specially corrections are welcome. +\ o.O| Documentation valid for at least version 1.2.8 of the joystick + =(_)= driver and as usual, the ultimate source for documentation is + U to "Use The Source Luke" or, at your convenience, Vojtech ;) + + - Ragnar +EOF diff -u --recursive --new-file v2.4.9/linux/Documentation/input/joystick-parport.txt linux/Documentation/input/joystick-parport.txt --- v2.4.9/linux/Documentation/input/joystick-parport.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/input/joystick-parport.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,533 @@ + Linux Joystick parport drivers v2.0 + (c) 1998-2000 Vojtech Pavlik + (c) 1998 Andree Borrmann + Sponsored by SuSE + $Id: joystick-parport.txt,v 1.5 2001/05/15 06:41:00 vojtech Exp $ +---------------------------------------------------------------------------- + +0. Disclaimer +~~~~~~~~~~~~~ + Any information in this file is provided as-is, without any guarantee that +it will be true. So, use it at your own risk. The possible damages that can +happen include burning your parallel port, and/or the sticks and joystick +and maybe even more. Like when a lightning kills you it is not our problem. + +1. Intro +~~~~~~~~ + The joystick parport drivers are used for joysticks and gamepads not +originally designed for PCs and other computers Linux runs on. Because of +that, PCs usually lack the right ports to connect these devices to. Parallel +port, because of its ability to change single bits at will, and providing +both output and input bits is the most suitable port on the PC for +connecting such devices. + +2. Devices supported +~~~~~~~~~~~~~~~~~~~~ + Many console and 8-bit computer gamepads and joysticks are supported. The +following subsections discuss usage of each. + +2.1 NES and SNES +~~~~~~~~~~~~~~~~ + The Nintendo Entertainment System and Super Nintendo Entertainment System +gamepads are widely available, and easy to get. Also, they are quite easy to +connect to a PC, and don't need much processing speed (108 us for NES and +165 us for SNES, compared to about 1000 us for PC gamepads) to communicate +with them. + + All NES and SNES use the same synchronous serial protocol, clocked from +the computer's side (and thus timing insensitive). To allow up to 5 NES +and/or SNES gamepads connected to the parallel port at once, the output +lines of the parallel port are shared, while one of 5 available input lines +is assigned to each gamepad. + + This protocol is handled by the gamecon.c driver, so that's the one +you'll use for NES and SNES gamepads. + + The main problem with PC parallel ports is that they don't have +5V power +source on any of their pins. So, if you want a reliable source of power +for your pads, use either keyboard or joystick port, and make a pass-through +cable. You can also pull the power directly from the power supply (the red +wire is +5V). + + If you want to use the parallel port only, you can take the power is from +some data pin. For most gamepad and parport implementations only one pin is +needed, and I'd recommend pin 9 for that, the highest data bit. On the other +hand, if you are not planning to use anything else than NES / SNES on the +port, anything between and including pin 4 and pin 9 will work. + +(pin 9) -----> Power + + Unfortunately, there are pads that need a lot more of power, and parallel +ports that can't give much current through the data pins. If this is your +case, you'll need to use diodes (as a prevention of destroying your parallel +port), and combine the currents of two or more data bits together. + + Diodes +(pin 9) ----|>|-------+------> Power + | +(pin 8) ----|>|-------+ + | +(pin 7) ----|>|-------+ + | + : + | +(pin 4) ----|>|-------+ + + Ground is quite easy. On PC's parallel port the ground is on any of the +pins from pin 18 to pin 25. So use any pin of these you like for the ground. + +(pin 18) -----> Ground + + NES and SNES pads have two input bits, Clock and Latch, which drive the +serial transfer. These are connected to pins 2 and 3 of the parallel port, +respectively. + +(pin 2) -----> Clock +(pin 3) -----> Latch + + And the last thing is the NES / SNES data wire. Only that isn't shared and +each pad needs its own data pin. The parallel port pins are: + +(pin 10) -----> Pad 1 data +(pin 11) -----> Pad 2 data +(pin 12) -----> Pad 3 data +(pin 13) -----> Pad 4 data +(pin 15) -----> Pad 5 data + + Note that pin 14 is not used, since it is not an input pin on the parallel +port. + + This is everything you need on the PC's side of the connection, now on to +the gamepads side. The NES and SNES have different connectors. Also, there +are quite a lot of NES clones, and because Nintendo used proprietary +connectors for their machines, the cloners couldn't and used standard D-Cannon +connectors. Anyway, if you've got a gamepad, and it has buttons A, B, Turbo +A, Turbo B, Select and Start, and is connected through 5 wires, then it is +either a NES or NES clone and will work with this connection. SNES gamepads +also use 5 wires, but have more buttons. They will work as well, of course. + +Pinout for NES gamepads Pinout for SNES gamepads + + +----> Power +-----------------------\ + | 7 | o o o o | x x o | 1 + 5 +---------+ 7 +-----------------------/ + | x x o \ | | | | | + | o o o o | | | | | +-> Ground + 4 +------------+ 1 | | | +------------> Data + | | | | | | +---------------> Latch + | | | +-> Ground | +------------------> Clock + | | +----> Clock +---------------------> Power + | +-------> Latch + +----------> Data + +Pinout for NES clone (db9) gamepads Pinout for NES clone (db15) gamepads + + +---------> Clock +-----------------> Data + | +-------> Latch | +---> Ground + | | +-----> Data | | + | | | ___________________ + _____________ 8 \ o x x x x x x o / 1 + 5 \ x o o o x / 1 \ o x x o x x o / + \ x o x o / 15 `~~~~~~~~~~~~~' 9 + 9 `~~~~~~~' 6 | | | + | | | | +----> Clock + | +----> Power | +----------> Latch + +--------> Ground +----------------> Power + +2.2 Multisystem joysticks +~~~~~~~~~~~~~~~~~~~~~~~~~ + In the era of 8-bit machines, there was something like de-facto standard +for joystick ports. They were all digital, and all used D-Cannon 9 pin +connectors (db9). Because of that, a single joystick could be used without +hassle on Atari (130, 800XE, 800XL, 2600, 7200), Amiga, Commodore C64, +Amstrad CPC, Sinclair ZX Spectrum and many other machines. That's why these +joysticks are called "Multisystem". + + Now their pinout: + + +---------> Right + | +-------> Left + | | +-----> Down + | | | +---> Up + | | | | + _____________ +5 \ x o o o o / 1 + \ x o x o / + 9 `~~~~~~~' 6 + | | + | +----> Button + +--------> Ground + + However, as time passed, extensions to this standard developed, and these +were not compatible with each other: + + + Atari 130, 800/XL/XE MSX + + +-----------> Power + +---------> Right | +---------> Right + | +-------> Left | | +-------> Left + | | +-----> Down | | | +-----> Down + | | | +---> Up | | | | +---> Up + | | | | | | | | | + _____________ _____________ +5 \ x o o o o / 1 5 \ o o o o o / 1 + \ x o o o / \ o o o o / + 9 `~~~~~~~' 6 9 `~~~~~~~' 6 + | | | | | | | + | | +----> Button | | | +----> Button 1 + | +------> Power | | +------> Button 2 + +--------> Ground | +--------> Output 3 + +----------> Ground + + Amstrad CPC Commodore C64 + + +-----------> Analog Y + +---------> Right | +---------> Right + | +-------> Left | | +-------> Left + | | +-----> Down | | | +-----> Down + | | | +---> Up | | | | +---> Up + | | | | | | | | | + _____________ _____________ +5 \ x o o o o / 1 5 \ o o o o o / 1 + \ x o o o / \ o o o o / + 9 `~~~~~~~' 6 9 `~~~~~~~' 6 + | | | | | | | + | | +----> Button 1 | | | +----> Button + | +------> Button 2 | | +------> Power + +--------> Ground | +--------> Ground + +----------> Analog X + + Sinclair Spectrum +2A/+3 Amiga 1200 + + +-----------> Up +-----------> Button 3 + | +---------> Fire | +---------> Right + | | | | +-------> Left + | | +-----> Ground | | | +-----> Down + | | | | | | | +---> Up + | | | | | | | | + _____________ _____________ +5 \ o o x o x / 1 5 \ o o o o o / 1 + \ o o o o / \ o o o o / + 9 `~~~~~~~' 6 9 `~~~~~~~' 6 + | | | | | | | | + | | | +----> Right | | | +----> Button 1 + | | +------> Left | | +------> Power + | +--------> Ground | +--------> Ground + +----------> Down +----------> Button 2 + + And there were many others. + +2.2.1 Multisystem joysticks using db9.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + For the Multisystem joysticks, and their derivatives, the db9.c driver +was written. It allows only one joystick / gamepad per parallel port, but +the interface is easy to build and works with almost anything. + + For the basic 1-button Multisystem joystick you connect its wires to the +parallel port like this: + +(pin 1) -----> Power +(pin 18) -----> Ground + +(pin 2) -----> Up +(pin 3) -----> Down +(pin 4) -----> Left +(pin 5) -----> Right +(pin 6) -----> Button 1 + + However, if the joystick is switch based (eg. clicks when you move it), +you might or might not, depending on your parallel port, need 10 kOhm pullup +resistors on each of the direction and button signals, like this: + +(pin 2) ------------+------> Up + Resistor | +(pin 1) --[10kOhm]--+ + + Try without, and if it doesn't work, add them. For TTL based joysticks / +gamepads the pullups are not needed. + + For joysticks with two buttons you connect the second button to pin 7 on +the parallel port. + +(pin 7) -----> Button 2 + + And that's it. + + On a side note, if you have already built a different adapter for use with +the digital joystick driver 0.8.0.2, this is also supported by the db9.c +driver, as device type 8. (See section 3.2) + +2.2.2 Multisystem joysticks using gamecon.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + For some people just one joystick per parallel port is not enough, and/or +want to use them on one parallel port together with NES/SNES/PSX pads. This is +possible using the gamecon.c. It supports up to 5 devices of the above types, +including 1 and 2 buttons Multisystem joysticks. + + However, there is nothing for free. To allow more sticks to be used at +once, you need the sticks to be purely switch based (that is non-TTL), and +not to need power. Just a plain simple six switches inside. If your +joystick can do more (eg. turbofire) you'll need to disable it totally first +if you want to use gamecon.c. + + Also, the connection is a bit more complex. You'll need a bunch of diodes, +and one pullup resistor. First, you connect the Directions and the button +the same as for db9, however with the diodes inbetween. + + Diodes +(pin 2) -----|<|----> Up +(pin 3) -----|<|----> Down +(pin 4) -----|<|----> Left +(pin 5) -----|<|----> Right +(pin 6) -----|<|----> Button 1 + + For two button sticks you also connect the other button. + +(pin 7) -----|<|----> Button 2 + + And finally, you connect the Ground wire of the joystick, like done in +this little schematic to Power and Data on the parallel port, as described +for the NES / SNES pads in section 2.1 of this file - that is, one data pin +for each joystick. The power source is shared. + +Data ------------+-----> Ground + Resistor | +Power --[10kOhm]--+ + + And that's all, here we go! + +2.2.3 Multisystem joysticks using turbografx.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The TurboGraFX interface, designed by + + Steffen Schwenke + + allows up to 7 Multisystem joysticks connected to the parallel port. In +Steffen's version, there is support for up to 5 buttons per joystick. However, +since this doesn't work reliably on all parallel ports, the turbografx.c driver +supports only one button per joystick. For more information on how to build the +interface, see + + http://www2.burg-halle.de/~schwenke/parport.html + +2.3 Sony Playstation +~~~~~~~~~~~~~~~~~~~~ + + The PSX controller is supported by the gamecon.c. Pinout of the PSX +controller (compatible with DirectPadPro): + + +---------+---------+---------+ +9 | o o o | o o o | o o o | 1 parallel + \________|_________|________/ port pins + | | | | | | + | | | | | +--------> Clock --- (4) + | | | | +------------> Select --- (3) + | | | +---------------> Power --- (5-9) + | | +------------------> Ground --- (18-25) + | +-------------------------> Command --- (2) + +----------------------------> Data --- (one of 10,11,12,13,15) + + The driver supports these controllers: + + * Standard PSX Pad + * NegCon PSX Pad + * Analog PSX Pad (red mode) + * Analog PSX Pad (green mode) + * PSX Rumble Pad + +2.4 Sega +~~~~~~~~ + All the Sega controllers are more or less based on the standard 2-button +Multisystem joystick. However, since they don't use switches and use TTL +logic, the only driver usable with them is the db9.c driver. + +2.4.1 Sega Master System +~~~~~~~~~~~~~~~~~~~~~~~~ + The SMS gamepads are almost exactly the same as normal 2-button +Multisystem joysticks. Set the driver to Multi2 mode, use the corresponding +parallel port pins, and the following schematic: + + +-----------> Power + | +---------> Right + | | +-------> Left + | | | +-----> Down + | | | | +---> Up + | | | | | + _____________ +5 \ o o o o o / 1 + \ o o x o / + 9 `~~~~~~~' 6 + | | | + | | +----> Button 1 + | +--------> Ground + +----------> Button 2 + +2.4.2 Sega Genesis aka MegaDrive +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The Sega Genesis (in Europe sold as Sega MegaDrive) pads are an extension +to the Sega Master System pads. They use more buttons (3+1, 5+1, 6+1). Use +the following schematic: + + +-----------> Power + | +---------> Right + | | +-------> Left + | | | +-----> Down + | | | | +---> Up + | | | | | + _____________ +5 \ o o o o o / 1 + \ o o o o / + 9 `~~~~~~~' 6 + | | | | + | | | +----> Button 1 + | | +------> Select + | +--------> Ground + +----------> Button 2 + + The Select pin goes to pin 14 on the parallel port. + +(pin 14) -----> Select + + The rest is the same as for Multi2 joysticks using db9.c + +2.4.3 Sega Saturn +~~~~~~~~~~~~~~~~~ + Sega Saturn has eight buttons, and to transfer that, without hacks like +Genesis 6 pads use, it needs one more select pin. Anyway, it is still +handled by the db9.c driver. Its pinout is very different from anything +else. Use this schematic: + + +-----------> Select 1 + | +---------> Power + | | +-------> Up + | | | +-----> Down + | | | | +---> Ground + | | | | | + _____________ +5 \ o o o o o / 1 + \ o o o o / + 9 `~~~~~~~' 6 + | | | | + | | | +----> Select 2 + | | +------> Right + | +--------> Left + +----------> Power + + Select 1 is pin 14 on the parallel port, Select 2 is pin 16 on the +parallel port. + +(pin 14) -----> Select 1 +(pin 16) -----> Select 2 + + The other pins (Up, Down, Right, Left, Power, Ground) are the same as for +Multi joysticks using db9.c + +3. The drivers +~~~~~~~~~~~~~~ + There are three drivers for the parallel port interfaces. Each, as +described above, allows to connect a different group of joysticks and pads. +Here are described their command lines: + +3.1 gamecon.c +~~~~~~~~~~~~~ + Using gamecon.c you can connect up to five devices to one parallel port. It +uses the following kernel/module command line: + + gc=port,pad1,pad2,pad3,pad4,pad5 + + Where 'port' the number of the parport interface (eg. 0 for parport0). + + And 'pad1' to 'pad5' are pad types connected to different data input pins +(10,11,12,13,15), as described in section 2.1 of this file. + + The types are: + + Type | Joystick/Pad + -------------------- + 0 | None + 1 | SNES pad + 2 | NES pad + 4 | Multisystem 1-button joystick + 5 | Multisystem 2-button joystick + 6 | N64 pad + 7 | Sony PSX controller + + The exact type of the PSX controller type is autoprobed, so you must have +your controller plugged in before initializing. + + Should you want to use more than one of parallel ports at once, you can use +gc_2 and gc_3 as additional command line parameters for two more parallel +ports. + +3.2 db9.c +~~~~~~~~~ + Apart from making an interface, there is nothing difficult on using the +db9.c driver. It uses the following kernel/module command line: + + db9=port,type + + Where 'port' is the number of the parport interface (eg. 0 for parport0). + + Caveat here: This driver only works on bidirectional parallel ports. If +your parallel port is recent enough, you should have no trouble with this. +Old parallel ports may not have this feature. + + 'Type' is the type of joystick or pad attached: + + Type | Joystick/Pad + -------------------- + 0 | None + 1 | Multisystem 1-button joystick + 2 | Multisystem 2-button joystick + 3 | Genesis pad (3+1 buttons) + 5 | Genesis pad (5+1 buttons) + 6 | Genesis pad (6+2 buttons) + 7 | Saturn pad (8 buttons) + 8 | Multisystem 1-button joystick (v0.8.0.2 pin-out) + 9 | Two Multisystem 1-button joysticks (v0.8.0.2 pin-out) + 10 | Amiga CD32 pad + + Should you want to use more than one of these joysticks/pads at once, you +can use db9_2 and db9_3 as additional command line parameters for two +more joysticks/pads. + +3.3 turbografx.c +~~~~~~~~~~~~~~~~ + The turbografx.c driver uses a very simple kernel/module command line: + + tgfx=port,js1,js2,js3,js4,js5,js6,js7 + + Where 'port' is the number of the parport interface (eg. 0 for parport0). + + 'jsX' is the number of buttons the Multisystem joysticks connected to the +interface ports 1-7 have. For a standard multisystem joystick, this is 1. + + Should you want to use more than one of these interfaces at once, you can +use tgfx_2 and tgfx_3 as additional command line parameters for two more +interfaces. + +3.4 PC parallel port pinout +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + .----------------------------------------. + At the PC: \ 13 12 11 10 9 8 7 6 5 4 3 2 1 / + \ 25 24 23 22 21 20 19 18 17 16 15 14 / + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Pin | Name | Description + ~~~~~~|~~~~~~~~~|~~~~~~~~~~ + 1 | /STROBE | Strobe + 2-9 | D0-D7 | Data Bit 0-7 + 10 | /ACK | Acknowledge + 11 | BUSY | Busy + 12 | PE | Paper End + 13 | SELIN | Select In + 14 | /AUTOFD | Autofeed + 15 | /ERROR | Error + 16 | /INIT | Initialize + 17 | /SEL | Select + 18-25 | GND | Signal Ground + +3.5 End +~~~~~~~ + That's all, folks! Have fun! diff -u --recursive --new-file v2.4.9/linux/Documentation/input/joystick.txt linux/Documentation/input/joystick.txt --- v2.4.9/linux/Documentation/input/joystick.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/input/joystick.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,583 @@ + Linux Joystick driver v2.0.0 + (c) 1996-2000 Vojtech Pavlik + Sponsored by SuSE + $Id: joystick.txt,v 1.6 2001/06/05 09:57:01 vojtech Exp $ +---------------------------------------------------------------------------- + +0. Disclaimer +~~~~~~~~~~~~~ + 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., 59 +Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Should you need to contact me, the author, you can do so either by e-mail +- mail your message to , or by paper mail: Vojtech Pavlik, +Ucitelska 1576, Prague 8, 182 00 Czech Republic + + For your convenience, the GNU General Public License version 2 is included +in the package: See the file COPYING. + +1. Intro +~~~~~~~~ + The joystick driver for Linux provides support for a variety of joysticks +and similar devices. It is based on a larger project aiming to support all +input devices in Linux. + + Should you encounter any problems while using the driver, or joysticks +this driver can't make complete use of, I'm very interested in hearing about +them. Bug reports and success stories are also welcome. + + The input project website is at: + + http://www.suse.cz/development/input/ + http://atrey.karlin.mff.cuni.cz/~vojtech/input/ + + There is also a mailing list for the driver at: + + listproc@atrey.karlin.mff.cuni.cz + +send "subscribe linux-joystick Your Name" to subscribe to it. + +2. Usage +~~~~~~~~ + For basic usage you just choose the right options in kernel config and +you should be set. + +2.1 inpututils +~~~~~~~~~~~~~~ +For testing and other purposes (for example serial devices), a set of +utilities is available at the abovementioned website. I suggest you download +and install it before going on. + +2.2 Device nodes +~~~~~~~~~~~~~~~~ +For applications to be able to use the joysticks, in you don't use devfs, +you'll have to manually create these nodes in /dev: + +cd /dev +rm js* +mkdir input +mknod input/js0 c 13 0 +mknod input/js1 c 13 1 +mknod input/js2 c 13 2 +mknod input/js3 c 13 3 +ln -s input/js0 js0 +ln -s input/js1 js1 +ln -s input/js2 js2 +ln -s input/js3 js3 + +For testing with inpututils it's also convenient to create these: + +mknod input/event0 c 13 64 +mknod input/event1 c 13 65 +mknod input/event2 c 13 66 +mknod input/event3 c 13 67 + +2.4 Modules needed +~~~~~~~~~~~~~~~~~~ + For all joystick drivers to function, you'll need the userland interface +module in kernel, either loaded or compiled in: + + modprobe joydev + + For gameport joysticks, you'll have to load the gameport driver as well; + + modprobe ns558 + + And for serial port joysticks, you'll need the serial input line +discipline module loaded and the inputattach utility started: + + modprobe serport + inputattach -xxx /dev/tts/X & + + In addition to that, you'll need the joystick driver module itself, most +usually you'll have an analog joystick: + + modprobe analog + + For automatic module loading, something like this might work - tailor to +your needs: + + alias tty-ldisc-2 serport + alias char-major-13 input + above input joydev ns558 analog + options analog js=gameport + +2.5 Verifying that it works +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + For testing the joystick driver functionality, there is the jstest +program in the utilities package. You run it by typing: + + jstest /dev/js0 + + And it should show a line with the joystick values, which update as you +move the stick, and press its buttons. The axes should all be zero when the +joystick is in the center position. They should not jitter by themselves to +other close values, and they also should be steady in any other position of +the stick. They should have the full range from -32767 to 32767. If all this +is met, then it's all fine, and you can play the games. :) + + If it's not, then there might be a problem. Try to calibrate the joystick, +and if it still doesn't work, read the drivers section of this file, the +troubleshooting section, and the FAQ. + +2.6. Calibration +~~~~~~~~~~~~~~~~ + For most joysticks you won't need any manual calibration, since the +joystick should be autocalibrated by the driver automagically. However, with +some analog joysticks, that either do not use linear resistors, or if you +want better precision, you can use the jscal program + + jscal -c /dev/js0 + + included in the joystick package to set better correction coefficients than +what the driver would choose itself. + + After calibrating the joystick you can verify if you like the new +calibration using the jstest command, and if you do, you then can save the +correction coefficients into a file + + jscal -p /dev/js0 > /etc/joystick.cal + + And add a line to your rc script executing that file + + source /etc/joystick.cal + + This way, after the next reboot your joystick will remain calibrated. You +can also add the jscal -p line to your shutdown script. + + +3. HW specific driver information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In this section each of the separate hardware specific drivers is described. + +3.1 Analog joysticks +~~~~~~~~~~~~~~~~~~~~ + The analog.c uses the standard analog inputs of the gameport, and thus +supports all standard joysticks and gamepads. It uses a very advanced +routine for this, allowing for data precision that can't be found on any +other system. + + It also supports extensions like additional hats and buttons compatible +with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads. Saitek +Cyborg 'digital' joysticks are also supported by this driver, because +they're basically souped up CHF sticks. + + However the only types that can be autodetected are: + +* 2-axis, 4-button joystick +* 3-axis, 4-button joystick +* 4-axis, 4-button joystick +* Saitek Cyborg 'digital' joysticks + + For other joystick types (more/less axes, hats, and buttons) support +you'll need to specify the types either on the kernel command line or on the +module command line, when inserting analog.o into the kernel. The +parameters are: + + js=type,type,type,.... + + 'type' is type of the joystick from the table below, defining joysticks +present on gameports in the system, starting with gameport0, second 'type' +entry defining joystick on gameport1 and so on. + + Type | Meaning + ----------------------------------- + none | No analog joystick on that port + auto | Autodetect joystick + 2btn | 2-button n-axis joystick + y-joy | Two 2-button 2-axis joysticks on an Y-cable + y-pad | Two 2-button 2-axis gamepads on an Y-cable + fcs | Thrustmaster FCS compatible joystick + chf | Joystick with a CH Flightstick compatible hat + fullchf | CH Flightstick compatible with two hats and 6 buttons + gamepad | 4/6-button n-axis gamepad + gamepad8 | 8-button 2-axis gamepad + + In case your joystick doesn't fit in any of the above categories, you can +specify the type as a number by combining the bits in the table below. This +is not recommended unless you really know what are you doing. It's not +dangerous, but not simple either. + + Bit | Meaning + -------------------------- + 0 | Axis X1 + 1 | Axis Y1 + 2 | Axis X2 + 3 | Axis Y2 + 4 | Button A + 5 | Button B + 6 | Button C + 7 | Button D + 8 | CHF Buttons X and Y + 9 | CHF Hat 1 + 10 | CHF Hat 2 + 11 | FCS Hat + 12 | Pad Button X + 13 | Pad Button Y + 14 | Pad Button U + 15 | Pad Button V + 16 | Saitek F1-F4 Buttons + 17 | Saitek Digital Mode + 19 | GamePad + 20 | Joy2 Axis X1 + 21 | Joy2 Axis Y1 + 22 | Joy2 Axis X2 + 23 | Joy2 Axis Y2 + 24 | Joy2 Button A + 25 | Joy2 Button B + 26 | Joy2 Button C + 27 | Joy2 Button D + 31 | Joy2 GamePad + +3.2 Microsoft SideWinder joysticks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Microsoft 'Digital Overdrive' protocol is supported by the sidewinder.c +module. All currently supported joysticks: + +* Microsoft SideWinder 3D Pro +* Microsoft SideWinder Force Feedback Pro +* Microsoft SideWinder Force Feedback Wheel +* Microsoft SideWinder FreeStyle Pro +* Microsoft SideWinder GamePad (up to four, chained) +* Microsoft SideWinder Precision Pro +* Microsoft SideWinder Precision Pro USB + + are autodetected, and thus no module parameters are needed. + + There is one caveat with the 3D Pro. There are 9 buttons reported, +although the joystick has only 8. The 9th button is the mode switch on the +rear side of the joystick. However, moving it, you'll reset the joystick, +and make it unresponsive for about a one third of a second. Furthermore, the +joystick will also re-center itself, taking the position it was in during +this time as a new center position. Use it if you want, but think first. + + The SideWinder Standard is not a digital joystick, and thus is supported +by the analog driver described above. + +3.3 Logitech ADI devices +~~~~~~~~~~~~~~~~~~~~~~~~ + Logitech ADI protocol is supported by the adi.c module. It should support +any Logitech device using this protocol. This includes, but is not limited +to: + +* Logitech CyberMan 2 +* Logitech ThunderPad Digital +* Logitech WingMan Extreme Digital +* Logitech WingMan Formula +* Logitech WingMan Interceptor +* Logitech WingMan GamePad +* Logitech WingMan GamePad USB +* Logitech WingMan GamePad Extreme +* Logitech WingMan Extreme Digital 3D + + ADI devices are autodetected, and the driver supports up to two (any +combination of) devices on a single gameport, using an Y-cable or chained +together. + + Logitech WingMan Joystick, Logitech WingMan Attack, Logitech WingMan +Extreme and Logitech WingMan ThunderPad are not digital joysticks and are +handled by the analog driver described above. Logitech WingMan Warrior and +Logitech Magellan are supported by serial drivers described below. Logitech +WingMan Force and Logitech WingMan Formula Force are supported by the +I-Force driver described below. Logitech CyberMan is not supported yet. + +3.4 Gravis GrIP +~~~~~~~~~~~~~~~ + Gravis GrIP protocol is supported by the grip.c module. It currently +supports: + +* Gravis GamePad Pro +* Gravis BlackHawk Digital +* Gravis Xterminator +* Gravis Xterminator DualControl + + All these devices are autodetected, and you can even use any combination +of up to two of these pads either chained together or using an Y-cable on a +single gameport. + +GrIP MultiPort isn't supported yet. Gravis Stinger is a serial device and is +supported by the stinger driver. Other Gravis joysticks are supported by the +analog driver. + +3.5 FPGaming A3D and MadCatz A3D +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The Assassin 3D protocol created by FPGaming, is used both by FPGaming +themselves and is licensed to MadCatz. A3D devices are supported by the +a3d.c module. It currently supports: + +* FPGaming Assassin 3D +* MadCatz Panther +* MadCatz Panther XL + + All these devices are autodetected. Because the Assassin 3D and the Panther +allow connecting analog joysticks to them, you'll need to load the analog +driver as well to handle the attached joysticks. + + The trackball should work with USB mousedev module as a normal mouse. See +the USB documentation for how to setup an USB mouse. + +3.6 ThrustMaster DirectConnect (BSP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The TM DirectConnect (BSP) protocol is supported by the tmdc.c +module. This includes, but is not limited to: + +* ThrustMaster Millenium 3D Inceptor +* ThrustMaster 3D Rage Pad +* ThrustMaster Fusion Digital Game Pad + + Devices not directly supported, but hopefully working are: + +* ThrustMaster FragMaster +* ThrustMaster Attack Throttle + + If you have one of these, contact me. + + TMDC devices are autodetected, and thus no parameters to the module +are needed. Up to two TMDC devices can be connected to one gameport, using +an Y-cable. + +3.7 Creative Labs Blaster +~~~~~~~~~~~~~~~~~~~~~~~~~ + The Blaster protocol is supported by the cobra.c module. It supports only +the: + +* Creative Blaster GamePad Cobra + + Up to two of these can be used on a single gameport, using an Y-cable. + +3.8 Genius Digital joysticks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The Genius digitally communicating joysticks are supported by the gf2k.c +module. This includes: + +* Genius Flight2000 F-23 joystick +* Genius Flight2000 F-31 joystick +* Genius G-09D gamepad + + Other Genius digital joysticks are not supported yet, but support can be +added fairly easily. + +3.9 InterAct Digital joysticks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The InterAct digitally communicating joysticks are supported by the +interact.c module. This includes: + +* InterAct HammerHead/FX gamepad +* InterAct ProPad8 gamepad + + Other InterAct digital joysticks are not supported yet, but support can be +added fairly easily. + +3.10 PDPI Lightning 4 gamecards +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + PDPI Lightning 4 gamecards are supported by the lightning.c module. +Once the module is loaded, the analog driver can be used to handle the +joysticks. Digitally communicating joystick will work only on port 0, while +using Y-cables, you can connect up to 8 analog joysticks to a single L4 +card, 16 in case you have two in your system. + +3.11 Trident 4DWave / Aureal Vortex +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Soundcards with a Trident 4DWave DX/NX or Aureal Vortex/Vortex2 chipsets +provide an "Enhanced Game Port" mode where the soundcard handles polling the +joystick. This mode is supported by the pcigame.c module. Once loaded the +analog driver can use the enhanced features of these gameports.. + +3.13 Crystal SoundFusion +~~~~~~~~~~~~~~~~~~~~~~~~ + Soundcards with Crystal SoundFusion chipsets provide an "Enhanced Game +Port", much like the 4DWave or Vortex above. This, and also the normal mode +for the port of the SoundFusion is supported by the cs461x.c module. + +3.14 SoundBlaster Live! +~~~~~~~~~~~~~~~~~~~~~~~~ + The Live! has a special PCI gameport, which, although it doesn't provide +any "Enhanced" stuff like 4DWave and friends, is quite a bit faster than +it's ISA counterparts. It also requires special support, hence the +emu10k1-gp.c module for it instead of the normal ns558.c one. + +3.15 SoundBlaster 64 and 128 - ES1370 and ES1371, ESS Solo1 and S3 SonicVibes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + These PCI soundcards have specific gameports. They are handled by the +sound drivers themselves. Make sure you select gameport support in the +joystick menu and sound card support in the sound menu for your appropriate +card. + +3.16 Amiga +~~~~~~~~~~ + Amiga joysticks, connected to an Amiga, are supported by the amijoy.c +driver. Since they can't be autodetected, the driver has a command line. + + amijoy=a,b + + a and b define the joysticks connected to the JOY0DAT and JOY1DAT ports of +the Amiga. + + Value | Joystick type + --------------------- + 0 | None + 1 | 1-button digital joystick + + No more joystick types are supported now, but that should change in the +future if I get an Amiga in the reach of my fingers. + +3.17 Game console and 8-bit pads and joysticks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +See joystick-parport.txt for more info. + +3.18 SpaceTec/LabTec devices +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + SpaceTec serial devices communicate using the SpaceWare protocol. It is +supported by the spaceorb.c and spaceball.c drivers. The devices currently +supported by spaceorb.c are: + +* SpaceTec SpaceBall Avenger +* SpaceTec SpaceOrb 360 + +Devices currently supported by spaceball.c are: + +* SpaceTec SpaceBall 4000 FLX + + In addition to having the spaceorb/spaceball and serport modules in the +kernel, you also need to attach a serial port to it. to do that, run the +inputattach program: + + inputattach --spaceorb /dev/tts/x & +or + inputattach --spaceball /dev/tts/x & + +where /dev/tts/x is the serial port which the device is connected to. After +doing this, the device will be reported and will start working. + + There is one caveat with the SpaceOrb. The button #6, the on the bottom +side of the orb, although reported as an ordinary button, causes internal +recentering of the spaceorb, moving the zero point to the position in which +the ball is at the moment of pressing the button. So, think first before +you bind it to some other function. + +SpaceTec SpaceBall 2003 FLX and 3003 FLX are not supported yet. + +3.19 Logitech SWIFT devices +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The SWIFT serial protocol is supported by the warrior.c module. It +currently supports only the: + +* Logitech WingMan Warrior + +but in the future, Logitech CyberMan (the original one, not CM2) could be +supported as well. To use the module, you need to run inputattach after you +insert/compile the module into your kernel: + + inputattach --warrior /dev/tts/x & + +/dev/tts/x is the serial port your Warrior is attached to. + +3.20 Magellan / Space Mouse +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The Magellan (or Space Mouse), manufactured by LogiCad3d (formerly Space +Systems), for many other companies (Logitech, HP, ...) is supported by the +joy-magellan module. It currently supports only the: + +* Magellan 3D +* Space Mouse + +models, the additional buttons on the 'Plus' versions are not supported yet. + + To use it, you need to attach the serial port to the driver using the + + inputattach --magellan /dev/tts/x & + +command. After that the Magellan will be detected, initialized, will beep, +and the /dev/input/jsX device should become usable. + +3.21 I-Force devices +~~~~~~~~~~~~~~~~~~~~ + All I-Force devices are supported by the iforce.c module. This includes: + +* AVB Mag Turbo Force +* AVB Top Shot Pegasus +* Logitech WingMan Force +* Logitech WingMan Force 3D +* Logitech WingMan Force Wheel +* Logitech WingMan Strike Force 3D +* Guillemot Race Leader Force Feedback + + To use it, you need to attach the serial port to the driver using the + + inputattach --iforce /dev/tts/x & + +command. After that the I-Force device will be detected, and the +/dev/input/jsX device should become usable. + + In case you're using the device via the USB port, the inputattach command +isn't needed. + + The I-Force driver now supports force feedback via the event interface. + +3.22 Gravis Stinger gamepad +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The Gravis Stinger serial port gamepad, designed for use with laptop +computers, is supported by the stinger.c module. To use it, attach the +serial port to the driver using: + + inputattach --stinger /dev/tty/x & + +where x is the number of the serial port. + +4. Troubleshooting +~~~~~~~~~~~~~~~~~~ + There is quite a high probability that you run into some problems. For +testing whether the driver works, if in doubt, use the jstest utility in +some of its modes. The most useful modes are "normal" - for the 1.x +interface, and "old" for the "0.x" interface. You run it by typing: + + jstest --normal /dev/input/js0 + jstest --old /dev/input/js0 + + Additionally you can do a test with the evtest utility: + + evtest /dev/input/event0 + + Oh, and read the FAQ! :) + +5. FAQ +~~~~~~ +Q: Running 'jstest /dev/js0' results in "File not found" error. What's the + cause? +A: The device files don't exist. Create them (see section 2.2). + +Q: Is it possible to connect my old Atari/Commodore/Amiga/console joystick + or pad that uses a 9-pin D-type cannon connector to the serial port of my + PC? +A: Yes, it is possible, but it'll burn your serial port or the pad. It + won't work, of course. + +Q: My joystick doesn't work with Quake / Quake 2. What's the cause? +A: Quake / Quake 2 don't support joystick. Use joy2key to simulate keypresses + for them. + +6. Programming Interface +~~~~~~~~~~~~~~~~~~~~~~~~ + The 1.0 driver uses a new, event based approach to the joystick driver. +Instead of the user program polling for the joystick values, the joystick +driver now reports only any changes of its state. See joystick-api.txt, +joystick.h and jstest.c included in the joystick package for more +information. The joystick device can be used in either blocking or +nonblocking mode and supports select() calls. + + For backward compatibility the old (v0.x) interface is still included. +Any call to the joystick driver using the old interface will return values +that are compatible to the old interface. This interface is still limited +to 2 axes, and applications using it usually decode only 2 buttons, although +the driver provides up to 32. diff -u --recursive --new-file v2.4.9/linux/Documentation/isdn/README linux/Documentation/isdn/README --- v2.4.9/linux/Documentation/isdn/README Sun Aug 13 10:05:32 2000 +++ linux/Documentation/isdn/README Sun Sep 9 10:52:35 2001 @@ -276,6 +276,8 @@ 1 = Add CPN to RING message on Bit 1: 0 = Add CPN to FCON message off 1 = Add CPN to FCON message on + Bit 2: 0 = Add CDN to RING/FCON message off + 1 = Add CDN to RING/FCON message on Last but not least a (at the moment fairly primitive) device to request the line-status (/dev/isdninfo) is made available. diff -u --recursive --new-file v2.4.9/linux/Documentation/joystick-api.txt linux/Documentation/joystick-api.txt --- v2.4.9/linux/Documentation/joystick-api.txt Fri Apr 6 10:42:48 2001 +++ linux/Documentation/joystick-api.txt Wed Dec 31 16:00:00 1969 @@ -1,315 +0,0 @@ - Joystick API Documentation -*-Text-*- - - Ragnar Hojland Espinosa - - - 7 Aug 1998 - - -1. Initialization -~~~~~~~~~~~~~~~~~ - -Open the joystick device following the usual semantics (that is, with open). -Since the driver now reports events instead of polling for changes, -immediately after the open it will issue a series of synthetic events -(JS_EVENT_INIT) that you can read to check the initial state of the -joystick. - -By default, the device is opened in blocking mode. - - int fd = open ("/dev/js0", O_RDONLY); - - -2. Event Reading -~~~~~~~~~~~~~~~~ - - struct js_event e; - read (fd, &e, sizeof(struct js_event)); - -where js_event is defined as - - struct js_event { - __u32 time; /* event timestamp in milliseconds */ - __s16 value; /* value */ - __u8 type; /* event type */ - __u8 number; /* axis/button number */ - }; - -If the read is successful, it will return sizeof(struct js_event), unless -you wanted to read more than one event per read as described in section 3.1. - - -2.1 js_event.type -~~~~~~~~~~~~~~~~~ - -The possible values of ``type'' are - - #define JS_EVENT_BUTTON 0x01 /* button pressed/released */ - #define JS_EVENT_AXIS 0x02 /* joystick moved */ - #define JS_EVENT_INIT 0x80 /* initial state of device */ - -As mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed -events on open. That is, if it's issuing a INIT BUTTON event, the -current type value will be - - int type = JS_EVENT_BUTTON | JS_EVENT_INIT; /* 0x81 */ - -If you choose not to differentiate between synthetic or real events -you can turn off the JS_EVENT_INIT bits - - type &= ~JS_EVENT_INIT; /* 0x01 */ - - -2.2 js_event.number -~~~~~~~~~~~~~~~~~~~ - -The values of ``number'' correspond to the axis or button that -generated the event. Note that they carry separate numeration (that -is, you have both an axis 0 and a button 0). Generally, - - number - 1st Axis X 0 - 1st Axis Y 1 - 2nd Axis X 2 - 2nd Axis Y 3 - ...and so on - -Hats vary from one joystick type to another. Some can be moved in 8 -directions, some only in 4, The driver, however, always reports a hat as two -independent axis, even if the hardware doesn't allow independent movement. - - -2.3 js_event.value -~~~~~~~~~~~~~~~~~~ - -For an axis, ``value'' is a signed integer between -32767 and +32767 -representing the position of the joystick along that axis. If you -don't read a 0 when the joystick is `dead', or if it doesn't span the -full range, you should recalibrate it (with, for example, jscal). - -For a button, ``value'' for a press button event is 1 and for a release -button event is 0. - -Though this - - if (js_event.type == JS_EVENT_BUTTON) { - buttons_state ^= (1 << js_event.number); - } - -may work well if you handle JS_EVENT_INIT events separately, - - if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) { - if (js_event.value) - buttons_state |= (1 << js_event.number); - else - buttons_state &= ~(1 << js_event.number); - } - -is much safer since it can't lose sync with the driver. As you would -have to write a separate handler for JS_EVENT_INIT events in the first -snippet, this ends up being shorter. - - -2.4 js_event.time -~~~~~~~~~~~~~~~~~ - -The time an event was generated is stored in ``js_event.time''. It's a time -in milliseconds since ... well, since sometime in the past. This eases the -task of detecting double clicks, figuring out if movement of axis and button -presses happened at the same time, and similar. - - -3. Reading -~~~~~~~~~~ - -If you open the device in blocking mode, a read will block (that is, -wait) forever until an event is generated and effectively read. There -are two alternatives if you can't afford to wait forever (which is, -admittedly, a long time;) - - a) use select to wait until there's data to be read on fd, or - until it timeouts. There's a good example on the select(2) - man page. - - b) open the device in non-blocking mode (O_NONBLOCK) - - -3.1 O_NONBLOCK -~~~~~~~~~~~~~~ - -If read returns -1 when reading in O_NONBLOCK mode, this isn't -necessarily a "real" error (check errno(3)); it can just mean there -are no events pending to be read on the driver queue. You should read -all events on the queue (that is, until you get a -1). - -For example, - - while (1) { - while (read (fd, &e, sizeof(struct js_event)) > 0) { - process_event (e); - } - /* EAGAIN is returned when the queue is empty */ - if (errno != EAGAIN) { - /* error */ - } - /* do something interesting with processed events */ - } - -One reason for emptying the queue is that if it gets full you'll start -missing events since the queue is finite, and older events will get -overwritten. - -The other reason is that you want to know all what happened, and not -delay the processing till later. - -Why can get the queue full? Because you don't empty the queue as -mentioned, or because too much time elapses from one read to another -and too many events to store in the queue get generated. Note that -high system load may contribute to space those reads even more. - -If time between reads is enough to fill the queue and loose an event, -the driver will switch to startup mode and next time you read it, -synthetic events (JS_EVENT_INIT) will be generated to inform you of -the actual state of the joystick. - -[As for version 1.2.8, the queue is circular and able to hold 64 - events. You can increment this size bumping up JS_BUFF_SIZE in - joystick.h and recompiling the driver.] - - -In the above code, you might as well want to read more than one event -at a time using the typical read(2) functionality. For that, you would -replace the read above with something like - - struct js_event mybuffer[0xff]; - int i = read (fd, mybuffer, sizeof(struct mybuffer)); - -In this case, read would return -1 if the queue was empty, or some -other value in which the number of events read would be i / -sizeof(js_event) Again, if the buffer was full, it's a good idea to -process the events and keep reading it until you empty the driver queue. - - -4. IOCTLs -~~~~~~~~~ - -The joystick driver defines the following ioctl(2) operations. - - /* function 3rd arg */ - #define JSIOCGAXES /* get number of axes char */ - #define JSIOCGBUTTONS /* get number of buttons char */ - #define JSIOCGVERSION /* get driver version int */ - #define JSIOCGNAME(len) /* get identifier string char */ - #define JSIOCSCORR /* set correction values &js_corr */ - #define JSIOCGCORR /* get correction values &js_corr */ - -For example, to read the number of axes - - char number_of_axes; - ioctl (fd, JSIOCGAXES, &number_of_axes); - - -4.1 JSIOGCVERSION -~~~~~~~~~~~~~~~~~ - -JSIOGCVERSION is a good way to check in run-time whether the running -driver is 1.0+ and supports the event interface. If it is not, the -IOCTL will fail. For a compile-time decision, you can test the -JS_VERSION symbol - - #ifdef JS_VERSION - #if JS_VERSION > 0xsomething - - -4.2 JSIOCGNAME -~~~~~~~~~~~~~~ - -JSIOCGNAME(len) allows you to get the name string of the joystick - the same -as is being printed at boot time. The 'len' argument is the length of the -buffer provided by the application asking for the name. It is used to avoid -possible overrun should the name be too long. - - char name[128]; - if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0) - strncpy(name, "Unknown", sizeof(name)); - printf("Name: %s\n", name); - - -4.3 JSIOC[SG]CORR -~~~~~~~~~~~~~~~~~ - -For usage on JSIOC[SG]CORR I suggest you to look into jscal.c They are -not needed in a normal program, only in joystick calibration software -such as jscal or kcmjoy. These IOCTLs and data types aren't considered -to be in the stable part of the API, and therefore may change without -warning in following releases of the driver. - -Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold -information for all axis. That is, struct js_corr corr[MAX_AXIS]; - -struct js_corr is defined as - - struct js_corr { - __s32 coef[8]; - __u16 prec; - __u16 type; - }; - -and ``type'' - - #define JS_CORR_NONE 0x00 /* returns raw values */ - #define JS_CORR_BROKEN 0x01 /* broken line */ - - -5. Backward compatibility -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The 0.x joystick driver API is quite limited and its usage is deprecated. -The driver offers backward compatibility, though. Here's a quick summary: - - struct JS_DATA_TYPE js; - while (1) { - if (read (fd, &js, JS_RETURN) != JS_RETURN) { - /* error */ - } - usleep (1000); - } - -As you can figure out from the example, the read returns immediately, -with the actual state of the joystick. - - struct JS_DATA_TYPE { - int buttons; /* immediate button state */ - int x; /* immediate x axis value */ - int y; /* immediate y axis value */ - }; - -and JS_RETURN is defined as - - #define JS_RETURN sizeof(struct JS_DATA_TYPE) - -To test the state of the buttons, - - first_button_state = js.buttons & 1; - second_button_state = js.buttons & 2; - -The axis values do not have a defined range in the original 0.x driver, -except for that the values are non-negative. The 1.2.8+ drivers use a -fixed range for reporting the values, 1 being the minimum, 128 the -center, and 255 maximum value. - -The v0.8.0.2 driver also had an interface for 'digital joysticks', (now -called Multisystem joysticks in this driver), under /dev/djsX. This driver -doesn't try to be compatible with that interface. - - -6. Final Notes -~~~~~~~~~~~~~~ - -____/| Comments, additions, and specially corrections are welcome. -\ o.O| Documentation valid for at least version 1.2.8 of the joystick - =(_)= driver and as usual, the ultimate source for documentation is - U to "Use The Source Luke" or, at your convenience, Vojtech ;) - - - Ragnar -EOF diff -u --recursive --new-file v2.4.9/linux/Documentation/joystick-parport.txt linux/Documentation/joystick-parport.txt --- v2.4.9/linux/Documentation/joystick-parport.txt Fri Jul 28 12:50:51 2000 +++ linux/Documentation/joystick-parport.txt Wed Dec 31 16:00:00 1969 @@ -1,521 +0,0 @@ - Linux Joystick parport drivers v2.0 - (c) 1998-2000 Vojtech Pavlik - (c) 1998 Andree Borrmann - Sponsored by SuSE ----------------------------------------------------------------------------- - -0. Disclaimer -~~~~~~~~~~~~~ - Any information in this file is provided as-is, without any guarantee that -it will be true. So, use it at your own risk. The possible damages that can -happen include burning your parallel port, and/or the sticks and joystick -and maybe even more. Like when a lightning kills you it is not our problem. - -1. Intro -~~~~~~~~ - The joystick parport drivers are used for joysticks and gamepads not -originally designed for PCs and other computers Linux runs on. Because of -that, PCs usually lack the right ports to connect these devices to. Parallel -port, because of its ability to change single bits at will, and providing -both output and input bits is the most suitable port on the PC for -connecting such devices. - -2. Devices supported -~~~~~~~~~~~~~~~~~~~~ - Many console and 8-bit computer gamepads and joysticks are supported. The -following subsections discuss usage of each. - -2.1 NES and SNES -~~~~~~~~~~~~~~~~ - The Nintendo Entertainment System and Super Nintendo Entertainment System -gamepads are widely available, and easy to get. Also, they are quite easy to -connect to a PC, and don't need much processing speed (108 us for NES and -165 us for SNES, compared to about 1000 us for PC gamepads) to communicate -with them. - - All NES and SNES use the same synchronous serial protocol, clocked from -the computer's side (and thus timing insensitive). To allow up to 5 NES -and/or SNES gamepads connected to the parallel port at once, the output -lines of the parallel port are shared, while one of 5 available input lines -is assigned to each gamepad. - - This protocol is handled by the gamecon.c driver, so that's the one -you'll use for NES and SNES gamepads. - - The main problem with PC parallel ports is that they don't have +5V power -source on any of their pins. So, if you want a reliable source of power -for your pads, use either keyboard or joystick port, and make a pass-through -cable. You can also pull the power directly from the power supply (the red -wire is +5V). - - If you want to use the parallel port only, you can take the power is from -some data pin. For most gamepad and parport implementations only one pin is -needed, and I'd recommend pin 9 for that, the highest data bit. On the other -hand, if you are not planning to use anything else than NES / SNES on the -port, anything between and including pin 4 and pin 9 will work. - -(pin 9) -----> Power - - Unfortunately, there are pads that need a lot more of power, and parallel -ports that can't give much current through the data pins. If this is your -case, you'll need to use diodes (as a prevention of destroying your parallel -port), and combine the currents of two or more data bits together. - - Diodes -(pin 9) ----|>|-------+------> Power - | -(pin 8) ----|>|-------+ - | -(pin 7) ----|>|-------+ - | - : - | -(pin 4) ----|>|-------+ - - Ground is quite easy. On PC's parallel port the ground is on any of the -pins from pin 18 to pin 25. So use any pin of these you like for the ground. - -(pin 18) -----> Ground - - NES and SNES pads have two input bits, Clock and Latch, which drive the -serial transfer. These are connected to pins 2 and 3 of the parallel port, -respectively. - -(pin 2) -----> Clock -(pin 3) -----> Latch - - And the last thing is the NES / SNES data wire. Only that isn't shared and -each pad needs its own data pin. The parallel port pins are: - -(pin 10) -----> Pad 1 data -(pin 11) -----> Pad 2 data -(pin 12) -----> Pad 3 data -(pin 13) -----> Pad 4 data -(pin 15) -----> Pad 5 data - - Note that pin 14 is not used, since it is not an input pin on the parallel -port. - - This is everything you need on the PC's side of the connection, now on to -the gamepads side. The NES and SNES have different connectors. Also, there -are quite a lot of NES clones, and because Nintendo used proprietary -connectors for their machines, the cloners couldn't and used standard D-Cannon -connectors. Anyway, if you've got a gamepad, and it has buttons A, B, Turbo -A, Turbo B, Select and Start, and is connected through 5 wires, then it is -either a NES or NES clone and will work with this connection. SNES gamepads -also use 5 wires, but have more buttons. They will work as well, of course. - -Pinout for NES gamepads Pinout for SNES gamepads - - +----> Power +-----------------------\ - | 7 | o o o o | x x o | 1 - 5 +---------+ 7 +-----------------------/ - | x x o \ | | | | | - | o o o o | | | | | +-> Ground - 4 +------------+ 1 | | | +------------> Data - | | | | | | +---------------> Latch - | | | +-> Ground | +------------------> Clock - | | +----> Clock +---------------------> Power - | +-------> Latch - +----------> Data - -Pinout for NES clone (db9) gamepads Pinout for NES clone (db15) gamepads - - +---------> Clock +-----------------> Data - | +-------> Latch | +---> Ground - | | +-----> Data | | - | | | ___________________ - _____________ 8 \ o x x x x x x o / 1 - 5 \ x o o o x / 1 \ o x x o x x o / - \ x o x o / 15 `~~~~~~~~~~~~~' 9 - 9 `~~~~~~~' 6 | | | - | | | | +----> Clock - | +----> Power | +----------> Latch - +--------> Ground +----------------> Power - -2.2 Multisystem joysticks -~~~~~~~~~~~~~~~~~~~~~~~~~ - In the era of 8-bit machines, there was something like de-facto standard -for joystick ports. They were all digital, and all used D-Cannon 9 pin -connectors (db9). Because of that, a single joystick could be used without -hassle on Atari (130, 800XE, 800XL, 2600, 7200), Amiga, Commodore C64, -Amstrad CPC, Sinclair ZX Spectrum and many other machines. That's why these -joysticks are called "Multisystem". - - Now their pinout: - - +---------> Right - | +-------> Left - | | +-----> Down - | | | +---> Up - | | | | - _____________ -5 \ x o o o o / 1 - \ x o x o / - 9 `~~~~~~~' 6 - | | - | +----> Button - +--------> Ground - - However, as time passed, extension to this standard developed, and these -were not compatible with each other: - - - Atari 130, 800(XL/XE) MSX - - +-----------> Power - +---------> Right | +---------> Right - | +-------> Left | | +-------> Left - | | +-----> Down | | | +-----> Down - | | | +---> Up | | | | +---> Up - | | | | | | | | | - _____________ _____________ -5 \ x o o o o / 1 5 \ o o o o o / 1 - \ x o o o / \ o o o o / - 9 `~~~~~~~' 6 9 `~~~~~~~' 6 - | | | | | | | - | | +----> Button | | | +----> Button 1 - | +------> Power | | +------> Button 2 - +--------> Ground | +--------> Output 3 - +----------> Ground - - Amstrad CPC Commodore C64 - - +-----------> Analog Y - +---------> Right | +---------> Right - | +-------> Left | | +-------> Left - | | +-----> Down | | | +-----> Down - | | | +---> Up | | | | +---> Up - | | | | | | | | | - _____________ _____________ -5 \ x o o o o / 1 5 \ o o o o o / 1 - \ x o o o / \ o o o o / - 9 `~~~~~~~' 6 9 `~~~~~~~' 6 - | | | | | | | - | | +----> Button 1 | | | +----> Button - | +------> Button 2 | | +------> Power - +--------> Ground | +--------> Ground - +----------> Analog X - - And there were many others. - -2.2.1 Multisystem joysticks using db9.c -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - For the Multisystem joysticks, and their derivatives, the db9.c driver -was written. It allows only one joystick / gamepad per parallel port, but -the interface is easy to build and works with almost anything. - - For the basic 1-button Multisystem joystick you connect its wires to the -parallel port like this: - -(pin 1) -----> Power -(pin 18) -----> Ground - -(pin 2) -----> Up -(pin 3) -----> Down -(pin 4) -----> Left -(pin 5) -----> Right -(pin 6) -----> Button 1 - - However, if the joystick is switch based (eg. clicks when you move it), -you might or might not, depending on your parallel port, need 10 kOhm pullup -resistors on each of the direction and button signals, like this: - -(pin 2) ------------+------> Up - Resistor | -(pin 1) --[10kOhm]--+ - - Try without, and if it doesn't work, add them. For TTL based joysticks / -gamepads the pullups are not needed. - - For joysticks with two buttons you connect the second button to pin 7 on -the parallel port. - -(pin 7) -----> Button 2 - - And that's it. - - On a side note, if you have already built a different adapter for use with -the digital joystick driver 0.8.0.2, this is also supported by the db9.c -driver, as device type 8. (See section 3.2) - -2.2.2 Multisystem joysticks using gamecon.c -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - For some people just one joystick per parallel port is not enough, and/or -want to use them on one parallel port together with NES/SNES/PSX pads. This is -possible using the gamecon.c. It supports up to 5 devices of the above types, -including 1 and 2 buttons Multisystem joysticks. - - However, there is nothing for free. To allow more sticks to be used at -once, you need the sticks to be purely switch based (that is non-TTL), and -not to need power. Just a plain simple six switches inside. If your -joystick can do more (eg. turbofire) you'll need to disable it totally first -if you want to use gamecon.c. - - Also, the connection is a bit more complex. You'll need a bunch of diodes, -and one pullup resistor. First, you connect the Directions and the button -the same as for db9, however with the diodes inbetween. - - Diodes -(pin 2) -----|<|----> Up -(pin 3) -----|<|----> Down -(pin 4) -----|<|----> Left -(pin 5) -----|<|----> Right -(pin 6) -----|<|----> Button 1 - - For two button sticks you also connect the other button. - -(pin 7) -----|<|----> Button 2 - - And finally, you connect the Ground wire of the joystick, like done in -this little schematic to Power and Data on the parallel port, as described -for the NES / SNES pads in section 2.1 of this file - that is, one data pin -for each joystick. The power source is shared. - -Data ------------+-----> Ground - Resistor | -Power --[10kOhm]--+ - - And that's all, here we go! - -2.2.3 Multisystem joysticks using turbografx.c -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The TurboGraFX interface, designed by - - Steffen Schwenke - - allows up to 7 Multisystem joysticks connected to the parallel port. In -Steffen's version, there is support for up to 5 buttons per joystick. However, -since this doesn't work reliably on all parallel ports, the turbografx.c driver -supports only one button per joystick. For more information on how to build the -interface, see - - http://www2.burg-halle.de/~schwenke/parport.html - -2.3 Sony Playstation -~~~~~~~~~~~~~~~~~~~~ - - WARNING: PSX support is experimental, and at the moment doesn't seem to -work for most people. If you like adventure, you can try yourself. - - The PSX controller is supported by the gamecon.c. - -Pinout of the PSX controller (compatible with DirectPadPro): - - +---------+---------+---------+ -9 | o o o | o o o | o o o | 1 parallel - \________|_________|________/ port pins - | | | | | | - | | | | | +--------> Clock --- (4) - | | | | +------------> Select --- (3) - | | | +---------------> Power --- (5-9) - | | +------------------> Ground --- (18-25) - | +-------------------------> Command --- (2) - +----------------------------> Data --- (10,11,12,13,15) one only... - - You may have to add pull up/down resistors. Maybe your pad also won't like -the 5V (PSX uses 3.7V). - - Currently the driver supports only one psx pad per parallel port, and these -controllers: - - * Standard PSX Pad - * NegCon PSX Pad - * Analog PSX Pad (red mode) - * Analog PSX Pad (green mode) - -2.4 Sega -~~~~~~~~ - All the Sega controllers are more or less based on the standard 2-button -Multisystem joystick. However, since they don't use switches and use TTL -logic, the only driver usable with them is the db9.c driver. - -2.4.1 Sega Master System -~~~~~~~~~~~~~~~~~~~~~~~~ - The SMS gamepads are almost exactly the same as normal 2-button -Multisystem joysticks. Set the driver to Multi2 mode, use the corresponding -parallel port pins, and the following schematic: - - +-----------> Power - | +---------> Right - | | +-------> Left - | | | +-----> Down - | | | | +---> Up - | | | | | - _____________ -5 \ o o o o o / 1 - \ o o x o / - 9 `~~~~~~~' 6 - | | | - | | +----> Button 1 - | +--------> Ground - +----------> Button 2 - -2.4.2 Sega Genesis aka MegaDrive -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The Sega Genesis (in Europe sold as Sega MegaDrive) pads are an extension -to the Sega Master System pads. They use more buttons (3+1, 5+1, 6+1). Use -the following schematic: - - +-----------> Power - | +---------> Right - | | +-------> Left - | | | +-----> Down - | | | | +---> Up - | | | | | - _____________ -5 \ o o o o o / 1 - \ o o o o / - 9 `~~~~~~~' 6 - | | | | - | | | +----> Button 1 - | | +------> Select - | +--------> Ground - +----------> Button 2 - - The Select pin goes to pin 14 on the parallel port. - -(pin 14) -----> Select - - The rest is the same as for Multi2 joysticks using db9.c - -2.4.3 Sega Saturn -~~~~~~~~~~~~~~~~~ - Sega Saturn has eight buttons, and to transfer that, without hacks like -Genesis 6 pads use, it needs one more select pin. Anyway, it is still -handled by the db9.c driver. Its pinout is very different from anything -else. Use this schematic: - - +-----------> Select 1 - | +---------> Power - | | +-------> Up - | | | +-----> Down - | | | | +---> Ground - | | | | | - _____________ -5 \ o o o o o / 1 - \ o o o o / - 9 `~~~~~~~' 6 - | | | | - | | | +----> Select 2 - | | +------> Right - | +--------> Left - +----------> Power - - Select 1 is pin 14 on the parallel port, Select 2 is pin 16 on the -parallel port. - -(pin 14) -----> Select 1 -(pin 16) -----> Select 2 - - The other pins (Up, Down, Right, Left, Power, Ground) are the same as for -Multi joysticks using db9.c - -3. The drivers -~~~~~~~~~~~~~~ - There are three drivers for the parallel port interfaces. Each, as -described above, allows to connect a different group of joysticks and pads. -Here are described their command lines: - -3.1 gamecon.c -~~~~~~~~~~~~~ - Using gamecon.c you can connect up to five devices to one parallel port. It -uses the following kernel/module command line: - - gc=port,pad1,pad2,pad3,pad4,pad5 - - Where 'port' the number of the parport interface (eg. 0 for parport0). - - And 'pad1' to 'pad5' are pad types connected to different data input pins -(10,11,12,13,15), as described in section 2.1 of this file. - - The types are: - - Type | Joystick/Pad - -------------------- - 0 | None - 1 | SNES pad - 2 | NES pad - 4 | Multisystem 1-button joystick - 5 | Multisystem 2-button joystick - 6 | Sony PSX controller - 7 | N64 pad - - The exact type of the PSX controller type is autoprobed, so you must have -your controller plugged in before initializing. - - Should you want to use more than one of parallel ports at once, you can use -gc_2 and gc_3 as additional command line parameters for two more parallel -ports. - -3.2 db9.c -~~~~~~~~~ - Apart from making an interface, there is nothing difficult on using the -db9.c driver. It uses the following kernel/module command line: - - db9=port,type - - Where 'port' is the number of the parport interface (eg. 0 for parport0). - - Caveat here: This driver only works on bidirectional parallel ports. If -your parallel port is recent enough, you should have no trouble with this. -Old parallel ports may not have this feature. - - 'Type' is the type of joystick or pad attached: - - Type | Joystick/Pad - -------------------- - 0 | None - 1 | Multisystem 1-button joystick - 2 | Multisystem 2-button joystick - 3 | Genesis pad (3+1 buttons) - 5 | Genesis pad (5+1 buttons) - 6 | Genesis pad (6+2 buttons) - 7 | Saturn pad (8 buttons) - 8 | Multisystem 1-button joystick (v0.8.0.2 pin-out) - 9 | Two Multisystem 1-button joysticks (v0.8.0.2 pin-out) - 10 | Amiga CD32 pad - - Should you want to use more than one of these joysticks/pads at once, you -can use db9_2 and db9_3 as additional command line parameters for two -more joysticks/pads. - -3.3 turbografx.c -~~~~~~~~~~~~~~~~ - The turbografx.c driver uses a very simple kernel/module command line: - - tgfx=port,js1,js2,js3,js4,js5,js6,js7 - - Where 'port' is the number of the parport interface (eg. 0 for parport0). - - 'jsX' is the number of buttons the Multisystem joysticks connected to the -interface ports 1-7 have. For a standard multisystem joystick, this is 1. - - Should you want to use more than one of these interfaces at once, you can -use tgfx_2 and tgfx_3 as additional command line parameters for two more -interfaces. - -3.4 PC parallel port pinout -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - .----------------------------------------. - At the PC: \ 13 12 11 10 9 8 7 6 5 4 3 2 1 / - \ 25 24 23 22 21 20 19 18 17 16 15 14 / - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Pin | Name | Description - ~~~~~~|~~~~~~~~~|~~~~~~~~~~ - 1 | /STROBE | Strobe - 2-9 | D0-D7 | Data Bit 0-7 - 10 | /ACK | Acknowledge - 11 | BUSY | Busy - 12 | PE | Paper End - 13 | SELIN | Select In - 14 | /AUTOFD | Autofeed - 15 | /ERROR | Error - 16 | /INIT | Initialize - 17 | /SEL | Select - 18-25 | GND | Signal Ground - -3.5 End -~~~~~~~ - That's all, folks! Have fun! diff -u --recursive --new-file v2.4.9/linux/Documentation/joystick.txt linux/Documentation/joystick.txt --- v2.4.9/linux/Documentation/joystick.txt Fri Jul 28 12:50:51 2000 +++ linux/Documentation/joystick.txt Wed Dec 31 16:00:00 1969 @@ -1,582 +0,0 @@ - Linux Joystick driver v2.0.0 - (c) 1996-2000 Vojtech Pavlik - Sponsored by SuSE ----------------------------------------------------------------------------- - -0. Disclaimer -~~~~~~~~~~~~~ - 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., 59 -Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Should you need to contact me, the author, you can do so either by e-mail -- mail your message to , or by paper mail: Vojtech Pavlik, -Ucitelska 1576, Prague 8, 182 00 Czech Republic - - For your convenience, the GNU General Public License version 2 is included -in the package: See the file COPYING. - -1. Intro -~~~~~~~~ - The joystick driver for Linux provides support for a variety of joysticks -and similar devices. It is based on a larger project aiming to support all -input devices in Linux. - - Should you encounter any problems while using the driver, or joysticks -this driver can't make complete use of, I'm very interested in hearing about -them. Bug reports and success stories are also welcome. - - The input project website is at: - - http://www.suse.cz/development/input/ - http://atrey.karlin.mff.cuni.cz/~vojtech/input/ - - There is also a mailing list for the driver at: - - listproc@atrey.karlin.mff.cuni.cz - -send "subscribe linux-joystick Your Name" to subscribe to it. - -2. Usage -~~~~~~~~ - For basic usage you just choose the right options in kernel config and -you should be set. - -2.1 inpututils -~~~~~~~~~~~~~~ -For testing and other purposes (for example serial devices), a set of -utilities is available at the abovementioned website. I suggest you download -and install it before going on. - -2.2 Device nodes -~~~~~~~~~~~~~~~~ -For applications to be able to use the joysticks, in you don't use devfs, -you'll have to manually create these nodes in /dev: - -cd /dev -rm js* -mkdir input -mknod input/js0 c 13 0 -mknod input/js1 c 13 1 -mknod input/js2 c 13 2 -mknod input/js3 c 13 3 -ln -s input/js0 js0 -ln -s input/js1 js1 -ln -s input/js2 js2 -ln -s input/js3 js3 - -For testing with inpututils it's also convenient to create these: - -mknod input/event0 c 13 64 -mknod input/event1 c 13 65 -mknod input/event2 c 13 66 -mknod input/event3 c 13 67 - -2.4 Modules needed -~~~~~~~~~~~~~~~~~~ - For all joystick drivers to function, you'll need the userland interface -module in kernel, either loaded or compiled in: - - modprobe joydev - - For gameport joysticks, you'll have to load the gameport driver as well; - - modprove ns558 - - And for serial port joysticks, you'll need the serial input line -discipline module loaded and the inputattach utility started: - - modprobe serport - inputattach -xxx /dev/tts/X & - - In addition to that, you'll need the joystick driver module itself, most -usually you'll have an analog joystick: - - modprobe analog - - For automatic module loading, something like this might work: - - alias tty-ldisc-2 serport - alias char-major-13 joydev ns558 analog - -2.5 Verifying that it works -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - For testing the joystick driver functionality, there is the jstest -program in the utilities package. You run it by typing: - - jstest /dev/js0 - - And it should show a line with the joystick values, which update as you -move the stick, and press its buttons. The axes should all be zero when the -joystick is in the center position. They should not jitter by themselves to -other close values, and they also should be steady in any other position of -the stick. They should have the full range from -32767 to 32767. If all this -is met, then it's all fine, and you can play the games. :) - - If it's not, then there might be a problem. Try to calibrate the joystick, -and if it still doesn't work, read the drivers section of this file, the -troubleshooting section, and the FAQ. - -2.6. Calibration -~~~~~~~~~~~~~~~~ - For most joysticks you won't need any manual calibration, since the -joystick should be autocalibrated by the driver automagically. However, with -some analog joysticks, that either do not use linear resistors, or if you -want better precision, you can use the jscal program - - jscal -c /dev/js0 - - included in the joystick package to set better correction coefficients than -what the driver would choose itself. - - After calibrating the joystick you can verify if you like the new -calibration using the jstest command, and if you do, you then can save the -correction coefficients into a file - - jscal -p /dev/js0 > /etc/joystick.cal - - And add a line to your rc script executing that file - - source /etc/joystick.cal - - This way, after the next reboot your joystick will remain calibrated. You -can also add the jscal -p line to your shutdown script. - - -3. HW specific driver information -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In this section each of the separate hardware specific drivers is described. - -3.1 Analog joysticks -~~~~~~~~~~~~~~~~~~~~ - The analog.c uses the standard analog inputs of the gameport, and thus -supports all standard joysticks and gamepads. It uses a very advanced -routine for this, allowing for data precision that can't be found on any -other system. - - It also supports extensions like additional hats and buttons compatible -with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads. Saitek -Cyborg 'digital' joysticks are also supported by this driver, because -they're basically souped up CHF sticks. - - However the only types that can be autodetected are: - -* 2-axis, 4-button joystick -* 3-axis, 4-button joystick -* 4-axis, 4-button joystick -* Saitek Cyborg 'digital' joysticks - - For other joystick types (more/less axes, hats, and buttons) support -you'll need to specify the types either on the kernel command line or on the -module command line, when inserting analog.o into the kernel. The -parameters are: - - js=type,type,type,.... - - 'type' is type of the joystick from the table below, defining joysticks -present on gameports in the system, starting with gameport0, second 'type' -entry defining joystick on gameport1 and so on. - - Type | Meaning - ----------------------------------- - none | No analog joystick on that port - auto | Autodetect joystick - 2btn | 2-button n-axis joystick - y-joy | Two 2-button 2-axis joysticks on an Y-cable - y-pad | Two 2-button 2-axis gamepads on an Y-cable - fcs | Thrustmaster FCS compatible joystick - chf | Joystick with a CH Flightstick compatible hat - fullchf | CH Flightstick compatible with two hats and 6 buttons - gamepad | 4/6-button n-axis gamepad - gamepad8 | 8-button 2-axis gamepad - - In case your joystick doesn't fit in any of the above categories, you can -specify the type as a number by combining the bits in the table below. This -is not recommended unless you really know what are you doing. It's not -dangerous, but not simple either. - - Bit | Meaning - -------------------------- - 0 | Axis X1 - 1 | Axis Y1 - 2 | Axis X2 - 3 | Axis Y2 - 4 | Button A - 5 | Button B - 6 | Button C - 7 | Button D - 8 | CHF Buttons X and Y - 9 | CHF Hat 1 - 10 | CHF Hat 2 - 11 | FCS Hat - 12 | Pad Button X - 13 | Pad Button Y - 14 | Pad Button U - 15 | Pad Button V - 16 | Saitek F1-F4 Buttons - 17 | Saitek Digital Mode - 19 | GamePad - 20 | Joy2 Axis X1 - 21 | Joy2 Axis Y1 - 22 | Joy2 Axis X2 - 23 | Joy2 Axis Y2 - 24 | Joy2 Button A - 25 | Joy2 Button B - 26 | Joy2 Button C - 27 | Joy2 Button D - 31 | Joy2 GamePad - -3.2 Microsoft SideWinder joysticks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Microsoft 'Digital Overdrive' protocol is supported by the sidewinder.c -module. All currently supported joysticks: - -* Microsoft SideWinder 3D Pro -* Microsoft SideWinder Force Feedback Pro -* Microsoft SideWinder Force Feedback Wheel -* Microsoft SideWinder FreeStyle Pro -* Microsoft SideWinder GamePad (up to four, chained) -* Microsoft SideWinder Precision Pro -* Microsoft SideWinder Precision Pro USB - - are autodetected, and thus no module parameters are needed. - - There is one caveat with the 3D Pro. There are 9 buttons reported, -although the joystick has only 8. The 9th button is the mode switch on the -rear side of the joystick. However, moving it, you'll reset the joystick, -and make it unresponsive for about a one third of a second. Furthermore, the -joystick will also re-center itself, taking the position it was in during -this time as a new center position. Use it if you want, but think first. - - The SideWinder Standard is not a digital joystick, and thus is supported -by the analog driver described above. - -3.3 Logitech ADI devices -~~~~~~~~~~~~~~~~~~~~~~~~ - Logitech ADI protocol is supported by the adi.c module. It should support -any Logitech device using this protocol. This includes, but is not limited -to: - -* Logitech CyberMan 2 -* Logitech ThunderPad Digital -* Logitech WingMan Extreme Digital -* Logitech WingMan Formula -* Logitech WingMan Interceptor -* Logitech WingMan GamePad -* Logitech WingMan GamePad USB -* Logitech WingMan GamePad Extreme -* Logitech WingMan Extreme Digital 3D - - ADI devices are autodetected, and the driver supports up to two (any -combination of) devices on a single gameport, using an Y-cable or chained -together. - - Logitech WingMan Joystick, Logitech WingMan Attack, Logitech WingMan -Extreme and Logitech WingMan ThunderPad are not digital joysticks and are -handled by the analog driver described above. Logitech WingMan Warrior and -Logitech Magellan are supported by serial drivers described below. Logitech -WingMan Force and Logitech WingMan Formula Force are supported by the -I-Force driver described below. Logitech CyberMan is not supported yet. - -3.4 Gravis GrIP -~~~~~~~~~~~~~~~ - Gravis GrIP protocol is supported by the grip.c module. It currently -supports: - -* Gravis GamePad Pro -* Gravis BlackHawk Digital -* Gravis Xterminator -* Gravis Xterminator DualControl - - All these devices are autodetected, and you can even use any combination -of up to two of these pads either chained together or using an Y-cable on a -single gameport. - -GrIP MultiPort isn't supported yet. Gravis Stinger is a serial device and -hopefully will be supported soon. Other Gravis joysticks are supported by -the analog driver. - -3.5 FPGaming A3D and MadCatz A3D -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The Assassin 3D protocol created by FPGaming, is used both by FPGaming -themselves and is licensed to MadCatz. A3D devices are supported by the -a3d.c module. It currently supports: - -* FPGaming Assassin 3D -* MadCatz Panther -* MadCatz Panther XL - - All these devices are autodetected. Because the Assassin 3D and the Panther -allow connecting analog joysticks to them, you'll need to load the analog -driver as well to handle the attached joysticks. - - The trackball should work with USB mousedev module as a normal mouse. See -the USB documentation for how to setup an USB mouse. - -3.6 ThrustMaster DirectConnect (BSP) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The TM DirectConnect (BSP) protocol is supported by the tmdc.c -module. This includes, but is not limited to: - -* ThrustMaster Millenium 3D Inceptor -* ThrustMaster 3D Rage Pad -* ThrustMaster Fusion Digital Game Pad - - Devices not directly supported, but hopefully working are: - -* ThrustMaster FragMaster -* ThrustMaster Attack Throttle - - If you have one of these, contact me. - - BSP devices are autodetected, and thus no parameters to the module -are needed. Up to two TMDC devices can be connected to one gameport, using -an Y-cable. - -3.7 Creative Labs Blaster -~~~~~~~~~~~~~~~~~~~~~~~~~ - The Blaster protocol is supported by the cobra.c module. It supports only -the: - -* Creative Blaster GamePad Cobra - - Up to two of these can be used on a single gameport, using an Y-cable. - -3.8 Genius Digital joysticks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The Genius digitally communicating joysticks are supported by the gf2k.c -module. This includes: - -* Genius Flight2000 F-23 joystick -* Genius Flight2000 F-31 joystick -* Genius G-09D gamepad - - Other Genius digital joysticks are not supported yet, but support can be -added fairly easily. - -3.9 InterAct Digital joysticks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The InterAct digitally communicating joysticks are supported by the -interact.c module. This includes: - -* InterAct HammerHead/FX gamepad -* InterAct ProPad8 gamepad - - Other InterAct digital joysticks are not supported yet, but support can be -added fairly easily. - -3.10 PDPI Lightning 4 gamecards -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - PDPI Lightning 4 gamecards are supported by the lightning.c module. -Once the module is loaded, the analog driver can be used to handle the -joysticks. Digitally communicating joystick will work only on port 0, while -using Y-cables, you can connect up to 8 analog joysticks to a single L4 -card, 16 in case you have two in your system. - -3.11 Trident 4DWave / Aureal Vortex -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Soundcards with a Trident 4DWave DX/NX or Aureal Vortex/Vortex2 chipsets -provide an "Enhanced Game Port" mode where the soundcard handles polling the -joystick. This mode is supported by the pcigame.c module. Once loaded the -analog driver can use the enhanced features of these gameports.. - -3.12 Amiga -~~~~~~~~~~ - Amiga joysticks, connected to an Amiga, are supported by the amijoy.c -driver. Since they can't be autodetected, the driver has a command line. - - amijoy=a,b - - a and b define the joysticks connected to the JOY0DAT and JOY1DAT ports of -the Amiga. - - Value | Joystick type - --------------------- - 0 | None - 1 | 1-button digital joystick - - No more joystick types are supported now, but that should change in the -future if I get an Amiga in the reach of my fingers. - -3.13 Game console and 8-bit pads and joysticks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -See joystick-parport.txt for more info. - -3.14 SpaceTec/LabTec devices -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - SpaceTec serial devices communicate using the SpaceWare protocol. It is -supported by the spaceorb.c and spaceball.c drivers. The devices currently -supported by spaceorb.c are: - -* SpaceTec SpaceBall Avenger -* SpaceTec SpaceOrb 360 - -Devices currently supported by spaceball.c are: - -* SpaceTec SpaceBall 4000 FLX - - In addition to having the spaceorb/spaceball and serport modules in the -kernel, you also need to attach a serial port to it. to do that, run the -jsattach program: - - inputattach --spaceorb /dev/tts/x & -or - jsattach --spaceball /dev/tts/x & - -where /dev/tts/x is the serial port which the device is connected to. After -doing this, the device will be reported and will start working. - - There is one caveat with the SpaceOrb. The button #6, the on the bottom -side of the orb, although reported as an ordinary button, causes internal -recentering of the spaceorb, moving the zero point to the position in which -the ball is at the moment of pressing the button. So, think first before -you bind it to some other function. - -SpaceTec SpaceBall 2003 FLX and 3003 FLX are not supported yet. - -3.15 Logitech SWIFT devices -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The SWIFT serial protocol is supported by the warrior.c module. It -currently supports only the: - -* Logitech WingMan Warrior - -but in the future, Logitech CyberMan (the original one, not CM2) could be -supported as well. To use the module, you need to run jsattach after you -insert/compile the module into your kernel: - - inputattach --warrior /dev/tts/x & - -/dev/tts/x is the serial port your Warrior is attached to. - -3.16 Magellan / Space Mouse -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The Magellan (or Space Mouse), manufactured by LogiCad3d (formerly Space -Systems), for many other companies (Logitech, HP, ...) is supported by the -joy-magellan module. It currently supports only the: - -* Magellan 3D -* Space Mouse - -models, the additional buttons on the 'Plus' versions are not supported yet. - - To use it, you need to attach the serial port to the driver using the - - inputattach --magellan /dev/tts/x & - -command. After that the Magellan will be detected, initialized, will beep, -and the /dev/input/jsX device should become usable. - -3.17 I-Force devices -~~~~~~~~~~~~~~~~~~~~ - All I-Force devices ale supported by the iforce.c module. This includes, -but is not limited to: - -* Logitech WingMan Force -* Logitech WingMan Force Wheel -* Guillemot Race Leader wheel - - To use it, you need to attach the serial port to the driver using the - - inputattach --iforce /dev/tts/x & - -command. After that the I-Force device will be detected, and the -/dev/input/jsX device should become usable. - - In case you're using the device via the USB port, the inputattach command -isn't needed. - -4. Troubleshooting -~~~~~~~~~~~~~~~~~~ - There is quite a high probability that you run into some problems. For -testing whether the driver works, if in doubt, use the jstest utility in -some of its modes. The most useful modes are "normal" - for the 1.x -interface, and "old" for the "0.x" interface. You run it by typing: - - jstest --normal /dev/input/js0 - jstest --old /dev/input/js0 - - Additionally you can do a test with the evtest utility: - - evtest /dev/input/event0 - - Oh, and read the FAQ! :) - -5. FAQ -~~~~~~ -Q: Running 'jstest /dev/js0' results in "File not found" error. What's the - cause? -A: The device files don't exist. Create them (see section 2.2). - -Q: Is it possible to connect my old Atari/Commodore/Amiga/console joystick - or pad that uses a 9-pin D-type cannon connector to the serial port of my - PC? -A: Yes, it is possible, but it'll burn your serial port or the pad. It - won't work, of course. - -Q: My joystick doesn't work with Quake / Quake 2. What's the cause? -A: Quake / Quake 2 don't support joystick. Use joy2key to simulate keypresses - for them. - -6. Programming Interface -~~~~~~~~~~~~~~~~~~~~~~~~ - The 1.0 driver uses a new, event based approach to the joystick driver. -Instead of the user program polling for the joystick values, the joystick -driver now reports only any changes of its state. See joystick-api.txt, -joystick.h and jstest.c included in the joystick package for more -information. The joystick device can be used in either blocking or -nonblocking mode and supports select() calls. - - For backward compatibility the old (v0.x) interface is still included. -Any call to the joystick driver using the old interface will return values -that are compatible to the old interface. This interface is still limited -to 2 axes, and applications using it usually decode only 2 buttons, although -the driver provides up to 32. - -7. Credits -~~~~~~~~~~ - Thanks to the following people who contributed code, ideas or specifications -to the joystick driver development: - - Arthur C. Smith - Eyal Lebedinsky - Jeff Tranter - Carlos Puchol - Matt Rhoten - Dan Fandrich - Sverker Wilberg - Hal Maney - Bernd Schmidt - Alan Cox - John Markus Bjorndalen - Boris Muehmer - Robert W. Grubbs - Pete Chown - Benji York - Leslie F. Donaldson - Eng-Jon Ong - Ragnar Hojland Espinosa - Brian Gerst - Andree Borrmann - Martin Giguere - David Thompson - Justin Wake - Benoit Triquet - John Dahlstrom - Dan Gohman - Joe Krahn - David Kuder - Raymond Ingles - - If you think you should be in this list and are not, it's possible that -I forgot to include you - contact me and I'll correct the error. :) 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/nmi_watchdog.txt linux/Documentation/nmi_watchdog.txt --- v2.4.9/linux/Documentation/nmi_watchdog.txt Mon Aug 21 08:57:35 2000 +++ linux/Documentation/nmi_watchdog.txt Mon Sep 17 23:03:09 2001 @@ -1,19 +1,27 @@ -Is your SMP system locking up unpredictably? No keyboard activity, just +Is your ix86 system locking up unpredictably? No keyboard activity, just a frustrating complete hard lockup? Do you want to help us debugging such lockups? If all yes then this document is definitely for you. -on Intel SMP hardware there is a feature that enables us to generate -'watchdog NMI interrupts'. (NMI: Non Maskable Interrupt - these get -executed even if the system is otherwise locked up hard) This can be -used to debug hard kernel lockups. By executing periodic NMI interrupts, -the kernel can monitor whether any CPU has locked up, and print out -debugging messages if so. You can enable/disable the NMI watchdog at boot -time with the 'nmi_watchdog=1' boot parameter. Eg. the relevant -lilo.conf entry: +On Intel and similar ix86 type hardware there is a feature that enables +us to generate 'watchdog NMI interrupts'. (NMI: Non Maskable Interrupt +which get executed even if the system is otherwise locked up hard). +This can be used to debug hard kernel lockups. By executing periodic +NMI interrupts, the kernel can monitor whether any CPU has locked up, +and print out debugging messages if so. You must enable the NMI +watchdog at boot time with the 'nmi_watchdog=n' boot parameter. Eg. +the relevant lilo.conf entry: append="nmi_watchdog=1" +For SMP machines and UP machines with an IO-APIC use nmi_watchdog=1. +For UP machines without an IO-APIC use nmi_watchdog=2, this only works +for some processor types. If in doubt, boot with nmi_watchdog=1 and +check the NMI count in /proc/interrupts; if the count is zero then +reboot with nmi_watchdog=2 and check the NMI count. If it is still +zero then log a problem, you probably have a processor that needs to be +added to the nmi code. + A 'lockup' is the following scenario: if any CPU in the system does not execute the period local timer interrupt for more than 5 seconds, then the NMI handler generates an oops and kills the process. This @@ -24,8 +32,9 @@ cannot even accept NMI interrupts, or the crash has made the kernel unable to print messages. -NOTE: currently the NMI-oopser is enabled unconditionally on x86 SMP -boxes. +NOTE: starting with 2.4.2-ac18 the NMI-oopser is disabled by default, +you have to enable it with a boot time parameter. Prior to 2.4.2-ac18 +the NMI-oopser is enabled unconditionally on x86 SMP boxes. [ feel free to send bug reports, suggestions and patches to Ingo Molnar or the Linux SMP mailing diff -u --recursive --new-file v2.4.9/linux/Documentation/parisc/registers linux/Documentation/parisc/registers --- v2.4.9/linux/Documentation/parisc/registers Tue Dec 5 12:29:38 2000 +++ linux/Documentation/parisc/registers Fri Sep 14 14:04:06 2001 @@ -16,17 +16,17 @@ CR11 as specified by ABI CR14 (interruption vector) initialized to fault_vector CR15 (EIEM) initialized to all ones* -CR16 (Interval Timer) timer interrupt +CR16 (Interval Timer) read for cycle count/write starts Interval Tmr CR17-CR22 interruption parameters -CR23 (EIRR) read for pending interrupts +CR23 (EIRR) read for pending interrupts/write clears bits CR24 (TR 0) Kernel Space Page Directory Pointer CR25 (TR 1) User Space Page Directory Pointer -CR26 (TR 2) -CR27 (TR 3) -CR28 (TR 4) used by interruption handlers -CR29 (TR 5) used by interruption handlers +CR26 (TR 2) not used +CR27 (TR 3) Thread descriptor pointer +CR28 (TR 4) not used +CR29 (TR 5) not used CR30 (TR 6) current / 0 -CR31 (TR 7) used by interruption handlers +CR31 (TR 7) Temporary register, used in various places Space Registers (kernel mode) 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/sound/btaudio linux/Documentation/sound/btaudio --- v2.4.9/linux/Documentation/sound/btaudio Sun Aug 12 13:27:58 2001 +++ linux/Documentation/sound/btaudio Tue Sep 18 14:25:27 2001 @@ -31,23 +31,28 @@ should'nt crash your box. It might not work as expected, have bugs, not being fully OSS API compilant, ... +Latest versions are available from http://bytesex.org/bttv/, the +driver is in the bttv tarball. Kernel patches might be available too, +have a look at http://bytesex.org/bttv/listing.html. + +The chip knows two different modes. btaudio registers two dsp +devices, one for each mode. They can not be used at the same time. + Digital audio mode ================== -The chip knows different modes. Right now you have to pick the one you -want to use at insmod time. Digital audio mode is the default. The -chip gives you 16 bit stereo sound with ~32 kHz sample rate. According -to the specs it should be possible to get up to 48 kHz, but I havn't -figured out yet how this works. The specs are not very verbose :-( - -Lower sample rates are possible too, but the code isn't written yet. -For now you are limited to the fixed 32 kHz. Mono works throuth, the -driver will do that in software for you. - -With my Hauppauge I get clear sound, but I got also reports saying that -digital audio mode does'nt work. Guess Hauppauge connected the msp34xx -output to the bt878's I2S digital audio input port. +The chip gives you 16 bit stereo sound. The sample rate depends on +the external source which feeds the bt878 with digital sound via I2S +interface. There is a insmod option (rate) to tell the driver which +sample rate the hardware uses (32000 is the default). + +One possible source for digital sound is the msp34xx audio processor +chip which provides digital sound via I2S with 32 kHz sample rate. My +Hauppauge board works this way. + +The Osprey-200 reportly gives you digital sound with 44100 Hz sample +rate. It is also possible that you get no sound at all. analog mode (A/D) @@ -67,11 +72,17 @@ by the mixer device). Others get a useable signal on line1. -more hints -========== +some examples +============= + +* read audio data from btaudio (dsp2), send to es1730 (dsp,dsp1): + $ sox -w -r 32000 -t ossdsp /dev/dsp2 -t ossdsp /dev/dsp + +* read audio data from btaudio, send to esound daemon (which might be + running on another host): + $ sox -c 2 -w -r 32000 -t ossdsp /dev/dsp2 -t sw - | esdcat -r 32000 + $ sox -c 1 -w -r 32000 -t ossdsp /dev/dsp2 -t sw - | esdcat -m -r 32000 -/me uses "sox -w -r 32000 -t ossdsp /dev/dsp2 -t ossdsp /dev/dsp" -to dump audio data from btaudio (dsp2) to es1730 (dsp,dsp1). Have fun, diff -u --recursive --new-file v2.4.9/linux/Documentation/sysctl/vm.txt linux/Documentation/sysctl/vm.txt --- v2.4.9/linux/Documentation/sysctl/vm.txt Wed Mar 14 14:39:07 2001 +++ linux/Documentation/sysctl/vm.txt Mon Sep 10 14:36:25 2001 @@ -33,32 +33,29 @@ This file controls the operation of the bdflush kernel daemon. The source code to this struct can be found in linux/fs/buffer.c. It currently contains 9 integer values, -of which 6 are actually used by the kernel. +of which 4 are actually used by the kernel. From linux/fs/buffer.c: -------------------------------------------------------------- -union bdflush_param{ - struct { - int nfract; /* Percentage of buffer cache dirty to - activate bdflush */ - int ndirty; /* Maximum number of dirty blocks to - write out per wake-cycle */ - int nrefill; /* Number of clean buffers to try to - obtain each time we call refill */ - int nref_dirt; /* Dirty buffer threshold for activating - bdflush when trying to refill buffers. */ - int dummy1; /* unused */ - int age_buffer; /* Time for normal buffer to age before - we flush it */ - int age_super; /* Time for superblock to age before we - flush it */ - int dummy2; /* unused */ - int dummy3; /* unused */ - } b_un; - unsigned int data[N_PARAM]; -} bdf_prm = {{40, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}}; +union bdflush_param { + struct { + int nfract; /* Percentage of buffer cache dirty to + activate bdflush */ + int dummy1; /* old "ndirty" */ + int dummy2; /* old "nrefill" */ + int dummy3; /* unused */ + int interval; /* jiffies delay between kupdate flushes */ + int age_buffer; /* Time for normal buffer to age */ + int nfract_sync;/* Percentage of buffer cache dirty to + activate bdflush synchronously */ + int dummy4; /* unused */ + int dummy5; /* unused */ + } b_un; + unsigned int data[N_PARAM]; +} bdf_prm = {{30, 64, 64, 256, 5*HZ, 30*HZ, 60, 0, 0}}; -------------------------------------------------------------- +int nfract: The first parameter governs the maximum number of dirty buffers in the buffer cache. Dirty means that the contents of the buffer still have to be written to disk (as opposed @@ -66,32 +63,31 @@ Setting this to a high value means that Linux can delay disk writes for a long time, but it also means that it will have to do a lot of I/O at once when memory becomes short. A low -value will spread out disk I/O more evenly. - -The second parameter (ndirty) gives the maximum number of -dirty buffers that bdflush can write to the disk in one time. -A high value will mean delayed, bursty I/O, while a small -value can lead to memory shortage when bdflush isn't woken -up often enough... - -The third parameter (nrefill) is the number of buffers that -bdflush will add to the list of free buffers when -refill_freelist() is called. It is necessary to allocate free -buffers beforehand, since the buffers often are of a different -size than memory pages and some bookkeeping needs to be done -beforehand. The higher the number, the more memory will be -wasted and the less often refill_freelist() will need to run. - -When refill_freelist() comes across more than nref_dirt dirty -buffers, it will wake up bdflush. - -Finally, the age_buffer and age_super parameters govern the -maximum time Linux waits before writing out a dirty buffer -to disk. The value is expressed in jiffies (clockticks), the -number of jiffies per second is 100, except on Alpha machines -(1024). Age_buffer is the maximum age for data blocks, while -age_super is for filesystem metadata. - +value will spread out disk I/O more evenly, at the cost of +more frequent I/O operations. The default value is 30%, +the minimum is 0%, and the maximum is 100%. + +int interval: +The fifth parameter, interval, is the minimum rate at +which kupdate will wake and flush. The value is expressed in +jiffies (clockticks), the number of jiffies per second is +normally 100 (Alpha is 1024). Thus, x*HZ is x seconds. The +default value is 5 seconds, the minimum is 0 seconds, and the +maximum is 600 seconds. + +int age_buffer: +The sixth parameter, age_buffer, governs the maximum time +Linux waits before writing out a dirty buffer to disk. The +value is in jiffies. The default value is 30 seconds, +the minimum is 1 second, and the maximum 6,000 seconds. + +int nfract_sync: +The seventh parameter, nfract_sync, governs the percentage +of buffer cache that is dirty before bdflush activates +synchronously. This can be viewed as the hard limit before +bdflush forces buffers to disk. The default is 60%, the +minimum is 0%, and the maximum is 100%. + ============================================================== buffermem: diff -u --recursive --new-file v2.4.9/linux/Documentation/sysrq.txt linux/Documentation/sysrq.txt --- v2.4.9/linux/Documentation/sysrq.txt Thu May 24 15:03:06 2001 +++ linux/Documentation/sysrq.txt Mon Sep 17 22:52:35 2001 @@ -1,26 +1,27 @@ +Linux Magic System Request Key Hacks +Documentation for sysrq.c version 1.15 +Last update: $Date: 2001/01/28 10:15:59 $ - MAGIC SYSRQ KEY DOCUMENTATION v1.32 - ------------------------------------ - [Sat Apr 8 22:15:03 CEST 2000] - -* What is the magic SysRQ key? +* What is the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -It is a 'magical' key combo you can hit which kernel will respond to +It is a 'magical' key combo you can hit which the kernel will respond to regardless of whatever else it is doing, unless it is completely locked up. -* How do I enable the magic SysRQ key? +* How do I enable the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when -configuring the kernel. This option is only available in 2.1.x or later -kernels. Once you boot the new kernel, you need to enable it manually -using following command: +configuring the kernel. When running on a kernel with SysRq compiled in, it +may be DISABLED at run-time using following command: + + echo "0" > /proc/sys/kernel/sysrq - echo "1" > /proc/sys/kernel/sysrq +Note that previous versions disabled sysrq by default, and you were required +to specifically enable it at run-time. That is not the case any longer. -* How do I use the magic SysRQ key? +* How do I use the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -On x86 - You press the key combo 'ALT-SysRQ-'. Note - Some - (older?) may not have a key labeled 'SysRQ'. The 'SysRQ' key is +On x86 - You press the key combo 'ALT-SysRq-'. Note - Some + keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is also known as the 'Print Screen' key. On SPARC - You press 'ALT-STOP-', I believe. @@ -33,14 +34,14 @@ Print Screen (or F13) - may suffice. On other - If you know of the key combos for other architectures, please - let me know so I can add them to this section. + let me know so I can add them to this section. * What are the 'command' keys? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'r' - Turns off keyboard raw mode and sets it to XLATE. -'k' - Secure Access Key (SAK) Kills all programs on the current virtual - console. NOTE: See important comments below in SAK section. +'k' - Secure Access Key (SAK) Kills all programs on the current virtual + console. NOTE: See important comments below in SAK section. 'b' - Will immediately reboot the system without syncing or unmounting your disks. @@ -70,8 +71,8 @@ 'l' - Send a SIGKILL to all processes, INCLUDING init. (Your system will be non-functional after this.) -'h' - Will display help ( actually any other key than those listed - above will display help. but 'h' is easy to remember :-) +'h' - Will display help ( actually any other key than those listed + above will display help. but 'h' is easy to remember :-) * Okay, so what can I use them for? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -83,8 +84,8 @@ and thus letting you make sure that the login prompt you see is actually the one from init, not some trojan program. IMPORTANT:In its true form it is not a true SAK like the one in :IMPORTANT -IMPORTATN:c2 compliant systems, and it should be mistook as such. :IMPORTANT - It seems other find it useful as (System Attention Key) which is +IMPORTANT:c2 compliant systems, and it should be mistook as such. :IMPORTANT + It seems other find it useful as (System Attention Key) which is useful when you want to exit a program that will not let you switch consoles. (For example, X or a svgalib program.) @@ -93,7 +94,7 @@ 'S'ync is great when your system is locked up, it allows you to sync your disks and will certainly lessen the chance of data loss and fscking. Note -that the sync hasn't taken place until you see the "OK" and "Done" appear +that the sync hasn't taken place until you see the "OK" and "Done" appear on the screen. (If the kernel is really in strife, you may not ever get the OK or Done message...) @@ -111,30 +112,72 @@ are unable to kill any other way, especially if it's spawning other processes. -* Sometimes SysRQ seems to get 'stuck' after using it, what can I do? +* Sometimes SysRq seems to get 'stuck' after using it, what can I do? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ That happens to me, also. I've found that tapping shift, alt, and control on both sides of the keyboard, and hitting an invalid sysrq sequence again will fix the problem. (ie, something like alt-sysrq-z). Switching to another virtual console (ALT+Fn) and then back again should also help. -* I hit SysRQ, but nothing seems to happen, what's wrong? +* I hit SysRq, but nothing seems to happen, what's wrong? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There are some keyboards that send different scancodes for SysRQ than the -pre-defined 0x54. So if SysRQ doesn't work out of the box for a certain -keyboard, run 'showkey -s' to find out the proper scancode sequence. Then -use 'setkeycodes 84' to define this sequence to the usual SysRQ +There are some keyboards that send different scancodes for SysRq than the +pre-defined 0x54. So if SysRq doesn't work out of the box for a certain +keyboard, run 'showkey -s' to find out the proper scancode sequence. Then +use 'setkeycodes 84' to define this sequence to the usual SysRq code (84 is decimal for 0x54). It's probably best to put this command in a -boot script. Oh, and by the way, you exit 'showkey' by not typing anything +boot script. Oh, and by the way, you exit 'showkey' by not typing anything for ten seconds. +* I want to add SysRQ key events to a module, how does it work? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In order to register a basic function with the table, you must first include +the header 'include/linux/sysrq.h', this will define everything else you need. +Next, you must create a sysrq_key_op struct, and populate it with A) the key +handler function you will use, B) a help_msg string, that will print when SysRQ +prints help, and C) an action_msg string, that will print right before your +handler is called. Your handler must conform to the protoype in 'sysrq.h'. + +After the sysrq_key_op is created, you can call the macro +register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in +sysrq.h, this will register the operation pointed to by 'op_p' at table +key 'key', if that slot in the table is blank. At module unload time, you must +call the macro unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which +will remove the key op pointed to by 'op_p' from the key 'key', if and only if +it is currently registered in that slot. This is in case the slot has been +overwritten since you registered it. + +The Magic SysRQ system works by registering key operations against a key op +lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has +a number of operations registered into it at compile time, but is mutable, +and 4 functions are exported for interface to it: __sysrq_lock_table, +__sysrq_unlock_table, __sysrq_get_key_op, and __sysrq_put_key_op. The +functions __sysrq_swap_key_ops and __sysrq_swap_key_ops_nolock are defined +in the header itself, and the REGISTER and UNREGISTER macros are built fromi +these. More complex (and dangerous!) manipulations of the table are possible +using these functions, but you must be careful to always lock the table before +you read or write from it, and to unlock it again when you are done. (And of +course, to never ever leave an invalid pointer in the table). Null pointers in +the table are always safe :) + +If for some reason you feel the need to call the handle_sysrq function from +within a function called by handle_sysrq, you must be aware that you are in +a lock (you are also in an interupt handler, which means don't sleep!), so +you must call __handle_sysrq_nolock instead. + * I have more questions, who can I ask? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You may feel free to send email to myrdraal@deathsdoor.com, and I will -respond as soon as possible. +respond as soon as possible. -Myrdraal +And I'll answer any questions about the registration system you got, also +responding as soon as possible. + -Crutcher + * Credits ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Written by Mydraal Updated by Adam Sulmicki +Updated by Jeremy M. Dolan 2001/01/28 10:15:59 +Added to by Crutcher Dunnavant diff -u --recursive --new-file v2.4.9/linux/Documentation/usb/hiddev.txt linux/Documentation/usb/hiddev.txt --- v2.4.9/linux/Documentation/usb/hiddev.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/hiddev.txt Wed Sep 12 15:34:06 2001 @@ -0,0 +1,162 @@ +Care and feeding of your Human Interface Devices + +INTRODUCTION + +In addition to the normal input type HID devices, USB also uses the +human interface device protocols for things that are not really human +interfaces, but have similar sorts of communication needs. The two big +examples for this are power devices (especially uninterruptable power +supplies) and monitor control on higher end monitors. + +To support these disparite requirements, the Linux USB system provides +HID events to two seperate interfaces: +* the input subsystem, which converts HID events into normal input +device interfaces (such as keyboard, mouse and joystick) and a +normalised event interface - see Documentation/input/input.txt +* the hiddev interface, which provides fairly raw HID events + +The data flow for a HID event produced by a device is something like +the following : + + usb.c ---> hid.c ----> input.c ----> [keyboard/mouse/joystick/event] + | + | + --> hiddev.c ----> POWER / MONITOR CONTROL + +In addition, other subsystems (apart from USB) can potentially feed +events into the input subsystem, but these have no effect on the hid +device interface. + +USING THE HID DEVICE INTERFACE + +The hiddev interface is a char interface using the normal USB major, +with the minor numbers starting at 96 and finishing at 111. Therefore, +you need the following commands: +mknod /dev/usb/hiddev0 c 180 96 +mknod /dev/usb/hiddev1 c 180 97 +mknod /dev/usb/hiddev2 c 180 98 +mknod /dev/usb/hiddev3 c 180 99 +mknod /dev/usb/hiddev4 c 180 100 +mknod /dev/usb/hiddev5 c 180 101 +mknod /dev/usb/hiddev6 c 180 102 +mknod /dev/usb/hiddev7 c 180 103 +mknod /dev/usb/hiddev8 c 180 104 +mknod /dev/usb/hiddev9 c 180 105 +mknod /dev/usb/hiddev10 c 180 106 +mknod /dev/usb/hiddev11 c 180 107 +mknod /dev/usb/hiddev12 c 180 108 +mknod /dev/usb/hiddev13 c 180 109 +mknod /dev/usb/hiddev14 c 180 110 +mknod /dev/usb/hiddev15 c 180 111 + +So you point your hiddev compliant user-space program at the correct +interface for your device, and it all just works. + +Assuming that you have a hiddev compliant user-space program, of +course. If you need to write one, read on. + + +THE HIDDEV API +This description should be read in conjunction with the HID +specification, freely available from http://www.usb.org, and +conveniently linked of http://www.linux-usb.org. + +The hiddev API uses a read() interface, and a set of ioctl() calls. + + +read(): +This is the event interface. When the HID device performs an +interrupt transfer, indicating a change of state, data will be made +available at the associated hiddev device with the content of a struct +hiddev_event: + + struct hiddev_event { + unsigned hid; + signed int value; + }; + +containing the HID usage identifier for the status that changed, and +the value that it was changed to. Note that the structure is defined +within , along with some other useful #defines and +structures. + + +ioctl(): +This is the control interface. There are a number of controls: + +HIDIOCGVERSION - int (read) +Gets the version code out of the hiddev driver. + +HIDIOCAPPLICATION - (none) +This ioctl call returns the HID application usage associated with the +hid device. The third argument to ioctl() specifies which application +index to get. This is useful when the device has more than one +application collection. If the index is invalid (greater or equal to +the number of application collections this device has) the ioctl +returns -1. You can find out beforehand how many application +collections the device has from the num_applications field from the +hiddev_devinfo structure. + +HIDIOCGDEVINFO - struct hiddev_devinfo (read) +Gets a hiddev_devinfo structure which describes the device. + +HIDIOCGSTRING - struct struct hiddev_string_descriptor (read/write) +Gets a string descriptor from the device. The caller must fill in the +"index" field to indicate which descriptor should be returned. + +HIDIOCINITREPORT - (none) +Instructs the kernel to retrieve all input and feature report values +from the device. At this point, all the usage structures will contain +current values for the device, and will maintain it as the device +changes. + +HIDIOCGNAME - string (variable length) +Gets the device name + +HIDIOCGREPORT - struct hiddev_report_info (write) +Instructs the kernel to get a feature or input report from the device, +in order to selectively update the usage structures (in contrast to +INITREPORT). + +HIDIOCSREPORT - struct hiddev_report_info (write) +Instructs the kernel to send a report to the device. This report can +be filled in by the user through HIDIOCSUSAGE calls (below) to fill in +individual usage values in the report beforesending the report in full +to the device. + +HIDIOCGREPORTINFO - struct hiddev_report_info (read/write) +Fills in a hiddev_report_info structure for the user. The report is +looked up by type (input, output or feature) and id, so these fields +must be filled in by the user. The ID can be absolute -- the actual +report id as reported by the device -- or relative -- +HID_REPORT_ID_FIRST for the first report, and (HID_REPORT_ID_NEXT | +report_id) for the next report after report_id. Without a-priori +information about report ids, the right way to use this ioctl is to +use the relative IDs above to enumerate the valid IDs. The ioctl +returns non-zero when there is no more next ID. The real report ID is +filled into the returned hiddev_report_info structure. + +HIDIOCGFIELDINFO - struct hiddev_field_info (read/write) +Returns the field information associated with a report in a +hiddev_field_info structure. The user must fill in report_id and +report_type in this structure, as above. The field_index should also +be filled in, which should be a number from 0 and maxfield-1, as +returned from a previous HIDIOCGREPORTINFO call. + +HIDIOCGUCODE - struct hiddev_usage_ref (read/write) +Returns the usage_code in a hiddev_usage_ref structure, given that +given its report type, report id, field index, and index within the +field have already been filled into the structure. + +HIDIOCGUSAGE - struct hiddev_usage_ref (read/write) +Returns the value of a usage in a hiddev_usage_ref structure. The +usage to be retrieved can be specified as above, or the user can +choose to fill in the report_type field and specify the report_id as +HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be +filled in with the report and field infomation associated with this +usage if it is found. + +HIDIOCSUSAGE - struct hiddev_usage_ref (write) +Sets the value of a usage in an output report. + + diff -u --recursive --new-file v2.4.9/linux/Documentation/usb/input.txt linux/Documentation/usb/input.txt --- v2.4.9/linux/Documentation/usb/input.txt Fri Jul 28 12:50:52 2000 +++ linux/Documentation/usb/input.txt Wed Dec 31 16:00:00 1969 @@ -1,306 +0,0 @@ - Linux Input drivers v1.0 - (c) 1999-2000 Vojtech Pavlik - Sponsored by SuSE - $Id: input.txt,v 1.4 2000/05/28 17:57:22 vojtech Exp $ ----------------------------------------------------------------------------- - -0. Disclaimer -~~~~~~~~~~~~~ - 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., 59 -Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Should you need to contact me, the author, you can do so either by e-mail -- mail your message to , or by paper mail: Vojtech Pavlik, -Ucitelska 1576, Prague 8, 182 00 Czech Republic - - For your convenience, the GNU General Public License version 2 is included -in the package: See the file COPYING. - -1. Introduction -~~~~~~~~~~~~~~~ - This is a collection of drivers that is designed to support all input -devices under Linux. However, in the current kernels, although it's -possibilities are much bigger, it's limited to USB devices only. This is -also why it resides in the drivers/usb subdirectory. - - The center of the input drivers is the input.o module, which must be -loaded before any other of the input modules - it serves as a way of -communication between two groups of modules: - -1.1 Device drivers -~~~~~~~~~~~~~~~~~~ - These modules talk to the hardware (for example via USB), and provide -events (keystrokes, mouse movements) to the input.o module. - -1.2 Event handlers -~~~~~~~~~~~~~~~~~~ - These modules get events from input.o and pass them where needed via -various interfaces - keystrokes to the kernel, mouse movements via a -simulated PS/2 interface to GPM and X and so on. - -2. Simple Usage -~~~~~~~~~~~~~~~ - For the most usual configuration, with one USB mouse and one USB keyboard, -you'll have to load the following modules (or have them built in to the -kernel): - - input.o - mousedev.o - keybdev.o - usbcore.o - usb-[uo]hci.o - hid.o - - After this, the USB keyboard will work straight away, and the USB mouse -will be available as a character device on major 13, minor 63: - - crw-r--r-- 1 root root 13, 63 Mar 28 22:45 mice - - This device, has to be created, unless you use devfs, in which case it's -created automatically. The commands to do that are: - - cd /dev - mkdir input - mknod input/mice c 13 63 - - After that you have to point GPM (the textmode mouse cut&paste tool) and -XFree to this device to use it - GPM should be called like: - - gpm -t ps2 -m /dev/input/mice - - And in X: - - Section "Pointer" - Protocol "ImPS/2" - Device "/dev/input/mice" - ZAxisMapping 4 5 - EndSection - - When you do all of the above, you can use your USB mouse and keyboard. - -3. Detailed Description -~~~~~~~~~~~~~~~~~~~~~~~ -3.1 Device drivers -~~~~~~~~~~~~~~~~~~ - Device drivers are the modules that generate events. The events are -however not useful without being handled, so you also will need to use some -of the modules from section 3.2. - -3.1.1 hid.c -~~~~~~~~~~~ - Hid.c is the largest and most complex driver of the whole suite. It -handles all HID devices, and because there is a very wide variety of them, -and because the USB HID specification isn't simple, it needs to be this big. - - Currently, it handles USB mice, joysticks, gamepads, steering wheels -keyboards, trackballs and digitizers. - - However, USB uses HID also for monitor controls, speaker controls, UPSs, -LCDs and many other purposes. - - The monitor and speaker controls should be easy to add to the hid/input -interface, but for the UPSs and LCDs it doesn't make much sense. The driver -doesn't support these yet, and a new, non-event interface should be designed -for them. If you have any of these devices (I don't), feel free to design -something and if it's good, it'll get into the driver. - - The usage of the hid.o module is very simple, it takes no parameters, -detects everything automatically and when a HID device is inserted, it -detects it appropriately. - - However, because the devices vary wildly, you might happen to have a -device that doesn't work well. In that case #define DEBUG at the beginning -of hid.c and send me the syslog traces. - -3.1.2 usbmouse.c -~~~~~~~~~~~~~~~~ - For embedded systems, for mice with broken HID descriptors and just any -other use when the big hid.c wouldn't be a good choice, there is the -usbmouse.c driver. It handles USB mice only. It uses a simpler HIDBP -protocol. This also means the mice must support this simpler protocol. Not -all do. If you don't have any strong reason to use this module, use hid.c -instead. - -3.1.3 usbkbd.c -~~~~~~~~~~~~~~ - Much like usbmouse.c, this module talks to keyboards with a simplified -HIDBP protocol. It's smaller, but doesn't support any extra special keys. -Use hid.c instead if there isn't any special reason to use this. - -3.1.4 wacom.c -~~~~~~~~~~~~~ - This is a driver for Wacom Graphire and Intuos tablets. Not for Wacom -PenPartner, that one is handled by the HID driver. Although the Intuos and -Graphire tablets claim that they are HID tablets as well, they are not and -thus need this specific driver. - -3.1.5 wmforce.c -~~~~~~~~~~~~~~~ - A driver for the Logitech WingMan Force joysticks, when connected via the -USB port. It works quite well, but there is no force feedback support yet, -because the interface to do that is a trade secret of Immersion Corp, and -even Logitech can't disclose it. - - Support for Logitech WingMan Force Wheel isn't present in this driver, but -if someone has the device, and is willing to cooperate, it should be a -matter of a couple days to add it. - -3.2 Event handlers -~~~~~~~~~~~~~~~~~~ - Event handlers distribute the events from the devices to userland and -kernel, as needed. - -3.2.1 keybdev.c -~~~~~~~~~~~~~~~ - Keybdev is currently a rather ugly hack that translates the input events -into architecture-specific keyboard raw mode (Xlated AT Set2 on x86), and -passes them into the handle_scancode function of the keyboard.c module. This -works well enough on all architectures that keybdev can generate rawmode on, -other architectures can be added to it. - - The right way would be to pass the events to keyboard.c directly, best if -keyboard.c would itself be an event handler. This is done in the input -patch, available on the webpage mentioned below. - -3.2.2 mousedev.c -~~~~~~~~~~~~~~~~ - Mousedev is also a hack to make programs that use mouse input work. It -takes events from either mice or digitizers/tablets and makes a PS/2-style -(a la /dev/psaux) mouse device available to the userland. Ideally, the -programs could use a more reasonable interface, for example evdev.c - - Mousedev devices in /dev/input (as shown above) are: - - crw-r--r-- 1 root root 13, 32 Mar 28 22:45 mouse0 - crw-r--r-- 1 root root 13, 33 Mar 29 00:41 mouse1 - crw-r--r-- 1 root root 13, 34 Mar 29 00:41 mouse2 - crw-r--r-- 1 root root 13, 35 Apr 1 10:50 mouse3 - ... - ... - crw-r--r-- 1 root root 13, 62 Apr 1 10:50 mouse30 - crw-r--r-- 1 root root 13, 63 Apr 1 10:50 mice - -Each 'mouse' device is assigned to a single mouse or digitizer, except the last -one - 'mice'. This single character device is shared by all mice and -digitizers, and even if none are connected, the device is present. This is -useful for hotplugging USB mice, so that programs can open the device even when -no mice are present. - - CONFIG_INPUT_MOUSEDEV_SCREEN_[XY] in the kernel configuration are the size -of your screen (in pixels) in XFree86. This is needed if you want to use -your digitizer in X, because it's movement is sent to X via a virtual PS/2 -mouse and thus needs to be scaled accordingly. These values won't be used if -you use a mouse only. - - Mousedev will generate either PS/2, ImPS/2 (Microsoft IntelliMouse) or -GenPS/2 (Genius NetMouse/NetScroll) protocols, depending on what the program -reading the data wishes. You can set GPM and X to any of these. You'll need -ImPS/2 if you want to make use of a wheel on a USB mouse and GenPS/2 if you -want to use extra (up to 5) buttons. I'm not sure how much is GenPS/2 supported -in X, though. - -3.2.3 joydev.c -~~~~~~~~~~~~~~ - Joydev implements v0.x and v1.x Linux joystick api, much like -drivers/char/joystick/joystick.c. See joystick-api.txt in the Documentation -subdirectory for details. Joydev does it on top of the input subsystem, -though. As soon as any USB joystick is connected, it can be accessed in -/dev/input on: - - crw-r--r-- 1 root root 13, 0 Apr 1 10:50 js0 - crw-r--r-- 1 root root 13, 1 Apr 1 10:50 js1 - crw-r--r-- 1 root root 13, 2 Apr 1 10:50 js2 - crw-r--r-- 1 root root 13, 3 Apr 1 10:50 js3 - ... - -And so on up to js31. - -3.2.4 evdev.c -~~~~~~~~~~~~~ - Evdev is the generic input event interface. It passes the events generated -in the kernel straight to the program, with timestamps. The API is still -evolving, but should be usable now. It's described in section 5. - - This should be the way for GPM and X to get keyboard and mouse mouse -events. It allows for multihead in X without any specific multihead kernel -support. The event codes are the same on all architectures and are hardware -independent. - - The devices are in /dev/input: - - crw-r--r-- 1 root root 13, 64 Apr 1 10:49 event0 - crw-r--r-- 1 root root 13, 65 Apr 1 10:50 event1 - crw-r--r-- 1 root root 13, 66 Apr 1 10:50 event2 - crw-r--r-- 1 root root 13, 67 Apr 1 10:50 event3 - ... - -3. Contacts -~~~~~~~~~~~ - This effort has it's home page at: - - http://www.suse.cz/development/input/ - -You'll find both the latest HID driver and the complete Input driver there -as well as information how to access the CVS repository for latest revisions -of the drivers. - - - There is also a mailing list for this: - - majordomo@atrey.karlin.mff.cuni.cz - -Send "subscribe linux-input" to subscribe to it. - -4. Verifying if it works -~~~~~~~~~~~~~~~~~~~~~~~~ - Typing a couple keys on the keyboard should be enough to check that a USB -keyboard works and is correctly connected to the kernel keyboard driver. - - Doing a cat /dev/input/mouse0 (c, 13, 32) will verify that a mouse is also -emulated, characters should appear if you move it. - - You can test the joystick emulation with the 'jstest' utility, available -in the joystick package (see Documentation/joystick.txt). - - You can test the event devics with the 'evtest' utility available on the -input driver homepage (see the URL above). - -5. Event interface -~~~~~~~~~~~~~~~~~~ - Should you want to add event device support into any application (X, gpm, -svgalib ...) I will be happy to provide you any help I -can. Here goes a description of the current state of things, which is going -to be extended, but not changed incompatibly as time goes: - - You can use blocking and nonblocking reads, also select() on the -/dev/input/eventX devices, and you'll always get a whole number of input -events on a read. Their layout is: - -struct input_event { - struct timeval time; - unsigned short type; - unsigned short code; - unsigned int value; -}; - - 'time' is the timestamp, it returns the time at which the event happened. -Type is for example EV_REL for relative movement, REL_KEY for a keypress or -release. More types are defined in include/linux/input.h. - - 'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete -list is in include/linux/input.h. - - 'value' is the value the event carries. Either a relative change for -EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for -release, 1 for keypress and 2 for autorepeat. 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 14 14:26:36 2001 @@ -81,6 +81,12 @@ L: linux-net@vger.kernel.org S: Maintained +53C700 AND 53C700-66 SCSI DRIVER +P: James E.J. Bottomley +M: James.Bottomley@HansenPartnership.com +L: linux-scsi@vger.kernel.org +S: Maintained + 6PACK NETWORK DRIVER FOR AX.25 P: Andreas Koensgen M: ajk@iehk.rwth-aachen.de @@ -182,9 +188,9 @@ M: linux@treblig.org S: Maintained -ARM PORT +ARM/STRONGARM110 PORT P: Russell King -M: linux@arm.linux.org.uk +M: rmk@arm.linux.org.uk L: linux-arm-kernel@lists.arm.linux.org.uk W: http://www.arm.linux.org.uk/ S: Maintained @@ -337,7 +343,7 @@ CYBERPRO FB DRIVER P: Russell King -M: linux@arm.linux.org.uk +M: rmk@arm.linux.org.uk W: http://www.arm.linux.org.uk/ S: Maintained @@ -689,8 +695,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 @@ -774,6 +780,13 @@ W: http://www.developer.axis.com/software/jffs/ S: Maintained +JOURNALLING FLASH FILE SYSTEM V2 (JFFS2) +P: David Woodhouse +M: dwmw2@infradead.org +L: jffs-dev@axis.com +W: http://sources.redhat.com/jffs2/ +S: Maintained + JOYSTICK DRIVER P: Vojtech Pavlik M: vojtech@suse.cz @@ -823,6 +836,12 @@ L: linux-x25@vger.kernel.org S: Maintained +LASI 53c700 driver for PARISC +P: James E.J. Bottomley +M: James.Bottomley@HansenPartnership.com +L: linux-scsi@vger.kernel.org +S: Maintained + LINUX FOR IBM pSERIES (RS/6000) P: Paul Mackerras M: paulus@au.ibm.com @@ -902,9 +921,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 @@ -948,6 +967,12 @@ L: linware@sh.cvut.cz S: Maintained +NCR DUAL 700 SCSI DRIVER (MICROCHANNEL) +P: James E.J. Bottomley +M: James.Bottomley@HansenPartnership.com +L: linux-scsi@vger.kernel.org +S: Maintained + NETFILTER P: Rusty Russell M: rusty@rustcorp.com.au @@ -1250,6 +1275,9 @@ SOFTWARE RAID (Multiple Disks) SUPPORT P: Ingo Molnar M: mingo@redhat.com +P: Neil Brown +M: neilb@cse.unsw.edu.au +L: linux-raid@vger.kernel.org S: Maintained SONIC NETWORK DRIVER @@ -1413,15 +1441,6 @@ W: http://www.kernel.dk S: Maintained -USB SUBSYSTEM -P: Johannes Erdfelt -M: jerdfelt@valinux.com -M: johannes@erdfelt.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net -W: http://www.linux-usb.org -S: Supported - USB ACM DRIVER P: Vojtech Pavlik M: vojtech@suse.cz @@ -1437,6 +1456,13 @@ S: Maintained W: http://www.kroah.com/linux-usb/ +USB CDC ETHERNET DRIVER +P: Brad Hards +M: bhards@bigpond.net.au +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Maintained + USB HID/HIDBP/INPUT DRIVERS P: Vojtech Pavlik M: vojtech@suse.cz @@ -1453,6 +1479,21 @@ L: linux-usb-devel@lists.sourceforge.net S: Maintained +USB KAWASAKI LSI DRIVER +P: Brad Hards +M: bhards@bigpond.net.au +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Maintained + +USB MASS STORAGE DRIVER +P: Matthew Dharm +M: mdharm-usb@one-eyed-alien.net +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Maintained +W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ + USB OHCI DRIVER P: Roman Weissgaerber M: weissg@vienna.at @@ -1482,21 +1523,21 @@ L: linux-usb-devel@lists.sourceforge.net S: Supported -USB SERIAL DIGI ACCELEPORT DRIVER -P: Peter Berger and Al Borchers -M: pberger@brimson.com -M: alborchers@steinerpoint.com +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 SERIAL KEYSPAN DRIVER -P: Hugh Blemings -M: hugh@misc.nu +USB SERIAL DIGI ACCELEPORT DRIVER +P: Peter Berger and Al Borchers +M: pberger@brimson.com +M: alborchers@steinerpoint.com L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained -W: http://misc.nu/hugh/keyspan/ USB SERIAL DRIVER P: Greg Kroah-Hartman @@ -1514,6 +1555,12 @@ L: linux-usb-devel@lists.sourceforge.net S: Maintained +USB SERIAL CYBERJACK PINPAD/E-COM DRIVER +M: linux-usb@sii.li +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Supported + USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER P: Gary Brubaker M: xavyer@ix.netcom.com @@ -1521,19 +1568,22 @@ L: linux-usb-devel@lists.sourceforge.net S: Maintained -USB SERIAL CYBERJACK PINPAD/E-COM DRIVER -M: linux-usb@sii.li -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net -S: Supported - -USB MASS STORAGE DRIVER -P: Matthew Dharm -M: mdharm-usb@one-eyed-alien.net +USB SERIAL KEYSPAN DRIVER +P: Hugh Blemings +M: hugh@misc.nu L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained -W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ +W: http://misc.nu/hugh/keyspan/ + +USB SUBSYSTEM +P: Johannes Erdfelt +M: jerdfelt@valinux.com +M: johannes@erdfelt.com +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +W: http://www.linux-usb.org +S: Supported USB UHCI DRIVER P: Georg Acher 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 Tue Sep 18 14:02:12 2001 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 -SUBLEVEL = 9 -EXTRAVERSION = +SUBLEVEL = 10 +EXTRAVERSION =-pre12 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -146,6 +146,7 @@ DRIVERS-$(CONFIG_ARCNET) += drivers/net/arcnet/arcnetdrv.o DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o DRIVERS-$(CONFIG_IDE) += drivers/ide/idedriver.o +DRIVERS-$(CONFIG_FC4) += drivers/fc4/fc4.a DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsidrv.o DRIVERS-$(CONFIG_FUSION_BOOT) += drivers/message/fusion/fusion.o DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394drv.o @@ -197,6 +198,10 @@ drivers/zorro/devlist.h drivers/zorro/gen-devlist \ drivers/sound/bin2hex drivers/sound/hex2hex \ drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2} \ + drivers/scsi/aic7xxx/aicasm/aicasm_gram.c \ + drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \ + drivers/scsi/aic7xxx/aicasm/y.tab.h \ + drivers/scsi/aic7xxx/aicasm/aicasm \ net/khttpd/make_times_h \ net/khttpd/times.h \ submenu* @@ -223,7 +228,9 @@ .menuconfig.log \ include/asm \ .hdepend scripts/mkdep scripts/split-include scripts/docproc \ - $(TOPDIR)/include/linux/modversions.h + $(TOPDIR)/include/linux/modversions.h \ + kernel.spec + # directories removed with 'make mrproper' MRPROPER_DIRS = \ include/config \ @@ -247,7 +254,7 @@ boot: vmlinux @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot -vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs +vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \ --start-group \ $(CORE_FILES) \ @@ -292,11 +299,7 @@ $(TOPDIR)/include/linux/compile.h: include/linux/compile.h newversion: - @if [ ! -f .version ]; then \ - echo 1 > .version; \ - else \ - expr 0`cat .version` + 1 > .version; \ - fi + . scripts/mkversion > .version include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion @echo -n \#define UTS_VERSION \"\#`cat .version` > .ver @@ -418,7 +421,8 @@ $(MAKE) -C Documentation/DocBook mrproper distclean: mrproper - rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ + rm -f core `find . \( -not -type d \) -and \ + \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags @@ -501,3 +505,30 @@ scripts/split-include: scripts/split-include.c $(HOSTCC) $(HOSTCFLAGS) -o scripts/split-include scripts/split-include.c + +# +# RPM target +# +# If you do a make spec before packing the tarball you can rpm -ta it +# +spec: + . scripts/mkspec >kernel.spec + +# +# Build a tar ball, generate an rpm from it and pack the result +# There arw two bits of magic here +# 1) The use of /. to avoid tar packing just the symlink +# 2) Removing the .dep files as they have source paths in them that +# will become invalid +# +rpm: clean spec + find . \( -size 0 -o -name .depend -o -name .hdepend \) -type f -print | xargs rm -f + set -e; \ + cd $(TOPDIR)/.. ; \ + ln -sf $(TOPDIR) $(KERNELPATH) ; \ + tar -cvz --exclude CVS -f $(KERNELPATH).tar.gz $(KERNELPATH)/. ; \ + rm $(KERNELPATH) ; \ + cd $(TOPDIR) ; \ + . scripts/mkversion > .version ; \ + rpm -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \ + rm $(TOPDIR)/../$(KERNELPATH).tar.gz 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 Thu Sep 13 15:21:32 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); @@ -200,6 +208,8 @@ EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(__cpu_number_map); EXPORT_SYMBOL(smp_num_cpus); +EXPORT_SYMBOL(smp_call_function); +EXPORT_SYMBOL(smp_call_function_on_cpu); EXPORT_SYMBOL(global_irq_holder); EXPORT_SYMBOL(__global_cli); EXPORT_SYMBOL(__global_sti); diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c --- v2.4.9/linux/arch/alpha/kernel/core_cia.c Tue May 22 16:29:57 2001 +++ linux/arch/alpha/kernel/core_cia.c Thu Sep 13 15:21:32 2001 @@ -352,13 +352,15 @@ so use them and read at window 3 base exactly 4 times. Reading more sometimes makes the chip crazy. -ink */ - bus_addr = cia_ioremap(CIA_BROKEN_TBIA_BASE); + bus_addr = cia_ioremap(CIA_BROKEN_TBIA_BASE, 32768 * 4); cia_readl(bus_addr + 0x00000); cia_readl(bus_addr + 0x08000); cia_readl(bus_addr + 0x10000); cia_readl(bus_addr + 0x18000); + cia_iounmap(bus_addr); + /* Restore normal PCI operation. */ mb(); *(vip)CIA_IOC_CIA_CTRL = ctrl; @@ -396,6 +398,7 @@ struct pci_iommu_arena *arena = pci_isa_hose->sg_isa; int ctrl, addr0, tag0, pte0, data0; int temp, use_tbia_try2 = 0; + unsigned long bus_addr; /* pyxis -- tbia is broken */ if (pci_isa_hose->dense_io_base) @@ -429,6 +432,9 @@ *(vip)CIA_IOC_TBn_PAGEm(0,3) = 0; mb(); + /* Get a usable bus address */ + bus_addr = cia_ioremap(addr0, 8*PAGE_SIZE); + /* First, verify we can read back what we've written. If this fails, we can't be sure of any of the other testing we're going to do, so bail. */ @@ -464,7 +470,7 @@ mcheck_expected(0) = 1; mcheck_taken(0) = 0; mb(); - temp = cia_readl(cia_ioremap(addr0)); + temp = cia_readl(bus_addr); mb(); mcheck_expected(0) = 0; mb(); @@ -501,7 +507,7 @@ mcheck_expected(0) = 1; mcheck_taken(0) = 0; mb(); - temp = cia_readl(cia_ioremap(addr0 + 4*PAGE_SIZE)); + temp = cia_readl(bus_addr + 4*PAGE_SIZE); mb(); mcheck_expected(0) = 0; mb(); @@ -525,7 +531,7 @@ mcheck_expected(0) = 1; mcheck_taken(0) = 0; mb(); - temp = cia_readl(cia_ioremap(addr0 + 5*PAGE_SIZE)); + temp = cia_readl(bus_addr + 5*PAGE_SIZE); mb(); mcheck_expected(0) = 0; mb(); @@ -549,7 +555,7 @@ mcheck_expected(0) = 1; mcheck_taken(0) = 0; mb(); - temp = cia_readl(cia_ioremap(addr0 + 6*PAGE_SIZE)); + temp = cia_readl(bus_addr + 6*PAGE_SIZE); mb(); mcheck_expected(0) = 0; mb(); @@ -575,6 +581,9 @@ alpha_mv.mv_pci_tbi(arena->hose, 0, -1); exit: + /* unmap the bus addr */ + cia_iounmap(bus_addr); + /* Restore normal PCI operation. */ mb(); *(vip)CIA_IOC_CIA_CTRL = ctrl; diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/core_irongate.c linux/arch/alpha/kernel/core_irongate.c --- v2.4.9/linux/arch/alpha/kernel/core_irongate.c Fri Mar 2 11:12:07 2001 +++ linux/arch/alpha/kernel/core_irongate.c Thu Sep 13 15:21:32 2001 @@ -30,6 +30,8 @@ #undef DEBUG_IRONGATE /* define to enable verbose Irongate debug */ +#define IRONGATE_DEFAULT_AGP_APER_SIZE (256*1024*1024) /* 256MB */ + /* * BIOS32-style PCI interface: */ @@ -374,6 +376,14 @@ irongate_register_dump(__FUNCTION__); /* + * HACK: set AGP aperture size to 256MB. + * This should really be changed during PCI probe, when the + * size of the aperture the AGP card wants is known. + */ + printk("irongate_init_arch: AGPVA was 0x%x\n", IRONGATE0->agpva); + IRONGATE0->agpva = (IRONGATE0->agpva & ~0x0000000f) | 0x00000007; + + /* * Create our single hose. */ @@ -396,4 +406,202 @@ hose->sg_isa = hose->sg_pci = NULL; __direct_map_base = 0; __direct_map_size = 0xffffffff; +} + +/* + * IO map and AGP support + */ +#include +#include + +static inline void +irongate_remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) +{ + unsigned long end; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + if (address >= end) + BUG(); + do { + if (!pte_none(*pte)) { + printk("irongate_remap_area_pte: page already exists\n"); + BUG(); + } + set_pte(pte, + mk_pte_phys(phys_addr, + __pgprot(_PAGE_VALID | _PAGE_ASM | + _PAGE_KRE | _PAGE_KWE | flags))); + address += PAGE_SIZE; + phys_addr += PAGE_SIZE; + pte++; + } while (address && (address < end)); +} + +static inline int +irongate_remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) +{ + unsigned long end; + + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + phys_addr -= address; + if (address >= end) + BUG(); + do { + pte_t * pte = pte_alloc(&init_mm, pmd, address); + if (!pte) + return -ENOMEM; + irongate_remap_area_pte(pte, address, end - address, + address + phys_addr, flags); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address && (address < end)); + return 0; +} + +static int +irongate_remap_area_pages(unsigned long address, unsigned long phys_addr, + unsigned long size, unsigned long flags) +{ + pgd_t * dir; + unsigned long end = address + size; + + phys_addr -= address; + dir = pgd_offset(&init_mm, address); + flush_cache_all(); + if (address >= end) + BUG(); + do { + pmd_t *pmd; + pmd = pmd_alloc(&init_mm, dir, address); + if (!pmd) + return -ENOMEM; + if (irongate_remap_area_pmd(pmd, address, end - address, + phys_addr + address, flags)) + return -ENOMEM; + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } while (address && (address < end)); + return 0; +} + +#include +#include + +#define GET_PAGE_DIR_OFF(addr) (addr >> 22) +#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr)) + +#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) +#define GET_GATT(addr) (gatt_pages[GET_PAGE_DIR_IDX(addr)]) + +unsigned long +irongate_ioremap(unsigned long addr, unsigned long size) +{ + struct vm_struct *area; + unsigned long vaddr; + unsigned long baddr, last; + u32 *mmio_regs, *gatt_pages, *cur_gatt, pte; + unsigned long gart_bus_addr, gart_aper_size; + + gart_bus_addr = (unsigned long)IRONGATE0->bar0 & + PCI_BASE_ADDRESS_MEM_MASK; + + if (!gart_bus_addr) /* FIXME - there must be a better way!!! */ + return addr + IRONGATE_MEM; + + gart_aper_size = IRONGATE_DEFAULT_AGP_APER_SIZE; /* FIXME */ + + /* + * Check for within the AGP aperture... + */ + do { + /* + * Check the AGP area + */ + if (addr >= gart_bus_addr && addr + size - 1 < + gart_bus_addr + gart_aper_size) + break; + + /* + * Not found - assume legacy ioremap + */ + return addr + IRONGATE_MEM; + } while(0); + + mmio_regs = (u32 *)(((unsigned long)IRONGATE0->bar1 & + PCI_BASE_ADDRESS_MEM_MASK) + IRONGATE_MEM); + + gatt_pages = (u32 *)(phys_to_virt(mmio_regs[1])); /* FIXME */ + + /* + * Adjust the limits (mappings must be page aligned) + */ + if (addr & ~PAGE_MASK) { + printk("AGP ioremap failed... addr not page aligned (0x%lx)\n", + addr); + return addr + IRONGATE_MEM; + } + last = addr + size - 1; + size = PAGE_ALIGN(last) - addr; + +#if 0 + printk("irongate_ioremap(0x%lx, 0x%lx)\n", addr, size); + printk("irongate_ioremap: gart_bus_addr 0x%lx\n", gart_bus_addr); + printk("irongate_ioremap: gart_aper_size 0x%lx\n", gart_aper_size); + printk("irongate_ioremap: mmio_regs %p\n", mmio_regs); + printk("irongate_ioremap: gatt_pages %p\n", gatt_pages); + + for(baddr = addr; baddr <= last; baddr += PAGE_SIZE) + { + cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1); + pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1; + printk("irongate_ioremap: cur_gatt %p pte 0x%x\n", + cur_gatt, pte); + } +#endif + + /* + * Map it + */ + area = get_vm_area(size, VM_IOREMAP); + if (!area) return (unsigned long)NULL; + + for(baddr = addr, vaddr = (unsigned long)area->addr; + baddr <= last; + baddr += PAGE_SIZE, vaddr += PAGE_SIZE) + { + cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1); + pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1; + + if (irongate_remap_area_pages(VMALLOC_VMADDR(vaddr), + pte, PAGE_SIZE, 0)) { + printk("AGP ioremap: FAILED to map...\n"); + vfree(area->addr); + return (unsigned long)NULL; + } + } + + flush_tlb_all(); + + vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK); +#if 0 + printk("irongate_ioremap(0x%lx, 0x%lx) returning 0x%lx\n", + addr, size, vaddr); +#endif + return vaddr; +} + +void +irongate_iounmap(unsigned long addr) +{ + if (((long)addr >> 41) == -2) + return; /* kseg map, nothing to do */ + if (addr) return vfree((void *)(PAGE_MASK & addr)); } diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.4.9/linux/arch/alpha/kernel/irq.c Mon Aug 27 12:41:37 2001 +++ linux/arch/alpha/kernel/irq.c Mon Sep 17 13:16:30 2001 @@ -38,7 +38,7 @@ static void register_irq_proc(unsigned int irq); -unsigned long irq_err_count; +volatile unsigned long irq_err_count; /* * Special irq handlers. diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/irq_alpha.c linux/arch/alpha/kernel/irq_alpha.c --- v2.4.9/linux/arch/alpha/kernel/irq_alpha.c Tue Jul 3 17:08:18 2001 +++ linux/arch/alpha/kernel/irq_alpha.c Mon Sep 17 13:16:30 2001 @@ -18,8 +18,6 @@ unsigned long __irq_attempt[NR_IRQS]; #endif -extern unsigned long irq_err_count; - /* Hack minimum IPL during interrupt processing for broken hardware. */ #ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK int __min_ipl; diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/machvec_impl.h linux/arch/alpha/kernel/machvec_impl.h --- v2.4.9/linux/arch/alpha/kernel/machvec_impl.h Wed Jun 21 22:30:59 2000 +++ linux/arch/alpha/kernel/machvec_impl.h Thu Sep 13 15:21:32 2001 @@ -80,7 +80,8 @@ mv_writew: CAT(low,_writew), \ mv_writel: CAT(low,_writel), \ mv_writeq: CAT(low,_writeq), \ - mv_ioremap: CAT(low,_ioremap) \ + mv_ioremap: CAT(low,_ioremap), \ + mv_iounmap: CAT(low,_iounmap) \ #define IO(UP,low) \ IO_LITE(UP,low), \ diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/pci-noop.c linux/arch/alpha/kernel/pci-noop.c --- v2.4.9/linux/arch/alpha/kernel/pci-noop.c Fri Mar 2 11:12:07 2001 +++ linux/arch/alpha/kernel/pci-noop.c Thu Sep 13 15:21:32 2001 @@ -102,3 +102,38 @@ else return -ENODEV; } +/* stubs for the routines in pci_iommu.c */ +void * +pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp) +{ +} +void +pci_free_consistent(struct pci_dev *pdev, long size, void *cpu_addr, + dma_addr_t dma_addr) +{ +} +dma_addr_t +pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, + int direction) +{ +} +void +pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size, + int direction) +{ +} +int +pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, + int direction) +{ +} +void +pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, + int direction) +{ +} +int +pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +{ + return 0; +} diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c --- v2.4.9/linux/arch/alpha/kernel/pci.c Mon May 21 13:38:41 2001 +++ linux/arch/alpha/kernel/pci.c Thu Sep 13 15:21:32 2001 @@ -76,6 +76,9 @@ dev->resource[3].end = dev->resource[3].start + 7; } +static void __init +quirk_cypress(struct pci_dev *dev) +{ /* * Notorious Cy82C693 chip. One of its numerous bugs: although * Cypress IDE controller doesn't support native mode, it has @@ -85,31 +88,27 @@ * and floppy controller. Ugh. * Fix that. */ -static void __init -quirk_cypress_ide_ports(struct pci_dev *dev) -{ - if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE) + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) { + dev->resource[0].flags = 0; + dev->resource[1].flags = 0; return; - dev->resource[0].flags = 0; - dev->resource[1].flags = 0; -} - -static void __init -quirk_vga_enable_rom(struct pci_dev *dev) -{ - /* If it's a VGA, enable its BIOS ROM at C0000. - But if its a Cirrus 543x/544x DISABLE it, since - enabling ROM disables the memory... */ - if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA && - (dev->vendor != PCI_VENDOR_ID_CIRRUS || - (dev->device < 0x00a0) || (dev->device > 0x00ac))) - { - u32 reg; - - pci_read_config_dword(dev, dev->rom_base_reg, ®); - reg |= PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(dev, dev->rom_base_reg, reg); - dev->resource[PCI_ROM_RESOURCE].flags |= PCI_ROM_ADDRESS_ENABLE; + } +/* + * Another "feature": Cypress bridge responds on the PCI bus + * in the address range 0xffff0000-0xffffffff (conventional + * x86 BIOS ROM). No way to turn this off, so if we use + * large SG window, we must avoid these addresses. + */ + if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) { + struct pci_controller *hose = dev->sysdata; + long overlap; + + if (hose->sg_pci) { + overlap = hose->sg_pci->dma_base + hose->sg_pci->size; + overlap -= 0xffff0000; + if (overlap > 0) + hose->sg_pci->size -= overlap; + } } } @@ -121,8 +120,7 @@ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, - quirk_cypress_ide_ports }, - { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_vga_enable_rom }, + quirk_cypress }, { 0 } }; @@ -148,10 +146,8 @@ /* * Put everything into 0x00-0xff region modulo 0x400 */ - if (start & 0x300) { + if (start & 0x300) start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } } else if (res->flags & IORESOURCE_MEM) { /* Make sure we start at our min on all hoses */ @@ -177,13 +173,13 @@ /* Align to multiple of size of minimum base. */ alignto = MAX(0x1000, size); start = ALIGN(start, alignto); - if (size <= 7 * 16*MB) { + if (hose->sparse_mem_base && size <= 7 * 16*MB) { if (((start / (16*MB)) & 0x7) == 0) { start &= ~(128*MB - 1); start += 16*MB; start = ALIGN(start, alignto); } - if (start/(128*MB) != (start + size)/(128*MB)) { + if (start/(128*MB) != (start + size - 1)/(128*MB)) { start &= ~(128*MB - 1); start += (128 + 16)*MB; start = ALIGN(start, alignto); diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/pci_impl.h linux/arch/alpha/kernel/pci_impl.h --- v2.4.9/linux/arch/alpha/kernel/pci_impl.h Fri May 25 09:54:50 2001 +++ linux/arch/alpha/kernel/pci_impl.h Thu Sep 13 15:21:32 2001 @@ -49,7 +49,7 @@ * APECS and LCA have only 34 bits for physical addresses, thus limiting PCI * bus memory addresses for SPARSE access to be less than 128Mb. */ -#define APECS_AND_LCA_DEFAULT_MEM_BASE ((32+2)*1024*1024) +#define APECS_AND_LCA_DEFAULT_MEM_BASE ((16+2)*1024*1024) /* * Because the MCPCIA core logic supports more bits for physical addresses, @@ -136,6 +136,7 @@ spinlock_t lock; struct pci_controller *hose; #define IOMMU_INVALID_PTE 0x2 /* 32:63 bits MBZ */ +#define IOMMU_RESERVED_PTE 0xface unsigned long *ptes; dma_addr_t dma_base; unsigned int size; @@ -161,3 +162,10 @@ extern const char *const pci_io_names[]; extern const char *const pci_mem_names[]; extern const char pci_hae0_name[]; + +extern int iommu_reserve(struct pci_iommu_arena *, long, long); +extern int iommu_release(struct pci_iommu_arena *, long, long); +extern int iommu_bind(struct pci_iommu_arena *, long, long, unsigned long *); +extern int iommu_unbind(struct pci_iommu_arena *, long, long); + + diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/pci_iommu.c linux/arch/alpha/kernel/pci_iommu.c --- v2.4.9/linux/arch/alpha/kernel/pci_iommu.c Mon Aug 27 12:41:37 2001 +++ linux/arch/alpha/kernel/pci_iommu.c Thu Sep 13 15:21:32 2001 @@ -42,24 +42,6 @@ return (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; } -static void __init -iommu_arena_fixup(struct pci_iommu_arena * arena) -{ - unsigned long base, size; - - /* - * The Cypress chip has a quirk, it get confused by addresses - * above -1M so reserve the pagetables that maps pci addresses - * above -1M. - */ - base = arena->dma_base; - size = arena->size; - if (base + size > 0xfff00000) { - int i, fixup_start = (0xfff00000 - base) >> PAGE_SHIFT; - for (i= 0; i < (0x100000 >> PAGE_SHIFT); i++) - arena->ptes[fixup_start+i] = IOMMU_INVALID_PTE; - } -} struct pci_iommu_arena * iommu_arena_new(struct pci_controller *hose, dma_addr_t base, @@ -90,24 +72,19 @@ unless there are chip bugs. */ arena->align_entry = 1; - iommu_arena_fixup(arena); - return arena; } -long -iommu_arena_alloc(struct pci_iommu_arena *arena, long n) +/* Must be called with the arena lock held */ +static long +iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask) { - unsigned long flags; unsigned long *ptes; - long i, p, nent, mask; + long i, p, nent; - spin_lock_irqsave(&arena->lock, flags); - - /* Search forward for the first sequence of N empty ptes. */ + /* Search forward for the first mask-aligned sequence of N free ptes */ ptes = arena->ptes; nent = arena->size >> PAGE_SHIFT; - mask = arena->align_entry - 1; p = (arena->next_entry + mask) & ~mask; i = 0; while (i < n && p+i < nent) { @@ -130,10 +107,31 @@ i = i + 1; } - if (i < n) { - spin_unlock_irqrestore(&arena->lock, flags); + if (i < n) return -1; - } + } + + /* Success. It's the responsibility of the caller to mark them + in use before releasing the lock */ + return p; +} + +long +iommu_arena_alloc(struct pci_iommu_arena *arena, long n) +{ + unsigned long flags; + unsigned long *ptes; + long i, p, mask; + + spin_lock_irqsave(&arena->lock, flags); + + /* Search for N empty ptes */ + ptes = arena->ptes; + mask = arena->align_entry - 1; + p = iommu_arena_find_pages(arena, n, mask); + if (p < 0) { + spin_unlock_irqrestore(&arena->lock, flags); + return -1; } /* Success. Mark them all in use, ie not zero and invalid @@ -660,6 +658,104 @@ arena = hose->sg_pci; if (arena && arena->dma_base + arena->size - 1 <= mask) return 1; + + return 0; +} + + +/* + * AGP GART extensions to the IOMMU + */ +int +iommu_reserve(struct pci_iommu_arena *arena, long pg_count, long align_mask) +{ + unsigned long flags; + unsigned long *ptes; + long i, p; + + if (!arena) return -EINVAL; + + spin_lock_irqsave(&arena->lock, flags); + + /* Search for N empty ptes. */ + ptes = arena->ptes; + p = iommu_arena_find_pages(arena, pg_count, align_mask); + if (p < 0) { + spin_unlock_irqrestore(&arena->lock, flags); + return -1; + } + + /* Success. Mark them all reserved (ie not zero and invalid) + for the iommu tlb that could load them from under us. + They will be filled in with valid bits by _bind() */ + for (i = 0; i < pg_count; ++i) + ptes[p+i] = IOMMU_RESERVED_PTE; + + arena->next_entry = p + pg_count; + spin_unlock_irqrestore(&arena->lock, flags); + + return p; +} + +int +iommu_release(struct pci_iommu_arena *arena, long pg_start, long pg_count) +{ + unsigned long *ptes; + long i; + + if (!arena) return -EINVAL; + + ptes = arena->ptes; + + /* Make sure they're all reserved first... */ + for(i = pg_start; i < pg_start + pg_count; i++) + if (ptes[i] != IOMMU_RESERVED_PTE) + return -EBUSY; + + iommu_arena_free(arena, pg_start, pg_count); + return 0; +} + +int +iommu_bind(struct pci_iommu_arena *arena, long pg_start, long pg_count, + unsigned long *physaddrs) +{ + unsigned long flags; + unsigned long *ptes; + long i, j; + + if (!arena) return -EINVAL; + + spin_lock_irqsave(&arena->lock, flags); + + ptes = arena->ptes; + + for(j = pg_start; j < pg_start + pg_count; j++) { + if (ptes[j] != IOMMU_RESERVED_PTE) { + spin_unlock_irqrestore(&arena->lock, flags); + return -EBUSY; + } + } + + for(i = 0, j = pg_start; i < pg_count; i++, j++) + ptes[j] = mk_iommu_pte(physaddrs[i]); + + spin_unlock_irqrestore(&arena->lock, flags); + + return 0; +} + +int +iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count) +{ + unsigned long *p; + long i; + + if (!arena) return -EINVAL; + + p = arena->ptes + pg_start; + for(i = 0; i < pg_count; i++) + p[i] = IOMMU_RESERVED_PTE; return 0; } diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.4.9/linux/arch/alpha/kernel/process.c Tue Jul 3 17:08:18 2001 +++ linux/arch/alpha/kernel/process.c Mon Sep 17 15:29:09 2001 @@ -50,7 +50,6 @@ */ unsigned long init_user_stack[1024] = { STACK_MAGIC, }; -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; @@ -213,7 +212,9 @@ void show_regs(struct pt_regs * regs) { - printk("\nps: %04lx pc: [<%016lx>]\n", regs->ps, regs->pc); + printk("\n"); + printk("Pid: %d, comm: %20s\n", current->pid, current->comm); + printk("ps: %04lx pc: [<%016lx>] CPU %d\n", regs->ps, regs->pc, smp_processor_id()); printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1); printk(" r0: %016lx r1: %016lx r2: %016lx r3: %016lx\n", regs->r0, regs->r1, regs->r2, regs->r3); diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c --- v2.4.9/linux/arch/alpha/kernel/ptrace.c Wed Jul 25 17:10:17 2001 +++ linux/arch/alpha/kernel/ptrace.c Tue Sep 18 17:03:51 2001 @@ -233,6 +233,16 @@ return (nsaved != 0); } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + ptrace_cancel_bpt(child); +} + asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4, int a5, struct pt_regs regs) @@ -362,21 +372,8 @@ ret = 0; goto out; - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - wake_up_process(child); - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - /* make sure single-step breakpoint is gone. */ - ptrace_cancel_bpt(child); - ret = 0; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); goto out; default: diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.4.9/linux/arch/alpha/kernel/smp.c Mon Aug 27 12:41:38 2001 +++ linux/arch/alpha/kernel/smp.c Thu Sep 13 15:21:32 2001 @@ -1,5 +1,13 @@ /* * linux/arch/alpha/kernel/smp.c + * + * 2001-07-09 Phil Ezolt (Phillip.Ezolt@compaq.com) + * Renamed modified smp_call_function to smp_call_function_on_cpu() + * Created an function that conforms to the old calling convention + * of smp_call_function(). + * + * This is helpful for DCPI. + * */ #include @@ -867,23 +875,31 @@ */ int -smp_call_function (void (*func) (void *info), void *info, int retry, int wait) +smp_call_function_on_cpu (void (*func) (void *info), void *info, int retry, + int wait, unsigned long to_whom) { - unsigned long to_whom = cpu_present_mask ^ (1UL << smp_processor_id()); struct smp_call_struct data; long timeout; + int num_cpus_to_call; + long i,j; data.func = func; data.info = info; data.wait = wait; - atomic_set(&data.unstarted_count, smp_num_cpus - 1); - atomic_set(&data.unfinished_count, smp_num_cpus - 1); + + to_whom &= ~(1L << smp_processor_id()); + for (i = 0, j = 1, num_cpus_to_call = 0; i < NR_CPUS; ++i, j <<= 1) + if (to_whom & j) + num_cpus_to_call++; + + atomic_set(&data.unstarted_count, num_cpus_to_call); + atomic_set(&data.unfinished_count, num_cpus_to_call); /* Acquire the smp_call_function_data mutex. */ if (pointer_lock(&smp_call_function_data, &data, retry)) return -EBUSY; - /* Send a message to all other CPUs. */ + /* Send a message to the requested CPUs. */ send_ipi_message(to_whom, IPI_CALL_FUNC); /* Wait for a minimal response. */ @@ -905,6 +921,13 @@ } return 0; +} + +int +smp_call_function (void (*func) (void *info), void *info, int retry, int wait) +{ + return smp_call_function_on_cpu (func, info, retry, wait, + cpu_present_mask); } static void diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/sys_jensen.c linux/arch/alpha/kernel/sys_jensen.c --- v2.4.9/linux/arch/alpha/kernel/sys_jensen.c Fri Mar 2 11:12:07 2001 +++ linux/arch/alpha/kernel/sys_jensen.c Thu Sep 13 15:21:32 2001 @@ -35,14 +35,16 @@ /* * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and - * 0x9X0 for the local motherboard interrupts.. + * 0x9X0 for the local motherboard interrupts. + * + * Note especially that those local interrupts CANNOT be masked, + * which causes much of the pain below... * * 0x660 - NMI * * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer) * 0x810 - IRQ1 line printer (duh..) * 0x860 - IRQ6 floppy disk - * 0x8E0 - IRQ14 SCSI controller * * 0x900 - COM1 * 0x920 - COM2 @@ -52,27 +54,77 @@ * PCI-based systems are more sane: they don't have the local * interrupts at all, and have only normal PCI interrupts from * devices. Happily it's easy enough to do a sane mapping from the - * Jensen.. Note that this means that we may have to do a hardware - * "ack" to a different interrupt than we report to the rest of the + * Jensen. + * + * Note that this means that we may have to do a hardware + * "local_op" to a different interrupt than we report to the rest of the * world. */ +static unsigned int +jensen_local_startup(unsigned int irq) +{ + /* the parport is really hw IRQ 1, silly Jensen. */ + if (irq == 7) + i8259a_startup_irq(1); + else + /* + * For all true local interrupts, set the flag that prevents + * the IPL from being dropped during handler processing. + */ + if (irq_desc[irq].action) + irq_desc[irq].action->flags |= SA_INTERRUPT; + return 0; +} + +static void +jensen_local_shutdown(unsigned int irq) +{ + /* the parport is really hw IRQ 1, silly Jensen. */ + if (irq == 7) + i8259a_disable_irq(1); +} + +static void +jensen_local_enable(unsigned int irq) +{ + /* the parport is really hw IRQ 1, silly Jensen. */ + if (irq == 7) + i8259a_enable_irq(1); +} + +static void +jensen_local_disable(unsigned int irq) +{ + /* the parport is really hw IRQ 1, silly Jensen. */ + if (irq == 7) + i8259a_disable_irq(1); +} + static void jensen_local_ack(unsigned int irq) { - /* irq1 is supposed to be the keyboard, silly Jensen. */ + /* the parport is really hw IRQ 1, silly Jensen. */ if (irq == 7) i8259a_mask_and_ack_irq(1); } +static void +jensen_local_end(unsigned int irq) +{ + /* the parport is really hw IRQ 1, silly Jensen. */ + if (irq == 7) + i8259a_end_irq(1); +} + static struct hw_interrupt_type jensen_local_irq_type = { typename: "LOCAL", - startup: i8259a_startup_irq, - shutdown: i8259a_disable_irq, - enable: i8259a_enable_irq, - disable: i8259a_disable_irq, + startup: jensen_local_startup, + shutdown: jensen_local_shutdown, + enable: jensen_local_enable, + disable: jensen_local_disable, ack: jensen_local_ack, - end: i8259a_end_irq, + end: jensen_local_end, }; static void @@ -104,6 +156,47 @@ break; } + /* If there is no handler yet... */ + if (irq_desc[irq].action == NULL) { + /* If it is a local interrupt that cannot be masked... */ + if (vector >= 0x900) + { + /* Clear keyboard/mouse state */ + inb(0x64); + inb(0x60); + /* Reset serial ports */ + inb(0x3fa); + inb(0x2fa); + outb(0x0c, 0x3fc); + outb(0x0c, 0x2fc); + /* Clear NMI */ + outb(0,0x61); + outb(0,0x461); + } + } + +#if 0 + /* A useful bit of code to find out if an interrupt is going wild. */ + { + static unsigned int last_msg = 0, last_cc = 0; + static int last_irq = -1, count = 0; + unsigned int cc; + + __asm __volatile("rpcc %0" : "=r"(cc)); + ++count; +#define JENSEN_CYCLES_PER_SEC (150000000) + if (cc - last_msg > ((JENSEN_CYCLES_PER_SEC) * 3) || + irq != last_irq) { + printk(KERN_CRIT " irq %d count %d cc %u @ %lx\n", + irq, count, cc-last_cc, regs->pc); + count = 0; + last_msg = cc; + last_irq = irq; + } + last_cc = cc; + } +#endif + handle_irq(irq, regs); } @@ -164,7 +257,7 @@ BUS(jensen), machine_check: jensen_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, - rtc_port: 0x170, + rtc_port: 0x170, nr_irqs: 16, device_interrupt: jensen_device_interrupt, diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c --- v2.4.9/linux/arch/alpha/kernel/traps.c Mon Aug 27 12:41:38 2001 +++ linux/arch/alpha/kernel/traps.c Mon Sep 17 13:16:30 2001 @@ -19,9 +19,37 @@ #include #include #include +#include #include "proto.h" +/* data/code implementing a work-around for some SRMs which + mishandle opDEC faults +*/ +static int opDEC_testing = 0; +static int opDEC_fix = 0; +static unsigned long opDEC_test_pc = 0; + +static void +opDEC_check(void) +{ + unsigned long test_pc; + + lock_kernel(); + opDEC_testing = 1; + + __asm__ __volatile__( + " br %0,1f\n" + "1: addq %0,8,%0\n" + " stq %0,%1\n" + " cvttq/svm $f31,$f31\n" + : "=&r"(test_pc), "=m"(opDEC_test_pc) + : ); + + opDEC_testing = 0; + unlock_kernel(); +} + void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) { @@ -56,10 +84,12 @@ #endif } +#if 0 static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"}; +#endif static void dik_show_code(unsigned int *pc) @@ -98,6 +128,18 @@ printk("\n"); } +void show_trace_task(struct task_struct * tsk) +{ + struct thread_struct * thread = &tsk->thread; + unsigned long fp, sp = thread->ksp, base = (unsigned long) thread; + + if (sp > base && sp+6*8 < base + 16*1024) { + fp = ((unsigned long*)sp)[6]; + if (fp > sp && fp < base + 16*1024) + dik_show_trace((unsigned long *)fp); + } +} + int kstack_depth_to_print = 24; void show_stack(unsigned long *sp) @@ -188,8 +230,10 @@ unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs) { - die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"), + if (!opDEC_testing || type != 4) { + die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"), ®s, type, 0); + } switch (type) { case 0: /* breakpoint */ @@ -242,6 +286,21 @@ case 4: /* opDEC */ if (implver() == IMPLVER_EV4) { + /* The some versions of SRM do not handle + the opDEC properly - they return the PC of the + opDEC fault, not the instruction after as the + Alpha architecture requires. Here we fix it up. + We do this by intentionally causing an opDEC + fault during the boot sequence and testing if + we get the correct PC. If not, we set a flag + to correct it every time through. + */ + if (opDEC_testing && regs.pc == opDEC_test_pc) { + opDEC_fix = 4; + printk("opDEC fixup enabled.\n"); + } + regs.pc += opDEC_fix; + /* EV4 does not implement anything except normal rounding. Everything else will come here as an illegal instruction. Emulate them. */ @@ -252,12 +311,13 @@ case 3: /* FEN fault */ case 5: /* illoc */ default: /* unexpected instruction-fault type */ + ; } send_sig(SIGILL, current, 1); } /* There is an ifdef in the PALcode in MILO that enables a - "kernel debugging entry point" as an unprivilaged call_pal. + "kernel debugging entry point" as an unpriviledged call_pal. We don't want to have anything to do with it, but unfortunately several versions of MILO included in distributions have it enabled, @@ -933,4 +993,11 @@ wrent(entUna, 4); wrent(entSys, 5); wrent(entDbg, 6); + + /* Hack for Multia (UDB) and JENSEN: some of their SRMs have + * a bug in the handling of the opDEC fault. Fix it up if so. + */ + if (implver() == IMPLVER_EV4) { + opDEC_check(); + } } diff -u --recursive --new-file v2.4.9/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c --- v2.4.9/linux/arch/alpha/mm/fault.c Mon Mar 19 12:35:09 2001 +++ linux/arch/alpha/mm/fault.c Mon Sep 17 16:15:02 2001 @@ -140,6 +140,7 @@ goto bad_area; } + survive: /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo @@ -194,6 +195,12 @@ * us unable to handle the page fault gracefully. */ out_of_memory: + if (current->pid == 1) { + current->policy |= SCHED_YIELD; + schedule(); + down_read(&mm->mmap_sem); + goto survive; + } printk(KERN_ALERT "VM: killing process %s(%d)\n", current->comm, current->pid); if (!user_mode(regs)) 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 Mon Sep 10 13:04:33 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,14 +58,14 @@ { 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); } static struct exec_domain arthur_exec_domain = { "Arthur", /* name */ - (lcall7_func)arthur_lcall7, + arthur_lcall7, PER_RISCOS, PER_RISCOS, arthur_to_linux_signals, linux_to_arthur_signals, diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/init_task.c linux/arch/arm/kernel/init_task.c --- v2.4.9/linux/arch/arm/kernel/init_task.c Mon Sep 18 15:15:25 2000 +++ linux/arch/arm/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -9,7 +9,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; 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/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c --- v2.4.9/linux/arch/arm/kernel/ptrace.c Mon Aug 27 12:41:38 2001 +++ linux/arch/arm/kernel/ptrace.c Tue Sep 18 17:03:51 2001 @@ -386,6 +386,16 @@ } } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + __ptrace_cancel_bpt(child); +} + static int do_ptrace(int request, struct task_struct *child, long addr, long data) { unsigned long tmp; @@ -491,20 +501,7 @@ * detach a process that was attached. */ case PTRACE_DETACH: - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - /* make sure single-step breakpoint is gone. */ - __ptrace_cancel_bpt(child); - wake_up_process (child); - ret = 0; + ret = ptrace_detach(child, data); break; /* diff -u --recursive --new-file v2.4.9/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.4.9/linux/arch/arm/kernel/traps.c Mon Aug 27 12:41:38 2001 +++ linux/arch/arm/kernel/traps.c Mon Sep 10 13:04:33 2001 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include 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/cris/drivers/parport.c linux/arch/cris/drivers/parport.c --- v2.4.9/linux/arch/cris/drivers/parport.c Sun Aug 12 13:27:58 2001 +++ linux/arch/cris/drivers/parport.c Fri Sep 14 14:04:06 2001 @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/cris/drivers/usb-host.c linux/arch/cris/drivers/usb-host.c --- v2.4.9/linux/arch/cris/drivers/usb-host.c Mon Aug 27 12:41:39 2001 +++ linux/arch/cris/drivers/usb-host.c Mon Sep 10 09:04:53 2001 @@ -2258,11 +2258,11 @@ case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { case (0x01): /* device descriptor */ - len = min(unsigned int, leni, min(unsigned int, sizeof (root_hub_dev_des), wLength)); + len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_dev_des), wLength)); memcpy (data, root_hub_dev_des, len); OK (len); case (0x02): /* configuration descriptor */ - len = min(unsigned int, leni, min(unsigned int, sizeof (root_hub_config_des), wLength)); + len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_config_des), wLength)); memcpy (data, root_hub_config_des, len); OK (len); case (0x03): /* string descriptors */ @@ -2270,7 +2270,7 @@ 0xff, "ETRAX 100LX", data, wLength); if (len > 0) { - OK(min(int, leni, len)); + OK(min_t(int, leni, len)); } else stat = -EPIPE; } @@ -2278,7 +2278,7 @@ case RH_GET_DESCRIPTOR | RH_CLASS: root_hub_hub_des[2] = hc->rh.numports; - len = min(unsigned int, leni, min(unsigned int, sizeof (root_hub_hub_des), wLength)); + len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_hub_des), wLength)); memcpy (data, root_hub_hub_des, len); OK (len); diff -u --recursive --new-file v2.4.9/linux/arch/cris/kernel/process.c linux/arch/cris/kernel/process.c --- v2.4.9/linux/arch/cris/kernel/process.c Sun Aug 12 13:27:58 2001 +++ linux/arch/cris/kernel/process.c Mon Sep 17 15:29:09 2001 @@ -65,7 +65,6 @@ * setup. */ -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/cris/kernel/ptrace.c linux/arch/cris/kernel/ptrace.c --- v2.4.9/linux/arch/cris/kernel/ptrace.c Sun Aug 12 13:27:58 2001 +++ linux/arch/cris/kernel/ptrace.c Tue Sep 18 17:03:51 2001 @@ -82,6 +82,16 @@ return 0; } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* Todo - pending singlesteps? */ +} + /* Note that this implementation of ptrace behaves differently from vanilla * ptrace. Contrary to what the man page says, in the PTRACE_PEEKTEXT, * PTRACE_PEEKDATA, and PTRACE_PEEKUSER requests the data variable is not @@ -245,24 +255,9 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - long tmp; - - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace &= ~(PT_PTRACED | PT_TRACESYS); - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - /* TODO: make sure any pending breakpoint is killed */ - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: + ret = ptrace_detach(child, data); break; - } case PTRACE_GETREGS: { /* Get all gp regs from the child. */ int i; diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S --- v2.4.9/linux/arch/i386/boot/bootsect.S Mon Jan 29 16:19:41 2001 +++ linux/arch/i386/boot/bootsect.S Fri Sep 14 14:04:08 2001 @@ -5,8 +5,12 @@ * modified by Bruce Evans (bde) * modified by Chris Noe (May 1999) (as86 -> gas) * - * bootsect is loaded at 0x7c00 by the bios-startup routines, and moves - * itself out of the way to address 0x90000, and jumps there. + * 360k/720k disk support: Andrzej Krzysztofowicz + * + * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment + * addresses must be multiplied by 16 to obtain their respective linear + * addresses. To avoid confusion, linear addresses are written using leading + * hex while segment addresses are written as segment:offset. * * bde - should not jump blindly, there may be systems with only 512K low * memory. Use int 0x12 to get the top of memory, etc. @@ -43,7 +47,7 @@ #ifndef RAMDISK #define RAMDISK 0 -#endif +#endif #ifndef ROOT_RDONLY #define ROOT_RDONLY 1 @@ -55,14 +59,12 @@ .global _start _start: -#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */ - int $0x3 -#endif +# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there. movw $BOOTSEG, %ax - movw %ax, %ds + movw %ax, %ds # %ds = BOOTSEG movw $INITSEG, %ax - movw %ax, %es + movw %ax, %es # %ax = %es = INITSEG movw $256, %cx subw %si, %si subw %di, %di @@ -81,7 +83,7 @@ # length of bootsect + length of # setup + room for stack; # 12 is disk parm size. - movw %ax, %ds # ax and es already contain INITSEG + movw %ax, %ds # %ax and %es already contain INITSEG movw %ax, %ss movw %di, %sp # put stack at INITSEG:0x4000-12. @@ -97,52 +99,29 @@ # # High doesn't hurt. Low does. # -# Segments are as follows: ds = es = ss = cs - INITSEG, fs = 0, -# and gs is unused. +# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0, +# and %gs is unused. - movw %cx, %fs # set fs to 0 - movw $0x78, %bx # fs:bx is parameter table address + movw %cx, %fs # %fs = 0 + movw $0x78, %bx # %fs:%bx is parameter table address pushw %ds - ldsw %fs:(%bx), %si # ds:si is source + ldsw %fs:(%bx), %si # %ds:%si is source movb $6, %cl # copy 12 bytes - pushw %di # di = 0x4000-12. - rep # don't need cld -> done on line 66 - movsw + pushw %di # %di = 0x4000-12. + rep # don't worry about cld + movsw # already done above popw %di popw %ds movb $36, 0x4(%di) # patch sector count movw %di, %fs:(%bx) movw %es, %fs:2(%bx) -# Load the setup-sectors directly after the bootblock. -# Note that 'es' is already set up. -# Also, cx = 0 from rep movsw above. - -load_setup: - xorb %ah, %ah # reset FDC - xorb %dl, %dl - int $0x13 - xorw %dx, %dx # drive 0, head 0 - movb $0x02, %cl # sector 2, track 0 - movw $0x0200, %bx # address = 512, in INITSEG - movb $0x02, %ah # service 2, "read sector(s)" - movb setup_sects, %al # (assume all on head 0, track 0) - int $0x13 # read it - jnc ok_load_setup # ok - continue - - pushw %ax # dump error code - call print_nl - movw %sp, %bp - call print_hex - popw %ax - jmp load_setup - -ok_load_setup: # Get disk drive parameters, specifically number of sectors/track. # It seems that there is no BIOS call to get the number of sectors. # Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18 # can be read, 15 if sector 15 can be read. Otherwise guess 9. +# Note that %cx = 0 from rep movsw above. movw $disksizes, %si # table of sizes to try probe_loop: @@ -151,30 +130,56 @@ movw %ax, sectors cmpw $disksizes+4, %si jae got_sectors # If all else fails, try 9 - - xchgw %cx, %ax # cx = track and sector + + xchgw %cx, %ax # %cx = track and sector xorw %dx, %dx # drive 0, head 0 - xorb %bl, %bl - movb setup_sects, %bh - incb %bh - shlb %bh # address after setup (es = cs) + movw $0x0200, %bx # address = 512, in INITSEG (%es = %cs) movw $0x0201, %ax # service 2, 1 sector int $0x13 jc probe_loop # try next value got_sectors: - movw $INITSEG, %ax - movw %ax, %es # set up es movb $0x03, %ah # read cursor pos xorb %bh, %bh int $0x10 movw $9, %cx - movw $0x0007, %bx # page 0, attribute 7 (normal) - movw $msg1, %bp - movw $0x1301, %ax # write string, move cursor + movb $0x07, %bl # page 0, attribute 7 (normal) + # %bh is set above; int10 doesn't + # modify it + movw $msg1, %bp + movw $0x1301, %ax # write string, move cursor int $0x10 # tell the user we're loading.. - movw $SYSSEG, %ax # ok, we've written the message, now - movw %ax, %es # we want to load system (at 0x10000) + +# Load the setup-sectors directly after the moved bootblock (at 0x90200). +# We should know the drive geometry to do it, as setup may exceed first +# cylinder (for 9-sector 360K and 720K floppies). + + movw $0x0001, %ax # set sread (sector-to-read) to 1 as + movw $sread, %si # the boot sector has already been read + movw %ax, (%si) + + xorw %ax, %ax # reset FDC + xorb %dl, %dl + int $0x13 + movw $0x0200, %bx # address = 512, in INITSEG +next_step: + movb setup_sects, %al + movw sectors, %cx + subw (%si), %cx # (%si) = sread + cmpb %cl, %al + jbe no_cyl_crossing + movw sectors, %ax + subw (%si), %ax # (%si) = sread +no_cyl_crossing: + call read_track + pushw %ax # save it + call set_next # set %bx properly; it uses %ax,%cx,%dx + popw %ax # restore + subb %al, setup_sects # rest - for next step + jnz next_step + + pushw $SYSSEG + popw %es # %es = SYSSEG call read_it call kill_motor call print_nl @@ -184,23 +189,26 @@ # Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8) # depending on the number of sectors we pretend to know we have. +# Segments are as follows: %cs = %ds = %ss = INITSEG, +# %es = SYSSEG, %fs = 0, %gs is unused. + movw root_dev, %ax orw %ax, %ax jne root_defined - + movw sectors, %bx movw $0x0208, %ax # /dev/ps0 - 1.2Mb cmpw $15, %bx je root_defined - + movb $0x1c, %al # /dev/PS0 - 1.44Mb cmpw $18, %bx je root_defined - + movb $0x20, %al # /dev/fd0H2880 - 2.88Mb cmpw $36, %bx je root_defined - + movb $0, %al # /dev/fd0 - autodetect root_defined: movw %ax, root_dev @@ -210,46 +218,45 @@ ljmp $SETUPSEG, $0 -# This routine loads the system at address 0x10000, making sure -# no 64kB boundaries are crossed. We try to load it as fast as -# possible, loading whole tracks whenever we can. - -# es = starting address segment (normally 0x1000) +# These variables are addressed via %si register as it gives shorter code. sread: .word 0 # sectors read of current track head: .word 0 # current head track: .word 0 # current track +# This routine loads the system at address SYSSEG, making sure +# no 64kB boundaries are crossed. We try to load it as fast as +# possible, loading whole tracks whenever we can. + read_it: - movb setup_sects, %al - incb %al - movb %al, sread - movw %es, %ax + movw %es, %ax # %es = SYSSEG when called testw $0x0fff, %ax -die: jne die # es must be at 64kB boundary - - xorw %bx, %bx # bx is starting address within segment +die: jne die # %es must be at 64kB boundary + xorw %bx, %bx # %bx is starting address within segment rp_read: -#ifdef __BIG_KERNEL__ - bootsect_kludge = 0x220 # 0x200 (size of bootsector) + 0x20 (offset - lcall bootsect_kludge # of bootsect_kludge in setup.S) +#ifdef __BIG_KERNEL__ # look in setup.S for bootsect_kludge + bootsect_kludge = 0x220 # 0x200 + 0x20 which is the size of the + lcall bootsect_kludge # bootsector + bootsect_kludge offset #else movw %es, %ax subw $SYSSEG, %ax + movw %bx, %cx + shr $4, %cx + add %cx, %ax # check offset #endif - cmpw syssize, %ax # have we loaded all yet? + cmpw syssize, %ax # have we loaded everything yet? jbe ok1_read ret ok1_read: movw sectors, %ax - subw sread, %ax + subw (%si), %ax # (%si) = sread movw %ax, %cx shlw $9, %cx addw %bx, %cx jnc ok2_read - + je ok2_read xorw %ax, %ax @@ -257,60 +264,64 @@ shrw $9, %ax ok2_read: call read_track - movw %ax, %cx - addw sread, %ax - cmpw sectors, %ax - jne ok3_read - - movw $1, %ax - subw head, %ax - jne ok4_read - - incw track -ok4_read: - movw %ax, head - xorw %ax, %ax -ok3_read: - movw %ax, sread - shlw $9, %cx - addw %cx, %bx - jnc rp_read - - movw %es, %ax - addb $0x10, %ah - movw %ax, %es - xorw %bx, %bx + call set_next jmp rp_read read_track: pusha pusha - movw $0xe2e, %ax # loading... message 2e = . + movw $0xe2e, %ax # loading... message 2e = . movw $7, %bx int $0x10 popa - movw track, %dx - movw sread, %cx + +# Accessing head, track, sread via %si gives shorter code. + + movw 4(%si), %dx # 4(%si) = track + movw (%si), %cx # (%si) = sread incw %cx movb %dl, %ch - movw head, %dx + movw 2(%si), %dx # 2(%si) = head movb %dl, %dh andw $0x0100, %dx movb $2, %ah - pushw %dx # save for error dump + pushw %dx # save for error dump pushw %cx pushw %bx pushw %ax int $0x13 jc bad_rt - + addw $8, %sp popa ret +set_next: + movw %ax, %cx + addw (%si), %ax # (%si) = sread + cmp sectors, %ax + jne ok3_set + movw $0x0001, %ax + xorw %ax, 2(%si) # change head + jne ok4_set + incw 4(%si) # next track +ok4_set: + xorw %ax, %ax +ok3_set: + movw %ax, (%si) # set sread + shlw $9, %cx + addw %cx, %bx + jnc set_next_fin + movw %es, %ax + addb $0x10, %ah + movw %ax, %es + xorw %bx, %bx +set_next_fin: + ret + bad_rt: - pushw %ax # save error code - call print_all # ah = error, al = read + pushw %ax # save error code + call print_all # %ah = error, %al = read xorb %ah, %ah xorb %dl, %dl int $0x13 @@ -331,13 +342,13 @@ # ret <- %sp print_all: - movw $5, %cx # error code + 4 registers + movw $5, %cx # error code + 4 registers movw %sp, %bp print_loop: - pushw %cx # save count left - call print_nl # nl for readability + pushw %cx # save count remaining + call print_nl # <-- for readability cmpb $5, %cl - jae no_reg # see if register name is needed + jae no_reg # see if register name is needed movw $0xe05 + 'A' - 1, %ax subb %cl, %al @@ -347,31 +358,31 @@ movb $':', %al int $0x10 no_reg: - addw $2, %bp # next register - call print_hex # print it + addw $2, %bp # next register + call print_hex # print it popw %cx loop print_loop ret print_nl: - movw $0xe0d, %ax # CR + movw $0xe0d, %ax # CR int $0x10 - movb $0xa, %al # LF + movb $0xa, %al # LF int $0x10 ret # print_hex is for debugging purposes, and prints the word -# pointed to by ss:bp in hexadecimal. +# pointed to by %ss:%bp in hexadecimal. print_hex: - movw $4, %cx # 4 hex digits - movw (%bp), %dx # load word into dx + movw $4, %cx # 4 hex digits + movw (%bp), %dx # load word into %dx print_digit: - rolw $4, %dx # rotate to use low 4 bits - movw $0xe0f, %ax # ah = request - andb %dl, %al # al = mask for nybble - addb $0x90, %al # convert al to ascii hex - daa # in only four instructions! + rolw $4, %dx # rotate to use low 4 bits + movw $0xe0f, %ax # %ah = request + andb %dl, %al # %al = mask for nybble + addb $0x90, %al # convert %al to ascii hex + daa # in only four instructions! adc $0x40, %al daa int $0x10 @@ -381,6 +392,7 @@ # This procedure turns off the floppy drive motor, so # that we enter the kernel in a known state, and # don't have to worry about it later. +# NOTE: Doesn't save %ax or %dx; do it yourself if you need to. kill_motor: movw $0x3f2, %dx diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile --- v2.4.9/linux/arch/i386/boot/compressed/Makefile Tue Mar 7 11:04:12 2000 +++ linux/arch/i386/boot/compressed/Makefile Tue Sep 11 23:08:12 2001 @@ -9,7 +9,6 @@ OBJECTS = $(HEAD) misc.o -CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS ZLDFLAGS = -e startup_32 # diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c --- v2.4.9/linux/arch/i386/boot/compressed/misc.c Tue Feb 13 13:15:04 2001 +++ linux/arch/i386/boot/compressed/misc.c Tue Sep 11 23:02:02 2001 @@ -12,6 +12,7 @@ #include #include #include + /* * gzip declarations */ @@ -21,6 +22,14 @@ #undef memset #undef memcpy + +/* + * Why do we do this? Don't ask me.. + * + * Incomprehensible are the ways of bootloaders. + */ +static void* memset(void *, int, size_t); +static void* memcpy(void *, __const void *, size_t); #define memzero(s, n) memset ((s), 0, (n)) typedef unsigned char uch; @@ -194,7 +203,7 @@ outb_p(0xff & (pos >> 1), vidport+1); } -void* memset(void* s, int c, size_t n) +static void* memset(void* s, int c, size_t n) { int i; char *ss = (char*)s; @@ -203,7 +212,7 @@ return s; } -void* memcpy(void* __dest, __const void* __src, +static void* memcpy(void* __dest, __const void* __src, size_t __n) { int i; diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/install.sh linux/arch/i386/boot/install.sh --- v2.4.9/linux/arch/i386/boot/install.sh Tue Jan 3 03:57:26 1995 +++ linux/arch/i386/boot/install.sh Fri Sep 14 14:04:06 2001 @@ -21,6 +21,7 @@ # User may have a custom install script +if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi # Default install - same as make zlilo diff -u --recursive --new-file v2.4.9/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.4.9/linux/arch/i386/config.in Wed Jul 25 17:10:17 2001 +++ linux/arch/i386/config.in Mon Sep 17 22:52:35 2001 @@ -186,7 +186,10 @@ comment 'General setup' bool 'Networking support' CONFIG_NET -bool 'SGI Visual Workstation support' CONFIG_VISWS + +# Visual Workstation support is utterly broken. +# If you want to see it working mail an VW540 to hch@infradead.org 8) +#bool 'SGI Visual Workstation support' CONFIG_VISWS if [ "$CONFIG_VISWS" = "y" ]; then define_bool CONFIG_X86_VISWS_APIC y define_bool CONFIG_X86_LOCAL_APIC y @@ -388,6 +391,13 @@ mainmenu_option next_comment comment 'Kernel hacking' -#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC -bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +bool 'Kernel debugging' CONFIG_DEBUG_KERNEL +if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then + bool ' Debug memory allocations' CONFIG_DEBUG_SLAB + bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT + bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ + bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK + bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE +fi + endmenu 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 Tue Sep 18 11:15:11 2001 @@ -65,7 +65,6 @@ # General setup # CONFIG_NET=y -# CONFIG_VISWS is not set CONFIG_X86_IO_APIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_PCI=y @@ -136,6 +135,7 @@ # CONFIG_MD_RAID0 is not set # CONFIG_MD_RAID1 is not set # CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set # CONFIG_BLK_DEV_LVM is not set # @@ -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 @@ -253,6 +254,9 @@ # CONFIG_IDEDMA_IVB is not set # CONFIG_DMA_NONPCI is not set CONFIG_BLK_DEV_IDE_MODES=y +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set # # SCSI support @@ -288,6 +292,7 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -306,6 +311,7 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set CONFIG_SCSI_SYM53C8XX=y @@ -374,7 +380,6 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_ARM_AM79C961A is not set # CONFIG_SUNLANCE is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNBMAC is not set @@ -396,8 +401,6 @@ # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set # CONFIG_TULIP is not set -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set # CONFIG_DE4X5 is not set # CONFIG_DGRS is not set # CONFIG_DM9102 is not set @@ -424,9 +427,9 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set -# CONFIG_ACENIC_OMIT_TIGON_I is not set # CONFIG_DL2K is not set # CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set @@ -464,6 +467,7 @@ # CONFIG_PCMCIA_XIRC2PS is not set # CONFIG_ARCNET_COM20020_CS is not set # CONFIG_PCMCIA_IBMTR is not set +# CONFIG_PCMCIA_XIRCOM is not set # CONFIG_PCMCIA_XIRTULIP is not set CONFIG_NET_PCMCIA_RADIO=y CONFIG_PCMCIA_RAYCS=y @@ -495,6 +499,10 @@ # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Character devices @@ -525,7 +533,11 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# # # Input core support is needed for joysticks @@ -705,6 +717,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 +751,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 @@ -761,4 +774,4 @@ # # Kernel hacking # -# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v2.4.9/linux/arch/i386/kernel/Makefile Fri Dec 29 14:35:47 2000 +++ linux/arch/i386/kernel/Makefile Mon Sep 17 23:03:09 2001 @@ -30,15 +30,15 @@ endif endif -obj-$(CONFIG_MCA) += mca.o -obj-$(CONFIG_MTRR) += mtrr.o -obj-$(CONFIG_X86_MSR) += msr.o -obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_MICROCODE) += microcode.o -obj-$(CONFIG_APM) += apm.o -obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o -obj-$(CONFIG_X86_LOCAL_APIC) += apic.o -obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o +obj-$(CONFIG_MCA) += mca.o +obj-$(CONFIG_MTRR) += mtrr.o +obj-$(CONFIG_X86_MSR) += msr.o +obj-$(CONFIG_X86_CPUID) += cpuid.o +obj-$(CONFIG_MICROCODE) += microcode.o +obj-$(CONFIG_APM) += apm.o +obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o +obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o +obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c --- v2.4.9/linux/arch/i386/kernel/apic.c Tue Jul 3 17:08:18 2001 +++ linux/arch/i386/kernel/apic.c Mon Sep 17 23:03:09 2001 @@ -9,6 +9,7 @@ * and Rolf G. Tews * for testing these extensively. * Maciej W. Rozycki : Various updates and fixes. + * Mikael Pettersson : Power Management for UP-APIC. */ #include @@ -29,6 +30,9 @@ #include #include +/* Using APIC to generate smp_local_timer_interrupt? */ +int using_apic_timer = 0; + int prof_multiplier[NR_CPUS] = { 1, }; int prof_old_multiplier[NR_CPUS] = { 1, }; int prof_counter[NR_CPUS] = { 1, }; @@ -90,10 +94,10 @@ */ clear_local_APIC(); /* - * PIC mode, enable symmetric IO mode in the IMCR, - * i.e. connect BSP's local APIC to INT and NMI lines. + * PIC mode, enable APIC mode in the IMCR, i.e. + * connect BSP's local APIC to INT and NMI lines. */ - printk("leaving PIC mode, enabling symmetric IO mode.\n"); + printk("leaving PIC mode, enabling APIC mode.\n"); outb(0x70, 0x22); outb(0x01, 0x23); } @@ -108,7 +112,7 @@ * interrupts, including IPIs, won't work beyond * this point! The only exception are INIT IPIs. */ - printk("disabling symmetric IO mode, entering PIC mode.\n"); + printk("disabling APIC mode, entering PIC mode.\n"); outb(0x70, 0x22); outb(0x00, 0x23); } @@ -125,7 +129,7 @@ * for 82489DX!). */ value = apic_read(APIC_SPIV); - value &= ~(1<<8); + value &= ~APIC_SPIV_APIC_ENABLED; apic_write_around(APIC_SPIV, value); } @@ -204,6 +208,48 @@ extern void __error_in_apic_c (void); +/* + * An initial setup of the virtual wire mode. + */ +void __init init_bsp_APIC(void) +{ + unsigned long value, ver; + + /* + * Don't do the setup now if we have a SMP BIOS as the + * through-I/O-APIC virtual wire mode might be active. + */ + if (smp_found_config || !cpu_has_apic) + return; + + value = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(value); + + /* + * Do not trust the local APIC being empty at bootup. + */ + clear_local_APIC(); + + /* + * Enable APIC. + */ + value = apic_read(APIC_SPIV); + value &= ~APIC_VECTOR_MASK; + value |= APIC_SPIV_APIC_ENABLED; + value |= APIC_SPIV_FOCUS_DISABLED; + value |= SPURIOUS_APIC_VECTOR; + apic_write_around(APIC_SPIV, value); + + /* + * Set up the virtual wire mode. + */ + apic_write_around(APIC_LVT0, APIC_DM_EXTINT); + value = APIC_DM_NMI; + if (!APIC_INTEGRATED(ver)) /* 82489DX */ + value |= APIC_LVT_LEVEL_TRIGGER; + apic_write_around(APIC_LVT1, value); +} + void __init setup_local_APIC (void) { unsigned long value, ver, maxlvt; @@ -256,7 +302,7 @@ /* * Enable APIC */ - value |= (1<<8); + value |= APIC_SPIV_APIC_ENABLED; /* * Some unknown Intel IO/APIC (or APIC) errata is biting us with @@ -279,10 +325,10 @@ */ #if 1 /* Enable focus processor (bit==0) */ - value &= ~(1<<9); + value &= ~APIC_SPIV_FOCUS_DISABLED; #else /* Disable focus processor (bit==1) */ - value |= (1<<9); + value |= APIC_SPIV_FOCUS_DISABLED; #endif /* * Set spurious IRQ vector @@ -339,24 +385,250 @@ printk("ESR value after enabling vector: %08lx\n", value); } else printk("No ESR for 82489DX.\n"); + + if (nmi_watchdog == NMI_LOCAL_APIC) + setup_apic_nmi_watchdog(); } -void __init init_apic_mappings(void) +#ifdef CONFIG_PM + +#include +#include + +static struct { + /* 'active' is true if the local APIC was enabled by us and + not the BIOS; this signifies that we are also responsible + for disabling it before entering apm/acpi suspend */ + int active; + /* 'perfctr_pmdev' is here because the current (2.4.1) PM + callback system doesn't handle hierarchical dependencies */ + struct pm_dev *perfctr_pmdev; + /* r/w apic fields */ + unsigned int apic_id; + unsigned int apic_taskpri; + unsigned int apic_ldr; + unsigned int apic_dfr; + unsigned int apic_spiv; + unsigned int apic_lvtt; + unsigned int apic_lvtpc; + unsigned int apic_lvt0; + unsigned int apic_lvt1; + unsigned int apic_lvterr; + unsigned int apic_tmict; + unsigned int apic_tdcr; +} apic_pm_state; + +static void apic_pm_suspend(void *data) { - unsigned long apic_phys; + unsigned int l, h; + unsigned long flags; - if (smp_found_config) { - apic_phys = mp_lapic_addr; - } else { + if (apic_pm_state.perfctr_pmdev) + pm_send(apic_pm_state.perfctr_pmdev, PM_SUSPEND, data); + apic_pm_state.apic_id = apic_read(APIC_ID); + apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); + apic_pm_state.apic_ldr = apic_read(APIC_LDR); + apic_pm_state.apic_dfr = apic_read(APIC_DFR); + apic_pm_state.apic_spiv = apic_read(APIC_SPIV); + apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); + apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); + apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); + apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); + apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); + apic_pm_state.apic_tmict = apic_read(APIC_TMICT); + apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); + __save_flags(flags); + __cli(); + disable_local_APIC(); + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_ENABLE; + wrmsr(MSR_IA32_APICBASE, l, h); + __restore_flags(flags); +} + +static void apic_pm_resume(void *data) +{ + unsigned int l, h; + unsigned long flags; + + __save_flags(flags); + __cli(); + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_BASE; + l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; + wrmsr(MSR_IA32_APICBASE, l, h); + apic_write(APIC_ID, apic_pm_state.apic_id); + apic_write(APIC_DFR, apic_pm_state.apic_dfr); + apic_write(APIC_LDR, apic_pm_state.apic_ldr); + apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri); + apic_write(APIC_SPIV, apic_pm_state.apic_spiv); + apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); + apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); + apic_write(APIC_ESR, 0); + apic_read(APIC_ESR); + apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); + apic_write(APIC_ESR, 0); + apic_read(APIC_ESR); + apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); + apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); + apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); + apic_write(APIC_TMICT, apic_pm_state.apic_tmict); + __restore_flags(flags); + if (apic_pm_state.perfctr_pmdev) + pm_send(apic_pm_state.perfctr_pmdev, PM_RESUME, data); +} + +static int apic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + switch (rqst) { + case PM_SUSPEND: + apic_pm_suspend(data); + break; + case PM_RESUME: + apic_pm_resume(data); + break; + } + return 0; +} + +/* perfctr driver should call this instead of pm_register() */ +struct pm_dev *apic_pm_register(pm_dev_t type, + unsigned long id, + pm_callback callback) +{ + struct pm_dev *dev; + + if (!apic_pm_state.active) + return pm_register(type, id, callback); + if (apic_pm_state.perfctr_pmdev) + return NULL; /* we're busy */ + dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL); + if (dev) { + memset(dev, 0, sizeof(*dev)); + dev->type = type; + dev->id = id; + dev->callback = callback; + apic_pm_state.perfctr_pmdev = dev; + } + return dev; +} + +/* perfctr driver should call this instead of pm_unregister() */ +void apic_pm_unregister(struct pm_dev *dev) +{ + if (!apic_pm_state.active) { + pm_unregister(dev); + } else if (dev == apic_pm_state.perfctr_pmdev) { + apic_pm_state.perfctr_pmdev = NULL; + kfree(dev); + } +} + +static void __init apic_pm_init1(void) +{ + /* can't pm_register() at this early stage in the boot process + (causes an immediate reboot), so just set the flag */ + apic_pm_state.active = 1; +} + +static void __init apic_pm_init2(void) +{ + if (apic_pm_state.active) + pm_register(PM_SYS_DEV, 0, apic_pm_callback); +} + +#else /* CONFIG_PM */ + +static inline void apic_pm_init1(void) { } +static inline void apic_pm_init2(void) { } + +#endif /* CONFIG_PM */ + +/* + * Detect and enable local APICs on non-SMP boards. + * Original code written by Keir Fraser. + */ + +static int __init detect_init_APIC (void) +{ + u32 h, l, features; + int needs_pm = 0; + extern void get_cpu_vendor(struct cpuinfo_x86*); + + /* Workaround for us being called before identify_cpu(). */ + get_cpu_vendor(&boot_cpu_data); + + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) + break; + goto no_apic; + case X86_VENDOR_INTEL: + if (boot_cpu_data.x86 == 6 || + (boot_cpu_data.x86 == 5 && cpu_has_apic)) + break; + goto no_apic; + default: + goto no_apic; + } + + if (!cpu_has_apic) { /* - * set up a fake all zeroes page to simulate the - * local APIC and another one for the IO-APIC. We - * could use the real zero-page, but it's safer - * this way if some buggy code writes to this page ... + * Some BIOSes disable the local APIC in the + * APIC_BASE MSR. This can only be done in + * software for Intel P6 and AMD K7 (Model > 1). */ + rdmsr(MSR_IA32_APICBASE, l, h); + if (!(l & MSR_IA32_APICBASE_ENABLE)) { + printk("Local APIC disabled by BIOS -- reenabling.\n"); + l &= ~MSR_IA32_APICBASE_BASE; + l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; + wrmsr(MSR_IA32_APICBASE, l, h); + needs_pm = 1; + } + } + /* + * The APIC feature bit should now be enabled + * in `cpuid' + */ + features = cpuid_edx(1); + if (!(features & (1 << X86_FEATURE_APIC))) { + printk("Could not enable APIC!\n"); + return -1; + } + set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability); + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + boot_cpu_id = 0; + if (nmi_watchdog != NMI_NONE) + nmi_watchdog = NMI_LOCAL_APIC; + + printk("Found and enabled local APIC!\n"); + + if (needs_pm) + apic_pm_init1(); + + return 0; + +no_apic: + printk("No local APIC present or hardware disabled\n"); + return -1; +} + +void __init init_apic_mappings(void) +{ + unsigned long apic_phys; + + /* + * If no local APIC can be found then set up a fake all + * zeroes page to simulate the local APIC and another + * one for the IO-APIC. + */ + if (!smp_found_config && detect_init_APIC()) { apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); apic_phys = __pa(apic_phys); - } + } else + apic_phys = mp_lapic_addr; + set_fixmap_nocache(FIX_APIC_BASE, apic_phys); Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys); @@ -603,6 +875,9 @@ void __init setup_APIC_clocks (void) { + printk("Using local APIC timer interrupts.\n"); + using_apic_timer = 1; + __cli(); calibration_result = calibrate_APIC_clock(); @@ -790,3 +1065,43 @@ smp_processor_id(), v , v1); } +/* + * This initializes the IO-APIC and APIC hardware if this is + * a UP kernel. + */ +int __init APIC_init_uniprocessor (void) +{ + if (!smp_found_config && !cpu_has_apic) + return -1; + + /* + * Complain if the BIOS pretends there is one. + */ + if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_id])) { + printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", + boot_cpu_id); + return -1; + } + + verify_local_APIC(); + + connect_bsp_APIC(); + + phys_cpu_present_map = 1; + apic_write_around(APIC_ID, boot_cpu_id); + + apic_pm_init2(); + + setup_local_APIC(); + + if (nmi_watchdog == NMI_LOCAL_APIC) + check_nmi_watchdog(); +#ifdef CONFIG_X86_IO_APIC + if (smp_found_config) + if (!skip_ioapic_setup && nr_ioapics) + setup_IO_APIC(); +#endif + setup_APIC_clocks(); + + return 0; +} diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.4.9/linux/arch/i386/kernel/apm.c Mon Aug 27 12:41:39 2001 +++ linux/arch/i386/kernel/apm.c Mon Sep 17 22:52:35 2001 @@ -148,6 +148,10 @@ * 1.14: Make connection version persist across module unload/load. * Enable and engage power management earlier. * Disengage power management on module unload. + * Changed to use the sysrq-register hack for registering the + * power off function called by magic sysrq based upon discussions + * in irc://irc.openprojects.net/#kernelnewbies + * (Crutcher Dunnavant ). * Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable. * (Arjan van de Ven ) modified by sfr. * Work around byte swap bug in one of the Vaio's BIOS's @@ -197,12 +201,11 @@ #include #include +#include + extern unsigned long get_cmos_time(void); extern void machine_real_restart(unsigned char *, int); -#ifdef CONFIG_MAGIC_SYSRQ -extern void (*sysrq_power_off)(void); -#endif #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) extern int (*console_blank_hook)(int); #endif @@ -686,6 +689,23 @@ (void) apm_set_power_state(APM_STATE_OFF); } +#ifdef CONFIG_MAGIC_SYSRQ +/* + * Magic sysrq key and handler for the power off function + */ + +void handle_poweroff (int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + apm_power_off(); +} +struct sysrq_key_op sysrq_poweroff_op = { + handler: handle_poweroff, + help_msg: "Off", + action_msg: "Power Off\n" +}; +#endif + + #ifdef CONFIG_APM_DO_ENABLE static int apm_enable_power_management(int enable) { @@ -1544,9 +1564,8 @@ /* Install our power off handler.. */ if (power_off) pm_power_off = apm_power_off; -#ifdef CONFIG_MAGIC_SYSRQ - sysrq_power_off = apm_power_off; -#endif + register_sysrq_key('o',&sysrq_poweroff_op); + if (smp_num_cpus == 1) { #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) console_blank_hook = apm_console_blank; @@ -1761,9 +1780,7 @@ } misc_deregister(&apm_device); remove_proc_entry("apm", NULL); -#ifdef CONFIG_MAGIC_SYSRQ - sysrq_power_off = NULL; -#endif + unregister_sysrq_key('o',&sysrq_poweroff_op); if (power_off) pm_power_off = NULL; exit_kapmd = 1; 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;i #include #include +#include +#include +#include struct dmi_header { @@ -87,7 +90,15 @@ unsigned char buf[20]; long fp=0xE0000L; fp -= 16; - + +#ifdef CONFIG_SIMNOW + /* + * Skip on x86/64 with simnow. Will eventually go away + * If you see this ifdef in 2.6pre mail me ! + */ + return; +#endif + while( fp < 0xFFFFF) { fp+=16; @@ -191,6 +202,11 @@ } /* + * Reboot options and system auto-detection code provided by + * Dell Computer Corporation so their systems "just work". :-) + */ + +/* * Some machines require the "reboot=b" commandline option, this quirk makes that automatic. */ static __init int set_bios_reboot(struct dmi_blacklist *d) @@ -205,6 +221,32 @@ } /* + * Some machines require the "reboot=s" commandline option, this quirk makes that automatic. + */ +static __init int set_smp_reboot(struct dmi_blacklist *d) +{ +#ifdef CONFIG_SMP + extern int reboot_smp; + if (reboot_smp == 0) + { + reboot_smp = 1; + printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident); + } +#endif + return 0; +} + +/* + * Some machines require the "reboot=b,s" commandline option, this quirk makes that automatic. + */ +static __init int set_smp_bios_reboot(struct dmi_blacklist *d) +{ + set_smp_reboot(d); + set_bios_reboot(d); + return 0; +} + +/* * Some bioses have a broken protected mode poweroff and need to use realmode */ @@ -271,6 +313,27 @@ return 0; } +#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE) +/* + * Check for a Sony Vaio system in order to enable the use of + * the sonypi driver (we don't want this driver to be used on + * other systems, even if they have the good PCI IDs). + * + * This one isn't a bug detect for those who asked, we simply want to + * activate Sony specific goodies like the camera and jogdial.. + */ +int is_sony_vaio_laptop; + +static __init int sony_vaio_laptop(struct dmi_blacklist *d) +{ + if (is_sony_vaio_laptop == 0) + { + is_sony_vaio_laptop = 1; + printk(KERN_INFO "%s laptop detected.\n", d->ident); + } + return 0; +} +#endif /* * This bios swaps the APM minute reporting bytes over (Many sony laptops @@ -283,6 +346,46 @@ printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n"); return 0; } + +/* + * The Intel 440GX hall of shame. + * + * On many (all we have checked) of these boxes the $PIRQ table is wrong. + * The MP1.4 table is right however and so SMP kernels tend to work. + */ + +static __init int broken_pirq(struct dmi_blacklist *d) +{ + printk(KERN_INFO " *** Possibly defective BIOS detected (irqtable)\n"); + printk(KERN_INFO " *** Many BIOSes matching this signature have incorrect IRQ routing tables.\n"); + printk(KERN_INFO " *** If you see IRQ problems, in paticular SCSI resets and hangs at boot\n"); + printk(KERN_INFO " *** contact your vendor and ask about updates.\n"); + printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.\n"); + return 0; +} + +/* + * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it + * was disabled before the suspend. Linux gets terribly confused by that. + */ + +typedef void (pm_kbd_func) (void); +extern pm_kbd_func *pm_kbd_request_override; + +static __init int broken_ps2_resume(struct dmi_blacklist *d) +{ +#ifdef CONFIG_VT + if (pm_kbd_request_override == NULL) + { + pm_kbd_request_override = pckbd_pm_resume; + printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround enabled.\n", d->ident); + } +#endif + return 0; +} + + + /* * Process the DMI blacklists */ @@ -300,6 +403,11 @@ NO_MATCH, NO_MATCH, NO_MATCH } }, #endif + { broken_ps2_resume, "Dell Latitude C600", { /* Handle problems with APM on the C600 */ + MATCH(DMI_SYS_VENDOR, "Dell"), + MATCH(DMI_PRODUCT_NAME, "Latitude C600"), + NO_MATCH, NO_MATCH + } }, { broken_apm_power, "Dell Inspiron 5000e", { /* Handle problems with APM on Inspiron 5000e */ MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), MATCH(DMI_BIOS_VERSION, "A04"), @@ -310,14 +418,14 @@ MATCH(DMI_BIOS_VERSION, "4.60 PGMA"), MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH } }, - { set_bios_reboot, "PowerEdge 1300/500", { /* Handle problems with rebooting on Dell 1300's */ + { set_smp_bios_reboot, "Dell PowerEdge 1300", { /* Handle problems with rebooting on Dell 1300's */ MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), - MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/500"), + MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"), NO_MATCH, NO_MATCH } }, - { set_bios_reboot, "PowerEdge 1300/550", { /* Handle problems with rebooting on Dell 1300's */ + { set_bios_reboot, "Dell PowerEdge 300", { /* Handle problems with rebooting on Dell 1300's */ MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), - MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/550"), + MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"), NO_MATCH, NO_MATCH } }, { set_apm_ints, "IBM", { /* Allow interrupts during suspend on IBM laptops */ @@ -329,6 +437,12 @@ MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), NO_MATCH, NO_MATCH } }, + { set_apm_ints, "Compaq 12XL125", { /* Allow interrupts during suspend on Compaq Laptops*/ + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "Compaq PC"), + MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + MATCH(DMI_BIOS_VERSION,"4.06") + } }, { set_apm_ints, "ASUSTeK", { /* Allow interrupts during APM or the clock goes slow */ MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), @@ -339,21 +453,97 @@ MATCH(DMI_PRODUCT_NAME, "Delhi3"), NO_MATCH, NO_MATCH, } }, - { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */ + { apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */ + MATCH(DMI_SYS_VENDOR, "SHARP"), + MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"), + MATCH(DMI_BIOS_VENDOR,"SystemSoft"), + MATCH(DMI_BIOS_VERSION,"Version R2.08") + } }, +#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE) + { sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */ + MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + MATCH(DMI_PRODUCT_NAME, "PCG-"), + NO_MATCH, NO_MATCH, + } }, +#endif + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */ MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - MATCH(DMI_BIOS_VERSION, "R0203Z3"), - MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH + MATCH(DMI_BIOS_VERSION, "R0206H"), + MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH + } }, + + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */ + MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + MATCH(DMI_BIOS_VERSION, "W2K06H0"), + MATCH(DMI_BIOS_DATE, "02/03/00"), NO_MATCH } }, - { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */ + + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-XG29 */ MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - MATCH(DMI_BIOS_VERSION, "R0203D0"), - MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH + MATCH(DMI_BIOS_VERSION, "R0117A0"), + MATCH(DMI_BIOS_DATE, "04/25/00"), NO_MATCH } }, + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z600NE */ MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), MATCH(DMI_BIOS_VERSION, "R0121Z1"), MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH } }, + + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */ + MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + MATCH(DMI_BIOS_VERSION, "R0203D0"), + MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH + } }, + + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */ + MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + MATCH(DMI_BIOS_VERSION, "R0203Z3"), + MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH + } }, + + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-F104K */ + MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + MATCH(DMI_BIOS_VERSION, "R0204K2"), + MATCH(DMI_BIOS_DATE, "08/28/00"), NO_MATCH + } }, + + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */ + MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + MATCH(DMI_BIOS_VERSION, "R0208P1"), + MATCH(DMI_BIOS_DATE, "11/09/00"), NO_MATCH + } }, + { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-C1VE */ + MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + MATCH(DMI_BIOS_VERSION, "R0204P1"), + MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH + } }, + + /* Problem Intel 440GX bioses */ + + { broken_pirq, "SABR1 Bios", { /* Bad $PIR */ + MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), + MATCH(DMI_BIOS_VERSION,"SABR1"), + NO_MATCH, NO_MATCH + } }, + { broken_pirq, "l44GX Bios", { /* Bad $PIR */ + MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), + MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0094.P10"), + NO_MATCH, NO_MATCH + } }, + { broken_pirq, "l44GX Bios", { /* Bad $PIR */ + MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), + MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"), + NO_MATCH, NO_MATCH + } }, + + /* Intel in disgiuse - In this case they can't hide and they don't run + too well either... */ + { broken_pirq, "Dell PowerEdge 8450", { /* Bad $PIR */ + MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"), + NO_MATCH, NO_MATCH, NO_MATCH + } }, + { NULL, } }; diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.4.9/linux/arch/i386/kernel/entry.S Tue Jul 3 17:08:18 2001 +++ linux/arch/i386/kernel/entry.S Sat Sep 8 12:02:32 2001 @@ -621,12 +621,6 @@ .long SYMBOL_NAME(sys_fcntl64) .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ - /* - * NOTE!! This doesn't have to be exact - we just have - * to make sure we have _enough_ of the "sys_ni_syscall" - * entries. Don't panic if you notice that this hasn't - * been shrunk every time we add a new system call. - */ - .rept NR_syscalls-221 + .rept NR_syscalls-(.-sys_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.4.9/linux/arch/i386/kernel/i386_ksyms.c Mon Aug 27 12:41:39 2001 +++ linux/arch/i386/kernel/i386_ksyms.c Mon Sep 17 22:52:35 2001 @@ -72,7 +72,7 @@ EXPORT_SYMBOL(apm_info); EXPORT_SYMBOL(gdt); -#ifdef CONFIG_IO_DEBUG +#ifdef CONFIG_DEBUG_IOVIRT EXPORT_SYMBOL(__io_virt_debug); #endif @@ -165,3 +165,13 @@ #ifdef CONFIG_HAVE_DEC_LOCK EXPORT_SYMBOL(atomic_dec_and_lock); #endif + +#ifdef CONFIG_DEBUG_BUGVERBOSE +EXPORT_SYMBOL(do_BUG); +#endif + +#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE) +extern int is_sony_vaio_laptop; +EXPORT_SYMBOL(is_sony_vaio_laptop); +#endif + diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c --- v2.4.9/linux/arch/i386/kernel/i8259.c Tue Jul 3 17:08:18 2001 +++ linux/arch/i386/kernel/i8259.c Mon Sep 17 23:03:09 2001 @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -415,6 +416,9 @@ { int i; +#ifdef CONFIG_X86_LOCAL_APIC + init_bsp_APIC(); +#endif init_8259A(0); for (i = 0; i < NR_IRQS; i++) { diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/init_task.c linux/arch/i386/kernel/init_task.c --- v2.4.9/linux/arch/i386/kernel/init_task.c Tue Aug 3 10:32:57 1999 +++ linux/arch/i386/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -6,7 +6,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.4.9/linux/arch/i386/kernel/io_apic.c Tue Jul 3 17:08:18 2001 +++ linux/arch/i386/kernel/io_apic.c Mon Sep 17 23:03:09 2001 @@ -33,25 +33,17 @@ #include #include +#undef APIC_LOCKUP_DEBUG + #define APIC_LOCKUP_DEBUG static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; /* - * # of IO-APICs and # of IRQ routing registers + * # of IRQ routing registers */ -int nr_ioapics; int nr_ioapic_registers[MAX_IO_APICS]; -/* I/O APIC entries */ -struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; - -/* # of MP IRQ source entries */ -struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; - -/* MP IRQ source entries */ -int mp_irq_entries; - #if CONFIG_SMP # define TARGET_CPUS cpu_online_map #else @@ -154,14 +146,17 @@ void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) { struct IO_APIC_route_entry entry; + unsigned long flags; /* * Disable it in the IO-APIC irq-routing table: */ memset(&entry, 0, sizeof(entry)); entry.mask = 1; + spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0)); io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1)); + spin_unlock_irqrestore(&ioapic_lock, flags); } static void clear_IO_APIC (void) @@ -595,6 +590,7 @@ { struct IO_APIC_route_entry entry; int apic, pin, idx, irq, first_notcon = 1, vector; + unsigned long flags; printk(KERN_DEBUG "init IO_APIC IRQs\n"); @@ -650,8 +646,10 @@ if (!apic && (irq < 16)) disable_8259A_irq(irq); } + spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); + spin_unlock_irqrestore(&ioapic_lock, flags); } } @@ -666,6 +664,7 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) { struct IO_APIC_route_entry entry; + unsigned long flags; memset(&entry,0,sizeof(entry)); @@ -695,8 +694,10 @@ /* * Add it to the IO-APIC irq-routing table: */ + spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); + spin_unlock_irqrestore(&ioapic_lock, flags); enable_8259A_irq(0); } @@ -713,6 +714,7 @@ struct IO_APIC_reg_00 reg_00; struct IO_APIC_reg_01 reg_01; struct IO_APIC_reg_02 reg_02; + unsigned long flags; printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); for (i = 0; i < nr_ioapics; i++) @@ -727,10 +729,12 @@ for (apic = 0; apic < nr_ioapics; apic++) { + spin_lock_irqsave(&ioapic_lock, flags); *(int *)®_00 = io_apic_read(apic, 0); *(int *)®_01 = io_apic_read(apic, 1); if (reg_01.version >= 0x10) *(int *)®_02 = io_apic_read(apic, 2); + spin_unlock_irqrestore(&ioapic_lock, flags); printk("\n"); printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid); @@ -742,11 +746,9 @@ printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01); printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.entries); if ( (reg_01.entries != 0x0f) && /* older (Neptune) boards */ - (reg_01.entries != 0x11) && (reg_01.entries != 0x17) && /* typical ISA+PCI boards */ (reg_01.entries != 0x1b) && /* Compaq Proliant boards */ (reg_01.entries != 0x1f) && /* dual Xeon boards */ - (reg_01.entries != 0x20) && (reg_01.entries != 0x22) && /* bigger Xeon boards */ (reg_01.entries != 0x2E) && (reg_01.entries != 0x3F) @@ -757,7 +759,8 @@ if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */ (reg_01.version != 0x10) && /* oldest IO-APICs */ (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */ - (reg_01.version != 0x13) /* Xeon IO-APICs */ + (reg_01.version != 0x13) && /* Xeon IO-APICs */ + (reg_01.entries != 0x20) /* Intel P64H (82806 AA) */ ) UNEXPECTED_IO_APIC(); if (reg_01.__reserved_1 || reg_01.__reserved_2) @@ -778,8 +781,10 @@ for (i = 0; i <= reg_01.entries; i++) { struct IO_APIC_route_entry entry; + spin_lock_irqsave(&ioapic_lock, flags); *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2); *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2); + spin_unlock_irqrestore(&ioapic_lock, flags); printk(KERN_DEBUG " %02x %03X %02X ", i, @@ -806,7 +811,7 @@ continue; printk(KERN_DEBUG "IRQ%d ", i); for (;;) { - printk("-> %d", entry->pin); + printk("-> %d:%d", entry->apic, entry->pin); if (!entry->next) break; entry = irq_2_pin + entry->next; @@ -956,6 +961,7 @@ { struct IO_APIC_reg_01 reg_01; int i; + unsigned long flags; for (i = 0; i < PIN_MAP_SIZE; i++) { irq_2_pin[i].pin = -1; @@ -969,7 +975,9 @@ * The number of IO-APIC IRQ registers (== #pins): */ for (i = 0; i < nr_ioapics; i++) { + spin_lock_irqsave(&ioapic_lock, flags); *(int *)®_01 = io_apic_read(i, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); nr_ioapic_registers[i] = reg_01.entries+1; } @@ -1006,6 +1014,7 @@ int apic; int i; unsigned char old_id; + unsigned long flags; /* * Set the IOAPIC ID to the value stored in the MPC table. @@ -1013,7 +1022,9 @@ for (apic = 0; apic < nr_ioapics; apic++) { /* Read the register 0 value */ + spin_lock_irqsave(&ioapic_lock, flags); *(int *)®_00 = io_apic_read(apic, 0); + spin_unlock_irqrestore(&ioapic_lock, flags); old_id = mp_ioapics[apic].mpc_apicid; @@ -1062,12 +1073,16 @@ mp_ioapics[apic].mpc_apicid); reg_00.ID = mp_ioapics[apic].mpc_apicid; + spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0, *(int *)®_00); + spin_unlock_irqrestore(&ioapic_lock, flags); /* * Sanity check */ + spin_lock_irqsave(&ioapic_lock, flags); *(int *)®_00 = io_apic_read(apic, 0); + spin_unlock_irqrestore(&ioapic_lock, flags); if (reg_00.ID != mp_ioapics[apic].mpc_apicid) panic("could not set ID!\n"); else @@ -1104,25 +1119,6 @@ return 0; } -static int __init nmi_irq_works(void) -{ - irq_cpustat_t tmp[NR_CPUS]; - int j, cpu; - - memcpy(tmp, irq_stat, sizeof(tmp)); - sti(); - mdelay(50); - - for (j = 0; j < smp_num_cpus; j++) { - cpu = cpu_logical_map(j); - if (nmi_count(cpu) - tmp[cpu].__nmi_count <= 3) { - printk(KERN_WARNING "CPU#%d NMI appears to be stuck.\n", cpu); - return 0; - } - } - return 1; -} - /* * In the SMP+IOAPIC case it might happen that there are an unspecified * number of pending IRQ events unhandled. These cases are very rare, @@ -1212,6 +1208,7 @@ static void end_level_ioapic_irq (unsigned int irq) { unsigned long v; + int i; /* * It appears there is an erratum which affects at least version 0x11 @@ -1232,11 +1229,12 @@ * operation to prevent an edge-triggered interrupt escaping meanwhile. * The idea is from Manfred Spraul. --macro */ - v = apic_read(APIC_TMR + ((IO_APIC_VECTOR(irq) & ~0x1f) >> 1)); + i = IO_APIC_VECTOR(irq); + v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); ack_APIC_irq(); - if (!(v & (1 << (IO_APIC_VECTOR(irq) & 0x1f)))) { + if (!(v & (1 << (i & 0x1f)))) { #ifdef APIC_MISMATCH_DEBUG atomic_inc(&irq_mis_count); #endif @@ -1416,13 +1414,16 @@ int pin, i; struct IO_APIC_route_entry entry0, entry1; unsigned char save_control, save_freq_select; + unsigned long flags; pin = find_isa_irq_pin(8, mp_INT); if (pin == -1) return; + spin_lock_irqsave(&ioapic_lock, flags); *(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin); *(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin); + spin_unlock_irqrestore(&ioapic_lock, flags); clear_IO_APIC_pin(0, pin); memset(&entry1, 0, sizeof(entry1)); @@ -1435,8 +1436,10 @@ entry1.trigger = 0; entry1.vector = 0; + spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1)); io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0)); + spin_unlock_irqrestore(&ioapic_lock, flags); save_control = CMOS_READ(RTC_CONTROL); save_freq_select = CMOS_READ(RTC_FREQ_SELECT); @@ -1455,8 +1458,10 @@ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); clear_IO_APIC_pin(0, pin); + spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1)); io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0)); + spin_unlock_irqrestore(&ioapic_lock, flags); } /* @@ -1493,7 +1498,7 @@ pin1 = find_isa_irq_pin(0, mp_INT); pin2 = find_isa_irq_pin(0, mp_ExtINT); - printk(KERN_INFO "..TIMER: vector=%02X pin1=%d pin2=%d\n", vector, pin1, pin2); + printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2); if (pin1 != -1) { /* @@ -1501,11 +1506,11 @@ */ unmask_IO_APIC_irq(0); if (timer_irq_works()) { - if (nmi_watchdog) { + if (nmi_watchdog == NMI_IO_APIC) { disable_8259A_irq(0); setup_nmi(); enable_8259A_irq(0); - nmi_irq_works(); + check_nmi_watchdog(); } return; } @@ -1522,9 +1527,9 @@ setup_ExtINT_IRQ0_pin(pin2, vector); if (timer_irq_works()) { printk("works.\n"); - if (nmi_watchdog) { + if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); - nmi_irq_works(); + check_nmi_watchdog(); } return; } @@ -1605,19 +1610,3 @@ check_timer(); print_IO_APIC(); } - -#ifndef CONFIG_SMP -/* - * This initializes the IO-APIC and APIC hardware if this is - * a UP kernel. - */ -void IO_APIC_init_uniprocessor (void) -{ - if (!smp_found_config) - return; - connect_bsp_APIC(); - setup_local_APIC(); - setup_IO_APIC(); - setup_APIC_clocks(); -} -#endif diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.4.9/linux/arch/i386/kernel/irq.c Tue Jul 3 17:08:18 2001 +++ linux/arch/i386/kernel/irq.c Mon Sep 17 23:03:09 2001 @@ -166,7 +166,7 @@ p += sprintf(p, "%10u ", nmi_count(cpu_logical_map(j))); p += sprintf(p, "\n"); -#if CONFIG_SMP +#if CONFIG_X86_LOCAL_APIC p += sprintf(p, "LOC: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", @@ -471,14 +471,15 @@ * disable_irq_nosync - disable an irq without waiting * @irq: Interrupt to disable * - * Disable the selected interrupt line. Disables of an interrupt - * stack. Unlike disable_irq(), this function does not ensure existing + * Disable the selected interrupt line. Disables and Enables are + * nested. + * Unlike disable_irq(), this function does not ensure existing * instances of the IRQ handler have completed before returning. * * This function may be called from IRQ context. */ -void inline disable_irq_nosync(unsigned int irq) +inline void disable_irq_nosync(unsigned int irq) { irq_desc_t *desc = irq_desc + irq; unsigned long flags; @@ -495,9 +496,9 @@ * disable_irq - disable an irq and wait for completion * @irq: Interrupt to disable * - * Disable the selected interrupt line. Disables of an interrupt - * stack. That is for two disables you need two enables. This - * function waits for any pending IRQ handlers for this interrupt + * Disable the selected interrupt line. Enables and Disables are + * nested. + * This function waits for any pending IRQ handlers for this interrupt * to complete before returning. If you use this function while * holding a resource the IRQ handler may need you will deadlock. * @@ -516,11 +517,12 @@ } /** - * enable_irq - enable interrupt handling on an irq + * enable_irq - enable handling of an irq * @irq: Interrupt to enable * - * Re-enables the processing of interrupts on this IRQ line - * providing no disable_irq calls are now in effect. + * Undoes the effect of one call to disable_irq(). If this + * matches the last disable, processing of interrupts on this + * IRQ line is re-enabled. * * This function may be called from IRQ context. */ @@ -1027,20 +1029,9 @@ static struct proc_dir_entry * root_irq_dir; static struct proc_dir_entry * irq_dir [NR_IRQS]; -static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; - -static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; #define HEX_DIGITS 8 -static int irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - if (count < HEX_DIGITS+1) - return -EINVAL; - return sprintf (page, "%08lx\n", irq_affinity[(long)data]); -} - static unsigned int parse_hex_value (const char *buffer, unsigned long count, unsigned long *ret) { @@ -1078,6 +1069,19 @@ return 0; } +#if CONFIG_SMP + +static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; + +static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; +static int irq_affinity_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08lx\n", irq_affinity[(long)data]); +} + static int irq_affinity_write_proc (struct file *file, const char *buffer, unsigned long count, void *data) { @@ -1089,7 +1093,6 @@ err = parse_hex_value(buffer, count, &new_value); -#if CONFIG_SMP /* * Do not allow disabling IRQs completely - it's a too easy * way to make the system unusable accidentally :-) At least @@ -1097,7 +1100,6 @@ */ if (!(new_value & cpu_online_map)) return -EINVAL; -#endif irq_affinity[irq] = new_value; irq_desc[irq].handler->set_affinity(irq, new_value); @@ -1105,6 +1107,8 @@ return full_count; } +#endif + static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -1132,7 +1136,6 @@ static void register_irq_proc (unsigned int irq) { - struct proc_dir_entry *entry; char name [MAX_NAMELEN]; if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || @@ -1145,15 +1148,23 @@ /* create /proc/irq/1234 */ irq_dir[irq] = proc_mkdir(name, root_irq_dir); - /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); +#if CONFIG_SMP + { + struct proc_dir_entry *entry; - entry->nlink = 1; - entry->data = (void *)(long)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; + /* create /proc/irq/1234/smp_affinity */ + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); - smp_affinity_entry[irq] = entry; + if (entry) { + entry->nlink = 1; + entry->data = (void *)(long)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } + + smp_affinity_entry[irq] = entry; + } +#endif } unsigned long prof_cpu_mask = -1; @@ -1168,6 +1179,9 @@ /* create /proc/irq/prof_cpu_mask */ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); + + if (!entry) + return; entry->nlink = 1; entry->data = (void *)&prof_cpu_mask; diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/microcode.c linux/arch/i386/kernel/microcode.c --- v2.4.9/linux/arch/i386/kernel/microcode.c Fri Feb 9 11:29:44 2001 +++ linux/arch/i386/kernel/microcode.c Fri Sep 14 14:04:08 2001 @@ -126,6 +126,7 @@ printk(KERN_ERR "microcode: failed to devfs_register()\n"); goto out; } + error = 0; printk(KERN_INFO "IA-32 Microcode Update Driver: v%s \n", MICROCODE_VERSION); diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c --- v2.4.9/linux/arch/i386/kernel/mpparse.c Sun Aug 12 13:27:58 2001 +++ linux/arch/i386/kernel/mpparse.c Mon Sep 17 23:03:09 2001 @@ -38,6 +38,18 @@ int mp_bus_id_to_type [MAX_MP_BUSSES]; int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; int mp_current_pci_id; + +/* I/O APIC entries */ +struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; + +/* # of MP IRQ source entries */ +struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; + +/* MP IRQ source entries */ +int mp_irq_entries; + +int nr_ioapics; + int pic_mode; unsigned long mp_lapic_addr; @@ -225,6 +237,11 @@ MAX_IO_APICS, nr_ioapics); panic("Recompile kernel with bigger MAX_IO_APICS!.\n"); } + if (!m->mpc_apicaddr) { + printk(KERN_ERR "WARNING: bogus zero I/O APIC address" + " found in MP table, skipping!\n"); + return; + } mp_ioapics[nr_ioapics] = *m; nr_ioapics++; } @@ -365,10 +382,19 @@ return num_processors; } +static int __init ELCR_trigger(unsigned int irq) +{ + unsigned int port; + + port = 0x4d0 + (irq >> 3); + return (inb(port) >> (irq & 7)) & 1; +} + static void __init construct_default_ioirq_mptable(int mpc_default_type) { struct mpc_config_intsrc intsrc; int i; + int ELCR_fallback = 0; intsrc.mpc_type = MP_INTSRC; intsrc.mpc_irqflag = 0; /* conforming */ @@ -376,6 +402,26 @@ intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid; intsrc.mpc_irqtype = mp_INT; + + /* + * If true, we have an ISA/PCI system with no IRQ entries + * in the MP table. To prevent the PCI interrupts from being set up + * incorrectly, we try to use the ELCR. The sanity check to see if + * there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can + * never be level sensitive, so we simply see if the ELCR agrees. + * If it does, we assume it's valid. + */ + if (mpc_default_type == 5) { + printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n"); + + if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13)) + printk("ELCR contains invalid data... not using ELCR\n"); + else { + printk("Using ELCR to identify PCI interrupts\n"); + ELCR_fallback = 1; + } + } + for (i = 0; i < 16; i++) { switch (mpc_default_type) { case 2: @@ -387,6 +433,18 @@ continue; /* IRQ2 is never connected */ } + if (ELCR_fallback) { + /* + * If the ELCR indicates a level-sensitive interrupt, we + * copy that information over to the MP table in the + * irqflag field (level sensitive, active high polarity). + */ + if (ELCR_trigger(i)) + intsrc.mpc_irqflag = 13; + else + intsrc.mpc_irqflag = 0; + } + intsrc.mpc_srcbusirq = i; intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ MP_intsrc_info(&intsrc); @@ -641,7 +699,7 @@ */ void __init find_smp_config (void) { -#ifdef CONFIG_X86_IO_APIC +#ifdef CONFIG_X86_LOCAL_APIC find_intel_smp(); #endif #ifdef CONFIG_VISWS diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- v2.4.9/linux/arch/i386/kernel/mtrr.c Thu May 24 15:14:08 2001 +++ linux/arch/i386/kernel/mtrr.c Sat Sep 1 11:05:16 2001 @@ -389,21 +389,19 @@ return; /* Save value of CR4 and clear Page Global Enable (bit 7) */ - if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) - asm volatile ("movl %%cr4, %0\n\t" - "movl %0, %1\n\t" - "andb $0x7f, %b1\n\t" - "movl %1, %%cr4\n\t" - : "=r" (ctxt->cr4val), "=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/nmi.c linux/arch/i386/kernel/nmi.c --- v2.4.9/linux/arch/i386/kernel/nmi.c Wed Dec 31 16:00:00 1969 +++ linux/arch/i386/kernel/nmi.c Mon Sep 17 23:03:09 2001 @@ -0,0 +1,299 @@ +/* + * linux/arch/i386/nmi.c + * + * NMI watchdog support on APIC systems + * + * Started by Ingo Molnar + * + * Fixes: + * Mikael Pettersson : AMD K7 support for local APIC NMI watchdog. + * Mikael Pettersson : Power Management for local APIC NMI watchdog. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +unsigned int nmi_watchdog = NMI_NONE; +static unsigned int nmi_hz = HZ; +unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ + +#define K7_EVNTSEL_ENABLE (1 << 22) +#define K7_EVNTSEL_INT (1 << 20) +#define K7_EVNTSEL_OS (1 << 17) +#define K7_EVNTSEL_USR (1 << 16) +#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76 +#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING + +#define P6_EVNTSEL0_ENABLE (1 << 22) +#define P6_EVNTSEL_INT (1 << 20) +#define P6_EVNTSEL_OS (1 << 17) +#define P6_EVNTSEL_USR (1 << 16) +#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79 +#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED + +int __init check_nmi_watchdog (void) +{ + irq_cpustat_t tmp[NR_CPUS]; + int j, cpu; + + printk(KERN_INFO "testing NMI watchdog ... "); + + memcpy(tmp, irq_stat, sizeof(tmp)); + sti(); + mdelay((10*1000)/nmi_hz); // wait 10 ticks + + for (j = 0; j < smp_num_cpus; j++) { + cpu = cpu_logical_map(j); + if (nmi_count(cpu) - tmp[cpu].__nmi_count <= 5) { + printk("CPU#%d: NMI appears to be stuck!\n", cpu); + return -1; + } + } + printk("OK.\n"); + + /* now that we know it works we can reduce NMI frequency to + something more reasonable; makes a difference in some configs */ + if (nmi_watchdog == NMI_LOCAL_APIC) + nmi_hz = 1; + + return 0; +} + +static int __init setup_nmi_watchdog(char *str) +{ + int nmi; + + get_option(&str, &nmi); + + if (nmi >= NMI_INVALID) + return 0; + if (nmi == NMI_NONE) + nmi_watchdog = nmi; + /* + * If any other x86 CPU has a local APIC, then + * please test the NMI stuff there and send me the + * missing bits. Right now Intel P6 and AMD K7 only. + */ + if ((nmi == NMI_LOCAL_APIC) && + (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && + (boot_cpu_data.x86 == 6)) + nmi_watchdog = nmi; + if ((nmi == NMI_LOCAL_APIC) && + (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && + (boot_cpu_data.x86 == 6)) + nmi_watchdog = nmi; + /* + * We can enable the IO-APIC watchdog + * unconditionally. + */ + if (nmi == NMI_IO_APIC) + nmi_watchdog = nmi; + return 1; +} + +__setup("nmi_watchdog=", setup_nmi_watchdog); + +#ifdef CONFIG_PM + +#include + +struct pm_dev *nmi_pmdev; + +static void disable_apic_nmi_watchdog(void) +{ + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + wrmsr(MSR_K7_EVNTSEL0, 0, 0); + break; + case X86_VENDOR_INTEL: + wrmsr(MSR_IA32_EVNTSEL0, 0, 0); + break; + } +} + +static int nmi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + switch (rqst) { + case PM_SUSPEND: + disable_apic_nmi_watchdog(); + break; + case PM_RESUME: + setup_apic_nmi_watchdog(); + break; + } + return 0; +} + +static void nmi_pm_init(void) +{ + if (!nmi_pmdev) + nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback); +} + +#define __pminit /*empty*/ + +#else /* CONFIG_PM */ + +static inline void nmi_pm_init(void) { } + +#define __pminit __init + +#endif /* CONFIG_PM */ + +/* + * Activate the NMI watchdog via the local APIC. + * Original code written by Keith Owens. + */ + +static void __pminit setup_k7_watchdog(void) +{ + int i; + unsigned int evntsel; + + nmi_perfctr_msr = MSR_K7_PERFCTR0; + + for(i = 0; i < 4; ++i) { + wrmsr(MSR_K7_EVNTSEL0+i, 0, 0); + wrmsr(MSR_K7_PERFCTR0+i, 0, 0); + } + + evntsel = K7_EVNTSEL_INT + | K7_EVNTSEL_OS + | K7_EVNTSEL_USR + | K7_NMI_EVENT; + + wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); + Dprintk("setting K7_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000)); + wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1); + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= K7_EVNTSEL_ENABLE; + wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); +} + +static void __pminit setup_p6_watchdog(void) +{ + int i; + unsigned int evntsel; + + nmi_perfctr_msr = MSR_IA32_PERFCTR0; + + for(i = 0; i < 2; ++i) { + wrmsr(MSR_IA32_EVNTSEL0+i, 0, 0); + wrmsr(MSR_IA32_PERFCTR0+i, 0, 0); + } + + evntsel = P6_EVNTSEL_INT + | P6_EVNTSEL_OS + | P6_EVNTSEL_USR + | P6_NMI_EVENT; + + wrmsr(MSR_IA32_EVNTSEL0, evntsel, 0); + Dprintk("setting IA32_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000)); + wrmsr(MSR_IA32_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0); + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= P6_EVNTSEL0_ENABLE; + wrmsr(MSR_IA32_EVNTSEL0, evntsel, 0); +} + +void __pminit setup_apic_nmi_watchdog (void) +{ + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + if (boot_cpu_data.x86 != 6) + return; + setup_k7_watchdog(); + break; + case X86_VENDOR_INTEL: + if (boot_cpu_data.x86 != 6) + return; + setup_p6_watchdog(); + break; + default: + return; + } + nmi_pm_init(); +} + +static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED; + +/* + * the best way to detect whether a CPU has a 'hard lockup' problem + * is to check it's local APIC timer IRQ counts. If they are not + * changing then that CPU has some problem. + * + * as these watchdog NMI IRQs are generated on every CPU, we only + * have to check the current processor. + * + * since NMIs dont listen to _any_ locks, we have to be extremely + * careful not to rely on unsafe variables. The printk might lock + * up though, so we have to break up any console locks first ... + * [when there will be more tty-related locks, break them up + * here too!] + */ + +static unsigned int + last_irq_sums [NR_CPUS], + alert_counter [NR_CPUS]; + +void touch_nmi_watchdog (void) +{ + int i; + + /* + * Just reset the alert counters, (other CPUs might be + * spinning on locks we hold): + */ + for (i = 0; i < smp_num_cpus; i++) + alert_counter[i] = 0; +} + +void nmi_watchdog_tick (struct pt_regs * regs) +{ + + /* + * Since current-> is always on the stack, and we always switch + * the stack NMI-atomically, it's safe to use smp_processor_id(). + */ + int sum, cpu = smp_processor_id(); + + sum = apic_timer_irqs[cpu]; + + if (last_irq_sums[cpu] == sum) { + /* + * Ayiee, looks like this CPU is stuck ... + * wait a few IRQs (5 seconds) before doing the oops ... + */ + alert_counter[cpu]++; + if (alert_counter[cpu] == 5*nmi_hz) { + spin_lock(&nmi_print_lock); + /* + * We are in trouble anyway, lets at least try + * to get a message out. + */ + bust_spinlocks(1); + printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu); + show_registers(regs); + printk("console shuts up ...\n"); + console_silent(); + spin_unlock(&nmi_print_lock); + bust_spinlocks(0); + do_exit(SIGSEGV); + } + } else { + last_irq_sums[cpu] = sum; + alert_counter[cpu] = 0; + } + if (nmi_perfctr_msr) + wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1); +} 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/process.c linux/arch/i386/kernel/process.c --- v2.4.9/linux/arch/i386/kernel/process.c Sun Aug 12 13:27:58 2001 +++ linux/arch/i386/kernel/process.c Mon Sep 17 22:52:35 2001 @@ -154,6 +154,12 @@ static int reboot_mode; int reboot_thru_bios; +#ifdef CONFIG_SMP +int reboot_smp = 0; +static int reboot_cpu = -1; +/* shamelessly grabbed from lib/vsprintf.c for readability */ +#define is_digit(c) ((c) >= '0' && (c) <= '9') +#endif static int __init reboot_setup(char *str) { while(1) { @@ -170,6 +176,19 @@ case 'h': /* "hard" reboot by toggling RESET and/or crashing the CPU */ reboot_thru_bios = 0; break; +#ifdef CONFIG_SMP + case 's': /* "smp" reboot by executing reset on BSP or other CPU*/ + reboot_smp = 1; + if (is_digit(*(str+1))) { + reboot_cpu = (int) (*(str+1) - '0'); + if (is_digit(*(str+2))) + reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0'); + } + /* we will leave sorting out the final value + when we are ready to reboot, since we might not + have set up boot_cpu_id or smp_num_cpu */ + break; +#endif } if((str = strchr(str,',')) != NULL) str++; @@ -346,6 +365,34 @@ void machine_restart(char * __unused) { #if CONFIG_SMP + int cpuid; + + cpuid = GET_APIC_ID(apic_read(APIC_ID)); + + if (reboot_smp) { + + /* check to see if reboot_cpu is valid + if its not, default to the BSP */ + if ((reboot_cpu == -1) || + (reboot_cpu > (NR_CPUS -1)) || + !(phys_cpu_present_map & (1<pid, current->comm); printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs,regs->eip, smp_processor_id()); if (regs->xcs & 3) printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v2.4.9/linux/arch/i386/kernel/ptrace.c Wed Jul 25 17:10:17 2001 +++ linux/arch/i386/kernel/ptrace.c Tue Sep 18 17:04:23 2001 @@ -134,6 +134,19 @@ return retval; } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + long tmp; + + tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; + put_stack_long(child, EFL_OFFSET, tmp); +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -202,7 +215,7 @@ break; tmp = 0; /* Default return condition */ - if(addr < 17*sizeof(long)) + if(addr < FRAME_SIZE*sizeof(long)) tmp = getreg(child, addr); if(addr >= (long) &dummy->u_debugreg[0] && addr <= (long) &dummy->u_debugreg[7]){ @@ -229,7 +242,7 @@ addr > sizeof(struct user) - 3) break; - if (addr < 17*sizeof(long)) { + if (addr < FRAME_SIZE*sizeof(long)) { ret = putreg(child, addr, data); break; } @@ -320,33 +333,17 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - long tmp; - - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace = 0; - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: + /* detach a process that was attached. */ + ret = ptrace_detach(child, data); break; - } case PTRACE_GETREGS: { /* Get all gp regs from the child. */ - if (!access_ok(VERIFY_WRITE, (unsigned *)data, 17*sizeof(long))) { + if (!access_ok(VERIFY_WRITE, (unsigned *)data, FRAME_SIZE*sizeof(long))) { ret = -EIO; break; } - for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) { + for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) { __put_user(getreg(child, i),(unsigned long *) data); data += sizeof(long); } @@ -356,11 +353,11 @@ case PTRACE_SETREGS: { /* Set all gp regs in the child. */ unsigned long tmp; - if (!access_ok(VERIFY_READ, (unsigned *)data, 17*sizeof(long))) { + if (!access_ok(VERIFY_READ, (unsigned *)data, FRAME_SIZE*sizeof(long))) { ret = -EIO; break; } - for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) { + for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) { __get_user(tmp, (unsigned long *) data); putreg(child, i, tmp); data += sizeof(long); 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 Mon Sep 17 23:03:09 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; @@ -937,27 +941,14 @@ * trampoline before removing it. (see the GDT stuff) */ reserve_bootmem(PAGE_SIZE, PAGE_SIZE); - smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif -#ifdef CONFIG_X86_IO_APIC +#ifdef CONFIG_X86_LOCAL_APIC /* * Find and reserve possible boot-time SMP configuration: */ find_smp_config(); #endif - paging_init(); -#ifdef CONFIG_X86_IO_APIC - /* - * get boot-time SMP configuration: - */ - if (smp_found_config) - get_smp_config(); -#endif -#ifdef CONFIG_X86_LOCAL_APIC - init_apic_mappings(); -#endif - #ifdef CONFIG_BLK_DEV_INITRD if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { @@ -977,6 +968,25 @@ #endif /* + * NOTE: before this point _nobody_ is allowed to allocate + * any memory using the bootmem allocator. + */ + +#ifdef CONFIG_SMP + smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ +#endif + paging_init(); +#ifdef CONFIG_X86_LOCAL_APIC + /* + * get boot-time SMP configuration: + */ + if (smp_found_config) + get_smp_config(); + init_apic_mappings(); +#endif + + + /* * Request address space for all standard RAM and ROM resources * and also for regions reported as reserved by the e820. */ @@ -1088,11 +1098,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 +1126,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 +1143,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 +1208,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 +1229,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 +1249,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 +1335,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 +1575,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 +1599,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 +1618,6 @@ } break; } - } @@ -1668,7 +1690,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 +1715,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 +2009,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/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.4.9/linux/arch/i386/kernel/signal.c Wed Jul 25 17:10:17 2001 +++ linux/arch/i386/kernel/signal.c Fri Sep 14 14:15:40 2001 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -665,13 +666,16 @@ continue; /* FALLTHRU */ - case SIGSTOP: + case SIGSTOP: { + struct signal_struct *sig; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + sig = current->p_pptr->sig; + if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; + } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.4.9/linux/arch/i386/kernel/smp.c Mon Aug 27 12:41:39 2001 +++ linux/arch/i386/kernel/smp.c Mon Sep 17 23:03:09 2001 @@ -429,9 +429,10 @@ atomic_t started; atomic_t finished; int wait; -}; +} __attribute__ ((__aligned__(SMP_CACHE_BYTES))); static struct call_data_struct * call_data; +static struct call_data_struct call_data_array[NR_CPUS]; /* * this function sends a 'generic call function' IPI to all other CPUs @@ -453,32 +454,45 @@ * hardware interrupt handler, you may call it from a bottom half handler. */ { - struct call_data_struct data; - int cpus = smp_num_cpus-1; + struct call_data_struct *data; + int cpus = (cpu_online_map & ~(1 << smp_processor_id())); if (!cpus) return 0; - data.func = func; - data.info = info; - atomic_set(&data.started, 0); - data.wait = wait; + data = &call_data_array[smp_processor_id()]; + + data->func = func; + data->info = info; + data->wait = wait; if (wait) - atomic_set(&data.finished, 0); - - spin_lock_bh(&call_lock); - call_data = &data; + atomic_set(&data->finished, 0); + /* We have do to this one last to make sure that the IPI service + * code desn't get confused if it gets an unexpected repeat + * trigger of an old IPI while we're still setting up the new + * one. */ + atomic_set(&data->started, 0); + + local_bh_disable(); + spin_lock(&call_lock); + call_data = data; /* Send a message to all other CPUs and wait for them to respond */ send_IPI_allbutself(CALL_FUNCTION_VECTOR); /* Wait for response */ - while (atomic_read(&data.started) != cpus) + while (atomic_read(&data->started) != cpus) barrier(); + /* It is now safe to reuse the "call_data" global, but we need + * to keep local bottom-halves disabled until after waiters have + * been acknowledged to prevent reuse of the per-cpu call data + * entry. */ + spin_unlock(&call_lock); + if (wait) - while (atomic_read(&data.finished) != cpus) + while (atomic_read(&data->finished) != cpus) barrier(); - spin_unlock_bh(&call_lock); + local_bh_enable(); return 0; } @@ -528,15 +542,17 @@ ack_APIC_irq(); /* - * Notify initiating CPU that I've grabbed the data and am - * about to execute the function + * Notify initiating CPU that I've grabbed the data and am about + * to execute the function (and avoid servicing any single IPI + * twice) */ - atomic_inc(&call_data->started); + if (test_and_set_bit(smp_processor_id(), &call_data->started)) + return; /* * At this point the info structure may be out of scope unless wait==1 */ (*func)(info); if (wait) - atomic_inc(&call_data->finished); + set_bit(smp_processor_id(), &call_data->finished); } diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c --- v2.4.9/linux/arch/i386/kernel/smpboot.c Tue Feb 13 14:13:43 2001 +++ linux/arch/i386/kernel/smpboot.c Mon Sep 17 23:03:09 2001 @@ -66,7 +66,7 @@ static volatile unsigned long cpu_callout_map; /* Per CPU bogomips and other parameters */ -struct cpuinfo_x86 cpu_data[NR_CPUS]; +struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; /* Set when the idlers are all forked */ int smp_threads_ready; @@ -780,7 +780,6 @@ } cycles_t cacheflush_time; -extern unsigned long cpu_khz; static void smp_tune_scheduling (void) { @@ -870,12 +869,15 @@ * get out of here now! */ if (!smp_found_config) { - printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n"); + printk(KERN_NOTICE "SMP motherboard not detected.\n"); #ifndef CONFIG_VISWS io_apic_irqs = 0; #endif cpu_online_map = phys_cpu_present_map = 1; smp_num_cpus = 1; + if (APIC_init_uniprocessor()) + printk(KERN_NOTICE "Local APIC not detected." + " Using dummy APIC emulation.\n"); goto smp_done; } @@ -1003,7 +1005,7 @@ * Here we can be sure that there is an IO-APIC in the system. Let's * go and set it up: */ - if (!skip_ioapic_setup) + if (!skip_ioapic_setup && nr_ioapics) setup_IO_APIC(); #endif @@ -1021,4 +1023,3 @@ smp_done: zap_low_mappings(); } - diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c --- v2.4.9/linux/arch/i386/kernel/time.c Fri Dec 29 14:07:57 2000 +++ linux/arch/i386/kernel/time.c Mon Sep 17 23:03:09 2001 @@ -178,6 +178,15 @@ jiffies_t = jiffies; count |= inb_p(0x40) << 8; + + /* VIA686a test code... reset the latch if count > max + 1 */ + if (count > LATCH) { + outb_p(0x34, 0x43); + outb_p(LATCH & 0xff, 0x40); + outb(LATCH >> 8, 0x40); + count = LATCH - 1; + } + spin_unlock(&i8253_lock); /* @@ -413,7 +422,7 @@ if (!user_mode(regs)) x86_do_profile(regs->eip); #else - if (!smp_found_config) + if (!using_apic_timer) smp_local_timer_interrupt(regs); #endif diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.4.9/linux/arch/i386/kernel/traps.c Mon Aug 27 12:41:39 2001 +++ linux/arch/i386/kernel/traps.c Tue Sep 18 13:39:51 2001 @@ -64,8 +64,6 @@ */ struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, }; -extern void bust_spinlocks(void); - asmlinkage void divide_error(void); asmlinkage void debug(void); asmlinkage void nmi(void); @@ -188,7 +186,7 @@ show_trace(esp); } -static void show_registers(struct pt_regs *regs) +void show_registers(struct pt_regs *regs) { int i; int in_kernel = 1; @@ -245,9 +243,10 @@ { console_verbose(); spin_lock_irq(&die_lock); + bust_spinlocks(1); printk("%s: %04lx\n", str, err & 0xffff); show_registers(regs); - + bust_spinlocks(0); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } @@ -419,83 +418,14 @@ printk("Do you have a strange power saving mode enabled?\n"); } -#if CONFIG_X86_IO_APIC - -int nmi_watchdog = 0; - -static int __init setup_nmi_watchdog(char *str) -{ - get_option(&str, &nmi_watchdog); - return 1; -} - -__setup("nmi_watchdog=", setup_nmi_watchdog); - -static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED; - -inline void nmi_watchdog_tick(struct pt_regs * regs) -{ - /* - * the best way to detect wether a CPU has a 'hard lockup' problem - * is to check it's local APIC timer IRQ counts. If they are not - * changing then that CPU has some problem. - * - * as these watchdog NMI IRQs are broadcasted to every CPU, here - * we only have to check the current processor. - * - * since NMIs dont listen to _any_ locks, we have to be extremely - * careful not to rely on unsafe variables. The printk might lock - * up though, so we have to break up console_lock first ... - * [when there will be more tty-related locks, break them up - * here too!] - */ - - static unsigned int last_irq_sums [NR_CPUS], - alert_counter [NR_CPUS]; - - /* - * Since current-> is always on the stack, and we always switch - * the stack NMI-atomically, it's safe to use smp_processor_id(). - */ - int sum, cpu = smp_processor_id(); - - sum = apic_timer_irqs[cpu]; - - if (last_irq_sums[cpu] == sum) { - /* - * Ayiee, looks like this CPU is stuck ... - * wait a few IRQs (5 seconds) before doing the oops ... - */ - alert_counter[cpu]++; - if (alert_counter[cpu] == 5*HZ) { - spin_lock(&nmi_print_lock); - /* - * We are in trouble anyway, lets at least try - * to get a message out. - */ - bust_spinlocks(); - printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu); - show_registers(regs); - printk("console shuts up ...\n"); - console_silent(); - spin_unlock(&nmi_print_lock); - do_exit(SIGSEGV); - } - } else { - last_irq_sums[cpu] = sum; - alert_counter[cpu] = 0; - } -} -#endif - asmlinkage void do_nmi(struct pt_regs * regs, long error_code) { unsigned char reason = inb(0x61); - ++nmi_count(smp_processor_id()); + if (!(reason & 0xc0)) { -#if CONFIG_X86_IO_APIC +#if CONFIG_X86_LOCAL_APIC /* * Ok, so this is none of the documented NMI sources, * so it must be the NMI watchdog. @@ -503,11 +433,9 @@ if (nmi_watchdog) { nmi_watchdog_tick(regs); return; - } else - unknown_nmi_error(reason, regs); -#else - unknown_nmi_error(reason, regs); + } #endif + unknown_nmi_error(reason, regs); return; } if (reason & 0x80) diff -u --recursive --new-file v2.4.9/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile --- v2.4.9/linux/arch/i386/lib/Makefile Tue Jul 3 17:08:18 2001 +++ linux/arch/i386/lib/Makefile Mon Sep 10 07:31:30 2001 @@ -13,5 +13,6 @@ obj-$(CONFIG_X86_USE_3DNOW) += mmx.o obj-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o +obj-$(CONFIG_DEBUG_IOVIRT) += iodebug.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/i386/lib/usercopy.c linux/arch/i386/lib/usercopy.c --- v2.4.9/linux/arch/i386/lib/usercopy.c Fri Apr 13 20:26:07 2001 +++ linux/arch/i386/lib/usercopy.c Tue Sep 18 14:10:43 2001 @@ -44,6 +44,7 @@ unsigned long __generic_copy_to_user(void *to, const void *from, unsigned long n) { + prefetch(from); if (access_ok(VERIFY_WRITE, to, n)) __copy_user(to,from,n); return n; @@ -52,6 +53,7 @@ unsigned long __generic_copy_from_user(void *to, const void *from, unsigned long n) { + prefetchw(to); if (access_ok(VERIFY_READ, from, n)) __copy_user_zeroing(to,from,n); else diff -u --recursive --new-file v2.4.9/linux/arch/i386/mm/extable.c linux/arch/i386/mm/extable.c --- v2.4.9/linux/arch/i386/mm/extable.c Fri Mar 2 11:12:07 2001 +++ linux/arch/i386/mm/extable.c Mon Sep 17 13:16:30 2001 @@ -37,13 +37,13 @@ search_exception_table(unsigned long addr) { unsigned long ret = 0; - unsigned long flags; #ifndef CONFIG_MODULES /* There is only the kernel to search. */ ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); return ret; #else + unsigned long flags; /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; 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 Mon Sep 17 22:52:35 2001 @@ -17,6 +17,7 @@ #include #include #include +#include /* For unblank_screen() */ #include #include @@ -25,6 +26,8 @@ extern void die(const char *,struct pt_regs *,long); +extern int console_loglevel; + /* * Ugly, ugly, but the goto's result in better assembly.. */ @@ -51,8 +54,14 @@ start &= PAGE_MASK; for (;;) { - if (handle_mm_fault(current->mm, vma, start, 1) <= 0) - goto bad_area; + survive: + { + int fault = handle_mm_fault(current->mm, vma, start, 1); + if (!fault) + goto bad_area; + if (fault < 0) + goto out_of_memory; + } if (!size) break; size--; @@ -75,19 +84,52 @@ bad_area: return 0; + +out_of_memory: + if (current->pid == 1) { + current->policy |= SCHED_YIELD; + schedule(); + goto survive; + } + goto bad_area; } -extern spinlock_t console_lock, timerlist_lock; +extern spinlock_t timerlist_lock; /* * Unlock any spinlocks which will prevent us from getting the * message out (timerlist_lock is acquired through the * console unblank code) */ -void bust_spinlocks(void) +void bust_spinlocks(int yes) { - spin_lock_init(&console_lock); spin_lock_init(&timerlist_lock); + if (yes) { + oops_in_progress = 1; +#ifdef CONFIG_SMP + global_irq_lock = 0; /* Many serial drivers do __global_cli() */ +#endif + } else { + int loglevel_save = console_loglevel; +#ifdef CONFIG_VT + unblank_screen(); +#endif + oops_in_progress = 0; + /* + * OK, the message is on the console. Now we call printk() + * without oops_in_progress set so that printk will give klogd + * a poke. Hold onto your hats... + */ + console_loglevel = 15; /* NMI oopser may have shut the console up */ + printk(" "); + console_loglevel = loglevel_save; + } +} + +void do_BUG(const char *file, int line) +{ + bust_spinlocks(1); + printk("kernel BUG at %s:%d!\n", file, line); } asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); @@ -196,6 +238,7 @@ goto bad_area; } + survive: /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo @@ -271,7 +314,7 @@ * terminate things with extreme prejudice. */ - bust_spinlocks(); + bust_spinlocks(1); if (address < PAGE_SIZE) printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); @@ -290,6 +333,7 @@ printk(KERN_ALERT "*pte = %08lx\n", page); } die("Oops", regs, error_code); + bust_spinlocks(0); do_exit(SIGKILL); /* @@ -298,6 +342,12 @@ */ out_of_memory: up_read(&mm->mmap_sem); + if (tsk->pid == 1) { + tsk->policy |= SCHED_YIELD; + schedule(); + down_read(&mm->mmap_sem); + goto survive; + } printk("VM: killing process %s\n", tsk->comm); if (error_code & 4) do_exit(SIGKILL); @@ -313,7 +363,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/ia64/kernel/init_task.c linux/arch/ia64/kernel/init_task.c --- v2.4.9/linux/arch/ia64/kernel/init_task.c Sun Feb 6 18:42:40 2000 +++ linux/arch/ia64/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -13,7 +13,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/ia64/kernel/ptrace.c linux/arch/ia64/kernel/ptrace.c --- v2.4.9/linux/arch/ia64/kernel/ptrace.c Sun Aug 12 13:27:58 2001 +++ linux/arch/ia64/kernel/ptrace.c Tue Sep 18 17:03:51 2001 @@ -789,6 +789,21 @@ return 0; } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the single step/take-branch tra bits are not set: */ + ia64_psr(pt)->ss = 0; + ia64_psr(pt)->tb = 0; + + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; +} + asmlinkage long sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, long arg4, long arg5, long arg6, long arg7, long stack) @@ -965,27 +980,7 @@ goto out_tsk; case PTRACE_DETACH: /* detach a process that was attached. */ - ret = -EIO; - if (data > _NSIG) - goto out_tsk; - - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - - /* make sure the single step/take-branch tra bits are not set: */ - ia64_psr(pt)->ss = 0; - ia64_psr(pt)->tb = 0; - - /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ - child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; - - wake_up_process(child); - ret = 0; + ret = ptrace_detach(child, data); goto out_tsk; default: diff -u --recursive --new-file v2.4.9/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c --- v2.4.9/linux/arch/m68k/amiga/config.c Tue Jul 3 17:08:18 2001 +++ linux/arch/m68k/amiga/config.c Thu Sep 13 15:21:32 2001 @@ -44,22 +44,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/m68k/kernel/process.c linux/arch/m68k/kernel/process.c --- v2.4.9/linux/arch/m68k/kernel/process.c Fri Feb 9 11:29:44 2001 +++ linux/arch/m68k/kernel/process.c Mon Sep 17 15:29:09 2001 @@ -38,7 +38,6 @@ * alignment requirements and potentially different initial * setup. */ -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.4.9/linux/arch/m68k/kernel/ptrace.c Wed Jul 25 17:10:18 2001 +++ linux/arch/m68k/kernel/ptrace.c Tue Sep 18 17:03:51 2001 @@ -87,6 +87,19 @@ return 0; } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + unsigned long tmp; + /* make sure the single step bit is not set. */ + tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); + put_reg(child, PT_SR, tmp); +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -279,26 +292,9 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - long tmp; - - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - /* make sure the single step bit is not set. */ - tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); - put_reg(child, PT_SR, tmp); - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); break; - } case PTRACE_GETREGS: { /* Get all gp regs from the child. */ int i; diff -u --recursive --new-file v2.4.9/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.4.9/linux/arch/mips/Makefile Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/Makefile Sun Sep 9 10:43:02 2001 @@ -36,8 +36,9 @@ # crossformat linking we rely on the elf2ecoff tool for format conversion. # GCCFLAGS := -G 0 -mno-abicalls -fno-pic -LINKFLAGS += -static -G 0 +LINKFLAGS += -static MODFLAGS += -mlong-calls +LD := $(LD) -G 0 ifdef CONFIG_REMOTE_DEBUG CFLAGS := $(CFLAGS) -g @@ -55,12 +56,18 @@ ifdef CONFIG_CPU_R4300 GCCFLAGS += -mcpu=r4300 -mips2 -Wa,--trap endif +ifdef CONFIG_CPU_VR41XX +GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap +endif ifdef CONFIG_CPU_R4X00 GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_MIPS32 GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap endif +ifdef CONFIG_CPU_MIPS64 +GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap +endif ifdef CONFIG_CPU_R5000 GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap endif @@ -68,7 +75,8 @@ GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_NEVADA -GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap -mmad +# Cannot use -mmad with currently recommended tools +GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_RM7000 GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap @@ -77,11 +85,6 @@ GCCFLAGS += -mcpu=sb1 -mips2 -Wa,--trap endif -ifdef CONFIG_MIPS_FPU_EMULATOR -CORE_FILES +=arch/mips/math-emu/fpu_emulator.o -SUBDIRS +=arch/mips/math-emu -endif - GCCFLAGS += -pipe CFLAGS := -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS) @@ -89,6 +92,12 @@ ASFLAGS += $(GCCFLAGS) # +# We unconditionally build the math emulator +# +CORE_FILES +=arch/mips/math-emu/fpu_emulator.o +SUBDIRS +=arch/mips/math-emu + +# # Board-dependent options and extra files # ifdef CONFIG_ALGOR_P4032 @@ -229,11 +238,27 @@ # ITE 8172 eval board with QED 5231 CPU # ifdef CONFIG_MIPS_ITE8172 -LIBS += arch/mips/ite-boards/qed-4n-s01b/ite.o \ - arch/mips/ite-boards/generic/it8172.o -SUBDIRS += arch/mips/ite-boards/generic \ - arch/mips/ite-boards/qed-4n-s01b -LOADADDR += 0x80100000 +LIBS += arch/mips/ite-boards/qed-4n-s01b/ite.o arch/mips/ite-boards/generic/it8172.o +SUBDIRS += arch/mips/ite-boards/generic arch/mips/ite-boards/qed-4n-s01b +LOADADDR += 0x80100000 +endif + +# +# Globespan IVR eval board with QED 5231 CPU +# +ifdef CONFIG_MIPS_IVR +LIBS += arch/mips/ite-boards/ivr/ivr.o arch/mips/ite-boards/generic/it8172.o +SUBDIRS += arch/mips/ite-boards/generic arch/mips/ite-boards/ivr +LOADADDR += 0x80100000 +endif + +# +# Au1000 eval board +# +ifdef CONFIG_MIPS_PB1000 +LIBS += arch/mips/au1000/pb1000/pb1000.o arch/mips/au1000/common/au1000.o +SUBDIRS += arch/mips/au1000/pb1000 arch/mips/au1000/common +LOADADDR += 0x80100000 endif # @@ -273,14 +298,6 @@ vmlinux.ecoff: vmlinux @$(MAKEBOOT) $@ - -zImage: vmlinux - @$(MAKEBOOT) zImage - -compressed: zImage - -zdisk: vmlinux - @$(MAKEBOOT) zdisk archclean: @$(MAKEBOOT) clean diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/Makefile linux/arch/mips/au1000/common/Makefile --- v2.4.9/linux/arch/mips/au1000/common/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/Makefile Sun Sep 9 10:43:01 2001 @@ -0,0 +1,31 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Alchemy Au1000 CPU, generic files. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: au1000.o + +O_TARGET := au1000.o + +obj-y := prom.o dbg_io.o int-handler.o irq.o puts.o time.o reset.o + +obj-$(CONFIG_AU1000_UART) += serial.o +obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o +obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o + +ramdisk.o: + mkramobj ramdisk ramdisk.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/dbg_io.c linux/arch/mips/au1000/common/dbg_io.c --- v2.4.9/linux/arch/mips/au1000/common/dbg_io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/dbg_io.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,118 @@ + +#include +#include +#include + +#ifdef CONFIG_REMOTE_DEBUG + +/* + * FIXME the user should be able to select the + * uart to be used for debugging. + */ +#define DEBUG_BASE UART2_ADDR +/**/ + +/* we need uint32 uint8 */ +/* #include "types.h" */ +typedef unsigned char uint8; +typedef unsigned int uint32; + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + + +#define UART_RX 0 /* Receive buffer */ +#define UART_TX 4 /* Transmit buffer */ +#define UART_IER 8 /* Interrupt Enable Register */ +#define UART_IIR 0xC /* Interrupt ID Register */ +#define UART_FCR 0x10 /* FIFO Control Register */ +#define UART_LCR 0x14 /* Line Control Register */ +#define UART_MCR 0x18 /* Modem Control Register */ +#define UART_LSR 0x1C /* Line Status Register */ +#define UART_MSR 0x20 /* Modem Status Register */ +#define UART_CLK 0x28 /* Baud Rat4e Clock Divider */ +#define UART_MOD_CNTRL 0x100 /* Module Control */ + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (inl(DEBUG_BASE + y) & 0xff) +#define UART16550_WRITE(y,z) (outl(z&0xff, DEBUG_BASE + y)) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + + if (UART16550_READ(UART_MOD_CNTRL) != 0x3) { + UART16550_WRITE(UART_MOD_CNTRL, 3); + } + cal_r4koff(); + + /* disable interrupts */ + UART16550_WRITE(UART_IER, 0); + + /* set up baud rate */ + { + uint32 divisor; + + /* set divisor */ + divisor = get_au1000_uart_baud() / baud; + UART16550_WRITE(UART_CLK, divisor & 0xffff); + } + + /* set data format */ + UART16550_WRITE(UART_LCR, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, + UART16550_STOP_1BIT); + } + + while((UART16550_READ(UART_LSR) & 0x1) == 0); + return UART16550_READ(UART_RX); +} + + +int putDebugChar(uint8 byte) +{ + int i; + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, + UART16550_STOP_1BIT); + } + + while ((UART16550_READ(UART_LSR)&0x40) == 0); + UART16550_WRITE(UART_TX, byte); + //for (i=0;i<0xfff;i++); + + return 1; +} + +#endif diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/int-handler.S linux/arch/mips/au1000/common/int-handler.S --- v2.4.9/linux/arch/mips/au1000/common/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/int-handler.S Sun Sep 9 10:43:01 2001 @@ -0,0 +1,71 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: ppopov@mvista.com + * + * Interrupt dispatcher for Au1000 boards. + * + * 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 + + .text + .set macro + .set noat + .align 5 + +NESTED(au1000_IRQ, PT_SIZE, sp) + SAVE_ALL + CLI # Important: mark KERNEL mode ! + + mfc0 t0,CP0_CAUSE # get pending interrupts + mfc0 t1,CP0_STATUS # get enabled interrupts + and t0,t1 # isolate allowed ones + + andi t0,0xff00 # isolate pending bits + beqz t0, 3f # spurious interrupt + + andi a0, t0, CAUSEF_IP7 + beq a0, zero, 1f + move a0, sp + jal mips_timer_interrupt + j ret_from_irq + +1: + andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0 + beq a0, zero, 2f + move a0,sp + jal intc0_req0_irqdispatch + j ret_from_irq +2: + andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1 + beq a0, zero, 3f + move a0,sp + jal intc0_req1_irqdispatch + j ret_from_irq +3: + andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0 + beq a0, zero, 4f + move a0,sp + jal intc1_req0_irqdispatch + j ret_from_irq +4: + andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1 + beq a0, zero, 5f + move a0, sp + jal intc1_req1_irqdispatch + j ret_from_irq + +5: + move a0, sp + jal mips_spurious_interrupt +done: + j ret_from_irq +END(au1000_IRQ) diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/irq.c linux/arch/mips/au1000/common/irq.c --- v2.4.9/linux/arch/mips/au1000/common/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/irq.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,471 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1000 interrupt routines. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + +#undef DEBUG_IRQ +#ifdef DEBUG_IRQ +/* note: prints function name for you */ +#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#define EXT_INTC0_REQ0 2 /* IP 2 */ +#define EXT_INTC0_REQ1 3 /* IP 3 */ +#define EXT_INTC1_REQ0 4 /* IP 4 */ +#define EXT_INTC1_REQ1 5 /* IP 5 */ +#define MIPS_TIMER_IP 7 /* IP 7 */ + +#ifdef CONFIG_REMOTE_DEBUG +extern void breakpoint(void); +#endif + +extern asmlinkage void au1000_IRQ(void); + +extern void set_debug_traps(void); +extern irq_cpustat_t irq_stat []; +extern irq_desc_t irq_desc[NR_IRQS]; + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; + +static void setup_local_irq(unsigned int irq, int type, int int_req); +static unsigned int startup_irq(unsigned int irq); +static void end_irq(unsigned int irq_nr); +static inline void mask_and_ack_level_irq(unsigned int irq_nr); +static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr); +static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr); +static inline void local_enable_irq(unsigned int irq_nr); +static inline void local_disable_irq(unsigned int irq_nr); + +unsigned long spurious_interrupts; +extern unsigned int do_IRQ(int irq, struct pt_regs *regs); +extern void __init init_generic_irq(void); + +static inline void sync(void) +{ + __asm volatile ("sync"); +} + + +/* Function for careful CP0 interrupt mask access */ +static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) +{ + unsigned long status = read_32bit_cp0_register(CP0_STATUS); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_32bit_cp0_register(CP0_STATUS, status); +} + + +static inline void mask_cpu_irq_input(unsigned int irq_nr) +{ + modify_cp0_intmask(irq_nr, 0); +} + + +static inline void unmask_cpu_irq_input(unsigned int irq_nr) +{ + modify_cp0_intmask(0, irq_nr); +} + + +static void disable_cpu_irq_input(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + mask_cpu_irq_input(irq_nr); + restore_flags(flags); +} + + +static void enable_cpu_irq_input(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + unmask_cpu_irq_input(irq_nr); + restore_flags(flags); +} + + +static void setup_local_irq(unsigned int irq_nr, int type, int int_req) +{ + /* Config2[n], Config1[n], Config0[n] */ + if (irq_nr > AU1000_LAST_INTC0_INT) { + switch (type) { + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + outl(1< AU1000_LAST_INTC0_INT) { + outl(1< AU1000_LAST_INTC0_INT) { + outl(1< AU1000_LAST_INTC0_INT) { + outl(1< AU1000_LAST_INTC0_INT) { + outl(1<>= 1; + } +} + + +void intc0_req1_irqdispatch(struct pt_regs *regs) +{ + int irq = 0, i; + unsigned long int_request; + + int_request = inl(INTC0_REQ1_INT); + + if (!int_request) return; + + for (i=0; i<32; i++) { + if ((int_request & 0x1)) { + do_IRQ(irq, regs); + } + irq++; + int_request >>= 1; + } +} + + +void intc1_req0_irqdispatch(struct pt_regs *regs) +{ + int irq = 0, i; + unsigned long int_request; + + int_request = inl(INTC1_REQ0_INT); + + if (!int_request) return; + + for (i=0; i<32; i++) { + if ((int_request & 0x1)) { + do_IRQ(irq, regs); + } + irq++; + int_request >>= 1; + } +} + + +void intc1_req1_irqdispatch(struct pt_regs *regs) +{ + int irq = 0, i; + unsigned long int_request; + + int_request = inl(INTC1_REQ1_INT); + + if (!int_request) return; + + for (i=0; i<32; i++) { + if ((int_request & 0x1)) { + do_IRQ(irq, regs); + } + irq++; + int_request >>= 1; + } +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/prom.c linux/arch/mips/au1000/common/prom.c --- v2.4.9/linux/arch/mips/au1000/common/prom.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/prom.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,120 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PROM library initialisation code, assuming a version of + * pmon is the boot code. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/xx files. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include + +/* #define DEBUG_CMDLINE */ + +char arcs_cmdline[COMMAND_LINE_SIZE]; +int prom_argc; +char **prom_argv, **prom_envp; + +typedef struct { + char *name; +/* char *val; */ +} t_env_var; + + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +void __init prom_init_cmdline(void) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + *cp = '\0'; + +} + + +char *prom_getenv(char *envname) +{ + /* + * Return a pointer to the given environment variable. + * Environment variables are stored in the form of "memsize=64". + */ + + t_env_var *env = (t_env_var *)prom_envp; + int i; + + i = strlen(envname); + + while(env->name) { + if(strncmp(envname, env->name, i) == 0) { + return(env->name + strlen(envname) + 1); + } + env++; + } + return(NULL); +} + +static inline unsigned char str2hexnum(unsigned char c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + return 0; /* foo */ +} + +int __init page_is_ram(unsigned long pagenr) +{ + return 1; +} + +void prom_free_prom_memory (void) +{ +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/puts.c linux/arch/mips/au1000/common/puts.c --- v2.4.9/linux/arch/mips/au1000/common/puts.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/puts.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,144 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Low level uart routines to directly access a 16550 uart. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@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. + */ + +#include + +#define SERIAL_BASE 0xB1100000 /* au1000, uart 0 */ +#define SER_CMD 0x7 +#define SER_DATA 0x1 +#define TX_BUSY 0x20 + +#define TIMEOUT 0xffffff +#define SLOW_DOWN + +static const char digits[16] = "0123456789abcdef"; +static volatile unsigned long * const com1 = (unsigned char *)SERIAL_BASE; + + +#ifdef SLOW_DOWN +static inline void slow_down() +{ + int k; + for (k=0; k<10000; k++); +} +#else +#define slow_down() +#endif + +void +putch(const unsigned char c) +{ + unsigned char ch; + int i = 0; + + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = c; +} + +void +puts(unsigned char *cp) +{ + unsigned char ch; + int i = 0; + + while (*cp) { + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = *cp++; + } + putch('\r'); + putch('\n'); +} + +void +fputs(unsigned char *cp) +{ + unsigned char ch; + int i = 0; + + while (*cp) { + + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = *cp++; + } +} + + +void +put64(uint64_t ul) +{ + int cnt; + unsigned ch; + + cnt = 16; /* 16 nibbles in a 64 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char)(ul >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} + +void +put32(unsigned u) +{ + int cnt; + unsigned ch; + + cnt = 8; /* 8 nibbles in a 32 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char)(u >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/reset.c linux/arch/mips/au1000/common/reset.c --- v2.4.9/linux/arch/mips/au1000/common/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/reset.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,60 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Au1000 reset routines. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@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. + */ + +#include +#include +#include +#include +#include +#include +#include + +void au1000_restart(char *command) +{ + set_cp0_status(ST0_BEV | ST0_ERL); + set_cp0_config(CONF_CM_UNCACHED); + flush_cache_all(); + write_32bit_cp0_register(CP0_WIRED, 0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void au1000_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void au1000_power_off(void) +{ + au1000_halt(); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/serial.c linux/arch/mips/au1000/common/serial.c --- v2.4.9/linux/arch/mips/au1000/common/serial.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/serial.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,3100 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Au1000 serial port driver. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * Derived almost entirely from drivers/char/serial.c: + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, + * 1998, 1999 Theodore Ts'o + * + * 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. + */ + +static char *serial_version = "1.01"; +static char *serial_revdate = "2001-02-08"; + + +#include +#include + +#undef SERIAL_PARANOIA_CHECK +#define CONFIG_SERIAL_NOPAUSE_IO +#define SERIAL_DO_RESTART + + +/* Set of debugging defines */ + +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT +#undef SERIAL_DEBUG_PCI +#undef SERIAL_DEBUG_AUTOCONF + +#ifdef MODULE +#undef CONFIG_AU1000_SERIAL_CONSOLE +#endif + +#define CONFIG_SERIAL_RSA + +#define RS_STROBE_TIME (10*HZ) +#define RS_ISR_PASS_LIMIT 256 + +/* + * End of serial driver configuration section. + */ + +#ifdef MODVERSIONS +#include +#endif +#include + +#include +#ifdef LOCAL_HEADERS +#include "serial_local.h" +#else +#include +#include +#include +#include +#define LOCAL_VERSTRING "" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_AU1000_SERIAL_CONSOLE +#include +#endif +#ifdef CONFIG_MAGIC_SYSRQ +#include +#endif + +#include +#include +#include +#include + +#ifdef CONFIG_MAC_SERIAL +#define SERIAL_DEV_OFFSET 2 +#else +#define SERIAL_DEV_OFFSET 0 +#endif + +#ifdef SERIAL_INLINE +#define _INLINE_ inline +#else +#define _INLINE_ +#endif + +static char *serial_name = "Serial driver"; + +static DECLARE_TASK_QUEUE(tq_serial); + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +static struct timer_list serial_timer; + +extern unsigned long get_au1000_uart_baud(void); + +/* serial subtype definitions */ +#ifndef SERIAL_TYPE_NORMAL +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 +#endif + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* + * IRQ_timeout - How long the timeout should be for each IRQ + * should be after the IRQ has been active. + */ + +static struct async_struct *IRQ_ports[NR_IRQS]; +static int IRQ_timeout[NR_IRQS]; +#ifdef CONFIG_AU1000_SERIAL_CONSOLE +static struct console sercons; +static int lsr_break_flag; +#endif +#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +static unsigned long break_pressed; /* break, really ... */ +#endif + +static void autoconfig(struct serial_state * state); +static void change_speed(struct async_struct *info, struct termios *old); +static void rs_wait_until_sent(struct tty_struct *tty, int timeout); + +/* + * Here we define the default xmit fifo size used for each type of + * UART + */ +static struct serial_uart_config uart_config[] = { + { "unknown", 1, 0 }, + { "8250", 1, 0 }, + { "16450", 1, 0 }, + { "16550", 1, 0 }, + { 0, 0} +}; + + +static struct serial_state rs_table[RS_TABLE_SIZE] = { + SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + +#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) + +#ifndef PREPARE_FUNC +#define PREPARE_FUNC(dev) (dev->prepare) +#define ACTIVATE_FUNC(dev) (dev->activate) +#define DEACTIVATE_FUNC(dev) (dev->deactivate) +#endif + +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) + +static struct tty_struct *serial_table[NR_PORTS]; +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; + + +#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) +#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ + kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s) +#else +#define DBG_CNT(s) +#endif + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char *tmp_buf; +#ifdef DECLARE_MUTEX +static DECLARE_MUTEX(tmp_buf_sem); +#else +static struct semaphore tmp_buf_sem = MUTEX; +#endif + + +static inline int serial_paranoia_check(struct async_struct *info, + kdev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%s) in %s\n"; + static const char *badinfo = + "Warning: null async_struct for (%s) in %s\n"; + + if (!info) { + printk(badinfo, kdevname(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, kdevname(device), routine); + return 1; + } +#endif + return 0; +} + + +static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) +{ + return (inl(info->port+offset) & 0xff); +} + +static _INLINE_ void serial_out(struct async_struct *info, int offset, int value) +{ + outl(value & 0xff, info->port+offset); +} + + +/* + * We used to support using pause I/O for certain machines. We + * haven't supported this for a while, but just in case it's badly + * needed for certain old 386 machines, I've left these #define's + * in.... + */ +#define serial_inp(info, offset) serial_in(info, offset) +#define serial_outp(info, offset, value) serial_out(info, offset, value) + + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + + save_flags(flags); cli(); + if (info->IER & UART_IER_THRI) { + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + restore_flags(flags); +} + +static void rs_start(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_start")) + return; + + save_flags(flags); cli(); + if (info->xmit.head != info->xmit.tail + && info->xmit.buf + && !(info->IER & UART_IER_THRI)) { + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + restore_flags(flags); +} + +/* + * ---------------------------------------------------------------------- + * + * 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 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static _INLINE_ void rs_sched_event(struct async_struct *info, + int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_serial); + mark_bh(SERIAL_BH); +} + +static _INLINE_ void receive_chars(struct async_struct *info, + int *status, struct pt_regs * regs) +{ + struct tty_struct *tty = info->tty; + unsigned char ch; + int ignored = 0; + struct async_icount *icount; + + icount = &info->state->icount; + do { + ch = serial_inp(info, UART_RX); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + *tty->flip.char_buf_ptr = ch; + icount->rx++; + +#ifdef SERIAL_DEBUG_INTR + printk("DR%02x:%02x...", ch, *status); +#endif + *tty->flip.flag_buf_ptr = 0; + if (*status & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE)) { + /* + * For statistics only + */ + if (*status & UART_LSR_BI) { + *status &= ~(UART_LSR_FE | UART_LSR_PE); + icount->brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ +#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) + if (info->line == sercons.index) { + if (!break_pressed) { + break_pressed = jiffies; + goto ignore_char; + } + break_pressed = 0; + } +#endif + if (info->flags & ASYNC_SAK) + do_SAK(tty); + } else if (*status & UART_LSR_PE) + icount->parity++; + else if (*status & UART_LSR_FE) + icount->frame++; + if (*status & UART_LSR_OE) + icount->overrun++; + + /* + * Now check to see if character should be + * ignored, and mask off conditions which + * should be ignored. + */ + if (*status & info->ignore_status_mask) { + if (++ignored > 100) + break; + goto ignore_char; + } + *status &= info->read_status_mask; + +#ifdef CONFIG_AU1000_SERIAL_CONSOLE + if (info->line == sercons.index) { + /* Recover the break flag from console xmit */ + *status |= lsr_break_flag; + lsr_break_flag = 0; + } +#endif + if (*status & (UART_LSR_BI)) { +#ifdef SERIAL_DEBUG_INTR + printk("handling break...."); +#endif + *tty->flip.flag_buf_ptr = TTY_BREAK; + } else if (*status & UART_LSR_PE) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (*status & UART_LSR_FE) + *tty->flip.flag_buf_ptr = TTY_FRAME; + if (*status & UART_LSR_OE) { + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + } + } +#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) + 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 + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + ignore_char: + *status = serial_inp(info, UART_LSR); + } while (*status & UART_LSR_DR); + tty_flip_buffer_push(tty); +} + +static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) +{ + int count; + + if (info->x_char) { + serial_outp(info, UART_TX, info->x_char); + info->state->icount.tx++; + info->x_char = 0; + if (intr_done) + *intr_done = 0; + return; + } + if (info->xmit.head == info->xmit.tail + || info->tty->stopped + || info->tty->hw_stopped) { + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + return; + } + + count = info->xmit_fifo_size; + do { + serial_out(info, UART_TX, info->xmit.buf[info->xmit.tail]); + info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); + info->state->icount.tx++; + if (info->xmit.head == info->xmit.tail) + break; + } while (--count > 0); + + if (CIRC_CNT(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE) < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + +#ifdef SERIAL_DEBUG_INTR + printk("THRE..."); +#endif + if (intr_done) + *intr_done = 0; + + if (info->xmit.head == info->xmit.tail) { + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } +} + +static _INLINE_ void check_modem_status(struct async_struct *info) +{ + int status; + struct async_icount *icount; + + status = serial_in(info, UART_MSR); + + if (status & UART_MSR_ANY_DELTA) { + icount = &info->state->icount; + /* update input line counters */ + if (status & UART_MSR_TERI) + icount->rng++; + if (status & UART_MSR_DDSR) + icount->dsr++; + if (status & UART_MSR_DDCD) { + icount->dcd++; +#ifdef CONFIG_HARD_PPS + if ((info->flags & ASYNC_HARDPPS_CD) && + (status & UART_MSR_DCD)) + hardpps(); +#endif + } + if (status & UART_MSR_DCTS) + icount->cts++; + wake_up_interruptible(&info->delta_msr_wait); + } + + if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { +#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) + printk("ttys%d CD now %s...", info->line, + (status & UART_MSR_DCD) ? "on" : "off"); +#endif + if (status & UART_MSR_DCD) + wake_up_interruptible(&info->open_wait); + else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_CALLOUT_NOHUP))) { +#ifdef SERIAL_DEBUG_OPEN + printk("doing serial hangup..."); +#endif + if (info->tty) + tty_hangup(info->tty); + } + } + if (info->flags & ASYNC_CTS_FLOW) { + if (info->tty->hw_stopped) { + if (status & UART_MSR_CTS) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx start..."); +#endif + info->tty->hw_stopped = 0; + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + return; + } + } else { + if (!(status & UART_MSR_CTS)) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx stop..."); +#endif + info->tty->hw_stopped = 1; + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + } + } +} + + + +/* + * This is the serial driver's interrupt routine for a single port + */ +static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) +{ + int status; + int pass_counter = 0; + struct async_struct * info; + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt_single(%d)...", irq); +#endif + + info = IRQ_ports[irq]; + if (!info || !info->tty) + return; + + do { + status = serial_inp(info, UART_LSR); +#ifdef SERIAL_DEBUG_INTR + printk("status = %x...", status); +#endif + if (status & UART_LSR_DR) + receive_chars(info, &status, regs); + check_modem_status(info); + if (status & UART_LSR_THRE) + transmit_chars(info, 0); + if (pass_counter++ > RS_ISR_PASS_LIMIT) { +#if 0 + printk("rs_single loop break.\n"); +#endif + break; + } + } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); + info->last_active = jiffies; +#ifdef SERIAL_DEBUG_INTR + printk("end.\n"); +#endif +} + + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_serial); +} + +static void do_softint(void *private_) +{ + struct async_struct *info = (struct async_struct *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); +#ifdef SERIAL_HAVE_POLL_WAIT + wake_up_interruptible(&tty->poll_wait); +#endif + } +} + +/* + * This subroutine is called when the RS_TIMER goes off. It is used + * by the serial driver to handle ports that do not have an interrupt + * (irq=0). This doesn't work very well for 16450's, but gives barely + * passable results for a 16550A. (Although at the expense of much + * CPU overhead). + */ +static void rs_timer(unsigned long dummy) +{ + static unsigned long last_strobe; + struct async_struct *info; + unsigned int i; + unsigned long flags; + + if ((jiffies - last_strobe) >= RS_STROBE_TIME) { + for (i=0; i < NR_IRQS; i++) { + info = IRQ_ports[i]; + if (!info) + continue; + save_flags(flags); cli(); + rs_interrupt_single(i, NULL, NULL); + restore_flags(flags); + } + } + last_strobe = jiffies; + mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); + +#if 0 + if (IRQ_ports[0]) { + save_flags(flags); cli(); + rs_interrupt_single(0, NULL, NULL); + restore_flags(flags); + + mod_timer(&serial_timer, jiffies + IRQ_timeout[0]); + } +#endif +} + +/* + * --------------------------------------------------------------- + * Low level utility subroutines for the serial driver: routines to + * figure out the appropriate timeout for an interrupt chain, routines + * to initialize and startup a serial port, and routines to shutdown a + * serial port. Useful stuff like that. + * --------------------------------------------------------------- + */ + +/* + * This routine figures out the correct timeout for a particular IRQ. + * It uses the smallest timeout of all of the serial ports in a + * particular interrupt chain. Now only used for IRQ 0.... + */ +static void figure_IRQ_timeout(int irq) +{ + struct async_struct *info; + int timeout = 60*HZ; /* 60 seconds === a long time :-) */ + + info = IRQ_ports[irq]; + if (!info) { + IRQ_timeout[irq] = 60*HZ; + return; + } + while (info) { + if (info->timeout < timeout) + timeout = info->timeout; + info = info->next_port; + } + if (!irq) + timeout = timeout / 2; + IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1; +} + + +static int startup(struct async_struct * info) +{ + unsigned long flags; + int retval=0; + void (*handler)(int, void *, struct pt_regs *); + struct serial_state *state= info->state; + unsigned long page; + + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + save_flags(flags); cli(); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } + + if (!CONFIGURED_SERIAL_PORT(state) || !state->type) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + goto errout; + } + if (info->xmit.buf) + free_page(page); + else + info->xmit.buf = (unsigned char *) page; + + + if (inl(UART_MOD_CNTRL + state->port) != 0x3) { + outl(3, UART_MOD_CNTRL + state->port); + } +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttys%d (irq %d)...", info->line, state->irq); +#endif + + + /* + * Clear the FIFO buffers and disable them + * (they will be reenabled in change_speed()) + */ + if (uart_config[state->type].flags & UART_CLEAR_FIFO) { + serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + serial_outp(info, UART_FCR, 0); + } + + /* + * Clear the interrupt registers. + */ + (void) serial_inp(info, UART_LSR); + (void) serial_inp(info, UART_RX); + (void) serial_inp(info, UART_IIR); + (void) serial_inp(info, UART_MSR); + + /* + * At this point there's no way the LSR could still be 0xFF; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (!(info->flags & ASYNC_BUGGY_UART) && + (serial_inp(info, UART_LSR) == 0xff)) { + printk("LSR safety check engaged!\n"); + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + } else + retval = -ENODEV; + goto errout; + } + + /* + * Allocate the IRQ if necessary + */ +#if 0 + /* au1000, uart0 irq is 0 */ + if (state->irq && (!IRQ_ports[state->irq] || !IRQ_ports[state->irq]->next_port)) { +#endif + if ((!IRQ_ports[state->irq] || !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + retval = -EBUSY; + goto errout; + } else + handler = rs_interrupt_single; + + retval = request_irq(state->irq, handler, SA_SHIRQ, + "serial", &IRQ_ports[state->irq]); + if (retval) { + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, + &info->tty->flags); + retval = 0; + } + goto errout; + } + } + + /* + * Insert serial port into IRQ chain. + */ + info->prev_port = 0; + info->next_port = IRQ_ports[state->irq]; + if (info->next_port) + info->next_port->prev_port = info; + IRQ_ports[state->irq] = info; + figure_IRQ_timeout(state->irq); + + /* + * Now, initialize the UART + */ + serial_outp(info, UART_LCR, UART_LCR_WLEN8); + + info->MCR = 0; + if (info->tty->termios->c_cflag & CBAUD) + info->MCR = UART_MCR_DTR | UART_MCR_RTS; + { + if (state->irq != 0) + info->MCR |= UART_MCR_OUT2; + } + info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ + serial_outp(info, UART_MCR, info->MCR); + + /* + * Finally, enable interrupts + */ + info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; + serial_outp(info, UART_IER, info->IER); /* enable interrupts */ + + + /* + * And clear the interrupt registers again for luck. + */ + (void)serial_inp(info, UART_LSR); + (void)serial_inp(info, UART_RX); + (void)serial_inp(info, UART_IIR); + (void)serial_inp(info, UART_MSR); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit.head = info->xmit.tail = 0; + + /* + * Set up serial timers... + */ + mod_timer(&serial_timer, jiffies + 2*HZ/100); + + /* + * Set up the tty->alt_speed kludge + */ + if (info->tty) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + } + + /* + * and set the speed of the serial port + */ + change_speed(info, 0); + + info->flags |= ASYNC_INITIALIZED; + restore_flags(flags); + return 0; + +errout: + restore_flags(flags); + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct async_struct * info) +{ + unsigned long flags; + struct serial_state *state; + int retval; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + state = info->state; + +#ifdef SERIAL_DEBUG_OPEN + printk("Shutting down serial port %d (irq %d)....", info->line, + state->irq); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&info->delta_msr_wait); + + /* + * First unlink the serial port from the IRQ chain... + */ + if (info->next_port) + info->next_port->prev_port = info->prev_port; + if (info->prev_port) + info->prev_port->next_port = info->next_port; + else + IRQ_ports[state->irq] = info->next_port; + figure_IRQ_timeout(state->irq); + + /* + * Free the IRQ, if necessary + */ +// if (state->irq && (!IRQ_ports[state->irq] || + if ((!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + free_irq(state->irq, &IRQ_ports[state->irq]); + retval = request_irq(state->irq, rs_interrupt_single, + SA_SHIRQ, "serial", + &IRQ_ports[state->irq]); + + if (retval) + printk("serial shutdown: request_irq: error %d" + " Couldn't reacquire IRQ.\n", retval); + } else + free_irq(state->irq, &IRQ_ports[state->irq]); + } + + if (info->xmit.buf) { + unsigned long pg = (unsigned long) info->xmit.buf; + info->xmit.buf = 0; + free_page(pg); + } + + info->IER = 0; + serial_outp(info, UART_IER, 0x00); /* disable all intrs */ + info->MCR &= ~UART_MCR_OUT2; + info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ + + /* disable break condition */ + serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC); + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); + serial_outp(info, UART_MCR, info->MCR); + + /* disable FIFO's */ + serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + serial_outp(info, UART_FCR, 0); + + (void)serial_in(info, UART_RX); /* read data port to reset things */ + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + restore_flags(flags); +} + + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct async_struct *info, + struct termios *old_termios) +{ + int quot = 0, baud_base, baud; + unsigned cflag, cval, fcr = 0; + int bits; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!CONFIGURED_SERIAL_PORT(info)) + return; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: cval = 0x00; bits = 7; break; + case CS6: cval = 0x01; bits = 8; break; + case CS7: cval = 0x02; bits = 9; break; + case CS8: cval = 0x03; bits = 10; break; + /* Never happens, but GCC is too dumb to figure it out */ + default: cval = 0x00; bits = 7; break; + } + if (cflag & CSTOPB) { + cval |= 0x04; + bits++; + } + if (cflag & PARENB) { + cval |= UART_LCR_PARITY; + bits++; + } + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; +#ifdef CMSPAR + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; +#endif + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(info->tty); + if (!baud) { + baud = 9600; /* B0 transition handled in rs_set_termios */ + } + baud_base = info->state->baud_base; + //if (baud == 38400 && + if (((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { + quot = info->state->custom_divisor; + } + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) + quot = baud_base / baud; + } + /* If the quotient is zero refuse the change */ + if (!quot && old_termios) { + info->tty->termios->c_cflag &= ~CBAUD; + info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); + baud = tty_get_baud_rate(info->tty); + if (!baud) + baud = 9600; + if (baud == 38400 && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->state->custom_divisor; + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) + quot = baud_base / baud; + } + } + /* As a last resort, if the quotient is zero, default to 9600 bps */ + if (!quot) + quot = baud_base / 9600; + + info->quot = quot; + info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + /* Set up FIFO's */ + if (uart_config[info->state->type].flags & UART_USE_FIFO) { + if ((info->state->baud_base / quot) < 2400) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1; + else + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8; + } + + /* CTS flow control flag and modem status interrupts */ + info->IER &= ~UART_IER_MSI; + if (info->flags & ASYNC_HARDPPS_CD) + info->IER |= UART_IER_MSI; + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->IER |= UART_IER_MSI; + } else + info->flags &= ~ASYNC_CTS_FLOW; + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else { + info->flags |= ASYNC_CHECK_CD; + info->IER |= UART_IER_MSI; + } + serial_out(info, UART_IER, info->IER); + + /* + * Set up parity check flag + */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + + info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (I_INPCK(info->tty)) + info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + info->read_status_mask |= UART_LSR_BI; + + /* + * Characters to ignore + */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (I_IGNBRK(info->tty)) { + info->ignore_status_mask |= UART_LSR_BI; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= UART_LSR_OE; + } + /* + * !!! ignore all characters if CREAD is not set + */ + if ((cflag & CREAD) == 0) + info->ignore_status_mask |= UART_LSR_DR; + save_flags(flags); cli(); + + serial_outp(info, UART_CLK, quot & 0xffff); + serial_outp(info, UART_LCR, cval); + info->LCR = cval; /* Save LCR */ + restore_flags(flags); +} + +static void rs_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_put_char")) + return; + + if (!tty || !info->xmit.buf) + return; + + save_flags(flags); cli(); + if (CIRC_SPACE(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE) == 0) { + restore_flags(flags); + return; + } + + info->xmit.buf[info->xmit.head] = ch; + info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); + restore_flags(flags); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit.head == info->xmit.tail + || tty->stopped + || tty->hw_stopped + || !info->xmit.buf) + return; + + save_flags(flags); cli(); + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + restore_flags(flags); +} + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, ret = 0; + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty || !info->xmit.buf || !tmp_buf) + return 0; + + save_flags(flags); + if (from_user) { + down(&tmp_buf_sem); + while (1) { + int c1; + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + cli(); + c1 = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (c1 < c) + c = c1; + memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + cli(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) { + break; + } + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + buf += c; + count -= c; + ret += c; + } + restore_flags(flags); + } + if (info->xmit.head != info->xmit.tail + && !tty->stopped + && !tty->hw_stopped + && !(info->IER & UART_IER_THRI)) { + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + return ret; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_write_room")) + return 0; + return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) + return 0; + return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) + return; + save_flags(flags); cli(); + info->xmit.head = info->xmit.tail = 0; + restore_flags(flags); + wake_up_interruptible(&tty->write_wait); +#ifdef SERIAL_HAVE_POLL_WAIT + wake_up_interruptible(&tty->poll_wait); +#endif + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * 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 async_struct *info = (struct async_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_send_char")) + return; + + info->x_char = ch; + if (ch) { + /* Make sure transmit interrupts are on */ + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } +} + +/* + * ------------------------------------------------------------ + * 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) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("throttle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_throttle")) + return; + + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) + info->MCR &= ~UART_MCR_RTS; + + save_flags(flags); cli(); + serial_out(info, UART_MCR, info->MCR); + restore_flags(flags); +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("unthrottle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + rs_send_xchar(tty, START_CHAR(tty)); + } + if (tty->termios->c_cflag & CRTSCTS) + info->MCR |= UART_MCR_RTS; + save_flags(flags); cli(); + serial_out(info, UART_MCR, info->MCR); + restore_flags(flags); +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct async_struct * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + struct serial_state *state = info->state; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = state->type; + tmp.line = state->line; + tmp.port = state->port; + if (HIGH_BITS_OFFSET) + tmp.port_high = state->port >> HIGH_BITS_OFFSET; + else + tmp.port_high = 0; + tmp.irq = state->irq; + tmp.flags = state->flags; + tmp.xmit_fifo_size = state->xmit_fifo_size; + tmp.baud_base = state->baud_base; + tmp.close_delay = state->close_delay; + tmp.closing_wait = state->closing_wait; + tmp.custom_divisor = state->custom_divisor; + tmp.hub6 = state->hub6; + tmp.io_type = state->io_type; + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct async_struct * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct serial_state old_state, *state; + unsigned int i,change_irq,change_port; + int retval = 0; + unsigned long new_port; + + if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) + return -EFAULT; + state = info->state; + old_state = *state; + + new_port = new_serial.port; + if (HIGH_BITS_OFFSET) + new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; + + change_irq = new_serial.irq != state->irq; + change_port = (new_port != ((int) state->port)) || + (new_serial.hub6 != state->hub6); + + if (!capable(CAP_SYS_ADMIN)) { + if (change_irq || change_port || + (new_serial.baud_base != state->baud_base) || + (new_serial.type != state->type) || + (new_serial.close_delay != state->close_delay) || + (new_serial.xmit_fifo_size != state->xmit_fifo_size) || + ((new_serial.flags & ~ASYNC_USR_MASK) != + (state->flags & ~ASYNC_USR_MASK))) + return -EPERM; + state->flags = ((state->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + info->flags = ((info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + state->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + new_serial.irq = irq_cannonicalize(new_serial.irq); + + if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || + (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) || + (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) || + (new_serial.type == PORT_STARTECH)) { + return -EINVAL; + } + + if ((new_serial.type != state->type) || + (new_serial.xmit_fifo_size <= 0)) + new_serial.xmit_fifo_size = + uart_config[new_serial.type].dfl_xmit_fifo_size; + + /* Make sure address is not already in use */ + if (new_serial.type) { + for (i = 0 ; i < NR_PORTS; i++) + if ((state != &rs_table[i]) && + (rs_table[i].port == new_port) && + rs_table[i].type) + return -EADDRINUSE; + } + + if ((change_port || change_irq) && (state->count > 1)) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + state->baud_base = new_serial.baud_base; + state->flags = ((state->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | + (info->flags & ASYNC_INTERNAL_FLAGS)); + state->custom_divisor = new_serial.custom_divisor; + state->close_delay = new_serial.close_delay * HZ/100; + state->closing_wait = new_serial.closing_wait * HZ/100; + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->xmit_fifo_size = state->xmit_fifo_size = + new_serial.xmit_fifo_size; + + if ((state->type != PORT_UNKNOWN) && state->port) { + release_region(state->port,8); + } + state->type = new_serial.type; + if (change_port || change_irq) { + /* + * We need to shutdown the serial port at the old + * port/irq combination. + */ + shutdown(info); + state->irq = new_serial.irq; + info->port = state->port = new_port; + info->hub6 = state->hub6 = new_serial.hub6; + if (info->hub6) + info->io_type = state->io_type = SERIAL_IO_HUB6; + else if (info->io_type == SERIAL_IO_HUB6) + info->io_type = state->io_type = SERIAL_IO_PORT; + } + if ((state->type != PORT_UNKNOWN) && state->port) { + request_region(state->port,8,"serial(set)"); + } + + +check_and_exit: + if (!state->port || !state->type) + return 0; + if (info->flags & ASYNC_INITIALIZED) { + if (((old_state.flags & ASYNC_SPD_MASK) != + (state->flags & ASYNC_SPD_MASK)) || + (old_state.custom_divisor != state->custom_divisor)) { + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + change_speed(info, 0); + } + } else { + retval = startup(info); + } + return retval; +} + + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct async_struct * info, unsigned int *value) +{ + unsigned char status; + unsigned int result; + unsigned long flags; + + save_flags(flags); cli(); + status = serial_in(info, UART_LSR); + restore_flags(flags); + result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); + + /* + * If we're about to load something into the transmit + * register, we'll pretend the transmitter isn't empty to + * avoid a race condition (depending on when the transmit + * interrupt happens). + */ + if (info->x_char || + ((CIRC_CNT(info->xmit.head, info->xmit.tail, + SERIAL_XMIT_SIZE) > 0) && + !info->tty->stopped && !info->tty->hw_stopped)) + result &= TIOCSER_TEMT; + + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + + +static int get_modem_info(struct async_struct * info, unsigned int *value) +{ + unsigned char control, status; + unsigned int result; + unsigned long flags; + + control = info->MCR; + save_flags(flags); cli(); + status = serial_in(info, UART_MSR); + restore_flags(flags); + result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) + | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) +#ifdef TIOCM_OUT1 + | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0) + | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0) +#endif + | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) + | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) + | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) + | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); + + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + +static int set_modem_info(struct async_struct * info, unsigned int cmd, + unsigned int *value) +{ + unsigned int arg; + unsigned long flags; + + if (copy_from_user(&arg, value, sizeof(int))) + return -EFAULT; + + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + info->MCR |= UART_MCR_RTS; + if (arg & TIOCM_DTR) + info->MCR |= UART_MCR_DTR; +#ifdef TIOCM_OUT1 + if (arg & TIOCM_OUT1) + info->MCR |= UART_MCR_OUT1; + if (arg & TIOCM_OUT2) + info->MCR |= UART_MCR_OUT2; +#endif + if (arg & TIOCM_LOOP) + info->MCR |= UART_MCR_LOOP; + break; + case TIOCMBIC: + if (arg & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (arg & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; +#ifdef TIOCM_OUT1 + if (arg & TIOCM_OUT1) + info->MCR &= ~UART_MCR_OUT1; + if (arg & TIOCM_OUT2) + info->MCR &= ~UART_MCR_OUT2; +#endif + if (arg & TIOCM_LOOP) + info->MCR &= ~UART_MCR_LOOP; + break; + case TIOCMSET: + info->MCR = ((info->MCR & ~(UART_MCR_RTS | +#ifdef TIOCM_OUT1 + UART_MCR_OUT1 | + UART_MCR_OUT2 | +#endif + UART_MCR_LOOP | + UART_MCR_DTR)) + | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) +#ifdef TIOCM_OUT1 + | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0) + | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0) +#endif + | ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0) + | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); + break; + default: + return -EINVAL; + } + save_flags(flags); cli(); + info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ + serial_out(info, UART_MCR, info->MCR); + restore_flags(flags); + return 0; +} + +static int do_autoconfig(struct async_struct * info) +{ + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (info->state->count > 1) + return -EBUSY; + + shutdown(info); + + autoconfig(info->state); + retval = startup(info); + if (retval) + return retval; + return 0; +} + +/* + * rs_break() --- routine which turns the break handling on or off + */ +static void rs_break(struct tty_struct *tty, int break_state) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_break")) + return; + + if (!CONFIGURED_SERIAL_PORT(info)) + return; + save_flags(flags); cli(); + if (break_state == -1) + info->LCR |= UART_LCR_SBC; + else + info->LCR &= ~UART_LCR_SBC; + serial_out(info, UART_LCR, info->LCR); + restore_flags(flags); +} + + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct async_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct icount; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + 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: + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERCONFIG: + return do_autoconfig(info); + + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + if (copy_to_user((struct async_struct *) arg, + info, sizeof(struct async_struct))) + return -EFAULT; + return 0; + + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + save_flags(flags); cli(); + /* note the counters on entry */ + cprev = info->state->icount; + restore_flags(flags); + /* Force modem status interrupts on */ + info->IER |= UART_IER_MSI; + serial_out(info, UART_IER, info->IER); + while (1) { + interruptible_sleep_on(&info->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + save_flags(flags); cli(); + cnow = info->state->icount; /* atomic copy */ + restore_flags(flags); + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + save_flags(flags); cli(); + cnow = info->state->icount; + restore_flags(flags); + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + if (copy_to_user((void *)arg, &icount, sizeof(icount))) + return -EFAULT; + return 0; + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ + printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + unsigned int cflag = tty->termios->c_cflag; + + if ( (cflag == old_termios->c_cflag) + && ( RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + change_speed(info, old_termios); + + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && + !(cflag & CBAUD)) { + info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); + save_flags(flags); cli(); + serial_out(info, UART_MCR, info->MCR); + restore_flags(flags); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && + (cflag & CBAUD)) { + info->MCR |= UART_MCR_DTR; + if (!(tty->termios->c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) { + info->MCR |= UART_MCR_RTS; + } + save_flags(flags); cli(); + serial_out(info, UART_MCR, info->MCR); + restore_flags(flags); + } + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rs_start(tty); + } +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->device, "rs_close")) + return; + + state = info->state; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + DBG_CNT("before DEC-hung"); + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_close ttys%d, count = %d\n", info->line, state->count); +#endif + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * 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, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, state->count); + state->count = 0; + } + if (state->count) { + DBG_CNT("before DEC-2"); + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + info->flags |= ASYNC_CLOSING; + restore_flags(flags); + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->state->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->state->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->IER &= ~UART_IER_RLSI; + info->read_status_mask &= ~UART_LSR_DR; + if (info->flags & ASYNC_INITIALIZED) { + serial_out(info, UART_IER, info->IER); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + rs_wait_until_sent(tty, info->timeout); + } + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + unsigned long orig_jiffies, char_time; + int lsr; + + if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) + return; + + if (info->state->type == PORT_UNKNOWN) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout && timeout < char_time) + char_time = timeout; + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2*info->timeout) + timeout = 2*info->timeout; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); + printk("jiff=%lu...", jiffies); +#endif + while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + set_current_state(TASK_RUNNING); +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rs_hangup(struct tty_struct *tty) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state = info->state; + + if (serial_paranoia_check(info, tty->device, "rs_hangup")) + return; + + state = info->state; + + rs_flush_buffer(tty); + if (info->flags & ASYNC_CLOSING) + return; + shutdown(info); + info->event = 0; + state->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct async_struct *info) +{ + DECLARE_WAITQUEUE(wait, current); + struct serial_state *state = info->state; + int retval; + int do_clocal = 0, extra_count = 0; + unsigned long flags; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ASYNC_CALLOUT_ACTIVE) { + if (state->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, state->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready before block: ttys%d, count = %d\n", + state->line, state->count); +#endif + save_flags(flags); cli(); + if (!tty_hung_up_p(filp)) { + extra_count = 1; + state->count--; + } + restore_flags(flags); + info->blocked_open++; + while (1) { + save_flags(flags); cli(); + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + (tty->termios->c_cflag & CBAUD)) + serial_out(info, UART_MCR, + serial_inp(info, UART_MCR) | + (UART_MCR_DTR | UART_MCR_RTS)); + restore_flags(flags); + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + !(info->flags & ASYNC_CLOSING) && + (do_clocal || (serial_in(info, UART_MSR) & + UART_MSR_DCD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + schedule(); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&info->open_wait, &wait); + if (extra_count) + state->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready after blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +static int get_async_struct(int line, struct async_struct **ret_info) +{ + struct async_struct *info; + struct serial_state *sstate; + + sstate = rs_table + line; + sstate->count++; + if (sstate->info) { + *ret_info = sstate->info; + return 0; + } + info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); + if (!info) { + sstate->count--; + return -ENOMEM; + } + memset(info, 0, sizeof(struct async_struct)); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->delta_msr_wait); + info->magic = SERIAL_MAGIC; + info->port = sstate->port; + info->flags = sstate->flags; + info->io_type = sstate->io_type; + info->iomem_base = sstate->iomem_base; + info->iomem_reg_shift = sstate->iomem_reg_shift; + info->xmit_fifo_size = sstate->xmit_fifo_size; + info->line = line; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->state = sstate; + if (sstate->info) { + kfree(info); + *ret_info = sstate->info; + return 0; + } + *ret_info = sstate->info = info; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct async_struct *info; + int retval, line; + unsigned long page; + + MOD_INC_USE_COUNT; + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + retval = get_async_struct(line, &info); + if (retval) { + MOD_DEC_USE_COUNT; + return retval; + } + tty->driver_data = info; + info->tty = tty; + if (serial_paranoia_check(info, tty->device, "rs_open")) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->state->count); +#endif + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + if (!tmp_buf) { + page = get_zeroed_page(GFP_KERNEL); + if (!page) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + } + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); + MOD_DEC_USE_COUNT; +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + MOD_DEC_USE_COUNT; + return retval; + } + + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open returning after block_til_ready with %d\n", + retval); +#endif + MOD_DEC_USE_COUNT; + return retval; + } + + if ((info->state->count == 1) && + (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->state->normal_termios; + else + *tty->termios = info->state->callout_termios; + change_speed(info, 0); + } +#ifdef CONFIG_AU1000_SERIAL_CONSOLE + if (sercons.cflag && sercons.index == line) { + tty->termios->c_cflag = sercons.cflag; + sercons.cflag = 0; + change_speed(info, 0); + } +#endif + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open ttys%d successful...", info->line); +#endif + return 0; +} + +/* + * /proc fs routines.... + */ + +static inline int line_info(char *buf, struct serial_state *state) +{ + struct async_struct *info = state->info, scr_info; + char stat_buf[30], control, status; + int ret; + unsigned long flags; + + ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d", + state->line, uart_config[state->type].name, + state->port, state->irq); + + if (!state->port || (state->type == PORT_UNKNOWN)) { + ret += sprintf(buf+ret, "\n"); + return ret; + } + + /* + * Figure out the current RS-232 lines + */ + if (!info) { + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->port = state->port; + info->flags = state->flags; + info->quot = 0; + info->tty = 0; + } + save_flags(flags); cli(); + status = serial_in(info, UART_MSR); + control = info != &scr_info ? info->MCR : serial_in(info, UART_MCR); + restore_flags(flags); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if (control & UART_MCR_RTS) + strcat(stat_buf, "|RTS"); + if (status & UART_MSR_CTS) + strcat(stat_buf, "|CTS"); + if (control & UART_MCR_DTR) + strcat(stat_buf, "|DTR"); + if (status & UART_MSR_DSR) + strcat(stat_buf, "|DSR"); + if (status & UART_MSR_DCD) + strcat(stat_buf, "|CD"); + if (status & UART_MSR_RI) + strcat(stat_buf, "|RI"); + + if (info->quot) { + ret += sprintf(buf+ret, " baud:%d", + state->baud_base / info->quot); + } + + ret += sprintf(buf+ret, " tx:%d rx:%d", + state->icount.tx, state->icount.rx); + + if (state->icount.frame) + ret += sprintf(buf+ret, " fe:%d", state->icount.frame); + + if (state->icount.parity) + ret += sprintf(buf+ret, " pe:%d", state->icount.parity); + + if (state->icount.brk) + ret += sprintf(buf+ret, " brk:%d", state->icount.brk); + + if (state->icount.overrun) + ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); + + /* + * Last thing is the RS-232 status lines + */ + ret += sprintf(buf+ret, " %s\n", stat_buf+1); + return ret; +} + +int rs_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int i, len = 0, l; + off_t begin = 0; + + len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n", + serial_version, LOCAL_VERSTRING, serial_revdate); + for (i = 0; i < NR_PORTS && len < 4000; i++) { + l = line_info(page + len, &rs_table[i]); + len += l; + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (off-begin); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * --------------------------------------------------------------------- + * rs_init() and friends + * + * rs_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static char serial_options[] __initdata = + " no serial options enabled\n"; +#undef SERIAL_OPT + +static _INLINE_ void show_serial_version(void) +{ + printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name, + serial_version, LOCAL_VERSTRING, serial_revdate, + serial_options); +} + + +/* + * This routine is called by rs_init() to initialize a specific serial + * port. It determines what type of UART chip this serial port is + * using: 8250, 16450, 16550, 16550A. The important question is + * whether or not this UART is a 16550A or not, since this will + * determine whether or not we can use its FIFO features or not. + */ +static void autoconfig(struct serial_state * state) +{ + struct async_struct *info, scr_info; + unsigned long flags; + + +#ifdef SERIAL_DEBUG_AUTOCONF + printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line, + state->port, (unsigned) state->iomem_base); +#endif + + if (!CONFIGURED_SERIAL_PORT(state)) + return; + + if (inl(UART_MOD_CNTRL + state->port) != 0x3) { + outl(3, UART_MOD_CNTRL + state->port); + } + + state->type = PORT_16550; + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->state = state; + info->port = state->port; + info->flags = state->flags; + info->io_type = state->io_type; + info->iomem_base = state->iomem_base; + info->iomem_reg_shift = state->iomem_reg_shift; + + + save_flags(flags); cli(); + state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size; + + if (info->port) { + request_region(info->port,8,"serial(auto)"); + } + + /* + * Reset the UART. + */ + serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + serial_outp(info, UART_FCR, 0); + (void)serial_in(info, UART_RX); + serial_outp(info, UART_IER, 0); + + restore_flags(flags); +} + +int register_serial(struct serial_struct *req); +void unregister_serial(int line); + +EXPORT_SYMBOL(register_serial); +EXPORT_SYMBOL(unregister_serial); + + +/* + * The serial driver boot-time initialization code! + */ +static int __init rs_init(void) +{ + int i; + struct serial_state * state; + + init_bh(SERIAL_BH, do_serial_bh); + init_timer(&serial_timer); + serial_timer.function = rs_timer; + mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); + + for (i = 0; i < NR_IRQS; i++) { + IRQ_ports[i] = 0; + IRQ_timeout[i] = 0; + } +#ifdef CONFIG_AU1000_SERIAL_CONSOLE + /* + * The interrupt of the serial console port + * can't be shared. + */ + if (sercons.flags & CON_CONSDEV) { + for(i = 0; i < NR_PORTS; i++) + if (i != sercons.index && + rs_table[i].irq == rs_table[sercons.index].irq) + rs_table[i].irq = 0; + } +#endif + show_serial_version(); + + /* Initialize the tty_driver structure */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.driver_name = "serial"; +#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_DEV_OFFSET; + serial_driver.num = NR_PORTS; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + 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; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.put_char = rs_put_char; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + serial_driver.break_ctl = rs_break; + serial_driver.send_xchar = rs_send_xchar; + serial_driver.wait_until_sent = rs_wait_until_sent; + serial_driver.read_proc = rs_read_proc; + + /* + * The callout device is just like normal device except for + * 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; + callout_driver.read_proc = 0; + callout_driver.proc_entry = 0; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + state->baud_base = get_au1000_uart_baud(); + state->magic = SSTATE_MAGIC; + state->line = i; + state->type = PORT_UNKNOWN; + state->custom_divisor = 0; + state->close_delay = 5*HZ/10; + state->closing_wait = 30*HZ; + state->callout_termios = callout_driver.init_termios; + state->normal_termios = serial_driver.init_termios; + state->icount.cts = state->icount.dsr = + state->icount.rng = state->icount.dcd = 0; + state->icount.rx = state->icount.tx = 0; + state->icount.frame = state->icount.parity = 0; + state->icount.overrun = state->icount.brk = 0; + state->irq = irq_cannonicalize(state->irq); + if (state->hub6) + state->io_type = SERIAL_IO_HUB6; + if (state->port && check_region(state->port,8)) { + continue; + } + + if (state->flags & ASYNC_BOOT_AUTOCONF) { + autoconfig(state); + } + } + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + if (state->type == PORT_UNKNOWN) { + continue; + } + printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n", + state->line + SERIAL_DEV_OFFSET, + (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", + state->port, state->irq, + uart_config[state->type].name); + tty_register_devfs(&serial_driver, 0, + serial_driver.minor_start + state->line); + tty_register_devfs(&callout_driver, 0, + callout_driver.minor_start + state->line); + } + return 0; +} + +/* + * register_serial and unregister_serial allows for 16x50 serial ports to be + * configured at run-time, to support PCMCIA modems. + */ + +/** + * register_serial - configure a 16x50 serial port at runtime + * @req: request structure + * + * Configure the serial port specified by the request. If the + * port exists and is in use an error is returned. If the port + * is not currently in the table it is added. + * + * The port is then probed and if neccessary the IRQ is autodetected + * If this fails an error is returned. + * + * On success the port is ready to use and the line number is returned. + */ + +int register_serial(struct serial_struct *req) +{ + int i; + unsigned long flags; + struct serial_state *state; + struct async_struct *info; + unsigned long port; + + port = req->port; + if (HIGH_BITS_OFFSET) + port += (unsigned long) req->port_high << HIGH_BITS_OFFSET; + + save_flags(flags); cli(); + for (i = 0; i < NR_PORTS; i++) { + if ((rs_table[i].port == port) && + (rs_table[i].iomem_base == req->iomem_base)) + break; + } + if (i == NR_PORTS) { + for (i = 0; i < NR_PORTS; i++) + if ((rs_table[i].type == PORT_UNKNOWN) && + (rs_table[i].count == 0)) + break; + } + if (i == NR_PORTS) { + restore_flags(flags); + return -1; + } + state = &rs_table[i]; + if (rs_table[i].count) { + restore_flags(flags); + printk("Couldn't configure serial #%d (port=%ld,irq=%d): " + "device already open\n", i, port, req->irq); + return -1; + } + state->irq = req->irq; + state->port = port; + state->flags = req->flags; + state->io_type = req->io_type; + state->iomem_base = req->iomem_base; + state->iomem_reg_shift = req->iomem_reg_shift; + if (req->baud_base) + state->baud_base = req->baud_base; + if ((info = state->info) != NULL) { + info->port = port; + info->flags = req->flags; + info->io_type = req->io_type; + info->iomem_base = req->iomem_base; + info->iomem_reg_shift = req->iomem_reg_shift; + } + autoconfig(state); + if (state->type == PORT_UNKNOWN) { + restore_flags(flags); + printk("register_serial(): autoconfig failed\n"); + return -1; + } + restore_flags(flags); + + printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n", + state->line + SERIAL_DEV_OFFSET, + state->iomem_base ? "iomem" : "port", + state->iomem_base ? (unsigned long)state->iomem_base : + state->port, state->irq, uart_config[state->type].name); + tty_register_devfs(&serial_driver, 0, + serial_driver.minor_start + state->line); + tty_register_devfs(&callout_driver, 0, + callout_driver.minor_start + state->line); + return state->line + SERIAL_DEV_OFFSET; +} + +/** + * unregister_serial - deconfigure a 16x50 serial port + * @line: line to deconfigure + * + * The port specified is deconfigured and its resources are freed. Any + * user of the port is disconnected as if carrier was dropped. Line is + * the port number returned by register_serial(). + */ + +void unregister_serial(int line) +{ + unsigned long flags; + struct serial_state *state = &rs_table[line]; + + save_flags(flags); cli(); + if (state->info && state->info->tty) + tty_hangup(state->info->tty); + state->type = PORT_UNKNOWN; + printk(KERN_INFO "tty%02d unloaded\n", state->line); + /* These will be hidden, because they are devices that will no longer + * be available to the system. (ie, PCMCIA modems, once ejected) + */ + tty_unregister_devfs(&serial_driver, + serial_driver.minor_start + state->line); + tty_unregister_devfs(&callout_driver, + callout_driver.minor_start + state->line); + restore_flags(flags); +} + +static void __exit rs_fini(void) +{ + unsigned long flags; + int e1, e2; + int i; + struct async_struct *info; + + /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ + del_timer_sync(&serial_timer); + save_flags(flags); cli(); + remove_bh(SERIAL_BH); + if ((e1 = tty_unregister_driver(&serial_driver))) + printk("serial: failed to unregister serial driver (%d)\n", + e1); + if ((e2 = tty_unregister_driver(&callout_driver))) + printk("serial: failed to unregister callout driver (%d)\n", + e2); + restore_flags(flags); + + for (i = 0; i < NR_PORTS; i++) { + if ((info = rs_table[i].info)) { + rs_table[i].info = NULL; + kfree(info); + } + if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) { + release_region(rs_table[i].port, 8); + } + } + if (tmp_buf) { + unsigned long pg = (unsigned long) tmp_buf; + tmp_buf = NULL; + free_page(pg); + } +} + +module_init(rs_init); +module_exit(rs_fini); +MODULE_DESCRIPTION("Au1000 serial driver"); + + +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ +#ifdef CONFIG_AU1000_SERIAL_CONSOLE + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct async_struct async_sercons; + +/* + * Wait for transmitter & holding register to empty + */ +static inline void wait_for_xmitr(struct async_struct *info) +{ + unsigned int status, tmout = 0xffffff; + + do { + status = serial_in(info, UART_LSR); + + if (status & UART_LSR_BI) + lsr_break_flag = UART_LSR_BI; + + if (--tmout == 0) + break; + } while((status & BOTH_EMPTY) != BOTH_EMPTY); +} + + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console_lock must be held when we get here. + */ +static void serial_console_write(struct console *co, const char *s, + unsigned count) +{ + static struct async_struct *info = &async_sercons; + int ier; + unsigned i; + + /* + * First save the IER then disable the interrupts + */ + ier = serial_in(info, UART_IER); + serial_out(info, UART_IER, 0x00); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + wait_for_xmitr(info); + + /* + * Send the character out. + * If a LF, also do CR... + */ + serial_out(info, UART_TX, *s); + if (*s == 10) { + wait_for_xmitr(info); + serial_out(info, UART_TX, 13); + } + } + + /* + * Finally, Wait for transmitter & holding register to empty + * and restore the IER + */ + wait_for_xmitr(info); + serial_out(info, UART_IER, ier); +} + +/* + * Receive character from the serial port + */ +static int serial_console_wait_key(struct console *co) +{ + static struct async_struct *info; + int ier, c; + + info = &async_sercons; + + /* + * First save the IER then disable the interrupts so + * that the real driver for the port does not get the + * character. + */ + ier = serial_in(info, UART_IER); + serial_out(info, UART_IER, 0x00); + + while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0); + c = serial_in(info, UART_RX); + + /* + * Restore the interrupts + */ + serial_out(info, UART_IER, ier); + + return c; +} + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +/* + * Setup initial baud/bits/parity. We do two things here: + * - construct a cflag setting for the first rs_open() + * - initialize the serial port + * Return non-zero if we didn't find a serial port. + */ +static int __init serial_console_setup(struct console *co, char *options) +{ + static struct async_struct *info; + struct serial_state *state; + unsigned cval; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + int quot = 0; + char *s; + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) parity = *s++; + if (*s) bits = *s - '0'; + } + + /* + * Now construct a cflag setting. + */ + switch(baud) { + case 1200: + cflag |= B1200; + break; + case 2400: + cflag |= B2400; + break; + case 4800: + cflag |= B4800; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + case 9600: + default: + cflag |= B9600; + break; + } + switch(bits) { + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; + } + switch(parity) { + case 'o': case 'O': + cflag |= PARODD; + break; + case 'e': case 'E': + cflag |= PARENB; + break; + } + co->cflag = cflag; + + /* + * Divisor, bytesize and parity + */ + state = rs_table + co->index; + info = &async_sercons; + info->magic = SERIAL_MAGIC; + info->state = state; + info->port = state->port; + info->flags = state->flags; + info->io_type = state->io_type; + info->iomem_base = state->iomem_base; + info->iomem_reg_shift = state->iomem_reg_shift; + state->baud_base = get_au1000_uart_baud(); + quot = state->baud_base / baud; + + cval = cflag & (CSIZE | CSTOPB); + cval >>= 4; + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; + + /* + * Disable UART interrupts, set DTR and RTS high + * and set speed. + */ + serial_out(info, UART_CLK, quot & 0xffff); + serial_out(info, UART_IER, 0); + serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); + + /* + * If we read 0xff from the LSR, there is no UART here. + */ + if (serial_in(info, UART_LSR) == 0xff) + return -1; + + 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, +}; + +/* + * Register console. + */ +void __init au1000_serial_console_init(void) +{ + register_console(&sercons); +} +#endif + +/* + Local variables: + compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" + End: +*/ diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/common/time.c linux/arch/mips/au1000/common/time.c --- v2.4.9/linux/arch/mips/au1000/common/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/common/time.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2001 MontaVista Software, ppopov@mvista.com + * Copied and modified Carsten Langgaard's time.c + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Setting up the clock on the MIPS boards. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern volatile unsigned long wall_jiffies; +unsigned long missed_heart_beats = 0; +unsigned long uart_baud_base; + +static unsigned long r4k_offset; /* Amount to increment compare reg each time */ +static unsigned long r4k_cur; /* What counter should be at next timer irq */ +extern rwlock_t xtime_lock; + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + +static inline void ack_r4ktimer(unsigned long newval) +{ + write_32bit_cp0_register(CP0_COMPARE, newval); +} + + +/* + * There are a lot of conceptually broken versions of the MIPS timer interrupt + * handler floating around. This one is rather different, but the algorithm + * is provably more robust. + */ +unsigned long wtimer; +void mips_timer_interrupt(struct pt_regs *regs) +{ + int irq = 7; + + if (r4k_offset == 0) + goto null; + + do { + kstat.irqs[0][irq]++; + do_timer(regs); + r4k_cur += r4k_offset; + ack_r4ktimer(r4k_cur); + + } while (((unsigned long)read_32bit_cp0_register(CP0_COUNT) + - r4k_cur) < 0x7fffffff); + + return; + +null: + ack_r4ktimer(0); +} + +/* + * Figure out the r4k offset, the amount to increment the compare + * register for each time tick. + * Use the Programmable Counter 1 to do this. + */ +unsigned long cal_r4koff(void) +{ + unsigned long count; + unsigned long cpu_pll; + unsigned long cpu_speed; + unsigned long start, end; + unsigned long counter; + int i; + int trim_divide = 16; + + counter = inl(PC_COUNTER_CNTRL); + outl(counter | PC_CNTRL_EN1, PC_COUNTER_CNTRL); + + while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T1S); + outl(trim_divide-1, PC1_TRIM); /* RTC now ticks at 32.768/16 kHz */ + while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T1S); + + while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_C1S); + outl (0, PC1_COUNTER_WRITE); + while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_C1S); + + start = inl(PC1_COUNTER_READ); + start += 2; + /* wait for the beginning of a new tick */ + while (inl(PC1_COUNTER_READ) < start); + + /* Start r4k counter. */ + write_32bit_cp0_register(CP0_COUNT, 0); + end = start + (32768 / trim_divide)/2; /* wait 0.5 seconds */ + + while (end > inl(PC1_COUNTER_READ)); + + count = read_32bit_cp0_register(CP0_COUNT); + cpu_speed = count * 2; + uart_baud_base = (((cpu_speed) / 4) / 16); + return (cpu_speed / HZ); +} + +static unsigned long __init get_mips_time(void) +{ + return inl(PC0_COUNTER_READ); +} + +void __init time_init(void) +{ + unsigned int est_freq, flags; + + printk("calculating r4koff... "); + r4k_offset = cal_r4koff(); + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + + //est_freq = 2*r4k_offset*HZ; + est_freq = r4k_offset*HZ; + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); + r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); + + write_32bit_cp0_register(CP0_COMPARE, r4k_cur); + set_cp0_status(ALLINTS); + + /* Read time from the RTC chipset. */ + write_lock_irqsave (&xtime_lock, flags); + xtime.tv_sec = get_mips_time(); + xtime.tv_usec = 0; + write_unlock_irqrestore(&xtime_lock, flags); +} + +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) +#define USECS_PER_JIFFY_FRAC ((1000000ULL << 32) / HZ & 0xffffffff) + +/* Cycle counter value at the previous timer interrupt.. */ + +static unsigned int timerhi = 0, timerlo = 0; + +static unsigned long +div64_32(unsigned long v1, unsigned long v2, unsigned long v3) +{ + unsigned long r0; + do_div64_32(r0, v1, v2, v3); + return r0; +} + + +/* + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_fast_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + unsigned long r0; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies=0; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient=0; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + if (last_jiffies != 0) { + r0 = div64_32(timerhi, timerlo, tmp); + quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0); + cached_quotient = quotient; + } + } + + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned int flags; + + read_lock_irqsave (&xtime_lock, flags); + *tv = xtime; + tv->tv_usec += do_fast_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. jiffies - wall_jiffies + * is nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; + + read_unlock_irqrestore (&xtime_lock, flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +void do_settimeofday(struct timeval *tv) +{ + write_lock_irq (&xtime_lock); + + /* This is revolting. We need to set the xtime.tv_usec correctly. + * However, the value in this location is is value at the last tick. + * Discover what correction gettimeofday would have done, and then + * undo it! + */ + tv->tv_usec -= do_fast_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + + write_unlock_irq (&xtime_lock); +} + +/* + * The UART baud base is not known at compile time ... if + * we want to be able to use the same code on different + * speed CPUs. + */ +unsigned long get_au1000_uart_baud() +{ + return uart_baud_base; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/pb1000/Makefile linux/arch/mips/au1000/pb1000/Makefile --- v2.4.9/linux/arch/mips/au1000/pb1000/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/pb1000/Makefile Sun Sep 9 10:43:01 2001 @@ -0,0 +1,24 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Alchemy Semiconductor PB1000 board. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: pb1000.o + +O_TARGET := pb1000.o + +obj-y := init.o setup.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/pb1000/init.c linux/arch/mips/au1000/pb1000/init.c --- v2.4.9/linux/arch/mips/au1000/pb1000/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/pb1000/init.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,59 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PB1000 board setup + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int prom_argc; +extern char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_PB1000; + + prom_init_cmdline(); + + add_memory_region(1, 64 << 20, BOOT_MEM_RAM); + + return 0; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/au1000/pb1000/setup.c linux/arch/mips/au1000/pb1000/setup.c --- v2.4.9/linux/arch/mips/au1000/pb1000/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/au1000/pb1000/setup.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,117 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Au1000-based board setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@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. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_AU1000_SERIAL_CONSOLE) +extern void console_setup(char *, int *); +char serial_console[20]; +#endif + +void (*__wbflush) (void); +extern struct rtc_ops no_rtc_ops; +extern char * __init prom_getcmdline(void); +extern void au1000_restart(void); +extern void au1000_halt(void); +extern void au1000_power_off(void); + +struct { + struct resource ram; + struct resource io; + struct resource sram; + struct resource flash; + struct resource boot; + struct resource pcmcia; + struct resource lcd; +} au1000_resources = { + { "RAM", 0, 0x3FFFFFF, IORESOURCE_MEM }, + { "I/O", 0x10000000, 0x119FFFFF }, + { "SRAM", 0x1e000000, 0x1E03FFFF }, + { "System Flash", 0x1F800000, 0x1FBFFFFF }, + { "Boot ROM", 0x1FC00000, 0x1FFFFFFF }, + { "PCMCIA", 0x20000000, 0x27FFFFFF }, + { "LCD", 0x60000000, 0x603FFFFF }, +}; + +void au1000_wbflush(void) +{ + __asm__ volatile ("sync"); +} + +void __init au1000_setup(void) +{ + char *argptr; + + argptr = prom_getcmdline(); + +#ifdef CONFIG_AU1000_SERIAL_CONSOLE + if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); + } +#endif + + //set_cp0_status(ST0_FR,0); + rtc_ops = &no_rtc_ops; + __wbflush = au1000_wbflush; + _machine_restart = au1000_restart; + _machine_halt = au1000_halt; + _machine_power_off = au1000_power_off; + + /* + * IO/MEM resources. + */ + mips_io_port_base = KSEG1; + ioport_resource.start = au1000_resources.io.start; + ioport_resource.end = au1000_resources.lcd.end; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); +#endif + + outl(PC_CNTRL_E0 | PC_CNTRL_EN0 | PC_CNTRL_EN0, PC_COUNTER_CNTRL); + while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T0S); + outl(0x8000-1, PC0_TRIM); + + printk("Alchemy Semi PB1000 Board\n"); + printk("Au1000/PB1000 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); +} + diff -u --recursive --new-file v2.4.9/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c --- v2.4.9/linux/arch/mips/baget/irq.c Tue Mar 6 19:44:36 2001 +++ linux/arch/mips/baget/irq.c Sun Sep 9 10:43:01 2001 @@ -4,8 +4,6 @@ * Copyright (C) 1998 Vladimir Roganov & Gleb Raiko * Code (mostly sleleton and comments) derived from DECstation IRQ * handling. - * - * $Id: irq.c,v 1.6 2000/02/04 07:40:23 ralf Exp $ */ #include #include @@ -180,7 +178,7 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; mask_irq(irq); @@ -202,7 +200,7 @@ printk("do_IRQ: Unregistered IRQ (0x%X) occurred\n", irq); } unmask_irq(irq); - irq_exit(cpu); + irq_exit(cpu, irq); /* unmasking and bottom half handling is done magically for us. */ } @@ -358,13 +356,6 @@ } printk("Trying to free free IRQ%d\n",irq); } - -static int baget_irq_canonicalize(int irq) -{ - return irq; -} - -int (*irq_cannonicalize)(int irq) = baget_irq_canonicalize; unsigned long probe_irq_on (void) { diff -u --recursive --new-file v2.4.9/linux/arch/mips/baget/prom/init.c linux/arch/mips/baget/prom/init.c --- v2.4.9/linux/arch/mips/baget/prom/init.c Mon Feb 28 07:18:20 2000 +++ linux/arch/mips/baget/prom/init.c Sun Sep 9 10:43:01 2001 @@ -2,25 +2,24 @@ * init.c: PROM library initialisation code. * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - * - * $Id: init.c,v 1.3 1999/10/09 00:00:57 ralf Exp $ */ #include +#include #include -char arcs_cmdline[CL_SIZE]; +char arcs_cmdline[COMMAND_LINE_SIZE]; -int __init prom_init(unsigned int mem_upper) +void __init prom_init(unsigned int mem_upper) { - mips_memory_upper = mem_upper; + mem_upper = PHYSADDR(mem_upper); + mips_machgroup = MACH_GROUP_UNKNOWN; mips_machtype = MACH_UNKNOWN; arcs_cmdline[0] = 0; - return 0; -} -void __init prom_fixup_mem_map(unsigned long start, unsigned long end) -{ + vac_memory_upper = mem_upper; + + add_memory_region(0, mem_upper, BOOT_MEM_RAM); } void prom_free_prom_memory (void) diff -u --recursive --new-file v2.4.9/linux/arch/mips/baget/setup.c linux/arch/mips/baget/setup.c --- v2.4.9/linux/arch/mips/baget/setup.c Mon Feb 28 07:18:20 2000 +++ linux/arch/mips/baget/setup.c Sun Sep 9 10:43:01 2001 @@ -14,7 +14,7 @@ #include -extern long mips_memory_upper; +long int vac_memory_upper; #define CACHEABLE_STR(val) ((val) ? "not cached" : "cached") #define MIN(a,b) (((a)<(b)) ? (a):(b)) @@ -172,7 +172,7 @@ static void __init vac_init(void) { - unsigned short mem_limit = ((mips_memory_upper-KSEG0) >> 16); + unsigned short mem_limit = (vac_memory_upper >> 16); switch(vac_inw(VAC_ID)) { case 0x1AC0: diff -u --recursive --new-file v2.4.9/linux/arch/mips/baget/time.c linux/arch/mips/baget/time.c --- v2.4.9/linux/arch/mips/baget/time.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/baget/time.c Sun Sep 9 10:43:01 2001 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.3 1999/08/17 22:18:37 ralf Exp $ +/* * time.c: Baget/MIPS specific time handling details * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include @@ -23,11 +23,14 @@ #include +extern rwlock_t xtime_lock; + /* * To have precision clock, we need to fix available clock frequency */ #define FREQ_NOM 79125 /* Baget frequency ratio */ #define FREQ_DEN 10000 + static inline int timer_intr_valid(void) { static unsigned long long ticks, valid_ticks; @@ -47,8 +50,8 @@ void static timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { if (timer_intr_valid()) { - sti(); - do_timer(regs); + sti(); + do_timer(regs); } } @@ -76,21 +79,20 @@ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; + unsigned long flags; - save_and_cli(flags); - *tv = xtime; - restore_flags(flags); + read_lock_irqsave (&xtime_lock, flags); + *tv = xtime; + read_unlock_irqrestore (&xtime_lock, flags); } void do_settimeofday(struct timeval *tv) { - unsigned long flags; - - save_and_cli(flags); - xtime = *tv; - time_state = TIME_BAD; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; - restore_flags(flags); -} + write_lock_irq (&xtime_lock); + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + write_unlock_irq (&xtime_lock); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/baget/vacserial.c linux/arch/mips/baget/vacserial.c --- v2.4.9/linux/arch/mips/baget/vacserial.c Fri Feb 9 11:29:44 2001 +++ linux/arch/mips/baget/vacserial.c Sun Sep 9 10:43:01 2001 @@ -1,4 +1,4 @@ -/* $Id: vacserial.c,v 1.3 1999/08/17 22:18:37 ralf Exp $ +/* * vacserial.c: VAC UART serial driver * This code stealed and adopted from linux/drivers/char/serial.c * See that for author info @@ -1300,7 +1300,7 @@ goto check_and_exit; } - new_serial.irq = irq_cannonicalize(new_serial.irq); + new_serial.irq = new_serial.irq; if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) || (new_serial.baud_base == 0) || (new_serial.type < PORT_UNKNOWN) || @@ -1417,12 +1417,10 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd, unsigned int *value) { - int error; unsigned int arg; - error = get_user(arg, value); - if (error) - return error; + if (get_user(arg, value)) + return -EFAULT; switch (cmd) { default: return -EINVAL; @@ -2426,7 +2424,7 @@ state->icount.rx = state->icount.tx = 0; state->icount.frame = state->icount.parity = 0; state->icount.overrun = state->icount.brk = 0; - state->irq = irq_cannonicalize(state->irq); + state->irq = state->irq; if (check_region(state->port,8)) continue; if (state->flags & ASYNC_BOOT_AUTOCONF) diff -u --recursive --new-file v2.4.9/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile --- v2.4.9/linux/arch/mips/boot/Makefile Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/boot/Makefile Sun Sep 9 10:43:01 2001 @@ -1,10 +1,9 @@ -# $Id: Makefile,v 1.9 1999/04/07 18:45:23 harald Exp $ # # 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. # -# Copyright (C) 1995, 1998 by Ralf Baechle +# Copyright (C) 1995, 1998, 2001 by Ralf Baechle # .S.s: @@ -46,25 +45,12 @@ clean: rm -f vmlinux.ecoff - rm -f zImage zImage.tmp mkboot + rm -f zImage zImage.tmp mrproper: rm -f vmlinux.ecoff rm -f addinitrd rm -f elf2ecoff - -zImage: $(CONFIGURE) mkboot $(TOPDIR)/vmlinux - $(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp - ./mkboot zImage.tmp zImage - rm -f zImage.tmp - -mkboot: mkboot.c - $(HOSTCC) -o $@ $^ - -zdisk: zImage - cp $(TOPDIR)/vmlinux $(TOPDIR)/vm - $(STRIP) $(TOPDIR)/vm - gzip -9f $(TOPDIR)/vm dummy: diff -u --recursive --new-file v2.4.9/linux/arch/mips/boot/mkboot.c linux/arch/mips/boot/mkboot.c --- v2.4.9/linux/arch/mips/boot/mkboot.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/boot/mkboot.c Wed Dec 31 16:00:00 1969 @@ -1,658 +0,0 @@ -/* - * Make a bootable image from a Linux/MIPS kernel. - * - * 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. - * - * Copyright (C) 1996, 2001 by Ralf Baechle - * - * This file is written in plain Kernighan & Ritchie C as it has to run - * on all crosscompile hosts no matter how braindead. This code might - * also become part of Milo. It's therefore important that we don't use - * seek because the Seek() call of the Magnum 4000 ARC BIOS is broken. - */ -#include -#include -#include -#include -#include -#include -#include - -/* - * Define this for verbose debugging output. - */ -#undef VERBOSE - -/* - * Don't use the host's elf.h - it might be using incompatible defines - */ - -#define EI_NIDENT 16 - -/* - * Basic ELF types. - */ -typedef unsigned short Elf32_Half; -typedef unsigned short Elf32_Section; -typedef unsigned int Elf32_Word; -typedef unsigned int Elf32_Addr; -typedef unsigned int Elf32_Off; - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf32_Half e_type; /* Object file type */ - Elf32_Half e_machine; /* Architecture */ - Elf32_Word e_version; /* Object file version */ - Elf32_Addr e_entry; /* Entry point virtual address */ - Elf32_Off e_phoff; /* Program header table file offset */ - Elf32_Off e_shoff; /* Section header table file offset */ - Elf32_Word e_flags; /* Processor-specific flags */ - Elf32_Half e_ehsize; /* ELF header size in bytes */ - Elf32_Half e_phentsize; /* Program header table entry size */ - Elf32_Half e_phnum; /* Program header table entry count */ - Elf32_Half e_shentsize; /* Section header table entry size */ - Elf32_Half e_shnum; /* Section header table entry count */ - Elf32_Half e_shstrndx; /* Section header string table index */ -} Elf32_Ehdr; - -/* - * ELF magic number - */ -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define EI_CLASS 4 /* File class byte index */ -#define ELFCLASSNONE 0 /* Invalid class */ -#define ELFCLASS32 1 /* 32-bit objects */ -#define ELFCLASS64 2 /* 64-bit objects */ - -#define EI_DATA 5 /* Data encoding byte index */ -#define ELFDATA2LSB 1 /* 2's complement, little endian */ -#define ELFDATA2MSB 2 /* 2's complement, big endian */ - -#define EI_VERSION 6 /* File version byte index */ -#define EV_CURRENT 1 /* Current version */ - -/* - * Acceptable machine type in e_machine. - */ -#define EM_MIPS 8 /* MIPS R3000 big-endian */ - -/* - * The type of ELF file we accept. - */ -#define ET_EXEC 2 /* Executable file */ - -/* - * Definition of a single program header structure - */ -typedef struct -{ - Elf32_Word p_type; /* Segment type */ - Elf32_Off p_offset; /* Segment file offset */ - Elf32_Addr p_vaddr; /* Segment virtual address */ - Elf32_Addr p_paddr; /* Segment physical address */ - Elf32_Word p_filesz; /* Segment size in file */ - Elf32_Word p_memsz; /* Segment size in memory */ - Elf32_Word p_flags; /* Segment flags */ - Elf32_Word p_align; /* Segment alignment */ -} Elf32_Phdr; - -/* - * Legal values for p_type - */ -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_NUM 7 /* Number of defined types. */ -#define PT_LOPROC 0x70000000 /* Start of processor-specific */ -#define PT_HIPROC 0x7fffffff /* End of processor-specific */ - -typedef struct -{ - Elf32_Word sh_name; /* Section name (string tbl index) */ - Elf32_Word sh_type; /* Section type */ - Elf32_Word sh_flags; /* Section flags */ - Elf32_Addr sh_addr; /* Section virtual addr at execution */ - Elf32_Off sh_offset; /* Section file offset */ - Elf32_Word sh_size; /* Section size in bytes */ - Elf32_Word sh_link; /* Link to another section */ - Elf32_Word sh_info; /* Additional section information */ - Elf32_Word sh_addralign; /* Section alignment */ - Elf32_Word sh_entsize; /* Entry size if section holds table */ -} Elf32_Shdr; - -typedef struct -{ - Elf32_Word st_name; /* Symbol name (string tbl index) */ - Elf32_Addr st_value; /* Symbol value */ - Elf32_Word st_size; /* Symbol size */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* No defined meaning, 0 */ - Elf32_Section st_shndx; /* Section index */ -} Elf32_Sym; - -/* How to extract and insert information held in the st_info field. */ -#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) -#define ELF32_ST_TYPE(val) ((val) & 0xf) - -/* Legal values for ST_BIND subfield of st_info (symbol binding). */ -#define STB_GLOBAL 1 /* Global symbol */ - -/* Legal values for ST_TYPE subfield of st_info (symbol type). */ -#define STT_NOTYPE 0 /* Symbol type is unspecified */ -#define STT_OBJECT 1 /* Symbol is a data object */ -#define STT_FUNC 2 /* Symbol is a code object */ - -static unsigned int -get_Elf32_Half(unsigned char *p) -{ - return p[0] | (p[1] << 8); -} -#define get_Elf32_Section(p) get_Elf32_Half(p) - -static unsigned int -get_Elf32_Word(unsigned char *p) -{ - return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); -} -#define get_Elf32_Addr(p) get_Elf32_Word(p) -#define get_Elf32_Off(p) get_Elf32_Word(p) - -static void -put_byte(p, x) - unsigned char *p; - unsigned char x; -{ - p[0] = x; -} - -static void -put_half(p, x) - unsigned char *p; - unsigned short x; -{ - p[0] = x & 0xff; - p[1] = (x >> 8) & 0xff; -} - -static void -put_word(p, x) - unsigned char *p; - unsigned long x; -{ - p[0] = x & 0xff; - p[1] = (x >> 8) & 0xff; - p[2] = (x >> 16) & 0xff; - p[3] = (x >> 24) & 0xff; -} - -/* - * Swap a program header in. - */ -static void -get_elfph(p, ph) - unsigned char *p; - Elf32_Phdr *ph; -{ - ph->p_type = get_Elf32_Word(p); - ph->p_offset = get_Elf32_Off(p + 4); - ph->p_vaddr = get_Elf32_Addr(p + 8); - ph->p_paddr = get_Elf32_Addr(p + 12); - ph->p_filesz = get_Elf32_Word(p + 16); - ph->p_memsz = get_Elf32_Word(p + 20); - ph->p_flags = get_Elf32_Word(p + 24); - ph->p_align = get_Elf32_Word(p + 28); -} - -/* - * Swap a section header in. - */ -static void -get_elfsh(p, sh) - unsigned char *p; - Elf32_Shdr *sh; -{ - sh->sh_name = get_Elf32_Word(p); - sh->sh_type = get_Elf32_Word(p + 4); - sh->sh_flags = get_Elf32_Word(p + 8); - sh->sh_addr = get_Elf32_Addr(p + 12); - sh->sh_offset = get_Elf32_Off(p + 16); - sh->sh_size = get_Elf32_Word(p + 20); - sh->sh_link = get_Elf32_Word(p + 24); - sh->sh_info = get_Elf32_Word(p + 28); - sh->sh_addralign = get_Elf32_Word(p + 32); - sh->sh_entsize = get_Elf32_Word(p + 36); -} - -/* - * Swap a section header in. - */ -static void -get_elfsym(p, sym) - unsigned char *p; - Elf32_Sym *sym; -{ - sym->st_name = get_Elf32_Word(p); - sym->st_value = get_Elf32_Addr(p + 4); - sym->st_size = get_Elf32_Word(p + 8); - sym->st_info = *(p + 12); - sym->st_other = *(p + 13); - sym->st_shndx = get_Elf32_Section(p + 14); -} - -/* - * The a.out magic number - */ -#define OMAGIC 0407 /* Code indicating object file or impure executable. */ -#define M_MIPS1 151 /* MIPS R3000/R3000 binary */ -#define M_MIPS2 152 /* MIPS R6000/R4000 binary */ - -/* - * Compute and return an a.out magic number. - */ -#define AOUT_INFO(magic, type, flags) \ - (((magic) & 0xffff) | \ - (((int)(type) & 0xff) << 16) | \ - (((flags) & 0xff) << 24)) - -/* - * a.out symbols - */ -#define N_UNDF 0 -#define N_ABS 2 -#define N_TEXT 4 -#define N_DATA 6 -#define N_BSS 8 -#define N_FN 15 -#define N_EXT 1 - -#define min(x,y) (((x)<(y))?(x):(y)) - -static void -do_read(fd, buf, size) - int fd; - char *buf; - ssize_t size; -{ - ssize_t rd; - - while(size != 0) { - rd = read(fd, buf, size); - if (rd == -1) { - perror("Can't read from file."); - exit(1); - } - size -= rd; - } -} - -static void -writepad(fd, size) - int fd; - size_t size; -{ - static void *zeropage = NULL; - ssize_t written; - - if (zeropage == NULL) { - zeropage = malloc(4096); - if (zeropage == NULL) { - fprintf(stderr, "Couldn't allocate zero buffer.\n"); - exit(1); - } - memset(zeropage, '\0', 4096); - } - while(size != 0) { - written = write(fd, zeropage, min(4096, size)); - if (written == -1) { - perror("Can't write to boot image"); - exit(1); - } - size -= written; - } -} - -static void -do_write(fd, buf, size) - int fd; - char *buf; - ssize_t size; -{ - ssize_t written; - - while(size != 0) { - written = write(fd, buf, size); - if (written == -1) { - perror("Can't write to boot image"); - exit(1); - } - size -= written; - } -} - -static int -usage(program_name) - char *program_name; -{ - fprintf(stderr, "Usage: %s infile outfile\n", program_name); - exit(0); -} - -int -main(argc, argv) - int argc; - char *argv[]; -{ - char *infile, *outfile; - struct stat ifstat; - off_t ifsize; - char *image; - int ifd, ofd, i, symtabix, strtabix; - Elf32_Ehdr eh; - Elf32_Phdr *ph; - Elf32_Shdr *sh; - unsigned long vaddr, entry, bss, kernel_entry, kernel_end; - unsigned char ahdr[32]; - Elf32_Sym sym; - int symnum; - char *symname; - - /* - * Verify some basic assuptions about type sizes made in this code - */ - if (sizeof(Elf32_Half) != 2) { - fprintf(stderr, "Fix mkboot: sizeof(Elf32_Half) != 2\n"); - exit(1); - } - if (sizeof(Elf32_Word) != 4) { - fprintf(stderr, "Fix mkboot: sizeof(Elf32_Word) != 4\n"); - exit(1); - } - if (sizeof(Elf32_Addr) != 4) { - fprintf(stderr, "Fix mkboot: sizeof(Elf32_Addr) != 4\n"); - exit(1); - } - - if (argc != 3) - usage(argv[0]); - - infile = argv[1]; - outfile = argv[2]; - - if (stat(infile, &ifstat) < 0) { - perror("Can't stat kernel image."); - exit(1); - } - - if (!S_ISREG(ifstat.st_mode)) { - fprintf(stderr, "Input file isn't a regular file.\n"); - exit(1); - } - ifsize = ifstat.st_size; - - image = malloc((size_t)ifsize); - if (image == NULL) { - fprintf(stderr, "Can't allocate memory to read file\n"); - exit(1); - } - - /* - * Read the entire input file in. - */ - ifd = open(infile, O_RDONLY); - if(ifd == 0) { - fprintf(stderr, "Can't open input file\n"); - exit(1); - } - do_read(ifd, image, ifsize); - close(ifd); - - /* - * Now swap the ELF header in. This is ugly but we the file - * we're reading might have different type sizes, byteorder - * or alignment than the host. - */ - memcpy(eh.e_ident, (void *)image, sizeof(eh.e_ident)); - if(memcmp(eh.e_ident, ELFMAG, SELFMAG)) { - fprintf(stderr, "Input file isn't a ELF file\n"); - exit(1); - } - if(eh.e_ident[EI_CLASS] != ELFCLASS32) { - fprintf(stderr, "Input file isn't a 32 bit ELF file\n"); - exit(1); - } - if(eh.e_ident[EI_DATA] != ELFDATA2LSB) { - fprintf(stderr, "Input file isn't a little endian ELF file\n"); - exit(1); - } - if(eh.e_ident[EI_VERSION] != EV_CURRENT) { - fprintf(stderr, "Input file isn't a version %d ELF file\n", - EV_CURRENT); - exit(1); - } - - /* - * Ok, so far the file looks ok. Now swap the rest of the header in - * and do some more paranoia checks. - */ - eh.e_type = get_Elf32_Half(image + 16); - eh.e_machine = get_Elf32_Half(image + 18); - eh.e_version = get_Elf32_Word(image + 20); - eh.e_entry = get_Elf32_Addr(image + 24); - eh.e_phoff = get_Elf32_Off(image + 28); - eh.e_shoff = get_Elf32_Off(image + 32); - eh.e_flags = get_Elf32_Word(image + 36); - eh.e_ehsize = get_Elf32_Half(image + 40); - eh.e_phentsize = get_Elf32_Half(image + 42); - eh.e_phnum = get_Elf32_Half(image + 44); - eh.e_shentsize = get_Elf32_Half(image + 46); - eh.e_shnum = get_Elf32_Half(image + 48); - eh.e_shstrndx = get_Elf32_Half(image + 50); - - if(eh.e_type != ET_EXEC) { - fprintf(stderr, "Input file isn't a executable.\n"); - exit(1); - } - if(eh.e_machine != EM_MIPS) { - fprintf(stderr, "Input file isn't a MIPS executable.\n"); - exit(1); - } - - /* - * Now read the program headers ... - */ - ph = malloc(sizeof(Elf32_Phdr) * eh.e_phnum); - if (ph == NULL) { - fprintf(stderr, "No memory for program header table.\n"); - exit(1); - } - for(i = 0;i < eh.e_phnum; i++) - get_elfph((void *)(image + eh.e_phoff + i * 32), ph + i); - - /* - * ... and then the section headers. - */ - sh = malloc(sizeof(Elf32_Shdr) * eh.e_shnum); - if (sh == NULL) { - fprintf(stderr, "No memory for section header table.\n"); - exit(1); - } - for(i = 0;i < eh.e_shnum; i++) - get_elfsh((void *)(image + eh.e_shoff + (i * 40)), sh + i); - - /* - * Find the symboltable and the stringtable in the file. - */ - for(i = 0;i < eh.e_shnum; i++) { - if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name, - ".symtab")) { - symtabix = i; - continue; - } - if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name, - ".strtab")) { - strtabix = i; - continue; - } - } - - if (symtabix == -1) { - fprintf(stderr, "The executable doesn't have a symbol table\n"); - exit(1); - } - if (strtabix == -1) { - fprintf(stderr, "The executable doesn't have a string table\n"); - exit(1); - } - - /* - * Dig for the two required symbols in the symbol table. - */ - symnum = sh[symtabix].sh_size / 16; - for(i = 0;i < symnum;i++) { - get_elfsym(image + sh[symtabix].sh_offset + (i * 16), &sym); - symname = image + sh[strtabix].sh_offset + sym.st_name; - if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL) - continue; - if (ELF32_ST_TYPE(sym.st_info) != STT_NOTYPE && - ELF32_ST_TYPE(sym.st_info) != STT_OBJECT && - ELF32_ST_TYPE(sym.st_info) != STT_FUNC) - continue; - if (strcmp("kernel_entry", symname) == 0) { - kernel_entry = sym.st_value; - continue; - } - if (strcmp("_end", symname) == 0) { - kernel_end = sym.st_value; - continue; - } - } - -#ifdef VERBOSE - /* - * And print what we will be loaded into memory. - */ - for(i = 0;i < eh.e_phnum; i++) { - if (ph[i].p_type != PT_LOAD) { - continue; - } - printf(" Offset: %08lx\n", ph[i].p_offset); - printf(" file size: %08lx\n", ph[i].p_filesz); - printf(" mem size: %08lx\n", ph[i].p_memsz); - printf(" Loading: %08lx - %08lx\n", - ph[i].p_vaddr, ph[i].p_vaddr + ph[i].p_filesz); - printf(" Zero mapping: %08lx - %08lx\n", - ph[i].p_vaddr + ph[i].p_filesz, - ph[i].p_vaddr + ph[i].p_memsz); - } -#endif - - /* - * Time to open the outputfile. - */ - ofd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666); - if (ofd == -1) { - perror("Can't open boot image for output."); - exit(1); - } - - /* - * First compute the layout of the file. We need to do this - * first because we can't seek back to the beginning due to the - * broken Seek() call in the Magnum firmware. - */ - entry = vaddr = 0xffffffff; - bss = 0; - for(i = 0;i < eh.e_phnum; i++) { - if (ph[i].p_type != PT_LOAD) - continue; - if (vaddr == 0xffffffff) - entry = vaddr = ph[i].p_vaddr; - vaddr = ph[i].p_vaddr + ph[i].p_filesz; - bss = ph[i].p_memsz - ph[i].p_filesz; - } - - /* - * In the next step we construct the boot image. The boot file - * looks essentially like a dump of the loaded kernel with a - * minimal header. Because Milo supports already a.out image - * we simply dump the image in an a.out image ... First let's - * write the header. - */ - - /* - * Create and write the a.out header. - */ - put_word(ahdr, AOUT_INFO(OMAGIC, M_MIPS1, 0)); - put_word(ahdr + 4, vaddr - entry); /* text size */ - put_word(ahdr + 8, 0); /* data size */ - put_word(ahdr + 12, bss); /* bss size */ - put_word(ahdr + 16, 2 * 12); /* size of symbol table */ - put_word(ahdr + 20, entry); /* base address */ - put_word(ahdr + 24, 0); /* size of text relocations */ - put_word(ahdr + 28, 0); /* size of data relocations */ - do_write(ofd, ahdr, 32); - - /* - * Write text and data segment combined into the a.out text segment - * and a zero length data segment into the file. - */ - vaddr = 0xffffffff; - bss = 0; - for(i = 0;i < eh.e_phnum; i++) { - if (ph[i].p_type != PT_LOAD) - continue; - if (vaddr == 0xffffffff) - vaddr = ph[i].p_vaddr; - writepad(ofd, ph[i].p_vaddr - vaddr); /* Write zero pad */ - do_write(ofd, image + ph[i].p_offset, ph[i].p_filesz); - vaddr = ph[i].p_vaddr + ph[i].p_filesz; - bss = ph[i].p_memsz - ph[i].p_filesz; - } - - /* - * Now write the symbol table. It has only two symbols, - * kernel_entry and _end which we need for booting. - */ - put_word(ahdr , 4); /* n_un.n_strx */ - put_byte(ahdr + 4, N_TEXT | N_EXT); /* n_type */ - put_byte(ahdr + 5, 0); /* n_other */ - put_half(ahdr + 6, 0); /* n_desc */ - put_word(ahdr + 8, kernel_entry); /* n_value */ - do_write(ofd, ahdr, 12); - - put_word(ahdr , 4 + 13); /* n_un.n_strx */ - put_byte(ahdr + 4, N_ABS | N_EXT); /* n_type */ - put_byte(ahdr + 5, 0); /* n_other */ - put_half(ahdr + 6, 0); /* n_desc */ - put_word(ahdr + 8, kernel_end); /* n_value */ - do_write(ofd, ahdr, 12); - - /* - * Now write stringtable size and the strings. - */ - put_word(ahdr, 4 + 20); - do_write(ofd, ahdr, 4); - do_write(ofd, "kernel_entry\0_end\0\0", 20); - - /* - * That's is all ... - */ - close(ofd); - -#ifdef VERBOSE - printf("Entry: %08lx\n", entry); - printf("Dumped image %08lx - %08lx\n", 0x80000000, vaddr); - printf("Extra bss at end: %08lx\n", bss); -#endif - - return 0; -} diff -u --recursive --new-file v2.4.9/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.4.9/linux/arch/mips/config.in Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/config.in Sun Sep 9 10:43:02 2001 @@ -76,6 +76,7 @@ # unset CONFIG_ARC32 unset CONFIG_BOARD_SCACHE +unset CONFIG_COHERENT_IO unset CONFIG_HAVE_STD_PC_SERIAL_PORT unset CONFIG_I8259 unset CONFIG_ISA @@ -92,6 +93,8 @@ define_bool CONFIG_PCI y define_bool CONFIG_MIPS_GT96100 y define_bool CONFIG_SWAP_IO_SPACE y + define_bool CONFIG_NEW_PCI y + define_bool CONFIG_PCI_AUTO y fi if [ "$CONFIG_MIPS_EV64120" = "y" ]; then define_bool CONFIG_PCI y @@ -132,6 +135,7 @@ define_bool CONFIG_I8259 y define_bool CONFIG_PCI y define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y + define_bool CONFIG_NEW_IRQ y define_bool CONFIG_SWAP_IO_SPACE y fi if [ "$CONFIG_MOMENCO_OCELOT" = "y" ]; then @@ -158,7 +162,7 @@ define_bool CONFIG_ROTTEN_IRQ y define_bool CONFIG_OLD_TIME_C y fi -if [ "$CONFIG_DDB5074" = "y"]; then +if [ "$CONFIG_DDB5074" = "y" ]; then define_bool CONFIG_I8259 y define_bool CONFIG_ISA y define_bool CONFIG_PCI y @@ -168,7 +172,6 @@ define_bool CONFIG_OLD_TIME_C y fi if [ "$CONFIG_DDB5476" = "y" ]; then - define_bool CONFIG_I8259 y define_bool CONFIG_ISA y define_bool CONFIG_PCI y define_bool CONFIG_PC_KEYB y @@ -186,6 +189,8 @@ define_bool CONFIG_PCI y define_bool CONFIG_IT8712 y define_bool CONFIG_PC_KEYB y + define_bool CONFIG_NEW_PCI y + define_bool CONFIG_PCI_AUTO y fi if [ "$CONFIG_MIPS_IVR" = "y" ]; then define_bool CONFIG_PCI y @@ -229,33 +234,45 @@ choice 'CPU type' \ "R3000 CONFIG_CPU_R3000 \ R6000 CONFIG_CPU_R6000 \ + R41xx CONFIG_CPU_VR41XX \ R4300 CONFIG_CPU_R4300 \ R4x00 CONFIG_CPU_R4X00 \ R5000 CONFIG_CPU_R5000 \ - R5432 CONFIG_CPU_R5432 \ + R5432 CONFIG_CPU_R5432 \ RM7000 CONFIG_CPU_RM7000 \ R52xx CONFIG_CPU_NEVADA \ R10000 CONFIG_CPU_R10000 \ SB1 CONFIG_CPU_SB1 \ - MIPS32 CONFIG_CPU_MIPS32" R4x00 + MIPS32 CONFIG_CPU_MIPS32 \ + MIPS64 CONFIG_CPU_MIPS64" R4x00 bool 'Override CPU Options' CONFIG_CPU_ADVANCED if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then bool ' ll/sc Instructions available' CONFIG_CPU_HAS_LLSC + bool ' lld/scd Instructions available' CONFIG_CPU_HAS_LLDSCD bool ' Writeback Buffer available' CONFIG_CPU_HAS_WB else - if [ "$CONFIG_CPU_R3000" = "y" ]; then - if [ "$CONFIG_DECSTATION" = "y" ]; then + if [ "$CONFIG_CPU_R3000" = "y" -o "$CONFIG_CPU_VR41XX" = "y" ]; then + if [ "CONFIG_DECSTATION" = "y" ]; then define_bool CONFIG_CPU_HAS_LLSC n + define_bool CONFIG_CPU_HAS_LLDSCD n define_bool CONFIG_CPU_HAS_WB y else define_bool CONFIG_CPU_HAS_LLSC n + define_bool CONFIG_CPU_HAS_LLDSCD n define_bool CONFIG_CPU_HAS_WB n fi else + if [ "$CONFIG_CPU_MIPS32" = "y" ]; then + define_bool CONFIG_CPU_HAS_LLSC y + define_bool CONFIG_CPU_HAS_LLDSCD n + define_bool CONFIG_CPU_HAS_WB n + else define_bool CONFIG_CPU_HAS_LLSC y + define_bool CONFIG_CPU_HAS_LLDSCD y define_bool CONFIG_CPU_HAS_WB n + fi fi fi endmenu @@ -270,7 +287,6 @@ else bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN fi -bool 'Kernel floating-point emulation' CONFIG_MIPS_FPU_EMULATOR if [ "$CONFIG_PROC_FS" = "y" ]; then define_bool CONFIG_KCORE_ELF y @@ -361,7 +377,7 @@ if [ "$CONFIG_DECSTATION" != "y" -a \ "$CONFIG_SGI_IP22" != "y" ]; then - source drivers/message/i2o/Config.in + source drivers/i2o/Config.in fi if [ "$CONFIG_NET" = "y" ]; then @@ -492,9 +508,6 @@ comment 'Kernel hacking' bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE -fi if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_AU1000_UART" = "y" ]; then bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG dep_bool 'Console output to GDB' CONFIG_GDB_CONSOLE $CONFIG_REMOTE_DEBUG diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5074/pci.c linux/arch/mips/ddb5074/pci.c --- v2.4.9/linux/arch/mips/ddb5074/pci.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ddb5074/pci.c Sun Sep 9 10:43:01 2001 @@ -417,5 +417,9 @@ } } +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} struct pci_fixup pcibios_fixups[] = { }; diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5476/int-handler.S linux/arch/mips/ddb5476/int-handler.S --- v2.4.9/linux/arch/mips/ddb5476/int-handler.S Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ddb5476/int-handler.S Sun Sep 9 10:43:01 2001 @@ -68,6 +68,8 @@ and s0, s1, t2 # isolate allowed ones #endif /* First we check for r4k counter/timer IRQ. */ + andi a0, s0, CAUSEF_IP7 # cpu timer */ + bnez a0, cpu_timer_irq andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero beq a0, zero, 1f andi a0, s0, CAUSEF_IP3 # delay slot, check local level one @@ -119,6 +121,15 @@ /* phamtom interrupt */ move a0, s1 jal ddb_phantom_irq + nop + j ret_from_irq + nop + +cpu_timer_irq: + li a0, 0 + move a1, sp + jal do_IRQ + /* jal ll_timer_interrupt */ nop j ret_from_irq nop diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5476/pci.c linux/arch/mips/ddb5476/pci.c --- v2.4.9/linux/arch/mips/ddb5476/pci.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ddb5476/pci.c Sun Sep 9 10:43:01 2001 @@ -14,7 +14,6 @@ #include - static u32 nile4_pre_pci_access0(int slot_num) { u32 pci_addr = 0; @@ -490,6 +489,11 @@ start = (start + 1024 - 1) & ~(1024 - 1); res->start = start; } +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; } struct pci_fixup pcibios_fixups[] = { {0} }; diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5476/setup.c linux/arch/mips/ddb5476/setup.c --- v2.4.9/linux/arch/mips/ddb5476/setup.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ddb5476/setup.c Sun Sep 9 10:43:01 2001 @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef CONFIG_REMOTE_DEBUG @@ -71,13 +72,27 @@ extern void ddb_irq_setup(void); -void (*board_time_init) (struct irqaction * irq); - - static void __init ddb_time_init(struct irqaction *irq) { - /* set the clock to 1 Hz */ - nile4_out32(NILE4_T2CTRL, 1000000); + printk("ddb_time_init invoked.\n"); + mips_counter_frequency = 83000000; +} + +static void __init ddb_timer_setup(struct irqaction *irq) +{ + unsigned int count; + + /* we are using the cpu counter for timer interrupts */ + i8259_setup_irq(0, irq); + set_cp0_status(IE_IRQ5); + + /* to generate the first timer interrupt */ + count = read_32bit_cp0_register(CP0_COUNT); + write_32bit_cp0_register(CP0_COMPARE, count + 1000); + +#if 0 /* the old way to do timer interrupt */ + /* set the clock to 100 Hz */ + nile4_out32(NILE4_T2CTRL, 830000); /* enable the General-Purpose Timer */ nile4_out32(NILE4_T2CTRL + 4, 0x00000001); /* reset timer */ @@ -85,6 +100,7 @@ /* enable interrupt */ nile4_enable_irq(NILE4_INT_GPT); i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq); +#endif } static struct { @@ -119,7 +135,9 @@ irq_setup = ddb_irq_setup; mips_io_port_base = NILE4_PCI_IO_BASE; isa_slot_offset = NILE4_PCI_MEM_BASE; + board_time_init = ddb_time_init; + board_timer_setup = ddb_timer_setup; _machine_restart = ddb_machine_restart; _machine_halt = ddb_machine_halt; diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/common/Makefile linux/arch/mips/ddb5xxx/common/Makefile --- v2.4.9/linux/arch/mips/ddb5xxx/common/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/common/Makefile Sun Sep 9 10:43:01 2001 @@ -0,0 +1,18 @@ +# +# Makefile for the common code of NEC DDB-Vrc5xxx board +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET:= ddb5xxx.o + +obj-y += irq.o irq_cpu.o nile4.o prom.o pci.o pci_auto.o rtc_ds1386.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/common/irq.c linux/arch/mips/ddb5xxx/common/irq.c --- v2.4.9/linux/arch/mips/ddb5xxx/common/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/common/irq.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,32 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/common/irq.c + * Common irq code for DDB boards. This really should belong + * arch/mips/kernel/irq.c. Need to talk to Ralf. + * + * 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 + +void (*irq_setup)(void); + +void __init init_IRQ(void) +{ +#ifdef CONFIG_REMOTE_DEBUG + extern void breakpoint(void); + extern void set_debug_traps(void); + + printk("Wait for gdb client connection ...\n"); + set_debug_traps(); + breakpoint(); +#endif + + /* invoke board-specific irq setup */ + irq_setup(); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/common/irq_cpu.c linux/arch/mips/ddb5xxx/common/irq_cpu.c --- v2.4.9/linux/arch/mips/ddb5xxx/common/irq_cpu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/common/irq_cpu.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,115 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/common/irq_cpu.c + * This file define the irq handler for MIPS CPU interrupts. + * + * 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. + *********************************************************************** + */ + +/* + * Almost all MIPS CPUs define 8 interrupt sources. They are typically + * level triggered (i.e., cannot be cleared from CPU; must be cleared from + * device). The first two are software interrupts. The last one is + * usually cpu timer interrupt if coutner register is present. + * + * This file exports one global function: + * mips_cpu_irq_init(u32 irq_base); + */ + +#include +#include +#include + +#include + +/* [jsun] sooner or later we should move this debug stuff to MIPS common */ +#include + +static int mips_cpu_irq_base=-1; + +static void +mips_cpu_irq_enable(unsigned int irq) +{ + MIPS_ASSERT(mips_cpu_irq_base != -1); + MIPS_ASSERT(irq >= mips_cpu_irq_base); + MIPS_ASSERT(irq < mips_cpu_irq_base+8); + + clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8)); + set_cp0_status(1 << (irq - mips_cpu_irq_base + 8)); +} + +static void +mips_cpu_irq_disable(unsigned int irq) +{ + MIPS_ASSERT(mips_cpu_irq_base != -1); + MIPS_ASSERT(irq >= mips_cpu_irq_base); + MIPS_ASSERT(irq < mips_cpu_irq_base+8); + + clear_cp0_status(1 << (irq - mips_cpu_irq_base + 8)); +} + +static unsigned int mips_cpu_irq_startup(unsigned int irq) +{ + mips_cpu_irq_enable(irq); + return 0; +} + +#define mips_cpu_irq_shutdown mips_cpu_irq_disable + +static void +mips_cpu_irq_ack(unsigned int irq) +{ + MIPS_ASSERT(mips_cpu_irq_base != -1); + MIPS_ASSERT(irq >= mips_cpu_irq_base); + MIPS_ASSERT(irq < mips_cpu_irq_base+8); + + /* although we attemp to clear the IP bit in cause reigster, I think + * usually it is cleared by device (irq source) + */ + clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8)); + + /* I am not fully convinced that I should disable irq here */ +} + +static void +mips_cpu_irq_end(unsigned int irq) +{ + MIPS_ASSERT(mips_cpu_irq_base != -1); + MIPS_ASSERT(irq >= mips_cpu_irq_base); + MIPS_ASSERT(irq < mips_cpu_irq_base+8); + /* I am not fully convinced that I should enable irq here */ +} + +static hw_irq_controller mips_cpu_irq_controller = { + "CPU_irq", + mips_cpu_irq_startup, + mips_cpu_irq_shutdown, + mips_cpu_irq_enable, + mips_cpu_irq_disable, + mips_cpu_irq_ack, + mips_cpu_irq_end, + NULL /* no affinity stuff for UP */ +}; + + +void +mips_cpu_irq_init(u32 irq_base) +{ + extern irq_desc_t irq_desc[]; + u32 i; + + for (i= irq_base; i< irq_base+8; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &mips_cpu_irq_controller; + } + + mips_cpu_irq_base = irq_base; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/common/nile4.c linux/arch/mips/ddb5xxx/common/nile4.c --- v2.4.9/linux/arch/mips/ddb5xxx/common/nile4.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/common/nile4.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,135 @@ +/*********************************************************************** + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/common/nile4.c + * misc low-level routines for vrc-5xxx controllers. + * + * derived from original code by Geert Uytterhoeven + * + * 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 + +u32 +ddb_calc_pdar(u32 phys, u32 size, int width, + int on_memory_bus, int pci_visible) +{ + u32 maskbits; + u32 widthbits; + + switch (size) { +#if 0 /* We don't support 4 GB yet */ + case 0x100000000: /* 4 GB */ + maskbits = 4; + break; +#endif + case 0x80000000: /* 2 GB */ + maskbits = 5; + break; + case 0x40000000: /* 1 GB */ + maskbits = 6; + break; + case 0x20000000: /* 512 MB */ + maskbits = 7; + break; + case 0x10000000: /* 256 MB */ + maskbits = 8; + break; + case 0x08000000: /* 128 MB */ + maskbits = 9; + break; + case 0x04000000: /* 64 MB */ + maskbits = 10; + break; + case 0x02000000: /* 32 MB */ + maskbits = 11; + break; + case 0x01000000: /* 16 MB */ + maskbits = 12; + break; + case 0x00800000: /* 8 MB */ + maskbits = 13; + break; + case 0x00400000: /* 4 MB */ + maskbits = 14; + break; + case 0x00200000: /* 2 MB */ + maskbits = 15; + break; + case 0: /* OFF */ + maskbits = 0; + break; + default: + panic("nile4_set_pdar: unsupported size %p\n", (void *) size); + } + switch (width) { + case 8: + widthbits = 0; + break; + case 16: + widthbits = 1; + break; + case 32: + widthbits = 2; + break; + case 64: + widthbits = 3; + break; + default: + panic("nile4_set_pdar: unsupported width %d\n", width); + } + + return maskbits | (on_memory_bus ? 0x10 : 0) | + (pci_visible ? 0x20 : 0) | (widthbits << 6) | + (phys & 0xffe00000); +} + +void +ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width, + int on_memory_bus, int pci_visible) +{ + u32 temp= ddb_calc_pdar(phys, size, width, on_memory_bus, pci_visible); + ddb_out32(pdar, temp); + ddb_out32(pdar + 4, 0); + + /* + * When programming a PDAR, the register should be read immediately + * after writing it. This ensures that address decoders are properly + * configured. + * [jsun] is this really necesary? + */ + ddb_in32(pdar); + ddb_in32(pdar + 4); +} + +/* + * routines that mess with PCIINITx registers + */ + +void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options) +{ + switch (type) { + case DDB_PCICMD_IACK: /* PCI Interrupt Acknowledge */ + case DDB_PCICMD_IO: /* PCI I/O Space */ + case DDB_PCICMD_MEM: /* PCI Memory Space */ + case DDB_PCICMD_CFG: /* PCI Configuration Space */ + break; + default: + panic("nile4_set_pmr: invalid type %d\n", type); + } + ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options ); + ddb_out32(pmr + 4, 0); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/common/pci.c linux/arch/mips/ddb5xxx/common/pci.c --- v2.4.9/linux/arch/mips/ddb5xxx/common/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/common/pci.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,179 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/common/pci.c + * Common PCI routines for DDB5xxx - as a matter of fact, meant for all + * MIPS machines. + * + * 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 contains common PCI routines meant to be shared for + * all MIPS machines. + * + * Strategies: + * + * . We rely on pci_auto.c file to assign PCI resources (MEM and IO) + * TODO: this shold be optional for some machines where they do have + * a real "pcibios" that does resource assignment. + * + * . We then use pci_scan_bus() to "discover" all the resources for + * later use by Linux. + * + * . We finally reply on a board supplied function, pcibios_fixup_irq(), to + * to assign the interrupts. We may use setup-irq.c under drivers/pci + * later. + * + * . Specifically, we will *NOT* use pci_assign_unassigned_resources(), + * because we assume all PCI devices should have the resources correctly + * assigned and recorded. + * + * Limitations: + * + * . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus + * into a contiguous range. + * + * . In the case of Memory space, the rnage is 1:1 mapping with CPU physical + * address space. + * + * . In the case of IO space, it starts from 0, and the beginning address + * is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address. + * + * . These are the current MIPS limitations (by ioremap, etc). In the + * future, we may remove them. + * + * Credits: + * Most of the code are derived from the pci routines from PPC and Alpha, + * which were mostly writtne by + * Cort Dougan, cort@fsmlabs.com + * Matt Porter, mporter@mvista.com + * Dave Rusling david.rusling@reo.mts.dec.com + * David Mosberger davidm@cs.arizona.edu + */ + +#include +#include +#include +#include + +#include +#include + + +struct pci_fixup pcibios_fixups[] = { {0} }; + + +extern int pciauto_assign_resources(int busno, struct pci_channel * hose); +void __init pcibios_init(void) +{ + struct pci_channel *p; + struct pci_bus *bus; + int busno; + + /* assign resources */ + busno=0; + for (p= mips_pci_channels; p->pci_ops != NULL; p++) { + busno = pciauto_assign_resources(busno, p) + 1; + } + + /* scan the buses */ + busno = 0; + for (p= mips_pci_channels; p->pci_ops != NULL; p++) { + bus = pci_scan_bus(busno, p->pci_ops, p); + busno = bus->subordinate+1; + } + + /* fixup irqs (board specific routines) */ + pcibios_fixup_irqs(); + + /* + * should we do a fixup of ioport_resource and iomem_resource + * based on mips_pci_channels? + * Let us wait and see if this is a common need and whether there + * are exceptions. Until then, each board should adjust them + * perhaps in their setup() function. + */ +} + +int pcibios_enable_device(struct pci_dev *dev) +{ + /* pciauto_assign_resources() will enable all devices found */ + return 0; +} + +unsigned long __init +pci_bridge_check_io(struct pci_dev *bridge) +{ + u16 io; + + pci_read_config_word(bridge, PCI_IO_BASE, &io); + if (!io) { + pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); + pci_read_config_word(bridge, PCI_IO_BASE, &io); + pci_write_config_word(bridge, PCI_IO_BASE, 0x0); + } + if (io) + return IORESOURCE_IO; + printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", + bridge->name); + return 0; +} + +void __init pcibios_fixup_bus(struct pci_bus *bus) +{ + /* Propogate hose info into the subordinate devices. */ + + struct pci_channel *hose = bus->sysdata; + struct pci_dev *dev = bus->self; + + if (!dev) { + /* Root bus */ + bus->resource[0] = hose->io_resource; + bus->resource[1] = hose->mem_resource; + } else { + /* This is a bridge. Do not care how it's initialized, + just link its resources to the bus ones */ + int i; + + for(i=0; i<3; i++) { + bus->resource[i] = + &dev->resource[PCI_BRIDGE_RESOURCES+i]; + bus->resource[i]->name = bus->name; + } + bus->resource[0]->flags |= pci_bridge_check_io(dev); + bus->resource[1]->flags |= IORESOURCE_MEM; + /* For now, propogate hose limits to the bus; + we'll adjust them later. */ + bus->resource[0]->end = hose->io_resource->end; + bus->resource[1]->end = hose->mem_resource->end; + /* Turn off downstream PF memory address range by default */ + bus->resource[2]->start = 1024*1024; + bus->resource[2]->end = bus->resource[2]->start - 1; + } +} + +char *pcibios_setup(char *str) +{ + return str; +} + +void +pcibios_align_resource(void *data, struct resource *res, unsigned long size) +{ + /* this should not be called */ + MIPS_ASSERT(1 == 0); +} + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + /* this should not be called */ + MIPS_ASSERT(1 == 0); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/common/pci_auto.c linux/arch/mips/ddb5xxx/common/pci_auto.c --- v2.4.9/linux/arch/mips/ddb5xxx/common/pci_auto.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/common/pci_auto.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,396 @@ +/* + * arch/ppc/kernel/pci_auto.c + * + * PCI autoconfiguration library + * + * Author: Matt Porter + * + * Copyright 2000, 2001 MontaVista Software 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. + */ + +/* + * Modified for MIPS by Jun Sun, jsun@mvista.com + * + * . Simplify the interface between pci_auto and the rest: a single function. + * . Assign resources from low address to upper address. + * . change most int to u32. + */ + +#include +#include +#include +#include + +#include +#include + +#define DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* These are used for config access before all the PCI probing + has been done. */ +int early_read_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 *val); +int early_read_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 *val); +int early_read_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 *val); +int early_write_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 val); +int early_write_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 val); +int early_write_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 val); + +static u32 pciauto_lower_iospc; +static u32 pciauto_upper_iospc; + +static u32 pciauto_lower_memspc; +static u32 pciauto_upper_memspc; + +void __init +pciauto_setup_bars(struct pci_channel *hose, + int current_bus, + int pci_devfn) +{ + u32 bar_response, bar_size, bar_value; + u32 bar, addr_mask, bar_nr = 0; + u32 * upper_limit; + u32 * lower_limit; + int found_mem64 = 0; + + DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n", + current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) ); + + for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) + { + /* Tickle the BAR and get the response */ + early_write_config_dword(hose, + current_bus, + pci_devfn, + bar, + 0xffffffff); + early_read_config_dword(hose, + current_bus, + pci_devfn, + bar, + &bar_response); + + /* If BAR is not implemented go to the next BAR */ + if (!bar_response) + continue; + + /* Check the BAR type and set our address mask */ + if (bar_response & PCI_BASE_ADDRESS_SPACE) + { + addr_mask = PCI_BASE_ADDRESS_IO_MASK; + upper_limit = &pciauto_upper_iospc; + lower_limit = &pciauto_lower_iospc; + DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr); + } + else + { + if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64) + found_mem64 = 1; + + addr_mask = PCI_BASE_ADDRESS_MEM_MASK; + upper_limit = &pciauto_upper_memspc; + lower_limit = &pciauto_lower_memspc; + DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr); + } + + /* Calculate requested size */ + bar_size = ~(bar_response & addr_mask) + 1; + + /* Allocate a base address */ + bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; + MIPS_ASSERT(bar_value + bar_size <= *upper_limit); + + /* Write it out and update our limit */ + early_write_config_dword(hose, + current_bus, + pci_devfn, + bar, + bar_value); + + *lower_limit = bar_value + bar_size; + + /* + * If we are a 64-bit decoder then increment to the + * upper 32 bits of the bar and force it to locate + * in the lower 4GB of memory. + */ + if (found_mem64) + { + bar += 4; + early_write_config_dword(hose, + current_bus, + pci_devfn, + bar, + 0x00000000); + } + + bar_nr++; + + DBG("size=0x%x, address=0x%x\n", + bar_size, bar_value); + } + +} + +void __init +pciauto_prescan_setup_bridge(struct pci_channel *hose, + int current_bus, + int pci_devfn, + int sub_bus) +{ + int cmdstat; + + /* Configure bus number registers */ + early_write_config_byte(hose, + current_bus, + pci_devfn, + PCI_PRIMARY_BUS, + current_bus); + early_write_config_byte(hose, + current_bus, + pci_devfn, + PCI_SECONDARY_BUS, + sub_bus + 1); + early_write_config_byte(hose, + current_bus, + pci_devfn, + PCI_SUBORDINATE_BUS, + 0xff); + + /* Round memory allocator to 1MB boundary */ + pciauto_upper_memspc &= ~(0x100000 - 1); + + /* Round I/O allocator to 4KB boundary */ + pciauto_upper_iospc &= ~(0x1000 - 1); + + /* Set up memory and I/O filter limits, assume 32-bit I/O space */ + early_write_config_word(hose, + current_bus, + pci_devfn, + PCI_MEMORY_LIMIT, + ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16); + early_write_config_byte(hose, + current_bus, + pci_devfn, + PCI_IO_LIMIT, + ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8); + early_write_config_word(hose, + current_bus, + pci_devfn, + PCI_IO_LIMIT_UPPER16, + ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16); + + /* We don't support prefetchable memory for now, so disable */ + early_write_config_word(hose, + current_bus, + pci_devfn, + PCI_PREF_MEMORY_BASE, + 0x1000); + early_write_config_word(hose, + current_bus, + pci_devfn, + PCI_PREF_MEMORY_LIMIT, + 0x1000); + + /* Enable memory and I/O accesses, enable bus master */ + early_read_config_dword(hose, + current_bus, + pci_devfn, + PCI_COMMAND, + &cmdstat); + early_write_config_dword(hose, + current_bus, + pci_devfn, + PCI_COMMAND, + cmdstat | + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER); +} + +void __init +pciauto_postscan_setup_bridge(struct pci_channel *hose, + int current_bus, + int pci_devfn, + int sub_bus) +{ + /* Configure bus number registers */ + early_write_config_byte(hose, + current_bus, + pci_devfn, + PCI_SUBORDINATE_BUS, + sub_bus); + + /* Round memory allocator to 1MB boundary */ + pciauto_upper_memspc &= ~(0x100000 - 1); + early_write_config_word(hose, + current_bus, + pci_devfn, + PCI_MEMORY_BASE, + pciauto_upper_memspc >> 16); + + /* Round I/O allocator to 4KB boundary */ + pciauto_upper_iospc &= ~(0x1000 - 1); + early_write_config_byte(hose, + current_bus, + pci_devfn, + PCI_IO_BASE, + (pciauto_upper_iospc & 0x0000f000) >> 8); + early_write_config_word(hose, + current_bus, + pci_devfn, + PCI_IO_BASE_UPPER16, + pciauto_upper_iospc >> 16); +} + +#define PCIAUTO_IDE_MODE_MASK 0x05 + +int __init +pciauto_bus_scan(struct pci_channel *hose, int current_bus) +{ + int sub_bus; + u32 pci_devfn, pci_class, cmdstat, found_multi=0; + unsigned short vid; + unsigned char header_type; + + sub_bus = current_bus; + + for (pci_devfn=0; pci_devfn<0xff; pci_devfn++) { + + if (PCI_FUNC(pci_devfn) && !found_multi) + continue; + + early_read_config_byte(hose, + current_bus, + pci_devfn, + PCI_HEADER_TYPE, + &header_type); + + if (!PCI_FUNC(pci_devfn)) + found_multi = header_type & 0x80; + + early_read_config_word(hose, + current_bus, + pci_devfn, + PCI_VENDOR_ID, + &vid); + + if (vid == 0xffff) continue; + + early_read_config_dword(hose, + current_bus, + pci_devfn, + PCI_CLASS_REVISION, &pci_class); + if ( (pci_class >> 16) == PCI_CLASS_BRIDGE_PCI ) { + DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn)); + pciauto_prescan_setup_bridge(hose, + current_bus, + pci_devfn, + sub_bus); + sub_bus = pciauto_bus_scan(hose, sub_bus+1); + pciauto_postscan_setup_bridge(hose, + current_bus, + pci_devfn, + sub_bus); + + } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { + + unsigned char prg_iface; + + early_read_config_byte(hose, + current_bus, + pci_devfn, + PCI_CLASS_PROG, + &prg_iface); + if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { + DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n"); + continue; + } + } + + /* + * Found a peripheral, enable some standard + * settings + */ + early_read_config_dword(hose, + current_bus, + pci_devfn, + PCI_COMMAND, + &cmdstat); + early_write_config_dword(hose, + current_bus, + pci_devfn, + PCI_COMMAND, + cmdstat | + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER); + early_write_config_byte(hose, + current_bus, + pci_devfn, + PCI_LATENCY_TIMER, + 0x80); + + /* Allocate PCI I/O and/or memory space */ + pciauto_setup_bars(hose, + current_bus, + pci_devfn); + } + return sub_bus; +} + +int __init +pciauto_assign_resources(int busno, struct pci_channel *hose) +{ + /* setup resource limits */ + pciauto_lower_iospc = hose->io_resource->start; + pciauto_upper_iospc = hose->io_resource->end + 1; + pciauto_lower_memspc = hose->mem_resource->start; + pciauto_upper_memspc = hose->mem_resource->end + 1; + + return pciauto_bus_scan(hose, busno); +} + + +/* + * These functions are used early on before PCI scanning is done + * and all of the pci_dev and pci_bus structures have been created. + */ +static struct pci_dev * +fake_pci_dev(struct pci_channel *hose, int busnr, int devfn) +{ + static struct pci_dev dev; + static struct pci_bus bus; + + dev.bus = &bus; + dev.sysdata = hose; + dev.devfn = devfn; + bus.number = busnr; + bus.ops = hose->pci_ops; + return &dev; +} + +#define EARLY_PCI_OP(rw, size, type) \ +int early_##rw##_config_##size(struct pci_channel *hose, int bus, \ + int devfn, int offset, type value) \ +{ \ + return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \ + offset, value); \ +} + +EARLY_PCI_OP(read, byte, u8 *) +EARLY_PCI_OP(read, word, u16 *) +EARLY_PCI_OP(read, dword, u32 *) +EARLY_PCI_OP(write, byte, u8) +EARLY_PCI_OP(write, word, u16) +EARLY_PCI_OP(write, dword, u32) diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/common/prom.c linux/arch/mips/ddb5xxx/common/prom.c --- v2.4.9/linux/arch/mips/ddb5xxx/common/prom.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/common/prom.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,58 @@ +/*********************************************************************** + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/common/prom.c + * prom.c file. + * + * 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 + +char arcs_cmdline[COMMAND_LINE_SIZE]; + +/* [jsun@junsun.net] PMON passes arguments in C main() style */ +void __init prom_init(int argc, const char **arg) +{ + int i; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_DDB; + +#if defined(CONFIG_DDB5074) + mips_machtype = MACH_NEC_DDB5074; +#elif defined(CONFIG_DDB5476) + mips_machtype = MACH_NEC_DDB5476; +#elif defined(CONFIG_DDB5477) + mips_machtype = MACH_NEC_DDB5477; +#endif + + add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/common/rtc_ds1386.c linux/arch/mips/ddb5xxx/common/rtc_ds1386.c --- v2.4.9/linux/arch/mips/ddb5xxx/common/rtc_ds1386.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/common/rtc_ds1386.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,167 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/common/rtc_ds1386.c + * low-level RTC hookups for s for Dallas 1396 chip. + * + * 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 exports a function, rtc_ds1386_init(), which expects an + * uncached base address as the argument. It will set the two function + * pointers expected by the MIPS generic timer code. + */ + +#include +#include + +#include +#include + +#include + +#define EPOCH 2000 + +#undef BCD_TO_BIN +#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) + +#undef BIN_TO_BCD +#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) + +#define READ_RTC(x) *(volatile unsigned char*)(rtc_base+x) +#define WRITE_RTC(x, y) *(volatile unsigned char*)(rtc_base+x) = y + +static unsigned long rtc_base; + +static unsigned long +rtc_ds1386_get_time(void) +{ + u8 byte; + u8 temp; + unsigned int year, month, day, hour, minute, second; + + /* let us freeze external registers */ + byte = READ_RTC(0xB); + byte &= 0x3f; + WRITE_RTC(0xB, byte); + + /* read time data */ + year = BCD_TO_BIN(READ_RTC(0xA)) + EPOCH; + month = BCD_TO_BIN(READ_RTC(0x9) & 0x1f); + day = BCD_TO_BIN(READ_RTC(0x8)); + minute = BCD_TO_BIN(READ_RTC(0x2)); + second = BCD_TO_BIN(READ_RTC(0x1)); + + /* hour is special - deal with it later */ + temp = READ_RTC(0x4); + + /* enable time transfer */ + byte |= 0x80; + WRITE_RTC(0xB, byte); + + /* calc hour */ + if (temp & 0x40) { + /* 12 hour format */ + hour = BCD_TO_BIN(temp & 0x1f); + if (temp & 0x20) hour += 12; /* PM */ + } else { + /* 24 hour format */ + hour = BCD_TO_BIN(temp & 0x3f); + } + + return mktime(year, month, day, hour, minute, second); +} + +static int +rtc_ds1386_set_time(unsigned long t) +{ + struct rtc_time tm; + u8 byte; + u8 temp; + u8 year, month, day, hour, minute, second; + + /* let us freeze external registers */ + byte = READ_RTC(0xB); + byte &= 0x3f; + WRITE_RTC(0xB, byte); + + /* convert */ + to_tm(t, &tm); + + /* check each field one by one */ + year = BIN_TO_BCD(tm.tm_year - EPOCH); + if (year != READ_RTC(0xA)) { + WRITE_RTC(0xA, year); + } + + temp = READ_RTC(0x9); + month = BIN_TO_BCD(tm.tm_mon); + if (month != (temp & 0x1f)) { + WRITE_RTC( 0x9, + (month & 0x1f) | (temp & ~0x1f) ); + } + + day = BIN_TO_BCD(tm.tm_mday); + if (day != READ_RTC(0x8)) { + WRITE_RTC(0x8, day); + } + + temp = READ_RTC(0x4); + if (temp & 0x40) { + /* 12 hour format */ + hour = 0x40; + if (tm.tm_hour > 12) { + hour |= 0x20 | (BIN_TO_BCD(hour-12) & 0x1f); + } else { + hour |= BIN_TO_BCD(tm.tm_hour); + } + } else { + /* 24 hour format */ + hour = BIN_TO_BCD(tm.tm_hour) & 0x3f; + } + if (hour != temp) WRITE_RTC(0x4, hour); + + minute = BIN_TO_BCD(tm.tm_min); + if (minute != READ_RTC(0x2)) { + WRITE_RTC(0x2, minute); + } + + second = BIN_TO_BCD(tm.tm_sec); + if (second != READ_RTC(0x1)) { + WRITE_RTC(0x1, second); + } + + return 0; +} + +void +rtc_ds1386_init(unsigned long base) +{ + unsigned char byte; + + /* remember the base */ + rtc_base = base; + MIPS_ASSERT((rtc_base & 0xe0000000) == KSEG1); + + /* turn on RTC if it is not on */ + byte = READ_RTC(0x9); + if (byte & 0x80) { + byte &= 0x7f; + WRITE_RTC(0x9, byte); + } + + /* enable time transfer */ + byte = READ_RTC(0xB); + byte |= 0x80; + WRITE_RTC(0xB, byte); + + /* set the function pointers */ + rtc_get_time = rtc_ds1386_get_time; + rtc_set_time = rtc_ds1386_set_time; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/Makefile linux/arch/mips/ddb5xxx/ddb5477/Makefile --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/Makefile Sun Sep 9 10:43:01 2001 @@ -0,0 +1,22 @@ +# +# Makefile for NEC DDB-Vrc5477 board +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET:= ddb5477.o + +obj-y += int-handler.o irq.o irq_5477.o setup.o pci.o pci_ops.o + +obj-$(CONFIG_LL_DEBUG) += debug.o +obj-$(CONFIG_REMOTE_DEBUG) += kgdb_io.o +obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/debug.c linux/arch/mips/ddb5xxx/ddb5477/debug.c --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/debug.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/debug.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,162 @@ +/*********************************************************************** + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/ddb5477/debug.c + * vrc5477 specific debug routines. + * + * 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 /* SA_INTERRUPT */ + +#include +#include + +typedef struct { + const char *regname; + unsigned regaddr; +} Register; + +void jsun_show_regs(char *name, Register *regs) +{ + int i; + + printk("\nshow regs: %s\n", name); + for(i=0;regs[i].regname!= NULL; i++) { + printk("%-16s= %08x\t\t(@%08x)\n", + regs[i].regname, + *(unsigned *)(regs[i].regaddr), + regs[i].regaddr); + } +} + +static Register int_regs[] = { + {"DDB_INTCTRL0", DDB_BASE + DDB_INTCTRL0}, + {"DDB_INTCTRL1", DDB_BASE + DDB_INTCTRL1}, + {"DDB_INTCTRL2", DDB_BASE + DDB_INTCTRL2}, + {"DDB_INTCTRL3", DDB_BASE + DDB_INTCTRL3}, + {"DDB_INT0STAT", DDB_BASE + DDB_INT0STAT}, + {"DDB_INT1STAT", DDB_BASE + DDB_INT1STAT}, + {"DDB_INT2STAT", DDB_BASE + DDB_INT2STAT}, + {"DDB_INT3STAT", DDB_BASE + DDB_INT3STAT}, + {"DDB_INT4STAT", DDB_BASE + DDB_INT4STAT}, + {"DDB_NMISTAT", DDB_BASE + DDB_NMISTAT}, + {"DDB_INTPPES0", DDB_BASE + DDB_INTPPES0}, + {"DDB_INTPPES1", DDB_BASE + DDB_INTPPES1}, + {NULL, 0x0} +}; + +void vrc5477_show_int_regs() +{ + jsun_show_regs("interrupt registers", int_regs); + printk("CPU CAUSE = %08x\n", read_32bit_cp0_register(CP0_CAUSE)); + printk("CPU STATUS = %08x\n", read_32bit_cp0_register(CP0_STATUS)); +} +static Register pdar_regs[] = { + {"DDB_SDRAM0", DDB_BASE + DDB_SDRAM0}, + {"DDB_SDRAM1", DDB_BASE + DDB_SDRAM1}, + {"DDB_LDCS0", DDB_BASE + DDB_LDCS0}, + {"DDB_LDCS1", DDB_BASE + DDB_LDCS1}, + {"DDB_LDCS2", DDB_BASE + DDB_LDCS2}, + {"DDB_INTCS", DDB_BASE + DDB_INTCS}, + {"DDB_BOOTCS", DDB_BASE + DDB_BOOTCS}, + {"DDB_PCIW0", DDB_BASE + DDB_PCIW0}, + {"DDB_PCIW1", DDB_BASE + DDB_PCIW1}, + {"DDB_IOPCIW0", DDB_BASE + DDB_IOPCIW0}, + {"DDB_IOPCIW1", DDB_BASE + DDB_IOPCIW1}, + {NULL, 0x0} +}; +void vrc5477_show_pdar_regs(void) +{ + jsun_show_regs("PDAR regs", pdar_regs); +} + +static Register bar_regs[] = { + {"DDB_BARC0", DDB_BASE + DDB_BARC0}, + {"DDB_BARM010", DDB_BASE + DDB_BARM010}, + {"DDB_BARM230", DDB_BASE + DDB_BARM230}, + {"DDB_BAR00", DDB_BASE + DDB_BAR00}, + {"DDB_BAR10", DDB_BASE + DDB_BAR10}, + {"DDB_BAR20", DDB_BASE + DDB_BAR20}, + {"DDB_BAR30", DDB_BASE + DDB_BAR30}, + {"DDB_BAR40", DDB_BASE + DDB_BAR40}, + {"DDB_BAR50", DDB_BASE + DDB_BAR50}, + {"DDB_BARB0", DDB_BASE + DDB_BARB0}, + {"DDB_BARC1", DDB_BASE + DDB_BARC1}, + {"DDB_BARM011", DDB_BASE + DDB_BARM011}, + {"DDB_BARM231", DDB_BASE + DDB_BARM231}, + {"DDB_BAR01", DDB_BASE + DDB_BAR01}, + {"DDB_BAR11", DDB_BASE + DDB_BAR11}, + {"DDB_BAR21", DDB_BASE + DDB_BAR21}, + {"DDB_BAR31", DDB_BASE + DDB_BAR31}, + {"DDB_BAR41", DDB_BASE + DDB_BAR41}, + {"DDB_BAR51", DDB_BASE + DDB_BAR51}, + {"DDB_BARB1", DDB_BASE + DDB_BARB1}, + {NULL, 0x0} +}; +void vrc5477_show_bar_regs(void) +{ + jsun_show_regs("BAR regs", bar_regs); +} + +static Register pci_regs[] = { + {"DDB_PCIW0", DDB_BASE + DDB_PCIW0}, + {"DDB_PCIW1", DDB_BASE + DDB_PCIW1}, + {"DDB_PCIINIT00", DDB_BASE + DDB_PCIINIT00}, + {"DDB_PCIINIT10", DDB_BASE + DDB_PCIINIT10}, + {"DDB_PCICTL0_L", DDB_BASE + DDB_PCICTL0_L}, + {"DDB_PCICTL0_H", DDB_BASE + DDB_PCICTL0_H}, + {"DDB_PCIARB0_L", DDB_BASE + DDB_PCIARB0_L}, + {"DDB_PCIARB0_H", DDB_BASE + DDB_PCIARB0_H}, + {"DDB_PCISWP0", DDB_BASE + DDB_PCISWP0}, + {"DDB_PCIERR0", DDB_BASE + DDB_PCIERR0}, + {"DDB_IOPCIW0", DDB_BASE + DDB_IOPCIW0}, + {"DDB_IOPCIW1", DDB_BASE + DDB_IOPCIW1}, + {"DDB_PCIINIT01", DDB_BASE + DDB_PCIINIT01}, + {"DDB_PCIINIT11", DDB_BASE + DDB_PCIINIT11}, + {"DDB_PCICTL1_L", DDB_BASE + DDB_PCICTL1_L}, + {"DDB_PCICTL1_H", DDB_BASE + DDB_PCICTL1_H}, + {"DDB_PCIARB1_L", DDB_BASE + DDB_PCIARB1_L}, + {"DDB_PCIARB1_H", DDB_BASE + DDB_PCIARB1_H}, + {"DDB_PCISWP1", DDB_BASE + DDB_PCISWP1}, + {"DDB_PCIERR1", DDB_BASE + DDB_PCIERR1}, + {NULL, 0x0} +}; +void vrc5477_show_pci_regs(void) +{ + jsun_show_regs("PCI regs", pci_regs); +} + +static Register lb_regs[] = { + {"DDB_LCNFG", DDB_BASE + DDB_LCNFG}, + {"DDB_LCST0", DDB_BASE + DDB_LCST0}, + {"DDB_LCST1", DDB_BASE + DDB_LCST1}, + {"DDB_LCST2", DDB_BASE + DDB_LCST2}, + {"DDB_ERRADR", DDB_BASE + DDB_ERRADR}, + {"DDB_ERRCS", DDB_BASE + DDB_ERRCS}, + {"DDB_BTM", DDB_BASE + DDB_BTM}, + {"DDB_BCST", DDB_BASE + DDB_BCST}, + {NULL, 0x0} +}; +void vrc5477_show_lb_regs(void) +{ + jsun_show_regs("Local Bus regs", lb_regs); +} + +void vrc5477_show_all_regs(void) +{ + vrc5477_show_pdar_regs(); + vrc5477_show_pci_regs(); + vrc5477_show_bar_regs(); + vrc5477_show_int_regs(); + vrc5477_show_lb_regs(); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/int-handler.S linux/arch/mips/ddb5xxx/ddb5477/int-handler.S --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/int-handler.S Sun Sep 9 10:43:01 2001 @@ -0,0 +1,76 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * First-level interrupt dispatcher for ddb5477 + * + * 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 + +/* + * first level interrupt dispatcher for ocelot board - + * We check for the timer first, then check PCI ints A and D. + * Then check for serial IRQ and fall through. + */ + .align 5 + NESTED(ddb5477_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + .set noreorder + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq + andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 ) + bnez t1, ll_vrc5477_irq + andi t1, t0, STATUSF_IP0 /* software int 0 */ + bnez t1, ll_cpu_ip0 + andi t1, t0, STATUSF_IP1 /* software int 1 */ + bnez t1, ll_cpu_ip1 + nop + .set reorder + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(ddb5477_handle_int) + + .align 5 + +ll_vrc5477_irq: + move a0, sp + jal vrc5477_irq_dispatch + j ret_from_irq + +ll_cputimer_irq: + li a0, 7 + move a1, sp + jal do_IRQ + j ret_from_irq + + +ll_cpu_ip0: + li a0, 0 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip1: + li a0, 1 + move a1, sp + jal do_IRQ + j ret_from_irq diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/irq.c linux/arch/mips/ddb5xxx/ddb5477/irq.c --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/irq.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,163 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/ddb5477/irq.c + * The irq setup and misc routines for DDB5476. + * + * 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 + +/* [jsun] sooner or later we should move this debug stuff to MIPS common */ +#include + +/* + * IRQ mapping + * + * 0-7: 8 CPU interrupts + * 0 - software interrupt 0 + * 1 - software interrupt 1 + * 2 - most Vrc5477 interrupts are routed to this pin + * 3 - (optional) some other interrupts routed to this pin for debugg + * 4 - not used + * 5 - not used + * 6 - not used + * 7 - cpu timer (used by default) + * + * 8-39: 32 Vrc5477 interrupt sources + * (refer to the Vrc5477 manual) + */ + +#define PCI0 DDB_INTPPES0 +#define PCI1 DDB_INTPPES1 + +#define ACTIVE_LOW 1 +#define ACTIVE_HIGH 0 + +#define LEVEL_SENSE 2 +#define EDGE_TRIGGER 0 + +#define INTA 0 +#define INTB 1 +#define INTC 2 +#define INTD 3 +#define INTE 4 + +static inline void +set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger) +{ + u32 reg_value; + u32 reg_bitmask; + + reg_value = ddb_in32(pci); + reg_bitmask = 0x3 << (intn * 2); + + reg_value &= ~reg_bitmask; + reg_value |= (active | trigger) << (intn * 2); + ddb_out32(pci, reg_value); +} + +extern void vrc5477_irq_init(u32 base); +extern void mips_cpu_irq_init(u32 base); +extern asmlinkage void ddb5477_handle_int(void); + +void +ddb5477_irq_setup(void) +{ + MIPS_DEBUG(printk("ddb5477_irq_setup invoked.\n")); + + /* by default, we disable all interrupts and route all vrc5477 + * interrupts to pin 0 (irq 2) */ + ddb_out32(DDB_INTCTRL0, 0); + ddb_out32(DDB_INTCTRL1, 0); + ddb_out32(DDB_INTCTRL2, 0); + ddb_out32(DDB_INTCTRL3, 0); + + clear_cp0_status(0xff00); + set_cp0_status(0x0400); + + /* setup PCI interrupt attributes */ + set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE); + set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE); + set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE); + set_pci_int_attr(PCI0, INTD, ACTIVE_LOW, LEVEL_SENSE); + set_pci_int_attr(PCI0, INTE, ACTIVE_LOW, LEVEL_SENSE); + + set_pci_int_attr(PCI1, INTA, ACTIVE_LOW, LEVEL_SENSE); + set_pci_int_attr(PCI1, INTB, ACTIVE_LOW, LEVEL_SENSE); + set_pci_int_attr(PCI1, INTC, ACTIVE_LOW, LEVEL_SENSE); + set_pci_int_attr(PCI1, INTD, ACTIVE_LOW, LEVEL_SENSE); + set_pci_int_attr(PCI1, INTE, ACTIVE_LOW, LEVEL_SENSE); + + /* + * for debugging purpose, we enable several error interrupts + * and route them to pin 1. (IP3) + */ + /* cpu parity check - 0 */ + ll_vrc5477_irq_route(0, 1); ll_vrc5477_irq_enable(0); + /* cpu no-target decode - 1 */ + ll_vrc5477_irq_route(1, 1); ll_vrc5477_irq_enable(1); + /* local bus read time-out - 7 */ + ll_vrc5477_irq_route(7, 1); ll_vrc5477_irq_enable(7); + /* PCI SERR# - 14 */ + ll_vrc5477_irq_route(14, 1); ll_vrc5477_irq_enable(14); + /* PCI internal error - 15 */ + ll_vrc5477_irq_route(15, 1); ll_vrc5477_irq_enable(15); + /* IOPCI SERR# - 30 */ + ll_vrc5477_irq_route(30, 1); ll_vrc5477_irq_enable(30); + /* IOPCI internal error - 31 */ + ll_vrc5477_irq_route(31, 1); ll_vrc5477_irq_enable(31); + + /* init all controllers */ + mips_cpu_irq_init(0); + vrc5477_irq_init(8); + + /* hook up the first-level interrupt handler */ + set_except_vector(0, ddb5477_handle_int); +} + +/* + * the first level int-handler will jump here if it is a vrc5477 irq + */ +#define NUM_5477_IRQS 32 +asmlinkage void +vrc5477_irq_dispatch(struct pt_regs *regs) +{ + extern unsigned int do_IRQ(int irq, struct pt_regs *regs); + + u32 intStatus; + u32 bitmask; + u32 i; + + MIPS_ASSERT(ddb_in32(DDB_INT2STAT) == 0); + MIPS_ASSERT(ddb_in32(DDB_INT3STAT) == 0); + MIPS_ASSERT(ddb_in32(DDB_INT4STAT) == 0); + MIPS_ASSERT(ddb_in32(DDB_NMISTAT) == 0); + + if (ddb_in32(DDB_INT1STAT) != 0) { +#if defined(CONFIG_LL_DEBUG) + vrc5477_show_int_regs(); +#endif + panic("error interrupt has happened.\n"); + } + + intStatus = ddb_in32(DDB_INT0STAT); + for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) { + /* do we need to "and" with the int mask? */ + if (intStatus & bitmask) { + do_IRQ(8 + i, regs); + } + } +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/irq_5477.c linux/arch/mips/ddb5xxx/ddb5477/irq_5477.c --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/irq_5477.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/irq_5477.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,179 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/ddb5477/irq_5477.c + * This file defines the irq handler for Vrc5477. + * + * 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. + *********************************************************************** + */ + +/* + * Vrc5477 defines 32 IRQs. + * + * This file exports one function: + * vrc5477_irq_init(u32 irq_base); + */ + +#include +#include +#include + +#include + +/* [jsun] sooner or later we should move this debug stuff to MIPS common */ +#include + +/* number of total irqs supported by Vrc5477 */ +#define NUM_5477_IRQ 32 + +static int vrc5477_irq_base=-1; + + +static void +vrc5477_irq_enable(unsigned int irq) +{ + MIPS_ASSERT(vrc5477_irq_base != -1); + MIPS_ASSERT(irq >= vrc5477_irq_base); + MIPS_ASSERT(irq < vrc5477_irq_base+ NUM_5477_IRQ); + + ll_vrc5477_irq_enable(irq - vrc5477_irq_base); +} + +static void +vrc5477_irq_disable(unsigned int irq) +{ + MIPS_ASSERT(vrc5477_irq_base != -1); + MIPS_ASSERT(irq >= vrc5477_irq_base); + MIPS_ASSERT(irq < vrc5477_irq_base + NUM_5477_IRQ); + + ll_vrc5477_irq_disable(irq - vrc5477_irq_base); +} + +static unsigned int vrc5477_irq_startup(unsigned int irq) +{ + vrc5477_irq_enable(irq); + return 0; +} + +#define vrc5477_irq_shutdown vrc5477_irq_disable + +static void +vrc5477_irq_ack(unsigned int irq) +{ + MIPS_ASSERT(vrc5477_irq_base != -1); + MIPS_ASSERT(irq >= vrc5477_irq_base); + MIPS_ASSERT(irq < vrc5477_irq_base+ NUM_5477_IRQ); + + /* clear the interrupt bit */ + /* some irqs require the driver to clear the sources */ + ddb_out32(DDB_INTCLR32, 1 << (irq - vrc5477_irq_base)); + + /* disable interrupt - some handler will re-enable the irq + * and if the interrupt is leveled, we will have infinite loop + */ + ll_vrc5477_irq_disable(irq - vrc5477_irq_base); +} + +static void +vrc5477_irq_end(unsigned int irq) +{ + MIPS_ASSERT(vrc5477_irq_base != -1); + MIPS_ASSERT(irq >= vrc5477_irq_base); + MIPS_ASSERT(irq < vrc5477_irq_base + NUM_5477_IRQ); + + ll_vrc5477_irq_enable( irq - vrc5477_irq_base); +} + +hw_irq_controller vrc5477_irq_controller = { + "vrc5477_irq", + vrc5477_irq_startup, + vrc5477_irq_shutdown, + vrc5477_irq_enable, + vrc5477_irq_disable, + vrc5477_irq_ack, + vrc5477_irq_end, + NULL /* no affinity stuff for UP */ +}; + +void +vrc5477_irq_init(u32 irq_base) +{ + extern irq_desc_t irq_desc[]; + u32 i; + + for (i= irq_base; i< irq_base+ NUM_5477_IRQ; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &vrc5477_irq_controller; + } + + vrc5477_irq_base = irq_base; +} + + +int vrc5477_irq_to_irq(int irq) +{ + MIPS_ASSERT(irq >= 0); + MIPS_ASSERT(irq < NUM_5477_IRQ); + + return irq + vrc5477_irq_base; +} + +void ll_vrc5477_irq_route(int vrc5477_irq, int ip) +{ + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + MIPS_ASSERT(vrc5477_irq >= 0); + MIPS_ASSERT(vrc5477_irq < NUM_5477_IRQ); + MIPS_ASSERT(ip >= 0); + MIPS_ASSERT((ip < 5) || (ip == 6)); + + reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; + reg_value = ddb_in32(reg_index); + reg_bitmask = 7 << (vrc5477_irq % 8 * 4); + reg_value &= ~reg_bitmask; + reg_value |= ip << (vrc5477_irq % 8 * 4); + ddb_out32(reg_index, reg_value); +} + +void ll_vrc5477_irq_enable(int vrc5477_irq) +{ + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + MIPS_ASSERT(vrc5477_irq >= 0); + MIPS_ASSERT(vrc5477_irq < NUM_5477_IRQ); + + reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; + reg_value = ddb_in32(reg_index); + reg_bitmask = 8 << (vrc5477_irq % 8 * 4); + MIPS_ASSERT((reg_value & reg_bitmask) == 0); + ddb_out32(reg_index, reg_value | reg_bitmask); +} + +void ll_vrc5477_irq_disable(int vrc5477_irq) +{ + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + MIPS_ASSERT(vrc5477_irq >= 0); + MIPS_ASSERT(vrc5477_irq < NUM_5477_IRQ); + + reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; + reg_value = ddb_in32(reg_index); + reg_bitmask = 8 << (vrc5477_irq % 8 * 4); + + /* we assert that the interrupt is enabled (perhaps over-zealous) */ + MIPS_ASSERT( (reg_value & reg_bitmask) != 0); + ddb_out32(reg_index, reg_value & ~reg_bitmask); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/kgdb_io.c linux/arch/mips/ddb5xxx/ddb5477/kgdb_io.c --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/kgdb_io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/kgdb_io.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,142 @@ + +#include + +#if (defined(CONFIG_DDB5477) && defined(CONFIG_REMOTE_DEBUG)) + +/* --- CONFIG --- */ + +/* we need uint32 uint8 */ +/* #include "types.h" */ +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE 0xbfa04240 +#define MAX_BAUD 115200 +#define REG_OFFSET 8 + +/* === END OF CONFIG === */ + +/* register offset */ +#define OFS_RCV_BUFFER (0*REG_OFFSET) +#define OFS_TRANS_HOLD (0*REG_OFFSET) +#define OFS_SEND_BUFFER (0*REG_OFFSET) +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +int debug_state = -1; + +uint8 getDebugChar(void) +{ + uint8 c; + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_38400, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + c= UART16550_READ(OFS_RCV_BUFFER); +/* + if (state != 1) { + state = 1; + debug_out("\ngetDebugChar: ", 15); + } + debug_out(&c, 1); +*/ + return c; +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_9600, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + if (debug_state != 2) { + debug_state = 2; + // debug_out("\nputDebugChar: ", 15); + } + // debug_out(&byte, 1); + return 1; +} + +#endif diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/pci.c linux/arch/mips/ddb5xxx/ddb5477/pci.c --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/pci.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,147 @@ +#include +#include +#include +#include + +#include +#include +#include + +static struct resource extpci_io_resource = { + "ext pci IO space", + DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE, + DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE -1, + IORESOURCE_IO}; + +static struct resource extpci_mem_resource = { + "ext pci memory space", + DDB_PCI0_MEM_BASE, + DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE -1, + IORESOURCE_MEM}; + +static struct resource iopci_io_resource = { + "io pci IO space", + DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE, + DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE -1, + IORESOURCE_IO}; + +static struct resource iopci_mem_resource = { + "ext pci memory space", + DDB_PCI1_MEM_BASE, + DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE -1, + IORESOURCE_MEM}; + +extern struct pci_ops ddb5477_ext_pci_ops; +extern struct pci_ops ddb5477_io_pci_ops; + +struct pci_channel mips_pci_channels[] = { + { &ddb5477_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource }, + { &ddb5477_io_pci_ops, &iopci_io_resource, &iopci_mem_resource }, + { NULL, NULL, NULL} +}; + + +/* + * we fix up irqs based on the slot number. + * The first entry is at AD:11. + * Fortunately this works because, although we have two pci buses, + * they all have different slot numbers. + * + * This does not work for devices on sub-buses. + * + * Note that the irq number in the array is relative number in vrc5477. + * We need to translate it to global irq number. + */ + +/* + * irq mapping : PCI int # -> vrc5477 irq # + * based on vrc5477 manual page 46 + */ +#define PCI_EXT_INTA 8 +#define PCI_EXT_INTB 9 +#define PCI_EXT_INTC 10 +#define PCI_EXT_INTD 11 +#define PCI_EXT_INTE 12 + +#define PCI_IO_INTA 16 +#define PCI_IO_INTB 17 +#define PCI_IO_INTC 18 +#define PCI_IO_INTD 19 + +/* + * irq mapping : device -> pci int #, + * ddb5477 board manual page 4 and vrc5477 manual page 46 + */ +#define INT_ONBOARD_TULIP PCI_EXT_INTA +#define INT_SLOT1 PCI_EXT_INTB +#define INT_SLOT2 PCI_EXT_INTC +#define INT_SLOT3 PCI_EXT_INTD +#define INT_SLOT4 PCI_EXT_INTE + +#define INT_USB_HOST PCI_IO_INTA +#define INT_USB_PERI PCI_IO_INTB +#define INT_AC97 PCI_IO_INTC + +/* + * based on ddb5477 manual page 11 + */ +#define MAX_SLOT_NUM 21 +static unsigned char irq_map[MAX_SLOT_NUM] = { + /* AD:11 */ 0xff, 0xff, 0xff, 0xff, + /* AD:15 */ INT_ONBOARD_TULIP, INT_SLOT1, INT_SLOT2, INT_SLOT3, + /* AD:19 */ INT_SLOT4, 0xff, 0xff, 0xff, + /* AD:23 */ 0xff, 0xff, 0xff, 0xff, + /* AD:27 */ 0xff, 0xff, INT_AC97, INT_USB_PERI, + /* AD:31 */ INT_USB_HOST +}; + +extern int vrc5477_irq_to_irq(int irq); +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev; + int slot_num; + + pci_for_each_dev(dev) { + slot_num = PCI_SLOT(dev->devfn); + MIPS_ASSERT(slot_num < MAX_SLOT_NUM); + MIPS_ASSERT(irq_map[slot_num] != 0xff); + + pci_write_config_byte(dev, + PCI_INTERRUPT_LINE, + irq_map[slot_num]); + dev->irq = vrc5477_irq_to_irq(irq_map[slot_num]); + } +} + +#if defined(CONFIG_LL_DEBUG) +extern void jsun_scan_pci_bus(void); +extern void jsun_assign_pci_resource(void); +#endif +void __init ddb_pci_reset_bus(void) +{ + u32 temp; + + /* + * I am not sure about the "official" procedure, the following + * steps work as far as I know: + * We first set PCI cold reset bit (bit 31) in PCICTRL-H. + * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. + * The same is true for both PCI channels. + */ + temp = ddb_in32(DDB_PCICTL0_H); + temp |= 0x80000000; + ddb_out32(DDB_PCICTL0_H, temp); + temp &= ~0xc0000000; + ddb_out32(DDB_PCICTL0_H, temp); + + temp = ddb_in32(DDB_PCICTL1_H); + temp |= 0x80000000; + ddb_out32(DDB_PCICTL1_H, temp); + temp &= ~0xc0000000; + ddb_out32(DDB_PCICTL1_H, temp); +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/pci_ops.c linux/arch/mips/ddb5xxx/ddb5477/pci_ops.c --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/pci_ops.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/pci_ops.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,416 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/ddb5477/pci_ops.c + * Define the pci_ops for DB5477. + * + * Much of the code is derived from the original DDB5074 port by + * Geert Uytterhoeven + * + * 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. + *********************************************************************** + */ + +/* + * DDB5477 has two PCI channels, external PCI and IOPIC (internal) + * Therefore we provide two sets of pci_ops. + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* + * config_swap structure records what set of pdar/pmr are used + * to access pci config space. It also provides a place hold the + * original values for future restoring. + */ +struct pci_config_swap { + u32 pdar; + u32 pmr; + u32 config_base; + u32 config_size; + u32 pdar_backup; + u32 pmr_backup; +}; + +/* + * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI. + */ +struct pci_config_swap ext_pci_swap = { + DDB_PCIW0, + DDB_PCIINIT00, + DDB_PCI0_CONFIG_BASE, + DDB_PCI0_CONFIG_SIZE +}; +struct pci_config_swap io_pci_swap = { + DDB_IOPCIW0, + DDB_PCIINIT01, + DDB_PCI1_CONFIG_BASE, + DDB_PCI1_CONFIG_SIZE +}; + + +/* + * access config space + */ +static inline u32 ddb_access_config_base(struct pci_config_swap *swap, + u32 bus,/* 0 means top level bus */ + u32 slot_num) +{ + u32 pci_addr = 0; + u32 pciinit_offset = 0; + u32 virt_addr = swap->config_base; + u32 option; + + /* [jsun] hack for testing */ + // if (slot_num == 4) slot_num = 0; + + /* minimum pdar (window) size is 2MB */ + MIPS_ASSERT(swap->config_size >= (2 << 20)); + + MIPS_ASSERT(slot_num < (1 << 5)); + MIPS_ASSERT(bus < (1 << 8)); + + /* backup registers */ + swap->pdar_backup = ddb_in32(swap->pdar); + swap->pmr_backup = ddb_in32(swap->pmr); + + /* set the pdar (pci window) register */ + ddb_set_pdar(swap->pdar, + swap->config_base, + swap->config_size, + 32, /* 32 bit wide */ + 0, /* not on local memory bus */ + 0); /* not visible from PCI bus (N/A) */ + + /* + * calcuate the absolute pci config addr; + * according to the spec, we start scanning from adr:11 (0x800) + */ + if (bus == 0) { + /* type 0 config */ + pci_addr = 0x800 << slot_num; + } else { + /* type 1 config */ + pci_addr = (bus << 16) | (slot_num << 11); + panic("ddb_access_config_base: we don't support type 1 config Yet"); + } + + /* + * if pci_addr is less than pci config window size, we set + * pciinit_offset to 0 and adjust the virt_address. + * Otherwise we will try to adjust pciinit_offset. + */ + if (pci_addr < swap->config_size) { + virt_addr = KSEG1ADDR(swap->config_base + pci_addr); + pciinit_offset = 0; + } else { + MIPS_ASSERT( (pci_addr & (swap->config_size - 1)) == 0); + virt_addr = KSEG1ADDR(swap->config_base); + pciinit_offset = pci_addr; + } + + /* set the pmr register */ + option = DDB_PCI_ACCESS_32; + if (bus != 0) option |= DDB_PCI_CFGTYPE1; + ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); + + return virt_addr; +} + +static inline void ddb_close_config_base(struct pci_config_swap *swap) +{ + ddb_out32(swap->pdar, swap->pdar_backup); + ddb_out32(swap->pmr, swap->pmr_backup); +} + +static int read_config_dword(struct pci_config_swap *swap, + struct pci_dev *dev, + u32 where, + u32 *val) +{ + u32 bus, slot_num, func_num; + u32 base; + + MIPS_ASSERT((where & 3) == 0); + MIPS_ASSERT(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + MIPS_ASSERT(bus != 0); + } else { + bus = 0; + } + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + base = ddb_access_config_base(swap, bus, slot_num); + *val = *(volatile u32*) (base + (func_num << 8) + where); + ddb_close_config_base(swap); + return PCIBIOS_SUCCESSFUL; +} + +static int read_config_word(struct pci_config_swap *swap, + struct pci_dev *dev, + u32 where, + u16 *val) +{ + int status; + u32 result; + + MIPS_ASSERT((where & 1) == 0); + + status = read_config_dword(swap, dev, where & ~3, &result); + if (where & 2) result >>= 16; + *val = result & 0xffff; + return status; +} + +static int read_config_byte(struct pci_config_swap *swap, + struct pci_dev *dev, + u32 where, + u8 *val) +{ + int status; + u32 result; + + status = read_config_dword(swap, dev, where & ~3, &result); + if (where & 1) result >>= 8; + if (where & 2) result >>= 16; + *val = result & 0xff; + return status; +} + +static int write_config_dword(struct pci_config_swap *swap, + struct pci_dev *dev, + u32 where, + u32 val) +{ + u32 bus, slot_num, func_num; + u32 base; + + MIPS_ASSERT((where & 3) == 0); + MIPS_ASSERT(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + MIPS_ASSERT(bus != 0); + } else { + bus = 0; + } + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + base = ddb_access_config_base(swap, bus, slot_num); + *(volatile u32*) (base + (func_num << 8) + where) = val; + ddb_close_config_base(swap); + return PCIBIOS_SUCCESSFUL; +} + +static int write_config_word(struct pci_config_swap *swap, + struct pci_dev *dev, + u32 where, + u16 val) +{ + int status, shift=0; + u32 result; + + MIPS_ASSERT((where & 1) == 0); + + status = read_config_dword(swap, dev, where & ~3, &result); + if (status != PCIBIOS_SUCCESSFUL) return status; + + if (where & 2) + shift += 16; + result &= ~(0xffff << shift); + result |= val << shift; + return write_config_dword(swap, dev, where & ~3, result); +} + +static int write_config_byte(struct pci_config_swap *swap, + struct pci_dev *dev, + u32 where, + u8 val) +{ + int status, shift=0; + u32 result; + + status = read_config_dword(swap, dev, where & ~3, &result); + if (status != PCIBIOS_SUCCESSFUL) return status; + + if (where & 2) + shift += 16; + if (where & 1) + shift += 8; + result &= ~(0xff << shift); + result |= val << shift; + return write_config_dword(swap, dev, where & ~3, result); +} + +#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ +static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ +{ \ + return rw##_config_##unitname(pciswap, \ + dev, \ + where, \ + val); \ +} + +MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) +MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) +MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) + +MAKE_PCI_OPS(iopci, read, byte, u8 *, &io_pci_swap) +MAKE_PCI_OPS(iopci, read, word, u16 *, &io_pci_swap) +MAKE_PCI_OPS(iopci, read, dword, u32 *, &io_pci_swap) + +MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) +MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) +MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) + +MAKE_PCI_OPS(iopci, write, byte, u8, &io_pci_swap) +MAKE_PCI_OPS(iopci, write, word, u16, &io_pci_swap) +MAKE_PCI_OPS(iopci, write, dword, u32, &io_pci_swap) + +struct pci_ops ddb5477_ext_pci_ops ={ + extpci_read_config_byte, + extpci_read_config_word, + extpci_read_config_dword, + extpci_write_config_byte, + extpci_write_config_word, + extpci_write_config_dword +}; + + +struct pci_ops ddb5477_io_pci_ops ={ + iopci_read_config_byte, + iopci_read_config_word, + iopci_read_config_dword, + iopci_write_config_byte, + iopci_write_config_word, + iopci_write_config_dword +}; + +#if defined(CONFIG_LL_DEBUG) +void jsun_scan_pci_bus(void) +{ + struct pci_bus bus; + struct pci_dev dev; + unsigned int devfn; + int j; + + bus.parent = NULL; /* we scan the top level only */ + dev.bus = &bus; + dev.sysdata = NULL; + + /* scan ext pci bus and io pci bus*/ + for (j=0; j< 2; j++) { + if (j == 0) { + printk("scan ddb5477 external PCI bus:\n"); + bus.ops = &ddb5477_ext_pci_ops; + } else { + printk("scan ddb5477 IO PCI bus:\n"); + bus.ops = &ddb5477_io_pci_ops; + } + + for (devfn = 0; devfn < 0x100; devfn += 8) { + u32 temp; + u16 temp16; + u8 temp8; + int i; + + dev.devfn = devfn; + MIPS_VERIFY(pci_read_config_dword(&dev, 0, &temp), + == PCIBIOS_SUCCESSFUL); + if (temp == 0xffffffff) continue; + + printk("slot %d: (addr %d) \n", devfn/8, 11+devfn/8); + + /* verify read word and byte */ + MIPS_VERIFY(pci_read_config_word(&dev, 2, &temp16), + == PCIBIOS_SUCCESSFUL); + MIPS_ASSERT(temp16 == (temp >> 16)); + MIPS_VERIFY(pci_read_config_byte(&dev, 3, &temp8), + == PCIBIOS_SUCCESSFUL); + MIPS_ASSERT(temp8 == (temp >> 24)); + MIPS_VERIFY(pci_read_config_byte(&dev, 1, &temp8), + == PCIBIOS_SUCCESSFUL); + MIPS_ASSERT(temp8 == ((temp >> 8) & 0xff)); + + for (i=0; i < 16; i++) { + MIPS_VERIFY(pci_read_config_dword(&dev, i*4, &temp), + == PCIBIOS_SUCCESSFUL); + printk("\t%08X", temp); + if ((i%4) == 3) printk("\n"); + } + } + } +} + + +static void jsun_hardcode_pci_resources_eepro(void) +{ + struct pci_bus bus; + struct pci_dev dev; + u32 temp; + + bus.parent = NULL; /* we scan the top level only */ + bus.ops = &ddb5477_ext_pci_ops; + dev.bus = &bus; + dev.sysdata = NULL; + + /* for slot 5 (ext pci 1) eepro card */ + dev.devfn = 5*8; + pci_read_config_dword(&dev, 0, &temp); + MIPS_ASSERT(temp == 0x12298086); + + pci_write_config_dword(&dev, PCI_BASE_ADDRESS_0, DDB_PCI0_MEM_BASE); + pci_write_config_dword(&dev, PCI_BASE_ADDRESS_1, 0); + pci_write_config_dword(&dev, PCI_BASE_ADDRESS_2, DDB_PCI0_MEM_BASE+0x100000); + pci_write_config_dword(&dev, PCI_INTERRUPT_LINE, 17); +} + +static void jsun_hardcode_pci_resources_onboard_tulip(void) +{ + struct pci_bus bus; + struct pci_dev dev; + u32 temp; + + bus.parent = NULL; /* we scan the top level only */ + bus.ops = &ddb5477_ext_pci_ops; + dev.bus = &bus; + dev.sysdata = NULL; + + /* for slot 4 on board ether chip */ + dev.devfn = 4*8; + pci_read_config_dword(&dev, 0, &temp); + MIPS_ASSERT(temp == 0x00191011); + + pci_write_config_dword(&dev, PCI_BASE_ADDRESS_0, 0x1000); + pci_write_config_dword(&dev, PCI_BASE_ADDRESS_1, DDB_PCI0_MEM_BASE); + pci_write_config_dword(&dev, PCI_INTERRUPT_LINE, 16); +} + +static void jsun_hardcode_pci_resources(void) +{ + jsun_hardcode_pci_resources_onboard_tulip(); +} + +void jsun_assign_pci_resource(void) +{ + jsun_hardcode_pci_resources(); +} + +#endif diff -u --recursive --new-file v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/setup.c linux/arch/mips/ddb5xxx/ddb5477/setup.c --- v2.4.9/linux/arch/mips/ddb5xxx/ddb5477/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5xxx/ddb5477/setup.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,251 @@ +/*********************************************************************** + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/ddb5477/setup.c + * Setup file for DDB5477. + * + * 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 /* for ROOT_DEV */ +#include +#include /* for HZ */ + +#include +#include +#include +#include +#include +#include + +#include + + + +#define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */ + +#ifdef USE_CPU_COUNTER_TIMER +#define CPU_COUNTER_FREQUENCY 83000000 +#else +/* otherwise we use special timer 1 */ +#define SP_TIMER_FREQUENCY 83000000 +#define SP_TIMER_BASE DDB_SPT1CTRL_L +#define SP_TIMER_IRQ (8 + 6) +#endif + +static void ddb_machine_restart(char *command) +{ + static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; + + u32 t; + + /* PCI cold reset */ + ddb_pci_reset_bus(); + + /* CPU cold reset */ + t = ddb_in32(DDB_CPUSTAT); + MIPS_ASSERT((t&1)); + ddb_out32(DDB_CPUSTAT, t); + + /* Call the PROM */ + back_to_prom(); +} + +static void ddb_machine_halt(void) +{ + printk("DDB Vrc-5477 halted.\n"); + while (1); +} + +static void ddb_machine_power_off(void) +{ + printk("DDB Vrc-5477 halted. Please turn off the power.\n"); + while (1); +} + +extern void rtc_ds1386_init(unsigned long base); +static void __init ddb_time_init(void) +{ +#if defined(USE_CPU_COUNTER_TIMER) + mips_counter_frequency = CPU_COUNTER_FREQUENCY; +#endif + + /* we have ds1396 RTC chip */ + rtc_ds1386_init(KSEG1ADDR(DDB_LCS1_BASE)); +} + +#if defined(CONFIG_LL_DEBUG) +int board_init_done_flag = 0; +#endif + +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); +static void __init ddb_timer_setup(struct irqaction *irq) +{ +#if defined(USE_CPU_COUNTER_TIMER) + unsigned int count; + + /* we are using the cpu counter for timer interrupts */ + setup_irq(7, irq); + + /* to generate the first timer interrupt */ + count = read_32bit_cp0_register(CP0_COUNT); + write_32bit_cp0_register(CP0_COMPARE, count + 1000); + +#else + + /* if we don't use Special purpose timer 1 */ + ddb_out32(SP_TIMER_BASE, SP_TIMER_FREQUENCY/HZ); + ddb_out32(SP_TIMER_BASE+4, 0x1); + setup_irq(SP_TIMER_IRQ, irq); + +#endif + + /* this is the last board dependent code */ + MIPS_DEBUG(board_init_done_flag = 1); +} + +static void ddb5477_board_init(void); +extern void ddb5477_irq_setup(void); + +#if defined(CONFIG_BLK_DEV_INITRD) +extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end; +#endif + +void __init ddb_setup(void) +{ + extern int panic_timeout; + + irq_setup = ddb5477_irq_setup; + mips_io_port_base = KSEG1ADDR(DDB_PCI_IO_BASE); + + board_time_init = ddb_time_init; + board_timer_setup = ddb_timer_setup; + + _machine_restart = ddb_machine_restart; + _machine_halt = ddb_machine_halt; + _machine_power_off = ddb_machine_power_off; + + /* setup resource limits */ + ioport_resource.end = DDB_PCI0_IO_SIZE + DDB_PCI1_IO_SIZE - 1; + iomem_resource.end = 0xffffffff; + + /* Reboot on panic */ + panic_timeout = 180; + + /* initialize board - we don't trust the loader */ + ddb5477_board_init(); + +#if defined(CONFIG_BLK_DEV_INITRD) + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + +} + +static void __init ddb5477_board_init() +{ + /* ----------- setup PDARs ------------ */ + + /* SDRAM should have been set */ + MIPS_ASSERT(ddb_in32(DDB_SDRAM0) == + ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1)); + + /* SDRAM1 should be turned off. What is this for anyway ? */ + MIPS_ASSERT( (ddb_in32(DDB_SDRAM1) & 0xf) == 0); + + /* Set LDCSs */ + /* flash */ + ddb_set_pdar(DDB_LCS0, DDB_LCS0_BASE, DDB_LCS0_SIZE, 16, 0, 0); + /* misc */ + ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 8, 0, 0); + /* mezzanie (?) */ + ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 16, 0, 0); + + /* verify VRC5477 base addr */ + MIPS_ASSERT(ddb_in32(DDB_VRC5477) == + ddb_calc_pdar(DDB_VRC5477_BASE, DDB_VRC5477_SIZE, 32, 0, 1)); + + /* verify BOOT ROM addr */ + MIPS_ASSERT(ddb_in32(DDB_BOOTCS) == + ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0)); + + /* setup PCI windows - window0 for MEM/config, window1 for IO */ + ddb_set_pdar(DDB_PCIW0, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1); + ddb_set_pdar(DDB_PCIW1, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1); + ddb_set_pdar(DDB_IOPCIW0, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1); + ddb_set_pdar(DDB_IOPCIW1, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1); + + /* ------------ reset PCI bus and BARs ----------------- */ + ddb_pci_reset_bus(); + + ddb_out32(DDB_BARM010, 0x00000008); + ddb_out32(DDB_BARM011, 0x00000008); + + ddb_out32(DDB_BARC0, 0xffffffff); + ddb_out32(DDB_BARM230, 0xffffffff); + ddb_out32(DDB_BAR00, 0xffffffff); + ddb_out32(DDB_BAR10, 0xffffffff); + ddb_out32(DDB_BAR20, 0xffffffff); + ddb_out32(DDB_BAR30, 0xffffffff); + ddb_out32(DDB_BAR40, 0xffffffff); + ddb_out32(DDB_BAR50, 0xffffffff); + ddb_out32(DDB_BARB0, 0xffffffff); + + ddb_out32(DDB_BARC1, 0xffffffff); + ddb_out32(DDB_BARM231, 0xffffffff); + ddb_out32(DDB_BAR01, 0xffffffff); + ddb_out32(DDB_BAR11, 0xffffffff); + ddb_out32(DDB_BAR21, 0xffffffff); + ddb_out32(DDB_BAR31, 0xffffffff); + ddb_out32(DDB_BAR41, 0xffffffff); + ddb_out32(DDB_BAR51, 0xffffffff); + ddb_out32(DDB_BARB1, 0xffffffff); + + /* + * We use pci master register 0 for memory space / config space + * And we use register 1 for IO space. + * Note that for memory space, we bump up the pci base address + * so that we have 1:1 mapping between PCI memory and cpu physical. + * For PCI IO space, it starts from 0 in PCI IO space but with + * DDB_xx_IO_BASE in CPU physical address space. + */ + ddb_set_pmr(DDB_PCIINIT00, DDB_PCICMD_MEM, DDB_PCI0_MEM_BASE, + DDB_PCI_ACCESS_32); + ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32); + + ddb_set_pmr(DDB_PCIINIT01, DDB_PCICMD_MEM, DDB_PCI1_MEM_BASE, + DDB_PCI_ACCESS_32); + ddb_set_pmr(DDB_PCIINIT11, DDB_PCICMD_IO, DDB_PCI0_IO_SIZE, + DDB_PCI_ACCESS_32); + + + /* PCI cross window should be set properly */ + ddb_set_pdar(DDB_BARP00, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1); + ddb_set_pdar(DDB_BARP10, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1); + ddb_set_pdar(DDB_BARP01, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1); + ddb_set_pdar(DDB_BARP11, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1); + + /* enable USB input buffers */ + ddb_out32(DDB_PIBMISC, 0x00000007); + + /* For dual-function pins, make them all non-GPIO */ + ddb_out32(DDB_GIUFUNSEL, 0x0); + // ddb_out32(DDB_GIUFUNSEL, 0xfe0fcfff); /* NEC recommanded value */ +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/Makefile linux/arch/mips/dec/Makefile --- v2.4.9/linux/arch/mips/dec/Makefile Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/dec/Makefile Sun Sep 9 10:43:01 2001 @@ -19,7 +19,6 @@ obj-y := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o wbflush.o obj-$(CONFIG_PROM_CONSOLE) += promcon.o -obj-$(CONFIG_SERIAL) += serial.o int-handler.o: int-handler.S diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/int-handler.S linux/arch/mips/dec/int-handler.S --- v2.4.9/linux/arch/mips/dec/int-handler.S Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/dec/int-handler.S Sun Sep 9 10:43:01 2001 @@ -2,6 +2,7 @@ * arch/mips/dec/int-handler.S * * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen + * Copyright (C) 2000 Maciej W. Rozycki * * Written by Ralf Baechle and Andreas Busse, modified for DECStation * support by Paul Antoine and Harald Koerfgen. @@ -16,6 +17,11 @@ #include #include +#include +#include +#include +#include +#include #include @@ -24,8 +30,6 @@ /* * decstation_handle_int: Interrupt handler for DECStations * - * FIXME: Detection of spurious interrupts not yet implemented! - * * We follow the model in the Indy interrupt code by David Miller, where he * says: a lot of complication here is taken away because: * @@ -139,12 +143,12 @@ la t1,cpu_mask_tbl and t0,t2 # isolate allowed ones - /* insert detection of spurious interrupts here */ + beqz t0,spurious /* * Find irq with highest priority */ -1: lw t2,(t1) +1: lw t2,(t1) move t3,t0 and t3,t2 beq t3,zero,1b @@ -156,18 +160,18 @@ lw a0,%lo(cpu_irq_nr-cpu_mask_tbl-PTRSIZE)(t1) lw t0,%lo(cpu_ivec_tbl-cpu_mask_tbl-PTRSIZE)(t1) bgez a0, handle_it # irq_nr >= 0? - # irq_nr < 0: a0 contains an address - nop + # irq_nr < 0: t0 contains an address + nop jr t0 nop # delay slot /* * Handle "IRQ Controller" Interrupts * Masked Interrupts are still visible and have to be masked "by hand". - * %hi(KN02_CSR_ADDR) does not work so all addresses are hardcoded :-(. */ EXPORT(kn02_io_int) -kn02_io_int: lui t0,0xbff0 # get interrupt status and mask +kn02_io_int: # 3max + lui t0,KN02_CSR_ADDR>>16 # get interrupt status and mask lw t0,(t0) la t1,asic_mask_tbl move t3,t0 @@ -176,27 +180,32 @@ and t0,t3 # mask out allowed ones EXPORT(kn03_io_int) -kn03_io_int: lui t2,0xbf84 # upper part of IOASIC Address - lw t0,0x0110(t2) # get status: IOASIC isr - lw t3,0x0120(t2) # get mask: IOASIC isrm +kn03_io_int: # 3max+ + lui t2,KN03_IOASIC_BASE>>16 # upper part of IOASIC Address + lw t0,SIR(t2) # get status: IOASIC isr + lw t3,SIMR(t2) # get mask: IOASIC isrm la t1,asic_mask_tbl b find_int and t0,t3 # mask out allowed ones - EXPORT(kn02ba_io_int) -kn02ba_io_int: lui t2,0xbc04 - lw t0,0x0110(t2) # IOASIC isr, works for maxine also - lw t3,0x0120(t2) # IOASIC isrm + EXPORT(kn02xa_io_int) +kn02xa_io_int: # 3min/maxine + lui t2,KN02XA_IOASIC_BASE>>16 + # upper part of IOASIC Address + lw t0,SIR(t2) # get status: IOASIC isr + lw t3,SIMR(t2) # get mask: IOASIC isrm la t1,asic_mask_tbl and t0,t3 /* * Find irq with highest priority */ -find_int: lw t2,(t1) +find_int: beqz t0,spurious + +1: lw t2,(t1) move t3,t0 and t3,t2 - beq zero,t3,find_int + beq zero,t3,1b addu t1,PTRSIZE # delay slot /* @@ -209,7 +218,10 @@ move a1,sp j ret_from_irq nop - + +spurious: + j spurious_interrupt + nop END(decstation_handle_int) /* * Interrupt routines common to all DECStations first. @@ -218,14 +230,6 @@ dec_intr_fpu: PANIC("Unimplemented FPU interrupt handler") /* - * Halt interrupt - */ - EXPORT(intr_halt) -intr_halt: la k0,0xbc000000 - jr k0 - nop - -/* * Generic unimplemented interrupt routines - ivec_tbl is initialised to * point all interrupts here. The table is then filled in by machine-specific * initialisation in dec_setup(). @@ -358,5 +362,3 @@ .word 0 .word 0 .word 0xffffffff # EOL - - diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/irq.c linux/arch/mips/dec/irq.c --- v2.4.9/linux/arch/mips/dec/irq.c Fri Feb 9 11:29:44 2001 +++ linux/arch/mips/dec/irq.c Sun Sep 9 10:43:01 2001 @@ -2,9 +2,7 @@ * Code to handle DECstation IRQs plus some generic interrupt stuff. * * Copyright (C) 1992 Linus Torvalds - * Copyright (C) 1994, 1995, 1996, 1997 Ralf Baechle - * - * $Id: irq.c,v 1.6 2000/02/04 07:40:23 ralf Exp $ + * Copyright (C) 1994, 1995, 1996, 1997, 2000 Ralf Baechle */ #include #include @@ -27,9 +25,14 @@ #include -extern volatile unsigned int *isr; /* address of the interrupt status register */ -extern volatile unsigned int *imr; /* address of the interrupt mask register */ -extern decint_t dec_interrupt[NR_INTS]; +extern void dec_init_kn01(void); +extern void dec_init_kn230(void); +extern void dec_init_kn02(void); +extern void dec_init_kn02ba(void); +extern void dec_init_kn02ca(void); +extern void dec_init_kn03(void); + +extern asmlinkage void decstation_handle_int(void); unsigned long spurious_count = 0; @@ -42,7 +45,7 @@ dummy = *imr; dummy = *imr; } else /* This is a cpu interrupt */ - set_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) & ~dec_interrupt[irq_nr].cpu_mask); + change_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) & ~dec_interrupt[irq_nr].cpu_mask); } static inline void unmask_irq(unsigned int irq_nr) @@ -54,7 +57,7 @@ dummy = *imr; dummy = *imr; } - set_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) | dec_interrupt[irq_nr].cpu_mask); + change_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) | dec_interrupt[irq_nr].cpu_mask); } void disable_irq(unsigned int irq_nr) @@ -125,7 +128,7 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; mask_irq(irq); @@ -142,10 +145,10 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - unmask_irq(irq); __cli(); + unmask_irq(irq); } - irq_exit(cpu); + irq_exit(cpu, irq); /* unmasking and bottom half handling is done magically for us. */ } @@ -261,5 +264,34 @@ void __init init_IRQ(void) { - irq_setup(); + switch (mips_machtype) { + case MACH_DS23100: + dec_init_kn01(); + break; + case MACH_DS5100: /* DS5100 MIPSMATE */ + dec_init_kn230(); + break; + case MACH_DS5000_200: /* DS5000 3max */ + dec_init_kn02(); + break; + case MACH_DS5000_1XX: /* DS5000/100 3min */ + dec_init_kn02ba(); + break; + case MACH_DS5000_2X0: /* DS5000/240 3max+ */ + dec_init_kn03(); + break; + case MACH_DS5000_XX: /* Personal DS5000/2x */ + dec_init_kn02ca(); + break; + case MACH_DS5800: /* DS5800 Isis */ + panic("Don't know how to set this up!"); + break; + case MACH_DS5400: /* DS5400 MIPSfair */ + panic("Don't know how to set this up!"); + break; + case MACH_DS5500: /* DS5500 MIPSfair-2 */ + panic("Don't know how to set this up!"); + break; + } + set_except_vector(0, decstation_handle_int); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/prom/cmdline.c linux/arch/mips/dec/prom/cmdline.c --- v2.4.9/linux/arch/mips/dec/prom/cmdline.c Mon Feb 28 07:18:20 2000 +++ linux/arch/mips/dec/prom/cmdline.c Sun Sep 9 10:43:01 2001 @@ -2,8 +2,6 @@ * cmdline.c: read the command line passed to us by the PROM. * * Copyright (C) 1998 Harald Koerfgen - * - * $Id: cmdline.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ */ #include #include @@ -19,7 +17,7 @@ extern int (*prom_printf)(char *, ...); #endif -char arcs_cmdline[CL_SIZE]; +char arcs_cmdline[COMMAND_LINE_SIZE]; void __init prom_init_cmdline(int argc, char **argv, unsigned long magic) { diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/prom/init.c linux/arch/mips/dec/prom/init.c --- v2.4.9/linux/arch/mips/dec/prom/init.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/dec/prom/init.c Sun Sep 9 10:43:01 2001 @@ -2,12 +2,11 @@ * init.c: PROM library initialisation code. * * Copyright (C) 1998 Harald Koerfgen - * - * $Id: init.c,v 1.3 1999/08/09 19:43:13 harald Exp $ */ #include #include #include +#include #include "prom.h" /* @@ -93,15 +92,17 @@ /* Were we compiled with the right CPU option? */ #if defined(CONFIG_CPU_R3000) - if ((mips_cputype == CPU_R4000SC) || (mips_cputype == CPU_R4400SC)) { + if ((mips_cpu.cputype == CPU_R4000SC) || + (mips_cpu.cputype == CPU_R4400SC)) { prom_printf("Sorry, this kernel is compiled for the wrong CPU type!\n"); prom_printf("Please recompile with \"CONFIG_CPU_R4x00 = y\"\n"); dec_machine_halt(); } #endif -#if defined(CONFIG_CPU_R4x00) - if ((mips_cputype == CPU_R3000) || (mips_cputype == CPU_R3000A)) { +#if defined(CONFIG_CPU_R4X00) + if ((mips_cpu.cputype == CPU_R3000) || + (mips_cpu.cputype == CPU_R3000A)) { prom_printf("Sorry, this kernel is compiled for the wrong CPU type!\n"); prom_printf("Please recompile with \"CONFIG_CPU_R3000 = y\"\n"); dec_machine_halt(); @@ -114,3 +115,4 @@ return 0; } + diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/prom/memory.c linux/arch/mips/dec/prom/memory.c --- v2.4.9/linux/arch/mips/dec/prom/memory.c Tue Mar 6 19:44:36 2001 +++ linux/arch/mips/dec/prom/memory.c Sun Sep 9 10:43:01 2001 @@ -2,6 +2,7 @@ * memory.c: memory initialisation code. * * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine + * Copyright (C) 2000 Maciej W. Rozycki * * $Id: memory.c,v 1.3 1999/10/09 00:00:58 ralf Exp $ */ @@ -14,6 +15,8 @@ #include #include +#include + #include #include "prom.h" @@ -33,11 +36,6 @@ volatile unsigned long mem_err = 0; /* So we know an error occurred */ -extern char _end; - -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) - /* * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen * off the end of real memory. Only suitable for the 2100/3100's (PMAX). @@ -45,7 +43,7 @@ #define CHUNK_SIZE 0x400000 -unsigned long __init pmax_get_memory_size(void) +static void __init pmax_setup_memory_region(void) { volatile unsigned char *memory_page, dummy; char old_handler[0x80]; @@ -66,17 +64,19 @@ dummy = *memory_page; } memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80); - return (unsigned long)memory_page - KSEG1 - CHUNK_SIZE; + + add_memory_region(0, (unsigned long)memory_page - KSEG1 - CHUNK_SIZE, + BOOT_MEM_RAM); } /* * Use the REX prom calls to get hold of the memory bitmap, and thence * determine memory size. */ -unsigned long __init rex_get_memory_size(void) +static void __init rex_setup_memory_region(void) { int i, bitmap_size; - unsigned long mem_size = 0; + unsigned long mem_start = 0, mem_size = 0; memmap *bm; /* some free 64k */ @@ -88,46 +88,30 @@ /* FIXME: very simplistically only add full sets of pages */ if (bm->bitmap[i] == 0xff) mem_size += (8 * bm->pagesize); + else if (!mem_size) + mem_start += (8 * bm->pagesize); + else { + add_memory_region(mem_start, mem_size, BOOT_MEM_RAM); + mem_start += mem_size + (8 * bm->pagesize); + mem_size = 0; + } } - - return (mem_size); + if (mem_size) + add_memory_region(mem_start, mem_size, BOOT_MEM_RAM); } void __init prom_meminit(unsigned int magic) { - unsigned long free_start, free_end, start_pfn, bootmap_size; - unsigned long mem_size = 0; - if (magic != REX_PROM_MAGIC) - mem_size = pmax_get_memory_size(); + pmax_setup_memory_region(); else - mem_size = rex_get_memory_size(); - - free_start = PHYSADDR(PFN_ALIGN(&_end)); - free_end = mem_size; - start_pfn = PFN_UP((unsigned long)&_end); - -#ifdef PROM_DEBUG - prom_printf("free_start: 0x%08x\n", free_start); - prom_printf("free_end: 0x%08x\n", free_end); - prom_printf("start_pfn: 0x%08x\n", start_pfn); -#endif - - /* Register all the contiguous memory with the bootmem allocator - and free it. Be careful about the bootmem freemap. */ - bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT); - free_bootmem(free_start + bootmap_size, free_end - free_start - bootmap_size); -} - -int __init page_is_ram(unsigned long pagenr) -{ - return 1; + rex_setup_memory_region(); } -void prom_free_prom_memory (void) +void __init prom_free_prom_memory (void) { unsigned long addr, end; - extern char _ftext; + extern char _ftext; /* * Free everything below the kernel itself but leave @@ -142,16 +126,16 @@ * XXX: save this address for use in dec_lance.c? */ if (IOASIC) - end = PHYSADDR(&_ftext) - 0x00020000; + end = __pa(&_ftext) - 0x00020000; else #endif - end = PHYSADDR(&_ftext); + end = __pa(&_ftext); addr = PAGE_SIZE; while (addr < end) { - ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); - free_page(addr); + ClearPageReserved(virt_to_page(__va(addr))); + set_page_count(virt_to_page(__va(addr)), 1); + free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; } diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/reset.c linux/arch/mips/dec/reset.c --- v2.4.9/linux/arch/mips/dec/reset.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/dec/reset.c Sun Sep 9 10:43:01 2001 @@ -23,3 +23,7 @@ back_to_prom(); } +void dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs) +{ + dec_machine_halt(); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/rtc-dec.c linux/arch/mips/dec/rtc-dec.c --- v2.4.9/linux/arch/mips/dec/rtc-dec.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/dec/rtc-dec.c Sun Sep 9 10:43:01 2001 @@ -1,13 +1,12 @@ - -/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $ - +/* * 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. * * RTC routines for DECstation style attached Dallas chip. * - * Copyright (C) 1998 by Ralf Baechle, Harald Koerfgen + * Copyright (C) 1998, 2001 by Ralf Baechle + * Copyright (C) 1998 by Harald Koerfgen */ #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/serial.c linux/arch/mips/dec/serial.c --- v2.4.9/linux/arch/mips/dec/serial.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/dec/serial.c Wed Dec 31 16:00:00 1969 @@ -1,98 +0,0 @@ -/* - * sercons.c - * choose the right serial device at boot time - * - * triemer 6-SEP-1998 - * sercons.c is designed to allow the three different kinds - * of serial devices under the decstation world to co-exist - * in the same kernel. The idea here is to abstract - * the pieces of the drivers that are common to this file - * so that they do not clash at compile time and runtime. - * - * HK 16-SEP-1998 v0.002 - * removed the PROM console as this is not a real serial - * device. Added support for PROM console in drivers/char/tty_io.c - * instead. Although it may work to enable more than one - * console device I strongly recommend to use only one. - */ - -#include -#include -#include - -#ifdef CONFIG_ZS -extern int zs_init(void); -#endif - -#ifdef CONFIG_DZ -extern int dz_init(void); -#endif - -#ifdef CONFIG_SERIAL_CONSOLE - -#ifdef CONFIG_ZS -extern void zs_serial_console_init(void); -#endif - -#ifdef CONFIG_DZ -extern void dz_serial_console_init(void); -#endif - -#endif - -/* rs_init - starts up the serial interface - - handle normal case of starting up the serial interface */ - -#ifdef CONFIG_SERIAL - -int __init rs_init(void) -{ - -#if defined(CONFIG_ZS) && defined(CONFIG_DZ) - if (IOASIC) - return zs_init(); - else - return dz_init(); -#else - -#ifdef CONFIG_ZS - return zs_init(); -#endif - -#ifdef CONFIG_DZ - return dz_init(); -#endif - -#endif -} - -__initcall(rs_init); - -#endif - -#ifdef CONFIG_SERIAL_CONSOLE - -/* serial_console_init handles the special case of starting - * up the console on the serial port - */ -void __init serial_console_init(void) -{ -#if defined(CONFIG_ZS) && defined(CONFIG_DZ) - if (IOASIC) - zs_serial_console_init(); - else - dz_serial_console_init(); -#else - -#ifdef CONFIG_ZS - zs_serial_console_init(); -#endif - -#ifdef CONFIG_DZ - dz_serial_console_init(); -#endif - -#endif -} - -#endif diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c --- v2.4.9/linux/arch/mips/dec/setup.c Thu Aug 26 12:42:31 1999 +++ linux/arch/mips/dec/setup.c Sun Sep 9 10:43:01 2001 @@ -6,11 +6,13 @@ * for more details. * * Copyright (C) 1998 Harald Koerfgen + * Copyright (C) 2000 Maciej W. Rozycki */ #include #include #include #include +#include #include #include #include @@ -22,25 +24,19 @@ #include #include #include +#include +#include #include -extern asmlinkage void decstation_handle_int(void); -void dec_init_kn01(void); -void dec_init_kn230(void); -void dec_init_kn02(void); -void dec_init_kn02ba(void); -void dec_init_kn02ca(void); -void dec_init_kn03(void); +char *dec_rtc_base = (void *) KN01_RTC_BASE; /* Assume DS2100/3100 initially */ -char *dec_rtc_base = (char *) KN01_RTC_BASE; /* Assume DS2100/3100 initially */ +volatile unsigned int *ioasic_base; decint_t dec_interrupt[NR_INTS]; -/* +/* * Information regarding the IRQ Controller - * - * isr and imr are also hardcoded for different machines in int_handler.S */ volatile unsigned int *isr = 0L; /* address of the interrupt status register */ @@ -49,50 +45,17 @@ extern void dec_machine_restart(char *command); extern void dec_machine_halt(void); extern void dec_machine_power_off(void); +extern void dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs); extern void wbflush_setup(void); extern struct rtc_ops dec_rtc_ops; -extern void intr_halt(void); - extern int setup_dec_irq(int, struct irqaction *); void (*board_time_init) (struct irqaction * irq); -static void __init dec_irq_setup(void) -{ - switch (mips_machtype) { - case MACH_DS23100: - dec_init_kn01(); - break; - case MACH_DS5100: /* DS5100 MIPSMATE */ - dec_init_kn230(); - break; - case MACH_DS5000_200: /* DS5000 3max */ - dec_init_kn02(); - break; - case MACH_DS5000_1XX: /* DS5000/100 3min */ - dec_init_kn02ba(); - break; - case MACH_DS5000_2X0: /* DS5000/240 3max+ */ - dec_init_kn03(); - break; - case MACH_DS5000_XX: /* Personal DS5000/2x */ - dec_init_kn02ca(); - break; - case MACH_DS5800: /* DS5800 Isis */ - panic("Don't know how to set this up!"); - break; - case MACH_DS5400: /* DS5400 MIPSfair */ - panic("Don't know how to set this up!"); - break; - case MACH_DS5500: /* DS5500 MIPSfair-2 */ - panic("Don't know how to set this up!"); - break; - } - set_except_vector(0, decstation_handle_int); -} +static struct irqaction irq10 = {dec_intr_halt, 0, 0, "halt", NULL, NULL}; /* * enable the periodic interrupts @@ -112,9 +75,16 @@ setup_dec_irq(CLOCK, irq); } +/* + * Enable the halt interrupt. + */ +static void __init dec_halt_init(struct irqaction *irq) +{ + setup_dec_irq(HALT, irq); +} + void __init decstation_setup(void) { - irq_setup = dec_irq_setup; board_time_init = dec_time_init; wbflush_setup(); @@ -123,6 +93,10 @@ _machine_halt = dec_machine_halt; _machine_power_off = dec_machine_power_off; +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + rtc_ops = &dec_rtc_ops; } @@ -206,8 +180,8 @@ * Setup some memory addresses. FIXME: probably incomplete! */ dec_rtc_base = (char *) KN02_RTC_BASE; - isr = (volatile unsigned int *) KN02_CSR_ADDR; - imr = (volatile unsigned int *) KN02_CSR_ADDR; + isr = (void *) KN02_CSR_ADDR; + imr = (void *) KN02_CSR_ADDR; /* * Setup IOASIC interrupt @@ -275,16 +249,17 @@ /* * Setup some memory addresses. */ + ioasic_base = (void *) KN02XA_IOASIC_BASE; dec_rtc_base = (char *) KN02XA_RTC_BASE; - isr = (volatile unsigned int *) KN02XA_SIR_ADDR; - imr = (volatile unsigned int *) KN02XA_SIRM_ADDR; + isr = (void *) KN02XA_IOASIC_REG(SIR); + imr = (void *) KN02XA_IOASIC_REG(SIMR); /* * Setup IOASIC interrupt */ cpu_mask_tbl[0] = IE_IRQ3; cpu_irq_nr[0] = -1; - cpu_ivec_tbl[0] = kn02ba_io_int; + cpu_ivec_tbl[0] = kn02xa_io_int; *imr = 0; /* @@ -345,6 +320,7 @@ cpu_mask_tbl[5] = IE_IRQ5; cpu_irq_nr[5] = FPU; + dec_halt_init(&irq10); } /* dec_init_kn02ba */ /* @@ -355,14 +331,15 @@ /* * Setup some memory addresses. FIXME: probably incomplete! */ + ioasic_base = (void *) KN02XA_IOASIC_BASE; dec_rtc_base = (char *) KN02XA_RTC_BASE; - isr = (volatile unsigned int *) KN02XA_SIR_ADDR; - imr = (volatile unsigned int *) KN02XA_SIRM_ADDR; + isr = (void *) KN02XA_IOASIC_REG(SIR); + imr = (void *) KN02XA_IOASIC_REG(SIMR); /* * Setup IOASIC interrupt */ - cpu_ivec_tbl[1] = kn02ba_io_int; + cpu_ivec_tbl[1] = kn02xa_io_int; cpu_irq_nr[1] = -1; cpu_mask_tbl[1] = IE_IRQ3; *imr = 0; @@ -420,6 +397,7 @@ cpu_mask_tbl[4] = IE_IRQ5; cpu_irq_nr[4] = FPU; + dec_halt_init(&irq10); } /* dec_init_kn02ca */ /* @@ -430,9 +408,10 @@ /* * Setup some memory addresses. FIXME: probably incomplete! */ + ioasic_base = (void *) KN03_IOASIC_BASE; dec_rtc_base = (char *) KN03_RTC_BASE; - isr = (volatile unsigned int *) KN03_SIR_ADDR; - imr = (volatile unsigned int *) KN03_SIRM_ADDR; + isr = (void *) KN03_IOASIC_REG(SIR); + imr = (void *) KN03_IOASIC_REG(SIMR); /* * Setup IOASIC interrupt @@ -500,4 +479,5 @@ cpu_mask_tbl[4] = IE_IRQ5; cpu_irq_nr[4] = FPU; + dec_halt_init(&irq10); } /* dec_init_kn03 */ diff -u --recursive --new-file v2.4.9/linux/arch/mips/dec/time.c linux/arch/mips/dec/time.c --- v2.4.9/linux/arch/mips/dec/time.c Mon Oct 16 12:58:51 2000 +++ linux/arch/mips/dec/time.c Sun Sep 9 10:43:01 2001 @@ -1,8 +1,8 @@ - /* - * linux/arch/mips/kernel/time.c + * linux/arch/mips/dec/time.c * * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Copyright (C) 2000 Maciej W. Rozycki * * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. @@ -17,14 +17,22 @@ #include #include +#include #include #include #include #include +#include +#include +#include #include #include +#include + +extern void (*board_time_init)(struct irqaction *irq); + extern volatile unsigned long wall_jiffies; extern rwlock_t xtime_lock; @@ -36,12 +44,22 @@ /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) +#define USECS_PER_JIFFY_FRAC ((1000000ULL << 32) / HZ & 0xffffffff) /* Cycle counter value at the previous timer interrupt.. */ static unsigned int timerhi, timerlo; /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ +static unsigned long cached_quotient = 0; + +/* Last jiffy when do_fast_gettimeoffset() was called. */ +static unsigned long last_jiffies = 0; + +/* * On MIPS only R4000 and better have a cycle counter. * * FIXME: Does playing with the RP bit in c0_status interfere with this code? @@ -50,45 +68,34 @@ { u32 count; unsigned long res, tmp; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies = 0; unsigned long quotient; - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient = 0; - tmp = jiffies; quotient = cached_quotient; - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "lwu\t%0,%2\n\t" - "dsll32\t$1,%1,0\n\t" - "or\t$1,$1,%0\n\t" - "ddivu\t$0,$1,%3\n\t" - "mflo\t$1\n\t" - "dsll32\t%0,%4,0\n\t" - "nop\n\t" - "ddivu\t$0,%0,$1\n\t" - "mflo\t%0\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r"(quotient) - :"r"(timerhi), - "m"(timerlo), - "r"(tmp), - "r"(USECS_PER_JIFFY) - :"$1"); + if (last_jiffies != tmp) { + last_jiffies = tmp; + if (last_jiffies != 0) { + unsigned long r0; + __asm__(".set push\n\t" + ".set mips3\n\t" + "lwu %0,%3\n\t" + "dsll32 %1,%2,0\n\t" + "or %1,%1,%0\n\t" + "ddivu $0,%1,%4\n\t" + "mflo %1\n\t" + "dsll32 %0,%5,0\n\t" + "or %0,%0,%6\n\t" + "ddivu $0,%0,%1\n\t" + "mflo %0\n\t" + ".set pop" + : "=&r" (quotient), "=&r" (r0) + : "r" (timerhi), "m" (timerlo), + "r" (tmp), "r" (USECS_PER_JIFFY), + "r" (USECS_PER_JIFFY_FRAC)); cached_quotient = quotient; + } } /* Get last timer tick in absolute kernel time */ count = read_32bit_cp0_register(CP0_COUNT); @@ -97,11 +104,9 @@ count -= timerlo; //printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo); - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r"(res) - :"r"(count), - "r"(quotient)); + __asm__("multu %2,%3" + : "=l" (tmp), "=h" (res) + : "r" (count), "r" (quotient)); /* * Due to possible jiffies inconsistencies, we need to check @@ -113,6 +118,47 @@ return res; } +static unsigned long do_ioasic_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + unsigned long quotient; + + tmp = jiffies; + + quotient = cached_quotient; + + if (last_jiffies != tmp) { + last_jiffies = tmp; + if (last_jiffies != 0) { + unsigned long r0; + do_div64_32(r0, timerhi, timerlo, tmp); + do_div64_32(quotient, USECS_PER_JIFFY, + USECS_PER_JIFFY_FRAC, r0); + cached_quotient = quotient; + } + } + /* Get last timer tick in absolute kernel time */ + count = ioasic_read(FCTR); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; +//printk("count: %08x, %08x:%08x\n", count, timerhi, timerlo); + + __asm__("multu %2,%3" + : "=l" (tmp), "=h" (res) + : "r" (count), "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY - 1; + + return res; +} + /* This function must be called with interrupts disabled * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs * @@ -170,8 +216,8 @@ tv->tv_usec += do_gettimeoffset(); /* - * xtime is atomically updated in timer_bh. lost_ticks is - * nonzero if the timer bottom half hasnt executed yet. + * xtime is atomically updated in timer_bh. jiffies - wall_jiffies + * is nonzero if the timer bottom half hasnt executed yet. */ if (jiffies - wall_jiffies) tv->tv_usec += USECS_PER_JIFFY; @@ -187,6 +233,7 @@ void do_settimeofday(struct timeval *tv) { write_lock_irq(&xtime_lock); + /* This is revolting. We need to set the xtime.tv_usec * correctly. However, the value in this location is * is value at the last tick. @@ -199,10 +246,13 @@ tv->tv_usec += 1000000; tv->tv_sec--; } + xtime = *tv; - time_state = TIME_BAD; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + write_unlock_irq(&xtime_lock); } @@ -307,13 +357,16 @@ * called as close as possible to 500 ms before the new second starts. */ read_lock(&xtime_lock); - if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec > 500000 - (tick >> 1) && - xtime.tv_usec < 500000 + (tick >> 1)) + if ((time_status & STA_UNSYNC) == 0 + && xtime.tv_sec > last_rtc_update + 660 + && xtime.tv_usec >= 500000 - tick / 2 + && xtime.tv_usec <= 500000 + tick / 2) { if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + /* do it again in 60 s */ + last_rtc_update = xtime.tv_sec - 600; + } /* As we return to user mode fire off the other CPU schedulers.. this is basically because we don't yet share IRQ's around. This message is rigged to be safe on the 386 - basically it's a hack, so don't look @@ -334,66 +387,50 @@ timerhi += (count < timerlo); /* Wrap around */ timerlo = count; - timer_interrupt(irq, dev_id, regs); - - if (!jiffies) { + if (jiffies == ~0) { /* - * If jiffies has overflowed in this timer_interrupt we must + * If jiffies is to overflow in this timer_interrupt we must * update the timer[hi]/[lo] to make do_fast_gettimeoffset() * quotient calc still valid. -arca */ + write_32bit_cp0_register(CP0_COUNT, 0); timerhi = timerlo = 0; } -} -char cyclecounter_available; + timer_interrupt(irq, dev_id, regs); +} -static inline void init_cycle_counter(void) +static void ioasic_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - switch (mips_cputype) { - case CPU_UNKNOWN: - case CPU_R2000: - case CPU_R3000: - case CPU_R3000A: - case CPU_R3041: - case CPU_R3051: - case CPU_R3052: - case CPU_R3081: - case CPU_R3081E: - case CPU_R6000: - case CPU_R6000A: - case CPU_R8000: /* Not shure about that one, play safe */ - cyclecounter_available = 0; - break; - case CPU_R4000PC: - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4200: - case CPU_R4400PC: - case CPU_R4400SC: - case CPU_R4400MC: - case CPU_R4600: - case CPU_R10000: - case CPU_R4300: - case CPU_R4650: - case CPU_R4700: - case CPU_R5000: - case CPU_R5000A: - case CPU_R4640: - case CPU_NEVADA: - cyclecounter_available = 1; - break; + unsigned int count; + + /* + * The free-running counter is 32 bit which is good for about + * 2 minutes, 50 seconds at possible count rates of upto 25MHz. + */ + count = ioasic_read(FCTR); + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + + if (jiffies == ~0) { + /* + * If jiffies is to overflow in this timer_interrupt we must + * update the timer[hi]/[lo] to make do_fast_gettimeoffset() + * quotient calc still valid. -arca + */ + ioasic_write(FCTR, 0); + timerhi = timerlo = 0; } + + timer_interrupt(irq, dev_id, regs); } struct irqaction irq0 = {timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; -void (*board_time_init) (struct irqaction * irq); - void __init time_init(void) { - unsigned int year, mon, day, hour, min, sec; + unsigned int year, mon, day, hour, min, sec, real_year; int i; /* The Linux interpretation of the CMOS clock register contents: @@ -425,23 +462,26 @@ BCD_TO_BIN(year); } /* - * The DECstation RTC is used as a TOY (Time Of Year). - * The PROM will reset the year to either '70, '71 or '72. - * This hack will only work until Dec 31 2001. + * The PROM will reset the year to either '72 or '73. + * Therefore we store the real year separately, in one + * of unused BBU RAM locations. */ - year += 1928; + real_year = CMOS_READ(RTC_DEC_YEAR); + year += real_year - 72 + 2000; write_lock_irq(&xtime_lock); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_usec = 0; write_unlock_irq(&xtime_lock); - init_cycle_counter(); - - if (cyclecounter_available) { + if (mips_cpu.options & MIPS_CPU_COUNTER) { write_32bit_cp0_register(CP0_COUNT, 0); do_gettimeoffset = do_fast_gettimeoffset; irq0.handler = r4k_timer_interrupt; - } + } else if (IOASIC) { + ioasic_write(FCTR, 0); + do_gettimeoffset = do_ioasic_gettimeoffset; + irq0.handler = ioasic_timer_interrupt; + } board_time_init(&irq0); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.4.9/linux/arch/mips/defconfig Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/defconfig Sun Sep 9 10:43:02 2001 @@ -1,6 +1,8 @@ # # Automatically generated make config: don't edit # +CONFIG_MIPS=y +# CONFIG_SMP is not set # # Code maturity level options @@ -13,21 +15,37 @@ # CONFIG_ACER_PICA_61 is not set # CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set -# CONFIG_COBALT_MICRO_SERVER is not set # CONFIG_DECSTATION is not set # CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set # CONFIG_OLIVETTI_M700 is not set CONFIG_SGI_IP22=y # CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set CONFIG_ARC32=y +CONFIG_BOARD_SCACHE=y CONFIG_PC_KEYB=y CONFIG_SGI=y +CONFIG_NEW_IRQ=y +CONFIG_OLD_TIME_C=y # CONFIG_ISA is not set # CONFIG_EISA is not set # CONFIG_PCI is not set +# CONFIG_I8259 is not set # # Loadable module support @@ -41,14 +59,20 @@ # # CONFIG_CPU_R3000 is not set # CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y # CONFIG_CPU_HAS_WB is not set # @@ -59,24 +83,26 @@ CONFIG_ELF_KERNEL=y CONFIG_BINFMT_IRIX=y CONFIG_FORWARD_KEYBOARD=y +# CONFIG_ARC_CONSOLE is not set # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_NET=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # -# Parallel port support +# Memory Technology Devices (MTD) # -# CONFIG_PARPORT is not set -# CONFIG_PCMCIA is not set +# CONFIG_MTD is not set # -# Memory Technology Devices (MTD) +# Parallel port support # -# CONFIG_MTD is not set +# CONFIG_PARPORT is not set # # Block devices @@ -107,19 +133,24 @@ # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK=y +CONFIG_RTNETLINK=y +CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_IPV6 is not set @@ -148,6 +179,13 @@ # CONFIG_NET_SCHED is not set # +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# # SCSI support # CONFIG_SCSI=y @@ -175,7 +213,7 @@ # # SCSI low-level drivers # -CONFIG_SCSI_SGIWD93=y +CONFIG_SGIWD93_SCSI=y # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -183,6 +221,7 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -199,6 +238,7 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set @@ -215,20 +255,159 @@ # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set -# CONFIG_SLIP is not set -# CONFIG_PPP is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set CONFIG_SGISEEQ=y # +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# # SGI Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SGI_NEWPORT_CONSOLE=y CONFIG_FONT_8x16=y -# CONFIG_SGI_PROM_CONSOLE is not set -# CONFIG_UNIX98_PTYS is not set +# CONFIG_PSMOUSE is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # # File systems @@ -238,22 +417,30 @@ CONFIG_AUTOFS4_FS=y # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -261,13 +448,12 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -277,6 +463,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y @@ -309,6 +496,7 @@ # CONFIG_MINIX_SUBPARTITION is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -319,7 +507,7 @@ # Console drivers # # CONFIG_VGA_CONSOLE is not set -# CONFIG_FB is not set +# CONFIG_MDA_CONSOLE is not set # # Frame-buffer support @@ -345,13 +533,111 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking # CONFIG_CROSSCOMPILE=y -# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-atlas linux/arch/mips/defconfig-atlas --- v2.4.9/linux/arch/mips/defconfig-atlas Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/defconfig-atlas Sun Sep 9 10:43:02 2001 @@ -0,0 +1,604 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +CONFIG_MIPS_ATLAS=y +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +CONFIG_PCI=y +CONFIG_SWAP_IO_SPACE=y +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_I8259 is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +CONFIG_BINFMT_IRIX=y +# CONFIG_FORWARD_KEYBOARD is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +# CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_DEBUG_QUEUES is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_SYM53C8XX is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +CONFIG_EFS_FS=y +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set +# CONFIG_LL_DEBUG is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-cobalt linux/arch/mips/defconfig-cobalt --- v2.4.9/linux/arch/mips/defconfig-cobalt Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/defconfig-cobalt Wed Dec 31 16:00:00 1969 @@ -1,598 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set -# CONFIG_BAGET_MIPS is not set -CONFIG_COBALT_MICRO_SERVER=y -CONFIG_COBALT_28=y -# CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_COBALT_27=y -CONFIG_COBALT_LCD=y -CONFIG_COBALT_SERIAL=y -CONFIG_PCI=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# CPU selection -# -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_R5000 is not set -CONFIG_CPU_NEVADA=y -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_WB is not set - -# -# General setup -# -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_NET=y -CONFIG_PCI_NAMES=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set -# CONFIG_PCMCIA is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=m -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -# CONFIG_UNIX is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -CONFIG_IP_MROUTE=y -# CONFIG_IP_PIMSM_V1 is not set -# CONFIG_IP_PIMSM_V2 is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set - -# -# -# -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=m -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AIC7XXX=y -CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 -CONFIG_AIC7XXX_RESET_DELAY=5 -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -CONFIG_SCSI_NCR53C8XX=y -# CONFIG_SCSI_SYM53C8XX is not set -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 -CONFIG_SCSI_NCR53C8XX_SYNC=5 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -CONFIG_SCSI_NCR53C8XX_IOMAPPED=y -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# Appletalk devices -# -# CONFIG_APPLETALK is not set -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -# CONFIG_SLIP_MODE_SLIP6 is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -# CONFIG_ISDN_PPP_BSDCOMP is not set -CONFIG_ISDN_AUDIO=y -# CONFIG_ISDN_TTY_FAX is not set - -# -# ISDN feature submodules -# -# CONFIG_ISDN_DRV_LOOP is not set -# CONFIG_ISDN_DIVERSION is not set - -# -# low-level hardware drivers -# - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m - -# -# D-channel protocol features -# -CONFIG_HISAX_EURO=y -CONFIG_DE_AOC=y -# CONFIG_HISAX_NO_SENDCOMPLETE is not set -# CONFIG_HISAX_NO_LLC is not set -# CONFIG_HISAX_NO_KEYPAD is not set -CONFIG_HISAX_1TR6=y -# CONFIG_HISAX_NI1 is not set - -# -# HiSax supported cards -# -# CONFIG_HISAX_16_0 is not set -# CONFIG_HISAX_16_3 is not set -# CONFIG_HISAX_TELESPCI is not set -# CONFIG_HISAX_S0BOX is not set -# CONFIG_HISAX_AVM_A1 is not set -# CONFIG_HISAX_FRITZPCI is not set -# CONFIG_HISAX_AVM_A1_PCMCIA is not set -CONFIG_HISAX_ELSA=y -# CONFIG_HISAX_IX1MICROR2 is not set -# CONFIG_HISAX_DIEHLDIVA is not set -# CONFIG_HISAX_ASUSCOM is not set -# CONFIG_HISAX_TELEINT is not set -# CONFIG_HISAX_HFCS is not set -# CONFIG_HISAX_SEDLBAUER is not set -# CONFIG_HISAX_SPORTSTER is not set -# CONFIG_HISAX_MIC is not set -# CONFIG_HISAX_NETJET is not set -# CONFIG_HISAX_NETJET_U is not set -# CONFIG_HISAX_NICCY is not set -# CONFIG_HISAX_ISURF is not set -# CONFIG_HISAX_HSTSAPHIR is not set -# CONFIG_HISAX_BKM_A4T is not set -# CONFIG_HISAX_SCT_QUADRO is not set -# CONFIG_HISAX_GAZEL is not set -# CONFIG_HISAX_HFC_PCI is not set -# CONFIG_HISAX_W6692 is not set -# CONFIG_HISAX_HFC_SX is not set -# CONFIG_HISAX_SEDLBAUER_CS is not set - -# -# Active ISDN cards -# -# CONFIG_ISDN_DRV_ICN is not set -# CONFIG_ISDN_DRV_PCBIT is not set -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -# CONFIG_ISDN_DRV_EICON is not set -# CONFIG_ISDN_CAPI is not set -# CONFIG_HYSDN is not set -# CONFIG_HYSDN_CAPI is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set - -# -# Input core support is needed for joysticks -# -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_RAMFS is not set -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_ISO8859_9=m -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_UTF8=m - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# Input core support -# -# CONFIG_INPUT is not set - -# -# Kernel hacking -# -# CONFIG_CROSSCOMPILE is not set -# CONFIG_MIPS_FPE_MODULE is not set -# CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-ddb5476 linux/arch/mips/defconfig-ddb5476 --- v2.4.9/linux/arch/mips/defconfig-ddb5476 Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/defconfig-ddb5476 Sun Sep 9 10:43:01 2001 @@ -25,19 +25,25 @@ # CONFIG_MIPS_MAGNUM_4000 is not set # CONFIG_MOMENCO_OCELOT is not set CONFIG_DDB5476=y +# CONFIG_DDB5477 is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set # CONFIG_SNI_RM200_PCI is not set # CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set -CONFIG_I8259=y CONFIG_ISA=y CONFIG_PCI=y CONFIG_PC_KEYB=y CONFIG_ROTTEN_IRQ=y +CONFIG_HAVE_STD_PC_SERIAL_PORT=y +CONFIG_NEW_TIME_C=y CONFIG_EISA=y +# CONFIG_I8259 is not set # # Loadable module support @@ -48,26 +54,27 @@ # CPU selection # # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R3912 is not set # CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set # CONFIG_CPU_R5000 is not set CONFIG_CPU_R5432=y # CONFIG_CPU_RM7000 is not set # CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set # CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y # CONFIG_CPU_HAS_WB is not set # # General setup # CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_MIPS_FPU_EMULATOR=y CONFIG_KCORE_ELF=y CONFIG_ELF_KERNEL=y # CONFIG_BINFMT_AOUT is not set @@ -75,21 +82,18 @@ # CONFIG_BINFMT_MISC is not set CONFIG_NET=y # CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # -# Parallel port support -# -# CONFIG_PARPORT is not set - -# # Plug and Play configuration # # CONFIG_PNP is not set # CONFIG_ISAPNP is not set -# CONFIG_PCMCIA is not set +# CONFIG_PNPBIOS is not set # # Memory Technology Devices (MTD) @@ -97,6 +101,11 @@ # CONFIG_MTD is not set # +# Parallel port support +# +# CONFIG_PARPORT is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set @@ -134,6 +143,7 @@ # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set @@ -170,6 +180,7 @@ # # CONFIG_PHONE is not set # CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set # # ATA/IDE/MFM/RLL support @@ -213,6 +224,7 @@ CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set # CONFIG_BLK_DEV_IDEDMA_PCI is not set +# CONFIG_BLK_DEV_ADMA is not set # CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_IDEDMA_PCI_AUTO is not set # CONFIG_BLK_DEV_IDEDMA is not set @@ -222,8 +234,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 is not set # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -234,7 +246,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 @@ -243,6 +256,9 @@ # CONFIG_IDEDMA_AUTO is not set # CONFIG_DMA_NONPCI is not set # CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set # # SCSI support @@ -250,16 +266,6 @@ # CONFIG_SCSI is not set # -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -272,12 +278,17 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set @@ -293,25 +304,28 @@ # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set # CONFIG_DE4X5 is not set # CONFIG_DGRS is not set # CONFIG_DM9102 is not set CONFIG_EEPRO100=y -# CONFIG_EEPRO100_PM is not set # CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set CONFIG_NE2K_PCI=y # CONFIG_NE3210 is not set # CONFIG_ES3210 is not set # CONFIG_8139TOO is not set -# CONFIG_RTL8129 is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_WINBOND_840 is not set -# CONFIG_HAPPYMEAL is not set # CONFIG_LAN_SAA9730 is not set # CONFIG_NET_POCKET is not set @@ -319,11 +333,15 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -346,6 +364,16 @@ # CONFIG_WAN is not set # +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -364,7 +392,8 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # # I2C support @@ -383,7 +412,11 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# # # Input core support is needed for joysticks @@ -400,6 +433,7 @@ # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -421,22 +455,30 @@ # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -444,13 +486,12 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -460,6 +501,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y @@ -490,7 +532,7 @@ # Console drivers # # CONFIG_VGA_CONSOLE is not set -CONFIG_FB=y +# CONFIG_MDA_CONSOLE is not set # # Frame-buffer support @@ -501,11 +543,13 @@ # CONFIG_FB_CLGEN is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_E1355 is not set # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set -CONFIG_FB_3DFX=y # CONFIG_FB_SIS is not set +CONFIG_FB_3DFX=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB8=y @@ -527,15 +571,114 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking # CONFIG_CROSSCOMPILE=y # CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set # CONFIG_LL_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set # CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-ddb5477 linux/arch/mips/defconfig-ddb5477 --- v2.4.9/linux/arch/mips/defconfig-ddb5477 Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/defconfig-ddb5477 Sun Sep 9 10:43:01 2001 @@ -0,0 +1,565 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +CONFIG_DDB5477=y +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_PCI=y +CONFIG_NEW_TIME_C=y +CONFIG_NEW_IRQ=y +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_I8259 is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +CONFIG_CPU_R5432=y +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +# CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_LAN_SAA9730 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set +CONFIG_LL_DEBUG=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-decstation linux/arch/mips/defconfig-decstation --- v2.4.9/linux/arch/mips/defconfig-decstation Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/defconfig-decstation Sun Sep 9 10:43:01 2001 @@ -1,6 +1,8 @@ # # Automatically generated make config: don't edit # +CONFIG_MIPS=y +# CONFIG_SMP is not set # # Code maturity level options @@ -13,18 +15,31 @@ # CONFIG_ACER_PICA_61 is not set # CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set -# CONFIG_COBALT_MICRO_SERVER is not set CONFIG_DECSTATION=y # CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set # CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set # CONFIG_ISA is not set # CONFIG_EISA is not set # CONFIG_PCI is not set +# CONFIG_I8259 is not set # # Loadable module support @@ -38,15 +53,21 @@ # CONFIG_CPU_R3000=y # CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set # CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set # CONFIG_CPU_HAS_LLSC is not set -CONFIG_CPU_HAS_WB=y +# CONFIG_CPU_HAS_LLDSCD is not set +# CONFIG_CPU_HAS_WB is not set # # General setup @@ -58,16 +79,12 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_NET=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set CONFIG_TC=y -# CONFIG_PCMCIA is not set # # Memory Technology Devices (MTD) @@ -75,6 +92,11 @@ # CONFIG_MTD is not set # +# Parallel port support +# +# CONFIG_PARPORT is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set @@ -112,6 +134,7 @@ # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set @@ -144,6 +167,13 @@ # CONFIG_NET_SCHED is not set # +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# # SCSI support # CONFIG_SCSI=y @@ -178,6 +208,7 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -194,6 +225,7 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set @@ -210,12 +242,149 @@ # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set -# CONFIG_SLIP is not set -# CONFIG_PPP is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set CONFIG_DECLANCE=y # +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# # DECStation Character devices # # CONFIG_VT is not set @@ -223,7 +392,8 @@ # CONFIG_DZ is not set CONFIG_ZS=y CONFIG_SERIAL_CONSOLE=y -# CONFIG_UNIX98_PTYS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # CONFIG_RTC is not set # @@ -234,22 +404,30 @@ # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -257,13 +435,12 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -273,6 +450,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set # CONFIG_NFS_FS is not set # CONFIG_NFS_V3 is not set # CONFIG_ROOT_NFS is not set @@ -305,6 +483,7 @@ # CONFIG_MINIX_SUBPARTITION is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set # CONFIG_SGI_PARTITION is not set CONFIG_ULTRIX_PARTITION=y # CONFIG_SUN_PARTITION is not set @@ -317,14 +496,114 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking # CONFIG_CROSSCOMPILE=y -# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set +# CONFIG_LL_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-ip22 linux/arch/mips/defconfig-ip22 --- v2.4.9/linux/arch/mips/defconfig-ip22 Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/defconfig-ip22 Sun Sep 9 10:43:02 2001 @@ -1,6 +1,8 @@ # # Automatically generated make config: don't edit # +CONFIG_MIPS=y +# CONFIG_SMP is not set # # Code maturity level options @@ -13,21 +15,37 @@ # CONFIG_ACER_PICA_61 is not set # CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set -# CONFIG_COBALT_MICRO_SERVER is not set # CONFIG_DECSTATION is not set # CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set # CONFIG_OLIVETTI_M700 is not set CONFIG_SGI_IP22=y # CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set CONFIG_ARC32=y +CONFIG_BOARD_SCACHE=y CONFIG_PC_KEYB=y CONFIG_SGI=y +CONFIG_NEW_IRQ=y +CONFIG_OLD_TIME_C=y # CONFIG_ISA is not set # CONFIG_EISA is not set # CONFIG_PCI is not set +# CONFIG_I8259 is not set # # Loadable module support @@ -41,14 +59,20 @@ # # CONFIG_CPU_R3000 is not set # CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y # CONFIG_CPU_HAS_WB is not set # @@ -59,24 +83,26 @@ CONFIG_ELF_KERNEL=y CONFIG_BINFMT_IRIX=y CONFIG_FORWARD_KEYBOARD=y +# CONFIG_ARC_CONSOLE is not set # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_NET=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # -# Parallel port support +# Memory Technology Devices (MTD) # -# CONFIG_PARPORT is not set -# CONFIG_PCMCIA is not set +# CONFIG_MTD is not set # -# Memory Technology Devices (MTD) +# Parallel port support # -# CONFIG_MTD is not set +# CONFIG_PARPORT is not set # # Block devices @@ -107,19 +133,24 @@ # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK=y +CONFIG_RTNETLINK=y +CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_IPV6 is not set @@ -148,6 +179,13 @@ # CONFIG_NET_SCHED is not set # +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# # SCSI support # CONFIG_SCSI=y @@ -175,7 +213,7 @@ # # SCSI low-level drivers # -CONFIG_SCSI_SGIWD93=y +CONFIG_SGIWD93_SCSI=y # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -183,6 +221,7 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -199,6 +238,7 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set @@ -215,20 +255,159 @@ # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set -# CONFIG_SLIP is not set -# CONFIG_PPP is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set CONFIG_SGISEEQ=y # +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# # SGI Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SGI_NEWPORT_CONSOLE=y CONFIG_FONT_8x16=y -# CONFIG_SGI_PROM_CONSOLE is not set -# CONFIG_UNIX98_PTYS is not set +# CONFIG_PSMOUSE is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # # File systems @@ -238,22 +417,30 @@ CONFIG_AUTOFS4_FS=y # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -261,13 +448,12 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -277,6 +463,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y @@ -309,6 +496,7 @@ # CONFIG_MINIX_SUBPARTITION is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -319,7 +507,7 @@ # Console drivers # # CONFIG_VGA_CONSOLE is not set -# CONFIG_FB is not set +# CONFIG_MDA_CONSOLE is not set # # Frame-buffer support @@ -345,13 +533,111 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking # CONFIG_CROSSCOMPILE=y -# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-it8172 linux/arch/mips/defconfig-it8172 --- v2.4.9/linux/arch/mips/defconfig-it8172 Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/defconfig-it8172 Sun Sep 9 10:43:02 2001 @@ -25,6 +25,7 @@ # CONFIG_MIPS_MAGNUM_4000 is not set # CONFIG_MOMENCO_OCELOT is not set # CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set # CONFIG_SNI_RM200_PCI is not set @@ -35,11 +36,16 @@ # CONFIG_IT8172_SCR0 is not set # CONFIG_IT8172_SCR1 is not set # CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set CONFIG_PCI=y CONFIG_IT8712=y CONFIG_PC_KEYB=y +CONFIG_NEW_PCI=y +CONFIG_PCI_AUTO=y # CONFIG_ISA is not set # CONFIG_EISA is not set # CONFIG_I8259 is not set @@ -55,26 +61,27 @@ # CPU selection # # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R3912 is not set # CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set # CONFIG_CPU_RM7000 is not set CONFIG_CPU_NEVADA=y -# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set # CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y # CONFIG_CPU_HAS_WB is not set # # General setup # CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_MIPS_FPU_EMULATOR=y CONFIG_KCORE_ELF=y CONFIG_ELF_KERNEL=y # CONFIG_BINFMT_AOUT is not set @@ -82,68 +89,87 @@ # CONFIG_BINFMT_MISC is not set CONFIG_NET=y CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y # -# Parallel port support -# -# CONFIG_PARPORT is not set -# CONFIG_PCMCIA is not set - -# # Memory Technology Devices (MTD) # CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_PARTITIONS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_BOOTLDR_PARTS is not set # -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC1000 is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set - +# User Modules And Translation Layers # -# RAM/ROM Device Drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_MTDRAM is not set +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set # -# Linearly Mapped Flash Device Drivers +# RAM/ROM/Flash chip drivers # CONFIG_MTD_CFI=y +# CONFIG_MTD_CFI_VIRTUAL_ER is not set +# CONFIG_MTD_CFI_ADV_OPTIONS is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# CONFIG_MTD_PHYSMAP=y CONFIG_MTD_PHYSMAP_START=8000000 CONFIG_MTD_PHYSMAP_LEN=2000000 CONFIG_MTD_PHYSMAP_BUSWIDTH=4 - -# -# Drivers for chip mappings -# -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_OCTAGON is not set # CONFIG_MTD_PNC2000 is not set # CONFIG_MTD_RPXLITE is not set +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_ELAN_104NC is not set +# CONFIG_MTD_DBOX2 is not set +# CONFIG_MTD_CSTM_MIPS_IXX is not set +# CONFIG_MTD_CFI_FLAGADM is not set +# CONFIG_MTD_MIXMEM is not set +# CONFIG_MTD_OCTAGON is not set # CONFIG_MTD_VMAX is not set +# CONFIG_MTD_OCELOT is not set # -# User modules and translation layers for MTD devices +# Self-contained MTD device drivers # -CONFIG_MTD_CHAR=y -# CONFIG_MTD_BLOCK is not set -# CONFIG_FTL is not set -# CONFIG_NFTL is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set # # Block devices @@ -182,6 +208,7 @@ # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set @@ -218,6 +245,7 @@ # # CONFIG_PHONE is not set # CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set # # ATA/IDE/MFM/RLL support @@ -261,6 +289,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 @@ -270,8 +299,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 is not set # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -280,11 +309,14 @@ # CONFIG_BLK_DEV_HPT366 is not set CONFIG_BLK_DEV_IT8172=y CONFIG_IT8172_TUNING=y +CONFIG_BLK_DEV_IT8172=y +CONFIG_IT8172_TUNING=y # CONFIG_BLK_DEV_NS87415 is not set # 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 @@ -299,12 +331,15 @@ # CONFIG_BLK_DEV_DTC2278 is not set # CONFIG_BLK_DEV_HT6560B is not set # CONFIG_BLK_DEV_PDC4030 is not set -# CONFIG_BLK_DEV_QD6580 is not set +# CONFIG_BLK_DEV_QD65XX is not set # CONFIG_BLK_DEV_UMC8672 is not set CONFIG_IDEDMA_AUTO=y # CONFIG_IDEDMA_IVB is not set # CONFIG_DMA_NONPCI is not set CONFIG_BLK_DEV_IDE_MODES=y +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set # # SCSI support @@ -312,16 +347,6 @@ # CONFIG_SCSI is not set # -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -334,18 +359,21 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set CONFIG_NET_PCI=y @@ -354,25 +382,28 @@ # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set # CONFIG_DE4X5 is not set # CONFIG_DGRS is not set # CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set -# CONFIG_EEPRO100_PM is not set # CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set # CONFIG_NE3210 is not set # CONFIG_ES3210 is not set CONFIG_8139TOO=y -# CONFIG_RTL8129 is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_WINBOND_840 is not set -# CONFIG_HAPPYMEAL is not set # CONFIG_LAN_SAA9730 is not set # CONFIG_NET_POCKET is not set @@ -380,11 +411,15 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -407,6 +442,16 @@ # CONFIG_WAN is not set # +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -424,7 +469,12 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set +CONFIG_QTRONIX_KEYBOARD=y +CONFIG_IT8172_CIR=y +# CONFIG_IT8172_SCR0 is not set +# CONFIG_IT8172_SCR1 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # # I2C support @@ -440,7 +490,11 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# # # Input core support is needed for joysticks @@ -457,6 +511,7 @@ # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -464,6 +519,7 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_ITE_GPIO is not set # # Multimedia devices @@ -478,22 +534,30 @@ # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -501,13 +565,12 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -517,6 +580,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y @@ -554,16 +618,114 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking # CONFIG_CROSSCOMPILE=y -# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set # CONFIG_LL_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set # CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-malta linux/arch/mips/defconfig-malta --- v2.4.9/linux/arch/mips/defconfig-malta Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/defconfig-malta Sun Sep 9 10:43:02 2001 @@ -0,0 +1,630 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +CONFIG_MIPS_MALTA=y +# CONFIG_NINO is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +CONFIG_I8259=y +CONFIG_PCI=y +CONFIG_HAVE_STD_PC_SERIAL_PORT=y +CONFIG_NEW_IRQ=y +CONFIG_SWAP_IO_SPACE=y +# CONFIG_ISA is not set +# CONFIG_EISA is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_HAS_LLDSCD is not set +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +# CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_DEBUG_QUEUES is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_SYM53C8XX is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_LAN_SAA9730 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +CONFIG_EFS_FS=y +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set +# CONFIG_LL_DEBUG is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-nino linux/arch/mips/defconfig-nino --- v2.4.9/linux/arch/mips/defconfig-nino Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/defconfig-nino Sun Sep 9 10:43:02 2001 @@ -0,0 +1,415 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +CONFIG_NINO=y +# CONFIG_NINO_4MB is not set +CONFIG_NINO_8MB=y +# CONFIG_NINO_16MB is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +CONFIG_PC_KEYB=y +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_PCI is not set +# CONFIG_I8259 is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# CPU selection +# +CONFIG_CPU_R3000=y +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_ADVANCED is not set +# CONFIG_CPU_HAS_LLSC is not set +# CONFIG_CPU_HAS_LLDSCD is not set +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +# CONFIG_NET is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=2048 +CONFIG_BLK_DEV_INITRD=y + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# ISDN subsystem +# + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +CONFIG_SERIAL_TX3912=y +CONFIG_SERIAL_TX3912_CONSOLE=y +# CONFIG_AU1000_UART is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_SMB_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# + +# +# Networking support is needed for USB Networking device support +# + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-ocelot linux/arch/mips/defconfig-ocelot --- v2.4.9/linux/arch/mips/defconfig-ocelot Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/defconfig-ocelot Sun Sep 9 10:43:02 2001 @@ -0,0 +1,566 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +CONFIG_MOMENCO_OCELOT=y +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +CONFIG_PCI=y +CONFIG_SYSCLK_100=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_NEW_IRQ=y +CONFIG_OLD_TIME_C=y +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_I8259 is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +CONFIG_CPU_RM7000=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +# CONFIG_BINFMT_IRIX is not set +# CONFIG_FORWARD_KEYBOARD is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +CONFIG_EEPRO100=y +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_LAN_SAA9730 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set +# CONFIG_LL_DEBUG is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-orion linux/arch/mips/defconfig-orion --- v2.4.9/linux/arch/mips/defconfig-orion Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/defconfig-orion Wed Dec 31 16:00:00 1969 @@ -1,304 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_COBALT_MICRO_SERVER is not set -# CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_PCI is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# CPU selection -# -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -CONFIG_CPU_R5000=y -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_WB is not set - -# -# General setup -# -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -# CONFIG_BINFMT_IRIX is not set -# CONFIG_FORWARD_KEYBOARD is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set -# CONFIG_PCMCIA is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -# CONFIG_UNIX is not set -# CONFIG_INET is not set -# CONFIG_ATM is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET_AUNUDP is not set -# CONFIG_ECONET_NATIVE is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Network device support -# -# CONFIG_NETDEVICES is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set - -# -# Input core support is needed for joysticks -# -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_CRAMFS is not set -CONFIG_RAMFS=y -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_NFS_FS is not set -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_SUNRPC is not set -# CONFIG_LOCKD is not set -# CONFIG_SMB_FS is not set -# CONFIG_NCPFS_NLS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# Input core support -# -# CONFIG_INPUT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-pb1000 linux/arch/mips/defconfig-pb1000 --- v2.4.9/linux/arch/mips/defconfig-pb1000 Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/defconfig-pb1000 Sun Sep 9 10:43:02 2001 @@ -0,0 +1,565 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +CONFIG_MIPS_PB1000=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +CONFIG_MIPS_AU1000=y +CONFIG_NEW_IRQ=y +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_PCI is not set +# CONFIG_I8259 is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +CONFIG_CPU_ADVANCED=y +CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_HAS_LLDSCD is not set +CONFIG_CPU_HAS_WB=y + +# +# General setup +# +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MIPS_AU1000_ENET=y +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_SYNCLINK is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +# CONFIG_SERIAL_TX3912 is not set +# CONFIG_SERIAL_TX3912_CONSOLE is not set +CONFIG_AU1000_UART=y +CONFIG_AU1000_SERIAL_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/defconfig-rm200 linux/arch/mips/defconfig-rm200 --- v2.4.9/linux/arch/mips/defconfig-rm200 Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/defconfig-rm200 Sun Sep 9 10:43:02 2001 @@ -1,6 +1,8 @@ # # Automatically generated make config: don't edit # +CONFIG_MIPS=y +# CONFIG_SMP is not set # # Code maturity level options @@ -13,19 +15,34 @@ # CONFIG_ACER_PICA_61 is not set # CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set -# CONFIG_COBALT_MICRO_SERVER is not set # CONFIG_DECSTATION is not set # CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set CONFIG_SNI_RM200_PCI=y +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set CONFIG_ARC32=y -CONFIG_PCI=y +CONFIG_I8259=y CONFIG_ISA=y CONFIG_PC_KEYB=y +CONFIG_PCI=y +CONFIG_ROTTEN_IRQ=y +CONFIG_OLD_TIME_C=y CONFIG_EISA=y # @@ -40,14 +57,20 @@ # # CONFIG_CPU_R3000 is not set # CONFIG_CPU_R6000 is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y # CONFIG_CPU_HAS_WB is not set # @@ -56,26 +79,24 @@ CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_KCORE_ELF=y CONFIG_ELF_KERNEL=y +# CONFIG_ARC_CONSOLE is not set # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_NET=y # CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # -# Parallel port support -# -# CONFIG_PARPORT is not set - -# # Plug and Play configuration # # CONFIG_PNP is not set # CONFIG_ISAPNP is not set -# CONFIG_PCMCIA is not set +# CONFIG_PNPBIOS is not set # # Memory Technology Devices (MTD) @@ -83,6 +104,11 @@ # CONFIG_MTD is not set # +# Parallel port support +# +# CONFIG_PARPORT is not set + +# # Block devices # CONFIG_BLK_DEV_FD=y @@ -154,6 +180,7 @@ # # CONFIG_PHONE is not set # CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set # # ATA/IDE/MFM/RLL support @@ -168,19 +195,19 @@ # CONFIG_SCSI is not set # -# I2O device support +# Network device support # -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set +# CONFIG_NETDEVICES is not set # -# Network device support +# Amateur Radio support # -# CONFIG_NETDEVICES is not set +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set # # ISDN subsystem @@ -200,7 +227,8 @@ # CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # # I2C support @@ -216,7 +244,11 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# # # Input core support is needed for joysticks @@ -233,6 +265,7 @@ # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -254,22 +287,30 @@ # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -277,13 +318,12 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -293,6 +333,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set # CONFIG_NFS_FS is not set # CONFIG_NFS_V3 is not set # CONFIG_ROOT_NFS is not set @@ -325,6 +366,7 @@ # CONFIG_MINIX_SUBPARTITION is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -335,7 +377,7 @@ # Console drivers # CONFIG_VGA_CONSOLE=y -# CONFIG_FB is not set +# CONFIG_MDA_CONSOLE is not set # # Frame-buffer support @@ -353,13 +395,111 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking # CONFIG_CROSSCOMPILE=y -# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/common/Makefile linux/arch/mips/gt64120/common/Makefile --- v2.4.9/linux/arch/mips/gt64120/common/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/common/Makefile Sun Sep 9 10:43:01 2001 @@ -0,0 +1,18 @@ +# +# Makefile for common code of gt64120-based boards. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET:= gt64120.o + +obj-y := gt_irq.o pci.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/common/gt_irq.c linux/arch/mips/gt64120/common/gt_irq.c --- v2.4.9/linux/arch/mips/gt64120/common/gt_irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/common/gt_irq.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,250 @@ +/* + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/gt64120/common/gt_irq.c + * Interrupt routines for gt64120. Currently it only handles timer irq. + * + * 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 + +/* + * These are interrupt handlers for the GT on-chip interrupts. They + * all come in to the MIPS on a single interrupt line, and have to + * be handled and ack'ed differently than other MIPS interrupts. + */ + +#if CURRENTLY_UNUSED + +struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; +void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); + +/* + * Hooks IRQ handler to the system. When the system is interrupted + * the interrupt service routine is called. + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * isr_ptr - Pointer to the interrupt service routine + */ +void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr) +{ + irq_handlers[int_cause][bit_num].routine = isr_ptr; +} + + +/* + * Enables the IRQ on Galileo Chip + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * + * Outputs : + * 1 if succesful, 0 if failure + */ +int enable_galileo_irq(int int_cause, int bit_num) +{ + if (int_cause == INT_CAUSE_MAIN) + SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num)); + else if (int_cause == INT_CAUSE_HIGH) + SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else + return 0; + + return 1; +} + +/* + * Disables the IRQ on Galileo Chip + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * + * Outputs : + * 1 if succesful, 0 if failure + */ +int disable_galileo_irq(int int_cause, int bit_num) +{ + if (int_cause == INT_CAUSE_MAIN) + RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else if (int_cause == INT_CAUSE_HIGH) + RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else + return 0; + return 1; +} +#endif /* UNUSED */ + +/* + * Interrupt handler for interrupts coming from the Galileo chip. + * It could be timer interrupt, built in ethernet ports etc... + */ +static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int irq_src, int_high_src, irq_src_mask, + int_high_src_mask; + int handled; + + GT_READ(GT_INTRCAUSE_OFS, &irq_src); + GT_READ(GT_INTRMASK_OFS, &irq_src_mask); + GT_READ(GT_HINTRCAUSE_OFS, &int_high_src); + GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask); + irq_src = irq_src & irq_src_mask; + int_high_src = int_high_src & int_high_src_mask; + + handled = 0; + + /* Execute all interrupt handlers */ + /* Check for timer interrupt */ + if (irq_src & 0x00000800) { + handled = 1; + irq_src &= ~0x00000800; + // RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8); + do_timer(regs); + } + + if (irq_src) { + printk(KERN_INFO + "Other Galileo interrupt received irq_src %x\n", + irq_src); +#if CURRENTLY_UNUSED + for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) { + if (irq_src & (1 << count)) { + if (irq_handlers[INT_CAUSE_MAIN][count]. + routine) { + queue_task(&irq_handlers + [INT_CAUSE_MAIN][count], + &tq_immediate); + mark_bh(IMMEDIATE_BH); + handled = 1; + } + } + } +#endif /* UNUSED */ + } + GT_WRITE(GT_INTRCAUSE_OFS, 0); + GT_WRITE(GT_HINTRCAUSE_OFS, 0); + +#undef GALILEO_I2O +#ifdef GALILEO_I2O + /* + * Future I2O support. We currently attach I2O interrupt handlers to + * the Galileo interrupt (int 4) and handle them in do_IRQ. + */ + if (isInBoundDoorBellInterruptSet()) { + printk(KERN_INFO "I2O doorbell interrupt received.\n"); + handled = 1; + } + + if (isInBoundPostQueueInterruptSet()) { + printk(KERN_INFO "I2O Queue interrupt received.\n"); + handled = 1; + } + + /* + * This normally would be outside of the ifdef, but since we're + * handling I2O outside of this handler, this printk shows up every + * time we get a valid I2O interrupt. So turn this off for now. + */ + if (handled == 0) { + if (counter < 50) { + printk("Spurious Galileo interrupt...\n"); + counter++; + } + } +#endif +} + +/* + * Initializes timer using galileo's built in timer. + */ +#ifdef CONFIG_SYSCLK_100 +#define Sys_clock (100 * 1000000) // 100 MHz +#endif +#ifdef CONFIG_SYSCLK_83 +#define Sys_clock (83.333 * 1000000) // 83.333 MHz +#endif +#ifdef CONFIG_SYSCLK_75 +#define Sys_clock (75 * 1000000) // 75 MHz +#endif + +/* + * This will ignore the standard MIPS timer interrupt handler + * that is passed in as *irq (=irq0 in ../kernel/time.c). + * We will do our own timer interrupt handling. + */ +void gt64120_time_init(void) +{ + extern irq_desc_t irq_desc[NR_IRQS]; + static struct irqaction timer; + + /* Disable timer first */ + GT_WRITE(GT_TC_CONTROL_OFS, 0); + /* Load timer value for 100 Hz */ + GT_WRITE(GT_TC3_OFS, Sys_clock / 100); + + /* + * Create the IRQ structure entry for the timer. Since we're too early + * in the boot process to use the "request_irq()" call, we'll hard-code + * the values to the correct interrupt line. + */ + timer.handler = >64120_irq; + timer.flags = SA_SHIRQ | SA_INTERRUPT; + timer.name = "timer"; + timer.dev_id = NULL; + timer.next = NULL; + timer.mask = 0; + irq_desc[TIMER].action = &timer; + + enable_irq(TIMER); + + /* Enable timer ints */ + GT_WRITE(GT_TC_CONTROL_OFS, 0xc0); + /* clear Cause register first */ + GT_WRITE(GT_INTRCAUSE_OFS, 0x0); + /* Unmask timer int */ + GT_WRITE(GT_INTRMASK_OFS, 0x800); + /* Clear High int register */ + GT_WRITE(GT_HINTRCAUSE_OFS, 0x0); + /* Mask All interrupts at High cause interrupt */ + GT_WRITE(GT_HINTRMASK_OFS, 0x0); +} + +void gt64120_irq_init(void) +{ +#if CURRENTLY_UNUSED + int i, j; + + /* Reset irq handlers pointers to NULL */ + for (i = 0; i < MAX_CAUSE_REGS; i++) { + for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) { + irq_handlers[i][j].next = NULL; + irq_handlers[i][j].sync = 0; + irq_handlers[i][j].routine = NULL; + irq_handlers[i][j].data = NULL; + } + } +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/common/pci.c linux/arch/mips/gt64120/common/pci.c --- v2.4.9/linux/arch/mips/gt64120/common/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/common/pci.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,1145 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo Evaluation Boards PCI support. + * + * The general-purpose functions to read/write and configure the GT64120A's + * PCI registers (function names start with pci0 or pci1) are either direct + * copies of functions written by Galileo Technology, or are modifications + * of their functions to work with Linux 2.4 vs Linux 2.2. These functions + * are Copyright - Galileo Technology. + * + * Other functions are derived from other MIPS PCI implementations, or were + * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_PCI + +#define SELF 0 + +/* + * These functions and structures provide the BIOS scan and mapping of the PCI + * devices. + */ + +#define MAX_PCI_DEVS 10 + +struct pci_device { + u32 slot; + u32 BARtype[6]; + u32 BARsize[6]; +}; + +static void __init scan_and_initialize_pci(void); +static u32 __init scan_pci_bus(struct pci_device *pci_devices); +static void __init allocate_pci_space(struct pci_device *pci_devices); + +/* + * The functions that actually read and write to the controller. + * + * Copied from or modified from Galileo Technology code. + */ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device); +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data); +static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device); +static void pci1WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data); + +static void pci0MapIOspace(unsigned int pci0IoBase, + unsigned int pci0IoLength); +static void pci1MapIOspace(unsigned int pci1IoBase, + unsigned int pci1IoLength); +static void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length); +static void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length); +static void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length); +static void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length); +static unsigned int pci0GetIOspaceBase(void); +static unsigned int pci0GetIOspaceSize(void); +static unsigned int pci0GetMemory0Base(void); +static unsigned int pci0GetMemory0Size(void); +static unsigned int pci0GetMemory1Base(void); +static unsigned int pci0GetMemory1Size(void); +static unsigned int pci1GetIOspaceBase(void); +static unsigned int pci1GetIOspaceSize(void); +static unsigned int pci1GetMemory0Base(void); +static unsigned int pci1GetMemory0Size(void); +static unsigned int pci1GetMemory1Base(void); +static unsigned int pci1GetMemory1Size(void); + + +/* Functions to implement "pci ops" */ +static int galileo_pcibios_read_config_word(struct pci_dev *dev, + int offset, u16 * val); +static int galileo_pcibios_read_config_byte(struct pci_dev *dev, + int offset, u8 * val); +static int galileo_pcibios_read_config_dword(struct pci_dev *dev, + int offset, u32 * val); +static int galileo_pcibios_write_config_byte(struct pci_dev *dev, + int offset, u8 val); +static int galileo_pcibios_write_config_word(struct pci_dev *dev, + int offset, u16 val); +static int galileo_pcibios_write_config_dword(struct pci_dev *dev, + int offset, u32 val); +static void galileo_pcibios_set_master(struct pci_dev *dev); + +/* + * General-purpose PCI functions. + */ + +/* + * pci0MapIOspace - Maps PCI0 IO space for the master. + * Inputs: base and length of pci0Io + */ + +static void pci0MapIOspace(unsigned int pci0IoBase, + unsigned int pci0IoLength) +{ + unsigned int pci0IoTop = + (unsigned int) (pci0IoBase + pci0IoLength); + + if (pci0IoLength == 0) + pci0IoTop++; + + pci0IoBase = (unsigned int) (pci0IoBase >> 21); + pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21); + GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase); + GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop); +} + +/* + * pci1MapIOspace - Maps PCI1 IO space for the master. + * Inputs: base and length of pci1Io + */ + +static void pci1MapIOspace(unsigned int pci1IoBase, + unsigned int pci1IoLength) +{ + unsigned int pci1IoTop = + (unsigned int) (pci1IoBase + pci1IoLength); + + if (pci1IoLength == 0) + pci1IoTop++; + + pci1IoBase = (unsigned int) (pci1IoBase >> 21); + pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21); + GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase); + GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop); +} + +/* + * pci0MapMemory0space - Maps PCI0 memory0 space for the master. + * Inputs: base and length of pci0Mem0 + */ + +static void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length) +{ + unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length; + + if (pci0Mem0Length == 0) + pci0Mem0Top++; + + pci0Mem0Base = pci0Mem0Base >> 21; + pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base); + GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top); +} + +/* + * pci1MapMemory0space - Maps PCI1 memory0 space for the master. + * Inputs: base and length of pci1Mem0 + */ + +static void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length) +{ + unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length; + + if (pci1Mem0Length == 0) + pci1Mem0Top++; + + pci1Mem0Base = pci1Mem0Base >> 21; + pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base); + GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top); +} + +/* + * pci0MapMemory1space - Maps PCI0 memory1 space for the master. + * Inputs: base and length of pci0Mem1 + */ + +static void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length) +{ + unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length; + + if (pci0Mem1Length == 0) + pci0Mem1Top++; + + pci0Mem1Base = pci0Mem1Base >> 21; + pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base); + GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top); + +} + +/* + * pci1MapMemory1space - Maps PCI1 memory1 space for the master. + * Inputs: base and length of pci1Mem1 + */ + +static void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length) +{ + unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length; + + if (pci1Mem1Length == 0) + pci1Mem1Top++; + + pci1Mem1Base = pci1Mem1Base >> 21; + pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base); + GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top); +} + +/* + * pci0GetIOspaceBase - Return PCI0 IO Base Address. + * Inputs: N/A + * Returns: PCI0 IO Base Address. + */ + +static unsigned int pci0GetIOspaceBase(void) +{ + unsigned int base; + GT_READ(GT_PCI0IOLD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetIOspaceSize - Return PCI0 IO Bar Size. + * Inputs: N/A + * Returns: PCI0 IO Bar Size. + */ + +static unsigned int pci0GetIOspaceSize(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0IOLD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0IOHD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci0GetMemory0Base - Return PCI0 Memory 0 Base Address. + * Inputs: N/A + * Returns: PCI0 Memory 0 Base Address. + */ + +static unsigned int pci0GetMemory0Base(void) +{ + unsigned int base; + GT_READ(GT_PCI0M0LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size. + * Inputs: N/A + * Returns: PCI0 Memory 0 Bar Size. + */ + +static unsigned int pci0GetMemory0Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0M0LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0M0HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci0GetMemory1Base - Return PCI0 Memory 1 Base Address. + * Inputs: N/A + * Returns: PCI0 Memory 1 Base Address. + */ + +static unsigned int pci0GetMemory1Base(void) +{ + unsigned int base; + GT_READ(GT_PCI0M1LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size. + * Inputs: N/A + * Returns: PCI0 Memory 1 Bar Size. + */ + +static unsigned int pci0GetMemory1Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetIOspaceBase - Return PCI1 IO Base Address. + * Inputs: N/A + * Returns: PCI1 IO Base Address. + */ + +static unsigned int pci1GetIOspaceBase(void) +{ + unsigned int base; + GT_READ(GT_PCI1IOLD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetIOspaceSize - Return PCI1 IO Bar Size. + * Inputs: N/A + * Returns: PCI1 IO Bar Size. + */ + +static unsigned int pci1GetIOspaceSize(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1IOLD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1IOHD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetMemory0Base - Return PCI1 Memory 0 Base Address. + * Inputs: N/A + * Returns: PCI1 Memory 0 Base Address. + */ + +static unsigned int pci1GetMemory0Base(void) +{ + unsigned int base; + GT_READ(GT_PCI1M0LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size. + * Inputs: N/A + * Returns: PCI1 Memory 0 Bar Size. + */ + +static unsigned int pci1GetMemory0Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetMemory1Base - Return PCI1 Memory 1 Base Address. + * Inputs: N/A + * Returns: PCI1 Memory 1 Base Address. + */ + +static unsigned int pci1GetMemory1Base(void) +{ + unsigned int base; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size. + * Inputs: N/A + * Returns: PCI1 Memory 1 Bar Size. + */ + +static unsigned int pci1GetMemory1Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + + + +/* + * pci_range_ck - + * + * Check if the pci device that are trying to access does really exists + * on the evaluation board. + * + * Inputs : + * bus - bus number (0 for PCI 0 ; 1 for PCI 1) + * dev - number of device on the specific pci bus + * + * Outpus : + * 0 - if OK , 1 - if failure + */ +static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) +{ + /* + * We don't even pretend to handle other busses than bus 0 correctly. + * Accessing device 31 crashes the CP7000 for some reason. + */ + if ((bus == 0) && (dev != 31)) + return 0; + return -1; +} + +/* + * pciXReadConfigReg - Read from a PCI configuration register + * - Make sure the GT is configured as a master before + * reading from another device on the PCI. + * - The function takes care of Big/Little endian conversion. + * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI + * spec) + * pciDevNum: The device number needs to be addressed. + * RETURNS: data , if the data == 0xffffffff check the master abort bit in the + * cause register to make sure the data is valid + * + * Configuration Address 0xCF8: + * + * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number + * |congif|Reserved| Bus |Device|Function|Register|00| + * |Enable| |Number|Number| Number | Number | | <=field Name + * + */ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + + /* + * The casual observer might wonder why the READ is duplicated here, + * rather than immediately following the WRITE, and just have the swap + * in the "if". That's because there is a latency problem with trying + * to read immediately after setting up the address register. The "if" + * check gives enough time for the address to stabilize, so the READ + * can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return data; + } else { /* The PCI is working in LE Mode so swap the Data. */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return cpu_to_le32(data); + } +} + +static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + /* + * The casual observer might wonder why the READ is duplicated here, + * rather than immediately following the WRITE, and just have the + * swap in the "if". That's because there is a latency problem + * with trying to read immediately after setting up the address + * register. The "if" check gives enough time for the address + * to stabilize, so the READ can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + /* when configurating our own PCI 1 L-unit the access is through + the PCI 0 interface with reg number = reg number + 0x80 */ + DataForRegCf8 |= 0x80; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + } else { /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); + } + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return data; + } else { + GT_READ(GT_PCI1_CFGDATA_OFS, &data); + return cpu_to_le32(data); + } +} + + + +/* + * pciXWriteConfigReg - Write to a PCI configuration register + * - Make sure the GT is configured as a master before + * writingto another device on the PCI. + * - The function takes care of Big/Little endian conversion. + * Inputs: unsigned int regOffset: The register offset as it apears in the + * GT spec + * (or any other PCI device spec) + * pciDevNum: The device number needs to be addressed. + * + * Configuration Address 0xCF8: + * + * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number + * |congif|Reserved| Bus |Device|Function|Register|00| + * |Enable| |Number|Number| Number | Number | | <=field Name + * + */ +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + } else { /* configuration Transaction over the pci. */ + /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data)); + } +} + +static void pci1WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + /* + * There is a latency problem + * with trying to read immediately after setting up the address + * register. The "if" check gives enough time for the address + * to stabilize, so the WRITE can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + /* + * when configurating our own PCI 1 L-unit the access is through + * the PCI 0 interface with reg number = reg number + 0x80 + */ + DataForRegCf8 |= 0x80; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + } else { /* configuration Transaction over the pci. */ + /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); + } + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + } else { /* configuration Transaction over the pci. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data)); + } +} + + +/* + * galileo_pcibios_(read/write)_config_(dword/word/byte) - + * + * reads/write a dword/word/byte register from the configuration space + * of a device. + * + * Inputs : + * bus - bus number + * dev - device number + * offset - register offset in the configuration space + * val - value to be written / read + * + * Outputs : + * PCIBIOS_SUCCESSFUL when operation was succesfull + * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous + * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned + */ + +static int galileo_pcibios_read_config_dword(struct pci_dev *device, + int offset, u32 * val) +{ + int dev, bus; + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + *val = pci0ReadConfigReg(offset, device); + + /* This is so that the upper PCI layer will get the correct return value if + we're not attached to anything. */ + if ((offset == 0) && (*val == 0xffffffff)) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_read_config_word(struct pci_dev *device, + int offset, u16 * val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (bus == 0) + *val = + (unsigned short) (pci0ReadConfigReg(offset, device) >> + ((offset & ~0x3) * 8)); + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_read_config_byte(struct pci_dev *device, + int offset, u8 * val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + if (bus == 0) + *val = + (unsigned char) (pci0ReadConfigReg(offset, device) >> + ((offset & ~0x3) * 8)); + + /* + * This is so that the upper PCI layer will get the correct return + * value if we're not attached to anything. + */ + if ((offset == 0xe) && (*val == 0xff)) { + u32 MasterAbort; + GT_READ(GT_INTRCAUSE_OFS, &MasterAbort); + if (MasterAbort & 0x40000) { + GT_WRITE(GT_INTRCAUSE_OFS, + (MasterAbort & 0xfffbffff)); + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write_config_dword(struct pci_dev *device, + int offset, u32 val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + pci0WriteConfigReg(offset, device, val); +// if (bus == 1) pci1WriteConfigReg (offset,device,val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int galileo_pcibios_write_config_word(struct pci_dev *device, + int offset, u16 val) +{ + int dev, bus; + unsigned long tmp; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + tmp = pci0ReadConfigReg(offset, device); +// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); + + if ((offset % 4) == 0) + tmp = (tmp & 0xffff0000) | (val & 0xffff); + if ((offset % 4) == 2) + tmp = (tmp & 0x0000ffff) | ((val & 0xffff) << 16); + + if (bus == 0) + pci0WriteConfigReg(offset, device, tmp); +// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write_config_byte(struct pci_dev *device, + int offset, u8 val) +{ + int dev, bus; + unsigned long tmp; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == 0) + tmp = pci0ReadConfigReg(offset, device); +// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); + + if ((offset % 4) == 0) + tmp = (tmp & 0xffffff00) | (val & 0xff); + if ((offset % 4) == 1) + tmp = (tmp & 0xffff00ff) | ((val & 0xff) << 8); + if ((offset % 4) == 2) + tmp = (tmp & 0xff00ffff) | ((val & 0xff) << 16); + if ((offset % 4) == 3) + tmp = (tmp & 0x00ffffff) | ((val & 0xff) << 24); + + if (bus == 0) + pci0WriteConfigReg(offset, device, tmp); +// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); + + return PCIBIOS_SUCCESSFUL; +} + +static void galileo_pcibios_set_master(struct pci_dev *dev) +{ + u16 cmd; + + galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); +} + +/* Externally-expected functions. Do not change function names */ + +int pcibios_enable_resources(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + u8 tmp1; + int idx; + struct resource *r; + + galileo_pcibios_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) { + galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); + } + + /* + * Let's fix up the latency timer and cache line size here. Cache + * line size = 32 bytes / sizeof dword (4) = 8. + * Latency timer must be > 8. 32 is random but appears to work. + */ + galileo_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1); + if (tmp1 != 8) { + printk(KERN_WARNING "PCI setting cache line size to 8 from " + "%d\n", tmp1); + galileo_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE, + 8); + } + galileo_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1); + if (tmp1 < 32) { + printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n", + tmp1); + galileo_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER, + 32); + } + + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev) +{ + return pcibios_enable_resources(dev); +} + +void pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + u32 new, check; + int reg; + + return; + + 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; + 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); + } +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size) +{ + struct pci_dev *dev = data; + + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + /* We need to avoid collisions with `mirrored' VGA ports + and other strange ISA hardware, so we always want the + addresses kilobyte aligned. */ + if (size > 0x100) { + printk(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", dev->slot_name, + dev->resource - res, size); + } + + start = (start + 1024 - 1) & ~(1024 - 1); + res->start = start; + } +} + +struct pci_ops galileo_pci_ops = { + galileo_pcibios_read_config_byte, + galileo_pcibios_read_config_word, + galileo_pcibios_read_config_dword, + galileo_pcibios_write_config_byte, + galileo_pcibios_write_config_word, + galileo_pcibios_write_config_dword +}; + +struct pci_fixup pcibios_fixups[] = { + {0} +}; + +void __init pcibios_fixup_bus(struct pci_bus *c) +{ + gt64120_board_pcibios_fixup_bus(c); +} + +/* + * This code was derived from Galileo Technology's example + * and significantly reworked. + * + * This is very simple. It does not scan multiple function devices. It does + * not scan behind bridges. Those would be simple to implement, but we don't + * currently need this. + */ + +static void __init scan_and_initialize_pci(void) +{ + struct pci_device pci_devices[MAX_PCI_DEVS]; + + if (scan_pci_bus(pci_devices)) { + allocate_pci_space(pci_devices); + } +} + +/* + * This is your basic PCI scan. It goes through each slot and checks to + * see if there's something that responds. If so, then get the size and + * type of each of the responding BARs. Save them for later. + */ + +static u32 __init scan_pci_bus(struct pci_device *pci_devices) +{ + u32 arrayCounter = 0; + u32 memType; + u32 memSize; + u32 pci_slot, bar; + u32 id; + u32 c18RegValue; + struct pci_dev device; + + /* + * According to PCI REV 2.1 MAX agents on the bus are 21. + * We don't bother scanning ourselves (slot 0). + */ + for (pci_slot = 1; pci_slot < 22; pci_slot++) { + + device.devfn = PCI_DEVFN(pci_slot, 0); + id = pci0ReadConfigReg(PCI_VENDOR_ID, &device); + + /* + * Check for a PCI Master Abort (nothing responds in the + * slot) + */ + GT_READ(GT_INTRCAUSE_OFS, &c18RegValue); + /* + * Clearing bit 18 of in the Cause Register 0xc18 by + * writting 0. + */ + GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff)); + if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) { + pci_devices[arrayCounter].slot = pci_slot; + for (bar = 0; bar < 6; bar++) { + memType = + pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device); + pci_devices[arrayCounter].BARtype[bar] = + memType & 1; + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device, + 0xffffffff); + memSize = + pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device); + if (memType & 1) { /* IO space */ + pci_devices[arrayCounter]. + BARsize[bar] = + ~(memSize & 0xfffffffc) + 1; + } else { /* memory space */ + pci_devices[arrayCounter]. + BARsize[bar] = + ~(memSize & 0xfffffff0) + 1; + } + } /* BAR counter */ + + arrayCounter++; + } + /* found a device */ + } /* slot counter */ + + if (arrayCounter < MAX_PCI_DEVS) + pci_devices[arrayCounter].slot = -1; + + return arrayCounter; +} + +#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) +#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) + +/* + * This function goes through the list of devices and allocates the BARs in + * either IO or MEM space. It does it in order of size, which will limit the + * amount of fragmentation we have in the IO and MEM spaces. + */ + +static void __init allocate_pci_space(struct pci_device *pci_devices) +{ + u32 count, maxcount, bar; + u32 maxSize, maxDevice, maxBAR; + u32 alignto; + u32 base; + u32 pci0_mem_base = pci0GetMemory0Base(); + u32 pci0_io_base = pci0GetIOspaceBase(); + struct pci_dev device; + + /* How many PCI devices do we have? */ + maxcount = MAX_PCI_DEVS; + for (count = 0; count < MAX_PCI_DEVS; count++) { + if (pci_devices[count].slot == -1) { + maxcount = count; + break; + } + } + + do { + /* Find the largest size BAR we need to allocate */ + maxSize = 0; + for (count = 0; count < maxcount; count++) { + for (bar = 0; bar < 6; bar++) { + if (pci_devices[count].BARsize[bar] > + maxSize) { + maxSize = + pci_devices[count]. + BARsize[bar]; + maxDevice = count; + maxBAR = bar; + } + } + } + + /* + * We've found the largest BAR. Allocate it into IO or + * mem space. We don't idiot check the bases to make + * sure they haven't overflowed the current size for that + * aperture. + * Don't bother to enable the device's IO or MEM space here. + * That will be done in pci_enable_resources if the device is + * activated by a driver. + */ + if (maxSize) { + device.devfn = + PCI_DEVFN(pci_devices[maxDevice].slot, 0); + if (pci_devices[maxDevice].BARtype[maxBAR] == 1) { + alignto = MAX(0x1000, maxSize); + base = ALIGN(pci0_io_base, alignto); + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (maxBAR * 4), &device, + base | 0x1); + pci0_io_base = base + alignto; + } else { + alignto = MAX(0x1000, maxSize); + base = ALIGN(pci0_mem_base, alignto); + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (maxBAR * 4), &device, + base); + pci0_mem_base = base + alignto; + } + /* + * This entry is finished. Remove it from the list + * we'll scan. + */ + pci_devices[maxDevice].BARsize[maxBAR] = 0; + } + } while (maxSize); +} + +void __init pcibios_init(void) +{ + u32 tmp; + struct pci_dev controller; + + controller.devfn = SELF; + + GT_READ(GT_PCI0_CMD_OFS, &tmp); + GT_READ(GT_PCI0_BARE_OFS, &tmp); + + /* + * You have to enable bus mastering to configure any other + * card on the bus. + */ + tmp = pci0ReadConfigReg(PCI_COMMAND, &controller); + tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + pci0WriteConfigReg(PCI_COMMAND, &controller, tmp); + + /* This scans the PCI bus and sets up initial values. */ + scan_and_initialize_pci(); + + /* + * Reset PCI I/O and PCI MEM values to ones supported by EVM. + */ + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; + iomem_resource.start = GT_PCI_MEM_BASE; + iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1; + + pci_scan_bus(0, &galileo_pci_ops, NULL); +} + +/* + * for parsing "pci=" kernel boot arguments. + */ +char *pcibios_setup(char *str) +{ + printk(KERN_INFO "rr: pcibios_setup\n"); + /* Nothing to do for now. */ + + return str; +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} + +#endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/Makefile linux/arch/mips/gt64120/momenco_ocelot/Makefile --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/Makefile Sun Sep 9 10:43:01 2001 @@ -0,0 +1,20 @@ +# +# Makefile for Momentum's Ocelot board. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET:= momenco_ocelot.o + +obj-y += int-handler.o irq.o pci.o prom.o reset.o setup.o + +obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/dbg_io.c linux/arch/mips/gt64120/momenco_ocelot/dbg_io.c --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/dbg_io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/dbg_io.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,124 @@ +#include + +#if defined(CONFIG_REMOTE_DEBUG) + +/* --- CONFIG --- */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE 0xbd000020 +#define MAX_BAUD 115200 + +/* === END OF CONFIG === */ + +#define REG_OFFSET 4 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_38400, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_9600, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} + +#endif diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/int-handler.S linux/arch/mips/gt64120/momenco_ocelot/int-handler.S --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/int-handler.S Sun Sep 9 10:43:01 2001 @@ -0,0 +1,132 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * First-level interrupt dispatcher for ocelot board. + * + * 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 + +/* + * first level interrupt dispatcher for ocelot board - + * We check for the timer first, then check PCI ints A and D. + * Then check for serial IRQ and fall through. + */ + .align 5 + NESTED(ocelot_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + andi t1, t0, STATUSF_IP2 /* int0 hardware line */ + bnez t1, ll_pri_enet_irq + andi t1, t0, STATUSF_IP3 /* int1 hardware line */ + bnez t1, ll_sec_enet_irq + andi t1, t0, STATUSF_IP4 /* int2 hardware line */ + bnez t1, ll_uart1_irq + andi t1, t0, STATUSF_IP5 /* int3 hardware line */ + bnez t1, ll_cpci_irq + andi t1, t0, STATUSF_IP6 /* int4 hardware line */ + bnez t1, ll_galileo_irq + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq + + /* now look at the extended interrupts */ + mfc0 t0, CP0_CAUSE + cfc0 t1, CP0_S1_INTCONTROL + + /* shift the mask 8 bits left to line up the bits */ + sll t2, t1, 8 + + and t0, t2 + srl t0, t0, 16 + + andi t1, t0, STATUSF_IP8 /* int6 hardware line */ + bnez t1, ll_pmc1_irq + andi t1, t0, STATUSF_IP9 /* int7 hardware line */ + bnez t1, ll_pmc2_irq + andi t1, t0, STATUSF_IP10 /* int8 hardware line */ + bnez t1, ll_cpci_abcd_irq + andi t1, t0, STATUSF_IP11 /* int9 hardware line */ + bnez t1, ll_uart2_irq + + .set reorder + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(ocelot_handle_int) + + .align 5 +ll_pri_enet_irq: + li a0, 2 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_sec_enet_irq: + li a0, 3 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_uart1_irq: + li a0, 4 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpci_irq: + li a0, 5 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_galileo_irq: + li a0, 6 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cputimer_irq: + li a0, 7 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_pmc1_irq: + li a0, 8 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_pmc2_irq: + li a0, 9 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpci_abcd_irq: + li a0, 10 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_uart2_irq: + li a0, 11 + move a1, sp + jal do_IRQ + j ret_from_irq diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/irq.c linux/arch/mips/gt64120/momenco_ocelot/irq.c --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/irq.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.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. + * + * 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED; + +/* Function for careful CP0 interrupt mask access */ +static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) +{ + unsigned long status; + unsigned clr_mask; + unsigned set_mask; + + /* do the low 8 bits first */ + clr_mask = 0xff & clr_mask_in; + set_mask = 0xff & set_mask_in; + status = read_32bit_cp0_register(CP0_STATUS); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_32bit_cp0_register(CP0_STATUS, status); + + /* do the high 8 bits */ + clr_mask = 0xff & (clr_mask_in >> 8); + set_mask = 0xff & (set_mask_in >> 8); + status = read_32bit_cp0_set1_register(CP0_S1_INTCONTROL); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_32bit_cp0_set1_register(CP0_S1_INTCONTROL, status); +} + +static inline void mask_irq(unsigned int irq) +{ + modify_cp0_intmask(irq, 0); +} + +static inline void unmask_irq(unsigned int irq) +{ + modify_cp0_intmask(0, irq); +} + +static void enable_cp7000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&rm7000_irq_lock, flags); + unmask_irq(1 << irq); + spin_unlock_irqrestore(&rm7000_irq_lock, flags); +} + +static unsigned int startup_cp7000_irq(unsigned int irq) +{ + enable_cp7000_irq(irq); + + return 0; /* never anything pending */ +} + +static void disable_cp7000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&rm7000_irq_lock, flags); + mask_irq(1 << irq); + spin_unlock_irqrestore(&rm7000_irq_lock, flags); +} + +#define shutdown_cp7000_irq disable_cp7000_irq + +static void mask_and_ack_cp7000_irq(unsigned int irq) +{ + mask_irq(1 << irq); +} + +static void end_cp7000_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_irq(1 << irq); +} + +static struct hw_interrupt_type cp7000_hpcdma_irq_type = { + "CP7000", + startup_cp7000_irq, + shutdown_cp7000_irq, + enable_cp7000_irq, + disable_cp7000_irq, + mask_and_ack_cp7000_irq, + end_cp7000_irq, + NULL +}; + + +extern asmlinkage void ocelot_handle_int(void); +extern void gt64120_irq_init(void); + +void __init init_IRQ(void) +{ + int i; + + /* + * Clear all of the interrupts while we change the able around a bit. + * int-handler is not on bootstrap + */ + clear_cp0_status(ST0_IM | ST0_BEV); + __cli(); + + /* Sets the first-level interrupt dispatcher. */ + set_except_vector(0, ocelot_handle_int); + init_generic_irq(); + + for (i = 0; i <= 15; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &cp7000_hpcdma_irq_type; + } + + gt64120_irq_init(); + +#ifdef CONFIG_REMOTE_DEBUG + printk("start kgdb ...\n"); + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif +#ifdef CONFIG_GDB_CONSOLE + register_gdb_console(); +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/ocelot_pld.h linux/arch/mips/gt64120/momenco_ocelot/ocelot_pld.h --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/ocelot_pld.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/ocelot_pld.h Sun Sep 9 10:43:01 2001 @@ -0,0 +1,34 @@ +/* + * $Id$ + * + * Ocelot Board Register Definitions + * + * (C) 2001 Red Hat, Inc. + * + * GPL'd + * + */ + +#ifndef __MOMENCO_OCELOT_PLD_H__ +#define __MOMENCO_OCELOT_PLD_H__ + +#define OCELOT_CS0_ADDR (0xe0020000) + +#define OCELOT_REG_BOARDREV (0) +#define OCELOT_REG_PLD1_ID (1) +#define OCELOT_REG_PLD2_ID (2) +#define OCELOT_REG_RESET_STATUS (3) +#define OCELOT_REG_BOARD_STATUS (4) +#define OCELOT_REG_CPCI_ID (5) +#define OCELOT_REG_I2C_CTRL (8) +#define OCELOT_REG_EEPROM_MODE (9) +#define OCELOT_REG_INTMASK (10) +#define OCELOT_REG_INTSTATUS (11) +#define OCELOT_REG_INTSET (12) +#define OCELOT_REG_INTCLR (13) + +#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y) +#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x) + + +#endif /* __MOMENCO_OCELOT_PLD_H__ */ diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/pci.c linux/arch/mips/gt64120/momenco_ocelot/pci.c --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/pci.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,75 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/gt64120/momenco_ocelot/pci.c + * Board-specific PCI routines for gt64120 controller. + * + * 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 + + +void __init gt64120_board_pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; + u16 cmd; + + list_for_each(devices_link, &(current_bus->devices)) { + + devices = pci_dev_b(devices_link); + if (devices == NULL) + continue; + + if (PCI_SLOT(devices->devfn) == 1) { + /* + * Slot 1 is primary ether port, i82559 + * we double-check against that assumption + */ + if ((devices->vendor != 0x8086) || + (devices->device != 0x1209) ) { + panic("gt64120_board_pcibios_fixup_bus: found " + "unexpected PCI device in slot 1."); + } + devices->irq = 2; /* irq_nr is 2 for INT0 */ + } else if (PCI_SLOT(devices->devfn) == 2) { + /* + * Slot 2 is secondary ether port, i21143 + * we double-check against that assumption + */ + if ((devices->vendor != 0x1011) || + (devices->device != 0x19) ) { + panic("galileo_pcibios_fixup_bus: " + "found unexpected PCI device in slot 2."); + } + devices->irq = 3; /* irq_nr is 3 for INT1 */ + } else if (PCI_SLOT(devices->devfn) == 4) { + /* PMC Slot 1 */ + devices->irq = 8; /* irq_nr is 8 for INT6 */ + } else if (PCI_SLOT(devices->devfn) == 5) { + /* PMC Slot 1 */ + devices->irq = 9; /* irq_nr is 9 for INT7 */ + } else { + /* We don't have assign interrupts for other devices. */ + devices->irq = 0xff; + } + + /* Assign an interrupt number for the device */ + bus->ops->write_byte(devices, PCI_INTERRUPT_LINE, devices->irq); + + /* enable master */ + bus->ops->read_word(devices, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + bus->ops->write_word(devices, PCI_COMMAND, cmd); + } +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/prom.c linux/arch/mips/gt64120/momenco_ocelot/prom.c --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/prom.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/prom.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,70 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * 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 + +#define PLD_BASE 0xbc000000 + +#define REV 0x0 /* Board Assembly Revision */ +#define PLD1ID 0x1 /* PLD 1 ID */ +#define PLD2ID 0x2 /* PLD 2 ID */ +#define RESET_STAT 0x3 /* Reset Status Register */ +#define BOARD_STAT 0x4 /* Board Status Register */ +#define CPCI_ID 0x5 /* Compact PCI ID Register */ +#define CONTROL 0x8 /* Control Register */ +#define CPU_EEPROM 0x9 /* CPU Configuration EEPROM Register */ +#define INTMASK 0xA /* Interrupt Mask Register */ +#define INTSTAT 0xB /* Interrupt Status Register */ +#define INTSET 0xC /* Interrupt Set Register */ +#define INTCLR 0xD /* Interrupt Clear Register */ + +#define PLD_REG(x) ((uint8_t*)(PLD_BASE+(x))) + +char arcs_cmdline[COMMAND_LINE_SIZE]; + +/* [jsun@junsun.net] PMON passes arguments in C main() style */ +void __init prom_init(int argc, const char **arg) +{ + int i; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_MOMENCO; + mips_machtype = MACH_MOMENCO_OCELOT; + + /* turn off the Bit Error LED, which comes on automatically + * at power-up reset */ + *PLD_REG(INTCLR) = 0x80; + + /* All the boards have at least 64MiB. If there's more, we + detect and register it later */ + add_memory_region(0, 64 << 20, BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +{ +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/reset.c linux/arch/mips/gt64120/momenco_ocelot/reset.c --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/reset.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,48 @@ +/* + * 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. + * + * Copyright (C) 1997, 2001 Ralf Baechle + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + */ +#include +#include +#include +#include +#include +#include +#include + +void momenco_ocelot_restart(char *command) +{ + *(volatile char *) 0xbc000000 = 0x0f; + + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + clear_cp0_status(ST0_BEV | ST0_ERL); + change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_32bit_cp0_register(CP0_WIRED, 0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void momenco_ocelot_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void momenco_ocelot_power_off(void) +{ + momenco_ocelot_halt(); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/setup.c linux/arch/mips/gt64120/momenco_ocelot/setup.c --- v2.4.9/linux/arch/mips/gt64120/momenco_ocelot/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/gt64120/momenco_ocelot/setup.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,282 @@ +/* + * setup.c + * + * BRIEF MODULE DESCRIPTION + * Galileo Evaluation Boards - board dependent boot routines + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2001 Red Hat, Inc. + * + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * 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. + * + */ +#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 "ocelot_pld.h" + +extern struct rtc_ops no_rtc_ops; + +unsigned long gt64120_base = KSEG1ADDR(GT_DEF_BASE); + +/* These functions are used for rebooting or halting the machine*/ +extern void momenco_ocelot_restart(char *command); +extern void momenco_ocelot_halt(void); +extern void momenco_ocelot_power_off(void); + +extern void gt64120_time_init(void); +extern void momenco_ocelot_irq_setup(void); + +static char reset_reason; + +#define ENTRYLO(x) ((pte_val(mk_pte_phys((x), PAGE_KERNEL_UNCACHED)) >> 6)|1) + +static void __init setup_l3cache(unsigned long size); + +void __init momenco_ocelot_setup(void) +{ + void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); + unsigned int tmpword; + + board_time_init = gt64120_time_init; + + _machine_restart = momenco_ocelot_restart; + _machine_halt = momenco_ocelot_halt; + _machine_power_off = momenco_ocelot_power_off; + + /* + * initrd_start = (ulong)ocelot_initrd_start; + * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size; + * initrd_below_start_ok = 1; + */ + rtc_ops = &no_rtc_ops; + + + /* A wired TLB entry for the GT64120A and the serial port. The + GT64120A is going to be hit on every IRQ anyway - there's + absolutely no point in letting it be a random TLB entry, as + it'll just cause needless churning of the TLB. And we use + the other half for the serial port, which is just a PITA + otherwise :) + + Device Physical Virtual + GT64120 Internal Regs 0x24000000 0xe0000000 + UARTs (CS2) 0x2d000000 0xe0001000 + */ + add_wired_entry(ENTRYLO(0x24000000), ENTRYLO(0x2D000000), 0xe0000000, PM_4K); + + /* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM + in the CS[012] region. We can't use ioremap() yet. The NVRAM + appears to be one of the variants of ST M48T35 - see + http://www.st.com/stonline/bin/sftab.exe?table=172&filter0=M48T35 + + Ocelot PLD (CS0) 0x2c000000 0xe0020000 + NVRAM 0x2c800000 0xe0030000 + */ + + add_temporary_entry(ENTRYLO(0x2C000000), ENTRYLO(0x2d000000), 0xe0020000, PM_64K); + + + /* Relocate the CS3/BootCS region */ + GT_WRITE( GT_CS3BOOTLD_OFS, 0x2f000000 >> 21); + + /* Relocate CS[012] */ + GT_WRITE(GT_CS20LD_OFS, 0x2c000000 >> 21); + + /* Relocate the GT64120A itself... */ + GT_WRITE(GT_ISD_OFS, 0x24000000 >> 21); + mb(); + gt64120_base = 0xe0000000; + + /* ...and the PCI0 view of it. */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000020); + GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x24000000); + GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000024); + GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x24000001); + + /* Relocate PCI0 I/O and Mem0 */ + GT_WRITE(GT_PCI0IOLD_OFS, 0x20000000 >> 21); + GT_WRITE(GT_PCI0M0LD_OFS, 0x22000000 >> 21); + + /* Relocate PCI0 Mem1 */ + GT_WRITE(GT_PCI0M1LD_OFS, 0x36000000 >> 21); + + /* Relocate all the PCI1 stuff, not that we use it */ + GT_WRITE(GT_PCI1IOLD_OFS, 0x30000000 >> 21); + GT_WRITE(GT_PCI1M0LD_OFS, 0x32000000 >> 21); + GT_WRITE(GT_PCI1M1LD_OFS, 0x34000000 >> 21); + + /* Relocate the CPU's view of the RAM... */ + GT_WRITE(GT_SCS10LD_OFS, 0); + GT_WRITE(GT_SCS10HD_OFS, 0x0fe00000 >> 21); + GT_WRITE(GT_SCS32LD_OFS, 0x10000000 >> 21); + GT_WRITE(GT_SCS32HD_OFS, 0x0fe00000 >> 21); + + GT_WRITE(GT_SCS1LD_OFS, 0xff); + GT_WRITE(GT_SCS1HD_OFS, 0x00); + GT_WRITE(GT_SCS0LD_OFS, 0); + GT_WRITE(GT_SCS0HD_OFS, 0xff); + GT_WRITE(GT_SCS3LD_OFS, 0xff); + GT_WRITE(GT_SCS3HD_OFS, 0x00); + GT_WRITE(GT_SCS2LD_OFS, 0); + GT_WRITE(GT_SCS2HD_OFS, 0xff); + + /* ...and the PCI0 view of it. */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000010); + GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x00000000); + GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000014); + GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x10000000); + GT_WRITE(GT_PCI0_BS_SCS10_OFS, 0x0ffff000); + GT_WRITE(GT_PCI0_BS_SCS32_OFS, 0x0ffff000); + + tmpword = OCELOT_PLD_READ(BOARDREV); + if (tmpword < 26) + printk("Momenco Ocelot: Board Assembly Rev. %c\n", 'A'+tmpword); + else + printk("Momenco Ocelot: Board Assembly Revision #0x%x\n", tmpword); + + tmpword = OCELOT_PLD_READ(PLD1_ID); + printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15); + tmpword = OCELOT_PLD_READ(PLD2_ID); + printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15); + tmpword = OCELOT_PLD_READ(RESET_STATUS); + printk("Reset reason: 0x%x\n", tmpword); + reset_reason = tmpword; + OCELOT_PLD_WRITE(0xff, RESET_STATUS); + + tmpword = OCELOT_PLD_READ(BOARD_STATUS); + printk("Board Status register: 0x%02x\n", tmpword); + printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); + printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); + printk(" - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not"); + printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1); + printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3))); + + if (tmpword&12) + l3func((1<<(((tmpword&12) >> 2)+20))); + + switch(tmpword &3) { + case 3: + /* 512MiB */ + add_memory_region(256<<20, 256<<20, BOOT_MEM_RAM); + case 2: + /* 256MiB */ + /* FIXME: Is it actually here, or at 0x10000000? */ + add_memory_region(128<<20, 128<<20, BOOT_MEM_RAM); + case 1: + /* 128MiB */ + add_memory_region(64<<20, 64<<20, BOOT_MEM_RAM); + case 0: + /* 64MiB */ + ; + } + + /* Fix up the DiskOnChip mapping */ + GT_WRITE(0x468, 0xfef73); +} + +extern int rm7k_tcache_enabled; +/* + * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache() + */ +#define Page_Invalidate_T 0x16 +static void __init setup_l3cache(unsigned long size) +{ + int register i; + unsigned long tmp; + + printk("Enabling L3 cache..."); + + /* Enable the L3 cache in the GT64120A's CPU Configuration register */ + GT_READ(0, &tmp); + GT_WRITE(0, tmp | (1<<14)); + + /* Enable the L3 cache in the CPU */ + set_cp0_config(1<<12 /* CONF_TE */); + + /* Clear the cache */ + set_taglo(0); + set_taghi(0); + + for (i=0; i < size; i+= 4096) { + __asm__ __volatile__ ( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (KSEG0ADDR(i)), + "i" (Page_Invalidate_T)); + } + + /* Let the RM7000 MM code know that the tertiary cache is enabled */ + rm7k_tcache_enabled = 1; + + printk("Done\n"); +} + + +/* This needs to be one of the first initcalls, because no I/O port access + can work before this */ + +static int io_base_ioremap(void) +{ + void *io_remap_range = ioremap(GT_PCI_IO_BASE, GT_PCI_IO_SIZE); + if (!io_remap_range) { + panic("Could not ioremap I/O port range\n"); + } + mips_io_port_base = io_remap_range - GT_PCI_IO_BASE; + return 0; +} +module_init(io_base_ioremap); + diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/Makefile linux/arch/mips/ite-boards/generic/Makefile --- v2.4.9/linux/arch/mips/ite-boards/generic/Makefile Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/generic/Makefile Sun Sep 9 10:43:01 2001 @@ -1,7 +1,7 @@ # # Copyright 2000 MontaVista Software Inc. # Author: MontaVista Software, Inc. -# ppopov@mvista.com or support@mvista.com +# ppopov@mvista.com or source@mvista.com # # Makefile for the ITE 8172 (qed-4n-s01b) board, generic files. # diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/dbg_io.c linux/arch/mips/ite-boards/generic/dbg_io.c --- v2.4.9/linux/arch/mips/ite-boards/generic/dbg_io.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/generic/dbg_io.c Sun Sep 9 10:43:01 2001 @@ -7,8 +7,8 @@ /* we need uint32 uint8 */ /* #include "types.h" */ -typedef unsigned char uint8; -typedef unsigned int uint32; +typedef unsigned char uint8; +typedef unsigned int uint32; /* --- END OF CONFIG --- */ @@ -39,7 +39,7 @@ /* === CONFIG === */ /* [stevel] we use the IT8712 serial port for kgdb */ -#define DEBUG_BASE 0xB40003F8 /* 8712 serial port 1 base address */ +#define DEBUG_BASE 0xB40003F8 /* 8712 serial port 1 base address */ #define MAX_BAUD 115200 /* === END OF CONFIG === */ @@ -69,59 +69,57 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) { - /* disable interrupts */ - UART16550_WRITE(OFS_INTR_ENABLE, 0); + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); - /* set up buad rate */ - { - uint32 divisor; - - /* set DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x80); - - /* set divisor */ - divisor = MAX_BAUD / baud; - UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); - UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8); - - /* clear DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x0); - } + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } - /* set data format */ - UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); } static int remoteDebugInitialized = 0; uint8 getDebugChar(void) { - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_115200, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, - UART16550_STOP_1BIT); - } + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } - while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); - return UART16550_READ(OFS_RCV_BUFFER); + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); } int putDebugChar(uint8 byte) { - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_115200, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, - UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0); - UART16550_WRITE(OFS_SEND_BUFFER, byte); - return 1; + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; } #endif diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/irq.c linux/arch/mips/ite-boards/generic/irq.c --- v2.4.9/linux/arch/mips/ite-boards/generic/irq.c Mon Aug 27 12:41:39 2001 +++ linux/arch/mips/ite-boards/generic/irq.c Sun Sep 9 10:43:01 2001 @@ -5,7 +5,7 @@ * * Copyright 2000,2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@mvista.com or source@mvista.com * * Part of this file was derived from Carsten Langgaard's * arch/mips/mips-boards/atlas/atlas_int.c. @@ -33,7 +33,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include @@ -76,12 +75,13 @@ extern void set_debug_traps(void); extern void mips_timer_interrupt(int irq, struct pt_regs *regs); extern asmlinkage void it8172_IRQ(void); -irq_cpustat_t irq_stat [NR_CPUS]; unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; irq_desc_t irq_desc[NR_IRQS]; irq_desc_t *irq_desc_base=&irq_desc[0]; +void disable_it8172_irq(unsigned int irq_nr); +void enable_it8172_irq(unsigned int irq_nr); struct it8172_intc_regs volatile *it8172_hw0_icregs = (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE)); @@ -110,7 +110,7 @@ unsigned long flags; save_and_cli(flags); - mask_irq(irq_nr); + disable_it8172_irq(irq_nr); restore_flags(flags); } @@ -119,15 +119,13 @@ unsigned long flags; save_and_cli(flags); - unmask_irq(irq_nr); + enable_it8172_irq(irq_nr); restore_flags(flags); } void disable_it8172_irq(unsigned int irq_nr) { - unsigned short mask; - DPRINTK("disable_it8172_irq %d\n", irq_nr); if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) { @@ -290,7 +288,6 @@ printk("Unhandled interrupt %d, cause %x, disabled\n", (unsigned)irq, (unsigned)regs->cp0_cause); disable_it8172_irq(irq); - //disable_irq(1<next; disable_it8172_irq(irq); - //disable_irq(1< #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/it8172_setup.c linux/arch/mips/ite-boards/generic/it8172_setup.c --- v2.4.9/linux/arch/mips/ite-boards/generic/it8172_setup.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/generic/it8172_setup.c Sun Sep 9 10:43:01 2001 @@ -5,7 +5,7 @@ * * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@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 @@ -66,7 +66,7 @@ extern int SearchIT8712(void); extern void InitLPCInterface(void); extern char * __init prom_getcmdline(void); -extern void it8172_restart(void); +extern void it8172_restart(char *command); extern void it8172_halt(void); extern void it8172_power_off(void); @@ -114,19 +114,18 @@ void __init it8172_setup(void) { -#ifdef CONFIG_BLK_DEV_IT8172 unsigned short dsr; -#endif char *argptr; argptr = prom_getcmdline(); #ifdef CONFIG_SERIAL_CONSOLE - if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) { - strcpy(serial_console, "ttyS0,115200"); - console_setup(serial_console, NULL); + if ((argptr = strstr(argptr, "console=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); } #endif + clear_cp0_status(ST0_FR); rtc_ops = &it8172_rtc_ops; _machine_restart = it8172_restart; @@ -153,19 +152,25 @@ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); #endif -#ifdef CONFIG_BLK_DEV_IT8172 /* - * Pull IDE device out of standby mode. + * Pull enabled devices out of standby */ IT_IO_READ16(IT_PM_DSR, dsr); +#ifdef CONFIG_SOUND_IT8172 + dsr &= ~IT_PM_DSR_ACSB; +#else + dsr |= IT_PM_DSR_ACSB; +#endif +#ifdef CONFIG_BLK_DEV_IT8172 dsr &= ~IT_PM_DSR_IDESB; - IT_IO_WRITE16(IT_PM_DSR, dsr); - ide_ops = &std_ide_ops; +#else + dsr |= IT_PM_DSR_IDESB; #endif + IT_IO_WRITE16(IT_PM_DSR, dsr); #ifdef CONFIG_FB - conswitchp = &dummy_con; + conswitchp = &dummy_con; #endif InitLPCInterface(); @@ -266,8 +271,6 @@ unsigned int data_port = 0x14000060; unsigned char data; int i; - - printk("8712 keyboard init"); outb(0xaa, cmd_port); /* send self-test cmd */ i = 0; diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/lpc.c linux/arch/mips/ite-boards/generic/lpc.c --- v2.4.9/linux/arch/mips/ite-boards/generic/lpc.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/generic/lpc.c Sun Sep 9 10:43:01 2001 @@ -5,7 +5,7 @@ * * Copyright 2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@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 @@ -41,7 +41,7 @@ #define FALSE 0 #endif -void LPCEnterMBPnP() +void LPCEnterMBPnP(void) { int i; unsigned char key[4] = {0x87, 0x01, 0x55, 0x55}; @@ -51,7 +51,7 @@ } -void LPCExitMBPnP() +void LPCExitMBPnP(void) { outb(0x02, LPC_KEY_ADDR); outb(0x02, LPC_DATA_ADDR); @@ -80,7 +80,7 @@ return rtn; } -int SearchIT8712() +int SearchIT8712(void) { unsigned char Id1, Id2; unsigned short Id; @@ -98,7 +98,7 @@ return FALSE; } -void InitLPCInterface() +void InitLPCInterface(void) { unsigned char bus, dev_fn; unsigned long data; diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/pmon_prom.c linux/arch/mips/ite-boards/generic/pmon_prom.c --- v2.4.9/linux/arch/mips/ite-boards/generic/pmon_prom.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/generic/pmon_prom.c Sun Sep 9 10:43:01 2001 @@ -6,7 +6,7 @@ * * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@mvista.com or source@mvista.com * * This file was derived from Carsten Langgaard's * arch/mips/mips-boards/xx files. @@ -35,6 +35,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -44,8 +45,8 @@ /* #define DEBUG_CMDLINE */ char arcs_cmdline[COMMAND_LINE_SIZE]; -int prom_argc; -char **prom_argv, **prom_envp; +extern int prom_argc; +extern char **prom_argv, **prom_envp; typedef struct { @@ -126,12 +127,16 @@ memsize_str = prom_getenv("memsize"); if (!memsize_str) { - printk("memsize unknown: setting to 32MB\n"); +#ifdef CONFIG_MIPS_ITE8172 memsize = 32; - } else { -#ifdef DEBUG - printk("prom_memsize: %s\n", memsize_str); +#elif defined(CONFIG_MIPS_IVR) + memsize = 64; +#else + memsize = 8; #endif + printk("memsize unknown: setting to %dMB\n", memsize); + } else { + printk("memsize: %s\n", memsize_str); memsize = simple_strtol(memsize_str, NULL, 0); } return memsize; diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/puts.c linux/arch/mips/ite-boards/generic/puts.c --- v2.4.9/linux/arch/mips/ite-boards/generic/puts.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/generic/puts.c Sun Sep 9 10:43:01 2001 @@ -5,7 +5,7 @@ * * Copyright 2000,2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@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 @@ -30,7 +30,7 @@ #include -#define SERIAL_BASE 0xB4011800 /* it8172 */ +#define SERIAL_BASE 0xB4011800 /* it8172 */ #define SER_CMD 5 #define SER_DATA 0x00 #define TX_BUSY 0x20 @@ -39,106 +39,101 @@ #undef SLOW_DOWN static const char digits[16] = "0123456789abcdef"; -static volatile unsigned char * const com1 = (unsigned char *)SERIAL_BASE; +static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE; #ifdef SLOW_DOWN static inline void slow_down() { - int k; - for (k=0; k<10000; k++); + int k; + for (k = 0; k < 10000; k++); } #else #define slow_down() #endif -void -putch(const unsigned char c) +void putch(const unsigned char c) { - unsigned char ch; - int i = 0; + unsigned char ch; + int i = 0; - do { - ch = com1[SER_CMD]; - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (0 == (ch & TX_BUSY)); - com1[SER_DATA] = c; + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = c; } -void -puts(unsigned char *cp) +void puts(unsigned char *cp) { - unsigned char ch; - int i = 0; + unsigned char ch; + int i = 0; - while (*cp) { - do { - ch = com1[SER_CMD]; - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (0 == (ch & TX_BUSY)); - com1[SER_DATA] = *cp++; - } - putch('\r'); - putch('\n'); + while (*cp) { + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = *cp++; + } + putch('\r'); + putch('\n'); } -void -fputs(unsigned char *cp) +void fputs(unsigned char *cp) { - unsigned char ch; - int i = 0; + unsigned char ch; + int i = 0; - while (*cp) { + while (*cp) { - do { - ch = com1[SER_CMD]; - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (0 == (ch & TX_BUSY)); - com1[SER_DATA] = *cp++; - } + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = *cp++; + } } -void -put64(uint64_t ul) +void put64(uint64_t ul) { - int cnt; - unsigned ch; + int cnt; + unsigned ch; - cnt = 16; /* 16 nibbles in a 64 bit long */ - putch('0'); - putch('x'); - do { - cnt--; - ch = (unsigned char)(ul >> cnt * 4) & 0x0F; - putch(digits[ch]); - } while (cnt > 0); + cnt = 16; /* 16 nibbles in a 64 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char) (ul >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); } -void -put32(unsigned u) +void put32(unsigned u) { - int cnt; - unsigned ch; + int cnt; + unsigned ch; - cnt = 8; /* 8 nibbles in a 32 bit long */ - putch('0'); - putch('x'); - do { - cnt--; - ch = (unsigned char)(u >> cnt * 4) & 0x0F; - putch(digits[ch]); - } while (cnt > 0); + cnt = 8; /* 8 nibbles in a 32 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char) (u >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/reset.c linux/arch/mips/ite-boards/generic/reset.c --- v2.4.9/linux/arch/mips/ite-boards/generic/reset.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/generic/reset.c Sun Sep 9 10:43:01 2001 @@ -3,10 +3,9 @@ * BRIEF MODULE DESCRIPTION * ITE 8172 reset routines. * - * Copyright (C) 1997, 2001 Ralf Baechle * Copyright 2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@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 @@ -37,7 +36,7 @@ #include #include -void it8172_restart(char *command) +void it8172_restart() { set_cp0_status(ST0_BEV | ST0_ERL); change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/generic/time.c linux/arch/mips/ite-boards/generic/time.c --- v2.4.9/linux/arch/mips/ite-boards/generic/time.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/generic/time.c Sun Sep 9 10:43:01 2001 @@ -23,6 +23,7 @@ * */ +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/ivr/Makefile linux/arch/mips/ite-boards/ivr/Makefile --- v2.4.9/linux/arch/mips/ite-boards/ivr/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ite-boards/ivr/Makefile Sun Sep 9 10:43:01 2001 @@ -0,0 +1,28 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Globespan IVR board, +# board-specific files. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: ivr.o + +O_TARGET := ivr.o + +obj-y := init.o + +obj-CONFIG_PCI += pci_fixup.o +obj-CONFIG_BLK_DEV_INITRD += le_ramdisk.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/ivr/README linux/arch/mips/ite-boards/ivr/README --- v2.4.9/linux/arch/mips/ite-boards/ivr/README Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ite-boards/ivr/README Sun Sep 9 10:43:01 2001 @@ -0,0 +1,3 @@ +This is not really a board made by ITE Semi, but it's very +similar to the ITE QED-4N-S01B board. The IVR board is made +by Globespan and it's a reference board for the PVR chip. diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/ivr/init.c linux/arch/mips/ite-boards/ivr/init.c --- v2.4.9/linux/arch/mips/ite-boards/ivr/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ite-boards/ivr/init.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,87 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * IVR board setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; + +extern char _end; +extern void __init prom_init_cmdline(void); +extern unsigned long __init prom_get_memsize(void); +extern void __init it8172_init_ram_resource(unsigned long memsize); + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) + + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned long mem_size; + unsigned long pcicr; + + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + puts("IVR board running..."); + + mips_machgroup = MACH_GROUP_GLOBESPAN; + mips_machtype = MACH_IVR; /* Globespan's iTVC15 reference board */ + + prom_init_cmdline(); + + /* pmon does not set memsize */ + mem_size = prom_get_memsize(); + mem_size = mem_size << 20; + + /* + * make the entire physical memory visible to pci bus masters + */ + IT_READ(IT_MC_PCICR, pcicr); + pcicr &= ~0x1f; + pcicr |= (mem_size - 1) >> 22; + IT_WRITE(IT_MC_PCICR, pcicr); + + it8172_init_ram_resource(mem_size); + add_memory_region(0, mem_size, BOOT_MEM_RAM); + return 0; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/ivr/pci_fixup.c linux/arch/mips/ite-boards/ivr/pci_fixup.c --- v2.4.9/linux/arch/mips/ite-boards/ivr/pci_fixup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ite-boards/ivr/pci_fixup.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,139 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Globespan IVR board-specific pci fixups. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@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. + */ +#include + +#ifdef CONFIG_PCI + +#include +#include +#include +#include + +#include +#include +#include + +void __init board_int_line_fixup(struct pci_dev *dev) +{ + unsigned int slot, func; + unsigned char pin; + const int internal_func_irqs[7] = { + IT8172_AC97_IRQ, + IT8172_DMA_IRQ, + IT8172_CDMA_IRQ, + IT8172_USB_IRQ, + IT8172_BRIDGE_MASTER_IRQ, + IT8172_IDE_IRQ, + IT8172_MC68K_IRQ + }; + +#ifdef DEBUG + printk("board_int_line_fixup bus %d\n", dev->bus->number); +#endif + if (dev->bus->number != 0) + return; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + +#ifdef DEBUG + pci_read_config_dword(dev, PCI_SUBSYSTEM_VENDOR_ID, &vendor); +#endif + + slot = PCI_SLOT(dev->devfn); + func = PCI_FUNC(dev->devfn); + + switch (slot) { + case 0x01: + /* + * Internal device 1 is actually 7 different internal + * devices on the IT8172G (a multi-function device). + */ + if (func < 7) + dev->irq = internal_func_irqs[func]; + break; + case 0x11: + switch (pin) { + case 0: /* pin A, hardware bug */ + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + case 0x13: + switch (pin) { + case 0: /* pin A, hardware bug */ + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + default: + return; + } + +#ifdef DEBUG + printk("irq fixup: slot %d, vendor %x, int line %d, int number %d\n", + slot, vendor, pin, dev->irq); +#endif + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + +} + +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, board_int_line_fixup }, + { 0 } +}; +#endif diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/qed-4n-s01b/Makefile linux/arch/mips/ite-boards/qed-4n-s01b/Makefile --- v2.4.9/linux/arch/mips/ite-boards/qed-4n-s01b/Makefile Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/qed-4n-s01b/Makefile Sun Sep 9 10:43:01 2001 @@ -1,7 +1,7 @@ # # Copyright 2000 MontaVista Software Inc. # Author: MontaVista Software, Inc. -# ppopov@mvista.com or support@mvista.com +# ppopov@mvista.com or source@mvista.com # # Makefile for the ITE 8172 (qed-4n-s01b) board, board # specific files. diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/qed-4n-s01b/init.c linux/arch/mips/ite-boards/qed-4n-s01b/init.c --- v2.4.9/linux/arch/mips/ite-boards/qed-4n-s01b/init.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/qed-4n-s01b/init.c Sun Sep 9 10:43:01 2001 @@ -5,7 +5,7 @@ * * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@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 @@ -34,8 +34,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -53,7 +55,7 @@ int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) { - unsigned long mem_size, free_start, free_end, bootmap_size; + unsigned long mem_size; unsigned long pcicr; prom_argc = argc; @@ -81,7 +83,7 @@ IT_WRITE(IT_MC_PCICR, pcicr); it8172_init_ram_resource(mem_size); - add_memory_region(0, 20 << 20, BOOT_MEM_RAM); + add_memory_region(0, mem_size, BOOT_MEM_RAM); return 0; } diff -u --recursive --new-file v2.4.9/linux/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c linux/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c --- v2.4.9/linux/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c Sun Sep 9 10:43:01 2001 @@ -5,7 +5,7 @@ * * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@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 diff -u --recursive --new-file v2.4.9/linux/arch/mips/jazz/irq.c linux/arch/mips/jazz/irq.c --- v2.4.9/linux/arch/mips/jazz/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/irq.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,45 @@ +/* + * 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. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994 - 2001 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +extern asmlinkage void jazz_handle_int(void); + +/* + * On systems with i8259-style interrupt controllers we assume for + * driver compatibility reasons interrupts 0 - 15 to be the i8295 + * interrupts even if the hardware uses a different interrupt numbering. + */ +void __init init_IRQ (void) +{ + int i; + + set_except_vector(0, jazz_handle_int); + + init_generic_irq(); + init_i8259_irqs(); /* Integrated i8259 */ +#if 0 + init_jazz_irq(); + + /* Actually we've got more interrupts to handle ... */ + for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &pciasic_irq_type; + } +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/jazz/jazzdma.c linux/arch/mips/jazz/jazzdma.c --- v2.4.9/linux/arch/mips/jazz/jazzdma.c Thu Feb 24 22:52:30 2000 +++ linux/arch/mips/jazz/jazzdma.c Sun Sep 9 10:43:01 2001 @@ -1,6 +1,4 @@ /* - * arch/mips/jazz/jazzdma.c - * * Mips Jazz DMA controller support * Copyright (C) 1995, 1996 by Andreas Busse * @@ -27,7 +25,7 @@ */ #define CONF_DEBUG_VDMA 0 -static unsigned long vdma_pagetable_start = 0; +static unsigned long vdma_pagetable_start; /* * Debug stuff @@ -44,16 +42,16 @@ */ static inline void vdma_pgtbl_init(void) { - int i; - unsigned long paddr = 0; - VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start; - - for (i=0; i 0x1fffffff) - { - if (vdma_debug) - printk("vdma_alloc: Invalid physical address: %08lx\n",paddr); - return VDMA_ERROR; /* invalid physical address */ - } - if (size > 0x400000 || size == 0) - { - if (vdma_debug) - printk("vdma_alloc: Invalid size: %08lx\n",size); - return VDMA_ERROR; /* invalid physical address */ - } - - save_and_cli (flags); - /* - * Find free chunk - */ - pages = (size + 4095) >> 12; /* no. of pages to allocate */ - first = 0; - while (1) - { - while (entry[first].owner != VDMA_PAGE_EMPTY && - first < VDMA_PGTBL_ENTRIES) - first++; - if (first+pages > VDMA_PGTBL_ENTRIES) { /* nothing free */ - restore_flags (flags); - return VDMA_ERROR; - } - - last = first+1; - while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages) - last++; - - if (last-first == pages) - break; /* found */ - } - - /* - * Mark pages as allocated - */ - laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1)); - frame = paddr & ~(VDMA_PAGESIZE-1); - - for (i=first; i 1) - printk("vdma_alloc: Allocated %d pages starting from %08lx\n", - pages,laddr); - - if (vdma_debug > 2) - { - printk("LADDR: "); - for (i=first; i 0x1fffffff) { + if (vdma_debug) + printk("vdma_alloc: Invalid physical address: %08lx\n", + paddr); + return VDMA_ERROR; /* invalid physical address */ + } + if (size > 0x400000 || size == 0) { + if (vdma_debug) + printk("vdma_alloc: Invalid size: %08lx\n", size); + return VDMA_ERROR; /* invalid physical address */ + } + + save_and_cli(flags); + /* + * Find free chunk + */ + pages = (size + 4095) >> 12; /* no. of pages to allocate */ + first = 0; + while (1) { + while (entry[first].owner != VDMA_PAGE_EMPTY && + first < VDMA_PGTBL_ENTRIES) first++; + if (first + pages > VDMA_PGTBL_ENTRIES) { /* nothing free */ + restore_flags(flags); + return VDMA_ERROR; + } + + last = first + 1; + while (entry[last].owner == VDMA_PAGE_EMPTY + && last - first < pages) + last++; + + if (last - first == pages) + break; /* found */ + } + + /* + * Mark pages as allocated + */ + laddr = (first << 12) + (paddr & (VDMA_PAGESIZE - 1)); + frame = paddr & ~(VDMA_PAGESIZE - 1); + + for (i = first; i < last; i++) { + entry[i].frame = frame; + entry[i].owner = laddr; + frame += VDMA_PAGESIZE; + } + + /* + * Update translation table and return logical start address + */ + r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0); + + if (vdma_debug > 1) + printk + ("vdma_alloc: Allocated %d pages starting from %08lx\n", + pages, laddr); + + if (vdma_debug > 2) { + printk("LADDR: "); + for (i = first; i < last; i++) + printk("%08x ", i << 12); + printk("\nPADDR: "); + for (i = first; i < last; i++) + printk("%08x ", entry[i].frame); + printk("\nOWNER: "); + for (i = first; i < last; i++) + printk("%08x ", entry[i].owner); + printk("\n"); + } + + restore_flags(flags); + return laddr; } /* @@ -186,102 +181,103 @@ */ int vdma_free(unsigned long laddr) { - VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start; - int i; + VDMA_PGTBL_ENTRY *pgtbl = + (VDMA_PGTBL_ENTRY *) vdma_pagetable_start; + int i; + + i = laddr >> 12; + + if (pgtbl[i].owner != laddr) { + printk + ("vdma_free: trying to free other's dma pages, laddr=%8lx\n", + laddr); + return -1; + } + + while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES) { + pgtbl[i].owner = VDMA_PAGE_EMPTY; + i++; + } - i = laddr >> 12; + if (vdma_debug > 1) + printk("vdma_free: freed %ld pages starting from %08lx\n", + i - (laddr >> 12), laddr); - if (pgtbl[i].owner != laddr) - { - printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n", - laddr); - return -1; - } - - while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES) - { - pgtbl[i].owner = VDMA_PAGE_EMPTY; - i++; - } - - if (vdma_debug > 1) - printk("vdma_free: freed %ld pages starting from %08lx\n", - i-(laddr>>12),laddr); - - return 0; + return 0; } /* * Map certain page(s) to another physical address. * Caller must have allocated the page(s) before. */ -int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size) +int vdma_remap(unsigned long laddr, unsigned long paddr, + unsigned long size) { - VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start; - int first, pages, npages; + VDMA_PGTBL_ENTRY *pgtbl = + (VDMA_PGTBL_ENTRY *) vdma_pagetable_start; + int first, pages, npages; + + if (laddr > 0xffffff) { + if (vdma_debug) + printk + ("vdma_map: Invalid logical address: %08lx\n", + laddr); + return -EINVAL; /* invalid logical address */ + } + if (paddr > 0x1fffffff) { + if (vdma_debug) + printk + ("vdma_map: Invalid physical address: %08lx\n", + paddr); + return -EINVAL; /* invalid physical address */ + } + + npages = pages = + (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1; + first = laddr >> 12; + if (vdma_debug) + printk("vdma_remap: first=%x, pages=%x\n", first, pages); + if (first + pages > VDMA_PGTBL_ENTRIES) { + if (vdma_debug) + printk("vdma_alloc: Invalid size: %08lx\n", size); + return -EINVAL; + } + + paddr &= ~(VDMA_PAGESIZE - 1); + while (pages > 0 && first < VDMA_PGTBL_ENTRIES) { + if (pgtbl[first].owner != laddr) { + if (vdma_debug) + printk("Trying to remap other's pages.\n"); + return -EPERM; /* not owner */ + } + pgtbl[first].frame = paddr; + paddr += VDMA_PAGESIZE; + first++; + pages--; + } + + /* + * Update translation table + */ + r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0); + + if (vdma_debug > 2) { + int i; + pages = (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1; + first = laddr >> 12; + printk("LADDR: "); + for (i = first; i < first + pages; i++) + printk("%08x ", i << 12); + printk("\nPADDR: "); + for (i = first; i < first + pages; i++) + printk("%08x ", pgtbl[i].frame); + printk("\nOWNER: "); + for (i = first; i < first + pages; i++) + printk("%08x ", pgtbl[i].owner); + printk("\n"); + } - if (laddr > 0xffffff) - { - if (vdma_debug) - printk("vdma_map: Invalid logical address: %08lx\n",laddr); - return -EINVAL; /* invalid logical address */ - } - if (paddr > 0x1fffffff) - { - if (vdma_debug) - printk("vdma_map: Invalid physical address: %08lx\n",paddr); - return -EINVAL; /* invalid physical address */ - } - - npages = pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1; - first = laddr >> 12; - if (vdma_debug) - printk("vdma_remap: first=%x, pages=%x\n",first,pages); - if (first+pages > VDMA_PGTBL_ENTRIES) - { - if (vdma_debug) - printk("vdma_alloc: Invalid size: %08lx\n",size); - return -EINVAL; - } - - paddr &= ~(VDMA_PAGESIZE-1); - while (pages > 0 && first < VDMA_PGTBL_ENTRIES) - { - if (pgtbl[first].owner != laddr) - { - if (vdma_debug) - printk("Trying to remap other's pages.\n"); - return -EPERM; /* not owner */ - } - pgtbl[first].frame = paddr; - paddr += VDMA_PAGESIZE; - first++; - pages--; - } - - /* - * Update translation table - */ - r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0); - - if (vdma_debug > 2) - { - int i; - pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1; - first = laddr >> 12; - printk("LADDR: "); - for (i=first; i> 12].frame + (laddr & (VDMA_PAGESIZE-1)); + return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE - 1)); } - + /* * Print DMA statistics */ void vdma_stats(void) { - int i; - - printk("vdma_stats: CONFIG: %08x\n", - r4030_read_reg32(JAZZ_R4030_CONFIG)); - printk("R4030 translation table base: %08x\n", - r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE)); - printk("R4030 translation table limit: %08x\n", - r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM)); - printk("vdma_stats: INV_ADDR: %08x\n", - r4030_read_reg32(JAZZ_R4030_INV_ADDR)); - printk("vdma_stats: R_FAIL_ADDR: %08x\n", - r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR)); - printk("vdma_stats: M_FAIL_ADDR: %08x\n", - r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR)); - printk("vdma_stats: IRQ_SOURCE: %08x\n", - r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE)); - printk("vdma_stats: I386_ERROR: %08x\n", - r4030_read_reg32(JAZZ_R4030_I386_ERROR)); - printk("vdma_chnl_modes: "); - for (i=0; i<8; i++) - printk("%04x ", - (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5))); - printk("\n"); - printk("vdma_chnl_enables: "); - for (i=0; i<8; i++) - printk("%04x ", - (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5))); - printk("\n"); + int i; + + printk("vdma_stats: CONFIG: %08x\n", + r4030_read_reg32(JAZZ_R4030_CONFIG)); + printk("R4030 translation table base: %08x\n", + r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE)); + printk("R4030 translation table limit: %08x\n", + r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM)); + printk("vdma_stats: INV_ADDR: %08x\n", + r4030_read_reg32(JAZZ_R4030_INV_ADDR)); + printk("vdma_stats: R_FAIL_ADDR: %08x\n", + r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR)); + printk("vdma_stats: M_FAIL_ADDR: %08x\n", + r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR)); + printk("vdma_stats: IRQ_SOURCE: %08x\n", + r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE)); + printk("vdma_stats: I386_ERROR: %08x\n", + r4030_read_reg32(JAZZ_R4030_I386_ERROR)); + printk("vdma_chnl_modes: "); + for (i = 0; i < 8; i++) + printk("%04x ", + (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_MODE + + (i << 5))); + printk("\n"); + printk("vdma_chnl_enables: "); + for (i = 0; i < 8; i++) + printk("%04x ", + (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + + (i << 5))); + printk("\n"); } /* @@ -363,33 +362,35 @@ */ void vdma_enable(int channel) { - int status; - - if (vdma_debug) - printk("vdma_enable: channel %d\n",channel); - - /* - * Check error conditions first - */ - status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)); - if (status & 0x400) - printk("VDMA: Channel %d: Address error!\n",channel); - if (status & 0x200) - printk("VDMA: Channel %d: Memory error!\n",channel); - - /* - * Clear all interrupt flags - */ - r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), - r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) | - R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR); - - /* - * Enable the desired channel - */ - r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), - r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) | - R4030_CHNL_ENABLE); + int status; + + if (vdma_debug) + printk("vdma_enable: channel %d\n", channel); + + /* + * Check error conditions first + */ + status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5)); + if (status & 0x400) + printk("VDMA: Channel %d: Address error!\n", channel); + if (status & 0x200) + printk("VDMA: Channel %d: Memory error!\n", channel); + + /* + * Clear all interrupt flags + */ + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + + (channel << 5)) | R4030_TC_INTR + | R4030_MEM_INTR | R4030_ADDR_INTR); + + /* + * Enable the desired channel + */ + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + + (channel << 5)) | + R4030_CHNL_ENABLE); } /* @@ -397,28 +398,34 @@ */ void vdma_disable(int channel) { - if (vdma_debug) - { - int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)); - - printk("vdma_disable: channel %d\n",channel); - printk("VDMA: channel %d status: %04x (%s) mode: " - "%02x addr: %06x count: %06x\n", - channel,status,((status & 0x600) ? "ERROR" : "OK"), - (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)), - (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)), - (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5))); - } - - r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), - r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) & - ~R4030_CHNL_ENABLE); - - /* - * After disabling a DMA channel a remote bus register should be - * read to ensure that the current DMA acknowledge cycle is completed. - */ - *((volatile unsigned int *)JAZZ_DUMMY_DEVICE); + if (vdma_debug) { + int status = + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + + (channel << 5)); + + printk("vdma_disable: channel %d\n", channel); + printk("VDMA: channel %d status: %04x (%s) mode: " + "%02x addr: %06x count: %06x\n", + channel, status, + ((status & 0x600) ? "ERROR" : "OK"), + (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_MODE + + (channel << 5)), + (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_ADDR + + (channel << 5)), + (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_COUNT + + (channel << 5))); + } + + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + + (channel << 5)) & + ~R4030_CHNL_ENABLE); + + /* + * After disabling a DMA channel a remote bus register should be + * read to ensure that the current DMA acknowledge cycle is completed. + */ + *((volatile unsigned int *) JAZZ_DUMMY_DEVICE); } /* @@ -432,56 +439,60 @@ */ void vdma_set_mode(int channel, int mode) { - if (vdma_debug) - printk("vdma_set_mode: channel %d, mode 0x%x\n", channel, mode); - - switch(channel) - { - case JAZZ_SCSI_DMA: /* scsi */ - r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5), + if (vdma_debug) + printk("vdma_set_mode: channel %d, mode 0x%x\n", channel, + mode); + + switch (channel) { + case JAZZ_SCSI_DMA: /* scsi */ + r4030_write_reg32(JAZZ_R4030_CHNL_MODE + (channel << 5), /* R4030_MODE_FAST | */ /* R4030_MODE_BURST | */ - R4030_MODE_INTR_EN | - R4030_MODE_WIDTH_16 | - R4030_MODE_ATIME_80); - break; - - case JAZZ_FLOPPY_DMA: /* floppy */ - r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5), + R4030_MODE_INTR_EN | + R4030_MODE_WIDTH_16 | + R4030_MODE_ATIME_80); + break; + + case JAZZ_FLOPPY_DMA: /* floppy */ + r4030_write_reg32(JAZZ_R4030_CHNL_MODE + (channel << 5), /* R4030_MODE_FAST | */ /* R4030_MODE_BURST | */ - R4030_MODE_INTR_EN | - R4030_MODE_WIDTH_8 | - R4030_MODE_ATIME_120); - break; - - case JAZZ_AUDIOL_DMA: - case JAZZ_AUDIOR_DMA: - printk("VDMA: Audio DMA not supported yet.\n"); - break; - - default: - printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n", - channel); - } - - switch(mode) - { - case DMA_MODE_READ: - r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), - r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) & - ~R4030_CHNL_WRITE); - break; - - case DMA_MODE_WRITE: - r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5), - r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) | - R4030_CHNL_WRITE); - break; - - default: - printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode); - } + R4030_MODE_INTR_EN | + R4030_MODE_WIDTH_8 | + R4030_MODE_ATIME_120); + break; + + case JAZZ_AUDIOL_DMA: + case JAZZ_AUDIOR_DMA: + printk("VDMA: Audio DMA not supported yet.\n"); + break; + + default: + printk + ("VDMA: vdma_set_mode() called with unsupported channel %d!\n", + channel); + } + + switch (mode) { + case DMA_MODE_READ: + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + + (channel << 5)) & + ~R4030_CHNL_WRITE); + break; + + case DMA_MODE_WRITE: + r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5), + r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + + (channel << 5)) | + R4030_CHNL_WRITE); + break; + + default: + printk + ("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n", + mode); + } } /* @@ -489,10 +500,11 @@ */ void vdma_set_addr(int channel, long addr) { - if (vdma_debug) - printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr); + if (vdma_debug) + printk("vdma_set_addr: channel %d, addr %lx\n", channel, + addr); - r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr); + r4030_write_reg32(JAZZ_R4030_CHNL_ADDR + (channel << 5), addr); } /* @@ -500,25 +512,28 @@ */ void vdma_set_count(int channel, int count) { - if (vdma_debug) - printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count); - - r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count); + if (vdma_debug) + printk("vdma_set_count: channel %d, count %08x\n", channel, + (unsigned) count); + + r4030_write_reg32(JAZZ_R4030_CHNL_COUNT + (channel << 5), count); } - + /* * Get Residual */ int vdma_get_residue(int channel) { - int residual; - - residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)); - - if (vdma_debug) - printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual); - - return residual; + int residual; + + residual = + r4030_read_reg32(JAZZ_R4030_CHNL_COUNT + (channel << 5)); + + if (vdma_debug) + printk("vdma_get_residual: channel %d: residual=%d\n", + channel, residual); + + return residual; } /* @@ -526,12 +541,13 @@ */ int vdma_get_enable(int channel) { - int enable; - - enable = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)); - - if (vdma_debug) - printk("vdma_get_enable: channel %d: enable=%d\n",channel,enable); - - return enable; + int enable; + + enable = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5)); + + if (vdma_debug) + printk("vdma_get_enable: channel %d: enable=%d\n", channel, + enable); + + return enable; } diff -u --recursive --new-file v2.4.9/linux/arch/mips/jazz/rtc-jazz.c linux/arch/mips/jazz/rtc-jazz.c --- v2.4.9/linux/arch/mips/jazz/rtc-jazz.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/jazz/rtc-jazz.c Sun Sep 9 10:43:01 2001 @@ -1,12 +1,11 @@ -/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $ - * +/* * 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. * * RTC routines for Jazz style attached Dallas chip. * - * Copyright (C) 1998 by Ralf Baechle + * Copyright (C) 1998, 2001 by Ralf Baechle */ #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c --- v2.4.9/linux/arch/mips/jazz/setup.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/jazz/setup.c Sun Sep 9 10:43:01 2001 @@ -1,12 +1,12 @@ -/* $Id: setup.c,v 1.24 1999/10/09 00:00:58 ralf Exp $ - * +/* * Setup pointers to hardware-dependent routines. * * 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. * - * Copyright (C) 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1996, 1997, 1998, 2001 by Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. */ #include #include @@ -72,7 +72,7 @@ JAZZ_IE_FLOPPY); r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ - set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); + change_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); /* set the clock to 100 Hz */ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); request_region(0x20, 0x20, "pic1"); @@ -80,11 +80,6 @@ i8259_setup_irq(2, &irq2); } -int __init page_is_ram(unsigned long pagenr) -{ - return 1; -} - void __init jazz_setup(void) { add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K); @@ -93,6 +88,8 @@ irq_setup = jazz_irq_setup; mips_io_port_base = JAZZ_PORT_BASE; + if (mips_machtype == MACH_MIPS_MAGNUM_4000) + EISA_bus = 1; isa_slot_offset = 0xe3000000; request_region(0x00,0x20,"dma1"); request_region(0x40,0x20,"timer"); diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile --- v2.4.9/linux/arch/mips/kernel/Makefile Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/Makefile Sun Sep 9 10:43:01 2001 @@ -35,15 +35,12 @@ endif obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_MIPS_FPE_MODULE) += fpe.o -ifndef CONFIG_MIPS_FPU_EMULATOR - obj-y += softfp.o -endif # Old style irq support, going to die in 2.5. export-objs += old-irq.o obj-$(CONFIG_NEW_IRQ) += irq.o obj-$(CONFIG_ROTTEN_IRQ) += old-irq.o +obj-$(CONFIG_I8259) += i8259.o # transition from old time.c to new time.c # some boards uses old-time.c, some use time.c, and some use their own ones @@ -56,6 +53,11 @@ obj-$(CONFIG_REMOTE_DEBUG) += gdb-low.o gdb-stub.o obj-$(CONFIG_PCI) += pci-dma.o obj-$(CONFIG_PROC_FS) += proc.o + +ifdef CONFIG_PCI +obj-$(CONFIG_NEW_PCI) += pci.o +obj-$(CONFIG_PCI_AUTO) += pci_auto.o +endif entry.o: entry.S head.o: head.S diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/branch.c linux/arch/mips/kernel/branch.c --- v2.4.9/linux/arch/mips/kernel/branch.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/branch.c Sun Sep 9 10:43:01 2001 @@ -5,9 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 97, 2000 by Ralf Baechle + * Copyright (C) 1996, 97, 2000, 2001 by Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. */ -#include #include #include #include @@ -29,11 +29,8 @@ union mips_instruction insn; epc = regs->cp0_epc; - if (epc & 3) { - printk("%s: unaligned epc - sending SIGBUS.\n", current->comm); - force_sig(SIGBUS, current); - return -EFAULT; - } + if (epc & 3) + goto unaligned; /* * Read the instruction @@ -167,12 +164,10 @@ * And now the FPA/cp1 branch instructions. */ case cop1_op: -#ifdef CONFIG_MIPS_FPU_EMULATOR if(!(mips_cpu.options & MIPS_CPU_FPU)) fcr31 = current->thread.fpu.soft.sr; else -#endif - asm ("cfc1\t%0,$31":"=r" (fcr31)); + asm ("cfc1\t%0,$31":"=r" (fcr31)); bit = (insn.i_format.rt >> 2); bit += (bit != 0); bit += 23; @@ -199,4 +194,9 @@ } return 0; + +unaligned: + printk("%s: unaligned epc - sending SIGBUS.\n", current->comm); + force_sig(SIGBUS, current); + return -EFAULT; } diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S --- v2.4.9/linux/arch/mips/kernel/entry.S Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/entry.S Sun Sep 9 10:43:01 2001 @@ -1,13 +1,12 @@ -/* $Id: entry.S,v 1.19 1999/12/08 22:05:10 harald Exp $ - * - * Low level exception handling - * +/* +/* * 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. * - * Copyright (C) 1994 - 2000 by Ralf Baechle + * Copyright (C) 1994 - 2000, 2001 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. */ #include #include @@ -26,50 +25,64 @@ #include #include +/* This duplicates the definition from */ +#define PT_TRACESYS 0x00000002 /* tracing system calls */ + + .text .align 4 .set push .set reorder EXPORT(ret_from_fork) - move a0, v0 # prev + move a0, v0 # prev jal schedule_tail + lw t0, TASK_PTRACE($28) # syscall tracing enabled? + andi t0, PT_TRACESYS + bnez t0, tracesys_exit j ret_from_sys_call -EXPORT(handle_softirq) - jal do_softirq - b 9f +tracesys_exit: jal syscall_trace + b ret_from_sys_call + +EXPORT(ret_from_irq) +EXPORT(ret_from_exception) + lw t0, PT_STATUS(sp) # returning to kernel mode? + andi t0, t0, KU_USER + bnez t0, ret_from_sys_call + j restore_all reschedule: jal schedule EXPORT(ret_from_sys_call) -EXPORT(ret_from_irq) .type ret_from_irq,@function - la t1, irq_stat # softirq_active -#ifdef CONFIG_SMP - lw t0, TASK_PROCESSOR($28) - sll t0, t0, 5 - addu t1, t0 -#endif - lw t0, 0(t1) # softirq_active - lw t1, 4(t1) # softirq_mask. unused delay slot - and t0, t1 - bnez t0, handle_softirq - -9: lw t0,PT_STATUS(sp) # returning to kernel mode? - lw t2, TASK_NEED_RESCHED($28) - andi t1, t0, KU_USER - beqz t1, return # -> yes - bnez t2, reschedule - lw v0, TASK_SIGPENDING($28) - move a0, zero - beqz v0, return - move a1, sp - jal do_signal -EXPORT(return) .set noat + mfc0 t0, CP0_STATUS # need_resched and signals atomic test + ori t0, t0, 1 + xori t0, t0, 1 + mtc0 t0, CP0_STATUS + nop; nop; nop + + lw v0, TASK_NEED_RESCHED($28) + lw v1, TASK_SIGPENDING($28) + bnez v0, reschedule + bnez v1, signal_return +restore_all: .set noat RESTORE_ALL_AND_RET .set at +/* Put this behind restore_all for the sake of the branch prediction. */ +signal_return: + .type signal_return, @function + + mfc0 t0, CP0_STATUS + ori t0, t0, 1 + mtc0 t0, CP0_STATUS + + move a0, zero + move a1, sp + jal do_signal + b restore_all + /* * Common spurious interrupt handler. */ @@ -85,8 +98,8 @@ lw t0,%lo(spurious_count)(t1) .set noreorder addiu t0,1 + sw t0,%lo(spurious_count)(t1) j ret_from_irq - sw t0,%lo(spurious_count)(t1) END(spurious_interrupt) /* @@ -106,7 +119,7 @@ ctc1 a2,fcr31; \ STI #define __BUILD_clear_ade(exception) \ - .set reorder; \ + .set reorder; \ MFC0 t0,CP0_BADVADDR; \ .set noreorder; \ REG_S t0,PT_BVADDR(sp); \ @@ -139,8 +152,8 @@ .set at; \ __BUILD_##verbose(exception); \ jal do_##handler; \ - move a0,sp; \ - j ret_from_sys_call; \ + move a0, sp; \ + j ret_from_exception; \ nop; \ END(handle_##exception) diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/fpe.c linux/arch/mips/kernel/fpe.c --- v2.4.9/linux/arch/mips/kernel/fpe.c Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/kernel/fpe.c Wed Dec 31 16:00:00 1969 @@ -1,51 +0,0 @@ -/* - * The real floating point exception handler. While it doesn't really - * make sense to have this in a module, it makes debugging of this code - * in the kernel space a lot easier. So far this handler in the released - * kernel source is just a dummy. - * - * Copyright (C) 1997, 2000 Ralf Baechle - */ -#include -#include -#include -#include -#include -#include - -#include -#include - -MODULE_AUTHOR("Ralf Baechle "); -MODULE_DESCRIPTION("Experimental floating point exception handler"); -MODULE_SUPPORTED_DEVICE("MIPS FPU"); - -static void do_fpe(struct pt_regs *regs, unsigned int fcr31) -{ -#ifdef CONF_DEBUG_EXCEPTIONS - show_regs(regs); -#endif - printk("Caught floating exception at epc == %08lx, fcr31 == %08x\n", - regs->cp0_epc, fcr31); - if (compute_return_epc(regs)) - goto out; - force_sig(SIGFPE, current); -out: -} - -/* - * For easier experimentation we never increment/decrement - * the module usable counter. - */ -int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); -int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); - -int init_module(void) -{ - return register_fpe(do_fpe); -} - -void cleanup_module(void) -{ - unregister_fpe(do_fpe); -} diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S --- v2.4.9/linux/arch/mips/kernel/gdb-low.S Sat May 13 08:29:14 2000 +++ linux/arch/mips/kernel/gdb-low.S Sun Sep 9 10:43:01 2001 @@ -1,16 +1,13 @@ /* - * arch/mips/kernel/gdb-low.S - * * gdb-low.S contains the low-level trap handler for the GDB stub. * * Copyright (C) 1995 Andreas Busse - * - * $Id: gdb-low.S,v 1.4 1997/12/01 17:57:26 ralf Exp $ */ - +#include #include #include +#include #include #include #include @@ -30,10 +27,15 @@ move k1,sp /* - * Called from user mode, new stack + * Called from user mode, go somewhere else. */ - lui k1,%hi(kernelsp) - lw k1,%lo(kernelsp)(k1) + lui k1,%hi(saved_vectors) + mfc0 k0,CP0_CAUSE + andi k0,k0,0x7c + add k1,k1,k0 + lw k0,%lo(saved_vectors)(k1) + jr k0 + nop 1: move k0,sp subu sp,k1,GDB_FR_SIZE @@ -302,11 +304,51 @@ lw v1,GDB_FR_REG3(sp) lw v0,GDB_FR_REG2(sp) lw $1,GDB_FR_REG1(sp) - lw sp,GDB_FR_REG29(sp) /* Deallocate stack */ +#ifdef CONFIG_CPU_R3000 + lw k0, GDB_FR_EPC(sp) + lw sp, GDB_FR_REG29(sp) /* Deallocate stack */ + jr k0 + rfe +#else + lw sp, GDB_FR_REG29(sp) /* Deallocate stack */ .set mips3 eret .set mips0 +#endif .set at .set reorder END(trap_low) + +LEAF(kgdb_read_byte) + .set push + .set noreorder + .set nomacro +4: lb t0, (a0) + .set pop + sb t0, (a1) + li v0, 0 + jr ra + .section __ex_table,"a" + PTR 4b, kgdbfault + .previous + END(kgdb_read_byte) + +LEAF(kgdb_write_byte) + .set push + .set noreorder + .set nomacro +5: sb a0, (a1) + .set pop + li v0, 0 + jr ra + .section __ex_table,"a" + PTR 5b, kgdbfault + .previous + END(kgdb_write_byte) + + .type kgdbfault@function + .ent kgdbfault +kgdbfault: li v0, -EFAULT + jr ra + .end kgdbfault diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v2.4.9/linux/arch/mips/kernel/gdb-stub.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/gdb-stub.c Sun Sep 9 10:43:01 2001 @@ -142,7 +142,6 @@ extern int putDebugChar(char c); /* write a single character */ extern char getDebugChar(void); /* read and return a single char */ -extern void fltr_set_mem_err(void); extern void trap_low(void); /* @@ -175,6 +174,10 @@ static int initialized; /* !0 means we've been initialized */ static const char hexchars[]="0123456789abcdef"; +/* Used to prevent crashes in memory access. Note that they'll crash anyway if + we haven't set up fault handlers yet... */ +int kgdb_read_byte(unsigned *address, unsigned *dest); +int kgdb_write_byte(unsigned val, unsigned *dest); /* * Convert ch from a hex digit to an int @@ -294,42 +297,18 @@ /* - * Indicate to caller of mem2hex or hex2mem that there - * has been an error. - */ -static volatile int mem_err = 0; - - -#if 0 -static void set_mem_fault_trap(int enable) -{ - mem_err = 0; - -#if 0 - if (enable) - exceptionHandler(9, fltr_set_mem_err); - else - exceptionHandler(9, trap_low); -#endif -} -#endif /* dead code */ - -/* * Convert the memory pointed to by mem into hex, placing result in buf. * Return a pointer to the last char put in buf (null), in case of mem fault, * return 0. - * If MAY_FAULT is non-zero, then we will handle memory faults by returning - * a 0, else treat a fault like any other fault in the stub. + * may_fault is non-zero if we are reading from arbitrary memory, but is currently + * not used. */ static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault) { unsigned char ch; -/* set_mem_fault_trap(may_fault); */ - while (count-- > 0) { - ch = *(mem++); - if (mem_err) + if (kgdb_read_byte(mem++, &ch) != 0) return 0; *buf++ = hexchars[ch >> 4]; *buf++ = hexchars[ch & 0xf]; @@ -337,33 +316,28 @@ *buf = 0; -/* set_mem_fault_trap(0); */ - return buf; } /* * convert the hex array pointed to by buf into binary to be placed in mem * return a pointer to the character AFTER the last byte written + * may_fault is non-zero if we are reading from arbitrary memory, but is currently + * not used. */ static char *hex2mem(char *buf, char *mem, int count, int may_fault) { int i; unsigned char ch; -/* set_mem_fault_trap(may_fault); */ - for (i=0; itt && ht->signo; ht++) - set_except_vector(ht->tt, trap_low); + saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low); putDebugChar('+'); /* 'hello world' */ /* @@ -417,18 +393,6 @@ initialized = 1; restore_flags(flags); -} - - -/* - * Trap handler for memory errors. This just sets mem_err to be non-zero. It - * assumes that %l1 is non-zero. This should be safe, as it is doubtful that - * 0 would ever contain code that could mem fault. This routine will skip - * past the faulting instruction after setting mem_err. - */ -extern void fltr_set_mem_err(void) -{ - /* FIXME: Needs to be written... */ } /* diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v2.4.9/linux/arch/mips/kernel/head.S Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/head.S Sun Sep 9 10:43:01 2001 @@ -76,7 +76,11 @@ addu k1, k1, k0 # add in pgd offset mfc0 k0, CP0_CONTEXT # get context reg lw k1, (k1) +#if defined(CONFIG_CPU_VR41XX) + srl k0, k0, 3 # get pte offset +#else srl k0, k0, 1 # get pte offset +#endif and k0, k0, 0xff8 addu k1, k1, k0 # add in offset lw k0, 0(k1) # get even pte @@ -275,7 +279,7 @@ END(except_vec0_r4k_MP250MHZhwbug) #endif - /* TLB refill, EXL == 0, R[23]00 version */ + /* TLB refill, R[23]00 version */ LEAF(except_vec0_r2300) .set noat .set mips1 diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/i8259.c linux/arch/mips/kernel/i8259.c --- v2.4.9/linux/arch/mips/kernel/i8259.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/i8259.c Sun Sep 9 10:43:01 2001 @@ -295,7 +295,6 @@ request_resource(&ioport_resource, &pic1_io_resource); request_resource(&ioport_resource, &pic2_io_resource); - setup_irq(2, &irq2); init_8259A(0); @@ -305,4 +304,6 @@ irq_desc[i].depth = 1; irq_desc[i].handler = &i8259A_irq_type; } + + setup_irq(2, &irq2); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/init_task.c linux/arch/mips/kernel/init_task.c --- v2.4.9/linux/arch/mips/kernel/init_task.c Mon Jul 26 22:41:09 1999 +++ linux/arch/mips/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -4,7 +4,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.4.9/linux/arch/mips/kernel/irq.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/irq.c Sun Sep 9 10:43:01 2001 @@ -303,7 +303,7 @@ desc->handler->end(irq); spin_unlock(&desc->lock); - if (softirq_active(cpu) & softirq_mask(cpu)) + if (softirq_pending(cpu)) do_softirq(); return 1; } diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.4.9/linux/arch/mips/kernel/mips_ksyms.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/mips_ksyms.c Sun Sep 9 10:43:01 2001 @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,7 @@ extern long __strnlen_user_nocheck_asm(const char *s); extern long __strnlen_user_asm(const char *s); +EXPORT_SYMBOL(mips_machtype); EXPORT_SYMBOL(EISA_bus); /* @@ -125,12 +127,6 @@ int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); - -#ifdef CONFIG_MIPS_FPE_MODULE -EXPORT_SYMBOL(__compute_return_epc); -EXPORT_SYMBOL(register_fpe); -EXPORT_SYMBOL(unregister_fpe); -#endif #ifdef CONFIG_VT EXPORT_SYMBOL(screen_info); diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/old-irq.c linux/arch/mips/kernel/old-irq.c --- v2.4.9/linux/arch/mips/kernel/old-irq.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/old-irq.c Sun Sep 9 10:43:01 2001 @@ -232,7 +232,7 @@ } irq_exit(cpu, irq); - if (softirq_active(cpu)&softirq_mask(cpu)) + if (softirq_pending(cpu)) do_softirq(); /* unmasking and bottom half handling is done magically for us. */ diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/old-time.c linux/arch/mips/kernel/old-time.c --- v2.4.9/linux/arch/mips/kernel/old-time.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/old-time.c Sun Sep 9 10:43:01 2001 @@ -1,18 +1,11 @@ /* * Copyright (C) 1991, 1992, 1995 Linus Torvalds * Copyright (C) 1996 - 2000 Ralf Baechle + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. * - * This file contains the time handling details for PC-style clocks as - * found in some MIPS systems. + * Don't use. Deprecated. Dead meat. */ -/************************************************************************** - * 9 Nov, 2000. - * Changed init_cycle_counter() routine, use the mips_cpu structure. - * - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ - #include #include #include @@ -450,7 +443,12 @@ void indy_r4k_timer_interrupt (struct pt_regs *regs) { static const int INDY_R4K_TIMER_IRQ = 7; + int cpu = smp_processor_id(); + r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs); + + if (softirq_pending(cpu)) + do_softirq(); } struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/pci-dma.c linux/arch/mips/kernel/pci-dma.c --- v2.4.9/linux/arch/mips/kernel/pci-dma.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/pci-dma.c Sun Sep 9 10:43:01 2001 @@ -4,9 +4,10 @@ * for more details. * * Copyright (C) 2000 Ani Joshi - * Copyright (C) 2000 Ralf Baechle + * Copyright (C) 2000, 2001 Ralf Baechle * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. */ +#include #include #include #include @@ -26,9 +27,11 @@ if (ret != NULL) { memset(ret, 0, size); +#ifndef CONFIG_COHERENT_IO dma_cache_wback_inv((unsigned long) ret, size); - *dma_handle = virt_to_bus(ret); ret = KSEG1ADDR(ret); +#endif + *dma_handle = virt_to_bus(ret); } return ret; @@ -37,5 +40,10 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { - free_pages((unsigned long) KSEG0ADDR(vaddr), get_order(size)); + unsigned long addr = (unsigned long) vaddr; + +#ifndef CONFIG_COHERENT_IO + addr = KSEG0ADDR(addr); +#endif + free_pages(addr, get_order(size)); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c --- v2.4.9/linux/arch/mips/kernel/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/pci.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,174 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * Modified to be mips generic, ppopov@mvista.com + * arch/mips/kernl/pci.c + * Common MIPS PCI routines. + * + * 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 contains common PCI routines meant to be shared for + * all MIPS machines. + * + * Strategies: + * + * . We rely on pci_auto.c file to assign PCI resources (MEM and IO) + * TODO: this shold be optional for some machines where they do have + * a real "pcibios" that does resource assignment. + * + * . We then use pci_scan_bus() to "discover" all the resources for + * later use by Linux. + * + * . We finally reply on a board supplied function, pcibios_fixup_irq(), to + * to assign the interrupts. We may use setup-irq.c under drivers/pci + * later. + * + * . Specifically, we will *NOT* use pci_assign_unassigned_resources(), + * because we assume all PCI devices should have the resources correctly + * assigned and recorded. + * + * Limitations: + * + * . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus + * into a contiguous range. + * + * . In the case of Memory space, the rnage is 1:1 mapping with CPU physical + * address space. + * + * . In the case of IO space, it starts from 0, and the beginning address + * is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address. + * + * . These are the current MIPS limitations (by ioremap, etc). In the + * future, we may remove them. + * + * Credits: + * Most of the code are derived from the pci routines from PPC and Alpha, + * which were mostly writtne by + * Cort Dougan, cort@fsmlabs.com + * Matt Porter, mporter@mvista.com + * Dave Rusling david.rusling@reo.mts.dec.com + * David Mosberger davidm@cs.arizona.edu + */ +#include +#include +#include +#include + +#include + +extern void pcibios_fixup(void); +extern void pcibios_fixup_irqs(void); + +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources }, + { 0 } +}; + +extern int pciauto_assign_resources(int busno, struct pci_channel * hose); + +void __init pcibios_init(void) +{ + struct pci_channel *p; + struct pci_bus *bus; + int busno; + +#ifdef CONFIG_PCI_AUTO + /* assign resources */ + busno=0; + for (p= mips_pci_channels; p->pci_ops != NULL; p++) { + busno = pciauto_assign_resources(busno, p) + 1; + } +#endif + + /* scan the buses */ + busno = 0; + for (p= mips_pci_channels; p->pci_ops != NULL; p++) { + bus = pci_scan_bus(busno, p->pci_ops, p); + busno = bus->subordinate+1; + } + + /* machine dependent fixups */ + pcibios_fixup(); + /* fixup irqs (board specific routines) */ + pcibios_fixup_irqs(); +} + +int pcibios_enable_device(struct pci_dev *dev) +{ + /* pciauto_assign_resources() will enable all devices found */ + return 0; +} + +unsigned long __init pci_bridge_check_io(struct pci_dev *bridge) +{ + u16 io; + + pci_read_config_word(bridge, PCI_IO_BASE, &io); + if (!io) { + pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); + pci_read_config_word(bridge, PCI_IO_BASE, &io); + pci_write_config_word(bridge, PCI_IO_BASE, 0x0); + } + if (io) + return IORESOURCE_IO; + printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", + bridge->name); + return 0; +} + +void __init pcibios_fixup_bus(struct pci_bus *bus) +{ + /* Propogate hose info into the subordinate devices. */ + + struct pci_channel *hose = bus->sysdata; + struct pci_dev *dev = bus->self; + + if (!dev) { + /* Root bus */ + bus->resource[0] = hose->io_resource; + bus->resource[1] = hose->mem_resource; + } else { + /* This is a bridge. Do not care how it's initialized, + just link its resources to the bus ones */ + int i; + + for(i=0; i<3; i++) { + bus->resource[i] = + &dev->resource[PCI_BRIDGE_RESOURCES+i]; + bus->resource[i]->name = bus->name; + } + bus->resource[0]->flags |= pci_bridge_check_io(dev); + bus->resource[1]->flags |= IORESOURCE_MEM; + /* For now, propogate hose limits to the bus; + we'll adjust them later. */ + bus->resource[0]->end = hose->io_resource->end; + bus->resource[1]->end = hose->mem_resource->end; + /* Turn off downstream PF memory address range by default */ + bus->resource[2]->start = 1024*1024; + bus->resource[2]->end = bus->resource[2]->start - 1; + } +} + +char *pcibios_setup(char *str) +{ + return str; +} + +void +pcibios_align_resource(void *data, struct resource *res, unsigned long size) +{ + /* this should not be called */ +} + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + /* this should not be called */ +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/pci_auto.c linux/arch/mips/kernel/pci_auto.c --- v2.4.9/linux/arch/mips/kernel/pci_auto.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/pci_auto.c Sun Sep 9 10:43:01 2001 @@ -0,0 +1,323 @@ +/* + * PCI autoconfiguration library + * + * Author: Matt Porter + * + * Copyright 2000, 2001 MontaVista Software 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. + */ + +/* + * Modified for MIPS by Jun Sun, jsun@mvista.com + * + * . Simplify the interface between pci_auto and the rest: a single function. + * . Assign resources from low address to upper address. + * . change most int to u32. + * + * Further modified to include it as mips generic code, ppopov@mvista.com. + */ + +#include +#include +#include +#include + +#include + +#define DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* These are used for config access before all the PCI probing has been done. */ +int early_read_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 *val); +int early_read_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 *val); +int early_read_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 *val); +int early_write_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 val); +int early_write_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 val); +int early_write_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 val); + +static u32 pciauto_lower_iospc; +static u32 pciauto_upper_iospc; + +static u32 pciauto_lower_memspc; +static u32 pciauto_upper_memspc; + +void __init +pciauto_setup_bars(struct pci_channel *hose, + int current_bus, + int pci_devfn) +{ + u32 bar_response, bar_size, bar_value; + u32 bar, addr_mask, bar_nr = 0; + u32 * upper_limit; + u32 * lower_limit; + int found_mem64 = 0; + + DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n", + current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) ); + + for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) { + /* Tickle the BAR and get the response */ + early_write_config_dword(hose, + current_bus, + pci_devfn, + bar, + 0xffffffff); + early_read_config_dword(hose, + current_bus, + pci_devfn, + bar, + &bar_response); + + /* If BAR is not implemented go to the next BAR */ + if (!bar_response) + continue; + + /* Check the BAR type and set our address mask */ + if (bar_response & PCI_BASE_ADDRESS_SPACE) { + addr_mask = PCI_BASE_ADDRESS_IO_MASK; + upper_limit = &pciauto_upper_iospc; + lower_limit = &pciauto_lower_iospc; + DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr); + } else { + if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64) + found_mem64 = 1; + + addr_mask = PCI_BASE_ADDRESS_MEM_MASK; + upper_limit = &pciauto_upper_memspc; + lower_limit = &pciauto_lower_memspc; + DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr); + } + + /* Calculate requested size */ + bar_size = ~(bar_response & addr_mask) + 1; + + /* Allocate a base address */ + bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; + + /* Write it out and update our limit */ + early_write_config_dword(hose, current_bus, pci_devfn, + bar, bar_value); + + *lower_limit = bar_value + bar_size; + + /* + * If we are a 64-bit decoder then increment to the + * upper 32 bits of the bar and force it to locate + * in the lower 4GB of memory. + */ + if (found_mem64) { + bar += 4; + early_write_config_dword(hose, + current_bus, + pci_devfn, + bar, + 0x00000000); + } + + bar_nr++; + + DBG("size=0x%x, address=0x%x\n", + bar_size, bar_value); + } + +} + +void __init +pciauto_prescan_setup_bridge(struct pci_channel *hose, + int current_bus, + int pci_devfn, + int sub_bus) +{ + int cmdstat; + + /* Configure bus number registers */ + early_write_config_byte(hose, current_bus, pci_devfn, + PCI_PRIMARY_BUS, current_bus); + early_write_config_byte(hose, current_bus, pci_devfn, + PCI_SECONDARY_BUS, sub_bus + 1); + early_write_config_byte(hose, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, 0xff); + + /* Round memory allocator to 1MB boundary */ + pciauto_upper_memspc &= ~(0x100000 - 1); + + /* Round I/O allocator to 4KB boundary */ + pciauto_upper_iospc &= ~(0x1000 - 1); + + /* Set up memory and I/O filter limits, assume 32-bit I/O space */ + early_write_config_word(hose, current_bus, pci_devfn, PCI_MEMORY_LIMIT, + ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16); + early_write_config_byte(hose, current_bus, pci_devfn, PCI_IO_LIMIT, + ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8); + early_write_config_word(hose, current_bus, pci_devfn, + PCI_IO_LIMIT_UPPER16, + ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16); + + /* We don't support prefetchable memory for now, so disable */ + early_write_config_word(hose, current_bus, pci_devfn, + PCI_PREF_MEMORY_BASE, 0x1000); + early_write_config_word(hose, current_bus, pci_devfn, + PCI_PREF_MEMORY_LIMIT, 0x1000); + + /* Enable memory and I/O accesses, enable bus master */ + early_read_config_dword(hose, current_bus, pci_devfn, PCI_COMMAND, + &cmdstat); + early_write_config_dword(hose, current_bus, pci_devfn, PCI_COMMAND, + cmdstat | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER); +} + +void __init +pciauto_postscan_setup_bridge(struct pci_channel *hose, + int current_bus, + int pci_devfn, + int sub_bus) +{ + /* Configure bus number registers */ + early_write_config_byte(hose, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, sub_bus); + + /* Round memory allocator to 1MB boundary */ + pciauto_upper_memspc &= ~(0x100000 - 1); + early_write_config_word(hose, current_bus, pci_devfn, PCI_MEMORY_BASE, + pciauto_upper_memspc >> 16); + + /* Round I/O allocator to 4KB boundary */ + pciauto_upper_iospc &= ~(0x1000 - 1); + early_write_config_byte(hose, current_bus, pci_devfn, PCI_IO_BASE, + (pciauto_upper_iospc & 0x0000f000) >> 8); + early_write_config_word(hose, current_bus, pci_devfn, + PCI_IO_BASE_UPPER16, pciauto_upper_iospc >> 16); +} + +#define PCIAUTO_IDE_MODE_MASK 0x05 + +int __init +pciauto_bus_scan(struct pci_channel *hose, int current_bus) +{ + int sub_bus; + u32 pci_devfn, pci_class, cmdstat, found_multi=0; + unsigned short vid; + unsigned char header_type; + int devfn_start = 0; + int devfn_stop = 0xff; + + sub_bus = current_bus; + + if (hose->first_devfn) + devfn_start = hose->first_devfn; + if (hose->last_devfn) + devfn_stop = hose->last_devfn; + + for (pci_devfn=devfn_start; pci_devfn> 16) == PCI_CLASS_BRIDGE_PCI) { + DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn)); + pciauto_prescan_setup_bridge(hose, current_bus, + pci_devfn, sub_bus); + sub_bus = pciauto_bus_scan(hose, sub_bus+1); + pciauto_postscan_setup_bridge(hose, current_bus, + pci_devfn, sub_bus); + + } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { + + unsigned char prg_iface; + + early_read_config_byte(hose, current_bus, pci_devfn, + PCI_CLASS_PROG, &prg_iface); + if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { + DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n"); + continue; + } + } + + /* + * Found a peripheral, enable some standard + * settings + */ + early_read_config_dword(hose, current_bus, pci_devfn, + PCI_COMMAND, &cmdstat); + early_write_config_dword(hose, current_bus, pci_devfn, + PCI_COMMAND, cmdstat | PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER); + early_write_config_byte(hose, current_bus, pci_devfn, + PCI_LATENCY_TIMER, 0x80); + + /* Allocate PCI I/O and/or memory space */ + pciauto_setup_bars(hose, current_bus, pci_devfn); + } + return sub_bus; +} + +int __init +pciauto_assign_resources(int busno, struct pci_channel *hose) +{ + /* setup resource limits */ + pciauto_lower_iospc = hose->io_resource->start; + pciauto_upper_iospc = hose->io_resource->end + 1; + pciauto_lower_memspc = hose->mem_resource->start; + pciauto_upper_memspc = hose->mem_resource->end + 1; + + return pciauto_bus_scan(hose, busno); +} + + +/* + * These functions are used early on before PCI scanning is done + * and all of the pci_dev and pci_bus structures have been created. + */ +static struct pci_dev *fake_pci_dev(struct pci_channel *hose, int busnr, + int devfn) +{ + static struct pci_dev dev; + static struct pci_bus bus; + + dev.bus = &bus; + dev.sysdata = hose; + dev.devfn = devfn; + bus.number = busnr; + bus.ops = hose->pci_ops; + + return &dev; +} + +#define EARLY_PCI_OP(rw, size, type) \ +int early_##rw##_config_##size(struct pci_channel *hose, int bus, \ + int devfn, int offset, type value) \ +{ \ + return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \ + offset, value); \ +} + +EARLY_PCI_OP(read, byte, u8 *) +EARLY_PCI_OP(read, word, u16 *) +EARLY_PCI_OP(read, dword, u32 *) +EARLY_PCI_OP(write, byte, u8) +EARLY_PCI_OP(write, word, u16) +EARLY_PCI_OP(write, dword, u32) diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/proc.c linux/arch/mips/kernel/proc.c --- v2.4.9/linux/arch/mips/kernel/proc.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/proc.c Sun Sep 9 10:43:01 2001 @@ -1,8 +1,10 @@ /* * linux/arch/mips/kernel/proc.c * - * Copyright (C) 1995, 1996 Ralf Baechle + * Copyright (C) 1995, 1996, 2001 Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. */ +#include #include #include #include @@ -12,9 +14,9 @@ #include #include -unsigned long unaligned_instructions; +extern unsigned long unaligned_instructions; unsigned int vced_count, vcei_count; -#if !defined(CONFIG_CPU_HAS_LLSC) +#ifndef CONFIG_CPU_HAS_LLSC unsigned long ll_ops, sc_ops; #endif @@ -83,7 +85,7 @@ len += sprintf(buffer + len, "microsecond timers\t: %s\n", (mips_cpu.options & MIPS_CPU_COUNTER) ? "yes" : "no"); len += sprintf(buffer + len, "extra interrupt vector\t: %s\n", - dedicated_iv_available ? "yes" : "no"); + (mips_cpu.options & MIPS_CPU_DIVEC) ? "yes" : "no"); len += sprintf(buffer + len, "hardware watchpoint\t: %s\n", watch_available ? "yes" : "no"); @@ -92,7 +94,7 @@ len += sprintf(buffer + len, fmt, 'D', vced_count); len += sprintf(buffer + len, fmt, 'I', vcei_count); -#if !defined(CONFIG_CPU_HAS_LLSC) +#ifndef CONFIG_CPU_HAS_LLSC len += sprintf(buffer + len, "ll emulations\t\t: %lu\n", ll_ops); len += sprintf(buffer + len, "sc emulations\t\t: %lu\n", diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v2.4.9/linux/arch/mips/kernel/process.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/process.c Sun Sep 9 10:43:01 2001 @@ -83,13 +83,10 @@ childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; if (last_task_used_math == current) -#ifdef CONFIG_MIPS_FPU_EMULATOR - if (mips_cpu.options & MIPS_CPU_FPU) -#endif - { + if (mips_cpu.options & MIPS_CPU_FPU) { set_cp0_status(ST0_CU1); save_fp(p); - } + } /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; *childregs = *regs; @@ -120,8 +117,8 @@ * switching for most programs since they don't use the fpu. */ p->thread.cp0_status = read_32bit_cp0_register(CP0_STATUS) & - ~(ST0_CU3|ST0_CU2|ST0_CU1|KU_MASK); - childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1); + ~(ST0_CU2|ST0_CU1|KU_MASK); + childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); return 0; } diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.4.9/linux/arch/mips/kernel/ptrace.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips/kernel/ptrace.c Tue Sep 18 16:56:19 2001 @@ -29,11 +29,21 @@ #include #include +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* Nothing to do.. */ +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int res; - extern void save_fp(void*); + extern void save_fp(struct task_struct *); lock_kernel(); #if 0 @@ -111,19 +121,31 @@ unsigned long long *fregs = (unsigned long long *) &child->thread.fpu.hard.fp_regs[0]; -#ifdef CONFIG_MIPS_FPU_EMULATOR - if(!(mips_cpu.options & MIPS_CPU_FPU)) { - fregs = (unsigned long long *) - &child->thread.fpu.soft.regs[0]; - } else + if(!(mips_cpu.options & MIPS_CPU_FPU)) { + fregs = (unsigned long long *) + child->thread.fpu.soft.regs; + } else + if (last_task_used_math == child) { + enable_cp1(); + save_fp(child); + disable_cp1(); + last_task_used_math = NULL; + regs->cp0_status &= ~ST0_CU1; + } + /* + * The odd registers are actually the high + * order bits of the values stored in the even + * registers - unless we're using r2k_switch.S. + */ +#ifdef CONFIG_CPU_R3000 + if (mips_cpu.options & MIPS_CPU_FPU) + tmp = *(unsigned long *)(fregs + addr); + else #endif - if (last_task_used_math == child) { - enable_cp1(); - save_fp(child); - disable_cp1(); - last_task_used_math = NULL; - } - tmp = (unsigned long) fregs[(addr - 32)]; + if (addr & 1) + tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); + else + tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); } else { tmp = -1; /* FP not yet used */ } @@ -144,12 +166,10 @@ tmp = regs->lo; break; case FPC_CSR: -#ifdef CONFIG_MIPS_FPU_EMULATOR - if(!(mips_cpu.options & MIPS_CPU_FPU)) + if (!(mips_cpu.options & MIPS_CPU_FPU)) tmp = child->thread.fpu.soft.sr; else -#endif - tmp = child->thread.fpu.hard.control; + tmp = child->thread.fpu.hard.control; break; case FPC_EIR: { /* implementation / version register */ unsigned int flags; @@ -192,19 +212,17 @@ unsigned long long *fregs; fregs = (unsigned long long *)&child->thread.fpu.hard.fp_regs[0]; if (child->used_math) { - if (last_task_used_math == child) -#ifdef CONFIG_MIPS_FPU_EMULATOR - if(!(mips_cpu.options & MIPS_CPU_FPU)) { - fregs = (unsigned long long *) - &child->thread.fpu.soft.regs[0]; - } else -#endif - { - enable_cp1(); - save_fp(child); - disable_cp1(); - last_task_used_math = NULL; - regs->cp0_status &= ~ST0_CU1; + if (last_task_used_math == child) { + if(!(mips_cpu.options & MIPS_CPU_FPU)) { + fregs = (unsigned long long *) + child->thread.fpu.soft.regs; + } else { + enable_cp1(); + save_fp(child); + disable_cp1(); + last_task_used_math = NULL; + regs->cp0_status &= ~ST0_CU1; + } } } else { /* FP not yet used */ @@ -212,7 +230,23 @@ sizeof(child->thread.fpu.hard)); child->thread.fpu.hard.control = 0; } - fregs[addr - FPR_BASE] = data; + /* + * The odd registers are actually the high order bits + * of the values stored in the even registers - unless + * we're using r2k_switch.S. + */ +#ifdef CONFIG_CPU_R3000 + if (mips_cpu.options & MIPS_CPU_FPU) + *(unsigned long *)(fregs + addr) = data; + else +#endif + if (addr & 1) { + fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; + fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32; + } else { + fregs[addr - FPR_BASE] &= ~0xffffffffLL; + fregs[addr - FPR_BASE] |= data; + } break; } case PC: @@ -225,12 +259,10 @@ regs->lo = data; break; case FPC_CSR: -#ifdef CONFIG_MIPS_FPU_EMULATOR - if(!(mips_cpu.options & MIPS_CPU_FPU)) + if (!(mips_cpu.options & MIPS_CPU_FPU)) child->thread.fpu.soft.sr = data; else -#endif - child->thread.fpu.hard.control = data; + child->thread.fpu.hard.control = data; break; default: /* The rest are not allowed. */ @@ -269,18 +301,7 @@ break; case PTRACE_DETACH: /* detach a process that was attached. */ - res = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace = 0; - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - wake_up_process(child); - res = 0; + res = ptrace_detach(child, data); break; case PTRACE_SETOPTIONS: diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S --- v2.4.9/linux/arch/mips/kernel/r2300_switch.S Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/r2300_switch.S Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: r2300_switch.S,v 1.8 1999/08/18 23:37:44 ralf Exp $ - * +/* * r2300_switch.S: R2300 specific task switching code. * * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S --- v2.4.9/linux/arch/mips/kernel/r4k_switch.S Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/r4k_switch.S Sun Sep 9 10:43:01 2001 @@ -7,15 +7,10 @@ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1994, 1995, 1996, by Andreas Busse * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2000 MIPS Technologies, Inc. + * written by Carsten Langgaard, carstenl@mips.com */ -/************************************************************************** - * 13 Nov, 2000. - * Made support for MIPS32 CPUs and restoring of fp registers. - * - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ - +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/reset.c linux/arch/mips/kernel/reset.c --- v2.4.9/linux/arch/mips/kernel/reset.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/reset.c Sun Sep 9 10:43:01 2001 @@ -1,7 +1,10 @@ /* - * linux/arch/mips/sni/process.c + * 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. * - * Reset the machine. + * Copyright (C) 2001 by Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. */ #include #include @@ -13,6 +16,9 @@ * So handle all using function pointers to machine specific * functions. */ +void (*_machine_restart)(char *command); +void (*_machine_halt)(void); +void (*_machine_power_off)(void); void machine_restart(char *command) { diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S --- v2.4.9/linux/arch/mips/kernel/scall_o32.S Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/scall_o32.S Sun Sep 9 10:43:01 2001 @@ -65,36 +65,32 @@ 1: sw v0, PT_R2(sp) # result EXPORT(o32_ret_from_sys_call) - la t1, irq_stat # softirq_active -#ifdef CONFIG_SMP - lw t0, TASK_PROCESSOR($28) - sll t0, t0, 5 - addu t1, t0 -#endif - lw t0, 0(t1) # softirq_active - lw t1, 4(t1) # softirq_mask. unused delay slot - and t0, t1 - bnez t0, o32_handle_softirq + mfc0 t0, CP0_STATUS # need_resched and signals atomic test + ori t0, t0, 1 + xori t0, t0, 1 + mtc0 t0, CP0_STATUS -9: lw t0,PT_STATUS(sp) # returning to kernel mode? - andi t1, t0, KU_USER lw t2, TASK_NEED_RESCHED($28) - beqz t1, o32_return # -> yes bnez t2, o32_reschedule lw v0, TASK_SIGPENDING($28) + bnez v0, signal_return +restore_all: + RESTORE_SOME + RESTORE_SP_AND_RET + +/* Put this behind restore_all for the sake of the branch prediction. */ +signal_return: + .type signal_return, @function + + mfc0 t0, CP0_STATUS + ori t0, t0, 1 + mtc0 t0, CP0_STATUS + move a0, zero - beqz v0, o32_return move a1, sp - SAVE_STATIC jal do_signal + b restore_all -o32_return: - RESTORE_SOME - RESTORE_SP_AND_RET - -o32_handle_softirq: - jal do_softirq - b 9b o32_reschedule: SAVE_STATIC jal schedule diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c --- v2.4.9/linux/arch/mips/kernel/setup.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/setup.c Sun Sep 9 10:43:01 2001 @@ -191,6 +191,12 @@ MIPS_CPU_WATCH | MIPS_CPU_VCE; mips_cpu.tlbsize = 48; break; + case PRID_IMP_VR41XX: + mips_cpu.cputype = CPU_VR41XX; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS; + mips_cpu.tlbsize = 32; + break; case PRID_IMP_R4600: mips_cpu.cputype = CPU_R4600; mips_cpu.isa_level = MIPS_CPU_ISA_III; @@ -282,7 +288,7 @@ break; case PRID_IMP_R10000: mips_cpu.cputype = CPU_R10000; - mips_cpu.cputype = MIPS_CPU_ISA_IV; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_COUNTER | MIPS_CPU_WATCH; @@ -719,8 +725,10 @@ #ifdef CONFIG_BLK_DEV_INITRD /* Board specific code should have set up initrd_start and initrd_end */ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; + if( __rd_start != __rd_end ) { + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; + } initrd_below_start_ok = 1; if (initrd_start) { unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v2.4.9/linux/arch/mips/kernel/signal.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/signal.c Sun Sep 9 10:43:01 2001 @@ -464,10 +464,10 @@ /* * Set up the return code ... * - * li v0, __NR_sigreturn + * li v0, __NR_rt_sigreturn * syscall */ - err |= __put_user(0x24020000 + __NR_sigreturn, + err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0); err |= __put_user(0x0000000c , frame->rs_code + 1); diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/softfp.S linux/arch/mips/kernel/softfp.S --- v2.4.9/linux/arch/mips/kernel/softfp.S Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/kernel/softfp.S Wed Dec 31 16:00:00 1969 @@ -1,666 +0,0 @@ -/* - * 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. - * - * Copyright (C) 1998, 2000 by Ralf Baechle - * - * For now it's just a crude hack good enough to run certain fp programs like - * Mozilla. - * XXX: Handle MIPS II/III/IV/V enhancements, exceptions, ... - */ -#include -#include - -#ifndef __KERNEL__ -#define printk printf -#endif - -#define LOCK_KERNEL -#define UNLOCK_KERNEL - -/* - * This duplicates definitions from . - */ -#define KERN_EMERG "<0>" /* system is unusable */ -#define KERN_ALERT "<1>" /* action must be taken immediately */ -#define KERN_CRIT "<2>" /* critical conditions */ -#define KERN_ERR "<3>" /* error conditions */ -#define KERN_WARNING "<4>" /* warning conditions */ -#define KERN_NOTICE "<5>" /* normal but significant condition */ -#define KERN_INFO "<6>" /* informational */ -#define KERN_DEBUG "<7>" /* debug-level messages */ - -/* - * This duplicates definitions from - */ -#define SIGILL 4 /* Illegal instruction (ANSI). */ - -/* - * Definitions about the instruction format - */ -#define fd_shift 6 -#define fr_shift 21 -#define fs_shift 11 -#define ft_shift 16 - -/* - * NaNs as use by the MIPS architecture - */ -#define S_QNaN 0x7fbfffff -#define D_QNaN 0x7ff7ffffffffffff -#define W_QNaN 0x7fffffff -#define L_QNaN 0x7fffffffffffffff - -/* - * Checking for NaNs - */ -#define S_is_QNaN(reg,res) \ - sll res, reg, S_F_size - S_F_bits -#define D_is_QNaN(reg1,reg2,res) \ - sll res, reg1, (D_F_size - 32) - (D_F_bits - 32); \ - or res, reg2 - -/* - * Checking for Denorms - */ -#define S_is_Denorm(reg,res) \ - li res, 1 << (S_F_bits - 1); \ - and reg, res - -/* - * Some constants that define the properties of single precission numbers. - */ -#define S_M_prec 24 -#define S_E_max 127 -#define S_E_min -126 -#define S_E_bias 127 -#define S_E_bits 8 -#define S_F_bits 23 -#define S_F_size 32 - -/* Set temp0, if exponent of reg is S_E_max + 1. */ -#define S_is_E_max(reg,temp0,temp1) \ - li temp0, (S_E_max + 1 + S_E_bias) << S_F_bits; \ - and temp1, temp0, reg; \ - seq temp0, temp1 /* temp0 != 0 if NaN */ - -/* Clear temp0, if exponent of reg is S_E_min - 1. */ -#define S_is_E_min(reg,temp0) \ - li temp0, (S_E_min - 1 + S_E_bias) << S_F_bits; \ - and temp0, reg /* temp0 == 0 if denorm or zero */ - -/* Set temp0 if reg is a NaN assuming S_is_E_max is true */ -#define S_get_F(reg,temp0) \ - li temp0, (1 << S_F_bits) - 1; \ - and temp0, reg /* temp0 != 0 if NaN */ - -/* Set res if fraction of reg is != 0. */ -#define S_is_Inf(reg,res) \ - li res, (1 << S_F_bits) - 1; \ - and res, reg /* temp0 == 0 if Inf */ - - -/* - * Some constants that define the properties of double precission numbers. - */ -#define D_M_prec 53 -#define D_E_max 1023 -#define D_E_min -1022 -#define D_E_bias 1023 -#define D_E_bits 8 -#define D_F_bits 52 -#define D_F_size 64 - -/* Set temp0, if exponent of reg1/reg2 is D_E_max. */ -#define D_is_E_max(reg1,reg2,temp0,temp1) \ - li temp0, (D_E_max + 1 + D_E_bias) << (D_F_bits - 32); \ - and temp1, temp0, reg1; \ - seq temp0, temp1 /* temp0 != 0 if NaN */ - -/* Clear temp0, if exponent of reg is D_E_min. */ -#define D_is_E_min(reg1,reg2,res) \ - li res, (D_E_min + 1 + D_E_bias) << (D_F_bits - 32); \ - and res, reg1 /* temp0 == 0 if NaN or zero */ - -/* Set res if reg is a NaN assuming S_is_E_max is true */ -#define D_get_F(reg1,reg2,res) \ - li res, (1 << (D_F_bits - 32)) - 1; \ - and res, reg1 /* temp0 != 0 if NaN */ - -/* Set temp0 if reg1/reg2 is a NaN */ -#define D_is_NAN(reg1,reg2,temp0,temp1) \ - li temp0, (1 << (D_F_bits - 32) - 1; \ - and temp0, reg1; \ - or temp0, reg2; \ - sne temp0, zero, temp0 /* temp0 != 0 if NaN */ - -/* Set res if fraction of reg1/reg2 is != 0. */ -#define D_is_Inf(reg1,reg2,res) \ - li res, (1 << (D_F_bits - 32)) - 1; \ - and res, reg1; \ - or res, reg2 /* temp0 == 0 if Inf */ - -/* Complain about yet unhandled instruction. */ -#define BITCH(insn) \ -insn: LOCK_KERNEL; \ - la a1, 8f; \ - TEXT(#insn); \ - la a0, nosim; \ - UNLOCK_KERNEL; \ - j done - - .data -nosim: .asciz KERN_DEBUG "Don't know how to simulate %s instruction\n" - .previous - -/* - * When we come here, we've saved some of the integer registers and - * reenabled interrupts. - */ -LEAF(simfp) - .set noreorder - .cpload $25 - .set reorder - - subu sp, 16 - .cprestore 20 - sw ra, 16(sp) - - /* For now we assume that we get the opcode to simulate passed in as - an argument. */ - move t0, a0 - - /* - * First table lookup using insn[5:0] - */ - la t1, lowtab - andi t2, t0, 0x3f - sll t2, t2, 2 - addu t1, t2 - lw t1, (t1) - jr t1 - END(simfp) - -/* - * We only decode the lower 3 of the 5 bit in the fmt field. That way we - * can keep the jump table significantly shorter. - */ -#define FMT_switch(insn,opc,temp0,temp1) \ -insn: srl temp0, opc, 19; \ - andi temp0, 0x1c; \ - la temp1, insn##.tab; \ - addu temp0, temp1; \ - lw temp0, (temp0); \ - jr temp0; \ - \ - .data; \ -insn##.tab: \ - .word insn##.s, insn##.d, unimp, unimp; \ - .word insn##.w, insn##.l, unimp, unimp; \ - .previous - - BITCH(add) - BITCH(sub) - BITCH(mul) - BITCH(div) - BITCH(sqrt) - BITCH(abs) - BITCH(mov) - BITCH(neg) - BITCH(round.l) - BITCH(trunc.l) - BITCH(ceil.l) - BITCH(floor.l) - BITCH(round.w) - BITCH(trunc.w) - BITCH(ceil.w) - BITCH(floor.w) - BITCH(cvt.s) - BITCH(cvt.d) - -/* ------------------------------------------------------------------------ */ - -FMT_switch(cvt.w,t0,t1,t2) - -/* Convert a single fp to a fixed point integer. */ -cvt.w.s: - srl t1, t0, fs_shift # Get source register - andi t1, 31 - jal s_get_fpreg - - S_is_E_max(t1,t2,t3) - beqz t2, 3f - /* Might be a NaN or Inf. */ - S_get_F(t1,t2) - beqz t2, 2f - - /* It's a NaN. IEEE says undefined. */ - /* Is it a QNaN? Then the result is a QNaN as well. */ - S_is_QNaN(t1,t2) - bltz t2, 1f - - /* XXX Ok, it's a SNaN. Signal invalid exception, if enabled. - For now we don't signal and supply a QNaN for result. */ - -1: li t2, W_QNaN - srl t1, t0, fd_shift # Put result register - andi t1, 31 - jal s_put_fpreg - j done -2: - - S_is_Inf(t1,t2) - bnez t2, 2f - - /* It's +/- Inf. Set register to +/- max. integer. */ - /* XXX Send invalid operation exception instead, if enabled. */ - srl t1, t1, 31 # Extract sign bit - li t2, 0x7fffffff - addu t2, t1 - - srl t1, t0, fd_shift # Put result register - andi t1, 31 - jal s_put_fpreg - j done -2: -3: - - /* But then it might be a denorm or zero? */ - S_is_E_min(t1,t2) - bnez t2, 2f - - /* Ok, it's a denorm or zero. */ - S_get_F(t1,t2) - beqz t2, 1f - - /* It's a denorm. */ - /* XXX Should be signaling inexact exception, if enabled. */ - /* Fall through. */ -1: - /* Yes, it is a denorm or zero. Supply a zero as result. */ - move t2, zero - srl t1, t0, fd_shift # Put result register - andi t1, 31 - jal s_put_fpreg - j done -2: - - /* XXX Ok, it's a normal number. We don't handle that case yet. - If we have fp hardware this case is unreached. Add this for - full fp simulation. */ - - /* Done, return. */ - lw ra, 16(sp) - addu sp, 16 - jr ra - -/* Convert a double fp to a fixed point integer. */ -cvt.w.d: - srl t1, t0, fs_shift # Get source register - andi t1, 31 - jal d_get_fpreg - - D_is_E_max(t1,t2,t3,t4) - beqz t3, 3f - - /* Might be a NaN or Inf. */ - D_get_F(t1,t2,t3) - or t3, t2 - beqz t3, 2f - - /* It's a NaN. IEEE says undefined. */ - /* Is it a QNaN? Then the result is a QNaN as well. */ - D_is_QNaN(t1,t2,t3) - bltz t3, 1f - - /* XXX Ok, it's a SNaN. Signal invalid exception, if enabled. - For now we don't signal and supply a QNaN for result. */ - -1: li t2, W_QNaN - srl t1, t0, fd_shift # Put result register - andi t1, 31 - jal s_put_fpreg - j done -2: - - D_is_Inf(t1,t2,t3) - bnez t3, 2f - - /* It's +/- Inf. Set register to +/- max. integer. */ - /* XXX Send invalid operation exception instead, if enabled. */ - srl t1, t1, 31 # Extract sign bit - li t2, 0x7fffffff - addu t2, t1 - - srl t1, t0, fd_shift # Put result register - andi t1, 31 - jal s_put_fpreg - j done -2: -3: - - /* But then it might be a denorm or zero? */ - D_is_E_min(t1,t2,t3) - bnez t3, 2f - - /* Ok, it's a denorm or zero. */ - D_get_F(t1,t2,t3) - or t3, t2 - beqz t3, 1f - - /* It's a denorm. */ - /* XXX Should be signaling inexact exception, if enabled. */ - /* Fall through. */ -1: - /* Yes, it is a denorm or zero. Supply a zero as result. */ - move t2, zero - srl t1, t0, fd_shift # Put result register - andi t1, 31 - jal s_put_fpreg - j done -2: - - /* XXX Ok, it's a normal number. We don't handle that case yet. - If we have fp hardware this case is only reached if the value - of the source register exceeds the range which is representable - in a single precission register. For now we kludge by returning - +/- maxint and don't signal overflow. */ - - srl t1, t1, 31 # Extract sign bit - li t2, 0x7fffffff - addu t2, t1 - - srl t1, t0, fd_shift # Put result register - andi t1, 31 - jal s_put_fpreg - - /* Done, return. */ - lw ra, 16(sp) - addu sp, 16 - jr ra - -cvt.w.w = unimp # undefined result -cvt.w.l = unimp # undefined result - -/* MIPS III extension, no need to handle for 32bit OS. */ -cvt.l = unimp - -/* ------------------------------------------------------------------------ */ - - BITCH(c.f) - BITCH(c.un) - BITCH(c.eq) - BITCH(c.ueq) - BITCH(c.olt) - BITCH(c.ult) - BITCH(c.ole) - BITCH(c.ule) - BITCH(c.sf) - BITCH(c.ngle) - BITCH(c.seq) - BITCH(c.ngl) - BITCH(c.lt) - BITCH(c.nge) - BITCH(c.le) - BITCH(c.ngt) - -/* Get the single precission register which's number is in t1. */ -s_get_fpreg: - .set noat - sll AT, t1, 2 - sll t1, 3 - addu t1, AT - la AT, 1f - addu AT, t1 - jr AT - .set at - -1: mfc1 t1, $0 - jr ra - mfc1 t1, $1 - jr ra - mfc1 t1, $2 - jr ra - mfc1 t1, $3 - jr ra - mfc1 t1, $4 - jr ra - mfc1 t1, $5 - jr ra - mfc1 t1, $6 - jr ra - mfc1 t1, $7 - jr ra - mfc1 t1, $8 - jr ra - mfc1 t1, $9 - jr ra - mfc1 t1, $10 - jr ra - mfc1 t1, $11 - jr ra - mfc1 t1, $12 - jr ra - mfc1 t1, $13 - jr ra - mfc1 t1, $14 - jr ra - mfc1 t1, $15 - jr ra - mfc1 t1, $16 - jr ra - mfc1 t1, $17 - jr ra - mfc1 t1, $18 - jr ra - mfc1 t1, $19 - jr ra - mfc1 t1, $20 - jr ra - mfc1 t1, $21 - jr ra - mfc1 t1, $22 - jr ra - mfc1 t1, $23 - jr ra - mfc1 t1, $24 - jr ra - mfc1 t1, $25 - jr ra - mfc1 t1, $26 - jr ra - mfc1 t1, $27 - jr ra - mfc1 t1, $28 - jr ra - mfc1 t1, $29 - jr ra - mfc1 t1, $30 - jr ra - mfc1 t1, $31 - jr ra - -/* - * Put the value in t2 into the single precission register which's number - * is in t1. - */ -s_put_fpreg: - .set noat - sll AT, t1, 2 - sll t1, 3 - addu t1, AT - la AT, 1f - addu AT, t1 - jr AT - .set at - -1: mtc1 t2, $0 - jr ra - mtc1 t2, $1 - jr ra - mtc1 t2, $2 - jr ra - mtc1 t2, $3 - jr ra - mtc1 t2, $4 - jr ra - mtc1 t2, $5 - jr ra - mtc1 t2, $6 - jr ra - mtc1 t2, $7 - jr ra - mtc1 t2, $8 - jr ra - mtc1 t2, $9 - jr ra - mtc1 t2, $10 - jr ra - mtc1 t2, $11 - jr ra - mtc1 t2, $12 - jr ra - mtc1 t2, $13 - jr ra - mtc1 t2, $14 - jr ra - mtc1 t2, $15 - jr ra - mtc1 t2, $16 - jr ra - mtc1 t2, $17 - jr ra - mtc1 t2, $18 - jr ra - mtc1 t2, $19 - jr ra - mtc1 t2, $20 - jr ra - mtc1 t2, $21 - jr ra - mtc1 t2, $22 - jr ra - mtc1 t2, $23 - jr ra - mtc1 t2, $24 - jr ra - mtc1 t2, $25 - jr ra - mtc1 t2, $26 - jr ra - mtc1 t2, $27 - jr ra - mtc1 t2, $28 - jr ra - mtc1 t2, $29 - jr ra - mtc1 t2, $30 - jr ra - mtc1 t2, $31 - jr ra - -/* Get the double precission register which's number is in t1 into t1/t2. */ -d_get_fpreg: - .set noat - sll t1, 3 - la AT, 1f - addu AT, t1 - jr AT - .set at - -1: mfc1 t1, $0 - mfc1 t2, $1 - jr ra - mfc1 t1, $2 - mfc1 t2, $3 - jr ra - mfc1 t1, $4 - mfc1 t2, $5 - jr ra - mfc1 t1, $6 - mfc1 t2, $7 - jr ra - mfc1 t1, $8 - mfc1 t2, $9 - jr ra - mfc1 t1, $10 - mfc1 t2, $11 - jr ra - mfc1 t1, $12 - mfc1 t2, $13 - jr ra - mfc1 t1, $14 - mfc1 t2, $15 - jr ra - mfc1 t1, $16 - mfc1 t2, $17 - jr ra - mfc1 t1, $18 - mfc1 t2, $19 - jr ra - mfc1 t1, $20 - mfc1 t2, $21 - jr ra - mfc1 t1, $22 - mfc1 t2, $23 - jr ra - mfc1 t1, $24 - mfc1 t2, $25 - jr ra - mfc1 t1, $26 - mfc1 t2, $27 - jr ra - mfc1 t1, $28 - mfc1 t2, $29 - jr ra - mfc1 t1, $30 - mfc1 t2, $31 - jr ra - -/* - * Send an invalid operation exception. - */ -invalid: - lw ra, 16(sp) - addu sp, 16 - jr ra - -/* - * Done, just skip over the current instruction - */ -done: - lw ra, 16(sp) - addu sp, 16 - jr ra - -unimp: - /* We've run into an yet unknown instruction. This happens either - on new, yet unsupported CPU types or when the faulting instruction - is being executed for cache but has been overwritten in memory. */ - LOCK_KERNEL - move a0, t0 - PRINT(KERN_DEBUG "FP support: unknown fp op %08lx, ") - PRINT("please mail to ralf@gnu.org.\n") - - li a0, SIGILL # Die, sucker ... - move a1, $28 - jal force_sig - UNLOCK_KERNEL - - lw ra, 16(sp) - addu sp, 16 - jr ra - -/* - * Jump table for the lowest 6 bits of a cp1 instruction. - */ - .data -lowtab: .word add, sub, mul, div, sqrt, abs, mov, neg - .word round.l,trunc.l,ceil.l,floor.l,round.w,trunc.w,ceil.w,floor.w - .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .word cvt.s, cvt.d, unimp, unimp, cvt.w, cvt.l, unimp, unimp - .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .word c.f, c.un, c.eq, c.ueq, c.olt, c.ult, c.ole, c.ule - .word c.sf, c.ngle,c.seq, c.ngl, c.lt, c.nge, c.le, c.ngt diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v2.4.9/linux/arch/mips/kernel/time.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/time.c Sun Sep 9 10:43:01 2001 @@ -1,18 +1,15 @@ -/*********************************************************************** +/* * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * - * arch/mips/kernel/time.c - * Common time service routines for MIPS machines. See - * Documents/MIPS/time.txt. + * Common time service routines for MIPS machines. See + * Documents/MIPS/README.txt. * * 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 @@ -29,22 +26,11 @@ #include #include #include - -/* - * macro for catching spurious errors. Eable to LL_DEBUG in kernel hacking - * config menu. - */ -#ifdef CONFIG_LL_DEBUG -#define MIPS_ASSERT(x) if (!(x)) { panic("MIPS_ASSERT failed at %s:%d\n", __FILE__, __LINE__); } -#define MIPS_DEBUG(x) do { x; } while (0) -#else -#define MIPS_ASSERT(x) -#define MIPS_DEBUG(x) -#endif +#include /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) +#define USECS_PER_JIFFY_FRAC ((1000000ULL << 32) / HZ & 0xffffffff) /* * forward reference @@ -74,50 +60,50 @@ */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; + unsigned long flags; + + read_lock_irqsave (&xtime_lock, flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. jiffies - wall_jiffies + * is nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; - read_lock_irqsave (&xtime_lock, flags); - *tv = xtime; - tv->tv_usec += do_gettimeoffset(); - - /* - * xtime is atomically updated in timer_bh. jiffies - wall_jiffies - * is nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; - - read_unlock_irqrestore (&xtime_lock, flags); - - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } + read_unlock_irqrestore (&xtime_lock, flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } } void do_settimeofday(struct timeval *tv) { - write_lock_irq (&xtime_lock); + write_lock_irq (&xtime_lock); - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! - */ - tv->tv_usec -= do_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); - write_unlock_irq (&xtime_lock); + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + + write_unlock_irq (&xtime_lock); } @@ -162,30 +148,26 @@ u32 count; unsigned long res; - MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER); - MIPS_ASSERT(mips_counter_frequency != 0); - MIPS_ASSERT(sll32_usecs_per_cycle != 0); - /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); + count = read_32bit_cp0_register(CP0_COUNT); - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (sll32_usecs_per_cycle)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (sll32_usecs_per_cycle)); - return res; + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; } /* @@ -197,156 +179,107 @@ /* Last jiffy when calibrate_divXX_gettimeoffset() was called. */ static unsigned long last_jiffies = 0; -/* - * copied from include/asm/div64. - * We do the copy instead of include the header file because we don't - * want to reply on _MIPS_ISA value. - */ -#define do_div64_32(res, high, low, base) ({ \ - unsigned long __quot, __mod; \ - unsigned long __cf, __tmp, __i; \ - \ - __asm__(".set push\n\t" \ - ".set noat\n\t" \ - ".set noreorder\n\t" \ - "b 1f\n\t" \ - " li %4,0x21\n" \ - "0:\n\t" \ - "sll $1,%0,0x1\n\t" \ - "srl %3,%0,0x1f\n\t" \ - "or %0,$1,$2\n\t" \ - "sll %1,%1,0x1\n\t" \ - "sll %2,%2,0x1\n" \ - "1:\n\t" \ - "bnez %3,2f\n\t" \ - "sltu $2,%0,%z5\n\t" \ - "bnez $2,3f\n\t" \ - "2:\n\t" \ - " addiu %4,%4,-1\n\t" \ - "subu %0,%0,%z5\n\t" \ - "addiu %2,%2,1\n" \ - "3:\n\t" \ - "bnez %4,0b\n\t" \ - " srl $2,%1,0x1f\n\t" \ - ".set pop" \ - : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ - "=&r" (__i) \ - : "Jr" (base), "0" (high), "1" (low), "2" (0), "3" (0) \ - /* Aarrgh! Ran out of gcc's limit on constraints... */ \ - : "$1", "$2"); \ - \ - (res) = __quot; \ - __mod; }) /* * This is copied from dec/time.c:do_ioasic_gettimeoffset() by Mercij. */ unsigned long calibrate_div32_gettimeoffset(void) { - u32 count; - unsigned long res, tmp; - unsigned long quotient; - - MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER); - - tmp = jiffies; - - quotient = cached_quotient; - - if (last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies != 0) { - unsigned long r0; - do_div64_32(r0, timerhi, timerlo, tmp); - do_div64_32(quotient, USECS_PER_JIFFY, - USECS_PER_JIFFY_FRAC, r0); - cached_quotient = quotient; - } - } - - /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu %2,%3" - : "=l" (tmp), "=h" (res) - : "r" (count), "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; + u32 count; + unsigned long res, tmp; + unsigned long quotient; + + tmp = jiffies; + + quotient = cached_quotient; + + if (last_jiffies != tmp) { + last_jiffies = tmp; + if (last_jiffies != 0) { + unsigned long r0; + do_div64_32(r0, timerhi, timerlo, tmp); + do_div64_32(quotient, USECS_PER_JIFFY, + USECS_PER_JIFFY_FRAC, r0); + cached_quotient = quotient; + } + } + + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu %2,%3" + : "=l" (tmp), "=h" (res) + : "r" (count), "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY - 1; - return res; + return res; } unsigned long calibrate_div64_gettimeoffset(void) { - u32 count; - unsigned long res, tmp; - unsigned long quotient; - - - MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER); - MIPS_ASSERT((mips_cpu.isa_level != MIPS_CPU_ISA_I) && - (mips_cpu.isa_level != MIPS_CPU_ISA_II) && - (mips_cpu.isa_level != MIPS_CPU_ISA_M32)); - - - tmp = jiffies; - - quotient = cached_quotient; - - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "lwu\t%0,%2\n\t" - "dsll32\t$1,%1,0\n\t" - "or\t$1,$1,%0\n\t" - "ddivu\t$0,$1,%3\n\t" - "mflo\t$1\n\t" - "dsll32\t%0,%4,0\n\t" - "nop\n\t" - "ddivu\t$0,%0,$1\n\t" - "mflo\t%0\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r" (quotient) - :"r" (timerhi), - "m" (timerlo), - "r" (tmp), - "r" (USECS_PER_JIFFY) - :"$1"); - cached_quotient = quotient; - } - - /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; + u32 count; + unsigned long res, tmp; + unsigned long quotient; + + tmp = jiffies; - return res; + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY) + :"$1"); + cached_quotient = quotient; + } + + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; } @@ -377,57 +310,56 @@ } - if(!user_mode(regs)) { + if(!user_mode(regs)) { if (prof_buffer && current->pid) { - extern int _stext; - unsigned long pc = regs->cp0_epc; + extern int _stext; + unsigned long pc = regs->cp0_epc; - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - /* - * Dont ignore out-of-bounds pc values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len-1) - pc = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[pc]); - } - } + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len-1) + pc = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } + } /* * call the generic timer interrupt handling */ - do_timer(regs); - - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be - * called as close as possible to 500 ms before the new second starts. - */ - read_lock (&xtime_lock); - if ((time_status & STA_UNSYNC) == 0 && - xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && - xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { + do_timer(regs); + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be + * called as close as possible to 500 ms before the new second starts. + */ + read_lock (&xtime_lock); + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && + xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { if (rtc_set_time(xtime.tv_sec) == 0) { last_rtc_update = xtime.tv_sec; } else { last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } - } - read_unlock (&xtime_lock); + } + read_unlock (&xtime_lock); /* * If jiffies has overflowed in this timer_interrupt we must * update the timer[hi]/[lo] to make fast gettimeoffset funcs * quotient calc still valid. -arca */ - if (!jiffies) { - timerhi = timerlo = 0; - } + if (!jiffies) { + timerhi = timerlo = 0; + } } asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) @@ -442,9 +374,8 @@ irq_exit(cpu, irq); - /* check for bottom half */ - if (softirq_active(cpu)&softirq_mask(cpu)) - do_softirq(); + if (softirq_pending(cpu)) + do_softirq(); } @@ -480,19 +411,14 @@ void __init time_init(void) { - printk("New MIPS time_init() invoked.\n"); - if (board_time_init) board_time_init(); - /* setup xtime */ - write_lock_irq(&xtime_lock); xtime.tv_sec = rtc_get_time(); xtime.tv_usec = 0; - write_unlock_irq(&xtime_lock); /* choose appropriate gettimeoffset routine */ - if ( ! (mips_cpu.options & MIPS_CPU_COUNTER) ) { + if (!(mips_cpu.options & MIPS_CPU_COUNTER)) { /* no cpu counter - sorry */ do_gettimeoffset = null_gettimeoffset; } else if (mips_counter_frequency != 0) { @@ -519,11 +445,6 @@ sll32_usecs_per_cycle = mips_counter_frequency / 100000; sll32_usecs_per_cycle = 0xffffffff / sll32_usecs_per_cycle; sll32_usecs_per_cycle *= 10; - - MIPS_DEBUG(printk("cycles_per_jiffy = %d\n", - cycles_per_jiffy)); - MIPS_DEBUG(printk("sll32_usecs_per_cycle = %d \n", - sll32_usecs_per_cycle)); } /* @@ -537,6 +458,52 @@ * to be NULL function so that we are sure the high-level code * is not invoked accidentally. */ - MIPS_ASSERT(board_timer_setup != NULL); board_timer_setup(&timer_irqaction); +} + +#define FEBRUARY 2 +#define STARTOFTIME 1970 +#define SECDAY 86400L +#define SECYR (SECDAY * 365) +#define leapyear(year) ((year) % 4 == 0) +#define days_in_year(a) (leapyear(a) ? 366 : 365) +#define days_in_month(a) (month_days[(a) - 1]) + +static int month_days[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +void to_tm(unsigned long tim, struct rtc_time * tm) +{ + long hms, day; + int i; + + day = tim / SECDAY; + hms = tim % SECDAY; + + /* Hours, minutes, seconds are easy */ + tm->tm_hour = hms / 3600; + tm->tm_min = (hms % 3600) / 60; + tm->tm_sec = (hms % 3600) % 60; + + /* Number of years in days */ + for (i = STARTOFTIME; day >= days_in_year(i); i++) + day -= days_in_year(i); + tm->tm_year = i; + + /* Number of months in days left */ + if (leapyear(tm->tm_year)) + days_in_month(FEBRUARY) = 29; + for (i = 1; day >= days_in_month(i); i++) + day -= days_in_month(i); + days_in_month(FEBRUARY) = 28; + tm->tm_mon = i; + + /* Days are what is left over (+1) from all that. */ + tm->tm_mday = day + 1; + + /* + * Determine the day of week + */ + tm->tm_wday = (day + 3) % 7; } diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.4.9/linux/arch/mips/kernel/traps.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/traps.c Sun Sep 9 10:43:01 2001 @@ -3,17 +3,18 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994 - 1999 by Ralf Baechle + * Copyright (C) 1994 - 1999, 2000, 01 Ralf Baechle * Modified for R3000 by Paul M. Antoine, 1995, 1996 * Complete output from die() by Ulf Carlsson, 1998 * Copyright (C) 1999 Silicon Graphics, Inc. * * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2000, 01 MIPS Technologies, Inc. */ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +34,6 @@ #include #include #include -#ifndef CONFIG_MIPS_FPU_EMULATOR -#include -#endif /* * Machine specific interrupt handlers @@ -63,12 +62,9 @@ extern asmlinkage void handle_mcheck(void); extern asmlinkage void handle_reserved(void); -extern int fpu_emulator_cop1Handler(int, struct pt_regs *); - -static char *cpu_names[] = CPU_NAMES; +extern int fpu_emulator_cop1Handler(struct pt_regs *); char watch_available = 0; -char dedicated_iv_available = 0; void (*ibe_board_handler)(struct pt_regs *regs); void (*dbe_board_handler)(struct pt_regs *regs); @@ -81,7 +77,7 @@ */ #define MODULE_RANGE (8*1024*1024) -#if !defined(CONFIG_CPU_HAS_LLSC) +#ifndef CONFIG_CPU_HAS_LLSC /* * This stuff is needed for the userland ll-sc emulation for R2300 */ @@ -94,8 +90,6 @@ #define OFFSET 0x0000ffff #define LL 0xc0000000 #define SC 0xe0000000 - -#undef DEBUG_LLSC #endif /* @@ -212,7 +206,6 @@ show_trace((unsigned int *) regs->regs[29]); show_code((unsigned int *) regs->cp0_epc); printk("\n"); -while(1); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } @@ -254,89 +247,101 @@ return (first == last && first->insn == value) ? first->nextinsn : 0; } -#define search_dbe_table(addr) \ - search_one_table(__start___dbe_table, __stop___dbe_table - 1, (addr)) +extern spinlock_t modlist_lock; + +static inline unsigned long +search_dbe_table(unsigned long addr) +{ + unsigned long ret = 0; + +#ifndef CONFIG_MODULES + /* There is only the kernel to search. */ + ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); + return ret; +#else + unsigned long flags; + + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + struct archdata *ap; + + spin_lock_irqsave(&modlist_lock, flags); + for (mp = module_list; mp != NULL; mp = mp->next) { + if (!mod_member_present(mp, archdata_end) || + !mod_archdata_member_present(mp, struct archdata, + dbe_table_end)) + continue; + ap = (struct archdata *)(mp->archdata_start); + + if (ap->dbe_table_start == NULL || + !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) + continue; + ret = search_one_table(ap->dbe_table_start, + ap->dbe_table_end - 1, addr); + if (ret) + break; + } + spin_unlock_irqrestore(&modlist_lock, flags); + return ret; +#endif +} static void default_be_board_handler(struct pt_regs *regs) { unsigned long new_epc; - unsigned long fixup = search_dbe_table(regs->cp0_epc); + unsigned long fixup; + int data = regs->cp0_cause & 4; - if (fixup) { - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); - regs->cp0_epc = new_epc; - return; + if (data && !user_mode(regs)) { + fixup = search_dbe_table(regs->cp0_epc); + if (fixup) { + new_epc = fixup_exception(dpf_reg, fixup, + regs->cp0_epc); + regs->cp0_epc = new_epc; + return; + } } /* * Assume it would be too dangerous to continue ... */ + printk(KERN_ALERT "%s bus error, epc == %08lx, ra == %08lx\n", + data ? "Data" : "Instruction", + regs->cp0_epc, regs->regs[31]); + die_if_kernel("Oops", regs); force_sig(SIGBUS, current); } -void do_ibe(struct pt_regs *regs) +asmlinkage void do_ibe(struct pt_regs *regs) { ibe_board_handler(regs); } -void do_dbe(struct pt_regs *regs) +asmlinkage void do_dbe(struct pt_regs *regs) { dbe_board_handler(regs); } -void do_ov(struct pt_regs *regs) +asmlinkage void do_ov(struct pt_regs *regs) { if (compute_return_epc(regs)) return; - force_sig(SIGFPE, current); -} - -#ifdef CONFIG_MIPS_FPE_MODULE -static void (*fpe_handler)(struct pt_regs *regs, unsigned int fcr31); -/* - * Register_fpe/unregister_fpe are for debugging purposes only. To make - * this hack work a bit better there is no error checking. - */ -int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)) -{ - fpe_handler = handler; - return 0; -} - -int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)) -{ - fpe_handler = NULL; - return 0; + force_sig(SIGFPE, current); } -#endif /* * XXX Delayed fp exceptions when doing a lazy ctx switch XXX */ -void do_fpe(struct pt_regs *regs, unsigned long fcr31) +asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { - -#ifdef CONFIG_MIPS_FPU_EMULATOR - if(!(mips_cpu.options & MIPS_CPU_FPU)) - panic("Floating Point Exception with No FPU"); -#endif - -#ifdef CONFIG_MIPS_FPE_MODULE - if (fpe_handler != NULL) { - fpe_handler(regs, fcr31); - return; - } -#endif - if (fcr31 & FPU_CSR_UNI_X) { -#ifdef CONFIG_MIPS_FPU_EMULATOR extern void save_fp(struct task_struct *); extern void restore_fp(struct task_struct *); int sig; /* * Unimplemented operation exception. If we've got the - * Full software emulator on-board, let's use it... + * full software emulator on-board, let's use it... * * Force FPU to dump state into task/thread context. * We're moving a lot of data here for what is probably @@ -348,11 +353,11 @@ save_fp(current); /* Run the emulator */ - sig = fpu_emulator_cop1Handler(0, regs); + sig = fpu_emulator_cop1Handler(regs); /* * We can't allow the emulated instruction to leave the - * Unimplemented Operation bit set in the FCR31 fp-register. + * Unimplemented Operation bit set in $fcr31. */ current->thread.fpu.soft.sr &= ~FPU_CSR_UNI_X; @@ -362,37 +367,6 @@ /* If something went wrong, signal */ if (sig) force_sig(sig, current); -#else - /* Else use mini-emulator */ - - extern void simfp(int); - unsigned long pc; - unsigned int insn; - - /* Retry instruction with flush to zero ... */ - if (!(fcr31 & (1<<24))) { - printk("Setting flush to zero for %s.\n", - current->comm); - fcr31 &= ~FPU_CSR_UNI_X; - fcr31 |= (1<<24); - __asm__ __volatile__( - "ctc1\t%0,$31" - : /* No outputs */ - : "r" (fcr31)); - return; - } - pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); - if(pc & 0x80000000) insn = *(unsigned int *)pc; - else if (get_user(insn, (unsigned int *)pc)) { - /* XXX Can this happen? */ - force_sig(SIGSEGV, current); - } - - printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n", - insn, regs->cp0_epc, current->comm); - simfp(MIPSInst(insn)); - compute_return_epc(regs); -#endif /* CONFIG_MIPS_FPU_EMULATOR */ return; } @@ -408,31 +382,31 @@ { unsigned int *epc; - epc = (unsigned int *) (unsigned long) regs->cp0_epc; - if (regs->cp0_cause & CAUSEF_BD) - epc++; - - if (verify_area(VERIFY_READ, epc, 4)) { - force_sig(SIGSEGV, current); - return 1; - } - *opcode = *epc; + epc = (unsigned int *) regs->cp0_epc + + ((regs->cp0_cause & CAUSEF_BD) != 0); + if (!get_user(*opcode, epc)) + return 0; - return 0; + force_sig(SIGSEGV, current); + return 1; } -void do_bp(struct pt_regs *regs) +asmlinkage void do_bp(struct pt_regs *regs) { siginfo_t info; unsigned int opcode, bcode; + unsigned int *epc; + + epc = (unsigned int *) regs->cp0_epc + + ((regs->cp0_cause & CAUSEF_BD) != 0); + if (get_user(opcode, epc)) + goto sigsegv; /* * There is the ancient bug in the MIPS assemblers that the break * code starts left to bit 16 instead to bit 6 in the opcode. * Gas is bug-compatible ... */ - if (get_insn_opcode(regs, &opcode)) - return; bcode = ((opcode >> 16) & ((1 << 20) - 1)); /* @@ -456,15 +430,23 @@ default: force_sig(SIGTRAP, current); } + return; + +sigsegv: + force_sig(SIGSEGV, current); } -void do_tr(struct pt_regs *regs) +asmlinkage void do_tr(struct pt_regs *regs) { siginfo_t info; unsigned int opcode, bcode; + unsigned *epc; + + epc = (unsigned int *) regs->cp0_epc + + ((regs->cp0_cause & CAUSEF_BD) != 0); + if (get_user(opcode, epc)) + goto sigsegv; - if (get_insn_opcode(regs, &opcode)) - return; bcode = ((opcode >> 6) & ((1 << 20) - 1)); /* @@ -488,9 +470,13 @@ default: force_sig(SIGTRAP, current); } + return; + +sigsegv: + force_sig(SIGSEGV, current); } -#if !defined(CONFIG_CPU_HAS_LLSC) +#ifndef CONFIG_CPU_HAS_LLSC #ifdef CONFIG_SMP #error "ll/sc emulation is not SMP safe" @@ -503,7 +489,7 @@ * this implementation can handle only sychronization between 2 or more * user contexts and is not SMP safe. */ -void do_ri(struct pt_regs *regs) +asmlinkage void do_ri(struct pt_regs *regs) { unsigned int opcode; @@ -520,9 +506,7 @@ return; } } - printk("[%s:%d] Illegal instruction %08lx at %08lx, ra=%08lx, CP0_STATUS=%08lx\n", - current->comm, current->pid, *((unsigned long*)regs->cp0_epc), regs->cp0_epc, - regs->regs[31], regs->cp0_status); + if (compute_return_epc(regs)) return; force_sig(SIGILL, current); @@ -558,10 +542,6 @@ vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); -#ifdef DEBUG_LLSC - printk("ll: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (opcode & RT) >> 16); -#endif - #ifdef CONFIG_PROC_FS ll_ops++; #endif @@ -604,10 +584,6 @@ vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); reg = (opcode & RT) >> 16; -#ifdef DEBUG_LLSC - printk("sc: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (unsigned int)reg); -#endif - #ifdef CONFIG_PROC_FS sc_ops++; #endif @@ -628,52 +604,33 @@ #else /* MIPS 2 or higher */ -void do_ri(struct pt_regs *regs) +asmlinkage void do_ri(struct pt_regs *regs) { unsigned int opcode; - get_insn_opcode(regs, &opcode); - printk("[%s:%ld] Illegal instruction %08x at %08lx ra=%08lx\n", - current->comm, (unsigned long)current->pid, opcode, - regs->cp0_epc, regs->regs[31]); + get_insn_opcode(regs, &opcode); if (compute_return_epc(regs)) return; + force_sig(SIGILL, current); } #endif -void do_cpu(struct pt_regs *regs) +asmlinkage void do_cpu(struct pt_regs *regs) { unsigned int cpid; - extern void lazy_fpu_switch(void*); + extern void lazy_fpu_switch(void *); extern void init_fpu(void); -#ifdef CONFIG_MIPS_FPU_EMULATOR void fpu_emulator_init_fpu(void); int sig; -#endif + cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; if (cpid != 1) goto bad_cid; -#ifdef CONFIG_MIPS_FPU_EMULATOR - if(!(mips_cpu.options & MIPS_CPU_FPU)) { - if (last_task_used_math != current) { - if(!current->used_math) { - fpu_emulator_init_fpu(); - current->used_math = 1; - } - } - sig = fpu_emulator_cop1Handler(0, regs); - last_task_used_math = current; - if(sig) { - force_sig(sig, current); - } - return; - } -#else - if(!(mips_cpu.options & MIPS_CPU_FPU)) goto bad_cid; -#endif + if (!(mips_cpu.options & MIPS_CPU_FPU)) + goto fp_emul; regs->cp0_status |= ST0_CU1; if (last_task_used_math == current) @@ -682,18 +639,30 @@ if (current->used_math) { /* Using the FPU again. */ lazy_fpu_switch(last_task_used_math); } else { /* First time FPU user. */ - init_fpu(); current->used_math = 1; } last_task_used_math = current; return; +fp_emul: + if (last_task_used_math != current) { + if (!current->used_math) { + fpu_emulator_init_fpu(); + current->used_math = 1; + } + } + sig = fpu_emulator_cop1Handler(regs); + last_task_used_math = current; + if (sig) + force_sig(sig, current); + return; + bad_cid: force_sig(SIGILL, current); } -void do_watch(struct pt_regs *regs) +asmlinkage void do_watch(struct pt_regs *regs) { /* * We use the watch exception where available to detect stack @@ -703,14 +672,14 @@ panic("Caught WATCH exception - probably caused by stack overflow."); } -void do_mcheck(struct pt_regs *regs) +asmlinkage void do_mcheck(struct pt_regs *regs) { show_regs(regs); panic("Caught Machine Check exception - probably caused by multiple " "matching entries in the TLB."); } -void do_reserved(struct pt_regs *regs) +asmlinkage void do_reserved(struct pt_regs *regs) { /* * Game over - no way to handle this if it ever occurs. Most probably @@ -723,34 +692,19 @@ static inline void watch_init(void) { - if(mips_cpu.options & MIPS_CPU_WATCH ) { - (void)set_except_vector(23, handle_watch); + if (mips_cpu.options & MIPS_CPU_WATCH ) { + set_except_vector(23, handle_watch); watch_available = 1; } } /* - * Some MIPS CPUs have a dedicated interrupt vector which reduces the - * interrupt processing overhead. Use it where available. - */ -static inline void setup_dedicated_int(void) -{ - extern void except_vec4(void); - - if(mips_cpu.options & MIPS_CPU_DIVEC) { - memcpy((void *)(KSEG0 + 0x200), except_vec4, 8); - set_cp0_cause(CAUSEF_IV); - dedicated_iv_available = 1; - } -} - -/* - * Some MIPS CPUs can enable/disable for cache parity detection, but does + * Some MIPS CPUs can enable/disable for cache parity detection, but do * it different ways. */ static inline void parity_protection_init(void) { - switch(mips_cpu.cputype) { + switch (mips_cpu.cputype) { case CPU_5KC: /* Set the PE bit (bit 31) in the CP0_ECC register. */ printk(KERN_INFO "Enable the cache parity protection for " @@ -764,38 +718,39 @@ } } -void cache_parity_error(void) +asmlinkage void cache_parity_error(void) { - unsigned int reg_val; + unsigned int reg_val; - /* For the moment, report the problem and hang. */ - reg_val = read_32bit_cp0_register(CP0_ERROREPC); + /* For the moment, report the problem and hang. */ + reg_val = read_32bit_cp0_register(CP0_ERROREPC); printk("Cache error exception:\n"); printk("cp0_errorepc == %08x\n", reg_val); reg_val = read_32bit_cp0_register(CP0_CACHEERR); printk("cp0_cacheerr == %08x\n", reg_val); printk("Decoded CP0_CACHEERR: %s cache fault in %s reference.\n", - reg_val&(1<<30)?"secondary":"primary", - reg_val&(1<<31)?"data":"insn"); + reg_val & (1<<30) ? "secondary" : "primary", + reg_val & (1<<31) ? "data" : "insn"); printk("Error bits: %s%s%s%s%s%s%s\n", - reg_val&(1<<29)?"ED ":"", - reg_val&(1<<28)?"ET ":"", - reg_val&(1<<26)?"EE ":"", - reg_val&(1<<25)?"EB ":"", - reg_val&(1<<24)?"EI ":"", - reg_val&(1<<23)?"E1 ":"", - reg_val&(1<<22)?"E0 ":""); - printk("IDX: 0x%08x\n", reg_val&((1<<22)-1)); + reg_val & (1<<29) ? "ED " : "", + reg_val & (1<<28) ? "ET " : "", + reg_val & (1<<26) ? "EE " : "", + reg_val & (1<<25) ? "EB " : "", + reg_val & (1<<24) ? "EI " : "", + reg_val & (1<<23) ? "E1 " : "", + reg_val & (1<<22) ? "E0 " : ""); + printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1)); if (reg_val&(1<<22)) - printk("DErrAddr0: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR0)); + printk("DErrAddr0: 0x%08x\n", + read_32bit_cp0_set1_register(CP0_S1_DERRADDR0)); if (reg_val&(1<<23)) - printk("DErrAddr1: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR1)); + printk("DErrAddr1: 0x%08x\n", + read_32bit_cp0_set1_register(CP0_S1_DERRADDR1)); - - panic("Can't handle the cache error - panic!"); + panic("Can't handle the cache error!"); } unsigned long exception_handlers[32]; @@ -810,7 +765,8 @@ unsigned handler = (unsigned long) addr; unsigned old_handler = exception_handlers[n]; exception_handlers[n] = handler; - if (n == 0 && dedicated_iv_available) { + + if (n == 0 && mips_cpu.options & MIPS_CPU_DIVEC) { *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); @@ -823,10 +779,8 @@ extern asmlinkage int _save_fp_context(struct sigcontext *sc); extern asmlinkage int _restore_fp_context(struct sigcontext *sc); -#ifdef CONFIG_MIPS_FPU_EMULATOR extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); -#endif void __init trap_init(void) { @@ -834,13 +788,10 @@ extern char except_vec0_r4600, except_vec0_r2300; extern char except_vec1_generic, except_vec2_generic; extern char except_vec3_generic, except_vec3_r4000; + extern char except_vec4; extern char except_vec_ejtag_debug; unsigned long i; - if(mips_machtype == MACH_MIPS_MAGNUM_4000 || - mips_machtype == MACH_SNI_RM200_PCI) - EISA_bus = 1; - /* Some firmware leaves the BEV flag set, clear it. */ clear_cp0_status(ST0_BEV); @@ -852,8 +803,8 @@ /* * Setup default vectors */ - for(i = 0; i <= 31; i++) - (void)set_except_vector(i, handle_reserved); + for (i = 0; i <= 31; i++) + set_except_vector(i, handle_reserved); /* * Copy the EJTAG debug exception vector handler code to it's final @@ -866,7 +817,15 @@ * interrupt vector. */ watch_init(); - setup_dedicated_int(); + + /* + * Some MIPS CPUs have a dedicated interrupt vector which reduces the + * interrupt processing overhead. Use it where available. + */ + if (mips_cpu.options & MIPS_CPU_DIVEC) { + memcpy((void *)(KSEG0 + 0x200), &except_vec4, 8); + set_cp0_cause(CAUSEF_IV); + } /* * Some CPUs can enable/disable for cache parity detection, but does @@ -874,35 +833,38 @@ */ parity_protection_init(); - (void)set_except_vector(1, handle_mod); - (void)set_except_vector(2, handle_tlbl); - (void)set_except_vector(3, handle_tlbs); - (void)set_except_vector(4, handle_adel); - (void)set_except_vector(5, handle_ades); + set_except_vector(1, handle_mod); + set_except_vector(2, handle_tlbl); + set_except_vector(3, handle_tlbs); + set_except_vector(4, handle_adel); + set_except_vector(5, handle_ades); + /* * The Data Bus Error/ Instruction Bus Errors are signaled * by external hardware. Therefore these two expection have * board specific handlers. */ - (void)set_except_vector(6, handle_ibe); - (void)set_except_vector(7, handle_dbe); + set_except_vector(6, handle_ibe); + set_except_vector(7, handle_dbe); ibe_board_handler = default_be_board_handler; dbe_board_handler = default_be_board_handler; - (void)set_except_vector(8, handle_sys); - (void)set_except_vector(9, handle_bp); - (void)set_except_vector(10, handle_ri); - (void)set_except_vector(11, handle_cpu); - (void)set_except_vector(12, handle_ov); - (void)set_except_vector(13, handle_tr); - (void)set_except_vector(15, handle_fpe); - + set_except_vector(8, handle_sys); + set_except_vector(9, handle_bp); + set_except_vector(10, handle_ri); + set_except_vector(11, handle_cpu); + set_except_vector(12, handle_ov); + set_except_vector(13, handle_tr); + + if (mips_cpu.options & MIPS_CPU_FPU) + set_except_vector(15, handle_fpe); + /* * Handling the following exceptions depends mostly of the cpu type */ if ((mips_cpu.options & MIPS_CPU_4KEX) && (mips_cpu.options & MIPS_CPU_4KTLB)) { - if(mips_cpu.cputype == CPU_NEVADA) { + if (mips_cpu.cputype == CPU_NEVADA) { memcpy((void *)KSEG0, &except_vec0_nevada, 0x80); } else if (mips_cpu.cputype == CPU_R4600) memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); @@ -919,36 +881,25 @@ 0x80); } - if(mips_cpu.options & MIPS_CPU_FPU) { + if (mips_cpu.options & MIPS_CPU_FPU) { save_fp_context = _save_fp_context; restore_fp_context = _restore_fp_context; -#ifdef CONFIG_MIPS_FPU_EMULATOR } else { save_fp_context = fpu_emulator_save_context; restore_fp_context = fpu_emulator_restore_context; -#endif } - } else switch(mips_cpu.cputype) { - case CPU_R10000: - /* - * The R10000 is in most aspects similar to the R4400. It - * should get some special optimizations. - */ - write_32bit_cp0_register(CP0_FRAMEMASK, 0); - set_cp0_status(ST0_XX); + } else switch (mips_cpu.cputype) { + case CPU_SB1: /* - * The R10k might even work for Linux/MIPS - but we're paranoid - * and refuse to run until this is tested on real silicon + * XXX - This should be folded in to the "cleaner" handling, + * above */ - panic("CPU too expensive - making holiday in the ANDES!"); - break; - case CPU_SB1: - /* XXX - This should be folded in to the "cleaner" handling, above */ memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); save_fp_context = _save_fp_context; restore_fp_context = _restore_fp_context; - /* Enable timer interrupt and scd mapped interrupt in status register */ + + /* Enable timer interrupt and scd mapped interrupt */ clear_cp0_status(0xf000); set_cp0_status(0xc00); break; @@ -983,17 +934,15 @@ memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); break; - case CPU_R8000: - printk("Detected unsupported CPU type %s.\n", - cpu_names[mips_cpu.cputype]); - panic("Can't handle CPU"); - break; case CPU_UNKNOWN: default: panic("Unknown CPU type"); } flush_icache_range(KSEG0, KSEG0 + 0x200); + + if (mips_cpu.isa_level == MIPS_CPU_ISA_IV) + set_cp0_status(ST0_XX); atomic_inc(&init_mm.mm_count); /* XXX UP? */ current->active_mm = &init_mm; diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c --- v2.4.9/linux/arch/mips/kernel/unaligned.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/kernel/unaligned.c Sun Sep 9 10:43:01 2001 @@ -72,6 +72,7 @@ * A store crossing a page boundary might be executed only partially. * Undo the partial store in this case. */ +#include #include #include #include @@ -378,26 +379,26 @@ return; } +#ifdef CONFIG_PROC_FS unsigned long unaligned_instructions; +#endif asmlinkage void do_ade(struct pt_regs *regs) { unsigned long pc; -#ifdef CONFIG_MIPS_FPU_EMULATOR - extern int do_dsemulret(struct pt_regs *); + extern int do_dsemulret(struct pt_regs *); + + /* + * Address errors may be deliberately induced + * by the FPU emulator to take retake control + * of the CPU after executing the instruction + * in the delay slot of an emulated branch. + */ - /* - * Address errors may be deliberately induced - * by the FPU emulator to take retake control - * of the CPU after executing the instruction - * in the delay slot of an emulated branch. - */ - - if((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) { - (void)do_dsemulret(regs); - return; - } -#endif /* CONFIG_MIPS_FPU_EMULATOR */ + if ((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) { + do_dsemulret(regs); + return; + } /* * Did we catch a fault trying to load an instruction? @@ -414,7 +415,9 @@ goto sigbus; emulate_load_store_insn(regs, regs->cp0_badvaddr, pc); +#ifdef CONFIG_PROC_FS unaligned_instructions++; +#endif return; diff -u --recursive --new-file v2.4.9/linux/arch/mips/lib/ide-std.c linux/arch/mips/lib/ide-std.c --- v2.4.9/linux/arch/mips/lib/ide-std.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/lib/ide-std.c Sun Sep 9 10:43:01 2001 @@ -1,12 +1,11 @@ -/* $Id: ide-std.c,v 1.4 1999/06/11 14:29:45 ralf Exp $ - * +/* * 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. * * IDE routines for typical pc-like standard configurations. * - * Copyright (C) 1998, 1999 by Ralf Baechle + * Copyright (C) 1998, 1999, 2001 by Ralf Baechle */ #include #include @@ -60,6 +59,7 @@ } if (irq != NULL) *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; } static int std_ide_request_irq(unsigned int irq, diff -u --recursive --new-file v2.4.9/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S --- v2.4.9/linux/arch/mips/lib/memcpy.S Tue Dec 5 23:15:12 2000 +++ linux/arch/mips/lib/memcpy.S Sun Sep 9 10:43:01 2001 @@ -402,16 +402,20 @@ .align 5 LEAF(memmove) - sltu t0, a0, a1 # dst < src -> memcpy - bnez t0, memcpy - addu v0, a0, a2 - sltu t0, v0, a1 # dst + len < src -> non- - bnez t0, __memcpy # overlapping, can use memcpy + addu t0, a0, a2 + sltu t0, a1, t0 # dst + len <= src -> memcpy + addu t1, a1, a2 + sltu t1, a0, t1 # dst >= src + len -> memcpy + and t0, t1 + beqz t0, __memcpy move v0, a0 /* return value */ beqz a2, r_out END(memmove) LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ + sltu t0, a1, a0 + beqz t0, r_end_bytes_up # src >= dst + nop addu a0, a2 # dst = dst + len addu a1, a2 # src = src + len @@ -563,6 +567,17 @@ subu a0, a0, 0x1 r_out: + jr ra + move a2, zero + +r_end_bytes_up: + lb t0, (a1) + subu a2, a2, 0x1 + sb t0, (a0) + addu a1, a1, 0x1 + bnez a2, r_end_bytes_up + addu a0, a0, 0x1 + jr ra move a2, zero diff -u --recursive --new-file v2.4.9/linux/arch/mips/math-emu/cp1emu.c linux/arch/mips/math-emu/cp1emu.c --- v2.4.9/linux/arch/mips/math-emu/cp1emu.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/math-emu/cp1emu.c Sun Sep 9 10:43:01 2001 @@ -5,7 +5,8 @@ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. * http://www.algor.co.uk * - * ######################################################################## + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as @@ -20,8 +21,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * A complete emulator for MIPS coprocessor 1 instructions. This is * required for #float(switch) or #float(trap), where it catches all * COP1 instructions via the "CoProcessor Unusable" exception. @@ -32,24 +31,9 @@ * quite nasty because emulation of some non-COP1 instructions is * required, e.g. in branch delay slots. * - * Notes: - * 1) the IEEE754 library (-le) performs the actual arithmetic; - * 2) if you know that you won't have an fpu, then you'll get much - * better performance by compiling with -msoft-float! */ - -/************************************************************************** - * Nov 7, 2000 - * Massive changes to integrate with Linux kernel. - * - * Replace use of kernel data area with use of user stack - * for execution of instructions in branch delay slots. - * - * Replace use of static kernel variables with thread_struct elements. - * - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ -#include + * Note if you know that you won't have an fpu, then you'll get much + * better performance by compiling with -msoft-float! + */ #include #include #include @@ -57,7 +41,9 @@ #include #include +#include #include +#include #include #include #include @@ -181,19 +167,17 @@ #define REG_TO_VA (vaddr_t) #define VA_TO_REG (unsigned long) -static unsigned long -mips_get_word(struct pt_regs *xcp, void *va, int *perr) +static unsigned long mips_get_word(struct pt_regs *xcp, void *va, int *perr) { unsigned long temp; if (!user_mode(xcp)) { *perr = 0; return (*(unsigned long *) va); - } else { - /* Use kernel get_user() macro */ - *perr = (int) get_user(temp, (unsigned long *) va); - return temp; } + + *perr = (int) get_user(temp, (unsigned long *) va); + return temp; } static unsigned long long @@ -204,11 +188,10 @@ if (!user_mode(xcp)) { *perr = 0; return (*(unsigned long long *) va); - } else { - /* Use kernel get_user() macro */ - *perr = (int) get_user(temp, (unsigned long long *) va); - return temp; } + + *perr = (int) get_user(temp, (unsigned long long *) va); + return temp; } static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val) @@ -216,10 +199,9 @@ if (!user_mode(xcp)) { *(unsigned long *) va = val; return 0; - } else { - /* Use kernel get_user() macro */ - return (int) put_user(val, (unsigned long *) va); } + + return put_user(val, (unsigned long *) va); } static int mips_put_dword(struct pt_regs *xcp, void *va, long long val) @@ -227,10 +209,9 @@ if (!user_mode(xcp)) { *(unsigned long long *) va = val; return 0; - } else { - /* Use kernel get_user() macro */ - return (int) put_user(val, (unsigned long long *) va); } + + return put_user(val, (unsigned long long *) va); } @@ -249,9 +230,7 @@ * Two instructions if the instruction is in a branch delay slot. */ -static int -cop1Emulate(int xcptno, struct pt_regs *xcp, - struct mips_fpu_soft_struct *ctx) +static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx) { mips_instruction ir; vaddr_t emulpc; @@ -259,7 +238,6 @@ unsigned int cond; int err = 0; - ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err); if (err) { fpuemuprivate.stats.errors++; @@ -303,7 +281,7 @@ contpc = REG_TO_VA xcp->cp0_epc + 4; } - emul: +emul: fpuemuprivate.stats.emulated++; switch (MIPSInst_OPCODE(ir)) { #ifdef CP0_STATUS_FR_SUPPORT @@ -491,9 +469,8 @@ } break; - case dmtc_op: + case dmtc_op: { /* copregister fs <- rt */ - { fpureg_t value; int fs = MIPSInst_RD(ir); if (!(xcp->cp0_status & ST0_FR)) @@ -502,8 +479,8 @@ (MIPSInst_RT(ir) == 0) ? 0 : xcp->regs[MIPSInst_RT(ir)]; ctx->regs[fs] = value; - } break; + } #endif case mfc_op: @@ -638,95 +615,92 @@ } break; - case bc_op: - if (xcp->cp0_cause & CAUSEF_BD) { + case bc_op: { + int likely = 0; + + if (xcp->cp0_cause & CAUSEF_BD) return SIGILL; - } - { - int likely = 0; #if __mips >= 4 - cond = - ctx-> - sr & fpucondbit[MIPSInst_RT(ir) >> 2]; + cond = ctx-> sr & fpucondbit[MIPSInst_RT(ir) >> 2]; #else - cond = ctx->sr & FPU_CSR_COND; + cond = ctx->sr & FPU_CSR_COND; #endif - switch (MIPSInst_RT(ir) & 3) { - case bcfl_op: - likely = 1; - case bcf_op: - cond = !cond; - break; - case bctl_op: - likely = 1; - case bct_op: - break; - default: - /* thats an illegal instruction */ - return SIGILL; - } + switch (MIPSInst_RT(ir) & 3) { + case bcfl_op: + likely = 1; + case bcf_op: + cond = !cond; + break; + case bctl_op: + likely = 1; + case bct_op: + break; + default: + /* thats an illegal instruction */ + return SIGILL; + } - xcp->cp0_cause |= CAUSEF_BD; - if (cond) { - /* branch taken: emulate dslot instruction */ - xcp->cp0_epc += 4; - contpc = - REG_TO_VA xcp->cp0_epc + - (MIPSInst_SIMM(ir) << 2); - - ir = - mips_get_word(xcp, - REG_TO_VA(xcp-> - cp0_epc), - &err); - if (err) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } + xcp->cp0_cause |= CAUSEF_BD; + if (cond) { + /* branch taken: emulate dslot instruction */ + xcp->cp0_epc += 4; + contpc = REG_TO_VA xcp->cp0_epc + + (MIPSInst_SIMM(ir) << 2); + + ir = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), + &err); + if (err) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } - switch (MIPSInst_OPCODE(ir)) { - case lwc1_op: - case swc1_op: + switch (MIPSInst_OPCODE(ir)) { + case lwc1_op: + case swc1_op: #if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU) - case ldc1_op: - case sdc1_op: + case ldc1_op: + case sdc1_op: #endif - case cop1_op: + case cop1_op: #if __mips >= 4 && __mips != 32 - case cop1x_op: + case cop1x_op: #endif - /* its one of ours */ - goto emul; + /* its one of ours */ + goto emul; #if __mips >= 4 - case spec_op: - if (MIPSInst_FUNC(ir) == - movc_op) goto emul; - break; + case spec_op: + if (MIPSInst_FUNC(ir) == movc_op) + goto emul; + break; #endif - } + } - /* single step the non-cp1 instruction in the dslot */ - return mips_dsemul(xcp, ir, - contpc); - } else { - /* branch not taken */ - if (likely) - /* branch likely nullifies dslot if not taken */ - xcp->cp0_epc += 4; + /* + * Single step the non-cp1 instruction in the + * dslot + */ + return mips_dsemul(xcp, ir, contpc); + } else { + /* branch not taken */ + if (likely) + /* + * branch likely nullifies dslot if not + * taken + */ + xcp->cp0_epc += 4; /* else continue & execute dslot as normal insn */ - } } break; + } - default: - if (!(MIPSInst_RS(ir) & 0x10)) { + default: { + int sig; + + if (!(MIPSInst_RS(ir) & 0x10)) return SIGILL; - } + /* a real fpu computation instruction */ - { - int sig; if ((sig = fpu_emu(xcp, ctx, ir))) return sig; } @@ -822,14 +796,15 @@ */ dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3); dsemul_insns -= 3; /* Two instructions, plus one for luck ;-) */ + /* Verify that the stack pointer is not competely insane */ - if (verify_area - (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2)) + if (verify_area(VERIFY_WRITE, dsemul_insns, + sizeof(mips_instruction) * 2)) return SIGBUS; if (mips_put_word(xcp, &dsemul_insns[0], ir)) { fpuemuprivate.stats.errors++; - return (SIGBUS); + return SIGBUS; } /* @@ -856,11 +831,8 @@ current->thread.dsemul_epc = (unsigned long) cpc; current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1]; xcp->cp0_epc = VA_TO_REG & dsemul_insns[0]; + flush_cache_sigtramp((unsigned long) dsemul_insns); - /* What we'd really like to do is just flush the line(s) of the */ - /* icache containing the dsemulret instructions, but there's no */ - /* mechanism to do this yet... */ - flush_cache_all(); return SIGILL; /* force out of emulation loop */ } @@ -971,9 +943,8 @@ return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r)); } -static int -fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, - mips_instruction ir) +static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, + mips_instruction ir) { unsigned rcsr = 0; /* resulting csr */ @@ -1226,9 +1197,8 @@ /* * Emulate a single COP1 arithmetic instruction. */ -static int -fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, - mips_instruction ir) +static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, + mips_instruction ir) { int rfmt; /* resulting format */ unsigned rcsr = 0; /* resulting csr */ @@ -1244,8 +1214,7 @@ fpuemuprivate.stats.cp1ops++; switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { - - case s_fmt:{ /* 0 */ + case s_fmt: { /* 0 */ ieee754sp(*handler) (); switch (MIPSInst_FUNC(ir)) { @@ -1342,73 +1311,68 @@ /* unary conv ops */ case fcvts_op: return SIGILL; /* not defined */ - case fcvtd_op: -#if defined(SINGLE_ONLY_FPU) + case fcvtd_op: { +#ifdef SINGLE_ONLY_FPU return SIGILL; /* not defined */ #else - { - ieee754sp fs; + ieee754sp fs; - SPFROMREG(fs, MIPSInst_FS(ir)); - rv.d = ieee754dp_fsp(fs); - rfmt = d_fmt; - goto copcsr; - } + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.d = ieee754dp_fsp(fs); + rfmt = d_fmt; + goto copcsr; + } #endif - case fcvtw_op: - { - ieee754sp fs; + case fcvtw_op: { + ieee754sp fs; - SPFROMREG(fs, MIPSInst_FS(ir)); - rv.w = ieee754sp_tint(fs); - rfmt = w_fmt; - goto copcsr; - } + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.w = ieee754sp_tint(fs); + rfmt = w_fmt; + goto copcsr; + } #if __mips >= 2 || __mips64 case fround_op: case ftrunc_op: case fceil_op: - case ffloor_op: - { - unsigned int oldrm = ieee754_csr.rm; - ieee754sp fs; - - SPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; - rv.w = ieee754sp_tint(fs); - ieee754_csr.rm = oldrm; - rfmt = w_fmt; - goto copcsr; - } -#endif /* __mips >= 2 */ + case ffloor_op: { + unsigned int oldrm = ieee754_csr.rm; + ieee754sp fs; + + SPFROMREG(fs, MIPSInst_FS(ir)); + ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; + rv.w = ieee754sp_tint(fs); + ieee754_csr.rm = oldrm; + rfmt = w_fmt; + goto copcsr; + } +#endif /* __mips >= 2 */ #if __mips64 && !defined(SINGLE_ONLY_FPU) - case fcvtl_op: - { - ieee754sp fs; + case fcvtl_op: { + ieee754sp fs; - SPFROMREG(fs, MIPSInst_FS(ir)); - rv.l = ieee754sp_tlong(fs); - rfmt = l_fmt; - goto copcsr; - } + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.l = ieee754sp_tlong(fs); + rfmt = l_fmt; + goto copcsr; + } case froundl_op: case ftruncl_op: case fceill_op: - case ffloorl_op: - { - unsigned int oldrm = ieee754_csr.rm; - ieee754sp fs; - - SPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; - rv.l = ieee754sp_tlong(fs); - ieee754_csr.rm = oldrm; - rfmt = l_fmt; - goto copcsr; - } + case ffloorl_op: { + unsigned int oldrm = ieee754_csr.rm; + ieee754sp fs; + + SPFROMREG(fs, MIPSInst_FS(ir)); + ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; + rv.l = ieee754sp_tlong(fs); + ieee754_csr.rm = oldrm; + rfmt = l_fmt; + goto copcsr; + } #endif /* __mips64 && !fpu(single) */ default: @@ -1484,9 +1448,11 @@ case fabs_op: handler = ieee754dp_abs; goto dcopuop; + case fneg_op: handler = ieee754dp_neg; goto dcopuop; + case fmov_op: /* an easy one */ DPFROMREG(rv.d, MIPSInst_FS(ir)); @@ -1513,71 +1479,67 @@ } /* unary conv ops */ - case fcvts_op: - { - ieee754dp fs; + case fcvts_op: { + ieee754dp fs; - DPFROMREG(fs, MIPSInst_FS(ir)); - rv.s = ieee754sp_fdp(fs); - rfmt = s_fmt; - goto copcsr; - } + DPFROMREG(fs, MIPSInst_FS(ir)); + rv.s = ieee754sp_fdp(fs); + rfmt = s_fmt; + goto copcsr; + } case fcvtd_op: return SIGILL; /* not defined */ - case fcvtw_op: - { - ieee754dp fs; - DPFROMREG(fs, MIPSInst_FS(ir)); - rv.w = ieee754dp_tint(fs); /* wrong */ - rfmt = w_fmt; - goto copcsr; - } + case fcvtw_op: { + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + rv.w = ieee754dp_tint(fs); /* wrong */ + rfmt = w_fmt; + goto copcsr; + } #if __mips >= 2 || __mips64 case fround_op: case ftrunc_op: case fceil_op: - case ffloor_op: - { - unsigned int oldrm = ieee754_csr.rm; - ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; - rv.w = ieee754dp_tint(fs); - ieee754_csr.rm = oldrm; - rfmt = w_fmt; - goto copcsr; - } + case ffloor_op: { + unsigned int oldrm = ieee754_csr.rm; + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; + rv.w = ieee754dp_tint(fs); + ieee754_csr.rm = oldrm; + rfmt = w_fmt; + goto copcsr; + } #endif #if __mips64 && !defined(SINGLE_ONLY_FPU) - case fcvtl_op: - { - ieee754dp fs; + case fcvtl_op: { + ieee754dp fs; - DPFROMREG(fs, MIPSInst_FS(ir)); - rv.l = ieee754dp_tlong(fs); - rfmt = l_fmt; - goto copcsr; - } + DPFROMREG(fs, MIPSInst_FS(ir)); + rv.l = ieee754dp_tlong(fs); + rfmt = l_fmt; + goto copcsr; + } case froundl_op: case ftruncl_op: case fceill_op: - case ffloorl_op: - { - unsigned int oldrm = ieee754_csr.rm; - ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; - rv.l = ieee754dp_tlong(fs); - ieee754_csr.rm = oldrm; - rfmt = l_fmt; - goto copcsr; - } + case ffloorl_op: { + unsigned int oldrm = ieee754_csr.rm; + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; + rv.l = ieee754dp_tlong(fs); + ieee754_csr.rm = oldrm; + rfmt = l_fmt; + goto copcsr; + } #endif /* __mips >= 3 && !fpu(single) */ default: @@ -1598,7 +1560,7 @@ } break; } -#endif /* !defined(SINGLE_ONLY_FPU) */ +#endif /* !defined(SINGLE_ONLY_FPU) */ case w_fmt: { switch (MIPSInst_FUNC(ir)) { @@ -1698,12 +1660,11 @@ /* - * Emulate the floating point instruction at EPC, and continue - * to run until we hit a non-fp instruction, or a backward - * branch. This cuts down dramatically on the per instruction - * exception overhead. + * Emulate the floating point instruction at EPC, and continue to run until we + * hit a non-fp instruction, or a backward branch. This cuts down dramatically + * on the per instruction exception overhead. */ -int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp) +int fpu_emulator_cop1Handler(struct pt_regs *xcp) { struct mips_fpu_soft_struct *ctx = ¤t->thread.fpu.soft; unsigned long oldepc, prevepc; @@ -1713,6 +1674,9 @@ oldepc = xcp->cp0_epc; do { + if (current->need_resched) + schedule(); + prevepc = xcp->cp0_epc; insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err); if (err) { @@ -1720,9 +1684,12 @@ return SIGBUS; } if (insn != 0) - sig = cop1Emulate(xcptno, xcp, ctx); + sig = cop1Emulate(xcp, ctx); else xcp->cp0_epc += 4; /* skip nops */ + + if (mips_cpu.options & MIPS_CPU_FPU) + break; } while (xcp->cp0_epc > prevepc && sig == 0); /* SIGILL indicates a non-fpu instruction */ @@ -1753,7 +1720,7 @@ /* get current rounding mode for IEEE library, and emulate insn */ ieee754_csr.rm = ieee_rm[ctx->sr & 0x3]; - sig = cop1Emulate(xcptno, xcp, ctx); + sig = cop1Emulate(xcp, ctx); /* don't return with f.p. exceptions pending */ ctx->sr &= ~FPU_CSR_ALL_X; @@ -1809,4 +1776,3 @@ } } #endif - diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/atlas/atlas_int.c linux/arch/mips/mips-boards/atlas/atlas_int.c --- v2.4.9/linux/arch/mips/mips-boards/atlas/atlas_int.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/atlas/atlas_int.c Sun Sep 9 10:43:02 2001 @@ -51,6 +51,11 @@ #define DEBUG_INT(x...) #endif +void inline disable_irq_nosync(unsigned int irq_nr) +{ + disable_atlas_irq(irq_nr); +} + void disable_atlas_irq(unsigned int irq_nr) { atlas_hw0_icregs->intrsten = (1 << irq_nr); diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/atlas/atlas_rtc.c linux/arch/mips/mips-boards/atlas/atlas_rtc.c --- v2.4.9/linux/arch/mips/mips-boards/atlas/atlas_rtc.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/atlas/atlas_rtc.c Sun Sep 9 10:43:02 2001 @@ -22,7 +22,6 @@ * RTC routines for Atlas style attached Dallas chip. * */ -#include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/atlas/atlas_setup.c linux/arch/mips/mips-boards/atlas/atlas_setup.c --- v2.4.9/linux/arch/mips/mips-boards/atlas/atlas_setup.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/atlas/atlas_setup.c Sun Sep 9 10:43:02 2001 @@ -54,8 +54,8 @@ char rs_getDebugChar(void); int saa9730_putDebugChar(char); char saa9730_getDebugChar(void); - extern int (*putDebugChar)(char); - extern char (*getDebugChar)(void); + extern int (*generic_putDebugChar)(char); + extern char (*generic_getDebugChar)(void); #endif char *argptr; @@ -89,12 +89,12 @@ if(line == 0) { rs_kgdb_hook(line); - putDebugChar = rs_putDebugChar; - getDebugChar = rs_getDebugChar; + generic_putDebugChar = rs_putDebugChar; + generic_getDebugChar = rs_getDebugChar; } else { saa9730_kgdb_hook(); - putDebugChar = saa9730_putDebugChar; - getDebugChar = saa9730_getDebugChar; + generic_putDebugChar = saa9730_putDebugChar; + generic_getDebugChar = saa9730_getDebugChar; } prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/generic/cmdline.c linux/arch/mips/mips-boards/generic/cmdline.c --- v2.4.9/linux/arch/mips/mips-boards/generic/cmdline.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/generic/cmdline.c Sun Sep 9 10:43:02 2001 @@ -17,6 +17,7 @@ * * Kernel command line creation using the prom monitor (YAMON) argc/argv. */ +#include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/generic/gdb_hook.c linux/arch/mips/mips-boards/generic/gdb_hook.c --- v2.4.9/linux/arch/mips/mips-boards/generic/gdb_hook.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/generic/gdb_hook.c Sun Sep 9 10:43:02 2001 @@ -23,7 +23,6 @@ * */ -#include #include #include @@ -36,8 +35,8 @@ static struct async_struct kdb_port_info = {0}; -int (*putDebugChar)(char); -char (*getDebugChar)(void); +int (*generic_putDebugChar)(char); +char (*generic_getDebugChar)(void); static __inline__ unsigned int serial_in(struct async_struct *info, int offset) { @@ -96,6 +95,16 @@ serial_out(&kdb_port_info, UART_DLM, t >> 8); /* MS of divisor */ /* reset DLAB */ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); +} + +int putDebugChar(char c) +{ + return generic_putDebugChar(c); +} + +char getDebugChar(void) +{ + return generic_getDebugChar(); } int rs_putDebugChar(char c) diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/generic/memory.c linux/arch/mips/mips-boards/generic/memory.c --- v2.4.9/linux/arch/mips/mips-boards/generic/memory.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/generic/memory.c Sun Sep 9 10:43:02 2001 @@ -50,6 +50,11 @@ }; #endif +/* References to section boundaries */ +extern char _end; + +#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) + struct prom_pmemblock * __init prom_getmdesc(void) { @@ -94,9 +99,13 @@ mdesc[2].size = 0x00010000; #endif - mdesc[3].type = yamon_free; + mdesc[3].type = yamon_dontuse; mdesc[3].base = 0x00100000; - mdesc[3].size = memsize - mdesc[3].base; + mdesc[3].size = PHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base; + + mdesc[4].type = yamon_free; + mdesc[4].base = PHYSADDR(PFN_ALIGN(&_end)); + mdesc[4].size = memsize - mdesc[4].base; return &mdesc[0]; } @@ -118,11 +127,10 @@ struct prom_pmemblock *p; #ifdef DEBUG - int i = 0; - prom_printf("YAMON MEMORY DESCRIPTOR dump:\n"); p = prom_getmdesc(); while (p->size) { + int i = 0; prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n", i, p, p->base, p->size, mtypes[p->type]); p++; @@ -130,24 +138,24 @@ } #endif p = prom_getmdesc(); + while (p->size) { - unsigned long base, size; long type; + unsigned long base, size; type = prom_memtype_classify (p->type); base = p->base; size = p->size; add_memory_region(base, size, type); - - p++; + p++; } } -void prom_free_prom_memory (void) +void __init +prom_free_prom_memory (void) { int i; - struct prom_pmemblock *p; unsigned long freed = 0; unsigned long addr; @@ -158,9 +166,9 @@ addr = boot_mem_map.map[i].addr; while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { - ClearPageReserved(virt_to_page(phys_to_virt(addr))); - set_page_count(virt_to_page(phys_to_virt(addr)), 1); - free_page(phys_to_virt(addr)); + ClearPageReserved(virt_to_page(__va(addr))); + set_page_count(virt_to_page(__va(addr)), 1); + free_page(__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; } diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/generic/pci.c linux/arch/mips/mips-boards/generic/pci.c --- v2.4.9/linux/arch/mips/mips-boards/generic/pci.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/generic/pci.c Sun Sep 9 10:43:02 2001 @@ -325,4 +325,9 @@ pci_read_bridge_bases(b); } +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} + #endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/generic/time.c linux/arch/mips/mips-boards/generic/time.c --- v2.4.9/linux/arch/mips/mips-boards/generic/time.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/generic/time.c Sun Sep 9 10:43:02 2001 @@ -275,7 +275,7 @@ /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) +#define USECS_PER_JIFFY_FRAC ((1000000 << 32) / HZ & 0xffffffff) /* Cycle counter value at the previous timer interrupt.. */ diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/malta/malta_int.c linux/arch/mips/mips-boards/malta/malta_int.c --- v2.4.9/linux/arch/mips/mips-boards/malta/malta_int.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/malta/malta_int.c Sun Sep 9 10:43:02 2001 @@ -1,6 +1,7 @@ /* * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2000, 2001 MIPS Technologies, Inc. + * Copyright (C) 2001 Ralf Baechle * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as @@ -20,6 +21,7 @@ * The interrupt controller is located in the South Bridge a PIIX4 device * with two internal 82C95 interrupt controllers. */ +#include #include #include #include @@ -37,342 +39,42 @@ extern asmlinkage void mipsIRQ(void); -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; -unsigned long spurious_count = 0; - -static struct irqaction *hw0_irq_action[MALTAINT_END] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL -}; - -static struct irqaction r4ktimer_action = { - NULL, 0, 0, "R4000 timer/counter", NULL, NULL, -}; - -static struct irqaction *irq_action[8] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, &r4ktimer_action -}; - -#if 0 -#define DEBUG_INT(x...) printk(x) -#else -#define DEBUG_INT(x...) -#endif - -/* - * This contains the interrupt mask for both 82C59 interrupt controllers. - */ -static unsigned int cached_int_mask = 0xffff; - - -void disable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - if(irq_nr >= MALTAINT_END) { - printk("whee, invalid irq_nr %d\n", irq_nr); - panic("IRQ, you lose..."); - } - - save_and_cli(flags); - cached_int_mask |= (1 << irq_nr); - if (irq_nr & 8) { - outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); - } else { - outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); - } - restore_flags(flags); -} - - -void enable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - if(irq_nr >= MALTAINT_END) { - printk("whee, invalid irq_nr %d\n", irq_nr); - panic("IRQ, you lose..."); - } - - save_and_cli(flags); - cached_int_mask &= ~(1 << irq_nr); - if (irq_nr & 8) { - outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); - - /* Enable irq 2 (cascade interrupt). */ - cached_int_mask &= ~(1 << 2); - outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); - } else { - outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); - } - restore_flags(flags); -} - - -int get_irq_list(char *buf) -{ - int i, len = 0; - int num = 0; - struct irqaction *action; - - for (i = 0; i < 8; i++, num++) { - action = irq_action[i]; - if (!action) - continue; - len += sprintf(buf+len, "%2d: %8d %c %s", - num, kstat.irqs[0][num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - len += sprintf(buf+len, " [on-chip]\n"); - } - for (i = 0; i < MALTAINT_END; i++, num++) { - action = hw0_irq_action[i]; - if (!action) - continue; - len += sprintf(buf+len, "%2d: %8d %c %s", - num, kstat.irqs[0][num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - len += sprintf(buf+len, " [hw0]\n"); - } - return len; -} - - -static int setup_irq(unsigned int irq, struct irqaction * new) -{ - int shared = 0; - struct irqaction *old, **p; - - p = &hw0_irq_action[irq]; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) - return -EBUSY; - - /* Can't share interrupts unless both are same type */ - if ((old->flags ^ new->flags) & SA_INTERRUPT) - return -EBUSY; - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - if (new->flags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - - *p = new; - if (!shared) - enable_irq(irq); - - return 0; -} - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - struct irqaction *action; - int retval; - - DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname); - - if (irq >= MALTAINT_END) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if(!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->dev_id = dev_id; - action->next = 0; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - - return retval; -} - - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction *action, **p; - - if (irq >= MALTAINT_END) { - printk("Trying to free IRQ%d\n",irq); - return; - } - - for (p = &hw0_irq_action[irq]; (action = *p) != NULL; - p = &action->next) - { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - *p = action->next; - kfree(action); - if (!hw0_irq_action[irq]) - disable_irq(irq); - return; - } - printk("Trying to free IRQ%d\n",irq); -} - -void __init init_IRQ(void) +void malta_hw0_irqdispatch(struct pt_regs *regs) { - irq_setup(); -} + int irq; -static inline int get_int(int *irq) -{ /* - * Determine highest priority pending interrupt by performing - * a PCI Interrupt Acknowledge cycle. + * Determine highest priority pending interrupt by performing a PCI + * Interrupt Acknowledge cycle. */ - GT_READ(GT_PCI0_IACK_OFS, *irq); - *irq &= 0xFF; + GT_READ(GT_PCI0_IACK_OFS, irq); + irq &= 0xFF; /* - * IRQ7 is used to detect spurious interrupts. - * The interrupt acknowledge cycle returns IRQ7, if no - * interrupts is requested. - * We can differentiate between this situation and a - * "Normal" IRQ7 by reading the ISR. + * IRQ7 is used to detect spurious interrupts. The interrupt + * acknowledge cycle returns IRQ7, if no interrupts is requested. We + * can differentiate between this situation and a "normal" IRQ7 by + * reading the ISR. */ - if (*irq == 7) - { + if (irq == 7) { outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, PIIX4_ICTLR1_OCW3); if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) - return -1; /* Spurious interrupt. */ - } - - return 0; -} - -static inline void ack_int(int irq) -{ - if (irq & 8) { - /* Specific EOI to cascade */ - outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI | PIIX4_OCW2_ILS_2, - PIIX4_ICTLR1_OCW2); - - /* Non specific EOI to cascade */ - outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR2_OCW2); - } else { - /* Non specific EOI to cascade */ - outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR1_OCW2); + return; /* Spurious interrupt. */ } -} - -void malta_hw0_irqdispatch(struct pt_regs *regs) -{ - struct irqaction *action; - int irq=0, cpu = smp_processor_id(); - - DEBUG_INT("malta_hw0_irqdispatch\n"); - - if (get_int(&irq)) - return; /* interrupt has already been cleared */ - disable_irq(irq); - ack_int(irq); - - DEBUG_INT("malta_hw0_irqdispatch: irq=%d\n", irq); - action = hw0_irq_action[irq]; - - /* - * if action == NULL, then we don't have a handler - * for the irq - */ - if ( action == NULL ) - return; - - irq_enter(cpu, irq); - kstat.irqs[0][irq + 8]++; - do { - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - - enable_irq(irq); - irq_exit(cpu, irq); + do_IRQ(irq, regs); } - -unsigned long probe_irq_on (void) +void __init init_IRQ(void) { - unsigned int i, irqs = 0; - unsigned long delay; + set_except_vector(0, mipsIRQ); + init_generic_irq(); + init_i8259_irqs(); - /* first, enable any unassigned irqs */ - for (i = MALTAINT_END-1; i > 0; i--) { - if (!hw0_irq_action[i]) { - enable_irq(i); - irqs |= (1 << i); - } +#ifdef CONFIG_REMOTE_DEBUG + if (remote_debug) { + set_debug_traps(); + breakpoint(); } - - /* wait for spurious interrupts to mask themselves out again */ - for (delay = jiffies + HZ/10; time_before(jiffies, delay); ) - /* about 100ms delay */; - - /* now filter out any obviously spurious interrupts */ - return irqs & ~cached_int_mask; -} - - -int probe_irq_off (unsigned long irqs) -{ - unsigned int i; - - irqs &= cached_int_mask; - if (!irqs) - return 0; - i = ffz(~irqs); - if (irqs != (irqs & (1 << i))) - i = -i; - - return i; -} - - -void __init maltaint_init(void) -{ - /* - * Mask out all interrupt by writing "1" to all bit position in - * the IMR register. - */ - outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); - outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); - - /* Now safe to set the exception vector. */ - set_except_vector(0, mipsIRQ); +#endif } diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/malta/malta_rtc.c linux/arch/mips/mips-boards/malta/malta_rtc.c --- v2.4.9/linux/arch/mips/mips-boards/malta/malta_rtc.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/malta/malta_rtc.c Sun Sep 9 10:43:02 2001 @@ -23,7 +23,6 @@ * Motorola MC146818A-compatible Real Time Clock. * */ -#include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/mips-boards/malta/malta_setup.c linux/arch/mips/mips-boards/malta/malta_setup.c --- v2.4.9/linux/arch/mips/mips-boards/malta/malta_setup.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mips-boards/malta/malta_setup.c Sun Sep 9 10:43:02 2001 @@ -2,8 +2,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -16,11 +14,6 @@ * 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., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Malta specific setup, including init of the feature struct. - * */ #include #include @@ -56,53 +49,33 @@ static int remote_debug = 0; #endif -#ifdef CONFIG_BLK_DEV_IDE extern struct ide_ops std_ide_ops; -#endif -#ifdef CONFIG_BLK_DEV_FD extern struct fd_ops std_fd_ops; -#endif extern struct rtc_ops malta_rtc_ops; +extern struct kbd_ops std_kbd_ops; extern void mips_reboot_setup(void); struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, - { "pic1", 0x20, 0x3f, IORESOURCE_BUSY }, { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, - { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY }, { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, }; #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) -static void __init malta_irq_setup(void) -{ - maltaint_init(); - -#ifdef CONFIG_REMOTE_DEBUG - if (remote_debug) { - set_debug_traps(); - breakpoint(); - } -#endif -} - - void __init malta_setup(void) { #ifdef CONFIG_REMOTE_DEBUG int rs_putDebugChar(char); char rs_getDebugChar(void); - extern int (*putDebugChar)(char); - extern char (*getDebugChar)(void); + extern int (*generic_putDebugChar)(char); + extern char (*generic_getDebugChar)(void); #endif char *argptr; int i; - irq_setup = malta_irq_setup; - /* Request I/O space for devices used on the Malta board. */ for (i = 0; i < STANDARD_IO_RESOURCES; i++) request_resource(&ioport_resource, standard_io_resources+i); @@ -133,14 +106,14 @@ line ? 1 : 0); rs_kgdb_hook(line); - putDebugChar = rs_putDebugChar; - getDebugChar = rs_getDebugChar; + generic_putDebugChar = rs_putDebugChar; + generic_getDebugChar = rs_getDebugChar; prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " "please connect your debugger\n", line ? 1 : 0); remote_debug = 1; - /* Breakpoints and stuff are in malta_irq_setup() */ + /* Breakpoints are in init_IRQ() */ } #endif @@ -154,6 +127,9 @@ #endif #ifdef CONFIG_BLK_DEV_FD fd_ops = &std_fd_ops; +#endif +#ifdef CONFIG_PC_KEYB + kbd_ops = &std_kbd_ops; #endif mips_reboot_setup(); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile --- v2.4.9/linux/arch/mips/mm/Makefile Tue Jul 3 17:08:18 2001 +++ linux/arch/mips/mm/Makefile Sun Sep 9 10:43:02 2001 @@ -15,11 +15,13 @@ obj-$(CONFIG_CPU_R3000) += r2300.o obj-$(CONFIG_CPU_R4300) += r4xx0.o obj-$(CONFIG_CPU_R4X00) += r4xx0.o +obj-$(CONFIG_CPU_VR41XX) += r4xx0.o obj-$(CONFIG_CPU_R5000) += r4xx0.o obj-$(CONFIG_CPU_NEVADA) += r4xx0.o obj-$(CONFIG_CPU_R5432) += r5432.o obj-$(CONFIG_CPU_RM7000) += rm7k.o obj-$(CONFIG_CPU_MIPS32) += mips32.o +obj-$(CONFIG_CPU_MIPS64) += mips32.o obj-$(CONFIG_SGI_IP22) += umap.o obj-$(CONFIG_BAGET_MIPS) += umap.o diff -u --recursive --new-file v2.4.9/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c --- v2.4.9/linux/arch/mips/mm/andes.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips/mm/andes.c Sun Sep 9 10:43:02 2001 @@ -132,7 +132,8 @@ static void andes_flush_cache_sigtramp(unsigned long page) { - /* XXX */ + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); } /* TLB operations. XXX Write these dave... */ @@ -182,6 +183,14 @@ _flush_icache_page = andes_flush_icache_page; _flush_icache_range = andes_flush_icache_range; + write_32bit_cp0_register(CP0_FRAMEMASK, 0); + flush_cache_all(); flush_tlb_all(); + + /* + * The R10k might even work for Linux/MIPS - but we're paranoid + * and refuse to run until this is tested on real silicon + */ + panic("CPU too expensive - making holiday in the ANDES!"); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c --- v2.4.9/linux/arch/mips/mm/loadmmu.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips/mm/loadmmu.c Sun Sep 9 10:43:02 2001 @@ -52,8 +52,9 @@ { if (mips_cpu.options & MIPS_CPU_4KTLB) { -#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_R4300) || \ - defined(CONFIG_CPU_R5000) || defined(CONFIG_CPU_NEVADA) +#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \ + defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \ + defined(CONFIG_CPU_NEVADA) printk("Loading R4000 MMU routines.\n"); ld_mmu_r4xx0(); #endif @@ -66,7 +67,7 @@ ld_mmu_r5432(); #endif -#if defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) printk("Loading MIPS32 MMU routines.\n"); ld_mmu_mips32(); #endif diff -u --recursive --new-file v2.4.9/linux/arch/mips/mm/mips32.c linux/arch/mips/mm/mips32.c --- v2.4.9/linux/arch/mips/mm/mips32.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips/mm/mips32.c Sun Sep 9 10:43:02 2001 @@ -69,10 +69,8 @@ { unsigned long i; - if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) - { - for (i=page; i #include @@ -134,31 +134,64 @@ dummy = *p; status = read_32bit_cp0_register(CP0_STATUS); - if (dummy != 0xa5a55a5a || (status & (1<<19))) { + if (dummy != 0xa5a55a5a || (status & ST0_CM)) { size = 0; } else { - for (size = 512; size <= 0x40000; size <<= 1) + for (size = 128; size <= 0x40000; size <<= 1) *(p + size) = 0; *p = -1; - for (size = 512; + for (size = 128; (size <= 0x40000) && (*(p + size) == 0); size <<= 1) ; if (size > 0x40000) size = 0; } + write_32bit_cp0_register(CP0_STATUS, flags); return size * sizeof(*p); } +unsigned long __init r3k_cache_lsize(unsigned long ca_flags) +{ + unsigned long flags, status, lsize, i, j; + volatile unsigned long *p; + + p = (volatile unsigned long *) KSEG0; + + flags = read_32bit_cp0_register(CP0_STATUS); + + /* isolate cache space */ + write_32bit_cp0_register(CP0_STATUS, (ca_flags|flags)&~ST0_IEC); + + for (i = 0; i < 128; i++) + *(p + i) = 0; + *(volatile unsigned char *)p = 0; + for (lsize = 1; lsize < 128; lsize <<= 1) { + *(p + lsize); + status = read_32bit_cp0_register(CP0_STATUS); + if (!(status & ST0_CM)) + break; + } + for (i = 0; i < 128; i += lsize) + *(volatile unsigned char *)(p + i) = 0; + + write_32bit_cp0_register(CP0_STATUS, flags); + + return lsize * sizeof(*p); +} + static void __init r3k_probe_cache(void) { dcache_size = r3k_cache_size(ST0_ISC); - dcache_lsize = 4; + if (dcache_size) + dcache_lsize = r3k_cache_lsize(ST0_ISC); + icache_size = r3k_cache_size(ST0_ISC|ST0_SWC); - icache_lsize = 4; + if (icache_size) + icache_lsize = r3k_cache_lsize(ST0_ISC|ST0_SWC); } static void r3k_flush_icache_range(unsigned long start, unsigned long end) @@ -391,11 +424,17 @@ flags = read_32bit_cp0_register(CP0_STATUS); + write_32bit_cp0_register(CP0_STATUS, flags&~ST0_IEC); + + /* Fill the TLB to avoid an exception with caches isolated. */ + asm ( "lw\t$0,0x000(%0)\n\t" + "lw\t$0,0x004(%0)\n\t" + : : "r" (addr) ); + write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC); asm ( "sb\t$0,0x000(%0)\n\t" "sb\t$0,0x004(%0)\n\t" - "sb\t$0,0x008(%0)\n\t" : : "r" (addr) ); write_32bit_cp0_register(CP0_STATUS, flags); diff -u --recursive --new-file v2.4.9/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c --- v2.4.9/linux/arch/mips/mm/r4xx0.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips/mm/r4xx0.c Sun Sep 9 10:43:02 2001 @@ -2088,43 +2088,29 @@ */ static void r4k_flush_cache_sigtramp(unsigned long addr) { - unsigned long daddr, iaddr; - - daddr = addr & ~(dc_lsize - 1); __asm__ __volatile__("nop;nop;nop;nop"); /* R4600 V1.7 */ - protected_writeback_dcache_line(daddr); - protected_writeback_dcache_line(daddr + dc_lsize); - iaddr = addr & ~(ic_lsize - 1); - protected_flush_icache_line(iaddr); - protected_flush_icache_line(iaddr + ic_lsize); + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); } static void r4600v20k_flush_cache_sigtramp(unsigned long addr) { - unsigned long daddr, iaddr; unsigned int flags; - daddr = addr & ~(dc_lsize - 1); __save_and_cli(flags); /* Clear internal cache refill buffer */ *(volatile unsigned int *)KSEG1; - protected_writeback_dcache_line(daddr); - protected_writeback_dcache_line(daddr + dc_lsize); - iaddr = addr & ~(ic_lsize - 1); - protected_flush_icache_line(iaddr); - protected_flush_icache_line(iaddr + ic_lsize); + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); + __restore_flags(flags); } #undef DEBUG_TLB #undef DEBUG_TLBUPDATE -#define NTLB_ENTRIES 48 /* Fixed on all R4XX0 variants... */ - -#define NTLB_ENTRIES_HALF 24 /* Fixed on all R4XX0 variants... */ - void flush_tlb_all(void) { unsigned long flags; @@ -2146,7 +2132,7 @@ entry = get_wired(); /* Blast 'em all away. */ - while(entry < NTLB_ENTRIES) { + while(entry < mips_cpu.tlbsize) { set_index(entry); BARRIER; tlb_write_indexed(); @@ -2188,7 +2174,7 @@ __save_and_cli(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; - if(size <= NTLB_ENTRIES_HALF) { + if(size <= mips_cpu.tlbsize/2) { int oldpid = (get_entryhi() & 0xff); int newpid = (mm->context & 0xff); @@ -2416,7 +2402,14 @@ /* Detect and size the various r4k caches. */ static void __init probe_icache(unsigned long config) { - icache_size = 1 << (12 + ((config >> 9) & 7)); + switch (mips_cpu.cputype) { + case CPU_VR41XX: + icache_size = 1 << (10 + ((config >> 9) & 7)); + break; + default: + icache_size = 1 << (12 + ((config >> 9) & 7)); + break; + } ic_lsize = 16 << ((config >> 5) & 1); printk("Primary instruction cache %dkb, linesize %d bytes.\n", @@ -2425,7 +2418,14 @@ static void __init probe_dcache(unsigned long config) { - dcache_size = 1 << (12 + ((config >> 6) & 7)); + switch (mips_cpu.cputype) { + case CPU_VR41XX: + dcache_size = 1 << (10 + ((config >> 6) & 7)); + break; + default: + dcache_size = 1 << (12 + ((config >> 6) & 7)); + break; + } dc_lsize = 16 << ((config >> 4) & 1); printk("Primary data cache %dkb, linesize %d bytes.\n", @@ -2708,6 +2708,6 @@ * - The entire mm handling assumes the c0_pagemask register to * be set for 4kb pages. */ - write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); + set_pagemask(PM_4K); flush_tlb_all(); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/mm/r5432.c linux/arch/mips/mm/r5432.c --- v2.4.9/linux/arch/mips/mm/r5432.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips/mm/r5432.c Sun Sep 9 10:43:02 2001 @@ -531,14 +531,8 @@ */ static void r5432_flush_cache_sigtramp(unsigned long addr) { - unsigned long daddr, iaddr; - - daddr = addr & ~(dc_lsize - 1); - protected_writeback_dcache_line(daddr); - protected_writeback_dcache_line(daddr + dc_lsize); - iaddr = addr & ~(ic_lsize - 1); - protected_flush_icache_line(iaddr); - protected_flush_icache_line(iaddr + ic_lsize); + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); } #undef DEBUG_TLB diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/Makefile linux/arch/mips/philips/nino/Makefile --- v2.4.9/linux/arch/mips/philips/nino/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/Makefile Sun Sep 9 10:43:02 2001 @@ -0,0 +1,33 @@ +# +# Makefile for the Philips Nino specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(AFLAGS) $< -o $@ +.S.o: + $(CC) $(AFLAGS) -c $< -o $@ + +O_TARGET := nino.o + +all: nino.o + +obj-y := int-handler.o setup.o irq.o time.o reset.o rtc.o prom.o power.o + +int-handler.o: int-handler.S + +obj-$(CONFIG_REMOTE_DEBUG) += kgdb.o + +obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o + +ramdisk.o: + $(MAKE) -C ramdisk + mv ramdisk/ramdisk.o ramdisk.o + +clean: + rm -f *.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/int-handler.S linux/arch/mips/philips/nino/int-handler.S --- v2.4.9/linux/arch/mips/philips/nino/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/int-handler.S Sun Sep 9 10:43:02 2001 @@ -0,0 +1,137 @@ +/* + * linux/arch/mips/philips/nino/int-handler.S + * + * Copyright (C) 1999 Harald Koerfgen + * Copyright (C) 2000 Jim Pick (jim@jimpick.com) + * 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. + * + * Interrupt handler for Philips Nino. + */ +#include +#include +#include +#include +#include + + .data + .globl HighPriVect + +HighPriVect: .word spurious # Reserved + .word io_posnegint0 # IOPOSINT(0) or IONEGINT(0) + .word spurious # CHIDMACNTINT + .word spurious # TELDMACNTINT + .word spurious # SNDDMACNTINT + .word spurious # Reserved + .word io_negint56 # IONEGINT(6) or IONEGINT(5) + .word spurious # Reserved + .word io_posint56 # IOPOSINT(6) or IOPOSINT(5) + .word spurious # Reserved + .word spurious # UARTBRXINT + .word uarta_rx # UARTARXINT + .word spurious # Reserved + .word periodic_timer # PERINT + .word spurious # ALARMINT + .word spurious # POSPWROKINT or NEGPWROKINT + +/* + * Here is the entry point to handle all interrupts. + */ + .text + .set noreorder + .align 5 + NESTED(nino_handle_int, PT_SIZE, ra) + .set noat + SAVE_ALL + CLI + .set at + + /* + * Get pending Interrupts + */ + mfc0 t0, CP0_CAUSE # Get pending interrupts + andi t2, t0, IE_IRQ4 # IRQ4 (high priority) + bne t2, IE_IRQ4, low_priority + nop + +/* + * Ok, we've got a high priority interrupt (a.k.a. an external interrupt). + * Read Interrupt Status Register 6 to get vector. + */ +high_priority: + lui t0, %hi(IntStatus6) + lw t1, %lo(IntStatus6)(t0) + andi t1, INT6_INTVECT + la t2, HighPriVect + addu t1, t1, t2 + lw t2, 0(t1) + jr t2 + nop + +/* + * Ok, we've got one of over a hundred other interupts. + */ +low_priority: + lui t0, %hi(IntStatus1) + lw t1, %lo(IntStatus1)(t0) + j handle_it + li a0, 20 + +/* + * We don't currently handle spurious interrupts. + */ +spurious: + j spurious_interrupt + nop + +/* + * We have the IRQ number, dispatch to the real handler. + */ +handle_it: jal do_IRQ + move a1,sp + j ret_from_irq + nop + +/************************************ + * High priority interrupt mappings * + ************************************/ + +/* + * Periodic timer - IRQ 0 + */ +periodic_timer: + j handle_it + li a0, 0 + +/* + * UARTA RX - IRQ 3 + */ +uarta_rx: + j handle_it + li a0, 3 + +/* + * GPIO Pin 0 transition - IRQ 10 + */ +io_posnegint0: + j handle_it + li a0, 10 + +/* + * GPIO Pin 5 or 6 transition (0-to-1) - IRQ 11 + */ +io_posint56: + j handle_it + li a0, 11 + +/* + * GPIO Pin 5 or 6 transition (1-to-0) - IRQ 12 + */ +io_negint56: + j handle_it + li a0, 12 + + END(nino_handle_int) diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/irq.c linux/arch/mips/philips/nino/irq.c --- v2.4.9/linux/arch/mips/philips/nino/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/irq.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,314 @@ +/* + * linux/arch/mips/philips/nino/irq.c + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1999 Harald Koerfgen + * Copyright (C) 2000 Pavel Machek (pavel@suse.cz) + * 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. + * + * Generic interrupt handler for Philips Nino. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +unsigned long spurious_count = 0; + +irq_cpustat_t irq_stat [NR_CPUS]; + +static inline void mask_irq(unsigned int irq_nr) +{ + switch (irq_nr) { + case 0: /* Periodic Timer Interrupt */ + IntClear5 = INT5_PERIODICINT; + IntClear6 = INT6_PERIODICINT; + IntEnable6 &= ~INT6_PERIODICINT; + break; + + case 3: + /* Serial port receive interrupt */ + break; + + case 2: + /* Serial port transmit interrupt */ + break; + + default: + printk( "Attempt to mask unknown IRQ %d?\n", irq_nr ); + } +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + switch (irq_nr) { + case 0: + IntEnable6 |= INT6_PERIODICINT; + break; + + case 3: + /* Serial port receive interrupt */ + break; + + case 2: + /* Serial port transmit interrupt */ + break; + + default: + printk( "Attempt to unmask unknown IRQ %d?\n", irq_nr ); + } +} + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + mask_irq(irq_nr); + restore_flags(flags); +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + unmask_irq(irq_nr); + restore_flags(flags); +} + +/* + * Pointers to the low-level handlers: first the general ones, then the + * fast ones, then the bad ones. + */ +extern void interrupt(void); + +static struct irqaction *irq_action[NR_IRQS] = +{ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +int get_irq_list(char *buf) +{ + int i, len = 0; + struct irqaction *action; + + for (i = 0; i < NR_IRQS; i++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf + len, "%2d: %8d %c %s", + i, kstat.irqs[0][i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action = action->next; action; action = action->next) { + len += sprintf(buf + len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf + len, "\n"); + } + return len; +} + +atomic_t __mips_bh_counter; + +/* + * do_IRQ handles IRQ's that have been installed without the + * SA_INTERRUPT flag: it uses the full signal-handling return + * and runs with other interrupts enabled. All relatively slow + * IRQ's should use this format: notably the keyboard/timer + * routines. + */ +asmlinkage void do_IRQ(int irq, struct pt_regs *regs) +{ + struct irqaction *action; + int do_random, cpu; + + if (irq == 20) { + if (IntStatus2 & 0xfffff00) { + if (IntStatus2 & 0x0f000000) + return do_IRQ(2, regs); + } + } + + cpu = smp_processor_id(); + irq_enter(cpu, irq); + kstat.irqs[cpu][irq]++; + + if (irq == 20) { + printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", + IntStatus1, IntStatus2, IntStatus3, + IntStatus4, IntStatus5 ); + printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", + IntEnable1, IntEnable2, IntEnable3, + IntEnable4, IntEnable5 ); + + } + + mask_irq(irq); + action = *(irq + irq_action); + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + unmask_irq(irq); + __cli(); + } else { + IntClear1 = ~0; + IntClear3 = ~0; + IntClear4 = ~0; + IntClear5 = ~0; + unmask_irq(irq); + } + irq_exit(cpu, irq); + + /* unmasking and bottom half handling is done magically for us. */ +} + +/* + * Idea is to put all interrupts + * in a single table and differenciate them just by number. + */ +int setup_nino_irq(int irq, struct irqaction *new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_and_cli(flags); + *p = new; + + if (!shared) { + unmask_irq(irq); + } + restore_flags(flags); + return 0; +} + +int request_irq(unsigned int irq, + void (*handler) (int, void *, struct pt_regs *), + unsigned long irqflags, + const char *devname, + void *dev_id) +{ + int retval; + struct irqaction *action; + + if (irq >= NR_IRQS) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_nino_irq(irq, action); + + if (retval) + kfree(action); + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *action, **p; + unsigned long flags; + + if (irq >= NR_IRQS) { + printk(KERN_CRIT __FUNCTION__ ": trying to free IRQ%d\n", irq); + return; + } + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_and_cli(flags); + *p = action->next; + if (!irq[irq_action]) + mask_irq(irq); + restore_flags(flags); + kfree(action); + return; + } + printk(KERN_CRIT __FUNCTION__ ": trying to free free IRQ%d\n", irq); +} + +unsigned long probe_irq_on(void) +{ + /* TODO */ + return 0; +} + +int probe_irq_off(unsigned long irqs) +{ + /* TODO */ + return 0; +} + +void __init init_IRQ(void) +{ + irq_setup(); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/kgdb.c linux/arch/mips/philips/nino/kgdb.c --- v2.4.9/linux/arch/mips/philips/nino/kgdb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/kgdb.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,83 @@ +/* + * linux/arch/mips/philips/nino/kgdb.c + * + * 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. + * + * Kernel debugging on the Philips Nino. + */ +#include +#include + +static int remoteDebugInitialized = 0; + +void debugInit(void) +{ +/* + * If low-level debugging (before GDB or console operational) is + * configured, then we do not need to re-initialize the UART. + */ +#ifndef CONFIG_DEBUG_LL + earlyInitUartPR31700(); +#endif +} + +char getDebugChar(void) +{ + char buf; + unsigned long int2, flags; + + if (!remoteDebugInitialized) { + debugInit(); + remoteDebugInitialized = 1; + } + + save_and_cli(flags); + + int2 = IntEnable2; + + IntEnable2 = 0; + + while(!(UartA_Ctrl1 & UART_RX_HOLD_FULL)); + + buf = UartA_Data; + + IntEnable2 = int2; + + restore_flags(flags); + + return buf; +} + +int putDebugChar(char c) +{ + int i; + unsigned long int2; + + if (!remoteDebugInitialized) { + debugInit(); + remoteDebugInitialized = 1; + } + + int2 = IntEnable2; + + IntEnable2 &= + ~(INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY); + + for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < 10000); i++); + + IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; + + UartA_Data = c; + + for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < 10000); i++); + + IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; + + IntEnable2 = int2; + + return 1; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/power.c linux/arch/mips/philips/nino/power.c --- v2.4.9/linux/arch/mips/philips/nino/power.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/power.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,36 @@ +/* + * linux/arch/mips/philips/nino/power.c + * + * 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. + * + * Power management routines on the Philips Nino. + */ +#include + +void nino_wait(void) +{ + /* We stop the CPU to conserve power */ + PowerControl |= PWR_STOPCPU; + + /* + * We wait until an interrupt happens... + */ + + /* We resume here */ + PowerControl &= ~PWR_STOPCPU; + + /* Give ourselves a little delay */ + __asm__ __volatile__( + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t"); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/prom.c linux/arch/mips/philips/nino/prom.c --- v2.4.9/linux/arch/mips/philips/nino/prom.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/prom.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,80 @@ +/* + * linux/arch/mips/philips/nino/prom.c + * + * 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. + * + * Early initialization code for the Philips Nino. + */ +#include +#include +#include +#include +#include +#include +#include + +char arcs_cmdline[COMMAND_LINE_SIZE]; + +#ifdef CONFIG_FB_TX3912 +extern u_long tx3912fb_paddr; +extern u_long tx3912fb_vaddr; +extern u_long tx3912fb_size; +#endif + +/* Do basic initialization */ +void __init prom_init(int argc, char **argv, + unsigned long magic, int *prom_vec) +{ + u_long free_end, mem_size; + u_int i; + + /* + * collect args and prepare cmd_line + */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_PHILIPS; + mips_machtype = MACH_PHILIPS_NINO; + +#ifdef CONFIG_NINO_4MB + mem_size = 4 << 20; +#elif CONFIG_NINO_8MB + mem_size = 8 << 20; +#elif CONFIG_NINO_16MB + mem_size = 16 << 20; +#endif + +#ifdef CONFIG_FB_TX3912 + /* + * The LCD controller requires that the framebuffer + * start address fall within a 1MB segment and is + * aligned on a 16 byte boundary. The way to assure + * this is to place the framebuffer at the end of + * memory and mark it as reserved. + */ + free_end = (mem_size - tx3912fb_size) & PAGE_MASK; + add_memory_region(0, free_end, BOOT_MEM_RAM); + add_memory_region(free_end, (mem_size - free_end), BOOT_MEM_RESERVED); + + /* + * Calculate physical and virtual addresses for + * the beginning of the framebuffer. + */ + tx3912fb_paddr = PHYSADDR(free_end); + tx3912fb_vaddr = KSEG1ADDR(free_end); +#else + add_memory_region(0, mem_size, BOOT_MEM_RAM); +#endif +} + +void __init prom_free_prom_memory (void) +{ +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/ramdisk/Makefile linux/arch/mips/philips/nino/ramdisk/Makefile --- v2.4.9/linux/arch/mips/philips/nino/ramdisk/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/ramdisk/Makefile Sun Sep 9 10:43:02 2001 @@ -0,0 +1,12 @@ +# +# Makefile for the Philips Nino ramdisk +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +ramdisk.o: ramdisk.gz ld.script + $(LD) -T ld.script -b binary -o $@ ramdisk.gz + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/ramdisk/ld.script linux/arch/mips/philips/nino/ramdisk/ld.script --- v2.4.9/linux/arch/mips/philips/nino/ramdisk/ld.script Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/ramdisk/ld.script Sun Sep 9 10:43:02 2001 @@ -0,0 +1,9 @@ +OUTPUT_FORMAT("ecoff-littlemips") +OUTPUT_ARCH(mips) +SECTIONS +{ + .initrd : + { + *(.data) + } +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/reset.c linux/arch/mips/philips/nino/reset.c --- v2.4.9/linux/arch/mips/philips/nino/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/reset.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,37 @@ +/* + * linux/arch/mips/philips/nino/reset.c + * + * 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. + * + * Generic restart, halt and power off functions for Philips Nino. + */ +#include +#include + +void (*reset_vector)(void) = (void (*)(void)) 0xBFC00000; + +void nino_machine_restart(char *command) +{ + reset_vector(); +} + +void nino_machine_halt(void) +{ + reset_vector(); +} + +void nino_machine_power_off(void) +{ + reset_vector(); +} + +void __init setup_nino_reset_vectors(void) +{ + _machine_restart = nino_machine_restart; + _machine_halt = nino_machine_halt; + _machine_power_off = nino_machine_power_off; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/rtc.c linux/arch/mips/philips/nino/rtc.c --- v2.4.9/linux/arch/mips/philips/nino/rtc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/rtc.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,34 @@ +/* + * linux/arch/mips/philips/nino/rtc.c + * + * 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. + * + * Functions to access RTC on the Philips Nino. + */ +#include +#include + +static unsigned char nino_rtc_read_data(unsigned long addr) +{ + return 0; +} + +static void nino_rtc_write_data(unsigned char data, unsigned long addr) +{ +} + +static int nino_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops nino_rtc_ops = +{ + &nino_rtc_read_data, + &nino_rtc_write_data, + &nino_rtc_bcd_mode +}; diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/setup.c linux/arch/mips/philips/nino/setup.c --- v2.4.9/linux/arch/mips/philips/nino/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/setup.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,120 @@ +/* + * linux/arch/mips/philips/nino/setup.c + * + * 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. + * + * Interrupt and exception initialization for Philips Nino. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct rtc_ops nino_rtc_ops; + +extern void nino_wait(void); +extern void setup_nino_reset_vectors(void); +extern asmlinkage void nino_handle_int(void); +extern int setup_nino_irq(int, struct irqaction *); +void (*board_time_init) (struct irqaction * irq); + +#ifdef CONFIG_REMOTE_DEBUG +extern void set_debug_traps(void); +extern void breakpoint(void); +static int remote_debug = 0; +#endif + +static void __init nino_irq_setup(void) +{ + unsigned int tmp; + + /* Turn all interrupts off */ + IntEnable1 = 0; + IntEnable2 = 0; + IntEnable3 = 0; + IntEnable4 = 0; + IntEnable5 = 0; + IntEnable6 = 0; + + /* Clear all interrupts */ + IntClear1 = 0xffffffff; + IntClear2 = 0xffffffff; + IntClear3 = 0xffffffff; + IntClear4 = 0xffffffff; + IntClear5 = 0xffffffff; + IntClear6 = 0xffffffff; + + /* + * Enable only the interrupts for the UART and negative + * edge (1-to-0) triggered multi-function I/O pins. + */ + change_cp0_status(ST0_BEV, 0); + tmp = read_32bit_cp0_register(CP0_STATUS); + change_cp0_status(ST0_IM, tmp | IE_IRQ2 | IE_IRQ4); + + /* Register the global interrupt handler */ + set_except_vector(0, nino_handle_int); + +#ifdef CONFIG_REMOTE_DEBUG + if (remote_debug) { + set_debug_traps(); + breakpoint(); + } +#endif +} + +static __init void nino_time_init(struct irqaction *irq) +{ + unsigned int scratch = 0; + + /* + * Enable periodic interrupts + */ + setup_nino_irq(0, irq); + + RTCperiodTimer = PER_TIMER_COUNT; + RTCtimerControl = TIM_ENPERTIMER; + IntEnable5 |= INT5_PERIODICINT; + + scratch = inl(TX3912_CLK_CTRL_BASE); + scratch |= TX3912_CLK_CTRL_ENTIMERCLK; + outl(scratch, TX3912_CLK_CTRL_BASE); + + /* Enable all interrupts */ + IntEnable6 |= INT6_GLOBALEN | INT6_PERIODICINT; +} + +void __init nino_setup(void) +{ + irq_setup = nino_irq_setup; + + board_time_init = nino_time_init; + + /* Base address to use for PC type I/O accesses */ + mips_io_port_base = KSEG1ADDR(0xB0C00000); + + setup_nino_reset_vectors(); + + /* Function called during process idle (cpu_idle) */ + cpu_wait = nino_wait; + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_REMOTE_DEBUG + remote_debug = 1; +#endif + + rtc_ops = &nino_rtc_ops; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/philips/nino/time.c linux/arch/mips/philips/nino/time.c --- v2.4.9/linux/arch/mips/philips/nino/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/philips/nino/time.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,216 @@ +/* + * linux/arch/mips/philips/nino/time.c + * + * Copyright (C) 1999 Harald Koerfgen + * Copyright (C) 2000 Pavel Machek (pavel@suse.cz) + * 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. + * + * Time handling functinos for Philips Nino. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern volatile unsigned long wall_jiffies; +extern rwlock_t xtime_lock; + +static struct timeval xbase; + +#define USECS_PER_JIFFY (1000000/HZ) + +/* + * Poll the Interrupt Status Registers + */ +#undef POLL_STATUS + +static unsigned long do_gettimeoffset(void) +{ + /* + * This is a kludge + */ + return 0; +} + +static +void inline readRTC(unsigned long *high, unsigned long *low) +{ + /* read twice, and keep reading till we find two + * the same pairs. This is needed in case the RTC + * was updating its registers and we read a old + * High but a new Low. */ + do { + *high = RTChigh & RTC_HIGHMASK; + *low = RTClow; + } while (*high != (RTChigh & RTC_HIGHMASK) || RTClow!=*low); +} + +/* + * This version of gettimeofday has near millisecond resolution. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + unsigned long high, low; + + read_lock_irqsave(&xtime_lock, flags); + // 40 bit RTC, driven by 32khz source: + // +-----------+-----------------------------------------+ + // | HHHH.HHHH | LLLL.LLLL.LLLL.LLLL.LMMM.MMMM.MMMM.MMMM | + // +-----------+-----------------------------------------+ + readRTC(&high,&low); + tv->tv_sec = (high << 17) | (low >> 15); + tv->tv_usec = (low % 32768) * 1953 / 64; + tv->tv_sec += xbase.tv_sec; + tv->tv_usec += xbase.tv_usec; + + tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. lost_ticks is + * nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; + + read_unlock_irqrestore(&xtime_lock, flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +void do_settimeofday(struct timeval *tv) +{ + write_lock_irq(&xtime_lock); + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + /* reset RTC to 0 (real time is xbase + RTC) */ + xbase = *tv; + RTCtimerControl |= TIM_RTCCLEAR; + RTCtimerControl &= ~TIM_RTCCLEAR; + RTCalarmHigh = RTCalarmLow = ~0UL; + + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + write_unlock_irq(&xtime_lock); +} + +static int set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + + return retval; +} + +/* last time the cmos clock got updated */ +static long last_rtc_update = 0; + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ + +int do_write = 1; + +static void +timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ +#ifdef POLL_STATUS + static unsigned long old_IntStatus1 = 0; + static unsigned long old_IntStatus3 = 0; + static unsigned long old_IntStatus4 = 0; + static unsigned long old_IntStatus5 = 0; + static int counter = 0; + int i; + + new_spircv = SPIData & 0xff; + if ((old_spircv != new_spircv) && (new_spircv != 0xff)) { + printk( "SPIData changed: %x\n", new_spircv ); + } + old_spircv = new_spircv; + if (do_write) + SPIData = 0; +#endif + + if (!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long pc = regs->cp0_epc; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len - 1) + pc = prof_len - 1; + atomic_inc((atomic_t *) & prof_buffer[pc]); + } + } + + /* + * aaaand... action! + */ + do_timer(regs); + + /* + * If we have an externally syncronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec > 500000 - (tick >> 1) && + xtime.tv_usec < 500000 + (tick >> 1)) + { + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } +} + +static struct irqaction irq0 = {timer_interrupt, SA_INTERRUPT, 0, + "timer", NULL, NULL}; + +void (*board_time_init) (struct irqaction * irq); + +int __init time_init(void) +{ + struct timeval starttime; + + starttime.tv_sec = mktime(2000, 1, 1, 0, 0, 0); + starttime.tv_usec = 0; + do_settimeofday(&starttime); + + board_time_init(&irq0); + + return 0; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c --- v2.4.9/linux/arch/mips/sgi/kernel/indy_hpc.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/sgi/kernel/indy_hpc.c Sun Sep 9 10:43:02 2001 @@ -12,6 +12,7 @@ #include #include #include +#include /* #define DEBUG_SGIHPC */ @@ -50,10 +51,12 @@ prom_printf("GUINESS "); #endif sgi_guiness = 1; + mips_machtype = MACH_SGI_INDY; } else { #ifdef DEBUG_SGIHPC prom_printf("FULLHOUSE "); #endif + mips_machtype = MACH_SGI_INDIGO2; sgi_guiness = 0; } sgi_boardid = brev; diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c --- v2.4.9/linux/arch/mips/sgi/kernel/indy_int.c Fri Feb 9 11:29:44 2001 +++ linux/arch/mips/sgi/kernel/indy_int.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: indy_int.c,v 1.18 2000/03/02 02:36:50 ralf Exp $ - * +/* * indy_int.c: Routines for generic manipulation of the INT[23] ASIC * found on INDY workstations.. * @@ -70,8 +69,6 @@ extern asmlinkage void indyIRQ(void); -unsigned long spurious_count = 0; - /* Local IRQ's are layed out logically like this: * * 0 --> 7 == local 0 interrupts @@ -79,433 +76,333 @@ * 16 --> 23 == vectored level 2 interrupts * 24 --> 31 == vectored level 3 interrupts (not used) */ -void disable_local_irq(unsigned int irq_nr) +static void enable_local0_irq(unsigned int irq) { unsigned long flags; save_and_cli(flags); - switch(irq_nr) { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - ioc_icontrol->imask0 &= ~(1 << irq_nr); - break; - - case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: - ioc_icontrol->imask1 &= ~(1 << (irq_nr - 8)); - break; - - case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: - ioc_icontrol->cmeimask0 &= ~(1 << (irq_nr - 16)); - break; - - default: - /* This way we'll see if anyone would ever want vectored - * level 3 interrupts. Highly unlikely. - */ - printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr); - panic("INVALID IRQ level!"); - }; + ioc_icontrol->imask0 |= (1 << (irq - SGINT_LOCAL0)); restore_flags(flags); } -void enable_local_irq(unsigned int irq_nr) +static unsigned int startup_local0_irq(unsigned int irq) +{ + enable_local0_irq(irq); + + return 0; /* Never anything pending */ +} + +static void disable_local0_irq(unsigned int irq) { unsigned long flags; + save_and_cli(flags); - switch(irq_nr) { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - ioc_icontrol->imask0 |= (1 << irq_nr); - break; - - case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: - ioc_icontrol->imask1 |= (1 << (irq_nr - 8)); - break; - - case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: - enable_local_irq(7); - ioc_icontrol->cmeimask0 |= (1 << (irq_nr - 16)); - break; - - default: - printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr); - panic("INVALID IRQ level!"); - }; + ioc_icontrol->imask0 &= ~(1 << (irq - SGINT_LOCAL0)); restore_flags(flags); } -void disable_gio_irq(unsigned int irq_nr) +#define shutdown_local0_irq disable_local0_irq +#define mask_and_ack_local0_irq disable_local0_irq + +static void end_local0_irq (unsigned int irq) { - /* XXX TODO XXX */ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_local0_irq(irq); } -void enable_gio_irq(unsigned int irq_nr) +static struct hw_interrupt_type ip22_local0_irq_type = { + "IP22 local 0", + startup_local0_irq, + shutdown_local0_irq, + enable_local0_irq, + disable_local0_irq, + mask_and_ack_local0_irq, + end_local0_irq, + NULL +}; + +static void enable_local1_irq(unsigned int irq) { - /* XXX TODO XXX */ + unsigned long flags; + + save_and_cli(flags); + ioc_icontrol->imask1 |= (1 << (irq - SGINT_LOCAL1)); + restore_flags(flags); } -void disable_hpcdma_irq(unsigned int irq_nr) +static unsigned int startup_local1_irq(unsigned int irq) { - /* XXX TODO XXX */ + enable_local1_irq(irq); + + return 0; /* Never anything pending */ } -void enable_hpcdma_irq(unsigned int irq_nr) +void disable_local1_irq(unsigned int irq) { - /* XXX TODO XXX */ + unsigned long flags; + + save_and_cli(flags); + ioc_icontrol->imask1 &= ~(1 << (irq- SGINT_LOCAL1)); + restore_flags(flags); } -void disable_irq(unsigned int irq_nr) +#define shutdown_local1_irq disable_local1_irq +#define mask_and_ack_local1_irq disable_local1_irq + +static void end_local1_irq (unsigned int irq) { - unsigned int n = irq_nr; - if(n >= SGINT_END) { - printk("whee, invalid irq_nr %d\n", irq_nr); - panic("IRQ, you lose..."); - } - if(n >= SGINT_LOCAL0 && n < SGINT_GIO) { - disable_local_irq(n - SGINT_LOCAL0); - } else if(n >= SGINT_GIO && n < SGINT_HPCDMA) { - disable_gio_irq(n - SGINT_GIO); - } else if(n >= SGINT_HPCDMA && n < SGINT_END) { - disable_hpcdma_irq(n - SGINT_HPCDMA); - } else { - panic("how did I get here?"); - } + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_local1_irq(irq); } -void enable_irq(unsigned int irq_nr) +static struct hw_interrupt_type ip22_local1_irq_type = { + "IP22 local 1", + startup_local1_irq, + shutdown_local1_irq, + enable_local1_irq, + disable_local1_irq, + mask_and_ack_local1_irq, + end_local1_irq, + NULL +}; + +static void enable_local2_irq(unsigned int irq) { - unsigned int n = irq_nr; - if(n >= SGINT_END) { - printk("whee, invalid irq_nr %d\n", irq_nr); - panic("IRQ, you lose..."); - } - if(n >= SGINT_LOCAL0 && n < SGINT_GIO) { - enable_local_irq(n - SGINT_LOCAL0); - } else if(n >= SGINT_GIO && n < SGINT_HPCDMA) { - enable_gio_irq(n - SGINT_GIO); - } else if(n >= SGINT_HPCDMA && n < SGINT_END) { - enable_hpcdma_irq(n - SGINT_HPCDMA); - } else { - panic("how did I get here?"); - } + unsigned long flags; + + save_and_cli(flags); + enable_local0_irq(7); + ioc_icontrol->cmeimask0 |= (1 << (irq - SGINT_LOCAL2)); + restore_flags(flags); } -#if 0 -/* - * Currently unused. - */ -static void local_unex(int irq, void *data, struct pt_regs *regs) +static unsigned int startup_local2_irq(unsigned int irq) { - printk("Whee: unexpected local IRQ at %08lx\n", - (unsigned long) regs->cp0_epc); - printk("DUMP: stat0<%x> stat1<%x> vmeistat<%x>\n", - ioc_icontrol->istat0, ioc_icontrol->istat1, - ioc_icontrol->vmeistat); -} -#endif + enable_local2_irq(irq); -static struct irqaction *local_irq_action[24] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL -}; + return 0; /* Never anything pending */ +} -int setup_indy_irq(int irq, struct irqaction * new) +void disable_local2_irq(unsigned int irq) { - printk("setup_indy_irq: Yeee, don't know how to setup irq<%d> for %s %p\n", - irq, new->name, new->handler); - return 0; + unsigned long flags; + + save_and_cli(flags); + ioc_icontrol->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2)); + restore_flags(flags); } -static struct irqaction r4ktimer_action = { - NULL, 0, 0, "R4000 timer/counter", NULL, NULL, -}; +#define shutdown_local2_irq disable_local2_irq +#define mask_and_ack_local2_irq disable_local2_irq -static struct irqaction indy_berr_action = { - NULL, 0, 0, "IP22 Bus Error", NULL, NULL, -}; +static void end_local2_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_local2_irq(irq); +} -static struct irqaction *irq_action[16] = { - NULL, NULL, NULL, NULL, - NULL, NULL, &indy_berr_action, &r4ktimer_action, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL +static struct hw_interrupt_type ip22_local2_irq_type = { + "IP22 local 2", + startup_local2_irq, + shutdown_local2_irq, + enable_local2_irq, + disable_local2_irq, + mask_and_ack_local2_irq, + end_local2_irq, + NULL }; -int get_irq_list(char *buf) +static void enable_local3_irq(unsigned int irq) { - int i, len = 0; - int num = 0; - struct irqaction * action; - - for (i = 0 ; i < 16 ; i++, num++) { - action = irq_action[i]; - if (!action) - continue; - len += sprintf(buf+len, "%2d: %8d %c %s", - num, kstat.irqs[0][num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - len += sprintf(buf+len, " [on-chip]\n"); - } - for (i = 0 ; i < 24 ; i++, num++) { - action = local_irq_action[i]; - if (!action) - continue; - len += sprintf(buf+len, "%2d: %8d %c %s", - num, kstat.irqs[0][num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - len += sprintf(buf+len, " [local]\n"); - } - return len; + unsigned long flags; + + save_and_cli(flags); + printk("Yeeee, got passed irq_nr %d at enable_local3_irq\n", irq); + panic("INVALID IRQ level!"); + restore_flags(flags); } -/* - * do_IRQ handles IRQ's that have been installed without the - * SA_INTERRUPT flag: it uses the full signal-handling return - * and runs with other interrupts enabled. All relatively slow - * IRQ's should use this format: notably the keyboard/timer - * routines. - */ -asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +static unsigned int startup_local3_irq(unsigned int irq) { - struct irqaction *action; - int do_random, cpu; + enable_local3_irq(irq); - cpu = smp_processor_id(); - irq_enter(cpu); - kstat.irqs[0][irq]++; + return 0; /* Never anything pending */ +} - printk("Got irq %d, press a key.", irq); - prom_getchar(); - romvec->imode(); +void disable_local3_irq(unsigned int irq) +{ + unsigned long flags; + save_and_cli(flags); /* - * mask and ack quickly, we don't want the irq controller - * thinking we're snobs just because some other CPU has - * disabled global interrupts (we have already done the - * INT_ACK cycles, it's too late to try to pretend to the - * controller that we aren't taking the interrupt). - * - * Commented out because we've already done this in the - * machinespecific part of the handler. It's reasonable to - * do this here in a highlevel language though because that way - * we could get rid of a good part of duplicated code ... + * This way we'll see if anyone would ever want vectored level 3 + * interrupts. Highly unlikely. */ - /* mask_and_ack_irq(irq); */ + printk("Yeeee, got passed irq_nr %d at disable_local3_irq\n", irq); + panic("INVALID IRQ level!"); + restore_flags(flags); +} - action = *(irq + irq_action); - if (action) { - if (!(action->flags & SA_INTERRUPT)) - __sti(); - action = *(irq + irq_action); - do_random = 0; - do { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - __cli(); - } - irq_exit(cpu); +#define shutdown_local3_irq disable_local3_irq +#define mask_and_ack_local3_irq disable_local3_irq - /* unmasking and bottom half handling is done magically for us. */ +static void end_local3_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_local3_irq(irq); } -int request_local_irq(unsigned int lirq, void (*func)(int, void *, struct pt_regs *), - unsigned long iflags, const char *dname, void *devid) +static struct hw_interrupt_type ip22_local3_irq_type = { + "IP22 local 3", + startup_local3_irq, + shutdown_local3_irq, + enable_local3_irq, + disable_local3_irq, + mask_and_ack_local3_irq, + end_local3_irq, + NULL +}; + +void enable_gio_irq(unsigned int irq) { - struct irqaction *action; + /* XXX TODO XXX */ +} - lirq -= SGINT_LOCAL0; - if(lirq >= 24 || !func) - return -EINVAL; +static unsigned int startup_gio_irq(unsigned int irq) +{ + enable_gio_irq(irq); - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if(!action) - return -ENOMEM; + return 0; /* Never anything pending */ +} - action->handler = func; - action->flags = iflags; - action->mask = 0; - action->name = dname; - action->dev_id = devid; - action->next = 0; - local_irq_action[lirq] = action; - enable_irq(lirq + SGINT_LOCAL0); - return 0; +void disable_gio_irq(unsigned int irq) +{ + /* XXX TODO XXX */ } -void free_local_irq(unsigned int lirq, void *dev_id) +#define shutdown_gio_irq disable_gio_irq +#define mask_and_ack_gio_irq disable_gio_irq + +static void end_gio_irq (unsigned int irq) { - struct irqaction *action; + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_gio_irq(irq); +} - lirq -= SGINT_LOCAL0; - if(lirq >= 24) { - printk("Aieee: trying to free bogus local irq %d\n", - lirq + SGINT_LOCAL0); - return; - } - action = local_irq_action[lirq]; - local_irq_action[lirq] = NULL; - disable_irq(lirq + SGINT_LOCAL0); - kfree(action); -} - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - int retval; - struct irqaction * action; - - if (irq >= SGINT_END) - return -EINVAL; - if (!handler) - return -EINVAL; - - if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO)) - return request_local_irq(irq, handler, irqflags, devname, dev_id); - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_indy_irq(irq, action); - - if (retval) - kfree(action); - return retval; +static struct hw_interrupt_type ip22_gio_irq_type = { + "IP22 GIO", + startup_gio_irq, + shutdown_gio_irq, + enable_gio_irq, + disable_gio_irq, + mask_and_ack_gio_irq, + end_gio_irq, + NULL +}; + +void enable_hpcdma_irq(unsigned int irq) +{ + /* XXX TODO XXX */ } - -void free_irq(unsigned int irq, void *dev_id) + +static unsigned int startup_hpcdma_irq(unsigned int irq) { - struct irqaction * action, **p; - unsigned long flags; + enable_hpcdma_irq(irq); - if (irq >= SGINT_END) { - printk("Trying to free IRQ%d\n",irq); - return; - } - if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO)) { - free_local_irq(irq, dev_id); - return; - } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - save_and_cli(flags); - *p = action->next; - restore_flags(flags); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); + return 0; /* Never anything pending */ } -int (*irq_cannonicalize)(int irq); - -static int indy_irq_cannonicalize(int irq) +void disable_hpcdma_irq(unsigned int irq) { - return irq; /* Sane hardware, sane code ... */ + /* XXX TODO XXX */ } -void __init init_IRQ(void) +#define shutdown_hpcdma_irq disable_hpcdma_irq +#define mask_and_ack_hpcdma_irq disable_hpcdma_irq + +static void end_hpcdma_irq (unsigned int irq) { - irq_cannonicalize = indy_irq_cannonicalize; - irq_setup(); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_hpcdma_irq(irq); } +static struct hw_interrupt_type ip22_hpcdma_irq_type = { + "IP22 HPC DMA", + startup_hpcdma_irq, + shutdown_hpcdma_irq, + enable_hpcdma_irq, + disable_hpcdma_irq, + mask_and_ack_hpcdma_irq, + end_hpcdma_irq, + NULL +}; + +static struct irqaction r4ktimer_action = { + NULL, 0, 0, "R4000 timer/counter", NULL, NULL, +}; + +static struct irqaction indy_berr_action = { + NULL, 0, 0, "IP22 Bus Error", NULL, NULL, +}; + +static struct irqaction *irq_action[16] = { + NULL, NULL, NULL, NULL, + NULL, NULL, &indy_berr_action, &r4ktimer_action, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL +}; + void indy_local0_irqdispatch(struct pt_regs *regs) { - struct irqaction *action; unsigned char mask = ioc_icontrol->istat0; unsigned char mask2 = 0; - int irq, cpu = smp_processor_id();; + int irq; mask &= ioc_icontrol->imask0; - if(mask & ISTAT0_LIO2) { + if (mask & ISTAT0_LIO2) { mask2 = ioc_icontrol->vmeistat; mask2 &= ioc_icontrol->cmeimask0; irq = lc2msk_to_irqnr[mask2]; - action = local_irq_action[irq]; } else { irq = lc0msk_to_irqnr[mask]; - action = local_irq_action[irq]; } /* if irq == 0, then the interrupt has already been cleared */ - if ( irq == 0 ) { goto end; } - /* if action == NULL, then we do have a handler for the irq */ - if ( action == NULL ) { goto no_handler; } - - irq_enter(cpu); - kstat.irqs[0][irq + 16]++; - action->handler(irq, action->dev_id, regs); - irq_exit(cpu); + if (irq == 0) + goto end; + + do_IRQ(irq, regs); goto end; no_handler: printk("No handler for local0 irq: %i\n", irq); end: - return; - + return; } void indy_local1_irqdispatch(struct pt_regs *regs) { - struct irqaction *action; unsigned char mask = ioc_icontrol->istat1; unsigned char mask2 = 0; - int irq, cpu = smp_processor_id();; + int irq; mask &= ioc_icontrol->imask1; - if(mask & ISTAT1_LIO3) { + if (mask & ISTAT1_LIO3) { printk("WHee: Got an LIO3 irq, winging it...\n"); mask2 = ioc_icontrol->vmeistat; mask2 &= ioc_icontrol->cmeimask1; irq = lc3msk_to_irqnr[ioc_icontrol->vmeistat]; - action = local_irq_action[irq]; } else { irq = lc1msk_to_irqnr[mask]; - action = local_irq_action[irq]; } + /* if irq == 0, then the interrupt has already been cleared */ /* not sure if it is needed here, but it is needed for local0 */ - if ( irq == 0 ) { goto end; } - /* if action == NULL, then we do have a handler for the irq */ - if ( action == NULL ) { goto no_handler; } - - irq_enter(cpu); - kstat.irqs[0][irq + 24]++; - action->handler(irq, action->dev_id, regs); - irq_exit(cpu); + if (irq == 0) + goto end; + + do_IRQ(irq, regs); goto end; no_handler: @@ -520,27 +417,16 @@ int cpu = smp_processor_id(); int irq = 6; - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[0][irq]++; printk("Got a bus error IRQ, shouldn't happen yet\n"); show_regs(regs); printk("Spinning...\n"); while(1); - irq_exit(cpu); -} - -/* Misc. crap just to keep the kernel linking... */ -unsigned long probe_irq_on (void) -{ - return 0; + irq_exit(cpu, irq); } -int probe_irq_off (unsigned long irqs) -{ - return 0; -} - -void __init sgint_init(void) +void __init init_IRQ(void) { int i; @@ -548,43 +434,43 @@ sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE); /* Init local mask --> irq tables. */ - for(i = 0; i < 256; i++) { - if(i & 0x80) { + for (i = 0; i < 256; i++) { + if (i & 0x80) { lc0msk_to_irqnr[i] = 7; lc1msk_to_irqnr[i] = 15; lc2msk_to_irqnr[i] = 23; lc3msk_to_irqnr[i] = 31; - } else if(i & 0x40) { + } else if (i & 0x40) { lc0msk_to_irqnr[i] = 6; lc1msk_to_irqnr[i] = 14; lc2msk_to_irqnr[i] = 22; lc3msk_to_irqnr[i] = 30; - } else if(i & 0x20) { + } else if (i & 0x20) { lc0msk_to_irqnr[i] = 5; lc1msk_to_irqnr[i] = 13; lc2msk_to_irqnr[i] = 21; lc3msk_to_irqnr[i] = 29; - } else if(i & 0x10) { + } else if (i & 0x10) { lc0msk_to_irqnr[i] = 4; lc1msk_to_irqnr[i] = 12; lc2msk_to_irqnr[i] = 20; lc3msk_to_irqnr[i] = 28; - } else if(i & 0x08) { + } else if (i & 0x08) { lc0msk_to_irqnr[i] = 3; lc1msk_to_irqnr[i] = 11; lc2msk_to_irqnr[i] = 19; lc3msk_to_irqnr[i] = 27; - } else if(i & 0x04) { + } else if (i & 0x04) { lc0msk_to_irqnr[i] = 2; lc1msk_to_irqnr[i] = 10; lc2msk_to_irqnr[i] = 18; lc3msk_to_irqnr[i] = 26; - } else if(i & 0x02) { + } else if (i & 0x02) { lc0msk_to_irqnr[i] = 1; lc1msk_to_irqnr[i] = 9; lc2msk_to_irqnr[i] = 17; lc3msk_to_irqnr[i] = 25; - } else if(i & 0x01) { + } else if (i & 0x01) { lc0msk_to_irqnr[i] = 0; lc1msk_to_irqnr[i] = 8; lc2msk_to_irqnr[i] = 16; @@ -614,6 +500,29 @@ ioc_icontrol->cmeimask0 = 0; ioc_icontrol->cmeimask1 = 0; - /* Now safe to set the exception vector. */ set_except_vector(0, indyIRQ); + + init_generic_irq(); + + for (i = SGINT_LOCAL0; i < SGINT_END; i++) { + hw_irq_controller *handler; + + if (i < SGINT_LOCAL1) + handler = &ip22_local0_irq_type; + else if (i < SGINT_LOCAL2) + handler = &ip22_local1_irq_type; + else if (i < SGINT_LOCAL3) + handler = &ip22_local2_irq_type; + else if (i < SGINT_GIO) + handler = &ip22_local3_irq_type; + else if (i < SGINT_HPCDMA) + handler = &ip22_gio_irq_type; + else if (i < SGINT_END) + handler = &ip22_hpcdma_irq_type; + + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = handler; + } } diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/indy_rtc.c linux/arch/mips/sgi/kernel/indy_rtc.c --- v2.4.9/linux/arch/mips/sgi/kernel/indy_rtc.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/sgi/kernel/indy_rtc.c Sun Sep 9 10:43:02 2001 @@ -1,12 +1,11 @@ -/* $Id: indy_rtc.c,v 1.1 1998/06/30 00:21:58 ralf Exp $ - * +/* * 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. * * RTC routines for Indy style attached Dallas chip. * - * Copyright (C) 1998 by Ralf Baechle + * Copyright (C) 1998, 2001 by Ralf Baechle */ #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/indy_sc.c linux/arch/mips/sgi/kernel/indy_sc.c --- v2.4.9/linux/arch/mips/sgi/kernel/indy_sc.c Tue Mar 6 19:44:36 2001 +++ linux/arch/mips/sgi/kernel/indy_sc.c Sun Sep 9 10:43:02 2001 @@ -1,8 +1,7 @@ -/* $Id: indy_sc.c,v 1.14 2000/03/25 22:35:07 ralf Exp $ - * +/* * indy_sc.c: Indy cache management functions. * - * Copyright (C) 1997 Ralf Baechle (ralf@gnu.org), + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org), * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). */ #include @@ -34,30 +33,30 @@ { unsigned long tmp; - __asm__ __volatile__(" - .set noreorder - .set mips3 - .set noat - mfc0 %2, $12 - li $1, 0x80 # Go 64 bit - mtc0 $1, $12 - - dli $1, 0x9000000080000000 - or %0, $1 # first line to flush - or %1, $1 # last line to flush - .set at - -1: sw $0, 0(%0) - bne %0, %1, 1b - daddu %0, 32 - - mtc0 %2, $12 # Back to 32 bit - nop; nop; nop; nop; - .set mips0 - .set reorder" - : "=r" (first), "=r" (last), "=&r" (tmp) - : "0" (first), "1" (last) - : "$1"); + __asm__ __volatile__( + ".set\tnoreorder\t\t\t# indy_sc_wipe\n\t" + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "mfc0\t%2, $12\n\t" + "li\t$1, 0x80\t\t\t# Go 64 bit\n\t" + "mtc0\t$1, $12\n\t" + + "dli\t$1, 0x9000000080000000\n\t" + "or\t%0, $1\t\t\t# first line to flush\n\t" + "or\t%1, $1\t\t\t# last line to flush\n\t" + ".set\tat\n\t" + + "1:\tsw\t$0, 0(%0)\n\t" + "bne\t%0, %1, 1b\n\t" + "daddu\t%0, 32\n\t" + + "mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t" + "nop; nop; nop; nop;\n\t" + ".set\tmips0\n\t" + ".set\treorder" + : "=r" (first), "=r" (last), "=&r" (tmp) + : "0" (first), "1" (last) + : "$1"); } static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size) @@ -96,27 +95,27 @@ #ifdef DEBUG_CACHE printk("Enabling R4600 SCACHE\n"); #endif - __asm__ __volatile__(" - .set push - .set noreorder - .set mips3 - mfc0 %2, $12 - nop; nop; nop; nop; - li %1, 0x80 - mtc0 %1, $12 - nop; nop; nop; nop; - li %0, 0x1 - dsll %0, 31 - lui %1, 0x9000 - dsll32 %1, 0 - or %0, %1, %0 - sb $0, 0(%0) - mtc0 $0, $12 - nop; nop; nop; nop; - mtc0 %2, $12 - nop; nop; nop; nop; - .set pop" - : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tnoreorder\n\t" + ".set\tmips3\n\t" + "mfc0\t%2, $12\n\t" + "nop; nop; nop; nop;\n\t" + "li\t%1, 0x80\n\t" + "mtc0\t%1, $12\n\t" + "nop; nop; nop; nop;\n\t" + "li\t%0, 0x1\n\t" + "dsll\t%0, 31\n\t" + "lui\t%1, 0x9000\n\t" + "dsll32\t%1, 0\n\t" + "or\t%0, %1, %0\n\t" + "sb\t$0, 0(%0)\n\t" + "mtc0\t$0, $12\n\t" + "nop; nop; nop; nop;\n\t" + "mtc0\t%2, $12\n\t" + "nop; nop; nop; nop;\n\t" + ".set\tpop" + : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); } static void indy_sc_disable(void) @@ -126,27 +125,27 @@ #ifdef DEBUG_CACHE printk("Disabling R4600 SCACHE\n"); #endif - __asm__ __volatile__(" - .set push - .set noreorder - .set mips3 - li %0, 0x1 - dsll %0, 31 - lui %1, 0x9000 - dsll32 %1, 0 - or %0, %1, %0 - mfc0 %2, $12 - nop; nop; nop; nop; - li %1, 0x80 - mtc0 %1, $12 - nop; nop; nop; nop; - sh $0, 0(%0) - mtc0 $0, $12 - nop; nop; nop; nop; - mtc0 %2, $12 - nop; nop; nop; nop; - .set pop" - : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tnoreorder\n\t" + ".set\tmips3\n\t" + "li\t%0, 0x1\n\t" + "dsll\t%0, 31\n\t" + "lui\t%1, 0x9000\n\t" + "dsll32\t%1, 0\n\t" + "or\t%0, %1, %0\n\t" + "mfc0\t%2, $12\n\t" + "nop; nop; nop; nop\n\t" + "li\t%1, 0x80\n\t" + "mtc0\t%1, $12\n\t" + "nop; nop; nop; nop\n\t" + "sh\t$0, 0(%0)\n\t" + "mtc0\t$0, $12\n\t" + "nop; nop; nop; nop\n\t" + "mtc0\t%2, $12\n\t" + "nop; nop; nop; nop\n\t" + ".set\tpop" + : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); } static inline int __init indy_sc_probe(void) diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c --- v2.4.9/linux/arch/mips/sgi/kernel/indy_timer.c Mon Oct 16 12:58:51 2000 +++ linux/arch/mips/sgi/kernel/indy_timer.c Wed Dec 31 16:00:00 1969 @@ -1,266 +0,0 @@ -/* $Id: indy_timer.c,v 1.17 2000/01/21 22:34:03 ralf Exp $ - * - * indy_timer.c: Setting up the clock on the INDY 8254 controller. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copytight (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Because of a bug in the i8254 timer we need to use the onchip r4k - * counter as our system wide timer interrupt running at 100HZ. - */ -static unsigned long r4k_offset; /* Amount to increment compare reg each time */ -static unsigned long r4k_cur; /* What counter should be at next timer irq */ - -extern rwlock_t xtime_lock; - -static inline void ack_r4ktimer(unsigned long newval) -{ - write_32bit_cp0_register(CP0_COMPARE, newval); -} - -static int set_rtc_mmss(unsigned long nowtime) -{ - struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS; - int retval = 0; - int real_seconds, real_minutes, clock_minutes; - -#define FROB_FROM_CLOCK(x) (((x) & 0xf) | ((((x) & 0xf0) >> 4) * 10)); -#define FROB_TO_CLOCK(x) ((((((x) & 0xff) / 10)<<4) | (((x) & 0xff) % 10)) & 0xff) - - clock->cmd &= ~(0x80); - clock_minutes = clock->min; - clock->cmd |= (0x80); - - clock_minutes = FROB_FROM_CLOCK(clock_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - - if(((abs(real_minutes - clock_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - - real_minutes %= 60; - if(abs(real_minutes - clock_minutes) < 30) { - /* Force clock oscillator to be on. */ - clock->month &= ~(0x80); - - /* Write real_seconds and real_minutes into the Dallas. */ - clock->cmd &= ~(0x80); - clock->sec = real_seconds; - clock->min = real_minutes; - clock->cmd |= (0x80); - } else - return -1; - -#undef FROB_FROM_CLOCK -#undef FROB_TO_CLOCK - - return retval; -} - -static long last_rtc_update; -unsigned long missed_heart_beats; - -void indy_timer_interrupt(struct pt_regs *regs) -{ - unsigned long count; - int irq = 7; - - write_lock(&xtime_lock); - /* Ack timer and compute new compare. */ - count = read_32bit_cp0_register(CP0_COUNT); - /* This has races. */ - if ((count - r4k_cur) >= r4k_offset) { - /* If this happens to often we'll need to compensate. */ - missed_heart_beats++; - r4k_cur = count + r4k_offset; - } - else - r4k_cur += r4k_offset; - ack_r4ktimer(r4k_cur); - kstat.irqs[0][irq]++; - do_timer(regs); - - /* We update the Dallas time of day approx. every 11 minutes, - * because of how the numbers work out we need to make - * absolutely sure we do this update within 500ms before the - * next second starts, thus the following code. - */ - if ((time_status & STA_UNSYNC) == 0 && - xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec >= 500000 - (tick >> 1) && - xtime.tv_usec <= 500000 + (tick >> 1)) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* do it again in 60 s */ - last_rtc_update = xtime.tv_sec - 600; - } - write_unlock(&xtime_lock); -} - -static unsigned long dosample(volatile unsigned char *tcwp, - volatile unsigned char *tc2p) -{ - unsigned long ct0, ct1; - unsigned char msb, lsb; - - /* Start the counter. */ - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN); - *tc2p = (SGINT_TCSAMP_COUNTER & 0xff); - *tc2p = (SGINT_TCSAMP_COUNTER >> 8); - - /* Get initial counter invariant */ - ct0 = read_32bit_cp0_register(CP0_COUNT); - - /* Latch and spin until top byte of counter2 is zero */ - do { - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); - lsb = *tc2p; - msb = *tc2p; - ct1 = read_32bit_cp0_register(CP0_COUNT); - } while(msb); - - /* Stop the counter. */ - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST); - - /* Return the difference, this is how far the r4k counter increments - * for every one HZ. - */ - return ct1 - ct0; -} - -static unsigned long __init get_indy_time(void) -{ - struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS; - unsigned int year, mon, day, hour, min, sec; - - /* Freeze it. */ - clock->cmd &= ~(0x80); - - /* Read regs. */ - sec = clock->sec; - min = clock->min; - hour = (clock->hr & 0x3f); - day = (clock->date & 0x3f); - mon = (clock->month & 0x1f); - year = clock->year; - - /* Unfreeze clock. */ - clock->cmd |= 0x80; - - /* Frob the bits. */ -#define FROB1(x) (((x) & 0xf) + ((((x) & 0xf0) >> 4) * 10)); -#define FROB2(x) (((x) & 0xf) + (((((x) & 0xf0) >> 4) & 0x3) * 10)); - - /* XXX Should really check that secs register is the same - * XXX as when we first read it and if not go back and - * XXX read the regs above again. - */ - sec = FROB1(sec); min = FROB1(min); day = FROB1(day); - mon = FROB1(mon); year = FROB1(year); - hour = FROB2(hour); - -#undef FROB1 -#undef FROB2 - - /* Wheee... */ - if(year < 45) - year += 30; - if ((year += 1940) < 1970) - year += 100; - - return mktime(year, mon, day, hour, min, sec); -} - -#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) - -void __init indy_timer_init(void) -{ - struct sgi_ioc_timers *p; - volatile unsigned char *tcwp, *tc2p; - - /* Figure out the r4k offset, the algorithm is very simple - * and works in _all_ cases as long as the 8254 counter - * register itself works ok (as an interrupt driving timer - * it does not because of bug, this is why we are using - * the onchip r4k counter/compare register to serve this - * purpose, but for r4k_offset calculation it will work - * ok for us). There are other very complicated ways - * of performing this calculation but this one works just - * fine so I am not going to futz around. ;-) - */ - p = ioc_timers; - tcwp = &p->tcword; - tc2p = &p->tcnt2; - - printk("calculating r4koff... "); - dosample(tcwp, tc2p); /* First sample. */ - dosample(tcwp, tc2p); /* Eat one. */ - r4k_offset = dosample(tcwp, tc2p); /* Second sample. */ - - printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); - - r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); - write_32bit_cp0_register(CP0_COMPARE, r4k_cur); - set_cp0_status(ST0_IM, ALLINTS); - sti(); - - write_lock_irq(&xtime_lock); - xtime.tv_sec = get_indy_time(); /* Read time from RTC. */ - xtime.tv_usec = 0; - write_unlock_irq(&xtime_lock); -} - -void indy_8254timer_irq(void) -{ - int cpu = smp_processor_id(); - int irq = 4; - - irq_enter(cpu); - kstat.irqs[0][irq]++; - printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); - prom_getchar(); - prom_imode(); - irq_exit(cpu); -} - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - - read_lock_irqsave(&xtime_lock, flags); - *tv = xtime; - read_unlock_irqrestore(&xtime_lock, flags); -} - -void do_settimeofday(struct timeval *tv) -{ - write_lock_irq(&xtime_lock); - xtime = *tv; - time_state = TIME_BAD; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; - write_unlock_irq(&xtime_lock); -} diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/promcon.c linux/arch/mips/sgi/kernel/promcon.c --- v2.4.9/linux/arch/mips/sgi/kernel/promcon.c Thu Oct 12 14:20:48 2000 +++ linux/arch/mips/sgi/kernel/promcon.c Wed Dec 31 16:00:00 1969 @@ -1,68 +0,0 @@ -/* - * Wrap-around code for a console using the - * SGI PROM io-routines. - * - * Copyright (c) 1999 Ulf Carlsson - * - * Derived from DECstation promcon.c - * Copyright (c) 1998 Harald Koerfgen - */ - -#include -#include -#include -#include -#include -#include - -#include - -static void prom_console_write(struct console *co, const char *s, - unsigned count) -{ - unsigned i; - - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); - } -} - -static int prom_console_wait_key(struct console *co) -{ - return prom_getchar(); -} - -static int __init prom_console_setup(struct console *co, char *options) -{ - return 0; -} - -static kdev_t prom_console_device(struct console *c) -{ - return MKDEV(TTY_MAJOR, 64 + c->index); -} - -static struct console sercons = -{ - name: "ttyS", - write: prom_console_write, - device: prom_console_device, - wait_key: prom_console_wait_key, - setup: prom_console_setup, - flags: CON_PRINTBUFFER, - index: -1, -}; - -/* - * Register console. - */ - -void __init sgi_prom_console_init(void ) -{ - register_console(&sercons); -} diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/reset.c linux/arch/mips/sgi/kernel/reset.c --- v2.4.9/linux/arch/mips/sgi/kernel/reset.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/sgi/kernel/reset.c Sun Sep 9 10:43:02 2001 @@ -1,12 +1,9 @@ -/* $Id: reset.c,v 1.7 1999/08/11 20:26:51 andrewb Exp $ - * - * Reset a SGI. - * +/* * 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. * - * Copyright (C) 1997, 1998 by Ralf Baechle + * Copyright (C) 1997, 1998, 2001 by Ralf Baechle */ #include #include @@ -54,7 +51,7 @@ { if (shuting_down) sgi_machine_power_off(); - prom_imode(); + ArcEnterInteractiveMode(); } static void sgi_machine_power_off(void) diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.4.9/linux/arch/mips/sgi/kernel/setup.c Tue Mar 6 19:44:36 2001 +++ linux/arch/mips/sgi/kernel/setup.c Sun Sep 9 10:43:02 2001 @@ -24,6 +24,7 @@ #include #include #include +#include #include #ifdef CONFIG_REMOTE_DEBUG @@ -32,7 +33,7 @@ static int remote_debug = 0; #endif -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SGI_PROM_CONSOLE) +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_ARC_CONSOLE) extern void console_setup(char *); #endif @@ -117,28 +118,6 @@ sgi_read_status }; -static void __init sgi_irq_setup(void) -{ - sgint_init(); - -#ifdef CONFIG_REMOTE_DEBUG - if (remote_debug) - set_debug_traps(); - breakpoint(); /* you may move this line to whereever you want :-) */ -#endif -} - -int __init page_is_ram(unsigned long pagenr) -{ - if ((pagenr< 0x08002000) - return 1; - return 0; -} - -void (*board_time_init)(struct irqaction *irq); - static unsigned long dosample(volatile unsigned char *tcwp, volatile unsigned char *tc2p) { @@ -161,14 +140,16 @@ ct1 = read_32bit_cp0_register(CP0_COUNT); } while(msb); - /* Stop the counter. */ - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST); + /* Stop the counter. */ + *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST); - /* Return the difference, this is how far the r4k counter increments - * for every 1/HZ seconds. We round off the nearest 1 MHz of - * master clock (= 1000000 / 100 / 2 = 5000 count). - */ - return ((ct1 - ct0) / 5000) * 5000; + /* + * Return the difference, this is how far the r4k counter increments + * for every 1/HZ seconds. We round off the nearest 1 MHz of master + * clock (= 1000000 / 100 / 2 = 5000 count). + */ + + return ((ct1 - ct0) / 5000) * 5000; } #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) @@ -180,7 +161,7 @@ */ struct sgi_ioc_timers *p; volatile unsigned char *tcwp, *tc2p; - unsigned long r4k_ticks[3] = { 0, 0, 0 }; + unsigned long r4k_ticks[3]; unsigned long r4k_next; /* Figure out the r4k offset, the algorithm is very simple @@ -201,10 +182,12 @@ dosample(tcwp, tc2p); /* Prime cache. */ dosample(tcwp, tc2p); /* Prime cache. */ /* Zero is NOT an option. */ - while (!r4k_ticks[0]) + do { r4k_ticks[0] = dosample (tcwp, tc2p); - while (!r4k_ticks[1]) + } while (!r4k_ticks[0]); + do { r4k_ticks[1] = dosample (tcwp, tc2p); + } while (!r4k_ticks[1]); if (r4k_ticks[0] != r4k_ticks[1]) { printk ("warning: timer counts differ, retrying..."); @@ -226,7 +209,7 @@ /* Set ourselves up for future interrupts */ r4k_next = (read_32bit_cp0_register(CP0_COUNT) + r4k_interval); write_32bit_cp0_register(CP0_COMPARE, r4k_next); - set_cp0_status(ST0_IM, ALLINTS); + change_cp0_status(ST0_IM, ALLINTS); sti (); } @@ -239,8 +222,6 @@ char *kgdb_ttyd; #endif - - irq_setup = sgi_irq_setup; board_time_init = sgi_time_init; /* Init the INDY HPC I/O controller. Need to call this before @@ -282,7 +263,7 @@ line ? 1 : 2); rs_kgdb_hook(line); - prom_printf("KGDB: Using serial line /dev/ttyd%d for session, " + printk("KGDB: Using serial line /dev/ttyd%d for session, " "please connect your debugger\n", line ? 1 : 2); remote_debug = 1; @@ -290,7 +271,7 @@ } #endif -#ifdef CONFIG_SGI_PROM_CONSOLE +#ifdef CONFIG_ARC_CONSOLE console_setup("ttyS0"); #endif @@ -324,5 +305,4 @@ #ifdef CONFIG_VIDEO_VINO init_vino(); #endif - } diff -u --recursive --new-file v2.4.9/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c --- v2.4.9/linux/arch/mips/sgi/kernel/time.c Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/sgi/kernel/time.c Sun Sep 9 10:43:02 2001 @@ -9,13 +9,13 @@ void indy_8254timer_irq(void) { - int cpu = smp_processor_id(); - int irq = 4; + int cpu = smp_processor_id(); + int irq = 4; - irq_enter(cpu); - kstat.irqs[0][irq]++; - printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); - prom_getchar(); - prom_imode(); - irq_exit(cpu); + irq_enter(cpu, irq); + kstat.irqs[0][irq]++; + printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); + prom_getchar(); + ArcEnterInteractiveMode(); + irq_exit(cpu, irq); } diff -u --recursive --new-file v2.4.9/linux/arch/mips/sni/dma.c linux/arch/mips/sni/dma.c --- v2.4.9/linux/arch/mips/sni/dma.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/sni/dma.c Wed Dec 31 16:00:00 1969 @@ -1,42 +0,0 @@ -/* $Id: dma.c,v 1.1 2000/02/18 00:24:30 ralf Exp $ - * - * Dynamic DMA mapping support. - * - * On RM200 there is no hardware dynamic DMA address translation, - * so consistent alloc/free are merely page allocation/freeing. - * The rest of the dynamic DMA mapping interface is implemented - * in . - * - * These routines assume that the RM has all it's memory at physical - * addresses of < 512mb. - */ -#include -#include -#include -#include -#include - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - int order = get_order(size); - - if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) - gfp |= GFP_DMA; - ret = (void *)__get_free_pages(gfp, order); - - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = virt_to_bus(ret); - } - dma_cache_wback_inv(ret, PAGE_SIZE << order); - return KSEG1ADDR(ret); -} - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long)vaddr, get_order(size)); -} diff -u --recursive --new-file v2.4.9/linux/arch/mips/sni/int-handler.S linux/arch/mips/sni/int-handler.S --- v2.4.9/linux/arch/mips/sni/int-handler.S Sat May 13 08:29:14 2000 +++ linux/arch/mips/sni/int-handler.S Sun Sep 9 10:43:02 2001 @@ -1,8 +1,7 @@ -/* $Id: int-handler.S,v 1.4 1999/01/04 16:03:58 ralf Exp $ - * +/* * SNI RM200 PCI specific interrupt handler code. * - * Copyright (C) 1994 - 1997 by Ralf Baechle + * Copyright (C) 1994, 95, 96, 97, 98, 1999, 2000 by Ralf Baechle */ #include #include @@ -37,22 +36,14 @@ mfc0 t1, CP0_CAUSE and t0, t1 - /* The following interrupt dispatch tests for hwint 1 / - EISA bridge first such that the timer interrupt get the - highest priority. */ - andi t1, t0, 0x0800 # hardware interrupt 1 - bnez t1, hwint1 - andi t1, t0, 0x4000 # hardware interrupt 4 - bnez t1, hwint4 - + andi t1, t0, 0x4a00 # hardware interrupt 1 + bnez t1, _hwint134 andi t1, t0, 0x1000 # hardware interrupt 2 - bnez t1, hwint2 - andi t1, t0, 0x2000 # hardware interrupt 3 - bnez t1, hwint3 + bnez t1, _hwint2 andi t1, t0, 0x8000 # hardware interrupt 5 - bnez t1, hwint5 + bnez t1, _hwint5 andi t1, t0, 0x0400 # hardware interrupt 0 - bnez t1, hwint0 + bnez t1, _hwint0 nop j return # spurious interrupt @@ -60,66 +51,23 @@ ############################################################################## -swint0: PANIC("swint0") -swint1: PANIC("swint1") - - /* ------------------------------------------------------------------------ */ - -/* hwint1 deals with EISA and SCSI interrupts. */ -hwint1: lbu s0, PCIMT_CSITPEND - - andi t1, s0, 0x20 - beqz t1, 1f - andi s1, s0, 0x40 - lbu a0, PCIMT_INT_ACKNOWLEDGE # IACK cycle - xori t0, a0, 0xff - beqz t0, 1f # spurious interrupt? - nop - jal i8259_do_irq # call real handler - move a1, sp - -1: bnez s1, 1f - li a0, PCIMT_IRQ_SCSI - jal do_IRQ - move a1, sp - -1: lui t0, %hi(PCIMT_CSITPEND) - j ret_from_irq - lbu zero, %lo(PCIMT_CSITPEND)(t0) - - /* ------------------------------------------------------------------------ */ - /* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug button interrupts. */ -hwint0: PANIC("Received int0 but no handler yet ...\n") -1: j 1b - nop - -go_spurious: j spurious_interrupt # we got fooled - nop - -/* hwint4 is used for only the onboard PCnet 32. */ -hwint4: mfc0 s0, CP0_STATUS - ori t0, s0, 0x4000 - xori t0, 0x4000 - mtc0 t0, CP0_STATUS - - li a0, PCIMT_IRQ_ETHERNET - jal do_IRQ +_hwint0: jal pciasic_hwint0 move a1, sp - mtc0 s0, CP0_STATUS +/* + * hwint 1 deals with EISA and SCSI interrupts, + * hwint 3 should deal with the PCI A - D interrupts, + * hwint 4 is used for only the onboard PCnet 32. + */ +_hwint134: jal pciasic_hwint134 - j ret_from_irq - nop /* This interrupt was used for the com1 console on the first prototypes. */ -hwint2: PANIC("hwint2 and no handler yet") - -/* hwint3 should deal with the PCI A - D interrupts. */ -hwint3: PANIC("hwint3 and no handler yet") +_hwint2: jal pciasic_hwint2 /* hwint5 is the r4k count / compare interrupt */ -hwint5: PANIC("hwint5 and no handler yet") +_hwint5: jal pciasic_hwint5 END(sni_rm200_pci_handle_int) diff -u --recursive --new-file v2.4.9/linux/arch/mips/sni/irq.c linux/arch/mips/sni/irq.c --- v2.4.9/linux/arch/mips/sni/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sni/irq.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,159 @@ +/* + * 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. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994 - 2000 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +spinlock_t pciasic_lock = SPIN_LOCK_UNLOCKED; + +extern asmlinkage void sni_rm200_pci_handle_int(void); +extern void do_IRQ(int irq, struct pt_regs *regs); + +static void enable_pciasic_irq(unsigned int irq); + +static unsigned int startup_pciasic_irq(unsigned int irq) +{ + enable_pciasic_irq(irq); + return 0; /* never anything pending */ +} + +#define shutdown_pciasic_irq disable_pciasic_irq + +void disable_pciasic_irq(unsigned int irq) +{ + unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2)); + unsigned long flags; + + spin_lock_irqsave(&pciasic_lock, flags); + *(volatile u8 *) PCIMT_IRQSEL &= mask; + spin_unlock_irqrestore(&pciasic_lock, flags); +} + +static void enable_pciasic_irq(unsigned int irq) +{ + unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2); + unsigned long flags; + + spin_lock_irqsave(&pciasic_lock, flags); + *(volatile u8 *) PCIMT_IRQSEL |= mask; + spin_unlock_irqrestore(&pciasic_lock, flags); +} + +#define mask_and_ack_pciasic_irq disable_pciasic_irq + +static void end_pciasic_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_pciasic_irq(irq); +} + +static struct hw_interrupt_type pciasic_irq_type = { + "PCIASIC", + startup_pciasic_irq, + shutdown_pciasic_irq, + enable_pciasic_irq, + disable_pciasic_irq, + mask_and_ack_pciasic_irq, + end_pciasic_irq, + NULL +}; + +/* + * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug + * button interrupts. Later ... + */ +void pciasic_hwint0(struct pt_regs *regs) +{ + panic("Received int0 but no handler yet ..."); +} + +/* This interrupt was used for the com1 console on the first prototypes. */ +void pciasic_hwint2(struct pt_regs *regs) +{ + /* I think this shouldn't happen on production machines. */ + panic("hwint2 and no handler yet"); +} + +/* hwint5 is the r4k count / compare interrupt */ +void pciasic_hwint5(struct pt_regs *regs) +{ + panic("hwint5 and no handler yet"); +} + +static inline int ls1bit8(unsigned int x) +{ + int b = 8, s; + + x <<= 24; + s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s; + s = 2; if ((x & 0x03) == 0) s = 0; b -= s; x <<= s; + s = 1; if ((x & 0x01) == 0) s = 0; b -= s; + + return b; +} + +/* + * hwint 1 deals with EISA and SCSI interrupts, + * hwint 3 should deal with the PCI A - D interrupts, + * hwint 4 is used for only the onboard PCnet 32. + */ +void pciasic_hwint134(struct pt_regs *regs) +{ + u8 pend = *(volatile char *)PCIMT_CSITPEND; + int irq; + + irq = PCIMT_IRQ_INT2 + ls1bit8(pend); + if (irq == PCIMT_IRQ_EISA) { + pend = *(volatile char *)PCIMT_INT_ACKNOWLEDGE; + if (!(pend ^ 0xff)) + return; + } + do_IRQ(irq, regs); + return; +} + +void __init init_pciasic(void) +{ + unsigned int flags; + + spin_lock_irqsave(&pciasic_lock, flags); + * (volatile u8 *) PCIMT_IRQSEL = + IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD; + spin_unlock_irqrestore(&pciasic_lock, flags); +} + +/* + * On systems with i8259-style interrupt controllers we assume for + * driver compatibility reasons interrupts 0 - 15 to be the i8295 + * interrupts even if the hardware uses a different interrupt numbering. + */ +void __init init_IRQ (void) +{ + int i; + + set_except_vector(0, sni_rm200_pci_handle_int); + + init_generic_irq(); + init_i8259_irqs(); /* Integrated i8259 */ + init_pciasic(); + + /* Actually we've got more interrupts to handle ... */ + for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &pciasic_irq_type; + } +} diff -u --recursive --new-file v2.4.9/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c --- v2.4.9/linux/arch/mips/sni/pci.c Mon Aug 7 14:31:40 2000 +++ linux/arch/mips/sni/pci.c Sun Sep 9 10:43:02 2001 @@ -203,6 +203,11 @@ { } +unsigned __init int pcibios_assign_all_busses(void) +{ + return 0; +} + char * __init pcibios_setup(char *str) { diff -u --recursive --new-file v2.4.9/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c --- v2.4.9/linux/arch/mips/sni/setup.c Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/sni/setup.c Sun Sep 9 10:43:02 2001 @@ -31,18 +31,6 @@ #include #include -/* - * Initial irq handlers. - */ -static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } - -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; - -extern asmlinkage void sni_rm200_pci_handle_int(void); - extern void sni_machine_restart(char *command); extern void sni_machine_halt(void); extern void sni_machine_power_off(void); @@ -51,20 +39,6 @@ extern struct rtc_ops std_rtc_ops; extern struct kbd_ops std_kbd_ops; -static void __init sni_irq_setup(void) -{ - set_except_vector(0, sni_rm200_pci_handle_int); - request_region(0x20,0x20, "pic1"); - request_region(0xa0,0x20, "pic2"); - i8259_setup_irq(2, &irq2); - /* - * IRQ0 seems to be the irq for PC style stuff. - * I don't know how to handle the debug button interrupt, so - * don't use this button yet or bad things happen ... - */ - set_cp0_status(ST0_IM, IE_IRQ1 | IE_IRQ3 | IE_IRQ4); -} - void (*board_time_init)(struct irqaction *irq); static void __init sni_rm200_pci_time_init(struct irqaction *irq) @@ -73,7 +47,7 @@ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ - i8259_setup_irq(0, irq); + setup_irq(0, irq); } unsigned char aux_device_present; @@ -101,45 +75,11 @@ printk("%s.\n", boardtype); } -int __init page_is_ram(unsigned long pagenr) -{ - return 1; -} - void __init sni_rm200_pci_setup(void) { -#if 0 /* XXX Tag me deeper */ - tag *atag; - - /* - * We just check if a tag_screen_info can be gathered - * in setup_arch(), if yes we don't proceed futher... - */ - atag = bi_TagFind(tag_screen_info); - if (!atag) { - /* - * If no, we try to find the tag_arc_displayinfo which is - * always created by Milo for an ARC box (for now Milo only - * works on ARC boxes :) -Stoned. - */ - atag = bi_TagFind(tag_arcdisplayinfo); - if (atag) { - screen_info.orig_x = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x; - screen_info.orig_y = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y; - screen_info.orig_video_cols = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns; - screen_info.orig_video_lines = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines; - } - } -#endif - sni_pcimt_detect(); sni_pcimt_sc_init(); - irq_setup = sni_irq_setup; mips_io_port_base = SNI_PORT_BASE; /* diff -u --recursive --new-file v2.4.9/linux/arch/mips64/Makefile linux/arch/mips64/Makefile --- v2.4.9/linux/arch/mips64/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/Makefile Sun Sep 9 10:43:02 2001 @@ -84,7 +84,8 @@ endif ifdef CONFIG_SGI_IP27 -LIBS += arch/mips64/sgi-ip27/ip27.a arch/mips64/arc/arclib.a +CORE_FILES += arch/mips64/sgi-ip27/ip27.o +LIBS += arch/mips64/arc/arclib.a SUBDIRS += arch/mips64/sgi-ip27 arch/mips64/arc # # Set LOADADDR to >= 0xc000000000300000 if you want to leave space for @@ -97,6 +98,17 @@ else LOADADDR += 0x8001c000 endif +endif + +ifdef CONFIG_SGI_IP32 +LIBS += arch/mips64/sgi-ip32/ip32-kern.a arch/mips64/arc/arclib.a +SUBDIRS += arch/mips64/sgi-ip32 arch/mips64/arc +# +# Set LOADADDR to >= 0x????????? if you want to leave space for symmon, +# 0x80002000 for production kernels. Note that the value must be +# 16kb aligned or the handling of the current variable will break. +# +LOADADDR += 0x80002000 endif # diff -u --recursive --new-file v2.4.9/linux/arch/mips64/arc/env.c linux/arch/mips64/arc/env.c --- v2.4.9/linux/arch/mips64/arc/env.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/arc/env.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: env.c,v 1.4 1999/10/19 20:51:44 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/arc/file.c linux/arch/mips64/arc/file.c --- v2.4.9/linux/arch/mips64/arc/file.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/arc/file.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: file.c,v 1.3 1999/10/19 20:51:44 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/arc/init.c linux/arch/mips64/arc/init.c --- v2.4.9/linux/arch/mips64/arc/init.c Mon Feb 28 07:18:20 2000 +++ linux/arch/mips64/arc/init.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: init.c,v 1.3 1999/11/19 23:29:05 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/arc/memory.c linux/arch/mips64/arc/memory.c --- v2.4.9/linux/arch/mips64/arc/memory.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/arc/memory.c Sun Sep 9 10:43:02 2001 @@ -54,7 +54,8 @@ "FirmwarePermanent", "FreeContiguous" }; -#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc] +#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \ + : arc_mtypes[a.arc] #endif static inline int memtype_classify_arcs (union linux_memtypes type) @@ -138,10 +139,8 @@ } } -void __init -prom_free_prom_memory (void) +void __init prom_free_prom_memory (void) { - struct prom_pmemblock *p; unsigned long freed = 0; unsigned long addr; int i; @@ -160,5 +159,5 @@ freed += PAGE_SIZE; } } - printk("Freeing prom memory: %ldkb freed\n", freed >> 10); + printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10); } diff -u --recursive --new-file v2.4.9/linux/arch/mips64/arc/misc.c linux/arch/mips64/arc/misc.c --- v2.4.9/linux/arch/mips64/arc/misc.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/arc/misc.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: misc.c,v 1.2 1999/08/21 21:42:59 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/arc/salone.c linux/arch/mips64/arc/salone.c --- v2.4.9/linux/arch/mips64/arc/salone.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/arc/salone.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: salone.c,v 1.2 1999/08/21 21:42:59 ralf Exp $ - * +/* * Routines to load into memory and execute stand-along program images using * ARCS PROM firmware. * diff -u --recursive --new-file v2.4.9/linux/arch/mips64/arc/time.c linux/arch/mips64/arc/time.c --- v2.4.9/linux/arch/mips64/arc/time.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/arc/time.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: time.c,v 1.2 1999/08/21 21:42:59 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/arc/tree.c linux/arch/mips64/arc/tree.c --- v2.4.9/linux/arch/mips64/arc/tree.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/arc/tree.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: tree.c,v 1.3 1999/09/27 16:01:37 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/config.in linux/arch/mips64/config.in --- v2.4.9/linux/arch/mips64/config.in Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/config.in Sun Sep 9 10:43:02 2001 @@ -41,6 +41,7 @@ unset CONFIG_BOOT_ELF64 unset CONFIG_COHERENT_IO unset CONFIG_ISA +unset CONFIG_MAPPED_PCI_IO unset CONFIG_PCI if [ "$CONFIG_SGI_IP22" = "y" ]; then @@ -56,6 +57,7 @@ define_bool CONFIG_BOOT_ELF64 y define_bool CONFIG_ARC64 y define_bool CONFIG_COHERENT_IO y + define_bool CONFIG_MAPPED_PCI_IO y define_bool CONFIG_PCI y define_bool CONFIG_QL_ISP_A64 y define_int CONFIG_L1_CACHE_SHIFT 7 @@ -177,7 +179,7 @@ fi endmenu -source drivers/message/i2o/Config.in +#source drivers/message/i2o/Config.in if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment @@ -270,7 +272,7 @@ fi bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ -if [ "$CONFIG_SMP" != "n" ]; then +if [ "$CONFIG_SMP" != "y" ]; then bool 'Run uncached' CONFIG_MIPS_UNCACHED fi endmenu diff -u --recursive --new-file v2.4.9/linux/arch/mips64/defconfig linux/arch/mips64/defconfig --- v2.4.9/linux/arch/mips64/defconfig Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/defconfig Sun Sep 9 10:43:02 2001 @@ -24,6 +24,7 @@ CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y +CONFIG_MAPPED_PCI_IO=y CONFIG_PCI=y CONFIG_QL_ISP_A64=y CONFIG_L1_CACHE_SHIFT=7 @@ -142,6 +143,7 @@ # # CONFIG_PHONE is not set # CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set # # ATA/IDE/MFM/RLL support @@ -184,6 +186,7 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -201,6 +204,7 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set @@ -219,16 +223,6 @@ # CONFIG_SCSI_U14_34F is not set # -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -241,18 +235,22 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_SGI_IOC3_ETH=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_DEPCA is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set @@ -262,9 +260,14 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -329,7 +332,11 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# # # Input core support is needed for joysticks @@ -367,24 +374,30 @@ # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -398,7 +411,6 @@ # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -408,6 +420,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y @@ -441,6 +454,7 @@ # CONFIG_MINIX_SUBPARTITION is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -459,9 +473,107 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking @@ -469,4 +581,3 @@ CONFIG_CROSSCOMPILE=y # CONFIG_REMOTE_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips64/defconfig-ip22 linux/arch/mips64/defconfig-ip22 --- v2.4.9/linux/arch/mips64/defconfig-ip22 Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/defconfig-ip22 Sun Sep 9 10:43:02 2001 @@ -149,6 +149,7 @@ # # CONFIG_PHONE is not set # CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set # # ATA/IDE/MFM/RLL support @@ -193,6 +194,7 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -209,6 +211,7 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set @@ -222,15 +225,6 @@ # CONFIG_SCSI_DEBUG is not set # -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -244,18 +238,20 @@ # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set # CONFIG_ETHERTAP is not set -# CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -265,11 +261,15 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -336,7 +336,11 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# # # Input core support is needed for joysticks @@ -353,6 +357,7 @@ # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -374,24 +379,30 @@ CONFIG_AUTOFS4_FS=y # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -405,7 +416,6 @@ # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -415,6 +425,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y @@ -447,6 +458,7 @@ # CONFIG_MINIX_SUBPARTITION is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -484,9 +496,107 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking diff -u --recursive --new-file v2.4.9/linux/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27 --- v2.4.9/linux/arch/mips64/defconfig-ip27 Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/defconfig-ip27 Sun Sep 9 10:43:02 2001 @@ -24,6 +24,7 @@ CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y +CONFIG_MAPPED_PCI_IO=y CONFIG_PCI=y CONFIG_QL_ISP_A64=y CONFIG_L1_CACHE_SHIFT=7 @@ -142,6 +143,7 @@ # # CONFIG_PHONE is not set # CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set # # ATA/IDE/MFM/RLL support @@ -184,6 +186,7 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -201,6 +204,7 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR_D700 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set @@ -219,16 +223,6 @@ # CONFIG_SCSI_U14_34F is not set # -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -241,18 +235,22 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_SGI_IOC3_ETH=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_DEPCA is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set @@ -262,9 +260,14 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -329,7 +332,11 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# # # Input core support is needed for joysticks @@ -367,24 +374,30 @@ # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_CMS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set +# CONFIG_FREEVXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -398,7 +411,6 @@ # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -408,6 +420,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y @@ -441,6 +454,7 @@ # CONFIG_MINIX_SUBPARTITION is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -459,9 +473,107 @@ # CONFIG_USB is not set # +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# Miscellaneous USB drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ID75 is not set + +# # Input core support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Kernel hacking @@ -469,4 +581,3 @@ CONFIG_CROSSCOMPILE=y # CONFIG_REMOTE_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set diff -u --recursive --new-file v2.4.9/linux/arch/mips64/defconfig-ip32 linux/arch/mips64/defconfig-ip32 --- v2.4.9/linux/arch/mips64/defconfig-ip32 Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/defconfig-ip32 Sun Sep 9 10:43:02 2001 @@ -0,0 +1,511 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +CONFIG_SGI_IP32=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_BOOT_ELF32=y +CONFIG_ARC32=y +CONFIG_PC_KEYB=y +CONFIG_PCI=y +CONFIG_ARC_MEMORY=y +CONFIG_L1_CACHE_SHIFT=5 +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set + +# +# CPU selection +# +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set + +# +# General setup +# +# CONFIG_CPU_LITTLE_ENDIAN is not set +# CONFIG_MIPS_FPU_EMULATOR is not set +CONFIG_NET=y +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +# CONFIG_PROM_CONSOLE is not set +CONFIG_BINFMT_ELF=y +CONFIG_MIPS32_COMPAT=y +CONFIG_BINFMT_ELF32=y +CONFIG_BINFMT_MISC=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set +CONFIG_PCI_NAMES=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +CONFIG_CHR_DEV_ST=y +CONFIG_CHR_DEV_OSST=y +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_DEBUG_QUEUES=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +CONFIG_SCSI_AIC7XXX=y +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_SYM53C8XX is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_DEBUG is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +CONFIG_TULIP=y +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +CONFIG_EEPRO100=y +# CONFIG_EEPRO100_PM is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_LAN_SAA9730 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_CRAMFS is not set +CONFIG_TMPFS=y +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set +CONFIG_KCORE_ELF=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Input core support +# +# CONFIG_INPUT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MIPS_UNCACHED=y diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/binfmt_elf32.c linux/arch/mips64/kernel/binfmt_elf32.c --- v2.4.9/linux/arch/mips64/kernel/binfmt_elf32.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/binfmt_elf32.c Sun Sep 9 10:43:01 2001 @@ -32,7 +32,7 @@ #define TASK32_SIZE 0x80000000UL #undef ELF_ET_DYN_BASE -#define ELF_ET_DYN_BASE (2 * TASK32_SIZE / 3) +#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/entry.S linux/arch/mips64/kernel/entry.S --- v2.4.9/linux/arch/mips64/kernel/entry.S Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/entry.S Sun Sep 9 10:43:01 2001 @@ -5,8 +5,9 @@ * * Low level exception handling * - * Copyright (C) 1994 - 2000 by Ralf Baechle + * Copyright (C) 1994 - 2000, 2001 Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics + * Copyright (C) 2001 MIPS Technologies, Inc. */ #include @@ -15,53 +16,61 @@ #include #include +/* This duplicates the definition from */ +#define PT_TRACESYS 0x00000002 /* tracing system calls */ + +#define KU_USER 0x10 + .text - .set noreorder .align 4 FEXPORT(ret_from_fork) + move a0, v0 # prev jal schedule_tail - move a0, v0 # prev + lw t0, TASK_PTRACE($28) # syscall tracing enabled? + andi t0, PT_TRACESYS + bnez t0, tracesys_exit j ret_from_sys_call - nop -FEXPORT(handle_softirq) - jal do_softirq - nop - b 9f - nop + +tracesys_exit: + jal syscall_trace + b ret_from_sys_call + +EXPORT(ret_from_irq) +EXPORT(ret_from_exception) + lw t0, PT_STATUS(sp) # returning to kernel mode? + andi t0, t0, KU_USER + bnez t0, ret_from_sys_call + j restore_all reschedule: jal schedule - nop FEXPORT(ret_from_sys_call) -FEXPORT(ret_from_irq) - la t1, irq_stat # softirq_active -#ifdef CONFIG_SMP - lwu t0, TASK_PROCESSOR($28) - dsll t0, t0, 5 - daddu t1, t0 -#endif - lw t0, 0 (t1) # softirq_active - lw t1, 4 (t1) # softirq_mask. unused delay slot - and t0, t1 - bnez t0, handle_softirq -9: ld t0, PT_STATUS(sp) # returning to kernel mode? - - andi t1, t0, 0x10 - beqz t1, return # -> yes - ld t1, TASK_NEED_RESCHED($28) - bnez t1, reschedule - lw v0, TASK_SIGPENDING($28) - move a0, zero - beqz v0, return - nop - jal do_signal - move a1, sp + mfc0 t0, CP0_STATUS # need_resched and signals atomic test + ori t0, t0, 1 + xori t0, t0, 1 + mtc0 t0, CP0_STATUS + + ld v0, TASK_NEED_RESCHED($28) + lw v1, TASK_SIGPENDING($28) + bnez v0, reschedule + bnez v1, signal_return -FEXPORT(return) .set noat +restore_all: .set noat RESTORE_ALL eret .set at +signal_return: .type signal_return, @function + + mfc0 t0, CP0_STATUS + ori t0, t0, 1 + mtc0 t0, CP0_STATUS + + move a0, zero + move a1, sp + jal do_signal + b restore_all + /* * Common spurious interrupt handler. */ @@ -75,6 +84,6 @@ lui t1,%hi(spurious_count) lw t0,%lo(spurious_count)(t1) addiu t0,1 + sw t0,%lo(spurious_count)(t1) j ret_from_irq - sw t0,%lo(spurious_count)(t1) END(spurious_interrupt) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/init_task.c linux/arch/mips64/kernel/init_task.c --- v2.4.9/linux/arch/mips64/kernel/init_task.c Thu Feb 24 22:53:35 2000 +++ linux/arch/mips64/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -4,7 +4,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; 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/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c --- v2.4.9/linux/arch/mips64/kernel/linux32.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/linux32.c Sun Sep 9 10:43:01 2001 @@ -1538,11 +1538,11 @@ err = -EFAULT; if (get_user (pad, (u32 *)uptr)) return err; - if(third == SETVAL) + if ((third & ~IPC_64) == SETVAL) fourth.val = (int)pad; else fourth.__pad = (void *)A(pad); - switch (third) { + switch (third & ~IPC_64) { case IPC_INFO: case IPC_RMID: diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/mips64_ksyms.c linux/arch/mips64/kernel/mips64_ksyms.c --- v2.4.9/linux/arch/mips64/kernel/mips64_ksyms.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/mips64_ksyms.c Sun Sep 9 10:43:01 2001 @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -37,6 +38,7 @@ extern long __strnlen_user_nocheck_asm(const char *s); extern long __strnlen_user_asm(const char *s); +EXPORT_SYMBOL(mips_machtype); EXPORT_SYMBOL(EISA_bus); /* diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/proc.c linux/arch/mips64/kernel/proc.c --- v2.4.9/linux/arch/mips64/kernel/proc.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/proc.c Sun Sep 9 10:43:01 2001 @@ -1,12 +1,10 @@ -/* $Id: proc.c,v 1.1 1999/09/28 22:25:51 ralf Exp $ - * +/* * 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. * - * Copyright (C) 1995, 1996, 1999 Ralf Baechle - * - * XXX Rewrite this mess. + * Copyright (C) 1995, 1996, 1999, 2001 Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. */ #include #include @@ -17,7 +15,7 @@ #include #include -unsigned long unaligned_instructions; +extern unsigned long unaligned_instructions; unsigned int vced_count, vcei_count; /* diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/ptrace.c linux/arch/mips64/kernel/ptrace.c --- v2.4.9/linux/arch/mips64/kernel/ptrace.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/ptrace.c Tue Sep 18 16:56:19 2001 @@ -29,6 +29,16 @@ #include /* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* Nothing to do.. */ +} + +/* * Tracing a 32-bit process with a 64-bit strace and vice versa will not * work. I don't know how to fix this. */ @@ -104,6 +114,9 @@ break; case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { + unsigned long *fregs = + (void *) child->thread.fpu.hard.fp_regs; + #ifndef CONFIG_SMP if (last_task_used_math == child) { set_cp0_status(ST0_CU1, ST0_CU1); @@ -112,7 +125,15 @@ last_task_used_math = NULL; } #endif - tmp = child->thread.fpu.hard.fp_regs[addr - 32]; + /* + * The odd registers are actually the high + * order bits of the values stored in the even + * registers. + */ + if (addr & 1) + tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); + else + tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); } else { tmp = -EIO; } @@ -171,7 +192,8 @@ regs->regs[addr] = data; break; case FPR_BASE ... FPR_BASE + 31: { - unsigned long *fregs; + unsigned long *fregs = + (void *) child->thread.fpu.hard.fp_regs; if (child->used_math) { #ifndef CONFIG_SMP if (last_task_used_math == child) { @@ -188,8 +210,18 @@ sizeof(child->thread.fpu.hard)); child->thread.fpu.hard.control = 0; } - fregs = child->thread.fpu.hard.fp_regs; - fregs[addr - FPR_BASE] = data; + /* + * The odd registers are actually the high order bits + * of the values stored in the even registers - unless + * we're using r2k_switch.S. + */ + if (addr & 1) { + fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; + fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long) data) << 32; + } else { + fregs[addr - FPR_BASE] &= ~0xffffffffLL; + fregs[addr - FPR_BASE] |= data; + } break; } case PC: @@ -239,21 +271,9 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace = 0; - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); break; - } case PTRACE_SETOPTIONS: { if (data & PTRACE_O_TRACESYSGOOD) @@ -354,6 +374,9 @@ break; case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { + unsigned long long *fregs + = (unsigned long long *) + &child->thread.fpu.hard.fp_regs[0]; #ifndef CONFIG_SMP if (last_task_used_math == child) { set_cp0_status(ST0_CU1, ST0_CU1); @@ -362,7 +385,15 @@ last_task_used_math = NULL; } #endif - tmp = child->thread.fpu.hard.fp_regs[addr - 32]; + /* + * The odd registers are actually the high + * order bits of the values stored in the even + * registers. + */ + if (addr & 1) + tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); + else + tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); } else { tmp = -EIO; } @@ -421,7 +452,8 @@ regs->regs[addr] = data; break; case FPR_BASE ... FPR_BASE + 31: { - unsigned long *fregs; + unsigned long *fregs = + (void *) child->thread.fpu.hard.fp_regs; if (child->used_math) { #ifndef CONFIG_SMP if (last_task_used_math == child) { @@ -438,8 +470,18 @@ sizeof(child->thread.fpu.hard)); child->thread.fpu.hard.control = 0; } - fregs = child->thread.fpu.hard.fp_regs; - fregs[addr - FPR_BASE] = data; + /* + * The odd registers are actually the high order bits + * of the values stored in the even registers - unless + * we're using r2k_switch.S. + */ + if (addr & 1) { + fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; + fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long) data) << 32; + } else { + fregs[addr - FPR_BASE] &= ~0xffffffffLL; + fregs[addr - FPR_BASE] |= data; + } break; } case PC: @@ -489,21 +531,9 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace = 0; - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); break; - } case PTRACE_SETOPTIONS: { if (data & PTRACE_O_TRACESYSGOOD) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/r4k_cache.S linux/arch/mips64/kernel/r4k_cache.S --- v2.4.9/linux/arch/mips64/kernel/r4k_cache.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/kernel/r4k_cache.S Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: r4k_cache.S,v 1.1 1999/10/10 18:49:17 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/r4k_genex.S linux/arch/mips64/kernel/r4k_genex.S --- v2.4.9/linux/arch/mips64/kernel/r4k_genex.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/kernel/r4k_genex.S Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: r4k_genex.S,v 1.3 1999/11/23 17:12:49 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/r4k_switch.S linux/arch/mips64/kernel/r4k_switch.S --- v2.4.9/linux/arch/mips64/kernel/r4k_switch.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/kernel/r4k_switch.S Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: r4k_switch.S,v 1.1 1999/12/04 03:59:00 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/r4k_tlb_debug.c linux/arch/mips64/kernel/r4k_tlb_debug.c --- v2.4.9/linux/arch/mips64/kernel/r4k_tlb_debug.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/kernel/r4k_tlb_debug.c Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: r4k_tlb_debug.c,v 1.2 2000/01/17 23:32:46 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/r4k_tlb_glue.S linux/arch/mips64/kernel/r4k_tlb_glue.S --- v2.4.9/linux/arch/mips64/kernel/r4k_tlb_glue.S Tue Jul 11 11:14:48 2000 +++ linux/arch/mips64/kernel/r4k_tlb_glue.S Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: r4k_tlb_glue.S,v 1.5 1999/11/23 17:12:49 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/scall_64.S linux/arch/mips64/kernel/scall_64.S --- v2.4.9/linux/arch/mips64/kernel/scall_64.S Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/scall_64.S Sun Sep 9 10:43:01 2001 @@ -3,8 +3,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. */ #include #include @@ -62,44 +63,39 @@ sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result -FEXPORT(ret_from_sys_call_64) - la t1, irq_stat # softirq_active -#ifdef CONFIG_SMP - lwu t0, TASK_PROCESSOR($28) - dsll t0, t0, 5 - daddu t1, t0 -#endif - lw t0, 0(t1) # softirq_active - lw t1, 4(t1) # softirq_mask. unused delay slot - and t0, t1 - bnez t0, handle_softirq_64 +ret_from_sys_call: + mfc0 t0, CP0_STATUS + xori t0, t0, 1 + ori t0, t0, 1 + mtc0 t0, CP0_STATUS -9: ld t0, PT_STATUS(sp) # returning to kernel mode? - andi t1, t0, 0x10 ld t2, TASK_NEED_RESCHED($28) - beqz t1, return_64 # -> yes - bnez t2, reschedule_64 + bnez t2, reschedule lw v0, TASK_SIGPENDING($28) - move a0, zero - beqz v0, return_64 - move a1, sp - SAVE_STATIC - jal do_signal + bnez v0, signal_return -return_64: +restore_all: RESTORE_SOME RESTORE_SP - .set mips3 eret - .set mips0 -handle_softirq_64: - jal do_softirq - b 9b -reschedule_64: +/* Put this behind restore_all for the sake of the branch prediction. */ +signal_return: + .type signal_return, @function + + mfc0 t0, CP0_STATUS + ori t0, t0, 1 + mtc0 t0, CP0_STATUS + + move a0, zero + move a1, sp + jal do_signal + b restore_all + +reschedule: SAVE_STATIC jal schedule - b ret_from_sys_call_64 + b ret_from_sys_call /* ------------------------------------------------------------------------ */ diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/scall_o32.S linux/arch/mips64/kernel/scall_o32.S --- v2.4.9/linux/arch/mips64/kernel/scall_o32.S Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/scall_o32.S Sun Sep 9 10:43:01 2001 @@ -3,8 +3,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 - 2000 by Ralf Baechle + * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. * * Hairy, the userspace application uses a different argument passing * convention than the kernel, so we have to translate things from o32 @@ -18,6 +19,7 @@ #include #include #include +#include /* This duplicates the definition from */ #define PT_TRACESYS 0x00000002 /* tracing system calls */ @@ -34,14 +36,6 @@ SAVE_SOME STI .set at -#if DEBUG_MIPS64 - jal dodebug - ld $4, PT_R4(sp) - ld $5, PT_R5(sp) - ld $6, PT_R6(sp) - ld $7, PT_R7(sp) - ld $2, PT_R2(sp) -#endif ld t1, PT_EPC(sp) # skip syscall on return subu t0, v0, __NR_Linux32 # check syscall number @@ -60,59 +54,50 @@ bgez t0, stackargs stack_done: - ld t0, TASK_PTRACE($28) # syscall tracing enabled? - andi t0, PT_TRACESYS - bnez t0, trace_a_syscall - - jalr t2 # Do The Real Thing (TM) - - li t0, -EMAXERRNO - 1 # error? - sltu t0, t0, v0 - sd t0, PT_R7(sp) # set error flag - beqz t0, 1f + ld t0, TASK_PTRACE($28) # syscall tracing enabled? + andi t0, PT_TRACESYS + bnez t0, trace_a_syscall + + jalr t2 # Do The Real Thing (TM) + + li t0, -EMAXERRNO - 1 # error? + sltu t0, t0, v0 + sd t0, PT_R7(sp) # set error flag + beqz t0, 1f + + negu v0 # error + sd v0, PT_R0(sp) # flag for syscall restarting +1: sd v0, PT_R2(sp) # result - negu v0 # error - sd v0, PT_R0(sp) # set flag for syscall restarting -1: sd v0, PT_R2(sp) # result - FEXPORT(o32_ret_from_sys_call) - la t1, irq_stat # softirq_active -#ifdef CONFIG_SMP - lwu t0, TASK_PROCESSOR($28) - dsll t0, t0, 5 - daddu t1, t0 -#endif - lw t0, 0(t1) # softirq_active - lw t1, 4(t1) # softirq_mask. unused delay slot - and t0, t1 - bnez t0, o32_handle_softirq - -9: ld t0,PT_STATUS(sp) # returning to kernel mode? - andi t1, t0, 0x10 - ld t2, TASK_NEED_RESCHED($28) - beqz t1, o32_return # -> yes - bnez t2, o32_reschedule - lw v0, TASK_SIGPENDING($28) - move a0, zero - beqz v0, o32_return - move a1, sp - SAVE_STATIC - jal do_signal + mfc0 t0, CP0_STATUS # need_resched and signals atomic test + ori t0, t0, 1 + xori t0, t0, 1 + mtc0 t0, CP0_STATUS + + ld t2, TASK_NEED_RESCHED($28) + bnez t2, o32_reschedule + lw v0, TASK_SIGPENDING($28) + bnez v0, signal_return + +restore_all: RESTORE_SOME + RESTORE_SP + .set mips3 + eret + .set mips0 + +signal_return: mfc0 t0, CP0_STATUS # need_resched and signals atomic test + ori t0, t0, 1 + mtc0 t0, CP0_STATUS + move a0, zero + move a1, sp + SAVE_STATIC + jal do_signal -o32_return: - RESTORE_SOME - RESTORE_SP - .set mips3 - eret - .set mips0 - -o32_handle_softirq: - jal do_softirq - b 9b o32_reschedule: - SAVE_STATIC - jal schedule - b o32_ret_from_sys_call + SAVE_STATIC + jal schedule + b o32_ret_from_sys_call /* ------------------------------------------------------------------------ */ @@ -205,6 +190,47 @@ sd t0, PT_R7(sp) j ret_from_sys_call END(handle_sys) + + LEAF(mips_atomic_set) + ld v1, THREAD_CURDS($28) + daddiu a0, a1, 4 + or a0, a0, a1 + li v0, -EFAULT + and a0, a0, v1 + bltz a0, 9f + + /* Ok, this is the ll/sc case. World is sane :-) */ +1: ll v0, (a1) + move a0, a2 +2: sc a0, (a1) + beqz a0, 1b + + .section __ex_table,"a" + PTR 1b, bad_stack + PTR 2b, bad_stack + .previous + +1: sd v0, PT_R2(sp) # result + + /* Success, so skip usual error handling garbage. */ + ld t0, TASK_PTRACE($28) # syscall tracing enabled? + andi t0, PT_TRACESYS + bnez t0, 1f + b o32_ret_from_sys_call + +1: SAVE_STATIC + jal syscall_trace + li a3, 0 # success + j ret_from_sys_call + +9: li v0, -EFAULT + jr ra + END(mips_atomic_set) + + LEAF(sys_sysmips) + beq a0, MIPS_ATOMIC_SET, mips_atomic_set + j _sys_sysmips + END(sys_sysmips) .macro syscalltable sys sys_syscall 0 /* 4000 */ diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/setup.c linux/arch/mips64/kernel/setup.c --- v2.4.9/linux/arch/mips64/kernel/setup.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/setup.c Sun Sep 9 10:43:01 2001 @@ -81,7 +81,6 @@ * * These are initialized so they are in the .data section */ -unsigned long mips_memory_upper = KSEG0; unsigned long mips_cputype = CPU_UNKNOWN; unsigned long mips_machtype = MACH_UNKNOWN; unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/signal.c linux/arch/mips64/kernel/signal.c --- v2.4.9/linux/arch/mips64/kernel/signal.c Wed Jan 24 15:22:55 2001 +++ linux/arch/mips64/kernel/signal.c Sun Sep 9 10:43:01 2001 @@ -267,8 +267,7 @@ struct ucontext rs_uc; }; -asmlinkage void -sys_sigreturn(abi64_no_regargs, struct pt_regs regs) +asmlinkage void sys_sigreturn(abi64_no_regargs, struct pt_regs regs) { struct sigframe *frame; sigset_t blocked; @@ -304,8 +303,7 @@ force_sig(SIGSEGV, current); } -asmlinkage void -sys_rt_sigreturn(abi64_no_regargs, struct pt_regs regs) +asmlinkage void sys_rt_sigreturn(abi64_no_regargs, struct pt_regs regs) { struct rt_sigframe *frame; sigset_t set; @@ -346,8 +344,8 @@ force_sig(SIGSEGV, current); } -static int inline -setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +static int inline setup_sigcontext(struct pt_regs *regs, + struct sigcontext *sc) { int err = 0; @@ -392,8 +390,8 @@ /* * Determine which stack to use.. */ -static inline void * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, + size_t frame_size) { unsigned long sp; @@ -407,9 +405,8 @@ return (void *)((sp - frame_size) & ALMASK); } -static void inline -setup_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set) +static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set) { struct sigframe *frame; int err = 0; @@ -470,9 +467,9 @@ force_sig(SIGSEGV, current); } -static void inline -setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set, siginfo_t *info) +static void inline setup_rt_frame(struct k_sigaction * ka, + struct pt_regs *regs, int signr, + sigset_t *set, siginfo_t *info) { struct rt_sigframe *frame; int err = 0; @@ -489,10 +486,10 @@ /* * Set up the return code ... * - * li v0, __NR_sigreturn + * li v0, __NR_rt_sigreturn * syscall */ - err |= __put_user(0x24020000 + __NR_sigreturn, + err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0); err |= __put_user(0x0000000c , frame->rs_code + 1); @@ -546,9 +543,9 @@ force_sig(SIGSEGV, current); } -static inline void -handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs *regs) { if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame(ka, regs, sig, oldset, info); @@ -566,8 +563,8 @@ } } -static inline void -syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +static inline void syscall_restart(struct pt_regs *regs, + struct k_sigaction *ka) { switch(regs->regs[0]) { case ERESTARTNOHAND: @@ -599,11 +596,6 @@ if (current->thread.mflags & MF_32BIT) { return do_signal32(oldset, regs); } -#endif - -#ifdef CONFIG_BINFMT_IRIX - if (current->personality != PER_LINUX) - return do_irix_signal(oldset, regs); #endif if (!oldset) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/signal32.c linux/arch/mips64/kernel/signal32.c --- v2.4.9/linux/arch/mips64/kernel/signal32.c Wed Jan 24 15:22:55 2001 +++ linux/arch/mips64/kernel/signal32.c Sun Sep 9 10:43:01 2001 @@ -152,10 +152,6 @@ sigset32_t *uset; sigset_t newset, saveset; -#if DEBUG_MIPS64 -printk("%s called.\n", __FUNCTION__); -#endif - save_static(®s); uset = (sigset32_t *) regs.regs[4]; if (get_sigset(&newset, uset)) @@ -185,10 +181,6 @@ sigset_t newset, saveset; size_t sigsetsize; -#if DEBUG_MIPS64 -printk("%s called.\n", __FUNCTION__); -#endif - save_static(®s); /* XXX Don't preclude handling different sized sigset_t's. */ sigsetsize = regs.regs[5]; @@ -359,10 +351,6 @@ struct sigframe *frame; sigset_t blocked; -#if DEBUG_MIPS64 -printk("%s called.\n", __FUNCTION__); -#endif - frame = (struct sigframe *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -400,7 +388,6 @@ struct rt_sigframe *frame; sigset_t set; stack_t st; -printk("%s called.\n", __FUNCTION__); frame = (struct rt_sigframe *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) @@ -580,10 +567,10 @@ /* * Set up the return code ... * - * li v0, __NR_Linux32_sigreturn + * li v0, __NR_Linux32_rt_sigreturn * syscall */ - err |= __put_user(0x24020000 + __NR_Linux32_sigreturn, + err |= __put_user(0x24020000 + __NR_Linux32_rt_sigreturn, frame->rs_code + 0); err |= __put_user(0x0000000c , frame->rs_code + 1); @@ -683,10 +670,6 @@ struct k_sigaction *ka; siginfo_t info; -#if DEBUG_MIPS64 -printk("%s: delivering signal.\n", current->comm); -#endif - if (!oldset) oldset = ¤t->blocked; @@ -785,9 +768,6 @@ if (regs->regs[0]) syscall_restart(regs, ka); /* Whee! Actually deliver the signal. */ -#if DEBUG_MIPS64 -printk("%s: delivering signal.\n", __FUNCTION__); -#endif handle_signal(signr, ka, &info, oldset, regs); return 1; } diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/syscall.c linux/arch/mips64/kernel/syscall.c --- v2.4.9/linux/arch/mips64/kernel/syscall.c Mon Mar 19 12:35:10 2001 +++ linux/arch/mips64/kernel/syscall.c Sun Sep 9 10:43:01 2001 @@ -3,8 +3,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 - 2000 by Ralf Baechle + * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. */ #include #include @@ -129,7 +130,7 @@ } asmlinkage int -sys_sysmips(int cmd, long arg1, int arg2, int arg3) +_sys_sysmips(int cmd, long arg1, int arg2, int arg3) { int *p; char *name; @@ -155,50 +156,9 @@ return 0; } - case MIPS_ATOMIC_SET: { - unsigned int tmp; - - p = (int *) arg1; - errno = verify_area(VERIFY_WRITE, p, sizeof(*p)); - if (errno) - return errno; - errno = 0; - - __asm__(".set\tpush\t\t\t# sysmips(MIPS_ATOMIC, ...)\n\t" - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "1:\tll\t%0, %4\n\t" - "2:\tmove\t$1, %3\n\t" - "3:\tsc\t$1, %1\n\t" - "beqzl\t$1, 2b\n\t" - "4:\t ll\t%0, %4\n\t" - ".set\tpop\n\t" - ".section\t.fixup,\"ax\"\n" - "5:\tli\t%2, 1\t\t\t# error\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - ".dword\t1b, 5b\n\t" - ".dword\t3b, 5b\n\t" - ".dword\t4b, 5b\n\t" - ".previous\n\t" - : "=&r" (tmp), "=o" (* (u32 *) p), "=r" (errno) - : "r" (arg2), "o" (* (u32 *) p), "2" (errno) - : "$1"); - - if (errno) - return -EFAULT; - - /* We're skipping error handling etc. */ - if (current->ptrace & PT_TRACESYS) - syscall_trace(); - - __asm__ __volatile__( - "move\t$29, %0\n\t" - "j\tret_from_sys_call" - : /* No outputs */ - : "r" (&cmd)); - /* Unreached */ - } + case MIPS_ATOMIC_SET: + printk(KERN_CRIT "How did I get here?\n"); + return -EINVAL; case MIPS_FIXADE: tmp = current->thread.mflags & ~3; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/traps.c linux/arch/mips64/kernel/traps.c --- v2.4.9/linux/arch/mips64/kernel/traps.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/traps.c Sun Sep 9 10:43:01 2001 @@ -258,58 +258,91 @@ printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm); } -static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) -{ - unsigned int *epc; - - epc = (unsigned int *) (unsigned long) regs->cp0_epc; - if (regs->cp0_cause & CAUSEF_BD) - epc++; - - if (verify_area(VERIFY_READ, epc, 4)) { - force_sig(SIGSEGV, current); - return 1; - } - *opcode = *epc; - - return 0; -} - void do_bp(struct pt_regs *regs) { unsigned int opcode, bcode; + unsigned int *epc; + siginfo_t info; + + epc = (unsigned int *) regs->cp0_epc + + ((regs->cp0_cause & CAUSEF_BD) != 0); + if (get_user(opcode, epc)) + goto sigsegv; /* * There is the ancient bug in the MIPS assemblers that the break * code starts left to bit 16 instead to bit 6 in the opcode. * Gas is bug-compatible ... */ - if (get_insn_opcode(regs, &opcode)) - return; bcode = ((opcode >> 16) & ((1 << 20) - 1)); /* * (A short test says that IRIX 5.3 sends SIGTRAP for all break * insns, even for break codes that indicate arithmetic failures. * Weird ...) + * But should we continue the brokenness??? --macro */ + switch (bcode) { + case 6: + case 7: + if (bcode == 7) + info.si_code = FPE_INTDIV; + else + info.si_code = FPE_INTOVF; + info.si_signo = SIGFPE; + info.si_errno = 0; + info.si_addr = (void *)compute_return_epc(regs); + force_sig_info(SIGFPE, &info, current); + break; + default: + force_sig(SIGTRAP, current); + } + force_sig(SIGTRAP, current); + return; + +sigsegv: + force_sig(SIGSEGV, current); } void do_tr(struct pt_regs *regs) { unsigned int opcode, bcode; + unsigned int *epc; + siginfo_t info; + + epc = (unsigned int *) regs->cp0_epc + + ((regs->cp0_cause & CAUSEF_BD) != 0); + if (get_user(opcode, epc)) + goto sigsegv; - if (get_insn_opcode(regs, &opcode)) - return; bcode = ((opcode >> 6) & ((1 << 20) - 1)); /* * (A short test says that IRIX 5.3 sends SIGTRAP for all break * insns, even for break codes that indicate arithmetic failures. * Wiered ...) + * But should we continue the brokenness??? --macro */ - force_sig(SIGTRAP, current); + switch (bcode) { + case 6: + case 7: + if (bcode == 7) + info.si_code = FPE_INTDIV; + else + info.si_code = FPE_INTOVF; + info.si_signo = SIGFPE; + info.si_errno = 0; + info.si_addr = (void *)compute_return_epc(regs); + force_sig_info(SIGFPE, &info, current); + break; + default: + force_sig(SIGTRAP, current); + } + return; + +sigsegv: + force_sig(SIGSEGV, current); } void do_ri(struct pt_regs *regs) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/kernel/unaligned.c linux/arch/mips64/kernel/unaligned.c --- v2.4.9/linux/arch/mips64/kernel/unaligned.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/kernel/unaligned.c Sun Sep 9 10:43:01 2001 @@ -72,6 +72,7 @@ * A store crossing a page boundary might be executed only partially. * Undo the partial store in this case. */ +#include #include #include #include @@ -378,7 +379,9 @@ return; } +#ifdef CONFIG_PROC_FS unsigned long unaligned_instructions; +#endif asmlinkage void do_ade(struct pt_regs *regs) { @@ -399,7 +402,9 @@ goto sigbus; emulate_load_store_insn(regs, regs->cp0_badvaddr, pc); +#ifdef CONFIG_PROC_FS unaligned_instructions++; +#endif return; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/csum_partial.S linux/arch/mips64/lib/csum_partial.S --- v2.4.9/linux/arch/mips64/lib/csum_partial.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/csum_partial.S Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: csum_partial.S,v 1.1 1999/08/21 21:43:00 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/csum_partial_copy.c linux/arch/mips64/lib/csum_partial_copy.c --- v2.4.9/linux/arch/mips64/lib/csum_partial_copy.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/csum_partial_copy.c Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: csum_partial_copy.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/dump_tlb.c linux/arch/mips64/lib/dump_tlb.c --- v2.4.9/linux/arch/mips64/lib/dump_tlb.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/lib/dump_tlb.c Sun Sep 9 10:43:01 2001 @@ -168,14 +168,12 @@ printk("\n"); } -void -dump_list_current(void *address) +void dump_list_current(void *address) { dump_list_process(current, address); } -unsigned int -vtop(void *address) +unsigned int vtop(void *address) { pgd_t *pgd; pmd_t *pmd; @@ -192,16 +190,17 @@ return paddr; } -void -dump16(unsigned long *p) +void dump16(unsigned long *p) { int i; for(i=0;i<8;i++) { printk("*%08lx == %08lx, ", - (unsigned long)p, (unsigned long)*p++); + (unsigned long)p, (unsigned long)*p); + p++; printk("*%08lx == %08lx\n", - (unsigned long)p, (unsigned long)*p++); + (unsigned long)p, (unsigned long)*p); + p++; } } diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/floppy-no.c linux/arch/mips64/lib/floppy-no.c --- v2.4.9/linux/arch/mips64/lib/floppy-no.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/floppy-no.c Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: floppy-no.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/ide-no.c linux/arch/mips64/lib/ide-no.c --- v2.4.9/linux/arch/mips64/lib/ide-no.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/ide-no.c Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: ide-no.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/ide-std.c linux/arch/mips64/lib/ide-std.c --- v2.4.9/linux/arch/mips64/lib/ide-std.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/ide-std.c Sun Sep 9 10:43:01 2001 @@ -1,12 +1,11 @@ -/* $Id: ide-std.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ - * +/* * 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. * * IDE routines for typical pc-like standard configurations. * - * Copyright (C) 1998, 1999 by Ralf Baechle + * Copyright (C) 1998, 1999, 2001 by Ralf Baechle */ #include #include @@ -60,6 +59,7 @@ } if (irq != NULL) *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; } static int std_ide_request_irq(unsigned int irq, diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/kbd-no.c linux/arch/mips64/lib/kbd-no.c --- v2.4.9/linux/arch/mips64/lib/kbd-no.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/kbd-no.c Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: kbd-no.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/kbd-std.c linux/arch/mips64/lib/kbd-std.c --- v2.4.9/linux/arch/mips64/lib/kbd-std.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/kbd-std.c Sun Sep 9 10:43:01 2001 @@ -1,5 +1,4 @@ -/* $Id: kbd-std.c,v 1.1 1999/08/21 21:43:01 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/memcpy.S linux/arch/mips64/lib/memcpy.S --- v2.4.9/linux/arch/mips64/lib/memcpy.S Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/lib/memcpy.S Sun Sep 9 10:43:02 2001 @@ -5,7 +5,7 @@ * * Unified implementation of memcpy, memmove and the __copy_user backend. * - * Copyright (C) 1998, 1999, 2000 Ralf Baechle + * Copyright (C) 1998, 1999, 2000, 2001 Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * * For __rmemcpy and memmove an exception is always a kernel bug, therefore @@ -238,10 +238,8 @@ andi ta2, a2, 0x40 move_128bytes: -#if (_MIPS_ISA == _MIPS_ISA_MIPS4) - pref 0, 2*128(a0) - pref 1, 2*128(a1) -#endif + PREF (0, 2*128(a0)) + PREF (1, 2*128(a1)) MOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) MOVE_BIGGERCHUNK(a1, a0, 0x40, ta0, ta1, ta3, t0) dsubu t8, t8, 0x01 @@ -454,16 +452,21 @@ .align 5 LEAF(memmove) - sltu ta0, a0, a1 # dst < src -> memcpy - bnez ta0, memcpy - daddu v0, a0, a2 - sltu ta0, v0, a1 # dst + len < src -> non- - bnez ta0, __memcpy # overlapping, can use memcpy + daddu t0, a0, a2 + sltu t0, a1, t0 # dst + len <= src -> memcpy + daddu t1, a1, a2 + sltu t1, a0, t1 # dst >= src + len -> memcpy + and t0, t1 + beqz t0, __memcpy + move v0, a0 /* return value */ beqz a2, r_out END(memmove) LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ + sltu t0, a1, a0 + beqz t0, r_end_bytes_up # src >= dst + nop daddu a0, a2 # dst = dst + len daddu a1, a2 # src = src + len @@ -615,6 +618,17 @@ dsubu a0, a0, 0x1 r_out: + jr ra + move a2, zero + +r_end_bytes_up: + lb t0, (a1) + dsubu a2, a2, 0x1 + sb t0, (a0) + daddu a1, a1, 0x1 + bnez a2, r_end_bytes_up + daddu a0, a0, 0x1 + jr ra move a2, zero diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/strlen_user.S linux/arch/mips64/lib/strlen_user.S --- v2.4.9/linux/arch/mips64/lib/strlen_user.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/strlen_user.S Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: strlen_user.S,v 1.2 1999/11/19 20:35:22 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/strncpy_user.S linux/arch/mips64/lib/strncpy_user.S --- v2.4.9/linux/arch/mips64/lib/strncpy_user.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/strncpy_user.S Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: strncpy_user.S,v 1.2 1999/11/19 20:35:23 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/lib/strnlen_user.S linux/arch/mips64/lib/strnlen_user.S --- v2.4.9/linux/arch/mips64/lib/strnlen_user.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/strnlen_user.S Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: strnlen_user.S,v 1.1 1999/11/19 20:35:23 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/math-emu/cp1emu.c linux/arch/mips64/math-emu/cp1emu.c --- v2.4.9/linux/arch/mips64/math-emu/cp1emu.c Tue Jul 3 17:08:18 2001 +++ linux/arch/mips64/math-emu/cp1emu.c Sun Sep 9 10:43:02 2001 @@ -53,7 +53,9 @@ #include #include +#include #include +#include #include #include #include @@ -851,11 +853,8 @@ current->thread.dsemul_epc = (unsigned long) cpc; current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1]; xcp->cp0_epc = VA_TO_REG & dsemul_insns[0]; + flush_cache_sigtramp((unsigned long) dsemul_insns); - /* What we'd really like to do is just flush the line(s) of the */ - /* icache containing the dsemulret instructions, but there's no */ - /* mechanism to do this yet... */ - flush_cache_all(); return SIGILL; /* force out of emulation loop */ } @@ -1708,6 +1707,9 @@ oldepc = xcp->cp0_epc; do { + if (current->need_resched) + schedule(); + prevepc = xcp->cp0_epc; insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err); if (err) { @@ -1718,6 +1720,9 @@ sig = cop1Emulate(xcptno, xcp, ctx); else xcp->cp0_epc += 4; /* skip nops */ + + if (mips_cpu.options & MIPS_CPU_FPU) + break; } while (xcp->cp0_epc > prevepc && sig == 0); /* SIGILL indicates a non-fpu instruction */ diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/atlas/Makefile linux/arch/mips64/mips-boards/atlas/Makefile --- v2.4.9/linux/arch/mips64/mips-boards/atlas/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/atlas/Makefile Sun Sep 9 10:43:02 2001 @@ -0,0 +1,42 @@ +# +# Carsten Langgaard, carstenl@mips.com +# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. +# +# ######################################################################## +# +# This program is free software; you can distribute it and/or modify it +# under the terms of the GNU General Public License (Version 2) as +# published by the Free Software Foundation. +# +# This program is distributed in the hope 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., +# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# ####################################################################### +# +# Makefile for the MIPS Atlas specific kernel interface routines +# under Linux. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: atlas.o + +O_TARGET := atlas.o + +obj-y := atlas_int.o atlas_rtc.o atlas_setup.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/atlas/atlas_int.c linux/arch/mips64/mips-boards/atlas/atlas_int.c --- v2.4.9/linux/arch/mips64/mips-boards/atlas/atlas_int.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/atlas/atlas_int.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,249 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Routines for generic manipulation of the interrupts found on the MIPS + * Atlas board. + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef CONFIG_REMOTE_DEBUG +#include +#endif + +struct atlas_ictrl_regs *atlas_hw0_icregs + = (struct atlas_ictrl_regs *)ATLAS_ICTRL_REGS_BASE; + +extern asmlinkage void mipsIRQ(void); +extern void do_IRQ(int irq, struct pt_regs *regs); + +unsigned long spurious_count = 0; +irq_desc_t irq_desc[NR_IRQS]; + +#if 0 +#define DEBUG_INT(x...) printk(x) +#else +#define DEBUG_INT(x...) +#endif + +void disable_atlas_irq(unsigned int irq_nr) +{ + atlas_hw0_icregs->intrsten = (1 << irq_nr); +} + +void enable_atlas_irq(unsigned int irq_nr) +{ + atlas_hw0_icregs->intseten = (1 << irq_nr); +} + +static unsigned int startup_atlas_irq(unsigned int irq) +{ + enable_atlas_irq(irq); + return 0; /* never anything pending */ +} + +#define shutdown_atlas_irq disable_atlas_irq + +#define mask_and_ack_atlas_irq disable_atlas_irq + +static void end_atlas_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_atlas_irq(irq); +} + +static struct hw_interrupt_type atlas_irq_type = { + "Atlas", + startup_atlas_irq, + shutdown_atlas_irq, + enable_atlas_irq, + disable_atlas_irq, + mask_and_ack_atlas_irq, + end_atlas_irq, + NULL +}; + +int get_irq_list(char *buf) +{ + int i, len = 0; + int num = 0; + struct irqaction *action; + + for (i = 0; i < ATLASINT_END; i++, num++) { + action = irq_desc[i].action; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", + num, kstat.irqs[0][num], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, " [hw0]\n"); + } + return len; +} + +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + struct irqaction *action; + + DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname); + + if (irq >= ATLASINT_END) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if(!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->dev_id = dev_id; + action->next = 0; + irq_desc[irq].action = action; + enable_atlas_irq(irq); + + return 0; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *action; + + if (irq >= ATLASINT_END) { + printk("Trying to free IRQ%d\n",irq); + return; + } + + action = irq_desc[irq].action; + irq_desc[irq].action = NULL; + disable_atlas_irq(irq); + kfree(action); +} + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +void atlas_hw0_irqdispatch(struct pt_regs *regs) +{ + struct irqaction *action; + unsigned long int_status; + int irq, cpu = smp_processor_id(); + + int_status = atlas_hw0_icregs->intstatus; + + /* if int_status == 0, then the interrupt has already been cleared */ + if (int_status == 0) + return; + + irq = ls1bit32(int_status); + action = irq_desc[irq].action; + + DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq); + + /* if action == NULL, then we don't have a handler for the irq */ + if ( action == NULL ) { + printk("No handler for hw0 irq: %i\n", irq); + spurious_count++; + return; + } + + irq_enter(cpu, irq); + kstat.irqs[0][irq]++; + action->handler(irq, action->dev_id, regs); + irq_exit(cpu, irq); + + return; +} + +unsigned long probe_irq_on (void) +{ + return 0; +} + + +int probe_irq_off (unsigned long irqs) +{ + return 0; +} + +#ifdef CONFIG_REMOTE_DEBUG +extern void breakpoint(void); +extern int remote_debug; +#endif + +void __init init_IRQ(void) +{ + int i; + + /* + * Mask out all interrupt by writing "1" to all bit position in + * the interrupt reset reg. + */ + atlas_hw0_icregs->intrsten = 0xffffffff; + + /* Now safe to set the exception vector. */ + set_except_vector(0, mipsIRQ); + + for (i = 0; i <= ATLASINT_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &atlas_irq_type; + } + +#ifdef CONFIG_REMOTE_DEBUG + if (remote_debug) { + set_debug_traps(); + breakpoint(); + } +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/atlas/atlas_rtc.c linux/arch/mips64/mips-boards/atlas/atlas_rtc.c --- v2.4.9/linux/arch/mips64/mips-boards/atlas/atlas_rtc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/atlas/atlas_rtc.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,58 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * RTC routines for Atlas style attached Dallas chip. + * + */ +#include +#include + + +static unsigned char atlas_rtc_read_data(unsigned long addr) +{ + volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG; + volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG; + + *rtc_adr_reg = addr; + + return *rtc_dat_reg; +} + +static void atlas_rtc_write_data(unsigned char data, unsigned long addr) +{ + volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG; + volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG; + + *rtc_adr_reg = addr; + *rtc_dat_reg = data; +} + +static int atlas_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops atlas_rtc_ops = { + &atlas_rtc_read_data, + &atlas_rtc_write_data, + &atlas_rtc_bcd_mode +}; + diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/atlas/atlas_setup.c linux/arch/mips64/mips-boards/atlas/atlas_setup.c --- v2.4.9/linux/arch/mips64/mips-boards/atlas/atlas_setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/atlas/atlas_setup.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,123 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Atlas specific setup, including init of the feature struct. + * + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) +extern void console_setup(char *, int *); +char serial_console[20]; +#endif + +#ifdef CONFIG_REMOTE_DEBUG +extern void rs_kgdb_hook(int); +extern void saa9730_kgdb_hook(void); +extern void breakpoint(void); +int remote_debug = 0; +#endif + +extern struct rtc_ops atlas_rtc_ops; + +extern void mips_reboot_setup(void); + +void __init atlas_setup(void) +{ +#ifdef CONFIG_REMOTE_DEBUG + int rs_putDebugChar(char); + char rs_getDebugChar(void); + int saa9730_putDebugChar(char); + char saa9730_getDebugChar(void); + extern int (*putDebugChar)(char); + extern char (*getDebugChar)(void); +#endif + char *argptr; + + current_cpu_data.asid_cache = ASID_FIRST_VERSION; + TLBMISS_HANDLER_SETUP(); + + ioport_resource.end = 0x7fffffff; + +#ifdef CONFIG_SERIAL_CONSOLE + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) { + int i = 0; + char *s = prom_getenv("modetty0"); + while(s[i] >= '0' && s[i] <= '9') + i++; + strcpy(serial_console, "ttyS0,"); + strncpy(serial_console + 6, s, i); + prom_printf("Config serial console: %s\n", serial_console); + console_setup(serial_console, NULL); + } +#endif + +#ifdef CONFIG_REMOTE_DEBUG + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { + int line; + argptr += strlen("kgdb=ttyS"); + if (*argptr != '0' && *argptr != '1') + printk("KGDB: Uknown serial line /dev/ttyS%c, " + "falling back to /dev/ttyS1\n", *argptr); + line = *argptr == '0' ? 0 : 1; + printk("KGDB: Using serial line /dev/ttyS%d for session\n", + line ? 1 : 0); + + if(line == 0) { + rs_kgdb_hook(line); + putDebugChar = rs_putDebugChar; + getDebugChar = rs_getDebugChar; + } else { + saa9730_kgdb_hook(); + putDebugChar = saa9730_putDebugChar; + getDebugChar = saa9730_getDebugChar; + } + + prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " + "please connect your debugger\n", line ? 1 : 0); + + remote_debug = 1; + /* Breakpoints and stuff are in atlas_irq_setup() */ + } +#endif + argptr = prom_getcmdline(); + + if ((argptr = strstr(argptr, "nofpu")) != NULL) + mips_cpu.options &= ~MIPS_CPU_FPU; + + rtc_ops = &atlas_rtc_ops; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/Makefile linux/arch/mips64/mips-boards/generic/Makefile --- v2.4.9/linux/arch/mips64/mips-boards/generic/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/Makefile Sun Sep 9 10:43:02 2001 @@ -0,0 +1,43 @@ +# +# Carsten Langgaard, carstenl@mips.com +# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. +# +# ######################################################################## +# +# This program is free software; you can distribute it and/or modify it +# under the terms of the GNU General Public License (Version 2) as +# published by the Free Software Foundation. +# +# This program is distributed in the hope 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., +# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# ####################################################################### +# +# Makefile for the MIPS boards generic routines under Linux. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: mipsboards.o + +O_TARGET := mipsboards.o + +obj-y := mipsIRQ.o pci.o reset.o display.o init.o \ + memory.o printf.o cmdline.o time.o +obj-$(CONFIG_REMOTE_DEBUG) += gdb_hook.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/cmdline.c linux/arch/mips64/mips-boards/generic/cmdline.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/cmdline.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/cmdline.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,71 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Kernel command line creation using the prom monitor (YAMON) argc/argv. + * + */ +#include +#include +#include + +#include + +/*#define DEBUG_CMDLINE*/ + +extern int prom_argc; +extern int *_prom_argv; + +/* + * A 32-bit PROM pass arguments and environment as 32-bit pointer. + * This macro take care of sign extension. + */ +#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)])) + +char arcs_cmdline[CL_SIZE]; + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + + +void __init prom_init_cmdline(void) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + strcpy(cp, prom_argv(actr)); + cp += strlen(prom_argv(actr)); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + *cp = '\0'; + +#ifdef DEBUG_CMDLINE + prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/display.c linux/arch/mips64/mips-boards/generic/display.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/display.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/display.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,47 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Display routines for display messages in MIPS boards ascii display. + * + */ + +#include + + +void mips_display_message(const char *str) +{ + volatile unsigned int *display = (void *)ASCII_DISPLAY_POS_BASE; + int i; + + for (i = 0; i <= 14; i=i+2) { + if (*str) + display[i] = *str++; + else + display[i] = ' '; + } +} + +void mips_display_word(unsigned int num) +{ + volatile unsigned int *display = (void *)ASCII_DISPLAY_WORD_BASE; + + *display = num; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/gdb_hook.c linux/arch/mips64/mips-boards/generic/gdb_hook.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/gdb_hook.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/gdb_hook.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,202 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * This is the interface to the remote debugger stub. + * + */ + +#include +#include + +#include +#include + +static struct serial_state rs_table[RS_TABLE_SIZE] = { + SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + +static struct async_struct kdb_port_info = {0}; + + +static __inline__ unsigned int serial_in(struct async_struct *info, int offset) +{ + return inb(info->port + offset); +} + +static __inline__ void serial_out(struct async_struct *info, int offset, + int value) +{ + outb(value, info->port+offset); +} + +void rs_kgdb_hook(int tty_no) { + int t; + struct serial_state *ser = &rs_table[tty_no]; + + kdb_port_info.state = ser; + kdb_port_info.magic = SERIAL_MAGIC; + kdb_port_info.port = ser->port; + kdb_port_info.flags = ser->flags; + + /* + * Clear all interrupts + */ + serial_in(&kdb_port_info, UART_LSR); + serial_in(&kdb_port_info, UART_RX); + serial_in(&kdb_port_info, UART_IIR); + serial_in(&kdb_port_info, UART_MSR); + + /* + * Now, initialize the UART + */ + serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ + if (kdb_port_info.flags & ASYNC_FOURPORT) { + kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS; + t = UART_MCR_DTR | UART_MCR_OUT1; + } else { + kdb_port_info.MCR + = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; + t = UART_MCR_DTR | UART_MCR_RTS; + } + + kdb_port_info.MCR = t; /* no interrupts, please */ + serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR); + + /* + * and set the speed of the serial port + * (currently hardwired to 9600 8N1 + */ + + /* baud rate is fixed to 9600 (is this sufficient?)*/ + t = kdb_port_info.state->baud_base / 9600; + /* set DLAB */ + serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB); + serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */ + serial_out(&kdb_port_info, UART_DLM, t >> 8); /* MS of divisor */ + /* reset DLAB */ + serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); +} + +int rs_putDebugChar(char c) +{ + + if (!kdb_port_info.state) { /* need to init device first */ + return 0; + } + + while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0) + ; + + serial_out(&kdb_port_info, UART_TX, c); + + return 1; +} + +char rs_getDebugChar(void) +{ + if (!kdb_port_info.state) { /* need to init device first */ + return 0; + } + + while (!(serial_in(&kdb_port_info, UART_LSR) & 1)) + ; + + return(serial_in(&kdb_port_info, UART_RX)); +} + + +#ifdef CONFIG_MIPS_ATLAS + +#include +#include + +#define INB(a) inb((unsigned long)a) +#define OUTB(x,a) outb(x,(unsigned long)a) + +/* + * This is the interface to the remote debugger stub + * if the Philips part is used for the debug port, + * called from the platform setup code. + * + * PCI init will not have been done yet, we make a + * universal assumption about the way the bootloader (YAMON) + * have located and set up the chip. + */ +static t_uart_saa9730_regmap *kgdb_uart = (void *)(ATLAS_SAA9730_REG + SAA9730_UART_REGS_ADDR); + +static int saa9730_kgdb_active = 0; + +void saa9730_kgdb_hook(void) +{ + volatile unsigned char t; + + /* + * Clear all interrupts + */ + t = INB(&kgdb_uart->Lsr); + t += INB(&kgdb_uart->Msr); + t += INB(&kgdb_uart->Thr_Rbr); + t += INB(&kgdb_uart->Iir_Fcr); + + /* + * Now, initialize the UART + */ + /* 8 data bits, one stop bit, no parity */ + OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr); + + /* baud rate is fixed to 9600 (is this sufficient?)*/ + OUTB(0, &kgdb_uart->BaudDivMsb); /* HACK - Assumes standard crystal */ + OUTB(23, &kgdb_uart->BaudDivLsb); /* HACK - known for MIPS Atlas */ + + /* Set RTS/DTR active */ + OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr); + saa9730_kgdb_active = 1; +} + +int saa9730_putDebugChar(char c) +{ + + if (!saa9730_kgdb_active) { /* need to init device first */ + return 0; + } + + while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE)) + ; + OUTB(c, &kgdb_uart->Thr_Rbr); + + return 1; +} + +char saa9730_getDebugChar(void) +{ + char c; + + if (!saa9730_kgdb_active) { /* need to init device first */ + return 0; + } + while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR)) + ; + + c = INB(&kgdb_uart->Thr_Rbr); + return(c); +} + +#endif diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/init.c linux/arch/mips64/mips-boards/generic/init.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/init.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,152 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * PROM library initialisation code. + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Environment variable */ +typedef struct +{ + char *name; + char *val; +}t_env_var; + +int prom_argc; +int *_prom_argv, *_prom_envp; + +/* + * A 32-bit PROM pass arguments and environment as 32-bit pointer. + * This macro take care of sign extension. + */ +#define prom_envp(index) ((char *)(((int *)(int)_prom_envp)[(index)])) + +int init_debug = 0; + +char *prom_getenv(char *envname) +{ + /* + * Return a pointer to the given environment variable. + * We're using 64-bit pointers, but all pointers in the PROM + * structures are only 32-bit, so we need some workarounds. + */ + int i, index=0; + + i = strlen(envname); + + while(prom_envp(index)) { + if(strncmp(envname, prom_envp(index), i) == 0) { + return(prom_envp(index+1)); + } + index += 2; + } + + return(NULL); +} + +static inline unsigned char str2hexnum(unsigned char c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + return 0; /* foo */ +} + +static inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for(i = 0; i < 6; i++) { + unsigned char num; + + if((*str == '.') || (*str == ':')) + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } +} + +int get_ethernet_addr(char *ethernet_addr) +{ + char *ethaddr_str; + + ethaddr_str = prom_getenv("ethaddr"); + if (!ethaddr_str) { + printk("ethaddr not set in boot prom\n"); + return -1; + } + str2eaddr(ethernet_addr, ethaddr_str); + + if (init_debug > 1) + { + int i; + printk("get_ethernet_addr: "); + for (i=0; i<5; i++) + printk("%02x:", (unsigned char)*(ethernet_addr+i)); + printk("%02x\n", *(ethernet_addr+i)); + } + + return 0; +} + +int __init prom_init(int argc, char **argv, char **envp) +{ + prom_argc = argc; + _prom_argv = (int *)argv; + _prom_envp = (int *)envp; + + mips_display_message("LINUX"); + + /* + * Setup the North bridge to do Master byte-lane swapping when + * running in bigendian. + */ +#if defined(__MIPSEL__) + GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT | + GT_PCI0_CMD_SBYTESWAP_BIT); +#else + GT_WRITE(GT_PCI0_CMD_OFS, 0); +#endif + +#if defined(CONFIG_MIPS_MALTA) + mips_io_port_base = MALTA_PORT_BASE; +#else + mips_io_port_base = KSEG1; +#endif + + setup_prom_printf(0); + prom_printf("\nLINUX started...\n"); + prom_init_cmdline(); + prom_meminit(); + + return 0; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/memory.c linux/arch/mips64/mips-boards/generic/memory.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/memory.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/memory.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,263 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * PROM library functions for acquiring/using memory descriptors given to + * us from the YAMON. + * + */ +#include +#include +#include +#include + +#include +#include + +#include + +/*#define DEBUG*/ + +enum yamon_memtypes { + yamon_dontuse, + yamon_prom, + yamon_free, +}; +struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; + +#define MEMTYPE_DONTUSE 0 +#define MEMTYPE_PROM 1 +#define MEMTYPE_FREE 2 + +#ifdef DEBUG +static char *mtypes[3] = { + "Dont use memory", + "YAMON PROM memory", + "Free memmory", +}; +#endif + +/* References to section boundaries */ +extern char _end; + +#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) + +struct prom_pmemblock * __init prom_getmdesc(void) +{ + char *memsize_str; + unsigned int memsize; + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + prom_printf("memsize not set in boot prom, set to default (32Mb)\n"); + memsize = 0x02000000; + } else { +#ifdef DEBUG + prom_printf("prom_memsize = %s\n", memsize_str); +#endif + memsize = simple_strtol(memsize_str, NULL, 0); + } + + memset(mdesc, 0, sizeof(mdesc)); + + mdesc[0].type = yamon_dontuse; + mdesc[0].base = 0x00000000; + mdesc[0].size = 0x00001000; + + mdesc[1].type = yamon_prom; + mdesc[1].base = 0x00001000; + mdesc[1].size = 0x000ef000; + +#if (CONFIG_MIPS_MALTA) + /* + * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the + * south bridge and PCI access always forwarded to the ISA Bus and + * BIOSCS# is always generated. + * This mean that this area can't be used as DMA memory for PCI + * devices. + */ + mdesc[2].type = yamon_dontuse; + mdesc[2].base = 0x000f0000; + mdesc[2].size = 0x00010000; +#else + mdesc[2].type = yamon_prom; + mdesc[2].base = 0x000f0000; + mdesc[2].size = 0x00010000; +#endif + + mdesc[3].type = yamon_dontuse; + mdesc[3].base = 0x00100000; + mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base; + + mdesc[4].type = yamon_free; + mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); + mdesc[4].size = memsize - mdesc[4].base; + + return &mdesc[0]; +} + +int __init page_is_ram(unsigned long pagenr) +{ + if ((pagenr << PAGE_SHIFT) < mdesc[4].base + mdesc[4].size) + return 1; + + return 0; +} + +static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS]; + +static int __init prom_memtype_classify (unsigned int type) +{ + switch (type) { + case yamon_free: + return MEMTYPE_FREE; + case yamon_prom: + return MEMTYPE_PROM; + default: + return MEMTYPE_DONTUSE; + } +} + +static inline unsigned long find_max_low_pfn(void) +{ + struct prom_pmemblock *p, *highest; + unsigned long pfn; + + p = pblocks; + highest = 0; + while (p->size != 0) { + if (!highest || p->base > highest->base) + highest = p; + p++; + } + + pfn = (highest->base + highest->size) >> PAGE_SHIFT; +#ifdef DEBUG + prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn); +#endif + return pfn; +} + +static inline struct prom_pmemblock *find_largest_memblock(void) +{ + struct prom_pmemblock *p, *largest; + + p = pblocks; + largest = 0; + while (p->size != 0) { + if (!largest || p->size > largest->size) + largest = p; + p++; + } + + return largest; +} + +void __init prom_meminit(void) +{ + struct prom_pmemblock *largest, *p; + unsigned long bootmap_size; + int totram; + int i = 0; + +#ifdef DEBUG + prom_printf("YAMON MEMORY DESCRIPTOR dump:\n"); + p = prom_getmdesc(); + while (p->size) { + prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n", + i, p, p->base, p->size, mtypes[p->type]); + p++; + i++; + } +#endif + totram = 0; + i = 0; + p = prom_getmdesc(); + + while (p->size) { + pblocks[i].type = prom_memtype_classify (p->type); + pblocks[i].base = p->base; + pblocks[i].size = p->size; + switch (pblocks[i].type) { + case MEMTYPE_FREE: + totram += pblocks[i].size; +#ifdef DEBUG + prom_printf("free_chunk[%d]: base=%08lx size=%d\n", + i, pblocks[i].base, pblocks[i].size); +#endif + i++; + break; + case MEMTYPE_PROM: +#ifdef DEBUG + prom_printf("prom_chunk[%d]: base=%08lx size=%d\n", + i, pblocks[i].base, pblocks[i].size); +#endif + i++; + break; + default: + break; + } + p++; + } + pblocks[i].base = 0xdeadbeef; + pblocks[i].size = 0; /* indicates last elem. of array */ + + max_low_pfn = find_max_low_pfn(); + largest = find_largest_memblock(); + bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn); + + for (i = 0; pblocks[i].size; i++) + if (pblocks[i].type == MEMTYPE_FREE) + free_bootmem(pblocks[i].base, pblocks[i].size); + + /* This test is simpleminded. It will fail if the bootmem bitmap + falls into multiple adjacent PROM memory areas. */ + if (bootmap_size > largest->size) { + prom_printf("CRITIAL: overwriting PROM data.\n"); + BUG(); + } + + /* Reserve the memory bootmap itself */ + reserve_bootmem(largest->base, bootmap_size); + printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", + totram, (totram/1024), (totram/1024/1024)); +} + +void prom_free_prom_memory (void) +{ + struct prom_pmemblock *p; + unsigned long freed = 0; + unsigned long addr; + + for (p = pblocks; p->size != 0; p++) { + if (p->type != MEMTYPE_PROM) + continue; + + addr = p->base; + while (addr < p->base + p->size) { + ClearPageReserved(virt_to_page(__va(addr))); + set_page_count(virt_to_page(__va(addr)), 1); + free_page(__va(addr)); + addr += PAGE_SIZE; + freed += PAGE_SIZE; + } + } + printk("Freeing prom memory: %ldkb freed\n", freed >> 10); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/mipsIRQ.S linux/arch/mips64/mips-boards/generic/mipsIRQ.S --- v2.4.9/linux/arch/mips64/mips-boards/generic/mipsIRQ.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/mipsIRQ.S Sun Sep 9 10:43:02 2001 @@ -0,0 +1,122 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Interrupt exception dispatch code. + * + */ +#include + +#include +#include +#include +#include + +/* A lot of complication here is taken away because: + * + * 1) We handle one interrupt and return, sitting in a loop and moving across + * all the pending IRQ bits in the cause register is _NOT_ the answer, the + * common case is one pending IRQ so optimize in that direction. + * + * 2) We need not check against bits in the status register IRQ mask, that + * would make this routine slow as hell. + * + * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in + * between like BSD spl() brain-damage. + * + * Furthermore, the IRQs on the MIPS board look basically (barring software + * IRQs which we don't use at all and all external interrupt sources are + * combined together on hardware interrupt 0 (MIPS IRQ 2)) like: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Combined hardware interrupt (hw0) + * 3 Hardware (ignored) + * 4 Hardware (ignored) + * 5 Hardware (ignored) + * 6 Hardware (ignored) + * 7 R4k timer (what we use) + * + * We handle the IRQ according to _our_ priority which is: + * + * Highest ---- R4k Timer + * Lowest ---- Combined hardware interrupt + * + * then we just return, if multiple IRQs are pending then we will just take + * another exception, big deal. + */ + + .text + .set noreorder + .set noat + .align 5 + NESTED(mipsIRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + mfc0 s0, CP0_CAUSE # get irq mask + + /* First we check for r4k counter/timer IRQ. */ + andi a0, s0, CAUSEF_IP7 + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt + + /* Wheee, a timer interrupt. */ + move a0, sp + jal mips_timer_interrupt + nop + + j ret_from_irq + nop + +1: + beq a0, zero, 1f + nop + + /* Wheee, combined hardware level zero interrupt. */ +#if defined(CONFIG_MIPS_ATLAS) + jal atlas_hw0_irqdispatch +#elif defined(CONFIG_MIPS_MALTA) + jal malta_hw0_irqdispatch +#else +#error "MIPS board not supported\n" +#endif + move a0, sp # delay slot + + j ret_from_irq + nop # delay slot + +1: + /* + * Here by mistake? This is possible, what can happen is that by the + * time we take the exception the IRQ pin goes low, so just leave if + * this is the case. + */ + move a1,s0 + PRINT("Got interrupt: c0_cause = %08x\n") + mfc0 a1, CP0_EPC + PRINT("c0_epc = %08x\n") + + j ret_from_irq + nop + END(mipsIRQ) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/pci.c linux/arch/mips64/mips-boards/generic/pci.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/pci.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,337 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * MIPS boards specific PCI support. + * + */ +#include + +#ifdef CONFIG_PCI + +#include +#include +#include +#include + +#include +#include +#ifdef CONFIG_MIPS_MALTA +#include +#endif + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +static int +mips_pcibios_config_access(unsigned char access_type, struct pci_dev *dev, + unsigned char where, u32 *data) +{ + unsigned char bus = dev->bus->number; + unsigned char dev_fn = dev->devfn; + u32 intr; + + if ((bus == 0) && (dev_fn >= PCI_DEVFN(31,0))) + return -1; /* Because of a bug in the galileo (for slot 31). */ + + /* Clear cause register bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + /* Setup address */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (dev_fn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + if (access_type == PCI_ACCESS_WRITE) { + if (bus == 0 && dev_fn == 0) { + /* + * Galileo is acting differently than other devices. + */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); + } else { + GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data); + } + } else { + if (bus == 0 && dev_fn == 0) { + /* + * Galileo is acting differently than other devices. + */ + GT_READ(GT_PCI0_CFGDATA_OFS, *data); + } else { + GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data); + } + } + + /* Check for master or target abort */ + GT_READ(GT_INTRCAUSE_OFS, intr); + + if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) + { + /* Error occured */ + + /* Clear bits */ + GT_WRITE( GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT) ); + + return -1; + } + + return 0; +} + + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int +mips_pcibios_read_config_byte (struct pci_dev *dev, int where, u8 *val) +{ + u32 data = 0; + + if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) + return -1; + + *val = (data >> ((where & 3) << 3)) & 0xff; + + return PCIBIOS_SUCCESSFUL; +} + + +static int +mips_pcibios_read_config_word (struct pci_dev *dev, int where, u16 *val) +{ + u32 data = 0; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) + return -1; + + *val = (data >> ((where & 3) << 3)) & 0xffff; + + return PCIBIOS_SUCCESSFUL; +} + +static int +mips_pcibios_read_config_dword (struct pci_dev *dev, int where, u32 *val) +{ + u32 data = 0; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) + return -1; + + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + + +static int +mips_pcibios_write_config_byte (struct pci_dev *dev, int where, u8 val) +{ + u32 data = 0; + + if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) + return -1; + + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +static int +mips_pcibios_write_config_word (struct pci_dev *dev, int where, u16 val) +{ + u32 data = 0; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) + return -1; + + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data)) + return -1; + + + return PCIBIOS_SUCCESSFUL; +} + +static int +mips_pcibios_write_config_dword(struct pci_dev *dev, int where, u32 val) +{ + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &val)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops mips_pci_ops = { + mips_pcibios_read_config_byte, + mips_pcibios_read_config_word, + mips_pcibios_read_config_dword, + mips_pcibios_write_config_byte, + mips_pcibios_write_config_word, + mips_pcibios_write_config_dword +}; + +void __init pcibios_init(void) +{ +#ifdef CONFIG_MIPS_MALTA + struct pci_dev *pdev; + unsigned char reg_val; +#endif + + printk("PCI: Probing PCI hardware on host bus 0.\n"); + pci_scan_bus(0, &mips_pci_ops, NULL); + + /* + * Due to a bug in the Galileo system controller, we need to setup + * the PCI BAR for the Galileo internal registers. + * This should be done in the bios/bootprom and will be fixed in + * a later revision of YAMON (the MIPS boards boot prom). + */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */ + (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 device */ + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0 */ + ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4 */ + GT_PCI0_CFGADDR_CONFIGEN_BIT ); + + /* Perform the write */ + GT_WRITE( GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE)); + +#ifdef CONFIG_MIPS_MALTA + pci_for_each_dev(pdev) { + if ((pdev->vendor == PCI_VENDOR_ID_INTEL) + && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB) + && (PCI_SLOT(pdev->devfn) == 0x0a)) { + /* + * IDE Decode enable. + */ + pci_read_config_byte(pdev, 0x41, ®_val); + pci_write_config_byte(pdev, 0x41, reg_val | 0x80); + pci_read_config_byte(pdev, 0x43, ®_val); + pci_write_config_byte(pdev, 0x43, reg_val | 0x80); + } + + if ((pdev->vendor == PCI_VENDOR_ID_INTEL) + && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB_0) + && (PCI_SLOT(pdev->devfn) == 0x0a)) { + /* + * Set top of main memory accessible by ISA or DMA + * devices to 16 Mb. + */ + pci_read_config_byte(pdev, 0x69, ®_val); + pci_write_config_byte(pdev, 0x69, reg_val | 0xf0); + } + } + + /* + * Activate Floppy Controller in the SMSC FDC37M817 Super I/O + * Controller. + * This should be done in the bios/bootprom and will be fixed in + * a later revision of YAMON (the MIPS boards boot prom). + */ + /* Entering config state. */ + SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); + + /* Activate floppy controller. */ + SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG); + SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG); + SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG); + SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG); + + /* Exit config state. */ + SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG); +#endif +} + +int __init +pcibios_enable_device(struct pci_dev *dev) +{ + /* Not needed, since we enable all devices at startup. */ + return 0; +} + +void __init +pcibios_align_resource(void *data, struct resource *res, unsigned long size) +{ +} + +char * __init +pcibios_setup(char *str) +{ + /* Nothing to do for now. */ + + return str; +} + +struct pci_fixup pcibios_fixups[] = { + { 0 } +}; + +void __init +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + unsigned long where, size; + u32 reg; + + 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); +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} + +/* + * Called after each bus is probed, but before its children + * are examined. + */ +void __init pcibios_fixup_bus(struct pci_bus *b) +{ + pci_read_bridge_bases(b); +} + +#endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/printf.c linux/arch/mips64/mips-boards/generic/printf.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/printf.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/printf.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,140 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Putting things on the screen/serial line using YAMONs facilities. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_MIPS_ATLAS +/* + * Atlas registers are memory mapped on 64-bit aligned boundaries and + * only word access are allowed. + * When reading the UART 8 bit registers only the LSB are valid. + */ +unsigned int atlas_serial_in(struct async_struct *info, int offset) +{ + return (*(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) & 0xff); +} + +void atlas_serial_out(struct async_struct *info, int offset, int value) +{ + *(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) = value; +} + +#define serial_in atlas_serial_in +#define serial_out atlas_serial_out + +#else + +static unsigned int serial_in(struct async_struct *info, int offset) +{ + return inb(info->port + offset); +} + +static void serial_out(struct async_struct *info, int offset, + int value) +{ + outb(value, info->port + offset); +} +#endif + +static struct serial_state rs_table[] = { + SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + +/* + * Hooks to fake "prom" console I/O before devices + * are fully initialized. + */ +static struct async_struct prom_port_info = {0}; + +void __init setup_prom_printf(int tty_no) { + struct serial_state *ser = &rs_table[tty_no]; + + prom_port_info.state = ser; + prom_port_info.magic = SERIAL_MAGIC; + prom_port_info.port = ser->port; + prom_port_info.flags = ser->flags; + + /* No setup of UART - assume YAMON left in sane state */ +} + +int putPromChar(char c) +{ + if (!prom_port_info.state) { /* need to init device first */ + return 0; + } + + while ((serial_in(&prom_port_info, UART_LSR) & UART_LSR_THRE) == 0) + ; + + serial_out(&prom_port_info, UART_TX, c); + + return 1; +} + +char getPromChar(void) +{ + if (!prom_port_info.state) { /* need to init device first */ + return 0; + } + + while (!(serial_in(&prom_port_info, UART_LSR) & 1)) + ; + + return(serial_in(&prom_port_info, UART_RX)); +} + +static char buf[1024]; + +void __init prom_printf(char *fmt, ...) +{ + va_list args; + int l; + char *p, *buf_end; + long flags; + + int putPromChar(char); + + /* Low level, brute force, not SMP safe... */ + save_and_cli(flags); + va_start(args, fmt); + l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */ + va_end(args); + + buf_end = buf + l; + + for (p = buf; p < buf_end; p++) { + /* Crude cr/nl handling is better than none */ + if(*p == '\n')putPromChar('\r'); + putPromChar(*p); + } + restore_flags(flags); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/reset.c linux/arch/mips64/mips-boards/generic/reset.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/reset.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,61 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Reset the MIPS boards. + * + */ +#include + +#include +#if defined(CONFIG_MIPS_ATLAS) +#include +#endif + +void machine_restart(char *command) __attribute__((noreturn)); +void machine_halt(void) __attribute__((noreturn)); +#if defined(CONFIG_MIPS_ATLAS) +void machine_power_off(void) __attribute__((noreturn)); +#endif + +void machine_restart(char *command) +{ + volatile unsigned int *softres_reg = (void *)SOFTRES_REG; + + *softres_reg = GORESET; +} + +void machine_halt(void) +{ + volatile unsigned int *softres_reg = (void *)SOFTRES_REG; + + *softres_reg = GORESET; +} + +void machine_power_off(void) +{ +#if defined(CONFIG_MIPS_ATLAS) + volatile unsigned int *psustby_reg = (void *)ATLAS_PSUSTBY_REG; + + *psustby_reg = ATLAS_GOSTBY; +#else + machine_halt(); +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/generic/time.c linux/arch/mips64/mips-boards/generic/time.c --- v2.4.9/linux/arch/mips64/mips-boards/generic/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/generic/time.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,399 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Setting up the clock on the MIPS boards. + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +extern volatile unsigned long wall_jiffies; +static long last_rtc_update = 0; +unsigned long missed_heart_beats = 0; + +static unsigned long r4k_offset; /* Amount to increment compare reg each time */ +static unsigned long r4k_cur; /* What counter should be at next timer irq */ +extern rwlock_t xtime_lock; + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + +#if defined(CONFIG_MIPS_ATLAS) +static char display_string[] = " LINUX ON ATLAS "; +#endif +#if defined(CONFIG_MIPS_MALTA) +static char display_string[] = " LINUX ON MALTA "; +#endif +static unsigned int display_count = 0; +#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) + +static unsigned int timer_tick_count=0; + + +static inline void ack_r4ktimer(unsigned long newval) +{ + write_32bit_cp0_register(CP0_COMPARE, newval); +} + + +/* + * In order to set the CMOS clock precisely, set_rtc_mmss has to be + * called 500 ms after the second nowtime has started, because when + * nowtime is written into the registers of the CMOS clock, it will + * jump to the next second precisely 500 ms later. Check the Motorola + * MC146818A or Dallas DS12887 data sheet for details. + * + * BUG: This routine does not handle hour overflow properly; it just + * sets the minutes. Usually you won't notice until after reboot! + */ +static int set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + CMOS_WRITE(real_seconds,RTC_SECONDS); + CMOS_WRITE(real_minutes,RTC_MINUTES); + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return retval; +} + +/* + * There are a lot of conceptually broken versions of the MIPS timer interrupt + * handler floating around. This one is rather different, but the algorithm + * is provably more robust. + */ +void mips_timer_interrupt(struct pt_regs *regs) +{ + int irq = 7; + + if (r4k_offset == 0) + goto null; + + do { + kstat.irqs[0][irq]++; + do_timer(regs); + + /* Historical comment/code: + * RTC time of day s updated approx. every 11 + * minutes. Because of how the numbers work out + * we need to make absolutely sure we do this update + * within 500ms before the * next second starts, + * thus the following code. + */ + read_lock(&xtime_lock); + if ((time_status & STA_UNSYNC) == 0 + && xtime.tv_sec > last_rtc_update + 660 + && xtime.tv_usec >= 500000 - (tick >> 1) + && xtime.tv_usec <= 500000 + (tick >> 1)) + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + /* do it again in 60 s */ + last_rtc_update = xtime.tv_sec - 600; + read_unlock(&xtime_lock); + + if ((timer_tick_count++ % HZ) == 0) { + mips_display_message(&display_string[display_count++]); + if (display_count == MAX_DISPLAY_COUNT) + display_count = 0; + } + + r4k_cur += r4k_offset; + ack_r4ktimer(r4k_cur); + + } while (((unsigned int)read_32bit_cp0_register(CP0_COUNT) + - (unsigned int)r4k_cur) < 0x7fffffff); + + return; + +null: + ack_r4ktimer(0); +} + +/* + * Figure out the r4k offset, the amount to increment the compare + * register for each time tick. + * Use the RTC to calculate offset. + */ +static unsigned long __init cal_r4koff(void) +{ + unsigned long count; + unsigned int flags; + + __save_and_cli(flags); + + /* Start counter exactly on falling edge of update flag */ + while (CMOS_READ(RTC_REG_A) & RTC_UIP); + while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); + + /* Start r4k counter. */ + write_32bit_cp0_register(CP0_COUNT, 0); + + /* Read counter exactly on falling edge of update flag */ + while (CMOS_READ(RTC_REG_A) & RTC_UIP); + while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); + + count = read_32bit_cp0_register(CP0_COUNT); + + /* restore interrupts */ + __restore_flags(flags); + + return (count / HZ); +} + +static unsigned long __init get_mips_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + unsigned char save_control; + + save_control = CMOS_READ(RTC_CONTROL); + + /* Freeze it. */ + CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL); + + /* Read regs. */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + + if (!(save_control & RTC_24H)) + { + if ((hour & 0xf) == 0xc) + hour &= 0x80; + if (hour & 0x80) + hour = (hour & 0xf) + 12; + } + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + + /* Unfreeze clock. */ + CMOS_WRITE(save_control, RTC_CONTROL); + + if ((year += 1900) < 1970) + year += 100; + + return mktime(year, mon, day, hour, min, sec); +} + +void __init time_init(void) +{ + unsigned int est_freq, flags; + + /* Set Data mode - binary. */ + CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); + + printk("calculating r4koff... "); + r4k_offset = cal_r4koff(); + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + + est_freq = 2*r4k_offset*HZ; + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); + r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); + + write_32bit_cp0_register(CP0_COMPARE, r4k_cur); + set_cp0_status(ST0_IM, ALLINTS); + + /* Read time from the RTC chipset. */ + write_lock_irqsave (&xtime_lock, flags); + xtime.tv_sec = get_mips_time(); + xtime.tv_usec = 0; + write_unlock_irqrestore(&xtime_lock, flags); +} + +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) +#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) + +/* Cycle counter value at the previous timer interrupt.. */ + +static unsigned int timerhi = 0, timerlo = 0; + +/* + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_fast_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies=0; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient=0; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY) + :"$1"); + cached_quotient = quotient; + } + + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned int flags; + + read_lock_irqsave (&xtime_lock, flags); + *tv = xtime; + tv->tv_usec += do_fast_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. jiffies - wall_jiffies + * is nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; + + read_unlock_irqrestore (&xtime_lock, flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +void do_settimeofday(struct timeval *tv) +{ + write_lock_irq (&xtime_lock); + + /* This is revolting. We need to set the xtime.tv_usec correctly. + * However, the value in this location is is value at the last tick. + * Discover what correction gettimeofday would have done, and then + * undo it! + */ + tv->tv_usec -= do_fast_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + + write_unlock_irq (&xtime_lock); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/malta/Makefile linux/arch/mips64/mips-boards/malta/Makefile --- v2.4.9/linux/arch/mips64/mips-boards/malta/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/malta/Makefile Sun Sep 9 10:43:02 2001 @@ -0,0 +1,42 @@ +# +# Carsten Langgaard, carstenl@mips.com +# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. +# +# ######################################################################## +# +# This program is free software; you can distribute it and/or modify it +# under the terms of the GNU General Public License (Version 2) as +# published by the Free Software Foundation. +# +# This program is distributed in the hope 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., +# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# ####################################################################### +# +# Makefile for the MIPS Malta specific kernel interface routines +# under Linux. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: malta.o + +O_TARGET := malta.o + +obj-y := malta_int.o malta_rtc.o malta_setup.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/malta/malta_int.c linux/arch/mips64/mips-boards/malta/malta_int.c --- v2.4.9/linux/arch/mips64/mips-boards/malta/malta_int.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/malta/malta_int.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,383 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Routines for generic manipulation of the interrupts found on the MIPS + * Malta board. + * The interrupt controller is located in the South Bridge a PIIX4 device + * with two internal 82C95 interrupt controllers. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern asmlinkage void mipsIRQ(void); + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; +unsigned long spurious_count = 0; + +static struct irqaction *hw0_irq_action[MALTAINT_END] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL +}; + +static struct irqaction r4ktimer_action = { + NULL, 0, 0, "R4000 timer/counter", NULL, NULL, +}; + +static struct irqaction *irq_action[8] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, &r4ktimer_action +}; + +#if 0 +#define DEBUG_INT(x...) printk(x) +#else +#define DEBUG_INT(x...) +#endif + +/* + * This contains the interrupt mask for both 82C59 interrupt controllers. + */ +static unsigned int cached_int_mask = 0xffff; + + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + if(irq_nr >= MALTAINT_END) { + printk("whee, invalid irq_nr %d\n", irq_nr); + panic("IRQ, you lose..."); + } + + save_and_cli(flags); + cached_int_mask |= (1 << irq_nr); + if (irq_nr & 8) { + outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); + } else { + outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); + } + restore_flags(flags); +} + + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + if(irq_nr >= MALTAINT_END) { + printk("whee, invalid irq_nr %d\n", irq_nr); + panic("IRQ, you lose..."); + } + + save_and_cli(flags); + cached_int_mask &= ~(1 << irq_nr); + if (irq_nr & 8) { + outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); + + /* Enable irq 2 (cascade interrupt). */ + cached_int_mask &= ~(1 << 2); + outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); + } else { + outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); + } + restore_flags(flags); +} + + +int get_irq_list(char *buf) +{ + int i, len = 0; + int num = 0; + struct irqaction *action; + + for (i = 0; i < 8; i++, num++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", + num, kstat.irqs[0][num], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, " [on-chip]\n"); + } + for (i = 0; i < MALTAINT_END; i++, num++) { + action = hw0_irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", + num, kstat.irqs[0][num], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, " [hw0]\n"); + } + return len; +} + +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + struct irqaction *action; + int retval; + + DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname); + + if (irq >= MALTAINT_END) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if(!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->dev_id = dev_id; + action->next = 0; + + retval = setup_irq(irq, action); + if (retval) + kfree(action); + + return retval; +} + + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *action, **p; + + if (irq >= MALTAINT_END) { + printk("Trying to free IRQ%d\n",irq); + return; + } + + for (p = &hw0_irq_action[irq]; (action = *p) != NULL; + p = &action->next) + { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + *p = action->next; + kfree(action); + if (!hw0_irq_action[irq]) + disable_irq(irq); + return; + } + printk("Trying to free IRQ%d\n",irq); +} + +void __init init_IRQ(void) +{ + irq_setup(); +} + +static int setup_irq(unsigned int irq, struct irqaction * new) +{ + int shared = 0; + struct irqaction *old, **p; + + p = &hw0_irq_action[irq]; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + *p = new; + if (!shared) + enable_irq(irq); + + return 0; +} + +static inline int get_int(int *irq) +{ + /* + * Determine highest priority pending interrupt by performing + * a PCI Interrupt Acknowledge cycle. + */ + GT_READ(GT_PCI0_IACK_OFS, *irq); + *irq &= 0xFF; + + /* + * IRQ7 is used to detect spurious interrupts. + * The interrupt acknowledge cycle returns IRQ7, if no + * interrupts is requested. + * We can differentiate between this situation and a + * "Normal" IRQ7 by reading the ISR. + */ + if (*irq == 7) + { + outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, PIIX4_ICTLR1_OCW3); + if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) + return -1; /* Spurious interrupt. */ + } + + return 0; +} + +static inline void ack_int(int irq) +{ + if (irq & 8) { + /* Specific EOI to cascade */ + outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI | PIIX4_OCW2_ILS_2, + PIIX4_ICTLR1_OCW2); + + /* Non specific EOI to cascade */ + outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR2_OCW2); + } else { + /* Non specific EOI to cascade */ + outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR1_OCW2); + } +} + +void malta_hw0_irqdispatch(struct pt_regs *regs) +{ + struct irqaction *action; + int irq=0, cpu = smp_processor_id(); + + DEBUG_INT("malta_hw0_irqdispatch\n"); + + if (get_int(&irq)) + return; /* interrupt has already been cleared */ + + disable_irq(irq); + ack_int(irq); + + DEBUG_INT("malta_hw0_irqdispatch: irq=%d\n", irq); + action = hw0_irq_action[irq]; + + /* + * if action == NULL, then we don't have a handler + * for the irq + */ + if ( action == NULL ) + return; + + irq_enter(cpu, irq); + kstat.irqs[0][irq + 8]++; + do { + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + + enable_irq(irq); + irq_exit(cpu, irq); +} + + +unsigned long probe_irq_on (void) +{ + unsigned int i, irqs = 0; + unsigned long delay; + + /* first, enable any unassigned irqs */ + for (i = MALTAINT_END-1; i > 0; i--) { + if (!hw0_irq_action[i]) { + enable_irq(i); + irqs |= (1 << i); + } + } + + /* wait for spurious interrupts to mask themselves out again */ + for (delay = jiffies + HZ/10; time_before(jiffies, delay); ) + /* about 100ms delay */; + + /* now filter out any obviously spurious interrupts */ + return irqs & ~cached_int_mask; +} + + +int probe_irq_off (unsigned long irqs) +{ + unsigned int i; + + irqs &= cached_int_mask; + if (!irqs) + return 0; + i = ffz(~irqs); + if (irqs != (irqs & (1 << i))) + i = -i; + + return i; +} + + +void __init maltaint_init(void) +{ + /* + * Mask out all interrupt by writing "1" to all bit position in + * the IMR register. + */ + outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); + outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); + + /* Now safe to set the exception vector. */ + set_except_vector(0, mipsIRQ); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/malta/malta_rtc.c linux/arch/mips64/mips-boards/malta/malta_rtc.c --- v2.4.9/linux/arch/mips64/mips-boards/malta/malta_rtc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/malta/malta_rtc.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,50 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * RTC routines for Malta style attached PIIX4 device, which contains a + * Motorola MC146818A-compatible Real Time Clock. + * + */ +#include +#include + +static unsigned char malta_rtc_read_data(unsigned long addr) +{ + outb(addr, MALTA_RTC_ADR_REG); + return inb(MALTA_RTC_DAT_REG); +} + +static void malta_rtc_write_data(unsigned char data, unsigned long addr) +{ + outb(addr, MALTA_RTC_ADR_REG); + outb(data, MALTA_RTC_DAT_REG); +} + +static int malta_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops malta_rtc_ops = { + &malta_rtc_read_data, + &malta_rtc_write_data, + &malta_rtc_bcd_mode +}; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mips-boards/malta/malta_setup.c linux/arch/mips64/mips-boards/malta/malta_setup.c --- v2.4.9/linux/arch/mips64/mips-boards/malta/malta_setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/mips-boards/malta/malta_setup.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,170 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Malta specific setup, including init of the feature struct. + * + */ +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_BLK_DEV_IDE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_BLK_DEV_FD +#include +#endif +#include +#include + +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) +extern void console_setup(char *, int *); +char serial_console[20]; +#endif + +#ifdef CONFIG_REMOTE_DEBUG +extern void set_debug_traps(void); +extern void rs_kgdb_hook(int); +extern void breakpoint(void); +static int remote_debug = 0; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops std_ide_ops; +#endif +#ifdef CONFIG_BLK_DEV_FD +extern struct fd_ops std_fd_ops; +#endif +extern struct rtc_ops malta_rtc_ops; + +extern void mips_reboot_setup(void); + +struct resource standard_io_resources[] = { + { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, + { "pic1", 0x20, 0x3f, IORESOURCE_BUSY }, + { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, + { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, + { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY }, + { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, +}; + +#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) + +static void __init malta_irq_setup(void) +{ + maltaint_init(); + +#ifdef CONFIG_REMOTE_DEBUG + if (remote_debug) { + set_debug_traps(); + breakpoint(); + } +#endif +} + + +void __init malta_setup(void) +{ +#ifdef CONFIG_REMOTE_DEBUG + int rs_putDebugChar(char); + char rs_getDebugChar(void); + extern int (*putDebugChar)(char); + extern char (*getDebugChar)(void); +#endif + char *argptr; + int i; + + current_cpu_data.asid_cache = ASID_FIRST_VERSION; + TLBMISS_HANDLER_SETUP(); + + irq_setup = malta_irq_setup; + + /* Request I/O space for devices used on the Malta board. */ + for (i = 0; i < STANDARD_IO_RESOURCES; i++) + request_resource(&ioport_resource, standard_io_resources+i); + + /* + * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge. + */ + enable_dma(4); + +#ifdef CONFIG_SERIAL_CONSOLE + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) + { + int i=0; + char *s = prom_getenv("modetty0"); + while(s[i] >= '0' && s[i] <= '9') + i++; + strcpy(serial_console, "ttyS0,"); + strncpy(serial_console + 6, s, i); + prom_printf("Config serial console: %s\n", serial_console); + console_setup(serial_console, NULL); + } +#endif + +#ifdef CONFIG_REMOTE_DEBUG + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { + int line; + argptr += strlen("kgdb=ttyS"); + if (*argptr != '0' && *argptr != '1') + printk("KGDB: Uknown serial line /dev/ttyS%c, " + "falling back to /dev/ttyS1\n", *argptr); + line = *argptr == '0' ? 0 : 1; + printk("KGDB: Using serial line /dev/ttyS%d for session\n", + line ? 1 : 0); + + rs_kgdb_hook(line); + putDebugChar = rs_putDebugChar; + getDebugChar = rs_getDebugChar; + + prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " + "please connect your debugger\n", line ? 1 : 0); + + remote_debug = 1; + /* Breakpoints and stuff are in malta_irq_setup() */ + } +#endif + + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "nofpu")) != NULL) + mips_cpu.options &= ~MIPS_CPU_FPU; + + rtc_ops = &malta_rtc_ops; +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif +#ifdef CONFIG_BLK_DEV_FD + fd_ops = &std_fd_ops; +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mm/andes.c linux/arch/mips64/mm/andes.c --- v2.4.9/linux/arch/mips64/mm/andes.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/mm/andes.c Sun Sep 9 10:43:02 2001 @@ -125,14 +125,8 @@ static void andes_flush_cache_sigtramp(unsigned long addr) { - unsigned long daddr, iaddr; - - daddr = addr & ~(dc_lsize - 1); - protected_writeback_dcache_line(daddr); - protected_writeback_dcache_line(daddr + dc_lsize); - iaddr = addr & ~(ic_lsize - 1); - protected_flush_icache_line(iaddr); - protected_flush_icache_line(iaddr + ic_lsize); + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); } #define NTLB_ENTRIES 64 diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mm/extable.c linux/arch/mips64/mm/extable.c --- v2.4.9/linux/arch/mips64/mm/extable.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/mm/extable.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: extable.c,v 1.2 1999/11/23 17:12:50 ralf Exp $ - * +/* * 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. @@ -38,8 +37,7 @@ extern spinlock_t modlist_lock; -unsigned long -search_exception_table(unsigned long addr) +unsigned long search_exception_table(unsigned long addr) { unsigned long ret = 0; unsigned long flags; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mm/fault.c linux/arch/mips64/mm/fault.c --- v2.4.9/linux/arch/mips64/mm/fault.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/mm/fault.c Sun Sep 16 21:22:50 2001 @@ -32,7 +32,6 @@ #define development_version (LINUX_VERSION_CODE & 0x100) extern void die(char *, struct pt_regs *, unsigned long write); -extern int console_loglevel; /* * Macro for exception fixup code to access integer registers. @@ -63,7 +62,7 @@ /* * Unlock any spinlocks which will prevent us from getting the - * message out (timerlist_lock is aquired through the + * message out (timerlist_lock is acquired through the * console unblank code) */ void bust_spinlocks(int yes) @@ -71,12 +70,11 @@ spin_lock_init(&timerlist_lock); if (yes) { oops_in_progress = 1; -#ifdef CONFIG_SMP - global_irq_lock = 0; /* Many serial drivers do __global_cli() */ -#endif } else { int loglevel_save = console_loglevel; +#ifdef CONFIG_VT unblank_screen(); +#endif oops_in_progress = 0; /* * OK, the message is on the console. Now we call printk() diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mm/loadmmu.c linux/arch/mips64/mm/loadmmu.c --- v2.4.9/linux/arch/mips64/mm/loadmmu.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/mm/loadmmu.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: loadmmu.c,v 1.5 2000/01/27 01:05:24 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mm/r4xx0.c linux/arch/mips64/mm/r4xx0.c --- v2.4.9/linux/arch/mips64/mm/r4xx0.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/mm/r4xx0.c Sun Sep 9 10:43:02 2001 @@ -776,9 +776,9 @@ __restore_flags(flags); } -static void -r4k_flush_cache_range_s16d16i16(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_s16d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) { struct vm_area_struct *vma; unsigned long flags; @@ -815,9 +815,9 @@ } } -static void -r4k_flush_cache_range_s32d16i16(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_s32d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) { struct vm_area_struct *vma; unsigned long flags; @@ -854,9 +854,9 @@ } } -static void -r4k_flush_cache_range_s64d16i16(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_s64d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) { struct vm_area_struct *vma; unsigned long flags; @@ -893,9 +893,9 @@ } } -static void -r4k_flush_cache_range_s128d16i16(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_s128d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) { struct vm_area_struct *vma; unsigned long flags; @@ -932,9 +932,9 @@ } } -static void -r4k_flush_cache_range_s32d32i32(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_s32d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) { struct vm_area_struct *vma; unsigned long flags; @@ -971,9 +971,9 @@ } } -static void -r4k_flush_cache_range_s64d32i32(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_s64d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) { struct vm_area_struct *vma; unsigned long flags; @@ -1010,9 +1010,9 @@ } } -static void -r4k_flush_cache_range_s128d32i32(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_s128d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) { struct vm_area_struct *vma; unsigned long flags; @@ -1049,9 +1049,9 @@ } } -static void -r4k_flush_cache_range_d16i16(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_d16i16(struct mm_struct *mm, + unsigned long start, + unsigned long end) { if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; @@ -1065,9 +1065,9 @@ } } -static void -r4k_flush_cache_range_d32i32(struct mm_struct *mm, unsigned long start, - unsigned long end) +static void r4k_flush_cache_range_d32i32(struct mm_struct *mm, + unsigned long start, + unsigned long end) { if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; @@ -1176,8 +1176,8 @@ } } -static void -r4k_flush_cache_page_s16d16i16(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_s16d16i16(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1213,8 +1213,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1227,8 +1227,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1263,8 +1263,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1277,8 +1277,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1315,7 +1315,7 @@ * in that case, which doesn't overly flush the cache too much. */ if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1328,8 +1328,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1366,7 +1366,7 @@ * in that case, which doesn't overly flush the cache too much. */ if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1380,8 +1380,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1419,7 +1419,7 @@ * in that case, which doesn't overly flush the cache too much. */ if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1433,8 +1433,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1472,7 +1472,7 @@ * in that case, which doesn't overly flush the cache too much. */ if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1486,8 +1486,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1524,7 +1524,7 @@ * in that case, which doesn't overly flush the cache too much. */ if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1537,8 +1537,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_d16i16(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1587,8 +1587,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_d32i32(struct vm_area_struct *vma, unsigned long page) +static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1639,9 +1639,8 @@ __restore_flags(flags); } -static void -r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma, - unsigned long page) +static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma, + unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; @@ -1741,8 +1740,7 @@ * (Revision 2.0 device errata from IDT available on http://www.idt.com/ * in .pdf format.) */ -static void -r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) +static void r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) { unsigned long end, a; unsigned int flags; @@ -1766,8 +1764,7 @@ bc_wback_inv(addr, size); } -static void -r4k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size) +static void r4k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size) { unsigned long end, a; @@ -1785,8 +1782,7 @@ } } -static void -r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size) +static void r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size) { unsigned long end, a; unsigned int flags; @@ -1811,8 +1807,7 @@ bc_inv(addr, size); } -static void -r4k_dma_cache_inv_sc(unsigned long addr, unsigned long size) +static void r4k_dma_cache_inv_sc(unsigned long addr, unsigned long size) { unsigned long end, a; @@ -1830,8 +1825,7 @@ } } -static void -r4k_dma_cache_wback(unsigned long addr, unsigned long size) +static void r4k_dma_cache_wback(unsigned long addr, unsigned long size) { panic("r4k_dma_cache called - should not happen.\n"); } @@ -1843,33 +1837,24 @@ */ static void r4k_flush_cache_sigtramp(unsigned long addr) { - unsigned long daddr, iaddr; - - daddr = addr & ~((unsigned long)dc_lsize - 1); __asm__ __volatile__("nop;nop;nop;nop"); /* R4600 V1.7 */ - protected_writeback_dcache_line(daddr); - protected_writeback_dcache_line(daddr + dc_lsize); - iaddr = addr & ~((unsigned long)ic_lsize - 1); - protected_flush_icache_line(iaddr); - protected_flush_icache_line(iaddr + ic_lsize); + + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); } static void r4600v20k_flush_cache_sigtramp(unsigned long addr) { - unsigned long daddr, iaddr; unsigned int flags; - daddr = addr & ~((unsigned long)dc_lsize - 1); __save_and_cli(flags); /* Clear internal cache refill buffer */ *(volatile unsigned int *)KSEG1; - protected_writeback_dcache_line(daddr); - protected_writeback_dcache_line(daddr + dc_lsize); - iaddr = addr & ~((unsigned long)ic_lsize - 1); - protected_flush_icache_line(iaddr); - protected_flush_icache_line(iaddr + ic_lsize); + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); + __restore_flags(flags); } @@ -2011,8 +1996,7 @@ } } -static void -r4k_flush_cache_l2(void) +static void r4k_flush_cache_l2(void) { } diff -u --recursive --new-file v2.4.9/linux/arch/mips64/mm/umap.c linux/arch/mips64/mm/umap.c --- v2.4.9/linux/arch/mips64/mm/umap.c Wed Jul 25 17:10:18 2001 +++ linux/arch/mips64/mm/umap.c Sun Sep 9 10:43:02 2001 @@ -25,8 +25,8 @@ #include #include -static inline void -remove_mapping_pte_range (pmd_t *pmd, unsigned long address, unsigned long size) +static inline void remove_mapping_pte_range (pmd_t *pmd, unsigned long address, + unsigned long size) { pte_t *pte; unsigned long end; @@ -34,7 +34,8 @@ if (pmd_none (*pmd)) return; if (pmd_bad (*pmd)){ - printk ("remove_graphics_pte_range: bad pmd (%08lx)\n", pmd_val (*pmd)); + printk ("remove_graphics_pte_range: bad pmd (%08lx)\n", + pmd_val (*pmd)); pmd_clear (pmd); return; } @@ -53,8 +54,8 @@ } -static inline void -remove_mapping_pmd_range (pgd_t *pgd, unsigned long address, unsigned long size) +static inline void remove_mapping_pmd_range (pgd_t *pgd, unsigned long address, + unsigned long size) { pmd_t *pmd; unsigned long end; @@ -63,7 +64,8 @@ return; if (pgd_bad (*pgd)){ - printk ("remove_graphics_pmd_range: bad pgd (%08lx)\n", pgd_val (*pgd)); + printk ("remove_graphics_pmd_range: bad pgd (%08lx)\n", + pgd_val (*pgd)); pgd_clear (pgd); return; } @@ -84,8 +86,8 @@ * This routine is called from the page fault handler to remove a * range of active mappings at this point */ -void -remove_mapping (struct task_struct *task, unsigned long start, unsigned long end) +void remove_mapping (struct task_struct *task, unsigned long start, + unsigned long end) { unsigned long beg = start; pgd_t *dir; @@ -137,8 +139,8 @@ * maps a range of vmalloc()ed memory into the requested pages. the old * mappings are removed. */ -static inline void -vmap_pte_range (pte_t *pte, unsigned long address, unsigned long size, unsigned long vaddr) +static inline void vmap_pte_range (pte_t *pte, unsigned long address, + unsigned long size, unsigned long vaddr) { unsigned long end; pgd_t *vdir; @@ -167,8 +169,8 @@ } while (address < end); } -static inline int -vmap_pmd_range (pmd_t *pmd, unsigned long address, unsigned long size, unsigned long vaddr) +static inline int vmap_pmd_range (pmd_t *pmd, unsigned long address, + unsigned long size, unsigned long vaddr) { unsigned long end; @@ -178,7 +180,7 @@ end = PGDIR_SIZE; vaddr -= address; do { - pte_t * pte = pte_alloc(pmd, address); + pte_t * pte = pte_alloc(current->mm, pmd, address); if (!pte) return -ENOMEM; vmap_pte_range(pte, address, end - address, address + vaddr); @@ -188,8 +190,8 @@ return 0; } -int -vmap_page_range (unsigned long from, unsigned long size, unsigned long vaddr) +int vmap_page_range (unsigned long from, unsigned long size, + unsigned long vaddr) { int error = 0; pgd_t * dir; @@ -200,7 +202,7 @@ dir = pgd_offset(current->mm, from); flush_cache_range(current->mm, beg, end); while (from < end) { - pmd_t *pmd = pmd_alloc(dir, from); + pmd_t *pmd = pmd_alloc(current->mm, dir, from); error = -ENOMEM; if (!pmd) break; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-berr.c linux/arch/mips64/sgi-ip22/ip22-berr.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-berr.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip22/ip22-berr.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: ip22-berr.c,v 1.1 2000/01/21 22:34:03 ralf Exp $ - * +/* * 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. @@ -9,6 +8,9 @@ */ #include #include +#include + +#include #include #include #include @@ -41,16 +43,43 @@ return 0; } +extern spinlock_t modlist_lock; + static inline unsigned long search_dbe_table(unsigned long addr) { - unsigned long ret; + unsigned long ret = 0; +#ifndef CONFIG_MODULES /* There is only the kernel to search. */ ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); - if (ret) return ret; - - return 0; + return ret; +#else + unsigned long flags; + + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + struct archdata *ap; + + spin_lock_irqsave(&modlist_lock, flags); + for (mp = module_list; mp != NULL; mp = mp->next) { + if (!mod_member_present(mp, archdata_end) || + !mod_archdata_member_present(mp, struct archdata, + dbe_table_end)) + continue; + ap = (struct archdata *)(mod->archdata_start); + + if (ap->dbe_table_start == NULL || + !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) + continue; + ret = search_one_table(ap->dbe_table_start, + ap->dbe_table_end - 1, addr); + if (ret) + break; + } + spin_unlock_irqrestore(&modlist_lock, flags); + return ret; +#endif } void do_ibe(struct pt_regs *regs) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-hpc.c linux/arch/mips64/sgi-ip22/ip22-hpc.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-hpc.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip22/ip22-hpc.c Sun Sep 9 10:43:02 2001 @@ -1,9 +1,8 @@ -/* $Id: ip22-hpc.c,v 1.2 1999/10/19 20:51:52 ralf Exp $ - * +/* * ip22-hpc.c: Routines for generic manipulation of the HPC controllers. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1998, 1999 Ralf Baechle + * Copyright (C) 1998, 1999, 2001 Ralf Baechle */ #include #include @@ -11,7 +10,6 @@ #include #include #include -#include #include #undef DEBUG_SGIHPC diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-int.c linux/arch/mips64/sgi-ip22/ip22-int.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-int.c Fri Feb 9 11:29:44 2001 +++ linux/arch/mips64/sgi-ip22/ip22-int.c Sun Sep 9 10:43:02 2001 @@ -34,7 +34,6 @@ #include #include #include -#include /* * Linux has a controller-independent x86 interrupt architecture. @@ -287,9 +286,7 @@ irq_enter(cpu, irq); kstat.irqs[0][irq]++; - printk("Got irq %d, press a key.", irq); - prom_getchar(); - ArcEnterInteractiveMode(); + panic(KERN_DEBUG "Got irq %d, press a key.", irq); /* * mask and ack quickly, we don't want the irq controller diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-irq.S linux/arch/mips64/sgi-ip22/ip22-irq.S --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-irq.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip22/ip22-irq.S Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: ip22-irq.S,v 1.1 1999/08/20 21:13:33 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-mc.c linux/arch/mips64/sgi-ip22/ip22-mc.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-mc.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip22/ip22-mc.c Sun Sep 9 10:43:02 2001 @@ -1,12 +1,10 @@ -/* $Id: ip22-mc.c,v 1.2 1999/10/19 20:51:52 ralf Exp $ - * +/* * 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. * - * indy_mc.c: Routines for manipulating the INDY memory controller. - * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 2001 Ralf Baechle (ralf@gnu.org) */ #include #include @@ -15,7 +13,6 @@ #include #include #include -#include /* #define DEBUG_SGIMC */ diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-reset.c linux/arch/mips64/sgi-ip22/ip22-reset.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-reset.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip22/ip22-reset.c Sun Sep 9 10:43:02 2001 @@ -1,12 +1,11 @@ -/* $Id: ip22-reset.c,v 1.3 1999/10/08 21:07:51 ralf Exp $ - * +/* * 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. * * Reset an IP22. * - * Copyright (C) 1997, 1998, 1999 by Ralf Baechle + * Copyright (C) 1997, 1998, 1999, 2001 by Ralf Baechle */ #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-rtc.c linux/arch/mips64/sgi-ip22/ip22-rtc.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-rtc.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip22/ip22-rtc.c Sun Sep 9 10:43:02 2001 @@ -1,12 +1,11 @@ -/* $Id: ip22-rtc.c,v 1.1 1999/08/20 21:13:34 ralf Exp $ - * +/* * 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. * * RTC routines for Indy style attached Dallas chip. * - * Copyright (C) 1998 by Ralf Baechle + * Copyright (C) 1998, 2001 by Ralf Baechle */ #include #include diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-sc.c linux/arch/mips64/sgi-ip22/ip22-sc.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-sc.c Tue Mar 6 19:44:36 2001 +++ linux/arch/mips64/sgi-ip22/ip22-sc.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: ip22-sc.c,v 1.2 1999/12/04 03:59:01 ralf Exp $ - * +/* * indy_sc.c: Indy cache management functions. * * Copyright (C) 1997 Ralf Baechle (ralf@gnu.org), @@ -16,7 +15,6 @@ #include #include #include -#include #include /* Secondary cache size in bytes, if present. */ @@ -31,17 +29,17 @@ static inline void indy_sc_wipe(unsigned long first, unsigned long last) { - __asm__ __volatile__(" - .set noreorder - or %0, %4 # first line to flush - or %1, %4 # last line to flush -1: sw $0, 0(%0) - bne %0, %1, 1b - daddu %0, 32 - .set reorder" - : "=r" (first), "=r" (last) - : "0" (first), "1" (last), "r" (0x9000000080000000) - : "$1"); + __asm__ __volatile__( + ".set\tnoreorder\n\t" + "or\t%0, %4\t\t\t# first line to flush\n\t" + "or\t%1, %4\t\t\t# last line to flush\n" + "1:\tsw $0, 0(%0)\n\t" + "bne\t%0, %1, 1b\n\t" + "daddu\t%0, 32\n\t" + ".set reorder" + : "=r" (first), "=r" (last) + : "0" (first), "1" (last), "r" (0x9000000080000000) + : "$1"); } static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-setup.c linux/arch/mips64/sgi-ip22/ip22-setup.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-setup.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip22/ip22-setup.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: ip22-setup.c,v 1.4 1999/10/08 21:07:51 ralf Exp $ - * +/* * 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. @@ -145,7 +144,7 @@ * graphics console, it is set to "d" for the first serial * line and "d2" for the second serial line. */ - ctype = ArcArcGetEnvironmentVariable("console"); + ctype = ArcGetEnvironmentVariable("console"); if(*ctype == 'd') { if(*(ctype+1)=='2') console_setup ("ttyS1"); diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/ip22-timer.c linux/arch/mips64/sgi-ip22/ip22-timer.c --- v2.4.9/linux/arch/mips64/sgi-ip22/ip22-timer.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip22/ip22-timer.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: ip22-timer.c,v 1.6 2000/02/04 07:40:24 ralf Exp $ - * +/* * indy_timer.c: Setting up the clock on the INDY 8254 controller. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -238,9 +237,7 @@ irq_enter(cpu, irq); kstat.irqs[0][irq]++; - printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); - prom_getchar(); - ArcEnterInteractiveMode(); + panic("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); irq_exit(cpu, irq); } diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/system.c linux/arch/mips64/sgi-ip22/system.c --- v2.4.9/linux/arch/mips64/sgi-ip22/system.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip22/system.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: system.c,v 1.3 1999/10/19 20:51:52 ralf Exp $ - * +/* * 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. @@ -7,6 +6,7 @@ * system.c: Probe the system type using ARCS prom interface library. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) */ #include #include @@ -17,8 +17,6 @@ #include #include -enum sgi_mach sgimach; - struct smatch { char *name; int type; @@ -46,10 +44,7 @@ if(!strcmp(s, sgi_cputable[i].name)) return sgi_cputable[i].type; } - prom_printf("\nYeee, could not determine MIPS cpu type <%s>\n", s); - prom_printf("press a key to reboot\n"); - prom_getchar(); - ArcEnterInteractiveMode(); + panic("\nYeee, could not determine MIPS cpu type <%s>", s); return 0; } @@ -74,23 +69,16 @@ int ncpus = 0; if(p->type == Cpu) { - if(++ncpus > 1) { - prom_printf("\nYeee, SGI MP not ready yet\n"); - prom_printf("press a key to reboot\n"); - prom_getchar(); - ArcEnterInteractiveMode(); - } + if (++ncpus > 1) + panic("\nYeee, SGI MP not ready yet"); printk("CPU: %s ", p->iname); cpup = p; cputype = string_to_cpu(cpup->iname); } p = ArcGetPeer(p); } - if(cputype == -1) { - prom_printf("\nYeee, could not find cpu ARCS component\n"); - prom_printf("press a key to reboot\n"); - prom_getchar(); - ArcEnterInteractiveMode(); + if (cputype == -1) { + panic("\nYeee, could not find cpu ARCS component"); } p = ArcGetChild(cpup); while(p) { diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip22/time.c linux/arch/mips64/sgi-ip22/time.c --- v2.4.9/linux/arch/mips64/sgi-ip22/time.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip22/time.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: time.c,v 1.1 1999/08/20 21:13:34 ralf Exp $ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/Makefile linux/arch/mips64/sgi-ip27/Makefile --- v2.4.9/linux/arch/mips64/sgi-ip27/Makefile Sun Feb 4 21:48:46 2001 +++ linux/arch/mips64/sgi-ip27/Makefile Sun Sep 9 10:43:02 2001 @@ -7,7 +7,7 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -O_TARGET = ip27.a +O_TARGET = ip27.o obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \ ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \ diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-berr.c linux/arch/mips64/sgi-ip27/ip27-berr.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-berr.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/sgi-ip27/ip27-berr.c Sun Sep 9 10:43:02 2001 @@ -8,6 +8,9 @@ */ #include #include +#include + +#include #include #include #include @@ -43,16 +46,43 @@ return 0; } +extern spinlock_t modlist_lock; + static inline unsigned long search_dbe_table(unsigned long addr) { unsigned long ret; +#ifndef CONFIG_MODULES /* There is only the kernel to search. */ ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); - if (ret) return ret; - - return 0; + return ret; +#else + unsigned long flags; + + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + struct archdata *ap; + + spin_lock_irqsave(&modlist_lock, flags); + for (mp = module_list; mp != NULL; mp = mp->next) { + if (!mod_member_present(mp, archdata_end) || + !mod_archdata_member_present(mp, struct archdata, + dbe_table_end)) + continue; + ap = (struct archdata *)(mod->archdata_start); + + if (ap->dbe_table_start == NULL || + !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) + continue; + ret = search_one_table(ap->dbe_table_start, + ap->dbe_table_end - 1, addr); + if (ret) + break; + } + spin_unlock_irqrestore(&modlist_lock, flags); + return ret; +#endif } void do_ibe(struct pt_regs *regs) @@ -64,9 +94,43 @@ while(1); } +static void dump_hub_information(unsigned long errst0, unsigned long errst1) +{ + static char *err_type[2][8] = { + { NULL, "Uncached Partial Read PRERR", "DERR", "Read Timeout", + NULL, NULL, NULL, NULL }, + { "WERR", "Uncached Partial Write", "PWERR", "Write Timeout", + NULL, NULL, NULL, NULL } + }; + int wrb = errst1 & PI_ERR_ST1_WRBRRB_MASK; + + if (!(errst0 & PI_ERR_ST0_VALID_MASK)) { + printk("Hub does not contain valid error information\n"); + return; + } + + + printk("Hub has valid error information:\n"); + if (errst0 & PI_ERR_ST0_OVERRUN_MASK) + printk("Overrun is set. Error stack may contain additional " + "information.\n"); + printk("Hub error address is %08lx\n", + (errst0 & PI_ERR_ST0_ADDR_MASK) >> (PI_ERR_ST0_ADDR_SHFT - 3)); + printk("Incoming message command 0x%lx\n", + (errst0 & PI_ERR_ST0_CMD_MASK) >> PI_ERR_ST0_CMD_SHFT); + printk("Supplemental field of incoming message is 0x%lx\n", + (errst0 & PI_ERR_ST0_SUPPL_MASK) >> PI_ERR_ST0_SUPPL_SHFT); + printk("T5 Rn (for RRB only) is 0x%lx\n", + (errst0 & PI_ERR_ST0_REQNUM_MASK) >> PI_ERR_ST0_REQNUM_SHFT); + printk("Error type is %s\n", err_type[wrb] + [(errst0 & PI_ERR_ST0_TYPE_MASK) >> PI_ERR_ST0_TYPE_SHFT] + ? : "invalid"); +} + void do_dbe(struct pt_regs *regs) { - unsigned long fixup; + unsigned long fixup, errst0, errst1; + int cpu = LOCAL_HUB_L(PI_CPU_NUM); fixup = search_dbe_table(regs->cp0_epc); if (fixup) { @@ -77,7 +141,12 @@ return; } - printk("Got dbe at 0x%lx\n", regs->cp0_epc); + printk("Slice %c got dbe at 0x%lx\n", 'A' + cpu, regs->cp0_epc); + printk("Hub information:\n"); + printk("ERR_INT_PEND = 0x%06lx\n", LOCAL_HUB_L(PI_ERR_INT_PEND)); + errst0 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS0_B : PI_ERR_STATUS0_A); + errst1 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS1_B : PI_ERR_STATUS1_A); + dump_hub_information(errst0, errst1); show_regs(regs); dump_tlb_all(); while(1); @@ -95,7 +164,7 @@ set_except_vector(7, handle_dbe); LOCAL_HUB_S(PI_ERR_INT_PEND, - cpu ? PI_ERR_CLEAR_ALL_A : PI_ERR_CLEAR_ALL_B); + cpu ? PI_ERR_CLEAR_ALL_B : PI_ERR_CLEAR_ALL_A); LOCAL_HUB_S(PI_ERR_INT_MASK_A + cpuoff, 0); LOCAL_HUB_S(PI_ERR_STACK_ADDR_A + cpuoff, 0); LOCAL_HUB_S(PI_ERR_STACK_SIZE, 0); /* Disable error stack */ diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-console.c linux/arch/mips64/sgi-ip27/ip27-console.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-console.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip27/ip27-console.c Sun Sep 9 10:43:02 2001 @@ -2,6 +2,8 @@ * 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. + * + * Copyright (C) 2001 Ralf Baechle */ #include #include @@ -11,7 +13,6 @@ #include #include #include -#include #include void prom_putchar(char c) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-init.c linux/arch/mips64/sgi-ip27/ip27-init.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-init.c Sun Feb 4 21:48:46 2001 +++ linux/arch/mips64/sgi-ip27/ip27-init.c Sun Sep 9 10:43:02 2001 @@ -1,3 +1,12 @@ +/* + * 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. + * + * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) + * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. + */ + #include #include #include @@ -23,14 +32,14 @@ #include #include #include +#include +#include #define CPU_NONE (cpuid_t)-1 -#define CPUMASK_CLRALL(p) (p) = 0 -#define CPUMASK_SETB(p, bit) (p) |= 1 << (bit) -#define CPUMASK_CLRB(p, bit) (p) &= ~(1ULL << (bit)) -#define CPUMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) - +/* + * The following should work till 64 nodes, ie 128p SN0s. + */ #define CNODEMASK_CLRALL(p) (p) = 0 #define CNODEMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) #define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit)) @@ -42,11 +51,13 @@ static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED; static cnodemask_t hub_init_mask; static atomic_t numstarted = ATOMIC_INIT(1); +static int router_distance; nasid_t master_nasid = INVALID_NASID; cnodeid_t nasid_to_compact_node[MAX_NASIDS]; nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; cnodeid_t cpuid_to_compact_node[MAXCPUS]; +char node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; hubreg_t get_region(cnodeid_t cnode) { @@ -89,9 +100,13 @@ return brd->brd_nasid; } +/* Tweak this for maximum number of CPUs to activate */ +static int max_cpus = NR_CPUS; + int do_cpumask(cnodeid_t cnode, nasid_t nasid, cpumask_t *boot_cpumask, int *highest) { + static int tot_cpus_found = 0; lboard_t *brd; klcpu_t *acpu; int cpus_found = 0; @@ -109,9 +124,11 @@ if (cpuid > *highest) *highest = cpuid; /* Only let it join in if it's marked enabled */ - if (acpu->cpu_info.flags & KLINFO_ENABLE) { + if ((acpu->cpu_info.flags & KLINFO_ENABLE) && + (tot_cpus_found != max_cpus)) { CPUMASK_SETB(*boot_cpumask, cpuid); cpus_found++; + tot_cpus_found++; } acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, KLSTRUCT_CPU); @@ -172,6 +189,9 @@ void mlreset (void) { int i; + void init_topology_matrix(void); + void dump_topology(void); + master_nasid = get_nasid(); fine_mode = is_fine_dirmode(); @@ -184,6 +204,9 @@ maxcpus = cpu_node_probe(&boot_cpumask, &numnodes); printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes); + init_topology_matrix(); + dump_topology(); + gen_region_mask(®ion_mask, numnodes); CNODEMASK_CLRALL(hub_init_mask); @@ -534,3 +557,284 @@ #else /* CONFIG_SMP */ void cboot(void) {} #endif /* CONFIG_SMP */ + + +#define rou_rflag rou_flags + +void +router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) +{ + klrou_t *router; + lboard_t *brd; + int port; + + if (router_a->rou_rflag == 1) + return; + + if (depth >= router_distance) + return; + + router_a->rou_rflag = 1; + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router_a->rou_port[port].port_nasid == INVALID_NASID) + continue; + + brd = (lboard_t *)NODE_OFFSET_TO_K0( + router_a->rou_port[port].port_nasid, + router_a->rou_port[port].port_offset); + + if (brd->brd_type == KLTYPE_ROUTER) { + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + if (router == router_b) { + if (depth < router_distance) + router_distance = depth; + } + else + router_recurse(router, router_b, depth + 1); + } + } + + router_a->rou_rflag = 0; +} + +int +node_distance(nasid_t nasid_a, nasid_t nasid_b) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd, *dest_brd; + int port; + klrou_t *router, *router_a = NULL, *router_b = NULL; + + /* Figure out which routers nodes in question are connected to */ + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == -1) continue; + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + router->rou_rflag = 0; + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router->rou_port[port].port_nasid == INVALID_NASID) + continue; + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + if (dest_brd->brd_type == KLTYPE_IP27) { + if (dest_brd->brd_nasid == nasid_a) + router_a = router; + if (dest_brd->brd_nasid == nasid_b) + router_b = router; + } + } + + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } + + if (router_a == NULL) { + printk("node_distance: router_a NULL\n"); + return -1; + } + if (router_b == NULL) { + printk("node_distance: router_b NULL\n"); + return -1; + } + + if (nasid_a == nasid_b) + return 0; + + if (router_a == router_b) + return 1; + + router_distance = 100; + router_recurse(router_a, router_b, 2); + + return router_distance; +} + +void +init_topology_matrix(void) +{ + nasid_t nasid, nasid2; + cnodeid_t row, col; + + for (row = 0; row < MAX_COMPACT_NODES; row++) + for (col = 0; col < MAX_COMPACT_NODES; col++) + node_distances[row][col] = -1; + + for (row = 0; row < numnodes; row++) { + nasid = COMPACT_TO_NASID_NODEID(row); + for (col = 0; col < numnodes; col++) { + nasid2 = COMPACT_TO_NASID_NODEID(col); + node_distances[row][col] = node_distance(nasid, nasid2); + } + } +} + +void +dump_topology(void) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd, *dest_brd; + int port; + int router_num = 0; + klrou_t *router; + cnodeid_t row, col; + + printk("************** Topology ********************\n"); + + printk(" "); + for (col = 0; col < numnodes; col++) + printk("%02d ", col); + printk("\n"); + for (row = 0; row < numnodes; row++) { + printk("%02d ", row); + for (col = 0; col < numnodes; col++) + printk("%2d ", node_distances[row][col]); + printk("\n"); + } + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == -1) continue; + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + printk("Router %d:", router_num); + router_num++; + + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router->rou_port[port].port_nasid == INVALID_NASID) + continue; + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + if (dest_brd->brd_type == KLTYPE_IP27) + printk(" %d", dest_brd->brd_nasid); + if (dest_brd->brd_type == KLTYPE_ROUTER) + printk(" r"); + } + printk("\n"); + + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } +} + +#if 0 +#define brd_widgetnum brd_slot +#define NODE_OFFSET_TO_KLINFO(n,off) ((klinfo_t*) TO_NODE_CAC(n,off)) +void +dump_klcfg(void) +{ + cnodeid_t cnode; + int i; + nasid_t nasid; + lboard_t *lbptr; + gda_t *gdap; + + gdap = (gda_t *)GDA_ADDR(get_nasid()); + if (gdap->g_magic != GDA_MAGIC) { + printk("dumpklcfg_cmd: Invalid GDA MAGIC\n"); + return; + } + + for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { + nasid = gdap->g_nasidtable[cnode]; + + if (nasid == INVALID_NASID) + continue; + + printk("\nDumpping klconfig Nasid %d:\n", nasid); + + lbptr = KL_CONFIG_INFO(nasid); + + while (lbptr) { + printk(" %s, Nasid %d, Module %d, widget 0x%x, partition %d, NIC 0x%x lboard 0x%lx", + "board name here", /* BOARD_NAME(lbptr->brd_type), */ + lbptr->brd_nasid, lbptr->brd_module, + lbptr->brd_widgetnum, + lbptr->brd_partition, + (lbptr->brd_nic), lbptr); + if (lbptr->brd_flags & DUPLICATE_BOARD) + printk(" -D"); + printk("\n"); + for (i = 0; i < lbptr->brd_numcompts; i++) { + klinfo_t *kli; + kli = NODE_OFFSET_TO_KLINFO(NASID_GET(lbptr), lbptr->brd_compts[i]); + printk(" type %2d, flags 0x%04x, diagval %3d, physid %4d, virtid %2d: %s\n", + kli->struct_type, + kli->flags, + kli->diagval, + kli->physid, + kli->virtid, + "comp. name here"); + /* COMPONENT_NAME(kli->struct_type)); */ + } + lbptr = KLCF_NEXT(lbptr); + } + } + printk("\n"); + + /* Useful to print router maps also */ + + for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { + klrou_t *kr; + int i; + + nasid = gdap->g_nasidtable[cnode]; + if (nasid == INVALID_NASID) + continue; + lbptr = KL_CONFIG_INFO(nasid); + + while (lbptr) { + + lbptr = find_lboard_class(lbptr, KLCLASS_ROUTER); + if(!lbptr) + break; + if (!KL_CONFIG_DUPLICATE_BOARD(lbptr)) { + printk("%llx -> \n", lbptr->brd_nic); + kr = (klrou_t *)find_first_component(lbptr, + KLSTRUCT_ROU); + for (i = 1; i <= MAX_ROUTER_PORTS; i++) { + printk("[%d, %llx]; ", + kr->rou_port[i].port_nasid, + kr->rou_port[i].port_offset); + } + printk("\n"); + } + lbptr = KLCF_NEXT(lbptr); + } + printk("\n"); + } + + dump_topology(); +} +#endif + diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-irq-glue.S linux/arch/mips64/sgi-ip27/ip27-irq-glue.S --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-irq-glue.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip27/ip27-irq-glue.S Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-irq.c linux/arch/mips64/sgi-ip27/ip27-irq.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-irq.c Fri Feb 9 11:29:44 2001 +++ linux/arch/mips64/sgi-ip27/ip27-irq.c Sun Sep 9 10:43:02 2001 @@ -3,6 +3,7 @@ * * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999 - 2001 Kanoj Sarcar */ #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include @@ -42,6 +44,10 @@ #define DBG(x...) #endif +/* These should die */ +unsigned char bus_to_wid[256]; /* widget id for linux pci bus */ +unsigned char bus_to_nid[256]; /* nasid for linux pci bus */ +unsigned char num_bridges; /* number of bridges in the system */ /* * Linux has a controller-independent x86 interrupt architecture. @@ -67,11 +73,11 @@ unsigned long spurious_count = 0; /* - * we need to map irq's up to at least bit 7 of the INT_MASK0_A register - * since bits 0-6 are pre-allocated for other purposes. + * There is a single intpend register per node, and we want to have + * distinct levels for intercpu intrs for both cpus A and B on a node. */ -#define IRQ_TO_SWLEVEL(cpu, i) i + 7 -#define SWLEVEL_TO_IRQ(cpu, s) s - 7 +int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS]; + /* * use these macros to get the encoded nasid and widget id * from the irq value @@ -82,6 +88,41 @@ #define WID_FROM_PCI_IRQ(i) bus_to_wid[IRQ_TO_BUS(i)] #define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] +static inline int alloc_level(cpuid_t cpunum, int irq) +{ + cnodeid_t nodenum = CPUID_TO_COMPACT_NODEID(cpunum); + int j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ + + while (++j < PERNODE_LEVELS) { + if (node_level_to_irq[nodenum][j] == -1) { + node_level_to_irq[nodenum][j] = irq; + return j; + } + } + printk("Cpu %ld flooded with devices\n", cpunum); + while(1); + return -1; +} + +static inline int find_level(cpuid_t *cpunum, int irq) +{ + int j; + cnodeid_t nodenum = INVALID_CNODEID; + + while (++nodenum < MAX_COMPACT_NODES) { + j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ + while (++j < PERNODE_LEVELS) + if (node_level_to_irq[nodenum][j] == irq) { + *cpunum = 0; /* XXX Fixme */ + return(j); + } + } + printk("Could not identify cpu/level for irq %d\n", irq); + while(1); + return(-1); +} + + void disable_irq(unsigned int irq_nr) { panic("disable_irq() called ..."); @@ -146,7 +187,8 @@ } irq_exit(thiscpu, irq); - /* unmasking and bottom half handling is done magically for us. */ + if (softirq_pending(thiscpu)) + do_softirq(); } /* @@ -196,7 +238,7 @@ swlevel = ms1bit(pend0); LOCAL_HUB_CLR_INTR(swlevel); /* "map" swlevel to irq */ - irq = SWLEVEL_TO_IRQ(thiscpu, swlevel); + irq = LEVEL_TO_IRQ(thiscpu, swlevel); do_IRQ(thiscpu, irq, regs); /* clear bit in pend0 */ pend0 ^= 1ULL << swlevel; @@ -227,7 +269,7 @@ * "map" irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ - swlevel = IRQ_TO_SWLEVEL(cpu, irq); + swlevel = alloc_level(cpu, irq); intr_connect_level(cpu, swlevel); bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8)); @@ -254,6 +296,7 @@ { bridge_t *bridge; int pin, swlevel; + cpuid_t cpu; bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), WID_FROM_PCI_IRQ(irq)); @@ -264,8 +307,9 @@ * map irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ - swlevel = IRQ_TO_SWLEVEL(cpu, irq); - intr_disconnect_level(smp_processor_id(), swlevel); + swlevel = find_level(&cpu, irq); + intr_disconnect_level(cpu, swlevel); + LEVEL_TO_IRQ(cpu, swlevel) = -1; bridge->b_int_enable &= ~(1 << pin); bridge->b_widget.w_tflush; /* Flush */ @@ -423,7 +467,6 @@ printk(" ]\nStack dumps:"); for(i = 0; i < smp_num_cpus; i++) { - unsigned long esp; if (i == cpu) continue; printk("\nCPU %d:",i); @@ -661,37 +704,50 @@ #ifdef CONFIG_SMP #if (CPUS_PER_NODE == 2) static int done = 0; - int irq; /* * This is a hack till we have a pernode irqlist. Currently, * just have the master cpu set up the handlers for the per * cpu irqs. */ + if (done == 0) { + int j; - irq = CPU_RESCHED_A_IRQ + cputoslice(cpu); - intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq)); - if (done == 0) - if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) - panic("intercpu intr unconnectible\n"); - irq = CPU_CALL_A_IRQ + cputoslice(cpu); - intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq)); - if (done == 0) - if (request_irq(irq, smp_call_function_interrupt, 0, - "callfunc", 0)) - panic("intercpu intr unconnectible\n"); - /* HACK STARTS */ - if (done) - return; - irq = CPU_RESCHED_A_IRQ + cputoslice(cpu) + 1; - if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) - panic("intercpu intr unconnectible\n"); - irq = CPU_CALL_A_IRQ + cputoslice(cpu) + 1; - if (request_irq(irq, smp_call_function_interrupt, 0, - "callfunc", 0)) - panic("intercpu intr unconnectible\n"); - done = 1; - /* HACK ENDS */ + if (request_irq(CPU_RESCHED_A_IRQ, handle_resched_intr, + 0, "resched", 0)) + panic("intercpu intr unconnectible\n"); + if (request_irq(CPU_RESCHED_B_IRQ, handle_resched_intr, + 0, "resched", 0)) + panic("intercpu intr unconnectible\n"); + if (request_irq(CPU_CALL_A_IRQ, smp_call_function_interrupt, + 0, "callfunc", 0)) + panic("intercpu intr unconnectible\n"); + if (request_irq(CPU_CALL_B_IRQ, smp_call_function_interrupt, + 0, "callfunc", 0)) + panic("intercpu intr unconnectible\n"); + + for (j = 0; j < PERNODE_LEVELS; j++) + LEVEL_TO_IRQ(0, j) = -1; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ)) = + CPU_RESCHED_A_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_B_IRQ)) = + CPU_RESCHED_B_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ)) = + CPU_CALL_A_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_B_IRQ)) = + CPU_CALL_B_IRQ; + for (j = 1; j < MAX_COMPACT_NODES; j++) + memcpy(&node_level_to_irq[j][0], + &node_level_to_irq[0][0], + sizeof(node_level_to_irq[0][0])*PERNODE_LEVELS); + + done = 1; + } + + intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ + + cputoslice(cpu))); + intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ + + cputoslice(cpu))); #else /* CPUS_PER_NODE */ #error Must redefine this for more than 2 CPUS. #endif /* CPUS_PER_NODE */ @@ -700,7 +756,9 @@ void install_tlbintr(int cpu) { +#if 0 int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu); intr_connect_level(cpu, intr_bit); +#endif } diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-klconfig.c linux/arch/mips64/sgi-ip27/ip27-klconfig.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-klconfig.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/sgi-ip27/ip27-klconfig.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ @@ -57,6 +56,19 @@ return start; start = KLCF_NEXT(start); } + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * find_lboard_class(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) + return start; + start = KLCF_NEXT(start); + } + /* Didn't find it. */ return (lboard_t *)NULL; } diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-klnuma.c linux/arch/mips64/sgi-ip27/ip27-klnuma.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-klnuma.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip27/ip27-klnuma.c Sun Sep 9 10:43:02 2001 @@ -1,6 +1,7 @@ /* * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00. - * Copyright 2000 Silicon Graphics, Inc. + * Copyright 2000 - 2001 Silicon Graphics, Inc. + * Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com) */ #include #include @@ -9,6 +10,7 @@ #include #include +#include #include #include #include @@ -16,10 +18,6 @@ #include #include #include - -#define CPUMASK_CLRALL(p) (p) = 0 -#define CPUMASK_SETB(p, bit) (p) |= 1 << (bit) -#define CPUMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) extern char _end; static cpumask_t ktext_repmask; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-memory.c linux/arch/mips64/sgi-ip27/ip27-memory.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-memory.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip27/ip27-memory.c Sun Sep 9 10:43:02 2001 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -227,15 +228,24 @@ void __init paging_init(void) { + pmd_t *pmd = kpmdtbl; + pte_t *pte = kptbl; + cnodeid_t node; unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + int i; /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); - pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table); - memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE); + + /* This is for vmalloc */ + memset((void *)kptbl, 0, PAGE_SIZE << KPTBL_PAGE_ORDER); + memset((void *)kpmdtbl, 0, PAGE_SIZE); + pgd_set(swapper_pg_dir, kpmdtbl); + for (i = 0; i < (1 << KPTBL_PAGE_ORDER); pmd++,i++,pte+=PTRS_PER_PTE) + pmd_val(*pmd) = (unsigned long)pte; for (node = 0; node < numnodes; node++) { pfn_t start_pfn = slot_getbasepfn(node, 0); diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-pci-dma.c linux/arch/mips64/sgi-ip27/ip27-pci-dma.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-pci-dma.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip27/ip27-pci-dma.c Sun Sep 9 10:43:02 2001 @@ -1,5 +1,4 @@ -/* $Id: ip27-pci-dma.c,v 1.1 2000/02/16 21:22:00 ralf Exp $ - * +/* * Dynamic DMA mapping support. * * On the Origin there is dynamic DMA address translation for all PCI DMA. @@ -52,4 +51,114 @@ void *vaddr, dma_addr_t dma_handle) { free_pages((unsigned long)vaddr, __get_order(size)); +} + +/* + * Map a single buffer of the indicated size for DMA in streaming mode. + * The 32-bit bus address to use is returned. + * + * Once the device is given the dma address, the device owns this memory + * until either pci_unmap_single or pci_dma_sync_single is performed. + */ +dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, + int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + return (bus_to_baddr[hwdev->bus->number] | __pa(ptr)); +} + +/* + * Unmap a single streaming mode DMA translation. The dma_addr and size + * must match what was provided for in a previous pci_map_single call. All + * other usages are undefined. + * + * After this call, reads by the cpu to the buffer are guarenteed to see + * whatever the device wrote there. + */ +void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + /* Nothing to do */ +} + +/* + * Map a set of buffers described by scatterlist in streaming + * mode for DMA. This is the scather-gather version of the + * above pci_map_single interface. Here the scatter gather list + * elements are each tagged with the appropriate dma address + * and length. They are obtained via sg_dma_{address,length}(SG). + * + * NOTE: An implementation may be able to use a smaller number of + * DMA address/length pairs than there are SG table elements. + * (for example via virtual mapping capabilities) + * The routine returns the number of addr/length pairs actually + * used, at most nents. + * + * Device ownership issues as mentioned above for pci_map_single are + * the same here. + */ +int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, + int direction) +{ + int i; + + if (direction == PCI_DMA_NONE) + BUG(); + + /* Make sure that gcc doesn't leave the empty loop body. */ + for (i = 0; i < nents; i++, sg++) { + sg->address = (char *)(bus_to_baddr[hwdev->bus->number] | __pa(sg->address)); + } + + return nents; +} + +/* + * Unmap a set of streaming mode DMA translations. + * Again, cpu read rules concerning calls here are the same as for + * pci_unmap_single() above. + */ +void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, + int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + /* Nothing to do */ +} + +/* + * Make physical memory consistent for a single + * streaming mode DMA translation after a transfer. + * + * If you perform a pci_map_single() but wish to interrogate the + * buffer using the cpu, yet do not wish to teardown the PCI dma + * mapping, you must call this function before doing so. At the + * next point you give the PCI dma address back to the card, the + * device again owns the buffer. + */ +void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); +} + +/* + * Make physical memory consistent for a set of streaming + * mode DMA translations after a transfer. + * + * The same as pci_dma_sync_single but for a scatter-gather list, + * same rules and usage. + */ +void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nelems, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); } diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-pci.c linux/arch/mips64/sgi-ip27/ip27-pci.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-pci.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip27/ip27-pci.c Sun Sep 9 10:43:02 2001 @@ -18,7 +18,7 @@ /* * Max #PCI busses we can handle; ie, max #PCI bridges. */ -#define MAX_PCI_BUSSES 20 +#define MAX_PCI_BUSSES 40 /* * Max #PCI devices (like scsi controllers) we handle on a bus. @@ -55,8 +55,12 @@ bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ bus_to_wid[bus_id]); \ \ - /*if (dev->bus->number) */ \ - /* return PCIBIOS_DEVICE_NOT_FOUND; */ \ + if (dev->vendor == PCI_VENDOR_ID_SGI \ + && dev->device == PCI_DEVICE_ID_SGI_IOC3 \ + && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) { \ + *value = 0; \ + return PCIBIOS_SUCCESSFUL; \ + } \ \ __bit = (((where) & (bm)) << 3); \ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ @@ -96,11 +100,9 @@ bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ bus_to_wid[bus_id]); \ \ - /* if (dev->bus->number) */ \ - /* return PCIBIOS_DEVICE_NOT_FOUND; */ \ - \ if (dev->vendor == PCI_VENDOR_ID_SGI \ - && dev->device == PCI_DEVICE_ID_SGI_IOC3) \ + && dev->device == PCI_DEVICE_ID_SGI_IOC3 \ + && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) \ return PCIBIOS_SUCCESSFUL; \ \ __bit = (((where) & (bm)) << 3); \ @@ -147,6 +149,7 @@ int i; ioport_resource.end = ~0UL; + iomem_resource.end = ~0UL; for (i=0; ibus->number >= MAX_PCI_BUSSES) || (pin != 1) || \ - (slot >= MAX_DEVICES_PER_PCIBUS)) { - printk("Increase supported PCI busses %d,%d,%d\n", \ - dev->bus->number, slot, pin); - while(1); - } + if ((dev->bus->number >= MAX_PCI_BUSSES) + || (pin != 1) + || (slot >= MAX_DEVICES_PER_PCIBUS)) + panic("Increase supported PCI busses %d,%d,%d\n", + dev->bus->number, slot, pin); /* * Already assigned? Then return previously assigned value ... */ if (irqstore[dev->bus->number][slot]) - return(irqstore[dev->bus->number][slot]); - else { - irq_to_bus[lastirq] = dev->bus->number; - irq_to_slot[lastirq] = slot; - irqstore[dev->bus->number][slot] = lastirq; - lastirq++; - return (lastirq - 1); - } + return irqstore[dev->bus->number][slot]; + + irq_to_bus[lastirq] = dev->bus->number; + irq_to_slot[lastirq] = slot; + irqstore[dev->bus->number][slot] = lastirq; + lastirq++; + return lastirq - 1; } void __init @@ -237,10 +238,10 @@ pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges) { - ranges->io_start -= bus->resource[0]->start; - ranges->io_end -= bus->resource[0]->start; + ranges->io_start -= bus->resource[0]->start; + ranges->io_end -= bus->resource[0]->start; ranges->mem_start -= bus->resource[1]->start; - ranges->mem_end -= bus->resource[1]->start; + ranges->mem_end -= bus->resource[1]->start; } int __init @@ -255,6 +256,11 @@ { } +unsigned __init int pcibios_assign_all_busses(void) +{ + return 0; +} + char * __init pcibios_setup(char *str) { @@ -263,19 +269,23 @@ return str; } +/* + * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses + * to find the slot number in sense of the bridge device register. + * XXX This also means multiple devices might rely on conflicting bridge + * settings. + */ + static void __init pci_disable_swapping(struct pci_dev *dev) { unsigned int bus_id = (unsigned) dev->bus->number; bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); + bus_to_wid[bus_id]); int slot = PCI_SLOT(dev->devfn); - bridgereg_t devreg; - - devreg = bridge->b_device[slot].reg; - devreg &= ~BRIDGE_DEV_SWAP_DIR; /* turn off byte swapping */ - bridge->b_device[slot].reg = devreg; + /* Turn off byte swapping */ + bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; bridge->b_widget.w_tflush; /* Flush */ } @@ -284,56 +294,25 @@ { unsigned int bus_id = (unsigned) dev->bus->number; bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); + bus_to_wid[bus_id]); int slot = PCI_SLOT(dev->devfn); - bridgereg_t devreg; - - devreg = bridge->b_device[slot].reg; - devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */ - bridge->b_device[slot].reg = devreg; + /* Turn on byte swapping */ + bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; bridge->b_widget.w_tflush; /* Flush */ } static void __init pci_fixup_ioc3(struct pci_dev *d) { - unsigned int bus_id = (unsigned) d->bus->number; - int i; + unsigned long bus_id = (unsigned) d->bus->number; - /* IOC3 only decodes 0x20 bytes of the config space, so we end up - with tons of bogus information in the pci_dev. On Origins the - INTA, INTB and INTC pins are all wired together as if it'd only - use INTA. */ printk("PCI: Fixing base addresses for IOC3 device %s\n", d->slot_name); d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]); - d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]); - - for (i = 1; i <= PCI_ROM_RESOURCE; i++) { - d->resource[i].start = 0UL; - d->resource[i].end = 0UL; - d->resource[i].flags = 0UL; - } + d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]); pci_disable_swapping(d); - - /* - * The serial driver will try to probe for serial ports - * later on. MENET boards dbe out unrecoverably on sio space - * access to the 4th ioc3. (The first 3 iocs work okay, they - * have kbd/ms ports; all have ethernet ports). Catch this - * case now and disable the serial driver from looking at - * these ioc3s. Identify MENET cards by seeing if an ioc3 is - * at slot 3. - */ - d->subsystem_vendor = 0xFF00; - if (PCI_SLOT(d->devfn) == 3) { - struct list_head *p; - list_for_each(p, &d->bus->devices) { - list_entry(p, struct pci_dev, bus_list)->subsystem_vendor = 0; - } - } } static void __init @@ -344,7 +323,8 @@ d->resource[0].start |= ((unsigned long)(bus_to_nid[d->bus->number])<<32); printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name); - /* Configure device to allow bus mastering, i/o and memory mapping. + /* + * Configure device to allow bus mastering, i/o and memory mapping. * Older qlogicisp driver expects to have the IO space enable * bit set. Things stop working if we program the controllers as not * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-setup.c linux/arch/mips64/sgi-ip27/ip27-setup.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-setup.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip27/ip27-setup.c Sun Sep 9 10:43:02 2001 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #define DBG(x...) #endif +unsigned long mips_io_port_base = IO_BASE; /* * get_nasid() returns the physical node id number of the caller. diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip27/ip27-timer.c linux/arch/mips64/sgi-ip27/ip27-timer.c --- v2.4.9/linux/arch/mips64/sgi-ip27/ip27-timer.c Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/sgi-ip27/ip27-timer.c Sun Sep 9 10:43:02 2001 @@ -145,6 +145,9 @@ } write_unlock(&xtime_lock); + + if (softirq_pending(cpu)) + do_softirq(); } unsigned long inline do_gettimeoffset(void) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/Makefile linux/arch/mips64/sgi-ip32/Makefile --- v2.4.9/linux/arch/mips64/sgi-ip32/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/Makefile Sun Sep 9 10:43:02 2001 @@ -0,0 +1,27 @@ +# +# Makefile for the SGI specific kernel interface routines +# under Linux. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET := ip32-kern.a + +all: ip32-kern.a ip32-irq-glue.o + +obj-y += ip32-irq.o ip32-rtc.o ip32-setup.o ip32-irq-glue.o \ + ip32-berr.o ip32-timer.o crime.o + +ifdef CONFIG_PCI +obj-y += ip32-pci.o ip32-pci-dma.o +endif + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/crime.c linux/arch/mips64/sgi-ip32/crime.c --- v2.4.9/linux/arch/mips64/sgi-ip32/crime.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/crime.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,50 @@ +/* + * 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. + * + * Copyright (C) 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include + +void __init crime_init (void) +{ + u64 id = crime_read_64 (CRIME_ID); + u64 rev = id & CRIME_ID_REV; + + id = (id & CRIME_ID_IDBITS) >> 4; + + printk ("CRIME id %1lx rev %ld detected at %016lx\n", id, rev, + (unsigned long) CRIME_BASE); +} + +/* XXX Like on Sun, these give us various useful information to printk. */ +void crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) +{ + u64 memerr = crime_read_64 (CRIME_MEM_ERROR_STAT); + u64 addr = crime_read_64 (CRIME_MEM_ERROR_ADDR); + memerr &= CRIME_MEM_ERROR_STAT_MASK; + + printk ("CRIME memory error at physaddr 0x%08lx status %08lx\n", + addr << 2, memerr); + + crime_write_64 (CRIME_MEM_ERROR_STAT, 0); +} + +void crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) +{ + u64 cpuerr = crime_read_64 (CRIME_CPU_ERROR_STAT); + u64 addr = crime_read_64 (CRIME_CPU_ERROR_ADDR); + cpuerr &= CRIME_CPU_ERROR_MASK; + addr <<= 2UL; + + printk ("CRIME CPU interface error detected at %09lx status %08lx\n", + addr, cpuerr); + + crime_write_64 (CRIME_CPU_ERROR_STAT, 0); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/ip32-berr.c linux/arch/mips64/sgi-ip32/ip32-berr.c --- v2.4.9/linux/arch/mips64/sgi-ip32/ip32-berr.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/ip32-berr.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,97 @@ +/* + * 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. + * + * Copyright (C) 1994, 1995, 1996, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 by Silicon Graphics + */ +#include +#include +#include +#include +#include +#include + +/* XXX I have no idea what this does --kmw */ + +extern asmlinkage void handle_ibe(void); +extern asmlinkage void handle_dbe(void); + +extern const struct exception_table_entry __start___dbe_table[]; +extern const struct exception_table_entry __stop___dbe_table[]; + +static inline unsigned long +search_one_table(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) +{ + while (first <= last) { + const struct exception_table_entry *mid; + long diff; + + mid = (last - first) / 2 + first; + diff = mid->insn - value; + if (diff == 0) + return mid->nextinsn; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } + return 0; +} + +static inline unsigned long +search_dbe_table(unsigned long addr) +{ + unsigned long ret; + + /* There is only the kernel to search. */ + ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); + if (ret) return ret; + + return 0; +} + +void do_ibe(struct pt_regs *regs) +{ + printk("Got ibe at 0x%lx\n", regs->cp0_epc); + show_regs(regs); + dump_tlb_addr(regs->cp0_epc); + force_sig(SIGBUS, current); + while(1); +} + +void do_dbe(struct pt_regs *regs) +{ + unsigned long fixup; + + fixup = search_dbe_table(regs->cp0_epc); + if (fixup) { + long new_epc; + + new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); + regs->cp0_epc = new_epc; + return; + } + + printk("Got dbe at 0x%lx\n", regs->cp0_epc); + show_regs(regs); + dump_tlb_all(); + while(1); + force_sig(SIGBUS, current); +} + +void __init +bus_error_init(void) +{ + int dummy; + + set_except_vector(6, handle_ibe); + set_except_vector(7, handle_dbe); + + /* At this time nothing uses the DBE protection mechanism on the + O2, so this here is needed to make the kernel link. */ + get_dbe(dummy, (int *)KSEG0); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/ip32-irq-glue.S linux/arch/mips64/sgi-ip32/ip32-irq-glue.S --- v2.4.9/linux/arch/mips64/sgi-ip32/ip32-irq-glue.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/ip32-irq-glue.S Sun Sep 9 10:43:02 2001 @@ -0,0 +1,87 @@ +/* + * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead + * + * 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. + * + * Copyright (C) 2000 Harald Koerfgen + * Copyright (C) 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include + + .text + .set noreorder + .set noat + .align 5 + NESTED(ip32_handle_int, PT_SIZE, ra) + .set noat + SAVE_ALL + CLI # TEST: interrupts should be off + .set at + .set noreorder + + mfc0 s0,CP0_CAUSE + + andi t1, s0, IE_IRQ0 + bnez t1, handle_irq0 + andi t1, s0, IE_IRQ1 + bnez t1, handle_irq1 + andi t1, s0, IE_IRQ2 + bnez t1, handle_irq2 + andi t1, s0, IE_IRQ3 + bnez t1, handle_irq3 + andi t1, s0, IE_IRQ4 + bnez t1, handle_irq4 + andi t1, s0, IE_IRQ5 + bnez t1, handle_irq5 + nop + + /* Either someone has triggered the "software interrupts" + * or we lost an interrupt somehow. Ignore it. + */ + j ret_from_irq + nop + +handle_irq0: + jal ip32_irq0 + move a0, sp + j ret_from_irq + nop + +handle_irq1: + jal ip32_irq1 + move a0, sp + j ret_from_irq + nop + +handle_irq2: + jal ip32_irq2 + move a0, sp + j ret_from_irq + nop + +handle_irq3: + jal ip32_irq3 + move a0, sp + j ret_from_irq + nop + +handle_irq4: + jal ip32_irq4 + move a0, sp + j ret_from_irq + nop + +handle_irq5: + jal ip32_irq5 + move a0, sp + j ret_from_irq + nop + + END(ip32_handle_int) diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/ip32-irq.c linux/arch/mips64/sgi-ip32/ip32-irq.c --- v2.4.9/linux/arch/mips64/sgi-ip32/ip32-irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/ip32-irq.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,556 @@ +/* + * Code to handle IP32 IRQs + * + * 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. + * + * Copyright (C) 2000 Harald Koerfgen + * Copyright (C) 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_IRQ +#ifdef DEBUG_IRQ +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* O2 irq map + * + * IP0 -> software (ignored) + * IP1 -> software (ignored) + * IP2 -> (irq0) C crime 1.1 all interrupts; crime 1.5 ??? + * IP3 -> (irq1) X unknown + * IP4 -> (irq2) X unknown + * IP5 -> (irq3) X unknown + * IP6 -> (irq4) X unknown + * IP7 -> (irq5) 0 CPU count/compare timer (system timer) + * + * crime: (C) + * + * CRIME_INT_STAT 31:0: + * + * 0 -> 1 Video in 1 + * 1 -> 2 Video in 2 + * 2 -> 3 Video out + * 3 -> 4 Mace ethernet + * 4 -> S SuperIO sub-interrupt + * 5 -> M Miscellaneous sub-interrupt + * 6 -> A Audio sub-interrupt + * 7 -> 8 PCI bridge errors + * 8 -> 9 PCI SCSI aic7xxx 0 + * 9 -> 10 PCI SCSI aic7xxx 1 + * 10 -> 11 PCI slot 0 + * 11 -> 12 unused (PCI slot 1) + * 12 -> 13 unused (PCI slot 2) + * 13 -> 14 unused (PCI shared 0) + * 14 -> 15 unused (PCI shared 1) + * 15 -> 16 unused (PCI shared 2) + * 16 -> 17 GBE0 (E) + * 17 -> 18 GBE1 (E) + * 18 -> 19 GBE2 (E) + * 19 -> 20 GBE3 (E) + * 20 -> 21 CPU errors + * 21 -> 22 Memory errors + * 22 -> 23 RE empty edge (E) + * 23 -> 24 RE full edge (E) + * 24 -> 25 RE idle edge (E) + * 25 -> 26 RE empty level + * 26 -> 27 RE full level + * 27 -> 28 RE idle level + * 28 -> 29 unused (software 0) (E) + * 29 -> 30 unused (software 1) (E) + * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E) + * 31 -> 32 VICE + * + * S, M, A: Use the MACE ISA interrupt register + * MACE_ISA_INT_STAT 31:0 + * + * 0-7 -> 33-40 Audio + * 8 -> 41 RTC + * 9 -> 42 Keyboard + * 10 -> X Keyboard polled + * 11 -> 44 Mouse + * 12 -> X Mouse polled + * 13-15 -> 46-48 Count/compare timers + * 16-19 -> 49-52 Parallel (16 E) + * 20-25 -> 53-58 Serial 1 (22 E) + * 26-31 -> 59-64 Serial 2 (28 E) + * + * Note that this means IRQs 5-7, 43, and 45 do not exist. This is a + * different IRQ map than IRIX uses, but that's OK as Linux irq handling + * is quite different anyway. + */ + +/* Some initial interrupts to set up */ +extern void crime_memerr_intr (unsigned int irq, void *dev_id, + struct pt_regs *regs); +extern void crime_cpuerr_intr (unsigned int irq, void *dev_id, + struct pt_regs *regs); + +struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT, + 0, "CRIME memory error", NULL, + NULL }; +struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT, + 0, "CRIME CPU error", NULL, + NULL }; + +unsigned long spurious_count = 0; +extern void ip32_handle_int (void); +extern void do_IRQ (unsigned int irq, struct pt_regs *regs); + +/* For interrupts wired from a single device to the CPU. Only the clock + * uses this it seems, which is IRQ 0 and IP7. + */ + +static void enable_cpu_irq (unsigned int irq) +{ + set_cp0_status (STATUSF_IP7); +} + +static unsigned int startup_cpu_irq (unsigned int irq) { + enable_cpu_irq (irq); + return 0; +} + +static void disable_cpu_irq (unsigned int irq) +{ + clear_cp0_status (STATUSF_IP7); +} + +static void end_cpu_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_cpu_irq (irq); +} + +#define shutdown_cpu_irq disable_cpu_irq +#define mask_and_ack_cpu_irq disable_cpu_irq + +static struct hw_interrupt_type ip32_cpu_interrupt = { + "IP32 CPU", + startup_cpu_irq, + shutdown_cpu_irq, + enable_cpu_irq, + disable_cpu_irq, + mask_and_ack_cpu_irq, + end_cpu_irq, + NULL +}; + +/* + * This is for pure CRIME interrupts - ie not MACE. The advantage? + * We get to split the register in half and do faster lookups. + */ + +static void enable_crime_irq (unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + save_and_cli (flags); + crime_mask = crime_read_64 (CRIME_INT_MASK); + crime_mask |= 1 << (irq - 1); + crime_write_64 (CRIME_INT_MASK, crime_mask); + restore_flags (flags); +} + +static unsigned int startup_crime_irq (unsigned int irq) +{ + enable_crime_irq (irq); + return 0; /* This is probably not right; we could have pending irqs */ +} + +static void disable_crime_irq (unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + save_and_cli (flags); + crime_mask = crime_read_64 (CRIME_INT_MASK); + crime_mask &= ~(1 << (irq - 1)); + crime_write_64 (CRIME_INT_MASK, crime_mask); + restore_flags (flags); +} + +static void mask_and_ack_crime_irq (unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + /* Edge triggered interrupts must be cleared. */ + if ((irq <= CRIME_GBE0_IRQ && irq >= CRIME_GBE3_IRQ) + || (irq <= CRIME_RE_EMPTY_E_IRQ && irq >= CRIME_RE_IDLE_E_IRQ) + || (irq <= CRIME_SOFT0_IRQ && irq >= CRIME_SOFT2_IRQ)) { + save_and_cli (flags); + crime_mask = crime_read_64 (CRIME_HARD_INT); + crime_mask &= ~(1 << (irq - 1)); + crime_write_64 (CRIME_HARD_INT, crime_mask); + restore_flags (flags); + } + disable_crime_irq (irq); +} + +static void end_crime_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_crime_irq (irq); +} + +#define shutdown_crime_irq disable_crime_irq + +static struct hw_interrupt_type ip32_crime_interrupt = { + "IP32 CRIME", + startup_crime_irq, + shutdown_crime_irq, + enable_crime_irq, + disable_crime_irq, + mask_and_ack_crime_irq, + end_crime_irq, + NULL +}; + +/* This is for MACE PCI interrupts. We can decrease bus traffic by masking + * as close to the source as possible. This also means we can take the + * next chunk of the CRIME register in one piece. + */ + +static void enable_macepci_irq (unsigned int irq) +{ + u32 mace_mask; + u64 crime_mask; + unsigned long flags; + + save_and_cli (flags); + mace_mask = mace_read_32 (MACEPCI_CONTROL); + mace_mask |= MACEPCI_CONTROL_INT (irq - 9); + mace_write_32 (MACEPCI_CONTROL, mace_mask); + /* In case the CRIME interrupt isn't enabled, we must enable it; + * however, we never disable interrupts at that level. + */ + crime_mask = crime_read_64 (CRIME_INT_MASK); + crime_mask |= 1 << (irq - 1); + crime_write_64 (CRIME_INT_MASK, crime_mask); + restore_flags (flags); +} + +static unsigned int startup_macepci_irq (unsigned int irq) { + enable_macepci_irq (irq); + return 0; /* XXX */ +} + +static void disable_macepci_irq (unsigned int irq) +{ + u32 mace_mask; + unsigned long flags; + + save_and_cli (flags); + mace_mask = mace_read_32 (MACEPCI_CONTROL); + mace_mask &= ~MACEPCI_CONTROL_INT (irq - 9); + mace_write_32 (MACEPCI_CONTROL, mace_mask); + restore_flags (flags); +} + +static void end_macepci_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_macepci_irq (irq); +} + +#define shutdown_macepci_irq disable_macepci_irq +#define mask_and_ack_macepci_irq disable_macepci_irq + +static struct hw_interrupt_type ip32_macepci_interrupt = { + "IP32 MACE PCI", + startup_macepci_irq, + shutdown_macepci_irq, + enable_macepci_irq, + disable_macepci_irq, + mask_and_ack_macepci_irq, + end_macepci_irq, + NULL +}; + +/* This is used for MACE ISA interrupts. That means bits 4-6 in the + * CRIME register. + */ + +static void enable_maceisa_irq (unsigned int irq) +{ + u64 crime_mask; + u32 mace_mask; + unsigned int crime_int = 0; + unsigned long flags; + + DBG ("maceisa enable: %u\n", irq); + + switch (irq) { + case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: + crime_int = MACE_AUDIO_INT; + break; + case MACEISA_RTC_IRQ ... MACEISA_TIMER2_IRQ: + crime_int = MACE_MISC_INT; + break; + case MACEISA_PARALLEL_IRQ ... MACEISA_SERIAL2_RDMAOR_IRQ: + crime_int = MACE_SUPERIO_INT; + break; + } + DBG ("crime_int %016lx enabled\n", crime_int); + save_and_cli (flags); + crime_mask = crime_read_64 (CRIME_INT_MASK); + crime_mask |= crime_int; + crime_write_64 (CRIME_INT_MASK, crime_mask); + mace_mask = mace_read_32 (MACEISA_INT_MASK); + mace_mask |= 1 << (irq - 33); + mace_write_32 (MACEISA_INT_MASK, mace_mask); + restore_flags (flags); +} + +static unsigned int startup_maceisa_irq (unsigned int irq) { + enable_maceisa_irq (irq); + return 0; +} + +static void disable_maceisa_irq (unsigned int irq) +{ + u32 mace_mask; + unsigned long flags; + + save_and_cli (flags); + mace_mask = mace_read_32 (MACEISA_INT_MASK); + mace_mask &= ~(1 << (irq - 33)); + mace_write_32 (MACEISA_INT_MASK, mace_mask); + restore_flags (flags); +} + +static void mask_and_ack_maceisa_irq (unsigned int irq) +{ + u32 mace_mask; + unsigned long flags; + + switch (irq) { + case MACEISA_PARALLEL_IRQ: + case MACEISA_SERIAL1_TDMAPR_IRQ: + case MACEISA_SERIAL2_TDMAPR_IRQ: + save_and_cli (flags); + mace_mask = mace_read_32 (MACEISA_INT_STAT); + mace_mask &= ~(1 << (irq - 33)); + mace_write_32 (MACEISA_INT_STAT, mace_mask); + restore_flags (flags); + break; + } + disable_maceisa_irq (irq); +} + +static void end_maceisa_irq (unsigned irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_maceisa_irq (irq); +} + +#define shutdown_maceisa_irq disable_maceisa_irq + +static struct hw_interrupt_type ip32_maceisa_interrupt = { + "IP32 MACE ISA", + startup_maceisa_irq, + shutdown_maceisa_irq, + enable_maceisa_irq, + disable_maceisa_irq, + mask_and_ack_maceisa_irq, + end_maceisa_irq, + NULL +}; + +/* This is used for regular non-ISA, non-PCI MACE interrupts. That means + * bits 0-3 and 7 in the CRIME register. + */ + +static void enable_mace_irq (unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + save_and_cli (flags); + crime_mask = crime_read_64 (CRIME_INT_MASK); + crime_mask |= 1 << (irq - 1); + crime_write_64 (CRIME_INT_MASK, crime_mask); + restore_flags (flags); +} + +static unsigned int startup_mace_irq (unsigned int irq) +{ + enable_mace_irq (irq); + return 0; +} + +static void disable_mace_irq (unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + save_and_cli (flags); + crime_mask = crime_read_64 (CRIME_INT_MASK); + crime_mask &= ~(1 << (irq - 1)); + crime_write_64 (CRIME_INT_MASK, crime_mask); + restore_flags (flags); +} + +static void end_mace_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_mace_irq (irq); +} + +#define shutdown_mace_irq disable_mace_irq +#define mask_and_ack_mace_irq disable_mace_irq + +static struct hw_interrupt_type ip32_mace_interrupt = { + "IP32 MACE", + startup_mace_irq, + shutdown_mace_irq, + enable_mace_irq, + disable_mace_irq, + mask_and_ack_mace_irq, + end_mace_irq, + NULL +}; + +static void ip32_unknown_interrupt (struct pt_regs *regs) +{ + u64 crime; + u32 mace; + + printk ("Unknown interrupt occurred!\n"); + printk ("cp0_status: %08x\tcp0_cause: %08x\n", + read_32bit_cp0_register (CP0_STATUS), + read_32bit_cp0_register (CP0_CAUSE)); + crime = crime_read_64 (CRIME_INT_MASK); + printk ("CRIME interrupt mask: %016lx\n", crime); + crime = crime_read_64 (CRIME_INT_STAT); + printk ("CRIME interrupt status: %016lx\n", crime); + crime = crime_read_64 (CRIME_HARD_INT); + printk ("CRIME hardware interrupt register: %016lx\n", crime); + mace = mace_read_32 (MACEISA_INT_MASK); + printk ("MACE ISA interrupt mask: %08x\n", mace); + mace = mace_read_32 (MACEISA_INT_STAT); + printk ("MACE ISA interrupt status: %08x\n", mace); + mace = mace_read_32 (MACEPCI_CONTROL); + printk ("MACE PCI control register: %08x\n", mace); + + printk ("Register dump:\n"); + show_regs (regs); + + printk ("Please mail this report to linux-mips@oss.sgi.com\n"); + printk ("Spinning..."); + while (1) ; +} + +void __init ip32_irq_init(void) +{ + unsigned int irq; + extern void init_generic_irq (void); + + /* Install our interrupt handler, then clear and disable all + * CRIME and MACE interrupts. + */ + crime_write_64 (CRIME_INT_MASK, 0); + crime_write_64 (CRIME_HARD_INT, 0); + crime_write_64 (CRIME_SOFT_INT, 0); + mace_write_32 (MACEISA_INT_STAT, 0); + mace_write_32 (MACEISA_INT_MASK, 0); + set_except_vector(0, ip32_handle_int); + + init_generic_irq (); + + for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { + hw_irq_controller *controller; + + if (irq == CLOCK_IRQ) + controller = &ip32_cpu_interrupt; + else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ) + controller = &ip32_mace_interrupt; + else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ) + controller = &ip32_macepci_interrupt; + else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ) + controller = &ip32_crime_interrupt; + else + controller = &ip32_maceisa_interrupt; + + irq_desc[irq].status = IRQ_DISABLED; + irq_desc[irq].action = 0; + irq_desc[irq].depth = 0; + irq_desc[irq].handler = controller; + } + setup_irq (CRIME_MEMERR_IRQ, &memerr_irq); + setup_irq (CRIME_CPUERR_IRQ, &cpuerr_irq); +} + +/* CRIME 1.1 appears to deliver all interrupts to this one pin. */ +void ip32_irq0 (struct pt_regs *regs) +{ + u64 crime_int = crime_read_64 (CRIME_INT_STAT); + int irq = 0; + + if (crime_int & CRIME_MACE_INT_MASK) { + crime_int &= CRIME_MACE_INT_MASK; + irq = ffs (crime_int); + } else if (crime_int & CRIME_MACEISA_INT_MASK) { + u32 mace_int; + mace_int = mace_read_32 (MACEISA_INT_STAT); + if (mace_int == 0) + irq = 0; + else + irq = ffs (mace_int) + 32; + } else if (crime_int & CRIME_MACEPCI_INT_MASK) { + crime_int &= CRIME_MACEPCI_INT_MASK; + crime_int >>= 8; + irq = ffs (crime_int) + 8; + } else if (crime_int & 0xffff0000) { + crime_int >>= 16; + irq = ffs (crime_int) + 16; + } + if (irq == 0) + ip32_unknown_interrupt (regs); + DBG ("*irq %u*\n", irq); + do_IRQ (irq, regs); +} + +void ip32_irq1 (struct pt_regs *regs) +{ + ip32_unknown_interrupt (regs); +} + +void ip32_irq2 (struct pt_regs *regs) +{ + ip32_unknown_interrupt (regs); +} + +void ip32_irq3 (struct pt_regs *regs) +{ + ip32_unknown_interrupt (regs); +} + +void ip32_irq4 (struct pt_regs *regs) +{ + ip32_unknown_interrupt (regs); +} + +void ip32_irq5 (struct pt_regs *regs) +{ + do_IRQ (CLOCK_IRQ, regs); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/ip32-pci-dma.c linux/arch/mips64/sgi-ip32/ip32-pci-dma.c --- v2.4.9/linux/arch/mips64/sgi-ip32/ip32-pci-dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/ip32-pci-dma.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,41 @@ +/* + * 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. + * + * Copyright (C) 2000 Ani Joshi + * Copyright (C) 2000 Ralf Baechle + * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. + */ +#include +#include +#include +#include + +#include +#include +#include + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) + gfp |= GFP_DMA; + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + dma_cache_wback_inv((unsigned long) ret, size); + *dma_handle = virt_to_bus(ret); + } + return ret; +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long) vaddr, get_order(size)); +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/ip32-pci.c linux/arch/mips64/sgi-ip32/ip32-pci.c --- v2.4.9/linux/arch/mips64/sgi-ip32/ip32-pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/ip32-pci.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,438 @@ +/* + * 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. + * + * Copyright (C) 2000, 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_MACE_PCI + +/* + * O2 has up to 5 PCI devices connected into the MACE bridge. The device + * map looks like this: + * + * 0 aic7xxx 0 + * 1 aic7xxx 1 + * 2 expansion slot + * 3 N/C + * 4 N/C + */ + +#define chkslot(dev) \ +do { \ + if ((dev)->bus->number > 0 || PCI_SLOT ((dev)->devfn) < 1 \ + || PCI_SLOT ((dev)->devfn) > 3) \ + return PCIBIOS_DEVICE_NOT_FOUND; \ +} while (0) + +#define mkaddr(dev, where) \ +((((dev)->devfn & 0xffUL) << 8) | ((where) & 0xfcUL)) + +void macepci_error (int irq, void *dev, struct pt_regs *regs); + +static int macepci_read_config_byte (struct pci_dev *dev, int where, + u8 *val) +{ + *val = 0xff; + chkslot (dev); + mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); + *val = mace_read_8 (MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL)); + + return PCIBIOS_SUCCESSFUL; +} + +static int macepci_read_config_word (struct pci_dev *dev, int where, + u16 *val) +{ + *val = 0xffff; + chkslot (dev); + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); + *val = mace_read_16 (MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL)); + + return PCIBIOS_SUCCESSFUL; +} + +static int macepci_read_config_dword (struct pci_dev *dev, int where, + u32 *val) +{ + *val = 0xffffffff; + chkslot (dev); + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); + *val = mace_read_32 (MACEPCI_CONFIG_DATA); + + return PCIBIOS_SUCCESSFUL; +} + +static int macepci_write_config_byte (struct pci_dev *dev, int where, + u8 val) +{ + chkslot (dev); + mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); + mace_write_8 (MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int macepci_write_config_word (struct pci_dev *dev, int where, + u16 val) +{ + chkslot (dev); + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); + mace_write_16 (MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int macepci_write_config_dword (struct pci_dev *dev, int where, + u32 val) +{ + chkslot (dev); + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); + mace_write_32 (MACEPCI_CONFIG_DATA, val); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops macepci_ops = { + macepci_read_config_byte, + macepci_read_config_word, + macepci_read_config_dword, + macepci_write_config_byte, + macepci_write_config_word, + macepci_write_config_dword +}; + +struct pci_fixup pcibios_fixups[] = { { 0 } }; + +void __init pcibios_init (void) +{ + struct pci_dev *dev; + u32 start, size; + u16 cmd; + u32 base_io = 0x3000; /* The first i/o address to assign after SCSI */ + u32 base_mem = 0x80100000; /* Likewise */ + u32 rev = mace_read_32 (MACEPCI_REV); + int i; + + printk ("MACE: PCI rev %d detected at %016lx\n", rev, + (u64) MACE_BASE + MACE_PCI); + + /* These are *bus* addresses */ + ioport_resource.start = 0; + ioport_resource.end = 0xffffffffUL; + iomem_resource.start = 0x80000000UL; + iomem_resource.end = 0xffffffffUL; + + /* Clear any outstanding errors and enable interrupts */ + mace_write_32 (MACEPCI_ERROR_ADDR, 0); + mace_write_32 (MACEPCI_ERROR_FLAGS, 0); + mace_write_32 (MACEPCI_CONTROL, 0xff008500); + crime_write_64 (CRIME_HARD_INT, 0UL); + crime_write_64 (CRIME_SOFT_INT, 0UL); + crime_write_64 (CRIME_INT_STAT, 0x000000000000ff00UL); + + if (request_irq (MACE_PCI_BRIDGE_IRQ, macepci_error, 0, + "MACE PCI error", NULL)) + panic ("PCI bridge can't get interrupt; can't happen.\n"); + + pci_scan_bus (0, &macepci_ops, NULL); + +#ifdef DEBUG_MACE_PCI + pci_for_each_dev (dev) { + printk ("Device: %d/%d/%d ARCS-assigned bus resource map\n", + dev->bus->number, PCI_SLOT (dev->devfn), + PCI_FUNC (dev->devfn)); + for (i=0; i < DEVICE_COUNT_RESOURCE; i++) { + if (dev->resource[i].start == 0) + continue; + printk ("%d: %016lx - %016lx (flags %04lx)\n", + i, dev->resource[i].start, + dev->resource[i].end, dev->resource[i].flags); + } + } +#endif + /* + * Assign sane resources to and enable all devices. The requirement + * for the SCSI controllers is well-known: a 256-byte I/O region + * which we must assign, and a 1-page memory region which is + * assigned by the system firmware. + */ + pci_for_each_dev (dev) { + switch (PCI_SLOT (dev->devfn)) { + case 1: /* SCSI bus 0 */ + dev->resource[0].start = 0x1000UL; + dev->resource[0].end = 0x10ffUL; + break; + case 2: /* SCSI bus 1 */ + dev->resource[0].start = 0x2000UL; + dev->resource[0].end = 0x20ffUL; + break; + default: /* Slots - I guess we have only 1 */ + for (i=0; i < 6; i++) { + size = dev->resource[i].end + - dev->resource[i].start; + if (!size + || !(dev->resource[i].flags + & (IORESOURCE_IO|IORESOURCE_MEM))) { + dev->resource[i].start + = dev->resource[i].end = 0UL; + continue; + } + if (dev->resource[i].flags & IORESOURCE_IO) { + dev->resource[i].start = base_io; + base_io += PAGE_ALIGN (size); + } else { + dev->resource[i].start = base_mem; + base_mem += 0x100000UL; + } + dev->resource[i].end = + dev->resource[i].start + size; + } + break; + } + for (i=0; i < 6; i++) { + if (dev->resource[i].start == 0) + continue; + start = dev->resource[i].start; + if (dev->resource[i].flags & IORESOURCE_IO) + start |= 1; + pci_write_config_dword (dev, + PCI_BASE_ADDRESS_0 + (i << 2), (u32) start); + } + pci_write_config_byte (dev, PCI_CACHE_LINE_SIZE, 0x20); + pci_write_config_byte (dev, PCI_LATENCY_TIMER, 0x30); + pci_read_config_word (dev, PCI_COMMAND, &cmd); + cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_PARITY); + pci_write_config_word (dev, PCI_COMMAND, cmd); + pci_set_master (dev); + } + +#ifdef DEBUG_MACE_PCI + printk ("Triggering PCI bridge interrupt...\n"); + mace_write_32 (MACEPCI_ERROR_FLAGS, MACEPCI_ERROR_INTERRUPT_TEST); + + pci_for_each_dev (dev) { + printk ("Device: %d/%d/%d final bus resource map\n", + dev->bus->number, PCI_SLOT (dev->devfn), + PCI_FUNC (dev->devfn)); + for (i=0; i < DEVICE_COUNT_RESOURCE; i++) { + if (dev->resource[i].start == 0) + continue; + printk ("%d: %016lx - %016lx (flags %04lx)\n", + i, dev->resource[i].start, + dev->resource[i].end, dev->resource[i].flags); + } + } +#endif +} + +/* + * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of + * the device (1-4 => A-D), tell what irq to use. Note that we don't + * in theory have slots 4 and 5, and we never normally use the shared + * irqs. I suppose a device without a pin A will thank us for doing it + * right if there exists such a broken piece of crap. + */ +static int __init macepci_map_irq (struct pci_dev *dev, u8 slot, u8 pin) +{ + chkslot (dev); + if (pin == 0) + pin = 1; + switch (slot) { + case 1: + return MACEPCI_SCSI0_IRQ; + case 2: + return MACEPCI_SCSI1_IRQ; + case 3: + switch (pin) { + case 2: + return MACEPCI_SHARED0_IRQ; + case 3: + return MACEPCI_SHARED1_IRQ; + case 4: + return MACEPCI_SHARED2_IRQ; + case 1: + default: + return MACEPCI_SLOT0_IRQ; + } + case 4: + switch (pin) { + case 2: + return MACEPCI_SHARED2_IRQ; + case 3: + return MACEPCI_SHARED0_IRQ; + case 4: + return MACEPCI_SHARED1_IRQ; + case 1: + default: + return MACEPCI_SLOT1_IRQ; + } + return MACEPCI_SLOT1_IRQ; + case 5: + switch (pin) { + case 2: + return MACEPCI_SHARED1_IRQ; + case 3: + return MACEPCI_SHARED2_IRQ; + case 4: + return MACEPCI_SHARED0_IRQ; + case 1: + default: + return MACEPCI_SLOT2_IRQ; + } + default: + return 0; + } +} + +/* + * It's not entirely clear what this does in a system with no bridges. + * In any case, bridges are not supported by Linux in O2. + */ +static u8 __init macepci_swizzle (struct pci_dev *dev, u8 *pinp) +{ + if (PCI_SLOT (dev->devfn) == 2) + *pinp = 2; + else + *pinp = 1; + return PCI_SLOT (dev->devfn); +} + +/* All devices are enabled during initialization. */ +int pcibios_enable_device (struct pci_dev *dev) +{ + return PCIBIOS_SUCCESSFUL; +} + +char * __init pcibios_setup (char *str) +{ + return str; +} + +void __init 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) +{ +} + +void __init pcibios_update_irq (struct pci_dev *dev, int irq) +{ + pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); +} + +void __init pcibios_fixup_bus (struct pci_bus *b) +{ + pci_fixup_irqs (macepci_swizzle, macepci_map_irq); +} + +/* XXX anybody know what this is supposed to do? */ +void __init pcibios_fixup_pbus_ranges(struct pci_bus * bus, + struct pbus_set_ranges_data * ranges) +{ + ranges->io_start -= bus->resource[0]->start; + ranges->io_end -= bus->resource[0]->start; + ranges->mem_start -= bus->resource[1]->start; + ranges->mem_end -= bus->resource[1]->start; +} + +/* + * Handle errors from the bridge. This includes master and target aborts, + * various command and address errors, and the interrupt test. This gets + * registered on the bridge error irq. It's conceivable that some of these + * conditions warrant a panic. Anybody care to say which ones? + */ +void macepci_error (int irq, void *dev, struct pt_regs *regs) { + u32 flags, error_addr; + char space; + + flags = mace_read_32 (MACEPCI_ERROR_FLAGS); + error_addr = mace_read_32 (MACEPCI_ERROR_ADDR); + + if (flags & MACEPCI_ERROR_MEMORY_ADDR) + space = 'M'; + else if (flags & MACEPCI_ERROR_CONFIG_ADDR) + space = 'C'; + else space = 'X'; + + if (flags & MACEPCI_ERROR_MASTER_ABORT) { + printk ("MACEPCI: Master abort at 0x%08x (%c)\n", error_addr, + space); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_MASTER_ABORT); + } + if (flags & MACEPCI_ERROR_TARGET_ABORT) { + printk ("MACEPCI: Target abort at 0x%08x (%c)\n", error_addr, + space); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_TARGET_ABORT); + } + if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) { + printk ("MACEPCI: Data parity error at 0x%08x (%c)\n", + error_addr, space); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_DATA_PARITY_ERR); + } + if (flags & MACEPCI_ERROR_RETRY_ERR) { + printk ("MACEPCI: Retry error at 0x%08x (%c)\n", error_addr, + space); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_RETRY_ERR); + } + if (flags & MACEPCI_ERROR_ILLEGAL_CMD) { + printk ("MACEPCI: Illegal command at 0x%08x (%c)\n", + error_addr, space); + mace_write_32 (MACEPCI_ERROR_FLAGS, + flags & ~MACEPCI_ERROR_ILLEGAL_CMD); + } + if (flags & MACEPCI_ERROR_SYSTEM_ERR) { + printk ("MACEPCI: System error at 0x%08x (%c)\n", + error_addr, space); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_SYSTEM_ERR); + } + if (flags & MACEPCI_ERROR_PARITY_ERR) { + printk ("MACEPCI: Parity error at 0x%08x (%c)\n", error_addr, + space); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_PARITY_ERR); + } + if (flags & MACEPCI_ERROR_OVERRUN) { + printk ("MACEPCI: Overrun error at 0x%08x (%c)\n", + error_addr, space); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_OVERRUN); + } + if (flags & MACEPCI_ERROR_SIG_TABORT) { + printk ("MACEPCI: Signaled target abort (clearing)\n"); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_SIG_TABORT); + } + if (flags & MACEPCI_ERROR_INTERRUPT_TEST) { + printk ("MACEPCI: Interrupt test triggered (clearing)\n"); + mace_write_32 (MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_INTERRUPT_TEST); + } +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/ip32-rtc.c linux/arch/mips64/sgi-ip32/ip32-rtc.c --- v2.4.9/linux/arch/mips64/sgi-ip32/ip32-rtc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/ip32-rtc.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,32 @@ +/* + * RTC routines for IP32 style attached Dallas chip. + * + * 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. + * + * Copyright (C) 2000 Harald Koerfgen + */ +#include +#include + +static unsigned char ip32_rtc_read_data(unsigned long addr) +{ + return (unsigned char) mace_read_8 (MACEISA_RTC_BASE + (addr << 8)); +} + +static void ip32_rtc_write_data(unsigned char data, unsigned long addr) +{ + mace_write_8 (MACEISA_RTC_BASE + (addr << 8), data); +} + +static int ip32_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops ip32_rtc_ops = { + &ip32_rtc_read_data, + &ip32_rtc_write_data, + &ip32_rtc_bcd_mode +}; diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/ip32-setup.c linux/arch/mips64/sgi-ip32/ip32-setup.c --- v2.4.9/linux/arch/mips64/sgi-ip32/ip32-setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/ip32-setup.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,62 @@ +/* + * IP32 basic setup + * + * 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. + * + * Copyright (C) 2000 Harald Koerfgen + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct rtc_ops ip32_rtc_ops; +extern u32 cc_interval; + +void __init ip32_init (int argc, char **argv, char **envp) { + arc_meminit (); +} + +void __init ip32_setup(void) +{ +#ifdef CONFIG_SERIAL_CONSOLE + char *ctype; +#endif + TLBMISS_HANDLER_SETUP (); + +#ifdef CONFIG_SERIAL_CONSOLE + ctype = ArcGetEnvironmentVariable("console"); + if (*ctype == 'd') { + if (ctype[1] == '2') + console_setup ("ttyS1"); + else + console_setup ("ttyS0"); + } +#endif + +#ifdef CONFIG_VT + conswitchp = &dummy_con; +#endif + + rtc_ops = &ip32_rtc_ops; + + crime_init (); +} + +int __init page_is_ram (unsigned long pagenr) +{ + /* XXX: to do? */ + return 1; +} diff -u --recursive --new-file v2.4.9/linux/arch/mips64/sgi-ip32/ip32-timer.c linux/arch/mips64/sgi-ip32/ip32-timer.c --- v2.4.9/linux/arch/mips64/sgi-ip32/ip32-timer.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip32/ip32-timer.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,47 @@ +/* + * IP32 timer calibration + * + * 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. + * + * Copyright (C) 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include +#include + +extern u32 cc_interval; + +/* An arbitrary time; this can be decreased if reliability looks good */ +#define WAIT_MS 10 +#define PER_MHZ (1000000 / 2 / HZ) + +void __init ip32_timer_setup (struct irqaction *irq) { + u64 crime_time; + u32 cc_tick; + + printk("Calibrating system timer... "); + + crime_time = crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK; + cc_tick = read_32bit_cp0_register (CP0_COUNT); + + while ((crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK) - crime_time + < WAIT_MS * 1000000 / CRIME_NS_PER_TICK) + ; + cc_tick = read_32bit_cp0_register (CP0_COUNT) - cc_tick; + cc_interval = cc_tick / HZ * (1000 / WAIT_MS); + /* The round-off seems unnecessary; in testing, the error of the + * above procedure is < 100 ticks, which means it gets filtered + * out by the HZ adjustment. + */ + cc_interval = (cc_interval / PER_MHZ) * PER_MHZ; + + printk("%d MHz CPU detected\n", (int) (cc_interval / PER_MHZ)); + + setup_irq (CLOCK_IRQ, irq); +} diff -u --recursive --new-file v2.4.9/linux/arch/parisc/kernel/init_task.c linux/arch/parisc/kernel/init_task.c --- v2.4.9/linux/arch/parisc/kernel/init_task.c Tue Dec 5 12:29:39 2000 +++ linux/arch/parisc/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -6,7 +6,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/parisc/kernel/pdc_cons.c linux/arch/parisc/kernel/pdc_cons.c --- v2.4.9/linux/arch/parisc/kernel/pdc_cons.c Tue Dec 5 12:29:39 2000 +++ linux/arch/parisc/kernel/pdc_cons.c Sun Sep 16 21:23:15 2001 @@ -141,11 +141,7 @@ --pdc_console_initialized; #ifdef CONFIG_VT_CONSOLE - { - /* fixme (needed?): Wait for console-tasklet to finish !*/ - extern struct tasklet_struct console_tasklet; - tasklet_schedule(&console_tasklet); - } + schedule_console_callback(); #endif unregister_console(&pdc_cons); diff -u --recursive --new-file v2.4.9/linux/arch/parisc/kernel/ptrace.c linux/arch/parisc/kernel/ptrace.c --- v2.4.9/linux/arch/parisc/kernel/ptrace.c Wed Jul 25 17:10:18 2001 +++ linux/arch/parisc/kernel/ptrace.c Tue Sep 18 16:56:19 2001 @@ -31,6 +31,20 @@ #define PT_SINGLESTEP 0x10000 #define PT_BLOCKSTEP 0x20000 +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the trap bits are not set */ + pa_psw(child)->r = 0; + pa_psw(child)->t = 0; + pa_psw(child)->h = 0; + pa_psw(child)->l = 0; +} + long sys_ptrace(long request, pid_t pid, long addr, long data) { struct task_struct *child; @@ -226,17 +240,8 @@ goto out_wake; case PTRACE_DETACH: - ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out_tsk; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS|PT_SINGLESTEP|PT_BLOCKSTEP); - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - goto out_wake_notrap; + ret = ptrace_detach(child, data); + goto out_tsk; default: ret = -EIO; 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 Sun Sep 16 21:25:28 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) @@ -86,6 +87,9 @@ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd +# All the instructions talk about "make bzImage". +bzImage: zImage + $(BOOT_TARGETS): $(CHECKS) vmlinux @$(MAKEBOOT) $@ @@ -99,5 +103,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 Sun Sep 16 21:22:50 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, }; @@ -760,20 +760,6 @@ break; } return 0; -} - -void dbprintf(const char *fmt , ...) -{ - static char buf[1024]; - va_list args; - extern void console_print (const char *str); - extern int vsprintf(char * buf, const char * fmt, va_list args); - - va_start(args, fmt); - vsprintf(buf, fmt, args); - va_end(args); - - console_print (buf); } static NORET_TYPE void amiga_reset( void ) 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 Sun Sep 16 21:22:50 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 @@ -325,7 +314,6 @@ EXPORT_SYMBOL(tb_ticks_per_jiffy); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); -EXPORT_SYMBOL(console_lock); #ifdef CONFIG_XMON EXPORT_SYMBOL(xmon); #endif @@ -367,3 +355,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 Mon Sep 17 15:29:09 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 @@ -48,7 +48,6 @@ struct task_struct *last_task_used_math = NULL; struct task_struct *last_task_used_altivec = NULL; -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; @@ -59,8 +58,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 +321,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 +358,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/ptrace.c linux/arch/ppc/kernel/ptrace.c --- v2.4.9/linux/arch/ppc/kernel/ptrace.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/ptrace.c Tue Sep 18 16:56:19 2001 @@ -89,6 +89,17 @@ regs->msr &= ~MSR_SE; } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the single step bit is not set. */ + clear_single_step(child); +} + int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -249,23 +260,9 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - /* make sure the single step bit is not set. */ - clear_single_step(child); - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: + ret = ptrace_detach(child, data); break; - } default: ret = -EIO; 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/s390/kernel/init_task.c linux/arch/s390/kernel/init_task.c --- v2.4.9/linux/arch/s390/kernel/init_task.c Fri May 12 11:41:44 2000 +++ linux/arch/s390/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -12,7 +12,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/s390/kernel/ptrace.c linux/arch/s390/kernel/ptrace.c --- v2.4.9/linux/arch/s390/kernel/ptrace.c Wed Jul 25 17:10:18 2001 +++ linux/arch/s390/kernel/ptrace.c Tue Sep 18 16:58:03 2001 @@ -202,6 +202,17 @@ return(0); } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the single step bit is not set. */ + clear_single_step(child); +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -327,20 +338,7 @@ break; case PTRACE_DETACH: /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - /* make sure the single step bit is not set. */ - clear_single_step(child); - wake_up_process(child); - ret = 0; + ret = ptrace_detach(child, data); break; case PTRACE_PEEKUSR_AREA: case PTRACE_POKEUSR_AREA: diff -u --recursive --new-file v2.4.9/linux/arch/s390x/kernel/init_task.c linux/arch/s390x/kernel/init_task.c --- v2.4.9/linux/arch/s390x/kernel/init_task.c Tue Feb 13 14:13:44 2001 +++ linux/arch/s390x/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -12,7 +12,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/s390x/kernel/ptrace.c linux/arch/s390x/kernel/ptrace.c --- v2.4.9/linux/arch/s390x/kernel/ptrace.c Wed Jul 25 17:10:19 2001 +++ linux/arch/s390x/kernel/ptrace.c Tue Sep 18 16:56:19 2001 @@ -216,6 +216,17 @@ return(0); } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the single step bit is not set. */ + clear_single_step(child); +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -341,21 +352,9 @@ break; case PTRACE_DETACH: /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - /* make sure the single step bit is not set. */ - clear_single_step(child); - wake_up_process(child); - ret = 0; + ret = ptrace_detach(child, data); break; + case PTRACE_PEEKUSR_AREA: case PTRACE_POKEUSR_AREA: if((ret=copy_from_user(&parea,(void *)addr,sizeof(parea)))==0) 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 -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/sh/kernel/io_7751se.c linux/arch/sh/kernel/io_7751se.c --- v2.4.9/linux/arch/sh/kernel/io_7751se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/io_7751se.c Sat Sep 8 12:29:09 2001 @@ -0,0 +1,304 @@ +/* + * linux/arch/sh/kernel/io_7751se.c + * + * Copyright (C) 2001 Ian da Silva, Jeremy Siegel + * Based largely on io_se.c. + * + * I/O routine for Hitachi 7751 SolutionEngine. + * + * Initial version only to support LAN access; some + * placeholder code from io_se.c left in with the + * expectation of later SuperIO and PCMCIA access. + */ + +#include +#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 Tue Sep 18 16:56:19 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,39 @@ { 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); + 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); + } } - ctrl_outw(BRCR_PCBA | BRCR_PCBB, UBC_BRCR); + if(UBC_TYPE_SH7729) + ctrl_outl(BRCR_PCBA | BRCR_PCBB | BRCR_PCTE, UBC_BRCR); + else + ctrl_outw(BRCR_PCBA | BRCR_PCBB, UBC_BRCR); +} + +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* nothing to do.. */ } asmlinkage int sys_ptrace(long request, long pid, long addr, long data) @@ -337,21 +352,9 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace = 0; - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); break; - } case PTRACE_SETOPTIONS: { if (data & PTRACE_O_TRACESYSGOOD) 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/sparc/kernel/init_task.c linux/arch/sparc/kernel/init_task.c --- v2.4.9/linux/arch/sparc/kernel/init_task.c Mon Jul 26 22:41:09 1999 +++ linux/arch/sparc/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -4,7 +4,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; diff -u --recursive --new-file v2.4.9/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c --- v2.4.9/linux/arch/sparc/kernel/ptrace.c Sun Aug 12 13:27:59 2001 +++ linux/arch/sparc/kernel/ptrace.c Tue Sep 18 17:03:51 2001 @@ -260,6 +260,16 @@ }; #endif +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* nothing to do */ +} + asmlinkage void do_ptrace(struct pt_regs *regs) { unsigned long request = regs->u_regs[UREG_I0]; @@ -576,19 +586,11 @@ } case PTRACE_SUNDETACH: { /* detach a process that was attached. */ - unsigned long flags; - if ((unsigned long) data > _NSIG) { + int err = ptrace_detach(child, data); + if (err) { pt_error_return(regs, EIO); goto out_tsk; } - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - wake_up_process(child); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); pt_succ_return(regs, 0); goto out_tsk; } diff -u --recursive --new-file v2.4.9/linux/arch/sparc/lib/debuglocks.c linux/arch/sparc/lib/debuglocks.c --- v2.4.9/linux/arch/sparc/lib/debuglocks.c Fri Sep 10 11:06:19 1999 +++ linux/arch/sparc/lib/debuglocks.c Sun Sep 16 21:22:50 2001 @@ -29,11 +29,9 @@ static inline void show(char *str, spinlock_t *lock, unsigned long caller) { int cpu = smp_processor_id(); - extern spinlock_t console_lock; - if (lock != &console_lock) - printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str, - lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str, + lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); } static inline void show_read(char *str, rwlock_t *lock, unsigned long caller) 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/init_task.c linux/arch/sparc64/kernel/init_task.c --- v2.4.9/linux/arch/sparc64/kernel/init_task.c Thu Apr 19 08:38:48 2001 +++ linux/arch/sparc64/kernel/init_task.c Mon Sep 17 15:29:09 2001 @@ -4,7 +4,6 @@ #include #include -static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; 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/ptrace.c linux/arch/sparc64/kernel/ptrace.c --- v2.4.9/linux/arch/sparc64/kernel/ptrace.c Sun Aug 12 13:27:59 2001 +++ linux/arch/sparc64/kernel/ptrace.c Tue Sep 18 16:58:03 2001 @@ -105,6 +105,16 @@ }; #endif +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* nothing to do */ +} + asmlinkage void do_ptrace(struct pt_regs *regs) { int request = regs->u_regs[UREG_I0]; @@ -562,22 +572,11 @@ } case PTRACE_SUNDETACH: { /* detach a process that was attached. */ - unsigned long flags; - - if ((unsigned long) data > _NSIG) { + int error = ptrace_detach(child, data); + if (error) { pt_error_return(regs, EIO); goto out_tsk; } - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - - wake_up_process(child); pt_succ_return(regs, 0); goto out_tsk; } 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/solaris/fs.c linux/arch/sparc64/solaris/fs.c --- v2.4.9/linux/arch/sparc64/solaris/fs.c Sun Feb 18 19:49:54 2001 +++ linux/arch/sparc64/solaris/fs.c Wed Sep 12 15:34:06 2001 @@ -406,21 +406,21 @@ u32 f_filler[16]; }; -static int report_statvfs(struct inode *inode, u32 buf) +static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf) { struct statfs s; int error; struct sol_statvfs *ss = (struct sol_statvfs *)A(buf); - error = vfs_statfs(inode->i_sb, &s); + error = vfs_statfs(mnt->mnt_sb, &s); if (!error) { - const char *p = inode->i_sb->s_type->name; + const char *p = mnt->mnt_sb->s_type->name; int i = 0; int j = strlen (p); if (j > 15) j = 15; if (IS_RDONLY(inode)) i = 1; - if (IS_NOSUID(inode)) i |= 2; + if (mnt->mnt_flags & MNT_NOSUID) i |= 2; if (put_user (s.f_bsize, &ss->f_bsize) || __put_user (0, &ss->f_frsize) || __put_user (s.f_blocks, &ss->f_blocks) || @@ -440,21 +440,21 @@ return error; } -static int report_statvfs64(struct inode *inode, u32 buf) +static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf) { struct statfs s; int error; struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf); - error = vfs_statfs(inode->i_sb, &s); + error = vfs_statfs(mnt->mnt_sb, &s); if (!error) { - const char *p = inode->i_sb->s_type->name; + const char *p = mnt->mnt_sb->s_type->name; int i = 0; int j = strlen (p); if (j > 15) j = 15; if (IS_RDONLY(inode)) i = 1; - if (IS_NOSUID(inode)) i |= 2; + if (mnt->mnt_flags & MNT_NOSUID) i |= 2; if (put_user (s.f_bsize, &ss->f_bsize) || __put_user (0, &ss->f_frsize) || __put_user (s.f_blocks, &ss->f_blocks) || @@ -482,7 +482,7 @@ error = user_path_walk((const char *)A(path),&nd); if (!error) { struct inode * inode = nd.dentry->d_inode; - error = report_statvfs(inode, buf); + error = report_statvfs(nd.mnt, inode, buf); path_release(&nd); } return error; @@ -496,7 +496,7 @@ error = -EBADF; file = fget(fd); if (file) { - error = report_statvfs(file->f_dentry->d_inode, buf); + error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf); fput(file); } @@ -512,7 +512,7 @@ error = user_path_walk((const char *)A(path), &nd); if (!error) { struct inode * inode = nd.dentry->d_inode; - error = report_statvfs64(inode, buf); + error = report_statvfs64(nd.mnt, inode, buf); path_release(&nd); } unlock_kernel(); @@ -528,7 +528,7 @@ file = fget(fd); if (file) { lock_kernel(); - error = report_statvfs64(file->f_dentry->d_inode, buf); + error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf); unlock_kernel(); fput(file); } diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c --- v2.4.9/linux/arch/sparc64/solaris/misc.c Sun Mar 25 18:14:21 2001 +++ linux/arch/sparc64/solaris/misc.c Mon Sep 10 13:04:33 2001 @@ -709,7 +709,7 @@ struct exec_domain solaris_exec_domain = { "Solaris", - (lcall7_func)NULL, + NULL, 1, 1, /* PER_SVR4 personality */ solaris_to_linux_signals, linux_to_solaris_signals, diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c --- v2.4.9/linux/arch/sparc64/solaris/timod.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/solaris/timod.c Mon Sep 10 09:04:53 2001 @@ -699,7 +699,7 @@ } if (ctl_maxlen >= 0 && sock->pfirst) { struct T_primsg *it = sock->pfirst; - int l = min(int, ctl_maxlen, it->length); + int l = min_t(int, ctl_maxlen, it->length); SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC); SOLD("purting ctl data"); if(copy_to_user(ctl_buf, 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 Thu Sep 13 15:21:32 2001 @@ -1210,6 +1210,8 @@ case BLKGETSIZE: return put_user (mfm[minor].nr_sects, (long *)arg); + case BLKGETSIZE64: + return put_user ((u64)mfm[minor].nr_sects << 9, (u64 *)arg); case BLKFRASET: if (!capable(CAP_SYS_ADMIN)) @@ -1311,15 +1313,13 @@ } static struct gendisk mfm_gendisk = { - MAJOR_NR, /* Major number */ - "mfm", /* Major name */ - 6, /* Bits to shift to get real from partition */ - 1 << 6, /* Number of partitions per real */ - mfm, /* hd struct */ - mfm_sizes, /* block sizes */ - 0, /* number */ - (void *) mfm_info, /* internal */ - NULL /* next */ + major: MAJOR_NR, + major_name: "mfm", + minor_shift: 6, + max_p: 1 << 6, + part: mfm, + sizes: mfm_sizes, + real_devices: (void *)mfm_info, }; static struct block_device_operations mfm_fops = @@ -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; @@ -1501,6 +1498,10 @@ } #ifdef MODULE + +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); + int init_module(void) { return mfm_init(); @@ -1512,6 +1513,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/acorn/char/serial-card.c linux/drivers/acorn/char/serial-card.c --- v2.4.9/linux/drivers/acorn/char/serial-card.c Mon Sep 18 15:15:22 2000 +++ linux/drivers/acorn/char/serial-card.c Thu Sep 13 15:21:32 2001 @@ -126,5 +126,7 @@ EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); + module_init(INIT); module_exit(EXIT); diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c --- v2.4.9/linux/drivers/acorn/net/ether1.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acorn/net/ether1.c Thu Sep 13 15:21:32 2001 @@ -1102,3 +1102,5 @@ module_init(ether1_init); module_exit(ether1_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c --- v2.4.9/linux/drivers/acorn/net/ether3.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acorn/net/ether3.c Thu Sep 13 15:21:32 2001 @@ -938,3 +938,5 @@ module_init(ether3_init); module_exit(ether3_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c --- v2.4.9/linux/drivers/acorn/net/etherh.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/acorn/net/etherh.c Thu Sep 13 15:21:32 2001 @@ -67,6 +67,7 @@ MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("EtherH/EtherM driver"); +MODULE_LICENSE("GPL"); static char version[] __initdata = "EtherH/EtherM Driver (c) 2000 Russell King v1.08\n"; diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c --- v2.4.9/linux/drivers/acorn/scsi/acornscsi.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/acorn/scsi/acornscsi.c Thu Sep 13 15:21:32 2001 @@ -1059,7 +1059,7 @@ /* * Allocate some buffer space, limited to half the buffer size */ - length = min(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); + length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); if (length) { host->dma.start_addr = address = host->dma.free_addr; host->dma.free_addr = (host->dma.free_addr + length) & @@ -1187,7 +1187,7 @@ /* * Allocate some buffer space, limited to half the on-board RAM size */ - length = min(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); + length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); if (length) { host->dma.start_addr = address = host->dma.free_addr; host->dma.free_addr = (host->dma.free_addr + length) & @@ -1656,8 +1656,8 @@ * to be in operation AFTER the target leaves message out phase. */ acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); - period = max(unsigned int, message[3], sdtr_period / 4); - length = min(unsigned int, message[4], sdtr_size); + period = max_t(unsigned int, message[3], sdtr_period / 4); + length = min_t(unsigned int, message[4], sdtr_size); msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, EXTENDED_SDTR, period, length); host->device[host->SCpnt->target].sync_xfer = @@ -3158,3 +3158,6 @@ module_init(acornscsi_init); module_exit(acornscsi_exit); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/arxescsi.c linux/drivers/acorn/scsi/arxescsi.c --- v2.4.9/linux/drivers/acorn/scsi/arxescsi.c Thu Feb 8 16:32:44 2001 +++ linux/drivers/acorn/scsi/arxescsi.c Thu Sep 13 15:21:32 2001 @@ -439,3 +439,4 @@ module_init(init_arxe_scsi_driver); module_exit(exit_arxe_scsi_driver); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/cumana_1.c linux/drivers/acorn/scsi/cumana_1.c --- v2.4.9/linux/drivers/acorn/scsi/cumana_1.c Thu Feb 8 16:32:44 2001 +++ linux/drivers/acorn/scsi/cumana_1.c Thu Sep 13 15:21:32 2001 @@ -424,3 +424,6 @@ module_init(cumanascsi_init); module_exit(cumanascsi_exit); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c --- v2.4.9/linux/drivers/acorn/scsi/cumana_2.c Fri Mar 2 18:38:37 2001 +++ linux/drivers/acorn/scsi/cumana_2.c Thu Sep 13 15:21:32 2001 @@ -86,6 +86,7 @@ MODULE_DESCRIPTION("Cumana SCSI II driver"); MODULE_PARM(term, "1-8i"); MODULE_PARM_DESC(term, "SCSI bus termination"); +MODULE_LICENSE("GPL"); /* * Use term=0,1,0,0,0 to turn terminators on/off diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/ecoscsi.c linux/drivers/acorn/scsi/ecoscsi.c --- v2.4.9/linux/drivers/acorn/scsi/ecoscsi.c Thu Feb 8 16:32:44 2001 +++ linux/drivers/acorn/scsi/ecoscsi.c Thu Sep 13 15:21:32 2001 @@ -292,3 +292,6 @@ module_init(ecoscsi_init); module_exit(ecoscsi_exit); + +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c --- v2.4.9/linux/drivers/acorn/scsi/eesox.c Fri Mar 2 18:38:37 2001 +++ linux/drivers/acorn/scsi/eesox.c Thu Sep 13 15:21:32 2001 @@ -602,3 +602,5 @@ module_init(eesox_init); module_exit(eesox_exit); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c --- v2.4.9/linux/drivers/acorn/scsi/fas216.c Thu Feb 8 16:32:44 2001 +++ linux/drivers/acorn/scsi/fas216.c Thu Sep 13 15:21:32 2001 @@ -2777,3 +2777,5 @@ { } #endif + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/msgqueue.c linux/drivers/acorn/scsi/msgqueue.c --- v2.4.9/linux/drivers/acorn/scsi/msgqueue.c Thu Feb 8 16:32:44 2001 +++ linux/drivers/acorn/scsi/msgqueue.c Thu Sep 13 15:21:32 2001 @@ -18,6 +18,7 @@ MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("SCSI message queue handling"); +MODULE_LICENSE("GPL"); /* * Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq) diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/oak.c linux/drivers/acorn/scsi/oak.c --- v2.4.9/linux/drivers/acorn/scsi/oak.c Thu Feb 8 16:32:44 2001 +++ linux/drivers/acorn/scsi/oak.c Thu Sep 13 15:21:32 2001 @@ -285,3 +285,6 @@ module_init(oakscsi_init); module_exit(oakscsi_exit); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c --- v2.4.9/linux/drivers/acorn/scsi/powertec.c Fri Mar 2 18:38:37 2001 +++ linux/drivers/acorn/scsi/powertec.c Thu Sep 13 15:21:32 2001 @@ -81,6 +81,7 @@ MODULE_DESCRIPTION("Powertec SCSI driver"); MODULE_PARM(term, "1-8i"); MODULE_PARM_DESC(term, "SCSI bus termination"); +MODULE_LICENSE("GPL"); static struct expansion_card *ecs[MAX_ECARDS]; diff -u --recursive --new-file v2.4.9/linux/drivers/acorn/scsi/queue.c linux/drivers/acorn/scsi/queue.c --- v2.4.9/linux/drivers/acorn/scsi/queue.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/acorn/scsi/queue.c Thu Sep 13 15:21:32 2001 @@ -27,6 +27,7 @@ MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("SCSI command queueing"); +MODULE_LICENSE("GPL"); #define DEBUG 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/os.c linux/drivers/acpi/os.c --- v2.4.9/linux/drivers/acpi/os.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/os.c Thu Sep 13 16:04:43 2001 @@ -156,7 +156,14 @@ } if ((unsigned long) phys < virt_to_phys(high_memory)) { + struct page *page; *virt = phys_to_virt((unsigned long) phys); + + /* Check for stamping */ + page = virt_to_page(*virt); + if(page && !test_bit(PG_reserved, &page->flags)) + printk(KERN_WARNING "ACPI attempting to access kernel owned memory at %08lX.\n", (unsigned long)phys); + return AE_OK; } diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/ospm/ac_adapter/ac_osl.c linux/drivers/acpi/ospm/ac_adapter/ac_osl.c --- v2.4.9/linux/drivers/acpi/ospm/ac_adapter/ac_osl.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/ac_adapter/ac_osl.c Thu Sep 13 16:04:43 2001 @@ -35,6 +35,7 @@ MODULE_AUTHOR("Andrew Grover"); MODULE_DESCRIPTION("ACPI Component Architecture (CA) - AC Adapter Driver"); +MODULE_LICENSE("GPL"); #define AC_PROC_ROOT "ac_adapter" diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/ospm/battery/bt_osl.c linux/drivers/acpi/ospm/battery/bt_osl.c --- v2.4.9/linux/drivers/acpi/ospm/battery/bt_osl.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/battery/bt_osl.c Thu Sep 13 16:04:43 2001 @@ -44,6 +44,7 @@ MODULE_AUTHOR("Andrew Grover"); MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Control Method Battery Driver"); +MODULE_LICENSE("GPL"); #define BT_PROC_ROOT "battery" 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/acpi/ospm/busmgr/bm_osl.c linux/drivers/acpi/ospm/busmgr/bm_osl.c --- v2.4.9/linux/drivers/acpi/ospm/busmgr/bm_osl.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/busmgr/bm_osl.c Thu Sep 13 16:04:43 2001 @@ -37,6 +37,7 @@ MODULE_AUTHOR("Andrew Grover"); MODULE_DESCRIPTION("ACPI Component Architecture (CA) - ACPI Bus Manager"); +MODULE_LICENSE("GPL"); #ifdef ACPI_DEBUG diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/ospm/button/bn_osl.c linux/drivers/acpi/ospm/button/bn_osl.c --- v2.4.9/linux/drivers/acpi/ospm/button/bn_osl.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/button/bn_osl.c Thu Sep 13 16:04:43 2001 @@ -35,6 +35,7 @@ MODULE_AUTHOR("Andrew Grover"); MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Button Driver"); +MODULE_LICENSE("GPL"); #define BN_PROC_ROOT "button" diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/ospm/ec/ec_osl.c linux/drivers/acpi/ospm/ec/ec_osl.c --- v2.4.9/linux/drivers/acpi/ospm/ec/ec_osl.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/ec/ec_osl.c Thu Sep 13 16:04:43 2001 @@ -36,6 +36,7 @@ MODULE_AUTHOR("Andrew Grover"); MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Embedded Controller Driver"); +MODULE_LICENSE("GPL"); #ifdef ACPI_DEBUG diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/ospm/processor/pr_osl.c linux/drivers/acpi/ospm/processor/pr_osl.c --- v2.4.9/linux/drivers/acpi/ospm/processor/pr_osl.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/processor/pr_osl.c Thu Sep 13 16:04:43 2001 @@ -36,6 +36,7 @@ MODULE_AUTHOR("Andrew Grover"); MODULE_DESCRIPTION("ACPI Component Architecture (CA) - IA32 Processor Driver"); +MODULE_LICENSE("GPL"); #define PR_PROC_ROOT "processor" diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/ospm/system/sm_osl.c linux/drivers/acpi/ospm/system/sm_osl.c --- v2.4.9/linux/drivers/acpi/ospm/system/sm_osl.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/system/sm_osl.c Thu Sep 13 16:04:43 2001 @@ -38,6 +38,7 @@ MODULE_AUTHOR("Andrew Grover"); MODULE_DESCRIPTION("ACPI Component Architecture (CA) - ACPI System Driver"); +MODULE_LICENSE("GPL"); #define SM_PROC_INFO "info" diff -u --recursive --new-file v2.4.9/linux/drivers/acpi/ospm/thermal/tz_osl.c linux/drivers/acpi/ospm/thermal/tz_osl.c --- v2.4.9/linux/drivers/acpi/ospm/thermal/tz_osl.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/acpi/ospm/thermal/tz_osl.c Thu Sep 13 16:04:43 2001 @@ -35,6 +35,7 @@ MODULE_AUTHOR("Andrew Grover"); MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Thermal Zone Driver"); +MODULE_LICENSE("GPL"); int TZP = 0; MODULE_PARM(TZP, "i"); 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/ambassador.c linux/drivers/atm/ambassador.c --- v2.4.9/linux/drivers/atm/ambassador.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/atm/ambassador.c Thu Sep 13 15:21:32 2001 @@ -297,16 +297,16 @@ #define UCODE2(x) #x #define UCODE1(x,y) UCODE2(x ## y) -static const u32 __initdata ucode_start = +static u32 __initdata ucode_start = #include UCODE(start) ; -static const region __initdata ucode_regions[] = { +static region __initdata ucode_regions[] = { #include UCODE(regions) { 0, 0 } }; -static const u32 __initdata ucode_data[] = { +static u32 __initdata ucode_data[] = { #include UCODE(data) 0xdeadbeef }; @@ -2585,6 +2585,7 @@ MODULE_AUTHOR(maintainer_string); MODULE_DESCRIPTION(description_string); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "h"); MODULE_PARM(cmds, "i"); MODULE_PARM(txs, "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/atm/ambassador.h linux/drivers/atm/ambassador.h --- v2.4.9/linux/drivers/atm/ambassador.h Mon Dec 11 13:22:06 2000 +++ linux/drivers/atm/ambassador.h Thu Sep 13 15:21:32 2001 @@ -664,9 +664,9 @@ unsigned int count; } region; -extern const region ucode_regions[]; -extern const u32 ucode_data[]; -extern const u32 ucode_start; +static region ucode_regions[]; +static u32 ucode_data[]; +static u32 ucode_start; /* rate rounding */ diff -u --recursive --new-file v2.4.9/linux/drivers/atm/atmtcp.c linux/drivers/atm/atmtcp.c --- v2.4.9/linux/drivers/atm/atmtcp.c Fri Dec 29 14:35:47 2000 +++ linux/drivers/atm/atmtcp.c Thu Sep 13 15:21:32 2001 @@ -420,6 +420,7 @@ atm_tcp_ops.remove_persistent = NULL; } +MODULE_LICENSE("GPL"); #else struct atm_tcp_ops atm_tcp_ops = { diff -u --recursive --new-file v2.4.9/linux/drivers/atm/eni.c linux/drivers/atm/eni.c --- v2.4.9/linux/drivers/atm/eni.c Wed May 16 10:22:50 2001 +++ linux/drivers/atm/eni.c Fri Sep 14 14:40:00 2001 @@ -32,7 +32,7 @@ #include "suni.h" #include "eni.h" -#ifndef __i386__ +#if !defined(__i386__) && !defined(__x86_64__) #ifndef ioremap_nocache #define ioremap_nocache(X,Y) ioremap(X,Y) #endif @@ -2340,3 +2340,6 @@ module_init(eni_init); module_exit(eni_cleanup); + +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/atm/firestream.c linux/drivers/atm/firestream.c --- v2.4.9/linux/drivers/atm/firestream.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/atm/firestream.c Thu Sep 13 15:21:32 2001 @@ -271,11 +271,11 @@ 150000 packets per second is close to the limit a PC is going to have anyway. We therefore have to disable this for production. -- REW */ -#undef IRQ_RATE_LIMIT 100 +#undef IRQ_RATE_LIMIT // 100 /* Interrupts work now. Unlike serial cards, ATM cards don't work all that great without interrupts. -- REW */ -#undef FS_POLL_FREQ 100 +#undef FS_POLL_FREQ // 100 /* This driver can spew a whole lot of debugging output at you. If you @@ -1928,8 +1928,6 @@ err_out_free_atm_dev: atm_dev_deregister(atm_dev); - err_out_free_fs_dev: - kfree(fs_dev); err_out: return -ENODEV; } @@ -2120,3 +2118,5 @@ module_init(firestream_init_module); module_exit(firestream_cleanup_module); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; 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/atm/fore200e.c linux/drivers/atm/fore200e.c --- v2.4.9/linux/drivers/atm/fore200e.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/atm/fore200e.c Thu Sep 13 15:21:32 2001 @@ -3000,3 +3000,5 @@ #endif {} }; + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/atm/horizon.c linux/drivers/atm/horizon.c --- v2.4.9/linux/drivers/atm/horizon.c Fri Dec 29 14:35:47 2000 +++ linux/drivers/atm/horizon.c Thu Sep 13 15:21:32 2001 @@ -2935,6 +2935,7 @@ MODULE_AUTHOR(maintainer_string); MODULE_DESCRIPTION(description_string); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "h"); MODULE_PARM(vpi_bits, "h"); MODULE_PARM(max_tx_size, "h"); diff -u --recursive --new-file v2.4.9/linux/drivers/atm/idt77105.c linux/drivers/atm/idt77105.c --- v2.4.9/linux/drivers/atm/idt77105.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/atm/idt77105.c Thu Sep 13 15:21:32 2001 @@ -374,9 +374,7 @@ } } -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif /* MODULE */ return 0; } @@ -384,6 +382,8 @@ EXPORT_SYMBOL(idt77105_init); EXPORT_SYMBOL(idt77105_stop); + +MODULE_LICENSE("GPL"); #ifdef MODULE diff -u --recursive --new-file v2.4.9/linux/drivers/atm/iphase.c linux/drivers/atm/iphase.c --- v2.4.9/linux/drivers/atm/iphase.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/atm/iphase.c Mon Sep 17 22:52:34 2001 @@ -1,6 +1,7 @@ /****************************************************************************** iphase.c: Device driver for Interphase ATM PCI adapter cards Author: Peter Wang + Some fixes: Arnaldo Carvalho de Melo Interphase Corporation Version: 1.0 ******************************************************************************* @@ -79,7 +80,7 @@ static IADEV *ia_dev[8]; static struct atm_dev *_ia_dev[8]; -static int iadev_count = 0; +static int iadev_count; static void ia_led_timer(unsigned long arg); static struct timer_list ia_timer = { function: ia_led_timer }; struct atm_vcc *vcc_close_que[100]; @@ -96,6 +97,8 @@ MODULE_PARM(IADebugFlag, "i"); #endif +MODULE_LICENSE("GPL"); + #if BITS_PER_LONG != 32 # error FIXME: this driver only works on 32-bit platforms #endif @@ -121,8 +124,7 @@ } static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) { - IARTN_Q *entry; - entry = (IARTN_Q *)kmalloc(sizeof(IARTN_Q), GFP_KERNEL); + IARTN_Q *entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return -1; entry->data = data; entry->next = NULL; @@ -429,7 +431,7 @@ if (srv_p->rdf > MAX_RDF) return INVALID_RDF; #endif - memset ((caddr_t)f_abr_vc, 0, sizeof(f_vc_abr_entry)); + memset ((caddr_t)f_abr_vc, 0, sizeof(*f_abr_vc)); f_abr_vc->f_vc_type = ABR; nrm = 2 << srv_p->nrm; /* (2 ** (srv_p->nrm +1)) */ /* i.e 2**n = 2 << (n-1) */ @@ -544,7 +546,7 @@ TstSchedTbl = (u16*)(SchedTbl+testSlot); //set index and read in value IF_CBR(printk("CBR Testslot 0x%x AT Location 0x%x, NumToAssign=%d\n", testSlot, (u32)TstSchedTbl,toBeAssigned);) - memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(u16)); + memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC)); while (cbrVC) // If another VC at this location, we have to keep looking { inc++; @@ -555,7 +557,7 @@ (u32)SchedTbl,testSlot);) } TstSchedTbl = (u16 *)(SchedTbl + testSlot); // set table index - memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(u16)); + memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC)); if (!cbrVC) break; testSlot = idealSlot + inc; @@ -569,10 +571,10 @@ TstSchedTbl = (u16*)(SchedTbl + testSlot); IF_CBR(printk("Reading CBR Tbl from 0x%x, CbrVal=0x%x Iteration %d\n", (u32)TstSchedTbl,cbrVC,inc);) - memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(u16)); + memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC)); } /* while */ // Move this VCI number into this location of the CBR Sched table. - memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex,sizeof(u16)); + memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex,sizeof(TstSchedTbl)); dev->CbrRemEntries--; toBeAssigned--; } /* while */ @@ -658,20 +660,20 @@ skb = rtne->data.txskb; if (!skb) { printk("ia_tx_poll: skb is null\n"); - return; + goto out; } vcc = ATM_SKB(skb)->vcc; if (!vcc) { printk("ia_tx_poll: vcc is null\n"); dev_kfree_skb_any(skb); - return; + goto out; } iavcc = INPH_IA_VCC(vcc); if (!iavcc) { printk("ia_tx_poll: iavcc is null\n"); dev_kfree_skb_any(skb); - return; + goto out; } skb1 = skb_dequeue(&iavcc->txing_skb); @@ -680,7 +682,7 @@ printk("IA_tx_intr: Vci %d lost pkt!!!\n", vcc->vci); } IF_ERR(printk("Release the SKB not match\n");) - if (vcc && (vcc->pop) && (skb1->len != 0)) + if ((vcc->pop) && (skb1->len != 0)) { vcc->pop(vcc, skb1); IF_EVENT(printk("Tansmit Done - skb 0x%lx return\n", @@ -695,7 +697,7 @@ ia_enque_head_rtn_q (&iadev->tx_return_q, rtne); break; } - if (vcc && (vcc->pop) && (skb->len != 0)) + if ((vcc->pop) && (skb->len != 0)) { vcc->pop(vcc, skb); IF_EVENT(printk("Tx Done - skb 0x%lx return\n",(long)skb);) @@ -705,6 +707,7 @@ kfree(rtne); } ia_que_tx(iadev); +out: return; } #if 0 @@ -924,9 +927,9 @@ suni_pm7345->suni_rxcp_ctrl = 0x2c; suni_pm7345->suni_rxcp_fctrl = 0x81; - suni_pm7345->suni_rxcp_idle_pat_h1 = 0; - suni_pm7345->suni_rxcp_idle_pat_h2 = 0; - suni_pm7345->suni_rxcp_idle_pat_h3 = 0; + suni_pm7345->suni_rxcp_idle_pat_h1 = + suni_pm7345->suni_rxcp_idle_pat_h2 = + suni_pm7345->suni_rxcp_idle_pat_h3 = 0; suni_pm7345->suni_rxcp_idle_pat_h4 = 1; suni_pm7345->suni_rxcp_idle_mask_h1 = 0xff; @@ -934,15 +937,15 @@ suni_pm7345->suni_rxcp_idle_mask_h3 = 0xff; suni_pm7345->suni_rxcp_idle_mask_h4 = 0xfe; - suni_pm7345->suni_rxcp_cell_pat_h1 = 0; - suni_pm7345->suni_rxcp_cell_pat_h2 = 0; - suni_pm7345->suni_rxcp_cell_pat_h3 = 0; + suni_pm7345->suni_rxcp_cell_pat_h1 = + suni_pm7345->suni_rxcp_cell_pat_h2 = + suni_pm7345->suni_rxcp_cell_pat_h3 = 0; suni_pm7345->suni_rxcp_cell_pat_h4 = 1; - suni_pm7345->suni_rxcp_cell_mask_h1 = 0xff; - suni_pm7345->suni_rxcp_cell_mask_h2 = 0xff; - suni_pm7345->suni_rxcp_cell_mask_h3 = 0xff; - suni_pm7345->suni_rxcp_cell_mask_h4 = 0xff; + suni_pm7345->suni_rxcp_cell_mask_h1 = + suni_pm7345->suni_rxcp_cell_mask_h2 = + suni_pm7345->suni_rxcp_cell_mask_h3 = + suni_pm7345->suni_rxcp_cell_mask_h4 = 0xff; suni_pm7345->suni_txcp_ctrl = 0xa4; suni_pm7345->suni_txcp_intr_en_sts = 0x10; @@ -1144,8 +1147,7 @@ else { IF_ERR(printk(" cause: buffer over flow\n");) } - free_desc(dev, desc); - return 0; + goto out_free_desc; } /* @@ -1158,8 +1160,7 @@ if (len > iadev->rx_buf_sz) { printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz); atomic_inc(&vcc->stats->rx_err); - free_desc(dev, desc); - return 0; + goto out_free_desc; } #if LINUX_VERSION_CODE >= 0x20312 @@ -1173,8 +1174,7 @@ IF_ERR(printk("can't allocate memory for recv, drop pkt!\n");) atomic_inc(&vcc->stats->rx_drop); atm_return(vcc, atm_pdu2truesize(len)); - free_desc(dev, desc); - return 0; + goto out_free_desc; } } else { @@ -1182,8 +1182,7 @@ #endif if (vcc->vci < 32) printk("Drop control packets\n"); - free_desc(dev, desc); - return 0; + goto out_free_desc; } skb_put(skb,len); // pwang_test @@ -1206,7 +1205,10 @@ udelay(1); /* Increment transaction counter */ writel(1, iadev->dma+IPHASE5575_RX_COUNTER); - return 0; +out: return 0; +out_free_desc: + free_desc(dev, desc); + goto out; } static void rx_intr(struct atm_dev *dev) @@ -1280,6 +1282,7 @@ u_short state; struct dle *dle, *cur_dle; u_int dle_lp; + int len; iadev = INPH_IA_DEV(dev); /* free all the dles done, that is just update our own dle read pointer @@ -1299,7 +1302,7 @@ desc = ATM_DESC(skb); free_desc(dev, desc); - if (!skb->len) + if (!(len = skb->len)) { printk("rx_dle_intr: skb len 0\n"); dev_kfree_skb_any(skb); @@ -1313,7 +1316,6 @@ vcc = ATM_SKB(skb)->vcc; if (!vcc) { printk("IA: null vcc\n"); - atomic_inc(&vcc->stats->rx_err); dev_kfree_skb_any(skb); goto INCR_DLE; } @@ -1323,27 +1325,27 @@ atomic_inc(&vcc->stats->rx_err); dev_kfree_skb_any(skb); #if LINUX_VERSION_CODE >= 0x20312 - atm_return(vcc, atm_guess_pdu2truesize(skb->len)); + atm_return(vcc, atm_guess_pdu2truesize(len)); #else - atm_return(vcc, atm_pdu2truesize(skb->len)); + atm_return(vcc, atm_pdu2truesize(len)); #endif goto INCR_DLE; } // get real pkt length pwang_test trailer = (struct cpcs_trailer*)((u_char *)skb->data + - skb->len - sizeof(struct cpcs_trailer)); + skb->len - sizeof(*trailer)); length = swap(trailer->length); if ((length > iadev->rx_buf_sz) || (length > (skb->len - sizeof(struct cpcs_trailer)))) { atomic_inc(&vcc->stats->rx_err); - dev_kfree_skb_any(skb); IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)", length, skb->len);) + dev_kfree_skb_any(skb); #if LINUX_VERSION_CODE >= 0x20312 - atm_return(vcc, atm_guess_pdu2truesize(skb->len)); + atm_return(vcc, atm_guess_pdu2truesize(len)); #else - atm_return(vcc, atm_pdu2truesize(skb->len)); + atm_return(vcc, atm_pdu2truesize(len)); #endif goto INCR_DLE; } @@ -1429,7 +1431,7 @@ IADEV *iadev; struct rx_buf_desc *buf_desc_ptr; unsigned long rx_pkt_start = 0; - u32 *dle_addr; + u32 *odle_addr, *dle_addr; struct abr_vc_table *abr_vc_table; u16 *vc_table; u16 *reass_table; @@ -1451,13 +1453,14 @@ */ /* allocate 8k bytes */ - dle_addr = (u32*)kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL); - if (!dle_addr) + odle_addr = kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL); + if (!odle_addr) { printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n"); + return -ENOMEM; } /* find 4k byte boundary within the 8k allocated */ - dle_addr = (u32*)( ((u32)dle_addr+(4096-1)) & ~(4096-1) ); + dle_addr = (u32*)( ((u32)odle_addr+(4096-1)) & ~(4096-1) ); iadev->rx_dle_q.start = (struct dle*)dle_addr; iadev->rx_dle_q.read = iadev->rx_dle_q.start; iadev->rx_dle_q.write = iadev->rx_dle_q.start; @@ -1499,12 +1502,12 @@ /* Initialize each entry in the Buffer Descriptor Table */ iadev->RX_DESC_BASE_ADDR = iadev->reass_ram+RX_DESC_BASE*iadev->memSize; buf_desc_ptr =(struct rx_buf_desc *)iadev->RX_DESC_BASE_ADDR; - memset((caddr_t)buf_desc_ptr, 0, sizeof(struct rx_buf_desc)); + memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); buf_desc_ptr++; rx_pkt_start = iadev->rx_pkt_ram; for(i=1; i<=iadev->num_rx_desc; i++) { - memset((caddr_t)buf_desc_ptr, 0, sizeof(struct rx_buf_desc)); + memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); buf_desc_ptr->buf_start_hi = rx_pkt_start >> 16; buf_desc_ptr->buf_start_lo = rx_pkt_start & 0x0000ffff; buf_desc_ptr++; @@ -1599,7 +1602,7 @@ i = ABR_VC_TABLE * iadev->memSize; abr_vc_table = (struct abr_vc_table *)(iadev->reass_ram+i); j = REASS_TABLE_SZ * iadev->memSize; - memset ((char*)abr_vc_table, 0, j * sizeof(struct abr_vc_table ) ); + memset ((char*)abr_vc_table, 0, j * sizeof(*abr_vc_table)); for(i = 0; i < j; i++) { abr_vc_table->rdf = 0x0003; abr_vc_table->air = 0x5eb1; @@ -1635,11 +1638,12 @@ skb_queue_head_init(&iadev->rx_dma_q); iadev->rx_free_desc_qhead = NULL; - iadev->rx_open =(struct atm_vcc **)kmalloc(4*iadev->num_vc,GFP_KERNEL); + iadev->rx_open = kmalloc(4*iadev->num_vc,GFP_KERNEL); if (!iadev->rx_open) { printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n", dev->number); + kfree(odle_addr); return -ENOMEM; } memset(iadev->rx_open, 0, 4*iadev->num_vc); @@ -1770,7 +1774,7 @@ } } ia_vcc = INPH_IA_VCC(vcc); - memset((caddr_t)ia_vcc, 0, sizeof(struct ia_vcc)); + memset((caddr_t)ia_vcc, 0, sizeof(*ia_vcc)); if (vcc->qos.txtp.max_sdu > (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){ printk("IA: SDU size over the configured SDU size %d\n", @@ -1815,8 +1819,8 @@ evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR; vc += vcc->vci; evc += vcc->vci; - memset((caddr_t)vc, 0, sizeof(struct main_vc)); - memset((caddr_t)evc, 0, sizeof(struct ext_vc)); + memset((caddr_t)vc, 0, sizeof(*vc)); + memset((caddr_t)evc, 0, sizeof(*evc)); /* store the most significant 4 bits of vci as the last 4 bits of first part of atm header. @@ -1921,10 +1925,11 @@ readw(iadev->seg_reg+SEG_MASK_REG));) /*---------- Initializing Transmit DLEs ----------*/ /* allocating 8k memory for transmit DLEs */ - dle_addr = (u32*)kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL); + dle_addr = kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL); if (!dle_addr) { printk(KERN_ERR DEV_LABEL "can't allocate TX DLEs\n"); + return -ENOMEM; } /* find 4k byte boundary within the 8k allocated */ @@ -1967,20 +1972,19 @@ /* initialize each entry in the buffer descriptor table */ buf_desc_ptr =(struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE); - memset((caddr_t)buf_desc_ptr, 0, sizeof(struct tx_buf_desc)); + memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); buf_desc_ptr++; tx_pkt_start = TX_PACKET_RAM; for(i=1; i<=iadev->num_tx_desc; i++) { - memset((caddr_t)buf_desc_ptr, 0, sizeof(struct tx_buf_desc)); + memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); buf_desc_ptr->desc_mode = AAL5; buf_desc_ptr->buf_start_hi = tx_pkt_start >> 16; buf_desc_ptr->buf_start_lo = tx_pkt_start & 0x0000ffff; buf_desc_ptr++; tx_pkt_start += iadev->tx_buf_sz; } - iadev->tx_buf= (caddr_t*)kmalloc(iadev->num_tx_desc*sizeof(caddr_t), - GFP_KERNEL); + iadev->tx_buf = kmalloc(iadev->num_tx_desc*sizeof(caddr_t), GFP_KERNEL); if (!iadev->tx_buf) { printk(KERN_ERR DEV_LABEL " couldn't get mem\n"); return -EAGAIN; @@ -1988,14 +1992,14 @@ for (i= 0; i< iadev->num_tx_desc; i++) { - iadev->tx_buf[i] =(caddr_t)kmalloc(sizeof(struct cpcs_trailer), + iadev->tx_buf[i] = kmalloc(sizeof(struct cpcs_trailer), GFP_KERNEL|GFP_DMA); if(!iadev->tx_buf[i]) { printk(KERN_ERR DEV_LABEL " couldn't get freepage\n"); return -EAGAIN; } } - iadev->desc_tbl = (struct desc_tbl_t *)kmalloc(iadev->num_tx_desc * + iadev->desc_tbl = kmalloc(iadev->num_tx_desc * sizeof(struct desc_tbl_t), GFP_KERNEL); /* Communication Queues base address */ @@ -2121,18 +2125,17 @@ memset((caddr_t)(iadev->seg_ram+i), 0, iadev->num_vc*4); vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR; evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR; - iadev->testTable = (struct testTable_t **) - kmalloc(sizeof(long)*iadev->num_vc, GFP_KERNEL); + iadev->testTable = kmalloc(sizeof(long)*iadev->num_vc, GFP_KERNEL); if (!iadev->testTable) { printk("Get freepage failed\n"); return -EAGAIN; } for(i=0; inum_vc; i++) { - memset((caddr_t)vc, 0, sizeof(struct main_vc)); - memset((caddr_t)evc, 0, sizeof(struct ext_vc)); - iadev->testTable[i] = (struct testTable_t *) - kmalloc(sizeof(struct testTable_t), GFP_KERNEL); + memset((caddr_t)vc, 0, sizeof(*vc)); + memset((caddr_t)evc, 0, sizeof(*evc)); + iadev->testTable[i] = kmalloc(sizeof(struct testTable_t), + GFP_KERNEL); if (!iadev->testTable[i]) return -ENOMEM; iadev->testTable[i]->lastTime = 0; @@ -2682,7 +2685,7 @@ vcc->dev->number, vcc->vpi, vcc->vci);) /* Device dependent initialization */ - ia_vcc = kmalloc(sizeof(struct ia_vcc), GFP_KERNEL); + ia_vcc = kmalloc(sizeof(*ia_vcc), GFP_KERNEL); if (!ia_vcc) return -ENOMEM; INPH_IA_VCC(vcc) = ia_vcc; @@ -2989,7 +2992,7 @@ /* Build the DLE structure */ wr_ptr = iadev->tx_dle_q.write; - memset((caddr_t)wr_ptr, 0, sizeof(struct dle)); + memset((caddr_t)wr_ptr, 0, sizeof(*wr_ptr)); wr_ptr->sys_pkt_addr = addr; wr_ptr->local_pkt_addr = (buf_desc_ptr->buf_start_hi << 16) | buf_desc_ptr->buf_start_lo; @@ -3175,9 +3178,9 @@ printk(KERN_ERR DEV_LABEL " driver but no PCI BIOS ?\n"); return 0; } - iadev = (IADEV *)kmalloc(sizeof(IADEV), GFP_KERNEL); + iadev = kmalloc(sizeof(*iadev), GFP_KERNEL); if (!iadev) return -ENOMEM; - memset((char*)iadev, 0, sizeof(IADEV)); + memset((char*)iadev, 0, sizeof(*iadev)); prev_dev = NULL; while((iadev->pci = pci_find_device(PCI_VENDOR_ID_IPHASE, PCI_DEVICE_ID_IPHASE_5575, prev_dev))) { @@ -3212,10 +3215,9 @@ prev_dev = iadev->pci; iadev->next_board = ia_boards; ia_boards = dev; - iadev = (IADEV *)kmalloc( - sizeof(IADEV), GFP_KERNEL); + iadev = kmalloc(sizeof(*iadev), GFP_KERNEL); if (!iadev) break; - memset((char*)iadev, 0, sizeof(IADEV)); + memset((char*)iadev, 0, sizeof(*iadev)); index++; dev = NULL; } diff -u --recursive --new-file v2.4.9/linux/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c --- v2.4.9/linux/drivers/atm/nicstar.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/atm/nicstar.c Thu Sep 13 15:21:32 2001 @@ -271,6 +271,7 @@ static struct timer_list ns_timer; static char *mac[NS_MAX_CARDS]; MODULE_PARM(mac, "1-" __MODULE_STRING(NS_MAX_CARDS) "s"); +MODULE_LICENSE("GPL"); /* Functions*******************************************************************/ diff -u --recursive --new-file v2.4.9/linux/drivers/atm/suni.c linux/drivers/atm/suni.c --- v2.4.9/linux/drivers/atm/suni.c Fri May 5 12:37:52 2000 +++ linux/drivers/atm/suni.c Thu Sep 13 15:21:32 2001 @@ -309,6 +309,8 @@ EXPORT_SYMBOL(suni_init); +MODULE_LICENSE("GPL"); + #ifdef MODULE diff -u --recursive --new-file v2.4.9/linux/drivers/atm/uPD98402.c linux/drivers/atm/uPD98402.c --- v2.4.9/linux/drivers/atm/uPD98402.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/atm/uPD98402.c Thu Sep 13 15:21:32 2001 @@ -255,6 +255,7 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); EXPORT_SYMBOL(uPD98402_init); diff -u --recursive --new-file v2.4.9/linux/drivers/atm/zatm.c linux/drivers/atm/zatm.c --- v2.4.9/linux/drivers/atm/zatm.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/atm/zatm.c Fri Sep 14 14:40:00 2001 @@ -52,6 +52,12 @@ #define DPRINTK(format,args...) #endif +#ifndef __i386__ +#ifdef CONFIG_ATM_ZATM_EXACT_TS +#warning Precise timestamping only available on i386 platform +#undef CONFIG_ATM_ZATM_EXACT_TS +#endif +#endif #ifndef CONFIG_ATM_ZATM_DEBUG @@ -1846,6 +1852,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { if (!zatm_detect()) { diff -u --recursive --new-file v2.4.9/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.4.9/linux/drivers/block/Config.in Sat Feb 3 12:13:19 2001 +++ linux/drivers/block/Config.in Fri Sep 14 14:04:06 2001 @@ -42,7 +42,7 @@ tristate 'RAM disk support' CONFIG_BLK_DEV_RAM if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then - int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096 + int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096 fi dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM 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 Mon Sep 10 12:42:31 2001 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1882,7 +1883,6 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) { int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber; - GenericDiskInfo_T *GenericDiskInfo; RequestQueue_T *RequestQueue; int MinorNumber; /* @@ -1937,13 +1937,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 +1973,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); } @@ -5089,26 +5074,19 @@ sizeof(DiskGeometry_T)) ? -EFAULT : 0); case BLKGETSIZE: /* Get Device Size. */ - if ((long *) Argument == NULL) return -EINVAL; return put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)] .nr_sects, (long *) Argument); + case BLKGETSIZE64: + return put_user((u64)Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].nr_sects << 9, + (u64 *) 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/Makefile linux/drivers/block/Makefile --- v2.4.9/linux/drivers/block/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/block/Makefile Sun Sep 9 12:00:55 2001 @@ -10,7 +10,7 @@ O_TARGET := block.o -export-objs := ll_rw_blk.o blkpg.o loop.o DAC960.o +export-objs := ll_rw_blk.o blkpg.o loop.o DAC960.o genhd.o obj-y := ll_rw_blk.o blkpg.o genhd.o elevator.o 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 Thu Sep 13 15:21:32 2001 @@ -1138,6 +1138,10 @@ return put_user(acsi_part[MINOR(inode->i_rdev)].nr_sects, (long *) arg); + case BLKGETSIZE64: /* Return device size */ + return put_user((u64)acsi_part[MINOR(inode->i_rdev)].nr_sects << 9, + (u64 *) arg); + case BLKROSET: case BLKROGET: case BLKFLSBUF: @@ -1386,16 +1390,14 @@ extern struct block_device_operations acsi_fops; static struct gendisk acsi_gendisk = { - MAJOR_NR, /* Major number */ - "ad", /* Major name */ - 4, /* Bits to shift to get real from partition */ - 1 << 4, /* Number of partitions per real */ - acsi_part, /* hd struct */ - acsi_sizes, /* block sizes */ - 0, /* number */ - (void *)acsi_info, /* internal */ - NULL, /* next */ - &acsi_fops, /* file operations */ + major: MAJOR_NR, + major_name: "ad", + minor_shift: 4, + max_p: 1 << 4, + part: acsi_part, + sizes: acsi_sizes, + real_devices: (void *)acsi_info, + fops: &acsi_fops, }; #define MAX_SCSI_DEVICE_CODE 10 @@ -1792,8 +1794,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(); @@ -1805,6 +1806,9 @@ #ifdef MODULE + +MODULE_LICENSE("GPL"); + int init_module(void) { int err; @@ -1817,8 +1821,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 +1828,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/amiflop.c linux/drivers/block/amiflop.c --- v2.4.9/linux/drivers/block/amiflop.c Sat Apr 28 11:27:53 2001 +++ linux/drivers/block/amiflop.c Thu Sep 13 15:21:32 2001 @@ -118,6 +118,7 @@ static long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */ MODULE_PARM(fd_def_df0,"l"); +MODULE_LICENSE("GPL"); /* * Macros @@ -1555,6 +1556,9 @@ break; case BLKGETSIZE: return put_user(unit[drive].blocks,(long *)param); + break; + case BLKGETSIZE64: + return put_user((u64)unit[drive].blocks << 9, (u64 *)param); break; case FDSETPRM: case FDDEFPRM: diff -u --recursive --new-file v2.4.9/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c --- v2.4.9/linux/drivers/block/ataflop.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/block/ataflop.c Thu Sep 13 15:21:32 2001 @@ -2056,6 +2056,9 @@ } #ifdef MODULE + +MODULE_LICENSE("GPL"); + int init_module (void) { if (!MACH_IS_ATARI) 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 Mon Sep 17 15:37:33 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. * @@ -250,6 +239,7 @@ case BLKGETSIZE: /* Today get_gendisk() requires a linear scan; add this when dev has pointer type. */ + /* add BLKGETSIZE64 too */ g = get_gendisk(dev); if (!g) longval = 0; @@ -273,6 +263,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 Tue Sep 18 14:10:43 2001 @@ -50,6 +50,7 @@ /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Charles M. White III - Compaq Computer Corporation"); MODULE_DESCRIPTION("Driver for Compaq Smart Array Controller 5300"); +MODULE_LICENSE("GPL"); #include "cciss_cmd.h" #include "cciss.h" @@ -400,17 +401,23 @@ put_user(hba[ctlr]->hd[MINOR(inode->i_rdev)].start_sect, &geo->start); return 0; case BLKGETSIZE: - if (!arg) return -EINVAL; put_user(hba[ctlr]->hd[MINOR(inode->i_rdev)].nr_sects, (long*)arg); return 0; + case BLKGETSIZE64: + put_user((u64)hba[ctlr]->hd[MINOR(inode->i_rdev)].nr_sects << 9, (u64*)arg); + return 0; case BLKRRPART: return revalidate_logvol(inode->i_rdev, 1); case BLKFLSBUF: + case BLKBSZSET: + case BLKBSZGET: case BLKROSET: case BLKROGET: case BLKRASET: case BLKRAGET: case BLKPG: + case BLKELVGET: + case BLKELVSET: return( blk_ioctl(inode->i_rdev, cmd, arg)); case CCISS_GETPCIINFO: { @@ -1963,8 +1970,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 +2010,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 Tue Sep 18 14:10:43 2001 @@ -48,6 +48,7 @@ /* Original author Chris Frantz - Compaq Computer Corporation */ MODULE_AUTHOR("Compaq Computer Corporation"); MODULE_DESCRIPTION("Driver for Compaq Smart2 Array Controllers"); +MODULE_LICENSE("GPL"); #define MAJOR_NR COMPAQ_SMART2_MAJOR #include @@ -311,7 +312,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 +541,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; @@ -1227,9 +1217,9 @@ case IDAGETDRVINFO: return copy_to_user(&io->c.drv,&hba[ctlr]->drv[dsk],sizeof(drv_info_t)); case BLKGETSIZE: - if (!arg) return -EINVAL; - put_user(ida[(ctlr<i_rdev)].nr_sects, (long*)arg); - return 0; + return put_user(ida[(ctlr<i_rdev)].nr_sects, (long*)arg); + case BLKGETSIZE64: + return put_user((u64)(ida[(ctlr<i_rdev)].nr_sects) << 9, (u64*)arg); case BLKRRPART: return revalidate_logvol(inode->i_rdev, 1); case IDAPASSTHRU: @@ -1266,10 +1256,14 @@ } case BLKFLSBUF: + case BLKBSZSET: + case BLKBSZGET: case BLKROSET: case BLKROGET: case BLKRASET: case BLKRAGET: + case BLKELVGET: + case BLKELVSET: case BLKPG: return blk_ioctl(inode->i_rdev, cmd, arg); 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 Mon Sep 10 12:42:31 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 @@ -3492,6 +3497,10 @@ case BLKGETSIZE: ECALL(get_floppy_geometry(drive, type, &g)); return put_user(g->size, (long *) param); + + case BLKGETSIZE64: + ECALL(get_floppy_geometry(drive, type, &g)); + return put_user((u64)g->size << 9, (u64 *) param); /* BLKRRPART is not defined as floppies don't have * partition tables */ } @@ -4144,7 +4153,7 @@ return 0; } -static int have_no_fdc= -EIO; +static int have_no_fdc= -ENODEV; int __init floppy_init(void) @@ -4200,7 +4209,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 +4267,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 +4478,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 Sun Sep 9 12:00:55 2001 @@ -10,12 +10,137 @@ * (linux@arm.uk.linux.org) */ +/* + * TODO: rip out the remaining init crap from this file --hch + */ + #include +#include #include #include #include #include #include +#include + + +static rwlock_t gendisk_lock; + +/* + * Global kernel list of partitioning information. + * + * XXX: you should _never_ access this directly. + * the only reason this is exported is source compatiblity. + */ +/*static*/ struct gendisk *gendisk_head; + +EXPORT_SYMBOL(gendisk_head); + + +/** + * add_gendisk - add partitioning information to kernel list + * @gp: per-device partitioning information + * + * This function registers the partitioning information in @gp + * with the kernel. + */ +void +add_gendisk(struct gendisk *gp) +{ + write_lock(&gendisk_lock); + gp->next = gendisk_head; + gendisk_head = gp; + write_unlock(&gendisk_lock); +} + +EXPORT_SYMBOL(add_gendisk); + + +/** + * del_gendisk - remove partitioning information from kernel list + * @gp: per-device partitioning information + * + * This function unregisters the partitioning information in @gp + * with the kernel. + */ +void +del_gendisk(struct gendisk *gp) +{ + struct gendisk **gpp; + + write_lock(&gendisk_lock); + for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next)) + if (*gpp == gp) + break; + if (*gpp) + *gpp = (*gpp)->next; + write_unlock(&gendisk_lock); +} + +EXPORT_SYMBOL(del_gendisk); + + +/** + * get_gendisk - get partitioning information for a given device + * @dev: device to get partitioning information for + * + * This function gets the structure containing partitioning + * information for the given device @dev. + */ +struct gendisk * +get_gendisk(kdev_t dev) +{ + struct gendisk *gp = NULL; + int maj = MAJOR(dev); + + read_lock(&gendisk_lock); + for (gp = gendisk_head; gp; gp = gp->next) + if (gp->major == maj) + break; + read_unlock(&gendisk_lock); + + return gp; +} + +EXPORT_SYMBOL(get_gendisk); + + +#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"); + read_lock(&gendisk_lock); + 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: + read_unlock(&gendisk_lock); + *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 @@ -33,6 +158,7 @@ int __init device_init(void) { + rwlock_init(&gendisk_lock); blk_dev_init(); sti(); #ifdef CONFIG_I2O 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 Mon Sep 17 15:28:32 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; @@ -990,12 +974,7 @@ major = MAJOR(bhs[0]->b_dev); /* Determine correct block size for this device. */ - correct_size = BLOCK_SIZE; - if (blksize_size[major]) { - i = blksize_size[major][MINOR(bhs[0]->b_dev)]; - if (i) - correct_size = i; - } + correct_size = get_hardsect_size(bhs[0]->b_dev); /* Verify requested block sizes. */ for (i = 0; i < nr; i++) { @@ -1272,7 +1251,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 Mon Sep 17 13:16:30 2001 @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -86,10 +87,12 @@ static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf, char *loop_buf, int size, int real_block) { - if (cmd == READ) - memcpy(loop_buf, raw_buf, size); - else - memcpy(raw_buf, loop_buf, size); + if (raw_buf != loop_buf) { + if (cmd == READ) + memcpy(loop_buf, raw_buf, size); + else + memcpy(raw_buf, loop_buf, size); + } return 0; } @@ -117,6 +120,7 @@ static int none_status(struct loop_device *lo, struct loop_info *info) { + lo->lo_flags |= LO_FLAGS_BH_REMAP; return 0; } @@ -313,9 +317,13 @@ return ret; } +static void loop_end_io_transfer(struct buffer_head *bh, int uptodate); static void loop_put_buffer(struct buffer_head *bh) { - if (bh) { + /* + * check b_end_io, may just be a remapped bh and not an allocated one + */ + if (bh && bh->b_end_io == loop_end_io_transfer) { __free_page(bh->b_page); kmem_cache_free(bh_cachep, bh); } @@ -385,6 +393,14 @@ { struct buffer_head *bh; + /* + * for xfer_funcs that can operate on the same bh, do that + */ + if (lo->lo_flags & LO_FLAGS_BH_REMAP) { + bh = rbh; + goto out_bh; + } + do { bh = kmem_cache_alloc(bh_cachep, SLAB_NOIO); if (bh) @@ -397,9 +413,6 @@ bh->b_size = rbh->b_size; bh->b_dev = rbh->b_rdev; - spin_lock_irq(&lo->lo_lock); - bh->b_rdev = lo->lo_device; - spin_unlock_irq(&lo->lo_lock); bh->b_state = (1 << BH_Req) | (1 << BH_Mapped) | (1 << BH_Lock); /* @@ -418,9 +431,15 @@ bh->b_data = page_address(bh->b_page); bh->b_end_io = loop_end_io_transfer; - bh->b_rsector = rbh->b_rsector + (lo->lo_offset >> 9); + bh->b_private = rbh; init_waitqueue_head(&bh->b_wait); +out_bh: + bh->b_rsector = rbh->b_rsector + (lo->lo_offset >> 9); + spin_lock_irq(&lo->lo_lock); + bh->b_rdev = lo->lo_device; + spin_unlock_irq(&lo->lo_lock); + return bh; } @@ -475,8 +494,7 @@ * piggy old buffer on original, and submit for I/O */ bh = loop_get_buffer(lo, rbh); - bh->b_private = rbh; - IV = loop_get_iv(lo, bh->b_rsector); + IV = loop_get_iv(lo, rbh->b_rsector); if (rw == WRITE) { set_bit(BH_Dirty, &bh->b_state); if (lo_do_transfer(lo, WRITE, bh->b_data, rbh->b_data, @@ -600,7 +618,7 @@ error = -EBUSY; if (lo->lo_state != Lo_unbound) goto out; - + error = -EBADF; file = fget(arg); if (!file) @@ -620,7 +638,6 @@ * If we can't read - sorry. If we only can't write - well, * it's going to be read-only. */ - error = -EINVAL; if (!aops->readpage) goto out_putf; @@ -848,11 +865,18 @@ err = -ENXIO; break; } - if (!arg) { - err = -EINVAL; + err = put_user(loop_sizes[lo->lo_number] << 1, (long *) arg); + break; + case BLKGETSIZE64: + if (lo->lo_state != Lo_bound) { + err = -ENXIO; break; } - err = put_user(loop_sizes[lo->lo_number] << 1, (long *) arg); + err = put_user((u64)loop_sizes[lo->lo_number] << 10, (u64*)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/nbd.c linux/drivers/block/nbd.c --- v2.4.9/linux/drivers/block/nbd.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/block/nbd.c Mon Sep 10 12:42:31 2001 @@ -446,6 +446,8 @@ #endif case BLKGETSIZE: return put_user(nbd_bytesizes[dev] >> 9, (long *) arg); + case BLKGETSIZE64: + return put_user((u64)nbd_bytesizes[dev], (u64 *) arg); } return -EINVAL; } diff -u --recursive --new-file v2.4.9/linux/drivers/block/paride/bpck6.c linux/drivers/block/paride/bpck6.c --- v2.4.9/linux/drivers/block/paride/bpck6.c Sun May 20 12:11:38 2001 +++ linux/drivers/block/paride/bpck6.c Mon Sep 17 22:52:34 2001 @@ -28,7 +28,7 @@ #define EXPORT_SYMTAB #include #include -#include +#include #include #include 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 Mon Sep 10 12:42:31 2001 @@ -287,6 +287,7 @@ static struct hd_struct pd_hd[PD_DEVS]; static int pd_sizes[PD_DEVS]; static int pd_blocksizes[PD_DEVS]; +static int pd_maxsectors[PD_DEVS]; #define PD_NAMELEN 8 @@ -343,16 +344,13 @@ extern struct block_device_operations pd_fops; static struct gendisk pd_gendisk = { - PD_MAJOR, /* Major number */ - PD_NAME, /* Major name */ - PD_BITS, /* Bits to shift to get real from partition */ - PD_PARTNS, /* Number of partitions per real */ - pd_hd, /* hd struct */ - pd_sizes, /* block sizes */ - 0, /* number */ - NULL, /* internal */ - NULL, /* next */ - &pd_fops, /* block device operations */ + major: PD_MAJOR, + major_name: PD_NAME, + minor_shift: PD_BITS, + max_p: PD_PARTNS, + part: pd_hd, + sizes: pd_sizes, + fops: &pd_fops, }; static struct block_device_operations pd_fops = { @@ -385,56 +383,6 @@ } } -static inline int pd_new_segment(request_queue_t *q, struct request *req, int max_segments) -{ - if (max_segments > cluster) - max_segments = cluster; - - if (req->nr_segments < max_segments) { - req->nr_segments++; - return 1; - } - return 0; -} - -static int pd_back_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int max_segments) -{ - if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data) - return 1; - return pd_new_segment(q, req, max_segments); -} - -static int pd_front_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int max_segments) -{ - if (bh->b_data + bh->b_size == req->bh->b_data) - return 1; - return pd_new_segment(q, req, max_segments); -} - -static int pd_merge_requests_fn(request_queue_t *q, struct request *req, - struct request *next, int max_segments) -{ - int total_segments = req->nr_segments + next->nr_segments; - int same_segment; - - if (max_segments > cluster) - max_segments = cluster; - - same_segment = 0; - if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) { - total_segments--; - same_segment = 1; - } - - if (total_segments > max_segments) - return 0; - - req->nr_segments = total_segments; - return 1; -} - int pd_init (void) { int i; @@ -448,19 +396,18 @@ } q = BLK_DEFAULT_QUEUE(MAJOR_NR); blk_init_queue(q, DEVICE_REQUEST); - q->back_merge_fn = pd_back_merge_fn; - q->front_merge_fn = pd_front_merge_fn; - q->merge_requests_fn = pd_merge_requests_fn; read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ 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; + del_gendisk(&pd_gendisk); for (unit=0;unitstart); return 0; case BLKGETSIZE: - if (!arg) return -EINVAL; - err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long)); - if (err) return (err); - put_user(PF.capacity,(long *) arg); - return (0); + return put_user(PF.capacity,(long *) arg); + case BLKGETSIZE64: + return put_user((u64)PF.capacity << 9,(u64 *)arg); case BLKROSET: case BLKROGET: case BLKRASET: diff -u --recursive --new-file v2.4.9/linux/drivers/block/paride/ppc6lnx.c linux/drivers/block/paride/ppc6lnx.c --- v2.4.9/linux/drivers/block/paride/ppc6lnx.c Fri Apr 6 10:42:55 2001 +++ linux/drivers/block/paride/ppc6lnx.c Fri Sep 7 09:28:38 2001 @@ -108,28 +108,11 @@ static u8 ppc6_rd_data_byte(PPC *ppc); static u8 ppc6_rd_port(PPC *ppc, u8 port); static void ppc6_wr_port(PPC *ppc, u8 port, u8 data); -static u8 ppc6_rd_reg(PPC *ppc, u8 reg); -static void ppc6_wr_reg(PPC *ppc, u8 reg, u8 data); -static u8 ppc6_version(PPC *ppc); static void ppc6_rd_data_blk(PPC *ppc, u8 *data, long count); static void ppc6_wait_for_fifo(PPC *ppc); static void ppc6_wr_data_blk(PPC *ppc, u8 *data, long count); static void ppc6_rd_port16_blk(PPC *ppc, u8 port, u8 *data, long length); -static u16 ppc6_rd_port16(PPC *ppc, u8 port); -static void ppc6_wr_port16(PPC *ppc, u8 port, u16 data); static void ppc6_wr_port16_blk(PPC *ppc, u8 port, u8 *data, long length); -static u8 ppc6_rd_eeprom_reg(PPC *ppc); -static void ppc6_wr_eeprom_reg(PPC *ppc, u8 data); -static void ppc6_eeprom_start(PPC *ppc); -static void ppc6_eeprom_end(PPC *ppc); -static void ppc6_set_cs(PPC *ppc); -static void ppc6_reset_cs(PPC *ppc); -static u8 ppc6_rd_eeprom_bit(PPC *ppc); -static void ppc6_eeprom_ready_wait(PPC *ppc); -static void ppc6_wr_eeprom_bit(PPC *ppc, u8 bit); -static u16 ppc6_eeprom_read(PPC *ppc, u8 addr); -static u8 ppc6_irq_test(PPC *ppc); -static u8 ppc6_rd_extout(PPC *ppc); static void ppc6_wr_extout(PPC *ppc, u8 regdata); static int ppc6_open(PPC *ppc); static void ppc6_close(PPC *ppc); @@ -304,7 +287,7 @@ static u8 ppc6_rd_data_byte(PPC *ppc) { - u8 data; + u8 data = 0; switch(ppc->mode) { @@ -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 Fri Sep 14 14:04:07 2001 @@ -157,16 +157,14 @@ static struct gendisk ps2esdi_gendisk = { - MAJOR_NR, /* Major number */ - "ed", /* Major name */ - 6, /* Bits to shift to get real from partition */ - 1 << 6, /* Number of partitions per real disk */ - ps2esdi, /* hd struct */ - ps2esdi_sizes, /* block sizes */ - 0, /* number */ - (void *) ps2esdi_info, /* internal */ - NULL, /* next */ - &ps2esdi_fops, /* file operations */ + major: MAJOR_NR, + major_name: "ed", + minor_shift: 6, + max_p: 1 << 6, + part: ps2esdi, + sizes: ps2esdi_sizes, + real_devices: (void *)ps2esdi_info, + fops: &ps2esdi_fops, }; /* initialization routine called by ll_rw_blk.c */ @@ -184,8 +182,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 */ @@ -200,6 +197,7 @@ MODULE_PARM(cyl, "i"); MODULE_PARM(head, "i"); MODULE_PARM(track, "i"); +MODULE_LICENSE("GPL"); int init_module(void) { int drive; @@ -223,15 +221,15 @@ void cleanup_module(void) { - if(ps2esdi_slot) - { + if(ps2esdi_slot) { mca_mark_as_unused(ps2esdi_slot); mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); } release_region(io_base, 4); free_dma(dma_arb_level); - free_irq(PS2ESDI_IRQ, NULL) + 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 */ @@ -1117,6 +1115,9 @@ } break; + case BLKGETSIZE64: + return put_user((u64)ps2esdi[MINOR(inode->i_rdev)].nr_sects << 9, (u64 *) arg); + case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -1127,6 +1128,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 Mon Sep 17 22:52:34 2001 @@ -186,6 +186,79 @@ #endif +static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor) +{ + struct address_space * mapping = rd_inode[minor]->i_mapping; + unsigned long index; + int offset, size, err = 0; + + if (sbh->b_page->mapping == mapping) { + if (rw != READ) + SetPageDirty(sbh->b_page); + goto out; + } + + index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9); + offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK; + size = sbh->b_size; + + do { + int count; + struct page ** hash; + struct page * page; + const char * src; + char * dst; + int unlock = 0; + + count = PAGE_CACHE_SIZE - offset; + if (count > size) + count = size; + size -= count; + + hash = page_hash(mapping, index); + page = __find_get_page(mapping, index, hash); + if (!page && rw != READ) { + page = grab_cache_page(mapping, index); + err = -ENOMEM; + if (!page) + goto out; + err = 0; + unlock = 1; + } + + index++; + if (!page) { + offset = 0; + continue; + } + + if (rw == READ) { + src = kmap(page); + src += offset; + dst = bh_kmap(sbh); + } else { + dst = kmap(page); + dst += offset; + src = bh_kmap(sbh); + } + offset = 0; + + memcpy(dst, src, count); + + kunmap(page); + bh_kunmap(sbh); + + if (rw != READ) + SetPageDirty(page); + if (unlock) + UnlockPage(page); + __free_page(page); + } while (size); + + out: + return err; +} + /* * Basically, my strategy here is to set up a buffer-head which can't be * deleted, and make that my Ramdisk. If the request is outside of the @@ -198,10 +271,7 @@ { unsigned int minor; unsigned long offset, len; - struct buffer_head *rbh; - char *bdata; - minor = MINOR(sbh->b_rdev); if (minor >= NUM_RAMDISKS) @@ -221,20 +291,8 @@ goto fail; } - rbh = getblk(sbh->b_rdev, sbh->b_rsector/(sbh->b_size>>9), sbh->b_size); - /* I think that it is safe to assume that rbh is not in HighMem, though - * sbh might be - NeilBrown - */ - bdata = bh_kmap(sbh); - if (rw == READ) { - if (sbh != rbh) - memcpy(bdata, rbh->b_data, rbh->b_size); - } else - if (sbh != rbh) - memcpy(rbh->b_data, bdata, rbh->b_size); - bh_kunmap(sbh); - mark_buffer_protected(rbh); - brelse(rbh); + if (rd_blkdev_pagecache_IO(rw, sbh, minor)) + goto fail; sbh->b_end_io(sbh,1); return 0; @@ -259,16 +317,30 @@ /* 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)) - return -EBUSY; - destroy_buffers(inode->i_rdev); - rd_blocksizes[minor] = 0; + { + struct block_device * bdev = inode->i_bdev; + + down(&bdev->bd_sem); + if (bdev->bd_openers > 2) { + up(&bdev->bd_sem); + return -EBUSY; + } + bdev->bd_openers--; + bdev->bd_cache_openers--; + iput(rd_inode[minor]); + rd_inode[minor] = NULL; + rd_blocksizes[minor] = rd_blocksize; + up(&bdev->bd_sem); + } break; case BLKGETSIZE: /* Return device size */ if (!arg) return -EINVAL; return put_user(rd_kbsize[minor] << 1, (long *) arg); + case BLKGETSIZE64: + return put_user((u64)rd_kbsize[minor] << 10, (u64*)arg); + case BLKROSET: case BLKROGET: case BLKSSZGET: @@ -302,21 +374,16 @@ { extern void free_initrd_mem(unsigned long, unsigned long); - lock_kernel(); if (!--initrd_users) { - blkdev_put(inode->i_bdev, BDEV_FILE); - iput(inode); free_initrd_mem(initrd_start, initrd_end); initrd_start = 0; } - unlock_kernel(); return 0; } static struct file_operations initrd_fops = { read: initrd_read, - release: initrd_release, }; #endif @@ -326,9 +393,15 @@ { #ifdef CONFIG_BLK_DEV_INITRD if (DEVICE_NR(inode->i_rdev) == INITRD_MINOR) { + static struct block_device_operations initrd_bd_op = { + open: rd_open, + release: initrd_release, + }; + if (!initrd_start) return -ENODEV; initrd_users++; filp->f_op = &initrd_fops; + inode->i_bdev->bd_op = &initrd_bd_op; return 0; } #endif @@ -341,8 +414,14 @@ */ 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_inode[DEVICE_NR(inode->i_rdev)] = igrab(inode)) != NULL) { + struct block_device *bdev = inode->i_bdev; + + /* bdev->bd_sem is held by caller */ + bdev->bd_openers++; + bdev->bd_cache_openers++; + bdev->bd_inode = inode; + } } MOD_INC_USE_COUNT; @@ -356,7 +435,7 @@ return 0; } -static struct block_device_operations fd_fops = { +static struct block_device_operations rd_bd_op = { open: rd_open, release: rd_release, ioctl: rd_ioctl, @@ -371,7 +450,13 @@ 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); + struct block_device *bdev = rd_inode[i]->i_bdev; + + down(&bdev->bd_sem); + bdev->bd_openers--; + bdev->bd_cache_openers--; + up(&bdev->bd_sem); + /* remove stale pointer to module address space */ rd_inode[i]->i_bdev->bd_op = NULL; iput(rd_inode[i]); @@ -400,7 +485,7 @@ rd_blocksize = BLOCK_SIZE; } - if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) { + if (register_blkdev(MAJOR_NR, "ramdisk", &rd_bd_op)) { printk("RAMDISK: Could not get major %d", MAJOR_NR); return -EIO; } @@ -418,14 +503,14 @@ devfs_register_series (devfs_handle, "%u", NUM_RAMDISKS, DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, - &fd_fops, NULL); + &rd_bd_op, NULL); for (i = 0; i < NUM_RAMDISKS; i++) - register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &fd_fops, rd_size<<1); + register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1); #ifdef CONFIG_BLK_DEV_INITRD /* We ought to separate initrd operations here */ - register_disk(NULL, MKDEV(MAJOR_NR,INITRD_MINOR), 1, &fd_fops, rd_size<<1); + register_disk(NULL, MKDEV(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1); #endif hardsect_size[MAJOR_NR] = rd_hardsec; /* Size of the RAM disk blocks */ @@ -451,6 +536,8 @@ MODULE_PARM (rd_blocksize, "i"); MODULE_PARM_DESC(rd_blocksize, "Blocksize of each RAM disk in bytes."); +MODULE_LICENSE("GPL"); + /* End of non-loading portions of the RAM disk driver */ #ifdef RD_LOADER @@ -595,8 +682,10 @@ outfile.f_op = &def_blk_fops; init_special_inode(out_inode, S_IFBLK | S_IRUSR | S_IWUSR, kdev_t_to_nr(ram_device)); - if (blkdev_open(inode, &infile) != 0) + if (blkdev_open(inode, &infile) != 0) { + iput(out_inode); goto free_inode; + } if (blkdev_open(out_inode, &outfile) != 0) goto free_inodes; @@ -659,14 +748,15 @@ if (i && (i % devblocks == 0)) { printk("done disk #%d.\n", i/devblocks); rotate = 0; - invalidate_buffers(device); - if (infile.f_op->release) - infile.f_op->release(inode, &infile); + if (blkdev_close(inode, &infile) != 0) { + printk("Error closing the disk.\n"); + goto noclose_input; + } printk("Please insert disk #%d and press ENTER\n", i/devblocks+1); wait_for_keypress(); if (blkdev_open(inode, &infile) != 0) { printk("Error opening disk.\n"); - goto done; + goto noclose_input; } infile.f_pos = 0; printk("Loading disk #%d... ", i/devblocks+1); @@ -684,18 +774,20 @@ kfree(buf); successful_load: - invalidate_buffers(device); ROOT_DEV = MKDEV(MAJOR_NR, unit); if (ROOT_DEVICE_NAME != NULL) strcpy (ROOT_DEVICE_NAME, "rd/0"); done: - if (infile.f_op->release) - infile.f_op->release(inode, &infile); + blkdev_close(inode, &infile); +noclose_input: + blkdev_close(out_inode, &outfile); + iput(inode); + iput(out_inode); set_fs(fs); return; free_inodes: /* free inodes on error */ iput(out_inode); - blkdev_put(inode->i_bdev, BDEV_FILE); + blkdev_close(inode, &infile); free_inode: iput(inode); } 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 Thu Sep 13 15:21:32 2001 @@ -126,17 +126,16 @@ extern struct block_device_operations xd_fops; static struct gendisk xd_gendisk = { - MAJOR_NR, /* Major number */ - "xd", /* Major name */ - 6, /* Bits to shift to get real from partition */ - 1 << 6, /* Number of partitions per real */ - xd_struct, /* hd struct */ - xd_sizes, /* block sizes */ - 0, /* number */ - (void *) xd_info, /* internal */ - NULL, /* next */ - &xd_fops, /* file operations */ + major: MAJOR_NR, + major_name: "xd", + minor_shift: 6, + max_p: 1 << 6, + part: xd_struct, + sizes: xd_sizes, + real_devices: (void *)xd_info, + fops: &xd_fops, }; + static struct block_device_operations xd_fops = { open: xd_open, release: xd_release, @@ -173,8 +172,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; @@ -339,6 +337,8 @@ case BLKGETSIZE: if (!arg) return -EINVAL; return put_user(xd_struct[MINOR(inode->i_rdev)].nr_sects,(long *) arg); + case BLKGETSIZE64: + return put_user((u64)xd_struct[MINOR(inode->i_rdev)].nr_sects << 9, (u64 *)arg); case HDIO_SET_DMA: if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (xdc_busy) return -EBUSY; @@ -376,9 +376,7 @@ int target = DEVICE_NR(inode->i_rdev); if (target < xd_drives) { xd_access[target]--; -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif /* MODULE */ } return 0; } @@ -1110,20 +1108,16 @@ MODULE_PARM(xd_geo, "3-6i"); MODULE_PARM(nodma, "i"); +MODULE_LICENSE("GPL"); + 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/block/z2ram.c linux/drivers/block/z2ram.c --- v2.4.9/linux/drivers/block/z2ram.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/block/z2ram.c Thu Sep 13 15:21:32 2001 @@ -376,6 +376,9 @@ } #if defined(MODULE) + +MODULE_LICENSE("GPL"); + int init_module( void ) { 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 Sun Sep 9 10:43:02 2001 @@ -167,7 +167,7 @@ #include -#define MAJOR_NR AZTECH_CDROM_MAJOR +#define MAJOR_NR AZTECH_CDROM_MAJOR #include #include "aztcd.h" @@ -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 +static int aztcd_blocksizes[1] = { 2048 }; /*########################################################################### @@ -206,7 +200,7 @@ */ #define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \ delay_timer.function = (void *) (func); \ - add_timer(&delay_timer); + add_timer(&delay_timer); #define CLEAR_TIMER del_timer(&delay_timer); @@ -219,17 +213,17 @@ #define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \ outb_p(0x10,azt_port+6); \ outb_p(0x00,azt_port+7); \ - outb_p(0x10,azt_port+6); + outb_p(0x10,azt_port+6); #define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6); #if 0 #define AZT_TEST -#define AZT_TEST1 /* */ -#define AZT_TEST2 /* do_aztcd_request */ -#define AZT_TEST3 /* AZT_S_state */ -#define AZT_TEST4 /* QUICK_LOOP-counter */ -#define AZT_TEST5 /* port(1) state */ +#define AZT_TEST1 /* */ +#define AZT_TEST2 /* do_aztcd_request */ +#define AZT_TEST3 /* AZT_S_state */ +#define AZT_TEST4 /* QUICK_LOOP-counter */ +#define AZT_TEST5 /* port(1) state */ #define AZT_DEBUG #define AZT_DEBUG_MULTISESSION #endif @@ -243,30 +237,23 @@ #define READ_TIMEOUT 3000 -#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 +#define azt_port aztcd /*needed for the modutils */ /*########################################################################## Type Definitions ########################################################################## */ -enum azt_state_e -{ AZT_S_IDLE, /* 0 */ - AZT_S_START, /* 1 */ - AZT_S_MODE, /* 2 */ - AZT_S_READ, /* 3 */ - AZT_S_DATA, /* 4 */ - AZT_S_STOP, /* 5 */ - AZT_S_STOPPING /* 6 */ +enum azt_state_e { AZT_S_IDLE, /* 0 */ + AZT_S_START, /* 1 */ + AZT_S_MODE, /* 2 */ + AZT_S_READ, /* 3 */ + AZT_S_DATA, /* 4 */ + AZT_S_STOP, /* 5 */ + AZT_S_STOPPING /* 6 */ }; -enum azt_read_modes -{ AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware*/ - AZT_MODE_1, /*read mode for normal CD-ROMs*/ - AZT_MODE_2 /*read mode for XA CD-ROMs*/ +enum azt_read_modes { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware */ + AZT_MODE_1, /*read mode for normal CD-ROMs */ + AZT_MODE_2 /*read mode for XA CD-ROMs */ }; /*########################################################################## @@ -275,20 +262,20 @@ */ static int aztPresent = 0; -static volatile int azt_transfer_is_active=0; +static volatile int azt_transfer_is_active = 0; -static char azt_buf[CD_FRAMESIZE_RAW*AZT_BUF_SIZ];/*buffer for block size conversion*/ +static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ]; /*buffer for block size conversion */ #if AZT_PRIVATE_IOCTLS -static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls*/ +static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls */ #endif static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn; static volatile int azt_buf_in, azt_buf_out = -1; -static volatile int azt_error=0; -static int azt_open_count=0; +static volatile int azt_error = 0; +static int azt_open_count = 0; static volatile enum azt_state_e azt_state = AZT_S_IDLE; #ifdef AZT_TEST3 -static volatile enum azt_state_e azt_state_old = AZT_S_STOP; +static volatile enum azt_state_e azt_state_old = AZT_S_STOP; static volatile int azt_st_old = 0; #endif static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1; @@ -298,15 +285,13 @@ 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; -static char azt_cont = 0; -static char azt_init_end = 0; -static char azt_auto_eject = AZT_AUTO_EJECT; +static char azt_cont = 0; +static char azt_init_end = 0; +static char azt_auto_eject = AZT_AUTO_EJECT; static int AztTimeout, AztTries; static DECLARE_WAIT_QUEUE_HEAD(azt_waitq); @@ -316,7 +301,7 @@ static struct azt_Toc Toc[MAX_TRACKS]; static struct azt_Play_msf azt_Play; -static int aztAudioStatus = CDROM_AUDIO_NO_STATUS; +static int aztAudioStatus = CDROM_AUDIO_NO_STATUS; static char aztDiskChanged = 1; static char aztTocUpToDate = 0; @@ -329,54 +314,51 @@ ########################################################################### */ /* CDROM Drive Low Level I/O Functions */ -void op_ok(void); -void pa_ok(void); -void sten_low(void); -void dten_low(void); -void statusAzt(void); +void op_ok(void); +void pa_ok(void); +void sten_low(void); +void dten_low(void); +void statusAzt(void); static void aztStatTimer(void); /* CDROM Drive Command Functions */ -static int aztSendCmd(int cmd); -static int sendAztCmd(int cmd, struct azt_Play_msf *params); -static int aztSeek(struct azt_Play_msf *params); -static int aztSetDiskType(int type); -static int aztStatus(void); -static int getAztStatus(void); -static int aztPlay(struct azt_Play_msf *arg); +static int aztSendCmd(int cmd); +static int sendAztCmd(int cmd, struct azt_Play_msf *params); +static int aztSeek(struct azt_Play_msf *params); +static int aztSetDiskType(int type); +static int aztStatus(void); +static int getAztStatus(void); +static int aztPlay(struct azt_Play_msf *arg); static void aztCloseDoor(void); static void aztLockDoor(void); static void aztUnlockDoor(void); -static int aztGetValue(unsigned char *result); -static int aztGetQChannelInfo(struct azt_Toc *qp); -static int aztUpdateToc(void); -static int aztGetDiskInfo(void); -#if AZT_MULTISESSION - static int aztGetMultiDiskInfo(void); +static int aztGetValue(unsigned char *result); +static int aztGetQChannelInfo(struct azt_Toc *qp); +static int aztUpdateToc(void); +static int aztGetDiskInfo(void); +#if AZT_MULTISESSION +static int aztGetMultiDiskInfo(void); #endif -static int aztGetToc(int multi); +static int aztGetToc(int multi); /* Kernel Interface Functions */ -static int check_aztcd_media_change(kdev_t full_dev); -static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); +static int check_aztcd_media_change(kdev_t full_dev); +static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, + unsigned long arg); static void azt_transfer(void); static void do_aztcd_request(request_queue_t *); static void azt_invalidate_buffers(void); -int aztcd_open(struct inode *ip, struct file *fp); +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 +static int aztcd_release(struct inode *inode, struct file *file); -int aztcd_init(void); +int aztcd_init(void); static struct block_device_operations azt_fops = { - open: aztcd_open, - release: aztcd_release, - ioctl: aztcd_ioctl, - check_media_change: check_aztcd_media_change, + open:aztcd_open, + release:aztcd_release, + ioctl:aztcd_ioctl, + check_media_change:check_aztcd_media_change, }; /* Aztcd State Machine: Controls Drive Operating State */ @@ -386,7 +368,7 @@ static void azt_hsg2msf(long hsg, struct msf *msf); static long azt_msf2hsg(struct msf *mp); static void azt_bin2bcd(unsigned char *p); -static int azt_bcd2bin(unsigned char bcd); +static int azt_bcd2bin(unsigned char bcd); /*########################################################################## CDROM Drive Low Level I/O Functions @@ -397,53 +379,64 @@ /* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/ # define OP_OK op_ok() void op_ok(void) -{ aztTimeOutCount=0; - do { aztIndatum=inb(DATA_PORT); - aztTimeOutCount++; - if (aztTimeOutCount>=AZT_TIMEOUT) - { printk("aztcd: Error Wait OP_OK\n"); - break; - } - } while (aztIndatum!=AFL_OP_OK); +{ + aztTimeOutCount = 0; + do { + aztIndatum = inb(DATA_PORT); + aztTimeOutCount++; + if (aztTimeOutCount >= AZT_TIMEOUT) { + printk("aztcd: Error Wait OP_OK\n"); + break; + } + } while (aztIndatum != AFL_OP_OK); } /* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/ # define PA_OK pa_ok() void pa_ok(void) -{ aztTimeOutCount=0; - do { aztIndatum=inb(DATA_PORT); - aztTimeOutCount++; - if (aztTimeOutCount>=AZT_TIMEOUT) - { printk("aztcd: Error Wait PA_OK\n"); - break; - } - } while (aztIndatum!=AFL_PA_OK); +{ + aztTimeOutCount = 0; + do { + aztIndatum = inb(DATA_PORT); + aztTimeOutCount++; + if (aztTimeOutCount >= AZT_TIMEOUT) { + printk("aztcd: Error Wait PA_OK\n"); + break; + } + } while (aztIndatum != AFL_PA_OK); } - + /* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/ # define STEN_LOW sten_low() void sten_low(void) -{ aztTimeOutCount=0; - do { aztIndatum=inb(STATUS_PORT); - aztTimeOutCount++; - if (aztTimeOutCount>=AZT_TIMEOUT) - { if (azt_init_end) printk("aztcd: Error Wait STEN_LOW commands:%x\n",aztCmd); - break; - } - } while (aztIndatum&AFL_STATUS); +{ + aztTimeOutCount = 0; + do { + aztIndatum = inb(STATUS_PORT); + aztTimeOutCount++; + if (aztTimeOutCount >= AZT_TIMEOUT) { + if (azt_init_end) + printk + ("aztcd: Error Wait STEN_LOW commands:%x\n", + aztCmd); + break; + } + } while (aztIndatum & AFL_STATUS); } /* Wait for DTEN=Low = handshake signal 'Data available'*/ # define DTEN_LOW dten_low() void dten_low(void) -{ aztTimeOutCount=0; - do { aztIndatum=inb(STATUS_PORT); - aztTimeOutCount++; - if (aztTimeOutCount>=AZT_TIMEOUT) - { printk("aztcd: Error Wait DTEN_OK\n"); - break; - } - } while (aztIndatum&AFL_DATA); +{ + aztTimeOutCount = 0; + do { + aztIndatum = inb(STATUS_PORT); + aztTimeOutCount++; + if (aztTimeOutCount >= AZT_TIMEOUT) { + printk("aztcd: Error Wait DTEN_OK\n"); + break; + } + } while (aztIndatum & AFL_DATA); } /* @@ -452,25 +445,29 @@ */ #define STEN_LOW_WAIT statusAzt() void statusAzt(void) -{ AztTimeout = AZT_STATUS_DELAY; - SET_TIMER(aztStatTimer, HZ/100); - sleep_on(&azt_waitq); - if (AztTimeout <= 0) printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",aztCmd); - return; +{ + AztTimeout = AZT_STATUS_DELAY; + SET_TIMER(aztStatTimer, HZ / 100); + sleep_on(&azt_waitq); + if (AztTimeout <= 0) + printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n", + aztCmd); + return; } static void aztStatTimer(void) -{ if (!(inb(STATUS_PORT) & AFL_STATUS)) - { wake_up(&azt_waitq); - return; - } - AztTimeout--; - if (AztTimeout <= 0) - { wake_up(&azt_waitq); - printk("aztcd: Error aztStatTimer: Timeout\n"); - return; - } - SET_TIMER(aztStatTimer, HZ/100); +{ + if (!(inb(STATUS_PORT) & AFL_STATUS)) { + wake_up(&azt_waitq); + return; + } + AztTimeout--; + if (AztTimeout <= 0) { + wake_up(&azt_waitq); + printk("aztcd: Error aztStatTimer: Timeout\n"); + return; + } + SET_TIMER(aztStatTimer, HZ / 100); } /*########################################################################## @@ -481,111 +478,125 @@ * Send a single command, return -1 on error, else 0 */ static int aztSendCmd(int cmd) -{ unsigned char data; - int retry; +{ + unsigned char data; + int retry; #ifdef AZT_DEBUG - printk("aztcd: Executing command %x\n",cmd); + printk("aztcd: Executing command %x\n", cmd); #endif - if ((azt_port==0x1f0)||(azt_port==0x170)) - SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration*/ - - aztCmd=cmd; - outb(POLLED,MODE_PORT); - do { if (inb(STATUS_PORT)&AFL_STATUS) break; - inb(DATA_PORT); /* if status left from last command, read and */ - } while (1); /* discard it */ - do { if (inb(STATUS_PORT)&AFL_DATA) break; - inb(DATA_PORT); /* if data left from last command, read and */ - } while (1); /* discard it */ - for (retry=0;retry=AZT_RETRY_ATTEMPTS) - { printk("### Error 2 aztcd: aztSendCmd %x \n",cmd); - azt_error=0xA5; - } - RETURNM("aztSendCmd",-1); + if ((azt_port == 0x1f0) || (azt_port == 0x170)) + SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */ + + aztCmd = cmd; + outb(POLLED, MODE_PORT); + do { + if (inb(STATUS_PORT) & AFL_STATUS) + break; + inb(DATA_PORT); /* if status left from last command, read and */ + } while (1); /* discard it */ + do { + if (inb(STATUS_PORT) & AFL_DATA) + break; + inb(DATA_PORT); /* if data left from last command, read and */ + } while (1); /* discard it */ + for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { + outb((unsigned char) cmd, CMD_PORT); + STEN_LOW; + data = inb(DATA_PORT); + if (data == AFL_OP_OK) { + return 0; + } /*OP_OK? */ + if (data == AFL_OP_ERR) { + STEN_LOW; + data = inb(DATA_PORT); + printk + ("### Error 1 aztcd: aztSendCmd %x Error Code %x\n", + cmd, data); + } + } + if (retry >= AZT_RETRY_ATTEMPTS) { + printk("### Error 2 aztcd: aztSendCmd %x \n", cmd); + azt_error = 0xA5; + } + RETURNM("aztSendCmd", -1); } /* * Send a play or read command to the drive, return -1 on error, else 0 */ static int sendAztCmd(int cmd, struct azt_Play_msf *params) -{ unsigned char data; - int retry; +{ + unsigned char data; + int retry; #ifdef AZT_DEBUG - printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n", \ - params->start.min, params->start.sec, params->start.frame, \ - params->end.min, params->end.sec, params->end.frame); -#endif - for (retry=0;retry start.min,CMD_PORT); - outb(params -> start.sec,CMD_PORT); - outb(params -> start.frame,CMD_PORT); - outb(params -> end.min,CMD_PORT); - outb(params -> end.sec,CMD_PORT); - outb(params -> end.frame,CMD_PORT); - STEN_LOW; - data=inb(DATA_PORT); - if (data==AFL_PA_OK) - { return 0;} /*PA_OK ?*/ - if (data==AFL_PA_ERR) - { STEN_LOW; - data=inb(DATA_PORT); - printk("### Error 1 aztcd: sendAztCmd %x Error Code %x\n",cmd,data); - } - } - if (retry>=AZT_RETRY_ATTEMPTS) - { printk("### Error 2 aztcd: sendAztCmd %x\n ",cmd); - azt_error=0xA5; - } - RETURNM("sendAztCmd",-1); + printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n", + params->start.min, params->start.sec, params->start.frame, + params->end.min, params->end.sec, params->end.frame); +#endif + for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { + aztSendCmd(cmd); + outb(params->start.min, CMD_PORT); + outb(params->start.sec, CMD_PORT); + outb(params->start.frame, CMD_PORT); + outb(params->end.min, CMD_PORT); + outb(params->end.sec, CMD_PORT); + outb(params->end.frame, CMD_PORT); + STEN_LOW; + data = inb(DATA_PORT); + if (data == AFL_PA_OK) { + return 0; + } /*PA_OK ? */ + if (data == AFL_PA_ERR) { + STEN_LOW; + data = inb(DATA_PORT); + printk + ("### Error 1 aztcd: sendAztCmd %x Error Code %x\n", + cmd, data); + } + } + if (retry >= AZT_RETRY_ATTEMPTS) { + printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd); + azt_error = 0xA5; + } + RETURNM("sendAztCmd", -1); } /* * Send a seek command to the drive, return -1 on error, else 0 */ static int aztSeek(struct azt_Play_msf *params) -{ unsigned char data; - int retry; +{ + unsigned char data; + int retry; #ifdef AZT_DEBUG - printk("aztcd: aztSeek %02x:%02x:%02x\n", \ - params->start.min, params->start.sec, params->start.frame); -#endif - for (retry=0;retry start.min,CMD_PORT); - outb(params -> start.sec,CMD_PORT); - outb(params -> start.frame,CMD_PORT); - STEN_LOW; - data=inb(DATA_PORT); - if (data==AFL_PA_OK) - { return 0;} /*PA_OK ?*/ - if (data==AFL_PA_ERR) - { STEN_LOW; - data=inb(DATA_PORT); - printk("### Error 1 aztcd: aztSeek\n"); - } - } - if (retry>=AZT_RETRY_ATTEMPTS) - { printk("### Error 2 aztcd: aztSeek\n "); - azt_error=0xA5; - } - RETURNM("aztSeek",-1); + printk("aztcd: aztSeek %02x:%02x:%02x\n", + params->start.min, params->start.sec, params->start.frame); +#endif + for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { + aztSendCmd(ACMD_SEEK); + outb(params->start.min, CMD_PORT); + outb(params->start.sec, CMD_PORT); + outb(params->start.frame, CMD_PORT); + STEN_LOW; + data = inb(DATA_PORT); + if (data == AFL_PA_OK) { + return 0; + } /*PA_OK ? */ + if (data == AFL_PA_ERR) { + STEN_LOW; + data = inb(DATA_PORT); + printk("### Error 1 aztcd: aztSeek\n"); + } + } + if (retry >= AZT_RETRY_ATTEMPTS) { + printk("### Error 2 aztcd: aztSeek\n "); + azt_error = 0xA5; + } + RETURNM("aztSeek", -1); } /* Send a Set Disk Type command @@ -593,79 +604,86 @@ dent on which mode is set ??? */ static int aztSetDiskType(int type) -{ unsigned char data; - int retry; +{ + unsigned char data; + int retry; #ifdef AZT_DEBUG - printk("aztcd: set disk type command: type= %i\n",type); + printk("aztcd: set disk type command: type= %i\n", type); #endif - for (retry=0;retry=AZT_RETRY_ATTEMPTS) - { printk("### Error 2 aztcd: aztSetDiskType %x\n ",type); - azt_error=0xA5; - } - RETURNM("aztSetDiskType",-1); + for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { + aztSendCmd(ACMD_SET_DISK_TYPE); + outb(type, CMD_PORT); + STEN_LOW; + data = inb(DATA_PORT); + if (data == AFL_PA_OK) { /*PA_OK ? */ + azt_read_mode = type; + return 0; + } + if (data == AFL_PA_ERR) { + STEN_LOW; + data = inb(DATA_PORT); + printk + ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n", + type, data); + } + } + if (retry >= AZT_RETRY_ATTEMPTS) { + printk("### Error 2 aztcd: aztSetDiskType %x\n ", type); + azt_error = 0xA5; + } + RETURNM("aztSetDiskType", -1); } /* used in azt_poll to poll the status, expects another program to issue a * ACMD_GET_STATUS directly before */ -static int aztStatus(void) -{ int st; +static int aztStatus(void) +{ + int st; /* int i; i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ??? if (!i) -*/ STEN_LOW; - if (aztTimeOutCount=AZT_TIMEOUT) - { printk("aztcd: aztGetValue timeout\n"); + if (aztTimeOutCount >= AZT_TIMEOUT) { + printk("aztcd: aztGetValue timeout\n"); return -1; } s = inb(DATA_PORT) & 0xFF; @@ -731,42 +752,55 @@ * table of contents. */ int aztGetQChannelInfo(struct azt_Toc *qp) -{ unsigned char notUsed; +{ + unsigned char notUsed; int st; #ifdef AZT_DEBUG - printk("aztcd: starting aztGetQChannelInfo Time:%li\n",jiffies); + printk("aztcd: starting aztGetQChannelInfo Time:%li\n", jiffies); #endif - if ((st=getAztStatus())==-1) RETURNM("aztGetQChannelInfo 1",-1); - if (aztSendCmd(ACMD_GET_Q_CHANNEL)) RETURNM("aztGetQChannelInfo 2",-1); - /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here*/ - if (aztGetValue(¬Used)) RETURNM("aztGetQChannelInfo 3",-1); /*??? Nullbyte einlesen*/ - if ((st&AST_MODE_BITS)==AST_INITIAL) - { qp->ctrl_addr=0; /* when audio stop ACMD_GET_Q_CHANNEL returns */ - qp->track=0; /* only one byte with Aztech drives */ - qp->pointIndex=0; - qp->trackTime.min=0; - qp->trackTime.sec=0; - qp->trackTime.frame=0; - qp->diskTime.min=0; - qp->diskTime.sec=0; - qp->diskTime.frame=0; - return 0; - } - else - { if (aztGetValue(&qp -> ctrl_addr) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(&qp -> track) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(&qp -> pointIndex) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(&qp -> trackTime.min) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(&qp -> trackTime.sec) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(&qp -> trackTime.frame) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(¬Used) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(&qp -> diskTime.min) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(&qp -> diskTime.sec) < 0) RETURNM("aztGetQChannelInfo 4",-1); - if (aztGetValue(&qp -> diskTime.frame) < 0) RETURNM("aztGetQChannelInfo 4",-1); - } + if ((st = getAztStatus()) == -1) + RETURNM("aztGetQChannelInfo 1", -1); + if (aztSendCmd(ACMD_GET_Q_CHANNEL)) + RETURNM("aztGetQChannelInfo 2", -1); + /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */ + if (aztGetValue(¬Used)) + RETURNM("aztGetQChannelInfo 3", -1); /*??? Nullbyte einlesen */ + if ((st & AST_MODE_BITS) == AST_INITIAL) { + qp->ctrl_addr = 0; /* when audio stop ACMD_GET_Q_CHANNEL returns */ + qp->track = 0; /* only one byte with Aztech drives */ + qp->pointIndex = 0; + qp->trackTime.min = 0; + qp->trackTime.sec = 0; + qp->trackTime.frame = 0; + qp->diskTime.min = 0; + qp->diskTime.sec = 0; + qp->diskTime.frame = 0; + return 0; + } else { + if (aztGetValue(&qp->ctrl_addr) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(&qp->track) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(&qp->pointIndex) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(&qp->trackTime.min) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(&qp->trackTime.sec) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(&qp->trackTime.frame) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(¬Used) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(&qp->diskTime.min) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(&qp->diskTime.sec) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + if (aztGetValue(&qp->diskTime.frame) < 0) + RETURNM("aztGetQChannelInfo 4", -1); + } #ifdef AZT_DEBUG - printk("aztcd: exiting aztGetQChannelInfo Time:%li\n",jiffies); + printk("aztcd: exiting aztGetQChannelInfo Time:%li\n", jiffies); #endif return 0; } @@ -775,11 +809,12 @@ * Read the table of contents (TOC) and TOC header if necessary */ static int aztUpdateToc() -{ int st; +{ + int st; #ifdef AZT_DEBUG - printk("aztcd: starting aztUpdateToc Time:%li\n",jiffies); -#endif + printk("aztcd: starting aztUpdateToc Time:%li\n", jiffies); +#endif if (aztTocUpToDate) return 0; @@ -789,57 +824,63 @@ if (aztGetToc(0) < 0) return -EIO; - /*audio disk detection - with my Aztech drive there is no audio status bit, so I use the copy - protection bit of the first track. If this track is copy protected - (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */ - if (!(Toc[DiskInfo.first].ctrl_addr & 0x40)) - DiskInfo.audio=1; - else - DiskInfo.audio=0; - - /* XA detection */ - if (! DiskInfo.audio) - { azt_Play.start.min = 0; /*XA detection only seems to work*/ - azt_Play.start.sec = 2; /*when we play a track*/ - azt_Play.start.frame = 0; - azt_Play.end.min = 0; - azt_Play.end.sec = 0; - azt_Play.end.frame = 1; - if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1; - DTEN_LOW; - for (st=0;st0;limit--) - { if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetDiskInfo 2",-1); - if (qInfo.pointIndex==0xA0) /*Number of FirstTrack*/ - { DiskInfo.first = qInfo.diskTime.min; - DiskInfo.first = azt_bcd2bin(DiskInfo.first); - test=test|0x01; - } - if (qInfo.pointIndex==0xA1) /*Number of LastTrack*/ - { DiskInfo.last = qInfo.diskTime.min; - DiskInfo.last = azt_bcd2bin(DiskInfo.last); - test=test|0x02; - } - if (qInfo.pointIndex==0xA2) /*DiskLength*/ - { DiskInfo.diskLength.min=qInfo.diskTime.min; - DiskInfo.diskLength.sec=qInfo.diskTime.sec; - DiskInfo.diskLength.frame=qInfo.diskTime.frame; - test=test|0x04; - } - if ((qInfo.pointIndex==DiskInfo.first)&&(test&0x01)) /*StartTime of First Track*/ - { DiskInfo.firstTrack.min=qInfo.diskTime.min; - DiskInfo.firstTrack.sec=qInfo.diskTime.sec; - DiskInfo.firstTrack.frame=qInfo.diskTime.frame; - test=test|0x08; - } - if (test==0x0F) break; - } -#ifdef AZT_DEBUG - printk ("aztcd: exiting aztGetDiskInfo Time:%li\n",jiffies); - printk("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n", - DiskInfo.first, - DiskInfo.last, - DiskInfo.diskLength.min, - DiskInfo.diskLength.sec, - DiskInfo.diskLength.frame, - DiskInfo.firstTrack.min, - DiskInfo.firstTrack.sec, - DiskInfo.firstTrack.frame); +{ + int limit; + unsigned char test; + struct azt_Toc qInfo; + +#ifdef AZT_DEBUG + printk("aztcd: starting aztGetDiskInfo Time:%li\n", jiffies); +#endif + if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) + RETURNM("aztGetDiskInfo 1", -1); + STEN_LOW_WAIT; + test = 0; + for (limit = 300; limit > 0; limit--) { + if (aztGetQChannelInfo(&qInfo) < 0) + RETURNM("aztGetDiskInfo 2", -1); + if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */ + DiskInfo.first = qInfo.diskTime.min; + DiskInfo.first = azt_bcd2bin(DiskInfo.first); + test = test | 0x01; + } + if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */ + DiskInfo.last = qInfo.diskTime.min; + DiskInfo.last = azt_bcd2bin(DiskInfo.last); + test = test | 0x02; + } + if (qInfo.pointIndex == 0xA2) { /*DiskLength */ + DiskInfo.diskLength.min = qInfo.diskTime.min; + DiskInfo.diskLength.sec = qInfo.diskTime.sec; + DiskInfo.diskLength.frame = qInfo.diskTime.frame; + test = test | 0x04; + } + if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) { /*StartTime of First Track */ + DiskInfo.firstTrack.min = qInfo.diskTime.min; + DiskInfo.firstTrack.sec = qInfo.diskTime.sec; + DiskInfo.firstTrack.frame = qInfo.diskTime.frame; + test = test | 0x08; + } + if (test == 0x0F) + break; + } +#ifdef AZT_DEBUG + printk("aztcd: exiting aztGetDiskInfo Time:%li\n", jiffies); + printk + ("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\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 (test!=0x0F) return -1; - return 0; + if (test != 0x0F) + return -1; + return 0; } #if AZT_MULTISESSION @@ -906,93 +949,105 @@ * Get Multisession Disk Info */ static int aztGetMultiDiskInfo(void) -{ int limit, k=5; - unsigned char test; - struct azt_Toc qInfo; - -#ifdef AZT_DEBUG - printk("aztcd: starting aztGetMultiDiskInfo\n"); -#endif - - do { azt_Play.start.min = Toc[DiskInfo.last+1].diskTime.min; - azt_Play.start.sec = Toc[DiskInfo.last+1].diskTime.sec; - azt_Play.start.frame = Toc[DiskInfo.last+1].diskTime.frame; - test=0; - - for (limit=30;limit>0;limit--) /*Seek for LeadIn of next session*/ - { if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 1",-1); - if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 2",-1); - if ((qInfo.track==0)&&(qInfo.pointIndex)) break; /*LeadIn found*/ - if ((azt_Play.start.sec+=10) > 59) - { azt_Play.start.sec=0; - azt_Play.start.min++; - } - } - if (!limit) break; /*Check, if a leadin track was found, if not we're - at the end of the disk*/ +{ + int limit, k = 5; + unsigned char test; + struct azt_Toc qInfo; + +#ifdef AZT_DEBUG + printk("aztcd: starting aztGetMultiDiskInfo\n"); +#endif + + do { + azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min; + azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec; + azt_Play.start.frame = + Toc[DiskInfo.last + 1].diskTime.frame; + test = 0; + + for (limit = 30; limit > 0; limit--) { /*Seek for LeadIn of next session */ + if (aztSeek(&azt_Play)) + RETURNM("aztGetMultiDiskInfo 1", -1); + if (aztGetQChannelInfo(&qInfo) < 0) + RETURNM("aztGetMultiDiskInfo 2", -1); + if ((qInfo.track == 0) && (qInfo.pointIndex)) + break; /*LeadIn found */ + if ((azt_Play.start.sec += 10) > 59) { + azt_Play.start.sec = 0; + azt_Play.start.min++; + } + } + if (!limit) + break; /*Check, if a leadin track was found, if not we're + at the end of the disk */ #ifdef AZT_DEBUG_MULTISESSION - printk("leadin found track %d pointIndex %x limit %d\n",qInfo.track,qInfo.pointIndex,limit); + printk("leadin found track %d pointIndex %x limit %d\n", + qInfo.track, qInfo.pointIndex, limit); #endif - for (limit=300;limit>0;limit--) - { if (++azt_Play.start.frame>74) - { azt_Play.start.frame=0; - if (azt_Play.start.sec > 59) - { azt_Play.start.sec=0; - azt_Play.start.min++; - } - } - if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 3",-1); - if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 4",-1); - if (qInfo.pointIndex==0xA0) /*Number of NextTrack*/ - { DiskInfo.next = qInfo.diskTime.min; - DiskInfo.next = azt_bcd2bin(DiskInfo.next); - test=test|0x01; - } - if (qInfo.pointIndex==0xA1) /*Number of LastTrack*/ - { DiskInfo.last = qInfo.diskTime.min; - DiskInfo.last = azt_bcd2bin(DiskInfo.last); - test=test|0x02; - } - if (qInfo.pointIndex==0xA2) /*DiskLength*/ - { DiskInfo.diskLength.min =qInfo.diskTime.min; - DiskInfo.diskLength.sec =qInfo.diskTime.sec; - DiskInfo.diskLength.frame=qInfo.diskTime.frame; - test=test|0x04; - } - if ((qInfo.pointIndex==DiskInfo.next)&&(test&0x01)) /*StartTime of Next Track*/ - { DiskInfo.nextSession.min=qInfo.diskTime.min; - DiskInfo.nextSession.sec=qInfo.diskTime.sec; - DiskInfo.nextSession.frame=qInfo.diskTime.frame; - test=test|0x08; + for (limit = 300; limit > 0; limit--) { + if (++azt_Play.start.frame > 74) { + azt_Play.start.frame = 0; + if (azt_Play.start.sec > 59) { + azt_Play.start.sec = 0; + azt_Play.start.min++; + } + } + if (aztSeek(&azt_Play)) + RETURNM("aztGetMultiDiskInfo 3", -1); + if (aztGetQChannelInfo(&qInfo) < 0) + RETURNM("aztGetMultiDiskInfo 4", -1); + if (qInfo.pointIndex == 0xA0) { /*Number of NextTrack */ + DiskInfo.next = qInfo.diskTime.min; + DiskInfo.next = azt_bcd2bin(DiskInfo.next); + test = test | 0x01; + } + if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */ + DiskInfo.last = qInfo.diskTime.min; + DiskInfo.last = azt_bcd2bin(DiskInfo.last); + test = test | 0x02; + } + if (qInfo.pointIndex == 0xA2) { /*DiskLength */ + DiskInfo.diskLength.min = + qInfo.diskTime.min; + DiskInfo.diskLength.sec = + qInfo.diskTime.sec; + DiskInfo.diskLength.frame = + qInfo.diskTime.frame; + test = test | 0x04; + } + if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) { /*StartTime of Next Track */ + DiskInfo.nextSession.min = + qInfo.diskTime.min; + DiskInfo.nextSession.sec = + qInfo.diskTime.sec; + DiskInfo.nextSession.frame = + qInfo.diskTime.frame; + test = test | 0x08; + } + if (test == 0x0F) + break; } - if (test==0x0F) break; - } #ifdef AZT_DEBUG_MULTISESSION - printk ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n", - DiskInfo.first, - DiskInfo.next, - DiskInfo.last, - DiskInfo.diskLength.min, - DiskInfo.diskLength.sec, - DiskInfo.diskLength.frame, - DiskInfo.firstTrack.min, - DiskInfo.firstTrack.sec, - DiskInfo.firstTrack.frame, - DiskInfo.nextSession.min, - DiskInfo.nextSession.sec, - DiskInfo.nextSession.frame); -#endif - if (test!=0x0F) - break; - else - DiskInfo.multi=1; /*found TOC of more than one session*/ - aztGetToc(1); - } while(--k); + printk + ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n", + DiskInfo.first, DiskInfo.next, DiskInfo.last, + DiskInfo.diskLength.min, DiskInfo.diskLength.sec, + DiskInfo.diskLength.frame, DiskInfo.firstTrack.min, + DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame, + DiskInfo.nextSession.min, DiskInfo.nextSession.sec, + DiskInfo.nextSession.frame); +#endif + if (test != 0x0F) + break; + else + DiskInfo.multi = 1; /*found TOC of more than one session */ + aztGetToc(1); + } while (--k); #ifdef AZT_DEBUG - printk ("aztcd: exiting aztGetMultiDiskInfo Time:%li\n",jiffies); + printk("aztcd: exiting aztGetMultiDiskInfo Time:%li\n", jiffies); #endif - return 0; + return 0; } #endif @@ -1000,75 +1055,81 @@ * Read the table of contents (TOC) */ static int aztGetToc(int multi) -{ int i, px; - int limit; - struct azt_Toc qInfo; - -#ifdef AZT_DEBUG - printk("aztcd: starting aztGetToc Time:%li\n",jiffies); -#endif - if (!multi) - { for (i = 0; i < MAX_TRACKS; i++) - Toc[i].pointIndex = 0; - i = DiskInfo.last + 3; - } - else - { for (i = DiskInfo.next; i < MAX_TRACKS; i++) - Toc[i].pointIndex = 0; - i = DiskInfo.last + 4 - DiskInfo.next; - } +{ + int i, px; + int limit; + struct azt_Toc qInfo; + +#ifdef AZT_DEBUG + printk("aztcd: starting aztGetToc Time:%li\n", jiffies); +#endif + if (!multi) { + for (i = 0; i < MAX_TRACKS; i++) + Toc[i].pointIndex = 0; + i = DiskInfo.last + 3; + } else { + for (i = DiskInfo.next; i < MAX_TRACKS; i++) + Toc[i].pointIndex = 0; + i = DiskInfo.last + 4 - DiskInfo.next; + } /*Is there a good reason to stop motor before TOC read? if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1); STEN_LOW_WAIT; */ - if (!multi) - { azt_mode = 0x05; - if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetToc 2",-1); - STEN_LOW_WAIT; - } - for (limit = 300; limit > 0; limit--) - { if (multi) - { if (++azt_Play.start.sec > 59) - { azt_Play.start.sec=0; - azt_Play.start.min++; - } - if (aztSeek(&azt_Play)) RETURNM("aztGetToc 3",-1); - } - if (aztGetQChannelInfo(&qInfo) < 0) - break; - - px = azt_bcd2bin(qInfo.pointIndex); - - if (px > 0 && px < MAX_TRACKS && qInfo.track == 0) - if (Toc[px].pointIndex == 0) - { Toc[px] = qInfo; - i--; - } - - if (i <= 0) - break; - } - - Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength; - Toc[DiskInfo.last].trackTime = DiskInfo.diskLength; - -#ifdef AZT_DEBUG_MULTISESSION - printk("aztcd: exiting aztGetToc\n"); - for (i = 1; i <= DiskInfo.last+1; i++) - printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\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 dez %02X:%02X.%02X dez\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); + if (!multi) { + azt_mode = 0x05; + if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) + RETURNM("aztGetToc 2", -1); + STEN_LOW_WAIT; + } + for (limit = 300; limit > 0; limit--) { + if (multi) { + if (++azt_Play.start.sec > 59) { + azt_Play.start.sec = 0; + azt_Play.start.min++; + } + if (aztSeek(&azt_Play)) + RETURNM("aztGetToc 3", -1); + } + if (aztGetQChannelInfo(&qInfo) < 0) + break; + + px = azt_bcd2bin(qInfo.pointIndex); + + if (px > 0 && px < MAX_TRACKS && qInfo.track == 0) + if (Toc[px].pointIndex == 0) { + Toc[px] = qInfo; + i--; + } + + if (i <= 0) + break; + } + + Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength; + Toc[DiskInfo.last].trackTime = DiskInfo.diskLength; + +#ifdef AZT_DEBUG_MULTISESSION + printk("aztcd: exiting aztGetToc\n"); + for (i = 1; i <= DiskInfo.last + 1; i++) + printk + ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\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 dez %02X:%02X.%02X dez\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; + return limit > 0 ? 0 : -1; } @@ -1080,163 +1141,186 @@ #ifndef MODULE static int __init aztcd_setup(char *str) { - int ints[4]; - - (void)get_options(str, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) - azt_port = ints[1]; - if (ints[1] > 1) - azt_cont = ints[2]; - return 1; + int ints[4]; + + (void) get_options(str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) + azt_port = ints[1]; + if (ints[1] > 1) + azt_cont = ints[2]; + return 1; } __setup("aztcd=", aztcd_setup); -#endif /* !MODULE */ +#endif /* !MODULE */ /* * Checking if the media has been changed */ static int check_aztcd_media_change(kdev_t full_dev) -{ if (aztDiskChanged) /* disk changed */ - { aztDiskChanged=0; - return 1; - } - else - return 0; /* no change */ +{ + if (aztDiskChanged) { /* disk changed */ + aztDiskChanged = 0; + return 1; + } else + return 0; /* no change */ } /* * Kernel IO-controls */ -static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) -{ int i, st; +static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, + unsigned long arg) +{ + int i; struct azt_Toc qInfo; struct cdrom_ti ti; struct cdrom_tochdr tocHdr; struct cdrom_msf msf; struct cdrom_tocentry entry; - struct azt_Toc *tocPtr; + struct azt_Toc *tocPtr; struct cdrom_subchnl subchnl; - struct cdrom_volctrl volctrl; + struct cdrom_volctrl volctrl; #ifdef AZT_DEBUG - printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n",cmd, jiffies); - printk("aztcd Status %x\n", getAztStatus()); -#endif - if (!ip) RETURNM("aztcd_ioctl 1",-EINVAL); - if (getAztStatus()<0) RETURNM("aztcd_ioctl 2", -EIO); - if ((!aztTocUpToDate)||(aztDiskChanged)) - { if ((i=aztUpdateToc())<0) RETURNM("aztcd_ioctl 3", i); /* error reading TOC */ + printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n", + cmd, jiffies); + printk("aztcd Status %x\n", getAztStatus()); +#endif + if (!ip) + RETURNM("aztcd_ioctl 1", -EINVAL); + if (getAztStatus() < 0) + RETURNM("aztcd_ioctl 2", -EIO); + if ((!aztTocUpToDate) || (aztDiskChanged)) { + if ((i = aztUpdateToc()) < 0) + RETURNM("aztcd_ioctl 3", i); /* error reading TOC */ } - switch (cmd) - { - case CDROMSTART: /* Spin up the drive. Don't know, what to do, - at least close the tray */ -#if AZT_PRIVATE_IOCTLS - if (aztSendCmd(ACMD_CLOSE)) RETURNM("aztcd_ioctl 4",-1); - STEN_LOW_WAIT; + switch (cmd) { + case CDROMSTART: /* Spin up the drive. Don't know, what to do, + at least close the tray */ +#if AZT_PRIVATE_IOCTLS + if (aztSendCmd(ACMD_CLOSE)) + RETURNM("aztcd_ioctl 4", -1); + STEN_LOW_WAIT; #endif break; - case CDROMSTOP: /* Spin down the drive */ - if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 5",-1); + case CDROMSTOP: /* Spin down the drive */ + if (aztSendCmd(ACMD_STOP)) + RETURNM("aztcd_ioctl 5", -1); STEN_LOW_WAIT; /* should we do anything if it fails? */ aztAudioStatus = CDROM_AUDIO_NO_STATUS; break; - case CDROMPAUSE: /* Pause the drive */ - if (aztAudioStatus != CDROM_AUDIO_PLAY) return -EINVAL; - - if (aztGetQChannelInfo(&qInfo) < 0) - { /* didn't get q channel info */ - aztAudioStatus = CDROM_AUDIO_NO_STATUS; - RETURNM("aztcd_ioctl 7",0); + case CDROMPAUSE: /* Pause the drive */ + if (aztAudioStatus != CDROM_AUDIO_PLAY) + return -EINVAL; + + if (aztGetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */ + aztAudioStatus = CDROM_AUDIO_NO_STATUS; + RETURNM("aztcd_ioctl 7", 0); } - azt_Play.start = qInfo.diskTime; /* remember restart point */ + azt_Play.start = qInfo.diskTime; /* remember restart point */ - if (aztSendCmd(ACMD_PAUSE)) RETURNM("aztcd_ioctl 8",-1); + if (aztSendCmd(ACMD_PAUSE)) + RETURNM("aztcd_ioctl 8", -1); STEN_LOW_WAIT; aztAudioStatus = CDROM_AUDIO_PAUSED; break; - case CDROMRESUME: /* Play it again, Sam */ - if (aztAudioStatus != CDROM_AUDIO_PAUSED) return -EINVAL; + case CDROMRESUME: /* Play it again, Sam */ + if (aztAudioStatus != CDROM_AUDIO_PAUSED) + return -EINVAL; /* restart the drive at the saved position. */ i = aztPlay(&azt_Play); - if (i < 0) - { aztAudioStatus = CDROM_AUDIO_ERROR; - return -EIO; + if (i < 0) { + aztAudioStatus = CDROM_AUDIO_ERROR; + return -EIO; } aztAudioStatus = CDROM_AUDIO_PLAY; break; - case CDROMMULTISESSION: /*multisession support -- experimental*/ - { struct cdrom_multisession ms; -#ifdef AZT_DEBUG - printk("aztcd ioctl MULTISESSION\n"); + case CDROMMULTISESSION: /*multisession support -- experimental */ + { + struct cdrom_multisession ms; +#ifdef AZT_DEBUG + printk("aztcd ioctl MULTISESSION\n"); +#endif + 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); + ms.addr.msf.frame = + azt_bcd2bin(DiskInfo.lastSession. + frame); + } else if (ms.addr_format == CDROM_LBA) + ms.addr.lba = + azt_msf2hsg(&DiskInfo.lastSession); + else + return -EINVAL; + ms.xa_flag = DiskInfo.xa; + 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", + ms.xa_flag, ms.addr.msf.minute, + ms.addr.msf.second, ms.addr.msf.frame, + DiskInfo.lastSession.min, + DiskInfo.lastSession.sec, + DiskInfo.lastSession.frame); + else + printk + ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n", + ms.xa_flag, ms.addr.lba, + DiskInfo.lastSession.min, + DiskInfo.lastSession.sec, + DiskInfo.lastSession.frame); #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 (ms.addr_format == CDROM_MSF) - { ms.addr.msf.minute = azt_bcd2bin(DiskInfo.lastSession.min); - ms.addr.msf.second = azt_bcd2bin(DiskInfo.lastSession.sec); - ms.addr.msf.frame = azt_bcd2bin(DiskInfo.lastSession.frame); - } - else if (ms.addr_format == CDROM_LBA) - ms.addr.lba = azt_msf2hsg(&DiskInfo.lastSession); - else - return -EINVAL; - ms.xa_flag = DiskInfo.xa; - memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession)); -#ifdef AZT_DEBUG - if (ms.addr_format == CDROM_MSF) - printk("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n", - ms.xa_flag, ms.addr.msf.minute, ms.addr.msf.second, - ms.addr.msf.frame, DiskInfo.lastSession.min, - DiskInfo.lastSession.sec, DiskInfo.lastSession.frame); - else - printk("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n", - ms.xa_flag, ms.addr.lba, DiskInfo.lastSession.min, - DiskInfo.lastSession.sec, DiskInfo.lastSession.frame); -#endif - 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); + return 0; + } + case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ + 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) - { return -EINVAL; + || ti.cdti_trk0 > DiskInfo.last + || ti.cdti_trk1 < ti.cdti_trk0) { + return -EINVAL; } if (ti.cdti_trk1 > DiskInfo.last) - ti.cdti_trk1 = DiskInfo.last; + ti.cdti_trk1 = DiskInfo.last; azt_Play.start = Toc[ti.cdti_trk0].diskTime; azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime; #ifdef AZT_DEBUG -printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n", - azt_Play.start.min, azt_Play.start.sec, azt_Play.start.frame, - azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame); + printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n", + azt_Play.start.min, azt_Play.start.sec, + azt_Play.start.frame, azt_Play.end.min, + azt_Play.end.sec, azt_Play.end.frame); #endif i = aztPlay(&azt_Play); - if (i < 0) - { aztAudioStatus = CDROM_AUDIO_ERROR; - return -EIO; + if (i < 0) { + aztAudioStatus = CDROM_AUDIO_ERROR; + return -EIO; } aztAudioStatus = CDROM_AUDIO_PLAY; break; - case CDROMPLAYMSF: /* Play starting at the given MSF address. */ + case CDROMPLAYMSF: /* Play starting at the given MSF address. */ /* if (aztAudioStatus == CDROM_AUDIO_PLAY) { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1); STEN_LOW; 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); @@ -1251,171 +1335,190 @@ azt_Play.end.sec = msf.cdmsf_sec1; azt_Play.end.frame = msf.cdmsf_frame1; #ifdef AZT_DEBUG -printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n", -azt_Play.start.min, azt_Play.start.sec, azt_Play.start.frame, -azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame); + printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n", + azt_Play.start.min, azt_Play.start.sec, + azt_Play.start.frame, azt_Play.end.min, + azt_Play.end.sec, azt_Play.end.frame); #endif i = aztPlay(&azt_Play); - if (i < 0) - { aztAudioStatus = CDROM_AUDIO_ERROR; - return -EIO; + if (i < 0) { + aztAudioStatus = CDROM_AUDIO_ERROR; + return -EIO; } aztAudioStatus = CDROM_AUDIO_PLAY; break; - case CDROMREADTOCHDR: /* Read the table of contents header */ - st = verify_area(VERIFY_WRITE, (void *) arg, sizeof tocHdr); - if (st) return st; + case CDROMREADTOCHDR: /* Read the table of contents header */ 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 ((!aztTocUpToDate)||aztDiskChanged) aztUpdateToc(); + case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ + 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]; + tocPtr = &Toc[DiskInfo.last + 1]; else if (entry.cdte_track > DiskInfo.last - || 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_track < DiskInfo.first) { + return -EINVAL; + } else + tocPtr = &Toc[entry.cdte_track]; + entry.cdte_adr = tocPtr->ctrl_addr; + entry.cdte_ctrl = tocPtr->ctrl_addr >> 4; if (entry.cdte_format == CDROM_LBA) - entry.cdte_addr.lba = azt_msf2hsg(&tocPtr -> diskTime); - else if (entry.cdte_format == CDROM_MSF) - { entry.cdte_addr.msf.minute = azt_bcd2bin(tocPtr -> diskTime.min); - entry.cdte_addr.msf.second = azt_bcd2bin(tocPtr -> diskTime.sec); - entry.cdte_addr.msf.frame = azt_bcd2bin(tocPtr -> diskTime.frame); + entry.cdte_addr.lba = + azt_msf2hsg(&tocPtr->diskTime); + else if (entry.cdte_format == CDROM_MSF) { + entry.cdte_addr.msf.minute = + azt_bcd2bin(tocPtr->diskTime.min); + entry.cdte_addr.msf.second = + azt_bcd2bin(tocPtr->diskTime.sec); + entry.cdte_addr.msf.frame = + azt_bcd2bin(tocPtr->diskTime.frame); + } else { + return -EINVAL; } - 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) { -#ifdef AZT_DEBUG - printk("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",cmd); + case CDROMSUBCHNL: /* Get subchannel info */ + 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 - return -EIO; - } + return -EIO; + } subchnl.cdsc_audiostatus = aztAudioStatus; subchnl.cdsc_adr = qInfo.ctrl_addr; subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4; subchnl.cdsc_trk = azt_bcd2bin(qInfo.track); subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex); - if (subchnl.cdsc_format == CDROM_LBA) - { subchnl.cdsc_absaddr.lba = azt_msf2hsg(&qInfo.diskTime); - subchnl.cdsc_reladdr.lba = azt_msf2hsg(&qInfo.trackTime); - } - else /*default*/ - { subchnl.cdsc_format = CDROM_MSF; - subchnl.cdsc_absaddr.msf.minute = azt_bcd2bin(qInfo.diskTime.min); - subchnl.cdsc_absaddr.msf.second = azt_bcd2bin(qInfo.diskTime.sec); - subchnl.cdsc_absaddr.msf.frame = azt_bcd2bin(qInfo.diskTime.frame); - subchnl.cdsc_reladdr.msf.minute = azt_bcd2bin(qInfo.trackTime.min); - subchnl.cdsc_reladdr.msf.second = azt_bcd2bin(qInfo.trackTime.sec); - subchnl.cdsc_reladdr.msf.frame = azt_bcd2bin(qInfo.trackTime.frame); + if (subchnl.cdsc_format == CDROM_LBA) { + subchnl.cdsc_absaddr.lba = + azt_msf2hsg(&qInfo.diskTime); + subchnl.cdsc_reladdr.lba = + azt_msf2hsg(&qInfo.trackTime); + } else { /*default */ + subchnl.cdsc_format = CDROM_MSF; + subchnl.cdsc_absaddr.msf.minute = + azt_bcd2bin(qInfo.diskTime.min); + subchnl.cdsc_absaddr.msf.second = + azt_bcd2bin(qInfo.diskTime.sec); + subchnl.cdsc_absaddr.msf.frame = + azt_bcd2bin(qInfo.diskTime.frame); + subchnl.cdsc_reladdr.msf.minute = + azt_bcd2bin(qInfo.trackTime.min); + 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)); + 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 */ + 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; - azt_Play.end.min = volctrl.channel1; - azt_Play.end.sec = volctrl.channel2; - azt_Play.end.frame = volctrl.channel3; - sendAztCmd(ACMD_SET_VOLUME, &azt_Play); - STEN_LOW_WAIT; - break; + azt_Play.end.min = volctrl.channel1; + azt_Play.end.sec = volctrl.channel2; + azt_Play.end.frame = volctrl.channel3; + sendAztCmd(ACMD_SET_VOLUME, &azt_Play); + STEN_LOW_WAIT; + break; case CDROMEJECT: - aztUnlockDoor(); /* Assume user knows what they're doing */ - /* all drives can at least stop! */ - if (aztAudioStatus == CDROM_AUDIO_PLAY) - { if (aztSendCmd(ACMD_STOP)) RETURNM("azt_ioctl 10",-1); - STEN_LOW_WAIT; + aztUnlockDoor(); /* Assume user knows what they're doing */ + /* all drives can at least stop! */ + if (aztAudioStatus == CDROM_AUDIO_PLAY) { + if (aztSendCmd(ACMD_STOP)) + RETURNM("azt_ioctl 10", -1); + STEN_LOW_WAIT; } - if (aztSendCmd(ACMD_EJECT)) RETURNM("azt_ioctl 11",-1); + if (aztSendCmd(ACMD_EJECT)) + RETURNM("azt_ioctl 11", -1); STEN_LOW_WAIT; aztAudioStatus = CDROM_AUDIO_NO_STATUS; break; case CDROMEJECT_SW: azt_auto_eject = (char) arg; - break; - case CDROMRESET: - outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/ - STEN_LOW; - if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/ - { printk("aztcd: AZTECH CD-ROM drive does not respond\n"); - } - break; + break; + case CDROMRESET: + outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */ + STEN_LOW; + if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */ + printk + ("aztcd: AZTECH CD-ROM drive does not respond\n"); + } + break; /*Take care, the following code is not compatible with other CD-ROM drivers, use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h, if you do not want to use it! -*/ -#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); - /* convert to bcd */ - azt_bin2bcd(&msf.cdmsf_min0); - azt_bin2bcd(&msf.cdmsf_sec0); - azt_bin2bcd(&msf.cdmsf_frame0); - msf.cdmsf_min1=0; - msf.cdmsf_sec1=0; - msf.cdmsf_frame1=1; /*read only one frame*/ - azt_Play.start.min = msf.cdmsf_min0; - azt_Play.start.sec = msf.cdmsf_sec0; - azt_Play.start.frame = msf.cdmsf_frame0; - azt_Play.end.min = msf.cdmsf_min1; - azt_Play.end.sec = msf.cdmsf_sec1; - azt_Play.end.frame = msf.cdmsf_frame1; - if (cmd==CDROMREADRAW) - { if (DiskInfo.xa) - { return -1; /*XA Disks can't be read raw*/ - } - else - { 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); - } - } - 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); - } - } - 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 AZT_PRIVATE_IOCTLS + case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes) */ + case CDROMREADRAW: /*read data in mode 2 (2336 Bytes) */ + { + if (copy_from_user(&msf, (void *) arg, sizeof msf)) + return -EFAULT; + /* convert to bcd */ + azt_bin2bcd(&msf.cdmsf_min0); + azt_bin2bcd(&msf.cdmsf_sec0); + azt_bin2bcd(&msf.cdmsf_frame0); + msf.cdmsf_min1 = 0; + msf.cdmsf_sec1 = 0; + msf.cdmsf_frame1 = 1; /*read only one frame */ + azt_Play.start.min = msf.cdmsf_min0; + azt_Play.start.sec = msf.cdmsf_sec0; + azt_Play.start.frame = msf.cdmsf_frame0; + azt_Play.end.min = msf.cdmsf_min1; + azt_Play.end.sec = msf.cdmsf_sec1; + azt_Play.end.frame = msf.cdmsf_frame1; + if (cmd == CDROMREADRAW) { + if (DiskInfo.xa) { + return -1; /*XA Disks can't be read raw */ + } else { + if (sendAztCmd + (ACMD_PLAY_READ_RAW, + &azt_Play)) + return -1; + DTEN_LOW; + insb(DATA_PORT, 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); + if (copy_to_user + ((void *) arg, &buf, CD_FRAMESIZE)) + return -EFAULT; + } + } + break; + case CDROMSEEK: /*seek msf address */ + if (copy_from_user(&msf, (void *) arg, sizeof msf)) + return -EFAULT; /* convert to bcd */ azt_bin2bcd(&msf.cdmsf_min0); azt_bin2bcd(&msf.cdmsf_sec0); @@ -1423,18 +1526,20 @@ azt_Play.start.min = msf.cdmsf_min0; azt_Play.start.sec = msf.cdmsf_sec0; azt_Play.start.frame = msf.cdmsf_frame0; - if (aztSeek(&azt_Play)) return -1; - break; -#endif /*end of incompatible code*/ - case CDROMREADMODE1: /*set read data in mode 1*/ - return aztSetDiskType(AZT_MODE_1); - case CDROMREADMODE2: /*set read data in mode 2*/ - return aztSetDiskType(AZT_MODE_2); + if (aztSeek(&azt_Play)) + return -1; + break; +#endif /*end of incompatible code */ + case CDROMREADMODE1: /*set read data in mode 1 */ + return aztSetDiskType(AZT_MODE_1); + case CDROMREADMODE2: /*set read data in mode 2 */ + return aztSetDiskType(AZT_MODE_2); default: return -EINVAL; } #ifdef AZT_DEBUG - printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n",cmd,jiffies); + printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n", cmd, + jiffies); #endif return 0; } @@ -1444,131 +1549,139 @@ * When Linux gets variable block sizes this will probably go away. */ static void azt_transfer(void) -{ +{ #ifdef AZT_TEST - printk("aztcd: executing azt_transfer Time:%li\n",jiffies); + printk("aztcd: executing azt_transfer Time:%li\n", jiffies); #endif - if (CURRENT_VALID) { - while (CURRENT -> nr_sectors) { - int bn = CURRENT -> sector / 4; - int i; - for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i) - ; - if (i < AZT_BUF_SIZ) { - int offs = (i * 4 + (CURRENT -> sector & 3)) * 512; - int nr_sectors = 4 - (CURRENT -> sector & 3); - if (azt_buf_out != i) { - azt_buf_out = i; - if (azt_buf_bn[i] != bn) { - azt_buf_out = -1; - continue; - } - } - if (nr_sectors > CURRENT -> nr_sectors) - nr_sectors = CURRENT -> nr_sectors; - memcpy(CURRENT -> buffer, azt_buf + offs, nr_sectors * 512); - CURRENT -> nr_sectors -= nr_sectors; - CURRENT -> sector += nr_sectors; - CURRENT -> buffer += nr_sectors * 512; - } else { - azt_buf_out = -1; - break; - } - } - } + if (CURRENT_VALID) { + while (CURRENT->nr_sectors) { + int bn = CURRENT->sector / 4; + int i; + for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; + ++i); + if (i < AZT_BUF_SIZ) { + int offs = + (i * 4 + (CURRENT->sector & 3)) * 512; + int nr_sectors = 4 - (CURRENT->sector & 3); + if (azt_buf_out != i) { + azt_buf_out = i; + if (azt_buf_bn[i] != bn) { + azt_buf_out = -1; + continue; + } + } + if (nr_sectors > CURRENT->nr_sectors) + nr_sectors = CURRENT->nr_sectors; + memcpy(CURRENT->buffer, azt_buf + offs, + nr_sectors * 512); + CURRENT->nr_sectors -= nr_sectors; + CURRENT->sector += nr_sectors; + CURRENT->buffer += nr_sectors * 512; + } else { + azt_buf_out = -1; + break; + } + } + } } static void do_aztcd_request(request_queue_t * q) { #ifdef AZT_TEST - printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT -> sector, CURRENT -> nr_sectors,jiffies); + printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector, + CURRENT->nr_sectors, jiffies); #endif - if (DiskInfo.audio) - { printk("aztcd: Error, tried to mount an Audio CD\n"); - end_request(0); - return; - } - azt_transfer_is_active = 1; - while (CURRENT_VALID) { - if (CURRENT->bh) { - if (!buffer_locked(CURRENT->bh)) - panic(DEVICE_NAME ": block not locked"); - } - azt_transfer(); - if (CURRENT -> nr_sectors == 0) { - end_request(1); - } else { - azt_buf_out = -1; /* Want to read a block not in buffer */ - if (azt_state == AZT_S_IDLE) { - if ((!aztTocUpToDate)||aztDiskChanged) { - if (aztUpdateToc() < 0) { - while (CURRENT_VALID) - end_request(0); - break; - } - } - azt_state = AZT_S_START; - AztTries = 5; - SET_TIMER(azt_poll, HZ/100); - } - break; - } - } - azt_transfer_is_active = 0; + if (DiskInfo.audio) { + printk("aztcd: Error, tried to mount an Audio CD\n"); + end_request(0); + return; + } + azt_transfer_is_active = 1; + while (CURRENT_VALID) { + if (CURRENT->bh) { + if (!buffer_locked(CURRENT->bh)) + panic(DEVICE_NAME ": block not locked"); + } + azt_transfer(); + if (CURRENT->nr_sectors == 0) { + end_request(1); + } else { + azt_buf_out = -1; /* Want to read a block not in buffer */ + if (azt_state == AZT_S_IDLE) { + if ((!aztTocUpToDate) || aztDiskChanged) { + if (aztUpdateToc() < 0) { + while (CURRENT_VALID) + end_request(0); + break; + } + } + azt_state = AZT_S_START; + AztTries = 5; + SET_TIMER(azt_poll, HZ / 100); + } + break; + } + } + azt_transfer_is_active = 0; #ifdef AZT_TEST2 - printk("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", \ - azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]); - printk(" do_aztcd_request ends Time:%li\n",jiffies); + printk + ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", + azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]); + printk(" do_aztcd_request ends Time:%li\n", jiffies); #endif } static void azt_invalidate_buffers(void) -{ int i; +{ + int i; #ifdef AZT_DEBUG - printk("aztcd: executing azt_invalidate_buffers\n"); + printk("aztcd: executing azt_invalidate_buffers\n"); #endif - for (i = 0; i < AZT_BUF_SIZ; ++i) - azt_buf_bn[i] = -1; - azt_buf_out = -1; + for (i = 0; i < AZT_BUF_SIZ; ++i) + azt_buf_bn[i] = -1; + azt_buf_out = -1; } /* * Open the device special file. Check that a disk is in. */ int aztcd_open(struct inode *ip, struct file *fp) -{ int st; +{ + int st; #ifdef AZT_DEBUG printk("aztcd: starting aztcd_open\n"); #endif if (aztPresent == 0) - return -ENXIO; /* no hardware */ + return -ENXIO; /* no hardware */ - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; + + if (!azt_open_count && azt_state == AZT_S_IDLE) { + azt_invalidate_buffers(); - if (!azt_open_count && azt_state == AZT_S_IDLE) - { azt_invalidate_buffers(); + st = getAztStatus(); /* check drive status */ + if (st == -1) + goto err_out; /* drive doesn't respond */ + + if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */ + printk("aztcd: Door Open?\n"); + aztCloseDoor(); + st = getAztStatus(); + } + + if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) { /*no disk in drive or changed */ + printk + ("aztcd: Disk Changed or No Disk in Drive?\n"); + aztTocUpToDate = 0; + } + if (aztUpdateToc()) + goto err_out; - st = getAztStatus(); /* check drive status */ - if (st == -1) goto err_out; /* drive doesn't respond */ - - if (st & AST_DOOR_OPEN) - { /* close door, then get the status again. */ - printk("aztcd: Door Open?\n"); - aztCloseDoor(); - st = getAztStatus(); - } - - if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) /*no disk in drive or changed*/ - { printk("aztcd: Disk Changed or No Disk in Drive?\n"); - aztTocUpToDate=0; - } - if (aztUpdateToc()) goto err_out; - - } + } ++azt_open_count; aztLockDoor(); @@ -1577,7 +1690,7 @@ #endif return 0; -err_out: + err_out: MOD_DEC_USE_COUNT; return -EIO; } @@ -1586,29 +1699,22 @@ /* * 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 -{ +static int aztcd_release(struct inode *inode, struct file *file) +{ #ifdef AZT_DEBUG - printk("aztcd: executing aztcd_release\n"); - printk("inode: %p, inode->i_rdev: %x file: %p\n",inode,inode->i_rdev,file); -#endif - MOD_DEC_USE_COUNT; - if (!--azt_open_count) { - azt_invalidate_buffers(); - aztUnlockDoor(); - if (azt_auto_eject) - aztSendCmd(ACMD_EJECT); - CLEAR_TIMER; - } -#ifdef AZT_KERNEL_PRIOR_2_1 - return; -#else - return 0; + printk("aztcd: executing aztcd_release\n"); + printk("inode: %p, inode->i_rdev: %x file: %p\n", inode, + inode->i_rdev, file); #endif + MOD_DEC_USE_COUNT; + if (!--azt_open_count) { + azt_invalidate_buffers(); + aztUnlockDoor(); + if (azt_auto_eject) + aztSendCmd(ACMD_EJECT); + CLEAR_TIMER; + } + return 0; } @@ -1618,222 +1724,244 @@ */ int __init aztcd_init(void) -{ long int count, max_count; +{ + long int count, max_count; unsigned char result[50]; int st; int i = 0; - if (azt_port == 0) - { printk("aztcd: no Aztech CD-ROM Initialization"); - return -EIO; + if (azt_port == 0) { + printk("aztcd: no Aztech CD-ROM Initialization"); + return -EIO; } - printk("aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM CD-ROM Driver\n"); + printk + ("aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM CD-ROM Driver\n"); printk("aztcd: (C) 1994-98 W.Zimmermann\n"); - if (azt_port == -1) - { printk("aztcd: KernelVersion=%s DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",UTS_RELEASE,AZT_VERSION); + if (azt_port == -1) { + printk + ("aztcd: KernelVersion=%s DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n", + UTS_RELEASE, AZT_VERSION); + } else + printk + ("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n", + AZT_VERSION, azt_port); + printk + ("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n"); + + +#ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */ + if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) { + printk + ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n", + AZT_SW32_BASE_ADDR, AZT_SW32_INIT, + AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG); + return -EIO; + } else { + printk(KERN_INFO + "aztcd: Soundwave32 card detected at %x Version %x\n", + AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG)); + outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG); + for (count = 0; count < 10000; count++); /*delay a bit */ } - else - printk("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",AZT_VERSION,azt_port); - printk("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n"); - - -#ifdef AZT_SW32 /*CDROM connected to Soundwave32 card*/ - if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) - { printk("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n", - AZT_SW32_BASE_ADDR,AZT_SW32_INIT,AZT_SW32_CONFIG_REG,AZT_SW32_ID_REG); - return -EIO; - } - else - { printk(KERN_INFO "aztcd: Soundwave32 card detected at %x Version %x\n", - AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG)); - outw(AZT_SW32_INIT,AZT_SW32_CONFIG_REG); - for (count=0;count<10000;count++); /*delay a bit*/ - } -#endif +#endif /* check for presence of drive */ - if (azt_port == -1) /* autoprobing */ - { for (i=0;(azt_port_auto[i]!=0)&&(i<16);i++) - { azt_port = azt_port_auto[i]; - printk("aztcd: Autoprobing BaseAddress=0x%x \n",azt_port); - st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/ - if (st) continue; - - outb(POLLED,MODE_PORT); - inb(CMD_PORT); - inb(CMD_PORT); - outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/ - - aztTimeOutCount=0; - do { aztIndatum=inb(STATUS_PORT); - aztTimeOutCount++; - if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break; - } while (aztIndatum&AFL_STATUS); - if (inb(DATA_PORT)==AFL_OP_OK) - break; - } - if ((azt_port_auto[i]==0)||(i==16)) - { printk("aztcd: no AZTECH CD-ROM drive found\n"); - return -EIO; - } - } - else /* no autoprobing */ - { if ((azt_port==0x1f0)||(azt_port==0x170)) - st = check_region(azt_port, 8); /*IDE-interfaces need 8 bytes*/ - else - st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/ - if (st) - { printk("aztcd: conflict, I/O port (%X) already used\n",azt_port); - return -EIO; - } - - if ((azt_port==0x1f0)||(azt_port==0x170)) - SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration*/ - - outb(POLLED,MODE_PORT); - inb(CMD_PORT); - inb(CMD_PORT); - outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/ - - aztTimeOutCount=0; - do { aztIndatum=inb(STATUS_PORT); - aztTimeOutCount++; - if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break; - } while (aztIndatum&AFL_STATUS); + if (azt_port == -1) { /* autoprobing */ + for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) { + azt_port = azt_port_auto[i]; + printk("aztcd: Autoprobing BaseAddress=0x%x \n", + azt_port); + st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes */ + if (st) + continue; + + outb(POLLED, MODE_PORT); + inb(CMD_PORT); + inb(CMD_PORT); + outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */ + + aztTimeOutCount = 0; + do { + aztIndatum = inb(STATUS_PORT); + aztTimeOutCount++; + if (aztTimeOutCount >= AZT_FAST_TIMEOUT) + break; + } while (aztIndatum & AFL_STATUS); + if (inb(DATA_PORT) == AFL_OP_OK) + break; + } + if ((azt_port_auto[i] == 0) || (i == 16)) { + printk("aztcd: no AZTECH CD-ROM drive found\n"); + return -EIO; + } + } else { /* no autoprobing */ + if ((azt_port == 0x1f0) || (azt_port == 0x170)) + st = check_region(azt_port, 8); /*IDE-interfaces need 8 bytes */ + else + st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes */ + if (st) { + printk + ("aztcd: conflict, I/O port (%X) already used\n", + azt_port); + return -EIO; + } - if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK? If not, reset and try again*/ - { + if ((azt_port == 0x1f0) || (azt_port == 0x170)) + SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */ + + outb(POLLED, MODE_PORT); + inb(CMD_PORT); + inb(CMD_PORT); + outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */ + + aztTimeOutCount = 0; + do { + aztIndatum = inb(STATUS_PORT); + aztTimeOutCount++; + if (aztTimeOutCount >= AZT_FAST_TIMEOUT) + break; + } while (aztIndatum & AFL_STATUS); + + if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */ #ifndef MODULE - if (azt_cont!=0x79) - { printk("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=,0x79\n"); - return -EIO; - } -#else - if (0) - { - } -#endif - else - { printk("aztcd: drive reset - please wait\n"); - for (count=0;count<50;count++) - { inb(STATUS_PORT); /*removing all data from earlier tries*/ - inb(DATA_PORT); - } - outb(POLLED,MODE_PORT); - inb(CMD_PORT); - inb(CMD_PORT); - getAztStatus(); /*trap errors*/ - outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/ - STEN_LOW; - if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/ - { printk("aztcd: no AZTECH CD-ROM drive found\n"); - return -EIO; - } - - for (count = 0; count < AZT_TIMEOUT; count++) - barrier(); /* Stop gcc 2.96 being smart */ - - if ((st=getAztStatus())==-1) - { printk("aztcd: Drive Status Error Status=%x\n",st); - return -EIO; - } -#ifdef AZT_DEBUG - printk("aztcd: Status = %x\n",st); -#endif - outb(POLLED,MODE_PORT); - inb(CMD_PORT); - inb(CMD_PORT); - outb(ACMD_GET_VERSION,CMD_PORT); /*GetVersion*/ - STEN_LOW; - OP_OK; - } - } + if (azt_cont != 0x79) { + printk + ("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=,0x79\n"); + return -EIO; + } +#else + if (0) { + } +#endif + else { + printk + ("aztcd: drive reset - please wait\n"); + for (count = 0; count < 50; count++) { + inb(STATUS_PORT); /*removing all data from earlier tries */ + inb(DATA_PORT); + } + outb(POLLED, MODE_PORT); + inb(CMD_PORT); + inb(CMD_PORT); + getAztStatus(); /*trap errors */ + outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */ + STEN_LOW; + if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */ + printk + ("aztcd: no AZTECH CD-ROM drive found\n"); + return -EIO; + } + + for (count = 0; count < AZT_TIMEOUT; + count++) + barrier(); /* Stop gcc 2.96 being smart */ + + if ((st = getAztStatus()) == -1) { + printk + ("aztcd: Drive Status Error Status=%x\n", + st); + return -EIO; + } +#ifdef AZT_DEBUG + printk("aztcd: Status = %x\n", st); +#endif + outb(POLLED, MODE_PORT); + inb(CMD_PORT); + inb(CMD_PORT); + outb(ACMD_GET_VERSION, CMD_PORT); /*GetVersion */ + STEN_LOW; + OP_OK; + } + } } - - azt_init_end=1; + + azt_init_end = 1; STEN_LOW; - result[0]=inb(DATA_PORT); /*reading in a null byte???*/ - for (count=1;count<50;count++) /*Reading version string*/ - { aztTimeOutCount=0; /*here we must implement STEN_LOW differently*/ - do { aztIndatum=inb(STATUS_PORT);/*because we want to exit by timeout*/ - aztTimeOutCount++; - if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break; - } while (aztIndatum&AFL_STATUS); - if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break; /*all chars read?*/ - result[count]=inb(DATA_PORT); - } - if (count>30) max_count=30; /*print max.30 chars of the version string*/ - else max_count=count; + result[0] = inb(DATA_PORT); /*reading in a null byte??? */ + for (count = 1; count < 50; count++) { /*Reading version string */ + aztTimeOutCount = 0; /*here we must implement STEN_LOW differently */ + do { + aztIndatum = inb(STATUS_PORT); /*because we want to exit by timeout */ + aztTimeOutCount++; + if (aztTimeOutCount >= AZT_FAST_TIMEOUT) + break; + } while (aztIndatum & AFL_STATUS); + if (aztTimeOutCount >= AZT_FAST_TIMEOUT) + break; /*all chars read? */ + result[count] = inb(DATA_PORT); + } + if (count > 30) + max_count = 30; /*print max.30 chars of the version string */ + else + max_count = count; printk(KERN_INFO "aztcd: FirmwareVersion="); - for (count=1;count> "); - if ((result[1]=='A')&&(result[2]=='Z')&&(result[3]=='T')) - { printk("AZTECH drive detected\n"); /*AZTECH*/ - } - else if ((result[2]=='C')&&(result[3]=='D')&&(result[4]=='D')) - { printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES*/ - } - else if ((result[1]==0x03)&&(result[2]=='5')) - { printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM*/ - } - else /*OTHERS or none*/ - { printk("\nunknown drive or firmware version detected\n"); - printk("aztcd may not run stable, if you want to try anyhow,\n"); - printk("boot with: aztcd=,0x79\n"); - if ((azt_cont!=0x79)) - { printk("aztcd: FirmwareVersion="); - for (count=1;count<5;count++) printk("%c",result[count]); - printk("<<>> "); - printk("Aborted\n"); - return -EIO; - } - } - devfs_register (NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, - S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL); - if (devfs_register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) - { + if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) { + printk("AZTECH drive detected\n"); + /*AZTECH*/} + else if ((result[2] == 'C') && (result[3] == 'D') + && (result[4] == 'D')) { + printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES */ + } else if ((result[1] == 0x03) && (result[2] == '5')) { + printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM */ + } else { /*OTHERS or none */ + printk("\nunknown drive or firmware version detected\n"); + printk + ("aztcd may not run stable, if you want to try anyhow,\n"); + printk("boot with: aztcd=,0x79\n"); + if ((azt_cont != 0x79)) { + printk("aztcd: FirmwareVersion="); + for (count = 1; count < 5; count++) + printk("%c", result[count]); + printk("<<>> "); + printk("Aborted\n"); + return -EIO; + } + } + devfs_register(NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, + S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL); + if (devfs_register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { printk("aztcd: Unable to get major %d for Aztech CD-ROM\n", MAJOR_NR); - return -EIO; + 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); + register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &azt_fops, 0); + + if ((azt_port == 0x1f0) || (azt_port == 0x170)) + request_region(azt_port, 8, "aztcd"); /*IDE-interface */ + else + request_region(azt_port, 4, "aztcd"); /*proprietary interface */ - if ((azt_port==0x1f0)||(azt_port==0x170)) - request_region(azt_port, 8, "aztcd"); /*IDE-interface*/ - else - request_region(azt_port, 4, "aztcd"); /*proprietary interface*/ - azt_invalidate_buffers(); aztPresent = 1; aztCloseDoor(); - return (0); + return (0); } void __exit aztcd_exit(void) { - devfs_unregister(devfs_find_handle(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, - 0)); - if ((devfs_unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) - { printk("What's that: can't unregister aztcd\n"); - return; - } - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - if ((azt_port==0x1f0)||(azt_port==0x170)) - { SWITCH_IDE_MASTER; - release_region(azt_port,8); /*IDE-interface*/ - } - else - release_region(azt_port,4); /*proprietary interface*/ - printk(KERN_INFO "aztcd module released.\n"); -} + devfs_unregister(devfs_find_handle + (NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0)); + if ((devfs_unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { + printk("What's that: can't unregister aztcd\n"); + return; + } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + if ((azt_port == 0x1f0) || (azt_port == 0x170)) { + SWITCH_IDE_MASTER; + release_region(azt_port, 8); /*IDE-interface */ + } else + release_region(azt_port, 4); /*proprietary interface */ + printk(KERN_INFO "aztcd module released.\n"); +} #ifdef MODULE module_init(aztcd_init); @@ -1846,405 +1974,485 @@ */ static void azt_poll(void) { - int st = 0; - int loop_ctl = 1; - int skip = 0; - - if (azt_error) { - if (aztSendCmd(ACMD_GET_ERROR)) RETURN("azt_poll 1"); - STEN_LOW; - azt_error=inb(DATA_PORT)&0xFF; - printk("aztcd: I/O error 0x%02x\n", azt_error); - azt_invalidate_buffers(); + int st = 0; + int loop_ctl = 1; + int skip = 0; + + if (azt_error) { + if (aztSendCmd(ACMD_GET_ERROR)) + RETURN("azt_poll 1"); + STEN_LOW; + azt_error = inb(DATA_PORT) & 0xFF; + printk("aztcd: I/O error 0x%02x\n", azt_error); + azt_invalidate_buffers(); #ifdef WARN_IF_READ_FAILURE - if (AztTries == 5) - printk("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n", azt_next_bn); -#endif - if (!AztTries--) { - printk("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n", azt_next_bn); - if (azt_transfer_is_active) { - AztTries = 0; - loop_ctl = 0; - } - if (CURRENT_VALID) - end_request(0); - AztTries = 5; - } - azt_error = 0; - azt_state = AZT_S_STOP; - } - - while (loop_ctl) - { - loop_ctl = 0; /* each case must flip this back to 1 if we want - to come back up here */ - switch (azt_state) { + if (AztTries == 5) + printk + ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n", + azt_next_bn); +#endif + if (!AztTries--) { + printk + ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n", + azt_next_bn); + if (azt_transfer_is_active) { + AztTries = 0; + loop_ctl = 0; + } + if (CURRENT_VALID) + end_request(0); + AztTries = 5; + } + azt_error = 0; + azt_state = AZT_S_STOP; + } + + while (loop_ctl) { + loop_ctl = 0; /* each case must flip this back to 1 if we want + to come back up here */ + switch (azt_state) { - case AZT_S_IDLE: + case AZT_S_IDLE: #ifdef AZT_TEST3 - if (azt_state!=azt_state_old) { - azt_state_old=azt_state; - printk("AZT_S_IDLE\n"); - } + if (azt_state != azt_state_old) { + azt_state_old = azt_state; + printk("AZT_S_IDLE\n"); + } #endif - return; + return; - case AZT_S_START: + case AZT_S_START: #ifdef AZT_TEST3 - if (azt_state!=azt_state_old) { - azt_state_old=azt_state; - printk("AZT_S_START\n"); - } -#endif - if(aztSendCmd(ACMD_GET_STATUS)) RETURN("azt_poll 2"); /*result will be checked by aztStatus() */ - azt_state = azt_mode == 1 ? AZT_S_READ : AZT_S_MODE; - AztTimeout = 3000; - break; + if (azt_state != azt_state_old) { + azt_state_old = azt_state; + printk("AZT_S_START\n"); + } +#endif + if (aztSendCmd(ACMD_GET_STATUS)) + RETURN("azt_poll 2"); /*result will be checked by aztStatus() */ + azt_state = + azt_mode == 1 ? AZT_S_READ : AZT_S_MODE; + AztTimeout = 3000; + break; - case AZT_S_MODE: + case AZT_S_MODE: #ifdef AZT_TEST3 - if (azt_state!=azt_state_old) { - azt_state_old=azt_state; - printk("AZT_S_MODE\n"); - } -#endif - if (!skip) { - if ((st = aztStatus()) != -1) { - if ((st & AST_DSK_CHG)||(st & AST_NOT_READY)) { - aztDiskChanged = 1; - aztTocUpToDate = 0; - azt_invalidate_buffers(); - end_request(0); - printk("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n"); - } - } else break; - } - skip = 0; - - if ((st & AST_DOOR_OPEN)||(st & AST_NOT_READY)) { - aztDiskChanged = 1; - aztTocUpToDate = 0; - printk("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n"); - end_request(0); - printk((st & AST_DOOR_OPEN) ? "aztcd: door open\n" : "aztcd: disk removed\n"); - if (azt_transfer_is_active) { - azt_state = AZT_S_START; - loop_ctl = 1; /* goto immediately */ - break; - } - azt_state = AZT_S_IDLE; - while (CURRENT_VALID) - end_request(0); - return; - } - + if (azt_state != azt_state_old) { + azt_state_old = azt_state; + printk("AZT_S_MODE\n"); + } +#endif + if (!skip) { + if ((st = aztStatus()) != -1) { + if ((st & AST_DSK_CHG) + || (st & AST_NOT_READY)) { + aztDiskChanged = 1; + aztTocUpToDate = 0; + azt_invalidate_buffers(); + end_request(0); + printk + ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n"); + } + } else + break; + } + skip = 0; + + if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) { + aztDiskChanged = 1; + aztTocUpToDate = 0; + printk + ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n"); + end_request(0); + printk((st & AST_DOOR_OPEN) ? + "aztcd: door open\n" : + "aztcd: disk removed\n"); + if (azt_transfer_is_active) { + azt_state = AZT_S_START; + loop_ctl = 1; /* goto immediately */ + break; + } + azt_state = AZT_S_IDLE; + while (CURRENT_VALID) + end_request(0); + return; + } + /* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3"); outb(0x01, DATA_PORT); PA_OK; STEN_LOW; -*/ if (aztSendCmd(ACMD_GET_STATUS)) RETURN("azt_poll 4"); - STEN_LOW; - azt_mode = 1; - azt_state = AZT_S_READ; - AztTimeout = 3000; +*/ + if (aztSendCmd(ACMD_GET_STATUS)) + RETURN("azt_poll 4"); + STEN_LOW; + azt_mode = 1; + azt_state = AZT_S_READ; + AztTimeout = 3000; - break; + break; - case AZT_S_READ: + case AZT_S_READ: #ifdef AZT_TEST3 - if (azt_state!=azt_state_old) { - azt_state_old=azt_state; - printk("AZT_S_READ\n"); - } -#endif - if (!skip) { - if ((st = aztStatus()) != -1) { - if ((st & AST_DSK_CHG)||(st & AST_NOT_READY)) { - aztDiskChanged = 1; - aztTocUpToDate = 0; - azt_invalidate_buffers(); - printk("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n"); - end_request(0); - } - } else break; - } - - skip = 0; - if ((st & AST_DOOR_OPEN)||(st & AST_NOT_READY)) { - aztDiskChanged = 1; - aztTocUpToDate = 0; - printk((st & AST_DOOR_OPEN) ? "aztcd: door open\n" : "aztcd: disk removed\n"); - if (azt_transfer_is_active) { - azt_state = AZT_S_START; - loop_ctl = 1; - break; - } - azt_state = AZT_S_IDLE; - while (CURRENT_VALID) - end_request(0); - return; - } - - if (CURRENT_VALID) { - struct azt_Play_msf msf; - int i; - azt_next_bn = CURRENT -> sector / 4; - azt_hsg2msf(azt_next_bn, &msf.start); - i = 0; - /* find out in which track we are */ - while (azt_msf2hsg(&msf.start)>azt_msf2hsg(&Toc[++i].trackTime)) {}; - if (azt_msf2hsg(&msf.start)nr_sectors; slow, no read ahead*/ - } - else /* don't read beyond end of track */ -#if AZT_MULTISESSION - { azt_read_count=(azt_msf2hsg(&Toc[i].trackTime)/4)*4-azt_msf2hsg(&msf.start); - if (azt_read_count < 0) azt_read_count=0; - if (azt_read_count > AZT_BUF_SIZ) azt_read_count=AZT_BUF_SIZ; - printk("aztcd: warning - trying to read beyond end of track\n"); + if (azt_state != azt_state_old) { + azt_state_old = azt_state; + printk("AZT_S_READ\n"); + } +#endif + if (!skip) { + if ((st = aztStatus()) != -1) { + if ((st & AST_DSK_CHG) + || (st & AST_NOT_READY)) { + aztDiskChanged = 1; + aztTocUpToDate = 0; + azt_invalidate_buffers(); + printk + ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n"); + end_request(0); + } + } else + break; + } + + skip = 0; + if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) { + aztDiskChanged = 1; + aztTocUpToDate = 0; + printk((st & AST_DOOR_OPEN) ? + "aztcd: door open\n" : + "aztcd: disk removed\n"); + if (azt_transfer_is_active) { + azt_state = AZT_S_START; + loop_ctl = 1; + break; + } + azt_state = AZT_S_IDLE; + while (CURRENT_VALID) + end_request(0); + return; + } + + if (CURRENT_VALID) { + struct azt_Play_msf msf; + int i; + azt_next_bn = CURRENT->sector / 4; + azt_hsg2msf(azt_next_bn, &msf.start); + i = 0; + /* find out in which track we are */ + while (azt_msf2hsg(&msf.start) > + azt_msf2hsg(&Toc[++i].trackTime)) { + }; + if (azt_msf2hsg(&msf.start) < + azt_msf2hsg(&Toc[i].trackTime) - + AZT_BUF_SIZ) { + azt_read_count = AZT_BUF_SIZ; /*fast, because we read ahead */ + /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead */ + } else /* don't read beyond end of track */ +#if AZT_MULTISESSION + { + azt_read_count = + (azt_msf2hsg(&Toc[i].trackTime) + / 4) * 4 - + azt_msf2hsg(&msf.start); + if (azt_read_count < 0) + azt_read_count = 0; + if (azt_read_count > AZT_BUF_SIZ) + azt_read_count = + AZT_BUF_SIZ; + printk + ("aztcd: warning - trying to read beyond end of track\n"); /* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime)); -*/ } +*/ } #else - { azt_read_count=AZT_BUF_SIZ; - } -#endif - msf.end.min = 0; - msf.end.sec = 0; - msf.end.frame = azt_read_count ;/*Mitsumi here reads 0xffffff sectors*/ + { + azt_read_count = AZT_BUF_SIZ; + } +#endif + msf.end.min = 0; + msf.end.sec = 0; + msf.end.frame = azt_read_count; /*Mitsumi here reads 0xffffff sectors */ #ifdef AZT_TEST3 - printk("---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("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", \ - azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]); -#endif - if (azt_read_mode==AZT_MODE_2) - { sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode*/ - } - else - { sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode*/ - } - azt_state = AZT_S_DATA; - AztTimeout = READ_TIMEOUT; - } else { - azt_state = AZT_S_STOP; - loop_ctl = 1; - break; - } + printk + ("---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 + ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", + azt_next_bn, azt_buf_in, azt_buf_out, + azt_buf_bn[azt_buf_in]); +#endif + if (azt_read_mode == AZT_MODE_2) { + sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode */ + } else { + sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode */ + } + azt_state = AZT_S_DATA; + AztTimeout = READ_TIMEOUT; + } else { + azt_state = AZT_S_STOP; + loop_ctl = 1; + break; + } - break; + break; - case AZT_S_DATA: + case AZT_S_DATA: #ifdef AZT_TEST3 - if (azt_state!=azt_state_old) { - azt_state_old=azt_state; - printk("AZT_S_DATA\n"); - } + if (azt_state != azt_state_old) { + azt_state_old = azt_state; + printk("AZT_S_DATA\n"); + } #endif - st = inb(STATUS_PORT) & AFL_STATUSorDATA; + st = inb(STATUS_PORT) & AFL_STATUSorDATA; - switch (st) { + switch (st) { - case AFL_DATA: + case AFL_DATA: #ifdef AZT_TEST3 - if (st!=azt_st_old) { - azt_st_old=st; - printk("---AFL_DATA st:%x\n",st); - } -#endif - if (!AztTries--) { - printk("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n", azt_next_bn); - if (azt_transfer_is_active) { - AztTries = 0; - break; - } - if (CURRENT_VALID) - end_request(0); - AztTries = 5; - } - azt_state = AZT_S_START; - AztTimeout = READ_TIMEOUT; - loop_ctl = 1; - break; + if (st != azt_st_old) { + azt_st_old = st; + printk("---AFL_DATA st:%x\n", st); + } +#endif + if (!AztTries--) { + printk + ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n", + azt_next_bn); + if (azt_transfer_is_active) { + AztTries = 0; + break; + } + if (CURRENT_VALID) + end_request(0); + AztTries = 5; + } + azt_state = AZT_S_START; + AztTimeout = READ_TIMEOUT; + loop_ctl = 1; + break; - case AFL_STATUSorDATA: + case AFL_STATUSorDATA: #ifdef AZT_TEST3 - if (st!=azt_st_old) { - azt_st_old=st; - printk("---AFL_STATUSorDATA st:%x\n",st); - } + if (st != azt_st_old) { + azt_st_old = st; + printk + ("---AFL_STATUSorDATA st:%x\n", + st); + } #endif - break; + break; - default: + default: #ifdef AZT_TEST3 - if (st!=azt_st_old) { - azt_st_old=st; - printk("---default: st:%x\n",st); - } -#endif - AztTries = 5; - if (!CURRENT_VALID && azt_buf_in == azt_buf_out) { - azt_state = AZT_S_STOP; - loop_ctl = 1; - break; - } - if (azt_read_count<=0) - printk("aztcd: warning - try to read 0 frames\n"); - while (azt_read_count) /*??? fast read ahead loop*/ - { azt_buf_bn[azt_buf_in] = -1; - DTEN_LOW; /*??? unsolved problem, very - seldom we get timeouts - here, don't now the real - reason. With my drive this - sometimes also happens with - Aztech's original driver under - DOS. Is it a hardware bug? - I tried to recover from such - situations here. Zimmermann*/ - if (aztTimeOutCount>=AZT_TIMEOUT) - { printk("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n", azt_read_count,CURRENT->nr_sectors,azt_buf_in); - printk("azt_transfer_is_active:%x\n",azt_transfer_is_active); - azt_read_count=0; - azt_state = AZT_S_STOP; - loop_ctl = 1; - end_request(1); /*should we have here (1) or (0)? */ - } - else - { if (azt_read_mode==AZT_MODE_2) - { insb(DATA_PORT, azt_buf + CD_FRAMESIZE_RAW * azt_buf_in, CD_FRAMESIZE_RAW); - } - else - { insb(DATA_PORT, azt_buf + CD_FRAMESIZE * azt_buf_in, CD_FRAMESIZE); - } - azt_read_count--; + if (st != azt_st_old) { + azt_st_old = st; + printk("---default: st:%x\n", st); + } +#endif + AztTries = 5; + if (!CURRENT_VALID + && azt_buf_in == azt_buf_out) { + azt_state = AZT_S_STOP; + loop_ctl = 1; + break; + } + if (azt_read_count <= 0) + printk + ("aztcd: warning - try to read 0 frames\n"); + while (azt_read_count) { /*??? fast read ahead loop */ + azt_buf_bn[azt_buf_in] = -1; + DTEN_LOW; /*??? unsolved problem, very + seldom we get timeouts + here, don't now the real + reason. With my drive this + sometimes also happens with + Aztech's original driver under + DOS. Is it a hardware bug? + I tried to recover from such + situations here. Zimmermann */ + if (aztTimeOutCount >= AZT_TIMEOUT) { + printk + ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n", + azt_read_count, + CURRENT->nr_sectors, + azt_buf_in); + printk + ("azt_transfer_is_active:%x\n", + azt_transfer_is_active); + azt_read_count = 0; + azt_state = AZT_S_STOP; + loop_ctl = 1; + end_request(1); /*should we have here (1) or (0)? */ + } else { + if (azt_read_mode == + AZT_MODE_2) { + insb(DATA_PORT, + azt_buf + + CD_FRAMESIZE_RAW + * azt_buf_in, + CD_FRAMESIZE_RAW); + } else { + insb(DATA_PORT, + azt_buf + + CD_FRAMESIZE * + azt_buf_in, + CD_FRAMESIZE); + } + azt_read_count--; #ifdef AZT_TEST3 - printk("AZT_S_DATA; ---I've read data- read_count: %d\n",azt_read_count); - printk("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n", \ - azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]); -#endif - azt_buf_bn[azt_buf_in] = azt_next_bn++; - if (azt_buf_out == -1) - azt_buf_out = azt_buf_in; - azt_buf_in = azt_buf_in + 1 == AZT_BUF_SIZ ? 0 : azt_buf_in + 1; - } - } - if (!azt_transfer_is_active) { - while (CURRENT_VALID) { - azt_transfer(); - if (CURRENT -> nr_sectors == 0) - end_request(1); - else - break; - } - } - - if (CURRENT_VALID - && (CURRENT -> sector / 4 < azt_next_bn || - CURRENT -> sector / 4 > azt_next_bn + AZT_BUF_SIZ)) { - azt_state = AZT_S_STOP; - loop_ctl = 1; - break; - } - AztTimeout = READ_TIMEOUT; - if (azt_read_count==0) { - azt_state = AZT_S_STOP; - loop_ctl = 1; - break; - } - break; - } - break; + printk + ("AZT_S_DATA; ---I've read data- read_count: %d\n", + azt_read_count); + printk + ("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n", + azt_next_bn, + azt_buf_in, + azt_buf_out, + azt_buf_bn + [azt_buf_in]); +#endif + azt_buf_bn[azt_buf_in] = + azt_next_bn++; + if (azt_buf_out == -1) + azt_buf_out = + azt_buf_in; + azt_buf_in = + azt_buf_in + 1 == + AZT_BUF_SIZ ? 0 : + azt_buf_in + 1; + } + } + if (!azt_transfer_is_active) { + while (CURRENT_VALID) { + azt_transfer(); + if (CURRENT->nr_sectors == + 0) + end_request(1); + else + break; + } + } + + if (CURRENT_VALID + && (CURRENT->sector / 4 < azt_next_bn + || CURRENT->sector / 4 > + azt_next_bn + AZT_BUF_SIZ)) { + azt_state = AZT_S_STOP; + loop_ctl = 1; + break; + } + AztTimeout = READ_TIMEOUT; + if (azt_read_count == 0) { + azt_state = AZT_S_STOP; + loop_ctl = 1; + break; + } + break; + } + break; - case AZT_S_STOP: + case AZT_S_STOP: #ifdef AZT_TEST3 - if (azt_state!=azt_state_old) { - azt_state_old=azt_state; - printk("AZT_S_STOP\n"); - } -#endif - if (azt_read_count!=0) printk("aztcd: discard data=%x frames\n",azt_read_count); - while (azt_read_count!=0) { - int i; - if ( !(inb(STATUS_PORT) & AFL_DATA) ) { - if (azt_read_mode==AZT_MODE_2) - for (i=0; i min = hsg / 4500; +{ + hsg += 150; + msf->min = hsg / 4500; hsg %= 4500; - msf -> sec = hsg / 75; - msf -> frame = hsg % 75; + msf->sec = hsg / 75; + msf->frame = hsg % 75; #ifdef AZT_DEBUG - if (msf->min >=70) printk("aztcd: Error hsg2msf address Minutes\n"); - if (msf->sec >=60) printk("aztcd: Error hsg2msf address Seconds\n"); - if (msf->frame>=75) printk("aztcd: Error hsg2msf address Frames\n"); -#endif - azt_bin2bcd(&msf -> min); /* convert to BCD */ - azt_bin2bcd(&msf -> sec); - azt_bin2bcd(&msf -> frame); + if (msf->min >= 70) + printk("aztcd: Error hsg2msf address Minutes\n"); + if (msf->sec >= 60) + printk("aztcd: Error hsg2msf address Seconds\n"); + if (msf->frame >= 75) + printk("aztcd: Error hsg2msf address Frames\n"); +#endif + azt_bin2bcd(&msf->min); /* convert to BCD */ + azt_bin2bcd(&msf->sec); + azt_bin2bcd(&msf->frame); } static long azt_msf2hsg(struct msf *mp) -{ return azt_bcd2bin(mp -> frame) + azt_bcd2bin(mp -> sec) * 75 - + azt_bcd2bin(mp -> min) * 4500 - CD_MSF_OFFSET; +{ + return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75 + + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET; } static void azt_bin2bcd(unsigned char *p) -{ int u, t; +{ + int u, t; u = *p % 10; t = *p / 10; @@ -2282,5 +2496,9 @@ } static int azt_bcd2bin(unsigned char bcd) -{ return (bcd >> 4) * 10 + (bcd & 0xF); +{ + 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 Sun Sep 9 10:43:02 2001 @@ -2,6 +2,7 @@ linux/kernel/blk_drv/mcd.c - Mitsumi CDROM driver Copyright (C) 1992 Martin Harriss + Portions Copyright (C) 2001 Red Hat martin@bdsi.com (no longer valid - where are you now, Martin?) @@ -74,7 +75,8 @@ module_init & module_exit. Torben Mathiasen - + September 2001 - Reformatted and cleaned up the code + Alan Cox */ #include @@ -102,14 +104,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; @@ -117,22 +119,8 @@ /* Is the drive connected properly and responding?? */ 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 */ -#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 */ -#endif -/* #define DOUBLE_QUICK_ONLY */ #define CURRENT_VALID \ (!QUEUE_EMPTY && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \ @@ -141,32 +129,30 @@ #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 */ -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 +181,58 @@ 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]; -#ifdef WORK_AROUND_MITSUMI_BUG_93 - if (ints[0] > 2) - mitsumi_bug_93_wait = ints[3]; -#endif /* WORK_AROUND_MITSUMI_BUG_93 */ + int ints[9]; + + (void) get_options(str, ARRAY_SIZE(ints), ints); - return 1; + if (ints[0] > 0) + mcd_port = ints[1]; + if (ints[0] > 1) + mcd_irq = ints[2]; + if (ints[0] > 2) + mitsumi_bug_93_wait = ints[3]; + + 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; - - -#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; - } - - retval = mcdDiskChanged; - mcdDiskChanged = 0; - - return retval; + return 0; } @@ -272,18 +241,17 @@ * 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++) { + /* send get-status cmd */ + outb(MCMD_GET_STATUS, MCDPORT(0)); st = getMcdStatus(MCD_STATUS_DELAY); - if (st != -1) - break; + if (st != -1) + break; } return st; @@ -294,13 +262,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 +277,39 @@ } -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 +325,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 +349,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 +368,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 +383,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 +400,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 +415,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 +442,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 +457,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 +495,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; @@ -551,14 +508,14 @@ 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_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_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 +547,37 @@ * 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 +586,423 @@ * 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); -#endif - if (!(st & MFL_STATUS)) - { + test1(printk("", st)); + if (!(st & MFL_STATUS)) { st = inb(MCDPORT(0)) & 0xFF; -#ifdef TEST1 - printk("", st); -#endif + test1(printk("", st)); 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); -#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_state = MCD_S_START; - McdTries = 5; - SET_TIMER(mcd_poll, 1); - } - break; - } - } - mcd_transfer_is_active = 0; -#ifdef TEST2 - printk(" do_mcd_request ends\n"); -#endif + test2(printk(" do_mcd_request(%ld+%ld)\n", CURRENT->sector, + CURRENT->nr_sectors)); + + 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; + mcd_timer.function = mcd_poll; + mod_timer(&mcd_timer, jiffies + 1); + } + break; + } + } + mcd_transfer_is_active = 0; + test2(printk(" do_mcd_request ends\n")); } -static void -mcd_poll(unsigned long dummy) +static void mcd_poll(unsigned long dummy) { - int st; + 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! */ + if (mcd_error) { + if (mcd_error & 0xA5) { + printk(KERN_ERR "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(KERN_ERR "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(KERN_ERR "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! */ - } - - - - immediately: - switch (mcd_state) { - + /* 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(KERN_INFO "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) { + case MCD_S_IDLE: + test3(printk("MCD_S_IDLE\n")); + goto out; + + case MCD_S_START: + test3(printk("MCD_S_START\n")); + outb(MCMD_GET_STATUS, MCDPORT(0)); + mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE; + McdTimeout = 3000; + break; + + case MCD_S_MODE: + test3(printk("MCD_S_MODE\n")); + if ((st = mcdStatus()) != -1) { + if (st & MST_DSK_CHG) { + mcdDiskChanged = 1; + tocUpToDate = 0; + mcd_invalidate_buffers(); + } - case MCD_S_IDLE: -#ifdef TEST3 - printk("MCD_S_IDLE\n"); -#endif - goto out; - - - - case MCD_S_START: -#ifdef TEST3 - 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; - - - - case MCD_S_MODE: -#ifdef TEST3 - printk("MCD_S_MODE\n"); -#endif - - if ((st = mcdStatus()) != -1) { - - if (st & MST_DSK_CHG) { - mcdDiskChanged = 1; - tocUpToDate = 0; - mcd_invalidate_buffers(); - } - - 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; - } - - outb(MCMD_SET_MODE, MCDPORT(0)); - outb(1, MCDPORT(0)); - mcd_mode = 1; - mcd_state = MCD_S_READ; - McdTimeout = 3000; - - } - break; - +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(KERN_INFO); + 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; + } + break; + case MCD_S_READ: + test3(printk("MCD_S_READ\n")); + if ((st = mcdStatus()) != -1) { + if (st & MST_DSK_CHG) { + mcdDiskChanged = 1; + tocUpToDate = 0; + mcd_invalidate_buffers(); + } - case MCD_S_READ: -#ifdef TEST3 - printk("MCD_S_READ\n"); -#endif +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(KERN_INFO); + 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 = mcdStatus()) != -1) { + 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_DSK_CHG) { - mcdDiskChanged = 1; - tocUpToDate = 0; - mcd_invalidate_buffers(); - } + } + break; - read_immediately: + case MCD_S_DATA: + test3(printk("MCD_S_DATA\n")); + st = inb(MCDPORT(1)) & (MFL_STATUSorDATA); +data_immediately: + test5(printk("Status %02x\n", st)) + switch (st) { + case MFL_DATA: +#ifdef WARN_IF_READ_FAILURE + if (McdTries == 5) + printk(KERN_WARNING "mcd: read of block %d failed\n", + mcd_next_bn); +#endif + if (!McdTries--) { + printk(KERN_ERR "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; - 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; - } - - } - break; - - - case MCD_S_DATA: -#ifdef TEST3 - printk("MCD_S_DATA\n"); -#endif + case MFL_STATUSorDATA: + break; - st = inb(MCDPORT(1)) & (MFL_STATUSorDATA); - data_immediately: -#ifdef TEST5 - printk("Status %02x\n",st); -#endif - switch (st) { + 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; + insb(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; + } + } - 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; -#ifdef DOUBLE_QUICK_ONLY - 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)) { -# ifdef TEST4 -/* printk("Quickloop success at %d\n",QUICK_LOOP_COUNT-count); */ - printk(" %d ",QUICK_LOOP_COUNT-count); -# endif - goto data_immediately; - } - } -# ifdef TEST4 -/* printk("Quickloop ended at %d\n",QUICK_LOOP_COUNT); */ - printk("ended "); -# endif - } - break; - } - 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; + { + int count = QUICK_LOOP_COUNT; + while (count--) { + QUICK_LOOP_DELAY; + if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) { + test4(printk(" %d ", QUICK_LOOP_COUNT - count)); + goto data_immediately; + } + } + test4(printk("ended ")); + } + break; + } + break; + case MCD_S_STOP: + test3(printk("MCD_S_STOP\n")); + 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; + case 9 + 3 + 1: + if (McdTimeout) + break; - case MCD_S_STOP: -#ifdef TEST3 - printk("MCD_S_STOP\n"); -#endif +do_not_work_around_mitsumi_bug_93_1: + outb(MCMD_STOP, MCDPORT(0)); + 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)); + } + } -#ifdef WORK_AROUND_MITSUMI_BUG_93 - 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; - - case 9+3+1: - if (McdTimeout) - break; - - do_not_work_around_mitsumi_bug_93_1: -#endif /* WORK_AROUND_MITSUMI_BUG_93 */ - - 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; - - case MCD_S_STOPPING: -#ifdef TEST3 - printk("MCD_S_STOPPING\n"); -#endif + mcd_state = MCD_S_STOPPING; + McdTimeout = 1000; + break; + + case MCD_S_STOPPING: + test3(printk("MCD_S_STOPPING\n")); + if ((st = mcdStatus()) == -1 && McdTimeout) + break; - if ((st = mcdStatus()) == -1 && McdTimeout) - break; + if ((st != -1) && (st & MST_DSK_CHG)) { + mcdDiskChanged = 1; + tocUpToDate = 0; + mcd_invalidate_buffers(); + } + if (!mitsumi_bug_93_wait) + goto do_not_work_around_mitsumi_bug_93_2; - 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; - - McdTimeout = mitsumi_bug_93_wait; - mcd_state = 9+3+2; - break; - - case 9+3+2: - if (McdTimeout) - break; - - st = -1; - - 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); -#endif + McdTimeout = mitsumi_bug_93_wait; + mcd_state = 9 + 3 + 2; + break; - 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; - } + case 9 + 3 + 2: + if (McdTimeout) + break; + st = -1; - SET_TIMER(mcd_poll, 1); +do_not_work_around_mitsumi_bug_93_2: + test3(printk("CURRENT_VALID %d mcd_mode %d\n", CURRENT_VALID, mcd_mode)); + 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(KERN_ERR "mcd: invalid state %d\n", mcd_state); + goto out; + } +ret: + if (!McdTimeout--) { + printk(KERN_WARNING "mcd: timeout in state %d\n", mcd_state); + mcd_state = MCD_S_STOP; + } + mcd_timer.function = mcd_poll; + mod_timer(&mcd_timer, jiffies + 1); out: - return; + return; } - - -static void -mcd_invalidate_buffers(void) +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; + 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: ++mcd_open_count; return 0; err_out: - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; return -EIO; } @@ -1130,11 +1010,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) +{ + if (!--mcd_open_count) { + mcd_invalidate_buffers(); + } + MOD_DEC_USE_COUNT; } @@ -1143,23 +1024,23 @@ * 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 +1056,18 @@ char msg[80]; if (mcd_port <= 0 || mcd_irq <= 0) { - printk("skip mcd_init\n"); - return -EIO; + printk(KERN_INFO "mcd: not probing.\n"); + return -EIO; } - 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; - } - if (check_region(mcd_port, 4)) { - cleanup(1); - printk("Init failed, I/O port (%X) already in use\n", - mcd_port); - return -EIO; + if (devfs_register_blkdev(MAJOR_NR, "mcd", &cdrom_fops) != 0) { + printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR); + return -EIO; + } + if (check_region(mcd_port, 4)) { + cleanup(1); + printk(KERN_ERR "mcd: Initialization failed, I/O port (%X) already in use\n", mcd_port); + return -EIO; } blksize_size[MAJOR_NR] = mcd_blocksizes; @@ -1198,106 +1076,103 @@ /* 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); + printk(KERN_INFO "mcd: initialisation failed - No mcd device at 0x%x irq %d\n", + 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)) { - printk("mitsumi get version failed at 0x%x\n", + 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(KERN_ERR "mcd: 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(KERN_ERR "mcd: 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(KERN_ERR "mcd: Unable to 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 +1181,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 +1192,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 +1210,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,23 +1227,20 @@ * (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; } - - SET_TIMER(mcdStatTimer, 1); + mcd_timer.function = mcdStatTimer; + mod_timer(&mcd_timer, jiffies + 1); } @@ -1383,13 +1250,13 @@ * excessive rescheduling. */ -static int -getMcdStatus(int timeout) +static int getMcdStatus(int timeout) { int st; McdTimeout = timeout; - SET_TIMER(mcdStatTimer, 1); + mcd_timer.function = mcdStatTimer; + mod_timer(&mcd_timer, jiffies + 1); sleep_on(&mcd_waitq); if (McdTimeout <= 0) return -1; @@ -1402,8 +1269,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 +1281,23 @@ /* 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 +1305,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; } @@ -1455,20 +1324,17 @@ return 0; } - /* * Read the current Q-channel info. Also used for reading the * 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,27 +1343,35 @@ 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; } - /* * Read the table of contents (TOC) and TOC header if necessary */ -static int -updateToc() +static int updateToc(void) { if (tocUpToDate) return 0; @@ -1512,18 +1386,15 @@ return 0; } - /* * Read the table of contents header */ -static int -GetDiskInfo() +static int GetDiskInfo(void) { 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,41 +1403,44 @@ 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); + 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; + 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; } - /* * Read the table of contents (TOC) */ -static int -GetToc() +static int GetToc(void) { int i, px; int limit; @@ -1578,8 +1452,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 +1461,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 +1472,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,41 +1489,44 @@ 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; } - 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/mcd.h linux/drivers/cdrom/mcd.h --- v2.4.9/linux/drivers/cdrom/mcd.h Wed Jul 5 11:24:41 2000 +++ linux/drivers/cdrom/mcd.h Sun Sep 9 10:43:02 2001 @@ -70,17 +70,6 @@ /* borrowed from hd.c */ -#define READ_DATA(port, buf, nr) \ -insb(port, buf, nr) - -#define SET_TIMER(func, jifs) \ - do { \ - mcd_timer.function = func; \ - mod_timer(&mcd_timer, jiffies + jifs); \ - } while (0) - -#define CLEAR_TIMER del_timer_async(&mcd_timer); - #define MAX_TRACKS 104 struct msf { @@ -108,3 +97,10 @@ struct msf trackTime; struct msf diskTime; }; + +#define test1(x) +#define test2(x) +#define test3(x) +#define test4(x) +#define test5(x) + 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/optcd.c linux/drivers/cdrom/optcd.c --- v2.4.9/linux/drivers/cdrom/optcd.c Sun Feb 4 10:05:29 2001 +++ linux/drivers/cdrom/optcd.c Sun Sep 9 10:43:02 2001 @@ -2097,3 +2097,4 @@ module_exit(optcd_exit); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c --- v2.4.9/linux/drivers/cdrom/sbpcd.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/cdrom/sbpcd.c Sun Sep 9 10:43:02 2001 @@ -4272,6 +4272,12 @@ D_S[d].aud_buf=NULL; D_S[d].sbp_audsiz=arg; + if (D_S[d].sbp_audsiz>16) + { + D_S[d].sbp_audsiz = 0; + RETURN_UP(D_S[d].sbp_audsiz); + } + if (D_S[d].sbp_audsiz>0) { D_S[d].aud_buf=(u_char *) vmalloc(D_S[d].sbp_audsiz*CD_FRAMESIZE_RAW); @@ -6016,6 +6022,9 @@ { return sbpcd_chk_disk_change(cdi->dev); } + +MODULE_LICENSE("GPL"); + /*==========================================================================*/ /* * Overrides for Emacs so that we follow Linus's tabbing style. @@ -6033,3 +6042,4 @@ * c-continued-brace-offset: 0 * End: */ + 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/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c --- v2.4.9/linux/drivers/cdrom/sonycd535.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/cdrom/sonycd535.c Sun Sep 9 10:43:02 2001 @@ -1709,3 +1709,4 @@ module_exit(sony535_exit); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.4.9/linux/drivers/char/Config.in Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/Config.in Sat Sep 15 22:19:46 2001 @@ -59,6 +59,24 @@ tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION fi + if [ "$CONFIG_MIPS" = "y" ]; then + bool ' TMPTX3912/PR31700 serial port support' CONFIG_SERIAL_TX3912 + dep_bool ' Console on TMPTX3912/PR31700 serial port' CONFIG_SERIAL_TX3912_CONSOLE $CONFIG_SERIAL_TX3912 + bool ' Enable Au1000 UART Support' CONFIG_AU1000_UART + if [ "$CONFIG_AU1000_UART" = "y" ]; then + bool ' Enable Au1000 serial console' CONFIG_AU1000_SERIAL_CONSOLE + fi + fi +fi +if [ "$CONFIG_IT8712" = "y" ]; then + bool 'Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD + if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then + define_bool CONFIG_IT8172_CIR y + else + bool ' Enable PS2 Keyboard Support' CONFIG_PC_KEYB + fi + bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0 + bool 'Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1 fi if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232 @@ -190,7 +208,7 @@ bool ' Intel 440LX/BX/GX and I815/I840/I850 support' CONFIG_AGP_INTEL bool ' Intel I810/I815 (on-board) support' CONFIG_AGP_I810 bool ' VIA chipset support' CONFIG_AGP_VIA - bool ' AMD Irongate support' CONFIG_AGP_AMD + bool ' AMD Irongate and 761 support' CONFIG_AGP_AMD bool ' Generic SiS support' CONFIG_AGP_SIS bool ' ALI chipset support' CONFIG_AGP_ALI bool ' Serverworks LE/HE support' CONFIG_AGP_SWORKS 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 9 10:43:02 2001 @@ -41,18 +41,10 @@ SERIAL = endif -ifeq ($(ARCH),s390x) - KEYMAP = - KEYBD = - CONSOLE = - SERIAL = -endif - -ifeq ($(ARCH),s390) - KEYMAP = - KEYBD = - CONSOLE = - SERIAL = +ifeq ($(ARCH),mips) + ifneq ($(CONFIG_PC_KEYB),y) + KEYBD = + endif endif ifeq ($(ARCH),s390x) @@ -109,8 +101,9 @@ endif ifeq ($(CONFIG_DECSTATION),y) + KEYMAP = KEYBD = - SERIAL = + SERIAL = decserial.o endif ifeq ($(CONFIG_BAGET_MIPS),y) @@ -118,10 +111,18 @@ SERIAL = endif +ifeq ($(CONFIG_NINO),y) + SERIAL = +endif + ifneq ($(CONFIG_SUN_SERIAL),) SERIAL = endif +ifeq ($(CONFIG_QTRONIX_KEYBOARD),y) + KEYBD = qtronix.o + KEYMAP = qtronixmap.o +endif obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o obj-$(CONFIG_SERIAL) += $(SERIAL) @@ -161,6 +162,7 @@ obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o +obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o subdir-$(CONFIG_RIO) += rio subdir-$(CONFIG_INPUT) += joystick @@ -241,5 +243,10 @@ 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 *//' > $@ + +qtronixmap.c: qtronixmap.map + set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ diff -u --recursive --new-file v2.4.9/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c --- v2.4.9/linux/drivers/char/acquirewdt.c Sat May 19 17:43:05 2001 +++ linux/drivers/char/acquirewdt.c Thu Sep 13 15:21:32 2001 @@ -226,3 +226,6 @@ module_init(acq_init); module_exit(acq_exit); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c --- v2.4.9/linux/drivers/char/adbmouse.c Sun Dec 3 17:48:19 2000 +++ linux/drivers/char/adbmouse.c Thu Sep 13 15:21:32 2001 @@ -205,3 +205,5 @@ module_init(adb_mouse_init); module_exit(adb_mouse_cleanup); + +MODULE_LICENSE("GPL"): diff -u --recursive --new-file v2.4.9/linux/drivers/char/advantechwdt.c linux/drivers/char/advantechwdt.c --- v2.4.9/linux/drivers/char/advantechwdt.c Sat May 19 17:43:05 2001 +++ linux/drivers/char/advantechwdt.c Thu Sep 13 15:21:32 2001 @@ -238,4 +238,7 @@ module_init(advwdt_init); module_exit(advwdt_exit); +MODULE_LICENSE("GPL"); + /* end of advantechwdt.c */ + 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 Sep 17 22:52:35 2001 @@ -101,6 +101,7 @@ int num_aperture_sizes; int num_of_masks; int capndx; + int cant_use_aperture; /* Links to driver specific functions */ @@ -119,6 +120,9 @@ void (*free_by_type) (agp_memory *); unsigned long (*agp_alloc_page) (void); void (*agp_destroy_page) (unsigned long); + int (*suspend)(void); + void (*resume)(void); + }; #define OUTREG32(mmap, addr, val) __raw_writel((val), (mmap)+(addr)) @@ -156,6 +160,9 @@ #ifndef PCI_DEVICE_ID_VIA_8363_0 #define PCI_DEVICE_ID_VIA_8363_0 0x0305 #endif +#ifndef PCI_DEVICE_ID_VIA_82C694X_0 +#define PCI_DEVICE_ID_VIA_82C694X_0 0x0605 +#endif #ifndef PCI_DEVICE_ID_INTEL_810_0 #define PCI_DEVICE_ID_INTEL_810_0 0x7120 #endif @@ -194,6 +201,9 @@ #endif #ifndef PCI_DEVICE_ID_AMD_IRONGATE_0 #define PCI_DEVICE_ID_AMD_IRONGATE_0 0x7006 +#endif +#ifndef PCI_DEVICE_ID_AMD_762_0 +#define PCI_DEVICE_ID_AMD_762_0 0x700C #endif #ifndef PCI_VENDOR_ID_AL #define PCI_VENDOR_ID_AL 0x10b9 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 Sep 17 22:52:35 2001 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ MODULE_AUTHOR("Jeff Hartmann "); MODULE_PARM(agp_try_unsupported, "1i"); +MODULE_LICENSE("GPL and additional rights"); EXPORT_SYMBOL(agp_free_memory); EXPORT_SYMBOL(agp_allocate_memory); EXPORT_SYMBOL(agp_copy_info); @@ -65,7 +67,7 @@ static inline void flush_cache(void) { -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) asm volatile ("wbinvd":::"memory"); #elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__) /* ??? I wonder if we'll really need to flush caches, or if the @@ -305,6 +307,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 +324,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 */ @@ -376,9 +387,9 @@ /* * Driver routines - start * Currently this module supports the following chipsets: - * i810, 440lx, 440bx, 440gx, i840, i850, via vp3, via mvp3, via kx133, - * via kt133, amd irongate, ALi M1541, and generic support for the SiS - * chipsets. + * i810, i815, 440lx, 440bx, 440gx, i840, i850, via vp3, via mvp3, + * via kx133, via kt133, amd irongate, amd 761, ALi M1541, and generic + * support for the SiS chipsets. */ /* Generic Agp routines - Start */ @@ -428,8 +439,8 @@ /* adjust RQ depth */ command = ((command & ~0xff000000) | - min(u32, (mode & 0xff000000), - min(u32, (command & 0xff000000), + min_t(u32, (mode & 0xff000000), + min_t(u32, (command & 0xff000000), (scratch & 0xff000000)))); /* disable SBA if it's not supported */ @@ -627,6 +638,15 @@ return 0; } +static int agp_generic_suspend(void) +{ + return 0; +} + +static void agp_generic_resume(void) +{ +} + static int agp_generic_free_gatt_table(void) { int page_order; @@ -775,28 +795,31 @@ static unsigned long agp_generic_alloc_page(void) { - void *pt; - - pt = (void *) __get_free_page(GFP_KERNEL); - if (pt == NULL) { + struct page * page; + + page = alloc_page(GFP_KERNEL); + if (page == NULL) { return 0; } - atomic_inc(&virt_to_page(pt)->count); - set_bit(PG_locked, &virt_to_page(pt)->flags); + atomic_inc(&page->count); + set_bit(PG_locked, &page->flags); atomic_inc(&agp_bridge.current_memory_agp); - return (unsigned long) pt; + return (unsigned long)page_address(page); } -static void agp_generic_destroy_page(unsigned long page) +static void agp_generic_destroy_page(unsigned long addr) { - void *pt = (void *) page; + void *pt = (void *) addr; + struct page *page; if (pt == NULL) { return; } - atomic_dec(&virt_to_page(pt)->count); - clear_bit(PG_locked, &virt_to_page(pt)->flags); - wake_up(&virt_to_page(pt)->wait); + + page = virt_to_page(pt); + atomic_dec(&page->count); + clear_bit(PG_locked, &page->flags); + wake_up(&page->wait); free_page((unsigned long) pt); atomic_dec(&agp_bridge.current_memory_agp); } @@ -1083,6 +1106,9 @@ 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.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; return 0; } @@ -1233,6 +1259,10 @@ return addr | agp_bridge.masks[0].mask; } +static void intel_resume(void) +{ + intel_configure(); +} /* Setup function */ static gatt_mask intel_generic_masks[] = @@ -1275,6 +1305,9 @@ 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.suspend = agp_generic_suspend; + agp_bridge.resume = intel_resume; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1305,6 +1338,9 @@ 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.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1335,6 +1371,9 @@ 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.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1452,6 +1491,9 @@ 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.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1563,6 +1605,9 @@ 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.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; return 0; } @@ -1938,6 +1983,9 @@ 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.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; return 0; @@ -2092,15 +2140,15 @@ static unsigned long ali_alloc_page(void) { - void *pt; + struct page *page; u32 temp; - pt = (void *) __get_free_page(GFP_KERNEL); - if (pt == NULL) + page = alloc_page(GFP_KERNEL); + if (page == NULL) return 0; - atomic_inc(&virt_to_page(pt)->count); - set_bit(PG_locked, &virt_to_page(pt)->flags); + atomic_inc(&page->count); + set_bit(PG_locked, &page->flags); atomic_inc(&agp_bridge.current_memory_agp); global_cache_flush(); @@ -2109,16 +2157,17 @@ pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp); pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys((void *)pt)) | + virt_to_phys(page_address(page))) | ALI_CACHE_FLUSH_EN )); } - return (unsigned long) pt; + return (unsigned long)page_address(page); } -static void ali_destroy_page(unsigned long page) +static void ali_destroy_page(unsigned long addr) { u32 temp; - void *pt = (void *) page; + void *pt = (void *) addr; + struct page *page; if (pt == NULL) return; @@ -2133,9 +2182,10 @@ ALI_CACHE_FLUSH_EN)); } - atomic_dec(&virt_to_page(pt)->count); - clear_bit(PG_locked, &virt_to_page(pt)->flags); - wake_up(&virt_to_page(pt)->wait); + page = virt_to_page(pt); + atomic_dec(&page->count); + clear_bit(PG_locked, &page->flags); + wake_up(&page->wait); free_page((unsigned long) pt); atomic_dec(&agp_bridge.current_memory_agp); } @@ -2181,6 +2231,9 @@ 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.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; return 0; @@ -2393,7 +2446,7 @@ &temp); pci_write_config_dword(agp_bridge.dev, serverworks_private.gart_addr_ofs, - 0xfe000000); + SVWRKS_SIZE_MASK); pci_read_config_dword(agp_bridge.dev, serverworks_private.gart_addr_ofs, &temp2); @@ -2657,8 +2710,8 @@ /* adjust RQ depth */ command = ((command & ~0xff000000) | - min(u32, (mode & 0xff000000), - min(u32, (command & 0xff000000), + min_t(u32, (mode & 0xff000000), + min_t(u32, (command & 0xff000000), (scratch & 0xff000000)))); /* disable SBA if it's not supported */ @@ -2766,6 +2819,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, @@ -2877,6 +2931,12 @@ "AMD", "Irongate", amd_irongate_setup }, + { PCI_DEVICE_ID_AMD_762_0, + PCI_VENDOR_ID_AMD, + AMD_IRONGATE, + "AMD", + "AMD 760MP", + amd_irongate_setup }, { 0, PCI_VENDOR_ID_AMD, AMD_GENERIC, @@ -2904,7 +2964,6 @@ "Intel", "440GX", intel_generic_setup }, - /* could we add support for PCI_DEVICE_ID_INTEL_815_1 too ? */ { PCI_DEVICE_ID_INTEL_815_0, PCI_VENDOR_ID_INTEL, INTEL_I815, @@ -2929,6 +2988,7 @@ "Intel", "Generic", intel_generic_setup }, + #endif /* CONFIG_AGP_INTEL */ #ifdef CONFIG_AGP_SIS @@ -2956,29 +3016,11 @@ "SiS", "530", sis_generic_setup }, - { PCI_DEVICE_ID_SI_630, + { PCI_DEVICE_ID_SI_735, PCI_VENDOR_ID_SI, SIS_GENERIC, "SiS", - "Generic", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_540, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "Generic", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_620, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "Generic", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_530, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "Generic", + "735", sis_generic_setup }, { 0, PCI_VENDOR_ID_SI, @@ -3025,6 +3067,12 @@ "Via", "Apollo Pro KT133", via_generic_setup }, + { PCI_DEVICE_ID_VIA_8367_0, + PCI_VENDOR_ID_VIA, + VIA_APOLLO_KT133, + "Via", + "Apollo Pro KT266", + via_generic_setup }, { 0, PCI_VENDOR_ID_VIA, VIA_GENERIC, @@ -3349,7 +3397,7 @@ size_value = agp_bridge.fetch_size(); if (size_value == 0) { - printk(KERN_ERR PFX "unable to detrimine aperture size.\n"); + printk(KERN_ERR PFX "unable to determine aperture size.\n"); rc = -EINVAL; goto err_out; } @@ -3411,6 +3459,19 @@ } } +static int agp_power(struct pm_dev *dev, pm_request_t rq, void *data) +{ + switch(rq) + { + case PM_SUSPEND: + return agp_bridge.suspend(); + case PM_RESUME: + agp_bridge.resume(); + return 0; + } + return 0; +} + extern int agp_frontend_initialize(void); extern void agp_frontend_cleanup(void); @@ -3445,11 +3506,14 @@ } inter_module_register("drm_agp", THIS_MODULE, &drm_agp); + + pm_register(PM_PCI_DEV, PM_PCI_ID(agp_bridge.dev), agp_power); return 0; } static void __exit agp_cleanup(void) { + pm_unregister_all(agp_power); agp_frontend_cleanup(); agp_backend_cleanup(); inter_module_unregister("drm_agp"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/amigamouse.c linux/drivers/char/amigamouse.c --- v2.4.9/linux/drivers/char/amigamouse.c Mon Nov 27 17:11:26 2000 +++ linux/drivers/char/amigamouse.c Thu Sep 13 15:21:32 2001 @@ -209,3 +209,5 @@ module_init(amiga_mouse_init); module_exit(amiga_mouse_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/amiserial.c linux/drivers/char/amiserial.c --- v2.4.9/linux/drivers/char/amiserial.c Fri Feb 16 16:02:35 2001 +++ linux/drivers/char/amiserial.c Sun Sep 16 21:22:56 2001 @@ -2288,7 +2288,7 @@ * Print a string to the serial port trying not to disturb * any possible real use of the port... * - * The console_lock must be held when we get here. + * The console must be locked when we get here. */ static void serial_console_write(struct console *co, const char *s, unsigned count) @@ -2353,3 +2353,5 @@ register_console(&sercons); } #endif + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/applicom.c linux/drivers/char/applicom.c --- v2.4.9/linux/drivers/char/applicom.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/applicom.c Thu Sep 13 15:21:32 2001 @@ -1,6 +1,6 @@ /* Derived from Applicom driver ac.c for SCO Unix */ /* Ported by David Woodhouse, Axiom (Cambridge) Ltd. */ -/* Dave@mvhi.com 30/8/98 */ +/* dwmw2@redhat.com 30/8/98 */ /* $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $ */ /* This module is for Linux 2.1 and 2.2 series kernels. */ /*****************************************************************************/ @@ -74,6 +74,7 @@ MODULE_AUTHOR("David Woodhouse & Applicom International"); MODULE_DESCRIPTION("Driver for Applicom Profibus card"); +MODULE_LICENSE("GPL"); MODULE_PARM(irq, "i"); MODULE_PARM_DESC(irq, "IRQ of the Applicom board"); MODULE_PARM(mem, "i"); @@ -82,7 +83,7 @@ MODULE_SUPPORTED_DEVICE("ac"); -struct applicom_board { +static struct applicom_board { unsigned long PhysIO; unsigned long RamIO; wait_queue_head_t FlagSleepSend; @@ -100,22 +101,21 @@ static unsigned int ReadErrorCount; /* number of read error */ static unsigned int DeviceErrorCount; /* number of device error */ -static loff_t ac_llseek(struct file *, loff_t, int); static ssize_t ac_read (struct file *, char *, size_t, loff_t *); static ssize_t ac_write (struct file *, const char *, size_t, loff_t *); static int ac_ioctl(struct inode *, struct file *, unsigned int, unsigned long); static void ac_interrupt(int, void *, struct pt_regs *); -struct file_operations ac_fops = { +static struct file_operations ac_fops = { owner:THIS_MODULE, - llseek:ac_llseek, + llseek:no_llseek, read:ac_read, write:ac_write, ioctl:ac_ioctl, }; -struct miscdevice ac_miscdev = { +static struct miscdevice ac_miscdev = { AC_MINOR, "ac", &ac_fops @@ -123,7 +123,7 @@ static int dummy; /* dev_id for request_irq() */ -int ac_register_board(unsigned long physloc, unsigned long loc, +static int ac_register_board(unsigned long physloc, unsigned long loc, unsigned char boardno) { volatile unsigned char byte_reset_it; @@ -254,6 +254,7 @@ /* Now try the specified ISA cards */ +#warning "LEAK" RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD); if (!RamIO) @@ -340,11 +341,6 @@ __initcall(applicom_init); #endif -static loff_t ac_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - static ssize_t ac_write(struct file *file, const char *buf, size_t count, loff_t * ppos) { unsigned int NumCard; /* Board number 1 -> 8 */ @@ -421,7 +417,7 @@ } /* Place ourselves on the wait queue */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait); /* Check whether the card is ready for us */ @@ -435,8 +431,9 @@ remove_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait); return -EINTR; - } + } spin_lock_irqsave(&apbs[IndexCard].mutex, flags); + set_current_state(TASK_INTERRUPTIBLE); } /* We may not have actually slept */ @@ -521,7 +518,7 @@ printk("\n"); #endif - /* Je suis stupide. DW. */ +#warning "Je suis stupide. DW. - copy*user in cli" if (copy_to_user(buf, &st_loc, sizeof(struct st_ram_io))) return -EFAULT; @@ -550,7 +547,7 @@ while(1) { /* Stick ourself on the wait queue */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&FlagSleepRec, &wait); /* Scan each board, looking for one which has a packet for us */ @@ -565,7 +562,7 @@ /* Got a packet for us */ ret = do_ac_read(i, buf); spin_unlock_irqrestore(&apbs[i].mutex, flags); - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&FlagSleepRec, &wait); return tmp; } @@ -575,7 +572,7 @@ Dummy = readb(apbs[i].RamIO + VERS); spin_unlock_irqrestore(&apbs[i].mutex, flags); - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&FlagSleepRec, &wait); printk(KERN_WARNING "APPLICOM driver read error board %d, DataToPcReady = %d\n", diff -u --recursive --new-file v2.4.9/linux/drivers/char/atarimouse.c linux/drivers/char/atarimouse.c --- v2.4.9/linux/drivers/char/atarimouse.c Tue Jun 20 07:32:13 2000 +++ linux/drivers/char/atarimouse.c Fri Sep 14 14:04:07 2001 @@ -133,3 +133,4 @@ module_init(atari_mouse_init); module_exit(atari_mouse_cleanup); +MODULE_LICENSE("GPL"); \ No newline at end of file diff -u --recursive --new-file v2.4.9/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c --- v2.4.9/linux/drivers/char/atixlmouse.c Mon Jun 19 13:45:52 2000 +++ linux/drivers/char/atixlmouse.c Fri Sep 14 14:04:07 2001 @@ -148,3 +148,4 @@ module_init(atixl_busmouse_init); module_exit(atixl_cleanup); +MODULE_LICENSE("GPL"); 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/console.c linux/drivers/char/console.c --- v2.4.9/linux/drivers/char/console.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/console.c Mon Sep 17 22:52:35 2001 @@ -69,6 +69,9 @@ * * Removed old-style timers, introduced console_timer, made timer * deletion SMP-safe. 17Jun00, Andrew Morton + * + * Removed console_lock, enabled interrupts across all console operations + * 13 March 2001, Andrew Morton */ #include @@ -149,6 +152,7 @@ static void set_cursor(int currcons); static void hide_cursor(int currcons); static void unblank_screen_t(unsigned long dummy); +static void console_callback(void *ignored); static int printable; /* Is console ready for printing? */ @@ -159,6 +163,10 @@ static int blankinterval = 10*60*HZ; static int vesa_off_interval; +static struct tq_struct console_callback_tq = { + routine: console_callback, +}; + /* * fg_console is the current virtual console, * last_console is the last used one, @@ -180,15 +188,13 @@ /* * Unfortunately, we need to delay tty echo when we're currently writing to the - * console since the code is (and always was) not re-entrant, so we insert - * all filp requests to con_task_queue instead of tq_timer and run it from - * the console_tasklet. The console_tasklet is protected by the IRQ - * protected console_lock. + * console since the code is (and always was) not re-entrant, so we schedule + * all flip requests to process context with schedule-task() and run it from + * console_callback(). */ -DECLARE_TASK_QUEUE(con_task_queue); /* - * For the same reason, we defer scrollback to the console tasklet. + * For the same reason, we defer scrollback to the console callback. */ static int scrollback_delta; @@ -232,7 +238,12 @@ static inline void scrolldelta(int lines) { scrollback_delta += lines; - tasklet_schedule(&console_tasklet); + schedule_console_callback(); +} + +void schedule_console_callback(void) +{ + schedule_task(&console_callback_tq); } static void scrup(int currcons, unsigned int t, unsigned int b, int nr) @@ -650,6 +661,7 @@ p = (long) kmalloc(structsize, GFP_KERNEL); if (!p) return -ENOMEM; + memset((void *)p, 0, structsize); vc_cons[currcons].d = (struct vc_data *)p; vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data)); visual_init(currcons, 1); @@ -780,6 +792,7 @@ void vc_disallocate(unsigned int currcons) { + acquire_console_sem(); if (vc_cons_allocated(currcons)) { sw->con_deinit(vc_cons[currcons].d); if (kmalloced) @@ -788,6 +801,7 @@ kfree(vc_cons[currcons].d); vc_cons[currcons].d = NULL; } + release_console_sem(); } /* @@ -1026,6 +1040,7 @@ color = def_color; } +/* console_sem is held */ static void csi_m(int currcons) { int i; @@ -1165,6 +1180,7 @@ return report_mouse; } +/* console_sem is held */ static void set_mode(int currcons, int on_off) { int i; @@ -1230,6 +1246,7 @@ } } +/* console_sem is held */ static void setterm_command(int currcons) { switch(par[0]) { @@ -1284,19 +1301,7 @@ } } -static void insert_line(int currcons, unsigned int nr) -{ - scrdown(currcons,y,bottom,nr); - need_wrap = 0; -} - - -static void delete_line(int currcons, unsigned int nr) -{ - scrup(currcons,y,bottom,nr); - need_wrap = 0; -} - +/* console_sem is held */ static void csi_at(int currcons, unsigned int nr) { if (nr > video_num_columns - x) @@ -1306,15 +1311,18 @@ insert_char(currcons, nr); } +/* console_sem is held */ static void csi_L(int currcons, unsigned int nr) { if (nr > video_num_lines - y) nr = video_num_lines - y; else if (!nr) nr = 1; - insert_line(currcons, nr); + scrdown(currcons,y,bottom,nr); + need_wrap = 0; } +/* console_sem is held */ static void csi_P(int currcons, unsigned int nr) { if (nr > video_num_columns - x) @@ -1324,15 +1332,18 @@ delete_char(currcons, nr); } +/* console_sem is held */ static void csi_M(int currcons, unsigned int nr) { if (nr > video_num_lines - y) nr = video_num_lines - y; else if (!nr) nr=1; - delete_line(currcons, nr); + scrup(currcons,y,bottom,nr); + need_wrap = 0; } +/* console_sem is held (except via vc_init->reset_terminal */ static void save_cur(int currcons) { saved_x = x; @@ -1347,6 +1358,7 @@ saved_G1 = G1_charset; } +/* console_sem is held */ static void restore_cur(int currcons) { gotoxy(currcons,saved_x,saved_y); @@ -1367,6 +1379,7 @@ EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd, ESpalette }; +/* console_sem is held (except via vc_init()) */ static void reset_terminal(int currcons, int do_clear) { top = 0; @@ -1422,6 +1435,7 @@ csi_J(currcons,2); } +/* console_sem is held */ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c) { /* @@ -1802,6 +1816,7 @@ #define CON_BUF_SIZE PAGE_SIZE DECLARE_MUTEX(con_buf_sem); +/* acquires console_sem */ static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { @@ -1822,6 +1837,9 @@ const unsigned char *orig_buf = NULL; int orig_count; + if (in_interrupt()) + return count; + currcons = vt->vc_num; if (!vc_cons_allocated(currcons)) { /* could this happen? */ @@ -1842,6 +1860,7 @@ again: if (count > CON_BUF_SIZE) count = CON_BUF_SIZE; + console_conditional_schedule(); if (copy_from_user(con_buf, buf, count)) { n = 0; /* ?? are error codes legal here ?? */ goto out; @@ -1857,7 +1876,7 @@ * the console spinlock during the entire write. */ - spin_lock_irq(&console_lock); + acquire_console_sem(); himask = hi_font_mask; charmask = himask ? 0x1ff : 0xff; @@ -1975,7 +1994,8 @@ do_con_trol(tty, currcons, c); } FLUSH - spin_unlock_irq(&console_lock); + console_conditional_schedule(); + release_console_sem(); out: if (from_user) { @@ -1999,23 +2019,17 @@ } /* - * This is the console switching tasklet. + * This is the console switching callback. * - * Doing console switching in a tasklet allows + * Doing console switching in a process context allows * us to do the switches asynchronously (needed when we want * to switch due to a keyboard interrupt). Synchronization * with other console code and prevention of re-entrancy is - * ensured with console_lock. + * ensured with console_sem. */ -static void console_softint(unsigned long ignored) +static void console_callback(void *ignored) { - /* Runs the task queue outside of the console lock. These - * callbacks can come back into the console code and thus - * will perform their own locking. - */ - run_task_queue(&con_task_queue); - - spin_lock_irq(&console_lock); + acquire_console_sem(); if (want_console >= 0) { if (want_console != fg_console && vc_cons_allocated(want_console)) { @@ -2039,7 +2053,13 @@ scrollback_delta = 0; } - spin_unlock_irq(&console_lock); + release_console_sem(); +} + +void set_console(int nr) +{ + want_console = nr; + schedule_console_callback(); } #ifdef CONFIG_VT_CONSOLE @@ -2047,7 +2067,7 @@ /* * Console on virtual terminal * - * The console_lock must be held when we get here. + * The console must be locked when we get here. */ void vt_console_print(struct console *co, const char * b, unsigned count) @@ -2134,6 +2154,9 @@ } set_cursor(currcons); + if (!oops_in_progress) + poke_blanked_console(); + quit: clear_bit(0, &printing); } @@ -2158,27 +2181,45 @@ * Handling of Linux-specific VC ioctls */ +/* + * Generally a bit racy with respect to console_sem(). + * + * There are some functions which don't need it. + * + * There are some functions which can sleep for arbitrary periods (paste_selection) + * but we don't need the lock there anyway. + * + * set_selection has locking, and definitely needs it + */ + int tioclinux(struct tty_struct *tty, unsigned long arg) { char type, data; + int ret; if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) return -EINVAL; - if (current->tty != tty && !suser()) + if (current->tty != tty && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(type, (char *)arg)) return -EFAULT; + ret = 0; switch (type) { case 2: - return set_selection(arg, tty, 1); + acquire_console_sem(); + ret = set_selection(arg, tty, 1); + release_console_sem(); + break; case 3: - return paste_selection(tty); + ret = paste_selection(tty); + break; case 4: unblank_screen(); - return 0; + break; case 5: - return sel_loadlut(arg); + ret = sel_loadlut(arg); + break; case 6: /* @@ -2188,24 +2229,33 @@ * related to the kernel should not use this. */ data = shift_state; - return __put_user(data, (char *) arg); + ret = __put_user(data, (char *) arg); + break; case 7: data = mouse_reporting(); - return __put_user(data, (char *) arg); + ret = __put_user(data, (char *) arg); + break; case 10: set_vesa_blanking(arg); - return 0; + break;; case 11: /* set kmsg redirect */ - if (!suser()) - return -EPERM; - if (get_user(data, (char *)arg+1)) - return -EFAULT; - kmsg_redirect = data; - return 0; + if (!capable(CAP_SYS_ADMIN)) { + ret = -EPERM; + } else { + if (get_user(data, (char *)arg+1)) + ret = -EFAULT; + else + kmsg_redirect = data; + } + break; case 12: /* get fg_console */ - return fg_console; + ret = fg_console; + break; + default: + ret = -EINVAL; + break; } - return -EINVAL; + return ret; } /* @@ -2226,6 +2276,8 @@ static void con_put_char(struct tty_struct *tty, unsigned char ch) { + if (in_interrupt()) + return; /* n_r3964 calls put_char() from interrupt context */ pm_access(pm_con); do_con_write(tty, 0, &ch, 1); } @@ -2290,13 +2342,15 @@ static void con_flush_chars(struct tty_struct *tty) { - unsigned long flags; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + if (in_interrupt()) /* from flush_to_ldisc */ + return; + pm_access(pm_con); - spin_lock_irqsave(&console_lock, flags); + acquire_console_sem(); set_cursor(vt->vc_num); - spin_unlock_irqrestore(&console_lock, flags); + release_console_sem(); } /* @@ -2367,8 +2421,6 @@ struct tty_driver console_driver; static int console_refcount; -DECLARE_TASKLET_DISABLED(console_tasklet, console_softint, 0); - void __init con_init(void) { const char *display_desc = NULL; @@ -2453,9 +2505,6 @@ #ifdef CONFIG_VT_CONSOLE register_console(&vt_console_driver); #endif - - tasklet_enable(&console_tasklet); - tasklet_schedule(&console_tasklet); } #ifndef VT_SINGLE_DRIVER @@ -2561,6 +2610,9 @@ console_driver.minor_start + i); } +/* + * This is called by a timer handler + */ static void vesa_powerdown(void) { struct vc_data *c = vc_cons[fg_console].d; @@ -2581,9 +2633,12 @@ } } +/* + * This is a timer handler + */ static void vesa_powerdown_screen(unsigned long dummy) { - console_timer.function = unblank_screen_t; /* I don't have a clue why this is necessary */ + console_timer.function = unblank_screen_t; vesa_powerdown(); } @@ -2642,11 +2697,17 @@ timer_do_blank_screen(entering_gfx, 0); } +/* + * This is a timer handler + */ static void unblank_screen_t(unsigned long dummy) { unblank_screen(); } +/* + * Called by timer as well as from vt_console_driver + */ void unblank_screen(void) { int currcons; @@ -2677,6 +2738,9 @@ set_cursor(fg_console); } +/* + * This is both a user-level callable and a timer handler + */ static void blank_screen(unsigned long dummy) { timer_do_blank_screen(0, 1); @@ -2684,7 +2748,7 @@ void poke_blanked_console(void) { - del_timer(&console_timer); /* Can't use _sync here: called from tasklet */ + del_timer(&console_timer); if (!vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) return; if (console_blanked) { @@ -2832,9 +2896,9 @@ op->data = temp; } - spin_lock_irq(&console_lock); + acquire_console_sem(); rc = sw->con_font_op(vc_cons[currcons].d, op); - spin_unlock_irq(&console_lock); + release_console_sem(); op->data = old_op.data; if (!rc && !set) { diff -u --recursive --new-file v2.4.9/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.4.9/linux/drivers/char/cyclades.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/cyclades.c Fri Sep 14 14:04:07 2001 @@ -1629,8 +1629,8 @@ for performance, but because of buffer boundaries, there may be several steps to the operation */ while(0 < (small_count = - min(unsigned int, (rx_bufsize - new_rx_get), - min(unsigned int, (TTY_FLIPBUF_SIZE - tty->flip.count), char_count)) + min_t(unsigned int, (rx_bufsize - new_rx_get), + min_t(unsigned int, (TTY_FLIPBUF_SIZE - tty->flip.count), char_count)) )) { memcpy_fromio(tty->flip.char_buf_ptr, (char *)(cinfo->base_addr @@ -1724,9 +1724,9 @@ } #ifdef BLOCKMOVE while(0 < (small_count = - min(unsigned int, (tx_bufsize - tx_put), - min(unsigned int, (SERIAL_XMIT_SIZE - info->xmit_tail), - min(unsigned int, info->xmit_cnt, char_count))))) { + min_t(unsigned int, (tx_bufsize - tx_put), + min_t(unsigned int, (SERIAL_XMIT_SIZE - info->xmit_tail), + min_t(unsigned int, info->xmit_cnt, char_count))))) { memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put), &info->xmit_buf[info->xmit_tail], @@ -5819,3 +5819,4 @@ } /* cy_setup */ #endif /* MODULE */ +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/decserial.c linux/drivers/char/decserial.c --- v2.4.9/linux/drivers/char/decserial.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/decserial.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,98 @@ +/* + * sercons.c + * choose the right serial device at boot time + * + * triemer 6-SEP-1998 + * sercons.c is designed to allow the three different kinds + * of serial devices under the decstation world to co-exist + * in the same kernel. The idea here is to abstract + * the pieces of the drivers that are common to this file + * so that they do not clash at compile time and runtime. + * + * HK 16-SEP-1998 v0.002 + * removed the PROM console as this is not a real serial + * device. Added support for PROM console in drivers/char/tty_io.c + * instead. Although it may work to enable more than one + * console device I strongly recommend to use only one. + */ + +#include +#include +#include + +#ifdef CONFIG_ZS +extern int zs_init(void); +#endif + +#ifdef CONFIG_DZ +extern int dz_init(void); +#endif + +#ifdef CONFIG_SERIAL_CONSOLE + +#ifdef CONFIG_ZS +extern void zs_serial_console_init(void); +#endif + +#ifdef CONFIG_DZ +extern void dz_serial_console_init(void); +#endif + +#endif + +/* rs_init - starts up the serial interface - + handle normal case of starting up the serial interface */ + +#ifdef CONFIG_SERIAL + +int __init rs_init(void) +{ + +#if defined(CONFIG_ZS) && defined(CONFIG_DZ) + if (IOASIC) + return zs_init(); + else + return dz_init(); +#else + +#ifdef CONFIG_ZS + return zs_init(); +#endif + +#ifdef CONFIG_DZ + return dz_init(); +#endif + +#endif +} + +__initcall(rs_init); + +#endif + +#ifdef CONFIG_SERIAL_CONSOLE + +/* serial_console_init handles the special case of starting + * up the console on the serial port + */ +void __init serial_console_init(void) +{ +#if defined(CONFIG_ZS) && defined(CONFIG_DZ) + if (IOASIC) + zs_serial_console_init(); + else + dz_serial_console_init(); +#else + +#ifdef CONFIG_ZS + zs_serial_console_init(); +#endif + +#ifdef CONFIG_DZ + dz_serial_console_init(); +#endif + +#endif +} + +#endif 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 Tue Sep 18 17:07:21 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; } } -#if __i386__ + ret = 1; + +#if defined(__i386__) || defined(__x86_64__) 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 Tue Sep 18 17:07:21 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 Tue Sep 18 17:07:21 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_context.h linux/drivers/char/drm/drm_context.h --- v2.4.9/linux/drivers/char/drm/drm_context.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/drm_context.h Tue Sep 18 17:07:21 2001 @@ -181,7 +181,7 @@ drm_device_t *dev = priv->dev; drm_ctx_priv_map_t request; drm_map_t *map = NULL; - drm_map_list_t *r_list; + drm_map_list_t *r_list = NULL; struct list_head *list; if (copy_from_user(&request, diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_drv.h linux/drivers/char/drm/drm_drv.h --- v2.4.9/linux/drivers/char/drm/drm_drv.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/drm_drv.h Fri Sep 14 14:04:07 2001 @@ -234,6 +234,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_PARM( drm_opts, "s" ); +MODULE_LICENSE("GPL and additional rights"); static int DRM(setup)( drm_device_t *dev ) { 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 Tue Sep 18 17:07:21 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 Tue Sep 18 17:07:21 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 Tue Sep 18 17:07:21 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 Fri Sep 14 14:29:41 2001 @@ -543,8 +543,7 @@ RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | RADEON_SOFT_RESET_E2 | - RADEON_SOFT_RESET_RB | - RADEON_SOFT_RESET_HDP ) ); + RADEON_SOFT_RESET_RB ) ); RADEON_READ( RADEON_RBBM_SOFT_RESET ); RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset & ~( RADEON_SOFT_RESET_CP | @@ -553,8 +552,7 @@ RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | RADEON_SOFT_RESET_E2 | - RADEON_SOFT_RESET_RB | - RADEON_SOFT_RESET_HDP ) ) ); + RADEON_SOFT_RESET_RB ) ) ); RADEON_READ( RADEON_RBBM_SOFT_RESET ); @@ -624,10 +622,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 +926,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 +941,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 +986,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/ds1620.c linux/drivers/char/ds1620.c --- v2.4.9/linux/drivers/char/ds1620.c Sun Aug 13 09:54:15 2000 +++ linux/drivers/char/ds1620.c Thu Sep 13 15:21:32 2001 @@ -410,3 +410,5 @@ module_init(ds1620_init); module_exit(ds1620_exit); + +MODULE_LICENSE("GPL"); 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 Mon Sep 10 08:06:32 2001 @@ -69,7 +69,7 @@ { \ long i, t, m; \ while (count > 0) { \ - m = min(unsigned long, count, maxio); \ + m = min_t(unsigned long, count, maxio); \ for (i = 0; i < m; i++) { \ for (t = 0; t < timeout && !ENABLE; t++) \ wait_some(HZ/50); \ @@ -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/dtlk.c linux/drivers/char/dtlk.c --- v2.4.9/linux/drivers/char/dtlk.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/dtlk.c Thu Sep 13 15:21:32 2001 @@ -678,3 +678,5 @@ #endif return 0; } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/dz.c linux/drivers/char/dz.c --- v2.4.9/linux/drivers/char/dz.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/dz.c Sun Sep 9 10:43:02 2001 @@ -21,15 +21,10 @@ * [07-SEP-99] Bugfixes */ -#define DEBUG_DZ 1 +/* #define DEBUG_DZ 1 */ -#ifdef MODULE -#include #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif +#include #include #include @@ -41,9 +36,10 @@ #include #include #include +#include +#include #include -/* for definition of SERIAL */ -#include +#include /* for definition of SERIAL */ /* for definition of struct console */ #ifdef CONFIG_SERIAL_CONSOLE @@ -91,13 +87,13 @@ */ static void debug_console( const char *s,int count) { - unsigned i; + unsigned i; - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); - } + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } } #endif @@ -112,16 +108,16 @@ static inline unsigned short dz_in (struct dz_serial *info, unsigned offset) { - volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset); - return *addr; + volatile u16 *addr = (volatile u16 *)(info->port + offset); + + return *addr; } -static inline void dz_out (struct dz_serial *info, unsigned offset, unsigned short value) +static inline void dz_out (struct dz_serial *info, unsigned offset, + unsigned short value) { - - volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset); - *addr = value; - + volatile u16 *addr = (volatile u16 *)(info->port + offset); + *addr = value; } /* @@ -136,33 +132,32 @@ static void dz_stop (struct tty_struct *tty) { - struct dz_serial *info; - unsigned short mask, tmp; + struct dz_serial *info; + unsigned short mask, tmp; - if (tty==0) - return; + if (!tty) + return; - info = (struct dz_serial *)tty->driver_data; - - mask = 1 << info->line; - tmp = dz_in (info, DZ_TCR); /* read the TX flag */ - - tmp &= ~mask; /* clear the TX flag */ - dz_out (info, DZ_TCR, tmp); -} + info = (struct dz_serial *)tty->driver_data; + + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); /* read the TX flag */ + + tmp &= ~mask; /* clear the TX flag */ + dz_out (info, DZ_TCR, tmp); +} static void dz_start (struct tty_struct *tty) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - unsigned short mask, tmp; - - mask = 1 << info->line; - tmp = dz_in (info, DZ_TCR); /* read the TX flag */ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned short mask, tmp; - tmp |= mask; /* set the TX flag */ - dz_out (info, DZ_TCR, tmp); + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); /* read the TX flag */ -} + tmp |= mask; /* set the TX flag */ + dz_out (info, DZ_TCR, tmp); +} /* * ------------------------------------------------------------ @@ -194,9 +189,9 @@ */ static inline void dz_sched_event (struct dz_serial *info, int event) { - info->event |= 1 << event; - queue_task (&info->tqueue, &tq_serial); - mark_bh (SERIAL_BH); + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_serial); + mark_bh(SERIAL_BH); } /* @@ -208,98 +203,101 @@ */ static inline void receive_chars (struct dz_serial *info_in) { + struct dz_serial *info; + struct tty_struct *tty = 0; + struct async_icount *icount; + int ignore = 0; + unsigned short status, tmp; + unsigned char ch; - struct dz_serial *info; - struct tty_struct *tty = 0; - struct async_icount *icount; - int ignore = 0; - unsigned short status, tmp; - unsigned char ch; - - /* this code is going to be a problem... - the call to tty_flip_buffer is going to need - to be rethought... - */ - do - { - status = dz_in (info_in, DZ_RBUF); - info = lines[LINE(status)]; - - /* punt so we don't get duplicate characters */ - if (!(status & DZ_DVAL)) - goto ignore_char; - + /* + * This code is going to be a problem... the call to tty_flip_buffer + * is going to need to be rethought... + */ + do { + status = dz_in (info_in, DZ_RBUF); + info = lines[LINE(status)]; + + /* punt so we don't get duplicate characters */ + if (!(status & DZ_DVAL)) + goto ignore_char; - ch = UCHAR(status); /* grab the char */ + ch = UCHAR(status); /* grab the char */ #if 0 - if (info->is_console) { - if (ch == 0) return; /* it's a break ... */ + if (info->is_console) { + if (ch == 0) + return; /* it's a break ... */ - wake_up (&keypress_wait); /* It is a 'keyboard interrupt' ;-) */ - } + wake_up (&keypress_wait); /* It is a 'keyboard interrupt' ;-) */ + } #endif - tty = info->tty; /* now tty points to the proper dev */ - icount = &info->icount; - - if (!tty) break; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; + tty = info->tty; /* now tty points to the proper dev */ + icount = &info->icount; - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = 0; - icount->rx++; - - /* keep track of the statistics */ - if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) { - if (status & DZ_PERR) /* parity error */ - icount->parity++; - else if (status & DZ_FERR) /* frame error */ - icount->frame++; - if (status & DZ_OERR) /* overrun error */ - icount->overrun++; - - /* check to see if we should ignore the character - and mask off conditions that should be ignored - */ - - if (status & info->ignore_status_mask) { - if (++ignore > 100 ) break; - goto ignore_char; - } + if (!tty) + break; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; + + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = 0; + icount->rx++; + + /* keep track of the statistics */ + if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) { + if (status & DZ_PERR) /* parity error */ + icount->parity++; + else if (status & DZ_FERR) /* frame error */ + icount->frame++; + if (status & DZ_OERR) /* overrun error */ + icount->overrun++; + + /* + * Check to see if we should ignore the character and + * mask off conditions that should be ignored + */ + + if (status & info->ignore_status_mask) { + if (++ignore > 100) + break; + goto ignore_char; + } - /* mask off the error conditions we want to ignore */ - tmp = status & info->read_status_mask; + /* mask off the error conditions we want to ignore */ + tmp = status & info->read_status_mask; - if (tmp & DZ_PERR) - { - *tty->flip.flag_buf_ptr = TTY_PARITY; - debug_console("PERR\n",5); - } - else if (tmp & DZ_FERR) - { - *tty->flip.flag_buf_ptr = TTY_FRAME; - debug_console("FERR\n",5); - } - if (tmp & DZ_OERR) - { - debug_console("OERR\n",5); - 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: - } while (status & DZ_DVAL); + if (tmp & DZ_PERR) { + *tty->flip.flag_buf_ptr = TTY_PARITY; +#ifdef DEBUG_DZ + debug_console("PERR\n",5); +#endif /* DEBUG_DZ */ + } else if (tmp & DZ_FERR) { + *tty->flip.flag_buf_ptr = TTY_FRAME; +#ifdef DEBUG_DZ + debug_console("FERR\n",5); +#endif /* DEBUG_DZ */ + } if (tmp & DZ_OERR) { +#ifdef DEBUG_DZ + debug_console("OERR\n",5); +#endif /* DEBUG_DZ */ + 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: + ; + } while (status & DZ_DVAL); - if (tty) - tty_flip_buffer_push(tty); + if (tty) + tty_flip_buffer_push(tty); } /* @@ -311,35 +309,37 @@ */ static inline void transmit_chars (struct dz_serial *info) { - unsigned char tmp; + unsigned char tmp; + if (info->x_char) { /* XON/XOFF chars */ + dz_out(info, DZ_TDR, info->x_char); + info->icount.tx++; + info->x_char = 0; + return; + } + /* if nothing to do or stopped or hardware stopped */ + if ((info->xmit_cnt <= 0) || info->tty->stopped || + info->tty->hw_stopped) { + dz_stop(info->tty); + return; + } - if (info->x_char) { /* XON/XOFF chars */ - dz_out (info, DZ_TDR, info->x_char); - info->icount.tx++; - info->x_char = 0; - return; - } - - /* if nothing to do or stopped or hardware stopped */ - if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) { - dz_stop (info->tty); - return; - } - - /* if something to do ... (rember the dz has no output fifo so we go one char at a time :-< */ - tmp = (unsigned short)info->xmit_buf[info->xmit_tail++]; - dz_out (info, DZ_TDR, tmp); - info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1); - info->icount.tx++; - - if (--info->xmit_cnt < WAKEUP_CHARS) - dz_sched_event (info, DZ_EVENT_WRITE_WAKEUP); - - - /* Are we done */ - if (info->xmit_cnt <= 0) dz_stop (info->tty); + /* + * If something to do ... (rember the dz has no output fifo so we go + * one char at a time :-< + */ + tmp = (unsigned short) info->xmit_buf[info->xmit_tail++]; + dz_out(info, DZ_TDR, tmp); + info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1); + info->icount.tx++; + + if (--info->xmit_cnt < WAKEUP_CHARS) + dz_sched_event(info, DZ_EVENT_WRITE_WAKEUP); + + /* Are we done */ + if (info->xmit_cnt <= 0) + dz_stop(info->tty); } /* @@ -351,15 +351,17 @@ */ static inline void check_modem_status (struct dz_serial *info) { - unsigned short status; + unsigned short status; - /* if not ne modem line just return */ - if (info->line != DZ_MODEM) return; + /* if not ne modem line just return */ + if (info->line != DZ_MODEM) + return; - status = dz_in (info, DZ_MSR); + status = dz_in(info, DZ_MSR); - /* it's easy, since DSR2 is the only bit in the register */ - if (status) info->icount.dsr++; + /* it's easy, since DSR2 is the only bit in the register */ + if (status) + info->icount.dsr++; } /* @@ -372,17 +374,18 @@ */ static void dz_interrupt (int irq, void *dev, struct pt_regs *regs) { - struct dz_serial *info; - unsigned short status; + struct dz_serial *info; + unsigned short status; - status = dz_in ((struct dz_serial *)dev, DZ_CSR); /* get the reason why we just got an irq */ - info = lines[LINE(status)]; /* re-arrange info the proper port */ + /* get the reason why we just got an irq */ + status = dz_in((struct dz_serial *)dev, DZ_CSR); + info = lines[LINE(status)]; /* re-arrange info the proper port */ - if (status & DZ_RDONE) - receive_chars (info); /* the receive function */ + if (status & DZ_RDONE) + receive_chars(info); /* the receive function */ - if (status & DZ_TRDY) - transmit_chars (info); + if (status & DZ_TRDY) + transmit_chars (info); } /* @@ -402,21 +405,23 @@ */ static void do_serial_bh (void) { - run_task_queue (&tq_serial); + run_task_queue (&tq_serial); } static void do_softint (void *private_data) { - struct dz_serial *info = (struct dz_serial *)private_data; - struct tty_struct *tty = info->tty; + struct dz_serial *info = (struct dz_serial *) private_data; + struct tty_struct *tty = info->tty; - if (!tty) return; + if (!tty) + return; - if (test_and_clear_bit (DZ_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - wake_up_interruptible (&tty->write_wait); - } + if (test_and_clear_bit(DZ_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup) (tty); + wake_up_interruptible (&tty->write_wait); + } } /* @@ -431,12 +436,13 @@ */ static void do_serial_hangup (void *private_data) { - struct dz_serial *info = (struct dz_serial *)private_data; - struct tty_struct *tty = info->tty;; + struct dz_serial *info = (struct dz_serial *) private_data; + struct tty_struct *tty = info->tty;; - if (!tty) return; + if (!tty) + return; - tty_hangup (tty); + tty_hangup(tty); } /* @@ -448,57 +454,52 @@ */ static int startup (struct dz_serial *info) { - unsigned long page, flags; - unsigned short tmp; + unsigned long page, flags; + unsigned short tmp; - if (info->is_initialized) return 0; + if (info->is_initialized) + return 0; - save_flags (flags); - cli (); + save_and_cli(flags); - if (!info->port) { - if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags); - restore_flags (flags); - return -ENODEV; - } - - if (!info->xmit_buf) { - page = get_free_page (GFP_KERNEL); - if (!page) { - restore_flags (flags); - return -ENOMEM; - } - info->xmit_buf = (unsigned char *)page; - } - - if (info->tty) clear_bit (TTY_IO_ERROR, &info->tty->flags); - - /* enable the interrupt and the scanning */ - tmp = dz_in (info, DZ_CSR); - tmp |= (DZ_RIE | DZ_TIE | DZ_MSE); - dz_out (info, DZ_CSR, tmp); - - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - /* set up the speed */ - change_speed (info); - - /* clear the line transmitter buffer - I can't figure out why I need to do this - but - its necessary - in order for the console portion - and the interrupt portion to live happily side by side. - */ - - /* clear the line transmitter buffer - I can't figure out why I need to do this - but - its necessary - in order for the console portion - and the interrupt portion to live happily side by side. - */ + if (!info->port) { + if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); + restore_flags(flags); + return -ENODEV; + } + + if (!info->xmit_buf) { + page = get_free_page(GFP_KERNEL); + if (!page) { + restore_flags (flags); + return -ENOMEM; + } + info->xmit_buf = (unsigned char *)page; + } - info->is_initialized = 1; + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); - restore_flags (flags); - return 0; + /* enable the interrupt and the scanning */ + tmp = dz_in(info, DZ_CSR); + tmp |= (DZ_RIE | DZ_TIE | DZ_MSE); + dz_out(info, DZ_CSR, tmp); + + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + change_speed(info); /* set up the speed */ + + /* + * Clear the line transmitter buffer I can't figure out why I need to + * do this - but its necessary - in order for the console portion and + * the interrupt portion to live happily side by side. + */ + + info->is_initialized = 1; + + restore_flags(flags); + + return 0; } /* @@ -511,38 +512,38 @@ */ static void shutdown (struct dz_serial *info) { - unsigned long flags; - unsigned short tmp; + unsigned long flags; + unsigned short tmp; - if (!info->is_initialized) return; + if (!info->is_initialized) + return; - save_flags (flags); - cli (); + save_and_cli(flags); - dz_stop (info->tty); + dz_stop (info->tty); + info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */ + dz_out(info, DZ_LPR, info->cflags); + if (info->xmit_buf) { /* free Tx buffer */ + free_page((unsigned long)info->xmit_buf); + info->xmit_buf = 0; + } - info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */ - dz_out (info, DZ_LPR, info->cflags); - - if (info->xmit_buf) { /* free Tx buffer */ - free_page ((unsigned long)info->xmit_buf); - info->xmit_buf = 0; - } + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + tmp = dz_in(info, DZ_TCR); + if (tmp & DZ_MODEM_DTR) { + tmp &= ~DZ_MODEM_DTR; + dz_out(info, DZ_TCR, tmp); + } + } - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - tmp = dz_in (info, DZ_TCR); - if (tmp & DZ_MODEM_DTR) { - tmp &= ~DZ_MODEM_DTR; - dz_out (info, DZ_TCR, tmp); - } - } + if (info->tty) + set_bit (TTY_IO_ERROR, &info->tty->flags); - if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags); + info->is_initialized = 0; - info->is_initialized = 0; - restore_flags (flags); + restore_flags (flags); } /* @@ -554,65 +555,104 @@ */ static void change_speed (struct dz_serial *info) { - unsigned long flags; - unsigned cflag; - int baud; + unsigned long flags; + unsigned cflag; + int baud; - if (!info->tty || !info->tty->termios) return; + if (!info->tty || !info->tty->termios) + return; - save_flags (flags); - cli (); + save_and_cli(flags); - info->cflags = info->line; + info->cflags = info->line; - cflag = info->tty->termios->c_cflag; + cflag = info->tty->termios->c_cflag; - switch (cflag & CSIZE) { - case CS5: info->cflags |= DZ_CS5; break; - case CS6: info->cflags |= DZ_CS6; break; - case CS7: info->cflags |= DZ_CS7; break; - case CS8: - default: info->cflags |= DZ_CS8; - } - - if (cflag & CSTOPB) info->cflags |= DZ_CSTOPB; - if (cflag & PARENB) info->cflags |= DZ_PARENB; - if (cflag & PARODD) info->cflags |= DZ_PARODD; + switch (cflag & CSIZE) { + case CS5: + info->cflags |= DZ_CS5; + break; + case CS6: + info->cflags |= DZ_CS6; + break; + case CS7: + info->cflags |= DZ_CS7; + break; + case CS8: + default: + info->cflags |= DZ_CS8; + } + + if (cflag & CSTOPB) + info->cflags |= DZ_CSTOPB; + if (cflag & PARENB) + info->cflags |= DZ_PARENB; + if (cflag & PARODD) + info->cflags |= DZ_PARODD; - baud = tty_get_baud_rate (info->tty); - switch (baud) { - case 50 : info->cflags |= DZ_B50; break; - case 75 : info->cflags |= DZ_B75; break; - case 110 : info->cflags |= DZ_B110; break; - case 134 : info->cflags |= DZ_B134; break; - case 150 : info->cflags |= DZ_B150; break; - case 300 : info->cflags |= DZ_B300; break; - case 600 : info->cflags |= DZ_B600; break; - case 1200: info->cflags |= DZ_B1200; break; - case 1800: info->cflags |= DZ_B1800; break; - case 2000: info->cflags |= DZ_B2000; break; - case 2400: info->cflags |= DZ_B2400; break; - case 3600: info->cflags |= DZ_B3600; break; - case 4800: info->cflags |= DZ_B4800; break; - case 7200: info->cflags |= DZ_B7200; break; - case 9600: - default : info->cflags |= DZ_B9600; - } - - info->cflags |= DZ_RXENAB; - dz_out (info, DZ_LPR, info->cflags); - - /* setup accept flag */ - info->read_status_mask = DZ_OERR; - if (I_INPCK(info->tty)) - info->read_status_mask |= (DZ_FERR | DZ_PERR); + baud = tty_get_baud_rate(info->tty); + switch (baud) { + case 50: + info->cflags |= DZ_B50; + break; + case 75: + info->cflags |= DZ_B75; + break; + case 110: + info->cflags |= DZ_B110; + break; + case 134: + info->cflags |= DZ_B134; + break; + case 150: + info->cflags |= DZ_B150; + break; + case 300: + info->cflags |= DZ_B300; + break; + case 600: + info->cflags |= DZ_B600; + break; + case 1200: + info->cflags |= DZ_B1200; + break; + case 1800: + info->cflags |= DZ_B1800; + break; + case 2000: + info->cflags |= DZ_B2000; + break; + case 2400: + info->cflags |= DZ_B2400; + break; + case 3600: + info->cflags |= DZ_B3600; + break; + case 4800: + info->cflags |= DZ_B4800; + break; + case 7200: + info->cflags |= DZ_B7200; + break; + case 9600: + default: + info->cflags |= DZ_B9600; + } + + info->cflags |= DZ_RXENAB; + dz_out(info, DZ_LPR, info->cflags); + + /* setup accept flag */ + info->read_status_mask = DZ_OERR; + if (I_INPCK(info->tty)) + info->read_status_mask |= (DZ_FERR | DZ_PERR); - /* characters to ignore */ - info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= (DZ_FERR | DZ_PERR); + /* characters to ignore */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= (DZ_FERR | DZ_PERR); - restore_flags (flags); + restore_flags(flags); } /* @@ -624,18 +664,16 @@ */ static void dz_flush_chars (struct tty_struct *tty) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - unsigned long flags; - - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf) - return; + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned long flags; - save_flags (flags); - cli (); - - dz_start (info->tty); - - restore_flags (flags); + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + save_and_cli(flags); + dz_start (info->tty); + restore_flags(flags); } @@ -646,83 +684,81 @@ * main output routine. * ------------------------------------------------------------------- */ -static int dz_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int dz_write (struct tty_struct *tty, int from_user, + const unsigned char *buf, int count) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - unsigned long flags; - int c, ret = 0; - - if (!tty ) return ret; - if (!info->xmit_buf) return ret; - if (!tmp_buf) tmp_buf = tmp_buffer; - - - - if (from_user) { - - down (&tmp_buf_sem); - while (1) { - c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); - if (c <= 0) break; - - c -= copy_from_user (tmp_buf, buf, c); - if (!c) { - if (!ret) ret = -EFAULT; - break; - } - - save_flags (flags); - cli (); - - c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1)); - info->xmit_cnt += c; - - restore_flags(flags); - - buf += c; - count -= c; - ret += c; - } - - up (&tmp_buf_sem); - } else { - + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned long flags; + int c, ret = 0; + + if (!tty ) + return ret; + if (!info->xmit_buf) + return ret; + if (!tmp_buf) + tmp_buf = tmp_buffer; + + if (from_user) { + down (&tmp_buf_sem); + while (1) { + c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, + DZ_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + c -= copy_from_user (tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + + save_and_cli(flags); + + c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, + DZ_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + info->xmit_head = ((info->xmit_head + c) & + (DZ_XMIT_SIZE - 1)); + info->xmit_cnt += c; + restore_flags(flags); + + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + while (1) { + save_and_cli(flags); + + c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, + DZ_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + restore_flags (flags); + break; + } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (DZ_XMIT_SIZE-1)); + info->xmit_cnt += c; + restore_flags(flags); + + buf += c; + count -= c; + ret += c; + } + } - while (1) { - save_flags (flags); - cli (); - - c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - restore_flags (flags); - break; - } - memcpy (info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1)); - info->xmit_cnt += c; - - restore_flags (flags); - - buf += c; - count -= c; - ret += c; - } - } - - - if (info->xmit_cnt) - { - if (!tty->stopped) - { - if (!tty->hw_stopped) - { - dz_start (info->tty); - } + if (info->xmit_cnt) { + if (!tty->stopped) { + if (!tty->hw_stopped) { + dz_start (info->tty); + } + } } - } - return ret; + + return ret; } /* @@ -734,12 +770,14 @@ */ static int dz_write_room (struct tty_struct *tty) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; - int ret; - - ret = DZ_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) ret = 0; - return ret; + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + int ret; + + ret = DZ_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + + return ret; } /* @@ -751,9 +789,9 @@ */ static int dz_chars_in_buffer (struct tty_struct *tty) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; + struct dz_serial *info = (struct dz_serial *)tty->driver_data; - return info->xmit_cnt; + return info->xmit_cnt; } /* @@ -765,16 +803,17 @@ */ static void dz_flush_buffer (struct tty_struct *tty) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; + struct dz_serial *info = (struct dz_serial *)tty->driver_data; - cli (); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - sti (); - - wake_up_interruptible (&tty->write_wait); - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + sti(); + + wake_up_interruptible (&tty->write_wait); + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + tty->ldisc.write_wakeup(tty); } /* @@ -787,31 +826,32 @@ */ static void dz_throttle (struct tty_struct *tty) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; + struct dz_serial *info = (struct dz_serial *)tty->driver_data; - if (I_IXOFF(tty)) - info->x_char = STOP_CHAR(tty); + if (I_IXOFF(tty)) + info->x_char = STOP_CHAR(tty); } static void dz_unthrottle (struct tty_struct *tty) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; + struct dz_serial *info = (struct dz_serial *)tty->driver_data; - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - info->x_char = START_CHAR(tty); - } + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + info->x_char = START_CHAR(tty); + } } static void dz_send_xchar (struct tty_struct *tty, char ch) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; + struct dz_serial *info = (struct dz_serial *)tty->driver_data; - info->x_char = ch; + info->x_char = ch; - if (ch) dz_start (info->tty); + if (ch) + dz_start(info->tty); } /* @@ -819,59 +859,62 @@ * rs_ioctl () and friends * ------------------------------------------------------------ */ -static int get_serial_info (struct dz_serial *info, struct serial_struct *retinfo) +static int get_serial_info(struct dz_serial *info, + struct serial_struct *retinfo) { - struct serial_struct tmp; + struct serial_struct tmp; - if (!retinfo) - return -EFAULT; + if (!retinfo) + return -EFAULT; - memset (&tmp, 0, sizeof(tmp)); + memset (&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = info->port; - tmp.irq = SERIAL; - tmp.flags = info->flags; - tmp.baud_base = info->baud_base; - tmp.close_delay = info->close_delay; - tmp.closing_wait = info->closing_wait; - - return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->port; + tmp.irq = SERIAL; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + + return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; } -static int set_serial_info (struct dz_serial *info, struct serial_struct *new_info) +static int set_serial_info (struct dz_serial *info, + struct serial_struct *new_info) { - struct serial_struct new_serial; - struct dz_serial old_info; - int retval = 0; + struct serial_struct new_serial; + struct dz_serial old_info; + int retval = 0; - if (!new_info) - return -EFAULT; + if (!new_info) + return -EFAULT; - if(copy_from_user (&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - - old_info = *info; + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; + old_info = *info; - if (info->count > 1) - return -EBUSY; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud_base = new_serial.baud_base; - info->type = new_serial.type; - info->close_delay = new_serial.close_delay; - info->closing_wait = new_serial.closing_wait; + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ - retval = startup (info); - return retval; + info->baud_base = new_serial.baud_base; + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + + retval = startup(info); + + return retval; } /* @@ -886,9 +929,9 @@ */ static int get_lsr_info (struct dz_serial *info, unsigned int *value) { - unsigned short status = dz_in (info, DZ_LPR); + unsigned short status = dz_in (info, DZ_LPR); - return put_user (status, value); + return put_user (status, value); } /* @@ -896,106 +939,112 @@ */ static void send_break (struct dz_serial *info, int duration) { - unsigned long flags; - unsigned short tmp, mask; - - if (!info->port) - return; - - mask = 1 << info->line; - tmp = dz_in (info, DZ_TCR); - tmp |= mask; + unsigned long flags; + unsigned short tmp, mask; - current->state = TASK_INTERRUPTIBLE; + if (!info->port) + return; - save_flags (flags); - cli(); - - dz_out (info, DZ_TCR, tmp); - - schedule_timeout(duration); - - tmp &= ~mask; - dz_out (info, DZ_TCR, tmp); - - restore_flags (flags); -} - -static int dz_ioctl (struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct dz_serial * info = (struct dz_serial *)tty->driver_data; - int retval; + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); + tmp |= mask; + + current->state = TASK_INTERRUPTIBLE; + + save_and_cli(flags); + dz_out(info, DZ_TCR, tmp); + schedule_timeout(duration); + tmp &= ~mask; + dz_out(info, DZ_TCR, tmp); + restore_flags(flags); +} + +static int dz_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct dz_serial * info = (struct dz_serial *)tty->driver_data; + int retval; + + if (cmd != TIOCGSERIAL && cmd != TIOCSSERIAL && + cmd != TIOCSERCONFIG && cmd != TIOCSERGWILD && + cmd != TIOCSERSWILD && cmd != TIOCSERGSTRUCT) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && - (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change (tty); - if (retval) - return retval; - tty_wait_until_sent (tty, 0); - if (!arg) - send_break (info, HZ/4); /* 1/4 second */ - return 0; - - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change (tty); - if (retval) - return retval; - tty_wait_until_sent (tty, 0); - send_break (info, arg ? arg*(HZ/10) : HZ/4); - return 0; - - case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg); - - case TIOCSSOFTCAR: - if (get_user (arg, (unsigned long *)arg)) - return -EFAULT; - tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); - return 0; - - case TIOCGSERIAL: - 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 */ - return get_lsr_info (info, (unsigned int *)arg); - - case TIOCSERGSTRUCT: - return copy_to_user((struct dz_serial *)arg, info, - sizeof(struct dz_serial)) ? -EFAULT : 0; - - default: - return -ENOIOCTLCMD; - } + switch (cmd) { + case TCSBRK: /* SVID version: non-zero arg --> no break */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + if (!arg) + send_break(info, HZ/4); /* 1/4 second */ + return 0; + + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + 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); + return 0; + + case TIOCSSOFTCAR: + if (get_user (arg, (unsigned long *)arg)) + return -EFAULT; + + tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | + (arg ? CLOCAL : 0); + return 0; + + 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 */ + return get_lsr_info (info, (unsigned int *)arg); + + case TIOCSERGSTRUCT: + return copy_to_user((struct dz_serial *)arg, info, + sizeof(struct dz_serial)) ? -EFAULT : 0; + + default: + return -ENOIOCTLCMD; + } - return 0; + return 0; } static void dz_set_termios (struct tty_struct *tty, struct termios *old_termios) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; + struct dz_serial *info = (struct dz_serial *)tty->driver_data; - if (tty->termios->c_cflag == old_termios->c_cflag) - return; + if (tty->termios->c_cflag == old_termios->c_cflag) + return; - change_speed (info); + change_speed (info); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - dz_start (tty); - } + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + dz_start(tty); + } } /* @@ -1007,97 +1056,95 @@ * the transmit enable and receive enable flags. * ------------------------------------------------------------ */ -static void dz_close (struct tty_struct *tty, struct file *filp) +static void dz_close(struct tty_struct *tty, struct file *filp) { - struct dz_serial * info = (struct dz_serial *)tty->driver_data; - unsigned long flags; + struct dz_serial * info = (struct dz_serial *)tty->driver_data; + unsigned long flags; - if (!info) return; - - save_flags (flags); - cli(); - - if (tty_hung_up_p (filp)) { - restore_flags (flags); - return; - } - - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("dz_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } - - if (--info->count < 0) { - printk("ds_close: bad serial port count for ttys%d: %d\n", - info->line, info->count); - info->count = 0; - } - - if (info->count) { - restore_flags (flags); - return; - } - info->flags |= DZ_CLOSING; - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (info->flags & DZ_NORMAL_ACTIVE) - info->normal_termios = *tty->termios; - if (info->flags & DZ_CALLOUT_ACTIVE) - info->callout_termios = *tty->termios; - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - - if (info->closing_wait != DZ_CLOSING_WAIT_NONE) - tty_wait_until_sent (tty, info->closing_wait); - - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts. - */ - - shutdown (info); - - if (tty->driver.flush_buffer) - tty->driver.flush_buffer (tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer (tty); - tty->closing = 0; - info->event = 0; - info->tty = 0; - - if (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; - if (tty->ldisc.open) - (tty->ldisc.open)(tty); - } - if (info->blocked_open) { - if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); - } - wake_up_interruptible (&info->open_wait); - } + if (!info) + return; + + save_and_cli(flags); + + if (tty_hung_up_p(filp)) { + restore_flags(flags); + return; + } - info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING); - wake_up_interruptible (&info->close_wait); + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty structure + * will be freed. Info->count should always be one in these + * conditions. If it's greater than one, we've got real + * problems, since it means the serial port won't be shutdown. + */ + printk("dz_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } - restore_flags (flags); + if (--info->count < 0) { + printk("ds_close: bad serial port count for ttyS%02d: %d\n", + info->line, info->count); + info->count = 0; + } + + if (info->count) { + restore_flags(flags); + return; + } + info->flags |= DZ_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & DZ_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & DZ_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify the line + * discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + + if (info->closing_wait != DZ_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + + /* + * At this point we stop accepting input. To do this, we disable the + * receive line status interrupts. + */ + shutdown(info); + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer (tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer (tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + + if (tty->ldisc.num != ldiscs[N_TTY].num) { + if (tty->ldisc.close) + tty->ldisc.close(tty); + tty->ldisc = ldiscs[N_TTY]; + tty->termios->c_line = N_TTY; + if (tty->ldisc.open) + tty->ldisc.open(tty); + } + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + + info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING); + wake_up_interruptible(&info->close_wait); + + restore_flags(flags); } /* @@ -1105,15 +1152,15 @@ */ static void dz_hangup (struct tty_struct *tty) { - struct dz_serial *info = (struct dz_serial *)tty->driver_data; + struct dz_serial *info = (struct dz_serial *) tty->driver_data; - dz_flush_buffer (tty); - shutdown (info); - info->event = 0; - info->count = 0; - info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE); - info->tty = 0; - wake_up_interruptible (&info->open_wait); + dz_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); } /* @@ -1121,101 +1168,103 @@ * rs_open() and friends * ------------------------------------------------------------ */ -static int block_til_ready (struct tty_struct *tty, struct file *filp, struct dz_serial *info) +static int block_til_ready(struct tty_struct *tty, struct file *filp, + struct dz_serial *info) { - DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (info->flags & DZ_CLOSING) { - interruptible_sleep_on (&info->close_wait); - return -EAGAIN; - } - - /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { - if (info->flags & DZ_NORMAL_ACTIVE) - return -EBUSY; + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & DZ_CLOSING) { + interruptible_sleep_on(&info->close_wait); + return -EAGAIN; + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & DZ_NORMAL_ACTIVE) + return -EBUSY; - if ((info->flags & DZ_CALLOUT_ACTIVE) && - (info->flags & DZ_SESSION_LOCKOUT) && - (info->session != current->session)) - return -EBUSY; + if ((info->flags & DZ_CALLOUT_ACTIVE) && + (info->flags & DZ_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; - if ((info->flags & DZ_CALLOUT_ACTIVE) && - (info->flags & DZ_PGRP_LOCKOUT) && - (info->pgrp != current->pgrp)) - return -EBUSY; - info->flags |= DZ_CALLOUT_ACTIVE; - return 0; - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - if (info->flags & DZ_CALLOUT_ACTIVE) - return -EBUSY; - info->flags |= DZ_NORMAL_ACTIVE; - return 0; - } - - if (info->flags & DZ_CALLOUT_ACTIVE) { - if (info->normal_termios.c_cflag & CLOCAL) - do_clocal = 1; - } else { - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - } - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * dz_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue (&info->open_wait, &wait); - - info->count--; - info->blocked_open++; - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p (filp) || !(info->is_initialized)) { - retval = -EAGAIN; - break; - } - if (!(info->flags & DZ_CALLOUT_ACTIVE) && - !(info->flags & DZ_CLOSING) && do_clocal) - break; - if (signal_pending (current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } + if ((info->flags & DZ_CALLOUT_ACTIVE) && + (info->flags & DZ_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + + info->flags |= DZ_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, then make + * the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & DZ_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= DZ_NORMAL_ACTIVE; + + return 0; + } + + if (info->flags & DZ_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become free + * (i.e., not in use by the callout). While we are in this loop, + * info->count is dropped by one, so that dz_close() knows when to free + * things. We restore it upon exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); + + info->count--; + info->blocked_open++; + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p (filp) || !(info->is_initialized)) { + retval = -EAGAIN; + break; + } + if (!(info->flags & DZ_CALLOUT_ACTIVE) && + !(info->flags & DZ_CLOSING) && do_clocal) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } - current->state = TASK_RUNNING; - remove_wait_queue (&info->open_wait, &wait); - if (!tty_hung_up_p(filp)) - info->count++; - info->blocked_open--; - - if (retval) - return retval; - info->flags |= DZ_NORMAL_ACTIVE; - return 0; -} + current->state = TASK_RUNNING; + remove_wait_queue (&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; + + if (retval) + return retval; + info->flags |= DZ_NORMAL_ACTIVE; + return 0; +} /* * This routine is called whenever a serial port is opened. It @@ -1224,201 +1273,220 @@ */ static int dz_open (struct tty_struct *tty, struct file *filp) { - struct dz_serial *info; - int retval, line; - - line = MINOR(tty->device) - tty->driver.minor_start; - - /* The dz lines for the mouse/keyboard must be - * opened using their respective drivers. - */ - if ((line < 0) || (line >= DZ_NB_PORT)) - return -ENODEV; + struct dz_serial *info; + int retval, line; - if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE)) - return -ENODEV; + line = MINOR(tty->device) - tty->driver.minor_start; - info = lines[line]; - info->count++; - - tty->driver_data = info; - info->tty = tty; - - /* - * Start up serial port - */ - retval = startup (info); - if (retval) - return retval; + /* + * The dz lines for the mouse/keyboard must be opened using their + * respective drivers. + */ + if ((line < 0) || (line >= DZ_NB_PORT)) + return -ENODEV; + if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE)) + return -ENODEV; + info = lines[line]; + info->count++; - retval = block_til_ready (tty, filp, info); - if (retval) - return retval; + tty->driver_data = info; + info->tty = tty; - if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) - *tty->termios = info->normal_termios; - else - *tty->termios = info->callout_termios; - change_speed (info); + /* + * Start up serial port + */ + retval = startup (info); + if (retval) + return retval; + + retval = block_til_ready (tty, filp, info); + if (retval) + return retval; + + if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed(info); + } - } + info->session = current->session; + info->pgrp = current->pgrp; - info->session = current->session; - info->pgrp = current->pgrp; - return 0; + return 0; } static void show_serial_version (void) { - printk("%s%s\n", dz_name, dz_version); + printk("%s%s\n", dz_name, dz_version); } int __init dz_init(void) { - int i; - unsigned long flags; - struct dz_serial *info; - - /* Setup base handler, and timer table. */ - init_bh (SERIAL_BH, do_serial_bh); - - show_serial_version (); - - memset(&serial_driver, 0, sizeof(struct tty_driver)); - serial_driver.magic = TTY_DRIVER_MAGIC; - serial_driver.name = "ttyS"; - serial_driver.major = TTY_MAJOR; - serial_driver.minor_start = 64; - serial_driver.num = DZ_NB_PORT; - serial_driver.type = TTY_DRIVER_TYPE_SERIAL; - serial_driver.subtype = SERIAL_TYPE_NORMAL; - serial_driver.init_termios = tty_std_termios; - - serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver.flags = TTY_DRIVER_REAL_RAW; - serial_driver.refcount = &serial_refcount; - serial_driver.table = serial_table; - serial_driver.termios = serial_termios; - serial_driver.termios_locked = serial_termios_locked; - - serial_driver.open = dz_open; - serial_driver.close = dz_close; - serial_driver.write = dz_write; - serial_driver.flush_chars = dz_flush_chars; - serial_driver.write_room = dz_write_room; - serial_driver.chars_in_buffer = dz_chars_in_buffer; - serial_driver.flush_buffer = dz_flush_buffer; - serial_driver.ioctl = dz_ioctl; - serial_driver.throttle = dz_throttle; - serial_driver.unthrottle = dz_unthrottle; - serial_driver.send_xchar = dz_send_xchar; - serial_driver.set_termios = dz_set_termios; - serial_driver.stop = dz_stop; - serial_driver.start = dz_start; - serial_driver.hangup = dz_hangup; - - /* - * The callout device is just like normal device except for - * major number and the subtype code. - */ - callout_driver = serial_driver; - callout_driver.name = "cua"; - callout_driver.major = TTYAUX_MAJOR; - callout_driver.subtype = SERIAL_TYPE_CALLOUT; - - if (tty_register_driver (&serial_driver)) - panic("Couldn't register serial driver\n"); - if (tty_register_driver (&callout_driver)) - panic("Couldn't register callout driver\n"); - save_flags(flags); cli(); - - for (i=0; i < DZ_NB_PORT; i++) - { - info = &multi[i]; - lines[i] = info; - info->magic = SERIAL_MAGIC; - - if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) - info->port = (unsigned long) KN01_DZ11_BASE; - else - info->port = (unsigned long) KN02_DZ11_BASE; - - info->line = i; - info->tty = 0; - info->close_delay = 50; - info->closing_wait = 3000; - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->tqueue.routine = do_softint; - info->tqueue.data = info; - info->tqueue_hangup.routine = do_serial_hangup; - info->tqueue_hangup.data = info; - 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); - - /* If we are pointing to address zero then punt - not correctly - set up in setup.c to handle this. */ - if (! info->port) - return 0; + int i, flags; + struct dz_serial *info; - printk("ttyS%02d at 0x%04x (irq = %d)\n", info->line, info->port, SERIAL); - } + /* Setup base handler, and timer table. */ + init_bh(SERIAL_BH, do_serial_bh); - /* reset the chip */ + show_serial_version(); + + 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 = "ttyS"; +#else + serial_driver.name = "tts/%d"; +#endif + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = DZ_NB_PORT; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + + serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | + CLOCAL; + 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; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = dz_open; + serial_driver.close = dz_close; + serial_driver.write = dz_write; + serial_driver.flush_chars = dz_flush_chars; + serial_driver.write_room = dz_write_room; + serial_driver.chars_in_buffer = dz_chars_in_buffer; + serial_driver.flush_buffer = dz_flush_buffer; + serial_driver.ioctl = dz_ioctl; + serial_driver.throttle = dz_throttle; + serial_driver.unthrottle = dz_unthrottle; + serial_driver.send_xchar = dz_send_xchar; + serial_driver.set_termios = dz_set_termios; + serial_driver.stop = dz_stop; + serial_driver.start = dz_start; + serial_driver.hangup = dz_hangup; + + /* + * The callout device is just like normal device except for major + * number and the subtype code. + */ + callout_driver = serial_driver; +#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) + callout_driver.name = "cua"; +#else + callout_driver.name = "cua/%d"; +#endif + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if (tty_register_driver (&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver (&callout_driver)) + panic("Couldn't register callout driver\n"); + + save_flags(flags); cli(); + for (i=0; i < DZ_NB_PORT; i++) { + info = &multi[i]; + lines[i] = info; + info->magic = SERIAL_MAGIC; + + if ((mips_machtype == MACH_DS23100) || + (mips_machtype == MACH_DS5100)) + info->port = (unsigned long) KN01_DZ11_BASE; + else + info->port = (unsigned long) KN02_DZ11_BASE; + + info->line = i; + info->tty = 0; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->tqueue_hangup.routine = do_serial_hangup; + info->tqueue_hangup.data = info; + 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); + + /* + * If we are pointing to address zero then punt - not correctly + * set up in setup.c to handle this. + */ + if (! info->port) + return 0; + + printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line, + info->port, SERIAL); + + tty_register_devfs(&serial_driver, 0, + serial_driver.minor_start + info->line); + tty_register_devfs(&callout_driver, 0, + callout_driver.minor_start + info->line); + } + + /* Reset the chip */ #ifndef CONFIG_SERIAL_CONSOLE - dz_out(info, DZ_CSR, DZ_CLR); - while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR) ; - wbflush(); + { + int tmp; + dz_out(info, DZ_CSR, DZ_CLR); + while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR); + wbflush(); - /* enable scanning */ - dz_out(info, DZ_CSR, DZ_MSE); + /* Enable scanning */ + dz_out(info, DZ_CSR, DZ_MSE); + } #endif - /* order matters here... the trick is that flags - is updated... in request_irq - to immediatedly obliterate - it is unwise. */ - restore_flags(flags); - + /* + * Order matters here... the trick is that flags is updated... in + * request_irq - to immediatedly obliterate it is unwise. + */ + restore_flags(flags); - if (request_irq (SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0])) - panic ("Unable to register DZ interrupt\n"); + if (request_irq(SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0])) + panic("Unable to register DZ interrupt\n"); - return 0; + return 0; } #ifdef CONFIG_SERIAL_CONSOLE static void dz_console_put_char (unsigned char ch) { - unsigned long flags; - int loops = 2500; - unsigned short tmp = ch; - /* this code sends stuff out to serial device - spinning its - wheels and waiting. */ + unsigned long flags; + int loops = 2500; + unsigned short tmp = ch; + /* + * this code sends stuff out to serial device - spinning its wheels and + * waiting. + */ - /* force the issue - point it at lines[3]*/ - dz_console=&multi[CONSOLE_LINE]; + /* force the issue - point it at lines[3]*/ + dz_console = &multi[CONSOLE_LINE]; - save_flags(flags); - cli(); - + save_and_cli(flags); - /* spin our wheels */ - while (((dz_in(dz_console,DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--) - ; + /* spin our wheels */ + while (((dz_in(dz_console, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--) + ; - /* Actually transmit the character. */ - dz_out (dz_console, DZ_TDR, tmp); + /* Actually transmit the character. */ + dz_out(dz_console, DZ_TDR, tmp); - restore_flags(flags); + restore_flags(flags); } + /* * ------------------------------------------------------------------- * dz_console_print () @@ -1432,19 +1500,18 @@ unsigned int count) { #ifdef DEBUG_DZ - prom_printf((char *)str); + prom_printf((char *)str); #endif - while (count--) - { - if (*str == '\n') - dz_console_put_char ('\r'); - dz_console_put_char (*str++); - } + while (count--) { + if (*str == '\n') + dz_console_put_char('\r'); + dz_console_put_char(*str++); + } } static int dz_console_wait_key(struct console *co) { - return 0; + return 0; } static kdev_t dz_console_device(struct console *c) @@ -1454,17 +1521,17 @@ static int __init dz_console_setup(struct console *co, char *options) { - int baud = 9600; - int bits = 8; - int parity = 'n'; - int cflag = CREAD | HUPCL | CLOCAL; - char *s; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + char *s; unsigned short mask,tmp; if (options) { baud = simple_strtoul(options, NULL, 10); s = options; - while(*s >= '0' && *s <= '9') + while (*s >= '0' && *s <= '9') s++; if (*s) parity = *s++; @@ -1473,9 +1540,9 @@ } /* - * Now construct a cflag setting. + * Now construct a cflag setting. */ - switch(baud) { + switch (baud) { case 1200: cflag |= DZ_B1200; break; @@ -1490,7 +1557,7 @@ cflag |= DZ_B9600; break; } - switch(bits) { + switch (bits) { case 7: cflag |= DZ_CS7; break; @@ -1499,11 +1566,13 @@ cflag |= DZ_CS8; break; } - switch(parity) { - case 'o': case 'O': + switch (parity) { + case 'o': + case 'O': cflag |= DZ_PARODD; break; - case 'e': case 'E': + case 'e': + case 'E': cflag |= DZ_PARENB; break; } @@ -1511,45 +1580,44 @@ /* TOFIX: force to console line */ dz_console = &multi[CONSOLE_LINE]; - if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) - dz_console->port = KN01_DZ11_BASE; - else - dz_console->port = KN02_DZ11_BASE; + if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) + dz_console->port = KN01_DZ11_BASE; + else + dz_console->port = KN02_DZ11_BASE; dz_console->line = CONSOLE_LINE; dz_out(dz_console, DZ_CSR, DZ_CLR); while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR) - ; + ; /* enable scanning */ dz_out(dz_console, DZ_CSR, DZ_MSE); - /* Set up flags... */ + /* Set up flags... */ dz_console->cflags = 0; dz_console->cflags |= DZ_B9600; dz_console->cflags |= DZ_CS8; dz_console->cflags |= DZ_PARENB; - dz_out (dz_console, DZ_LPR, dz_console->cflags); + dz_out(dz_console, DZ_LPR, dz_console->cflags); mask = 1 << dz_console->line; - tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */ + tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */ if (!(tmp & mask)) { - tmp |= mask; /* set the TX flag */ - dz_out (dz_console, DZ_TCR, tmp); + tmp |= mask; /* set the TX flag */ + dz_out (dz_console, DZ_TCR, tmp); } - return 0; } static struct console dz_sercons = { - name: "ttyS", - write: dz_console_print, - device: dz_console_device, - wait_key: dz_console_wait_key, - setup: dz_console_setup, - flags: CON_CONSDEV | CON_PRINTBUFFER, - index: CONSOLE_LINE, + name: "ttyS", + write: dz_console_print, + device: dz_console_device, + wait_key: dz_console_wait_key, + setup: dz_console_setup, + flags: CON_CONSDEV | CON_PRINTBUFFER, + index: CONSOLE_LINE, }; void __init dz_serial_console_init(void) @@ -1559,3 +1627,4 @@ #endif /* ifdef CONFIG_SERIAL_CONSOLE */ +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/ec3104_keyb.c linux/drivers/char/ec3104_keyb.c --- v2.4.9/linux/drivers/char/ec3104_keyb.c Fri Apr 13 20:31:32 2001 +++ linux/drivers/char/ec3104_keyb.c Thu Sep 13 15:21:32 2001 @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/char/efirtc.c linux/drivers/char/efirtc.c --- v2.4.9/linux/drivers/char/efirtc.c Mon Sep 18 14:57:01 2000 +++ linux/drivers/char/efirtc.c Thu Sep 13 15:21:32 2001 @@ -403,3 +403,5 @@ module_init(efi_rtc_init); module_exit(efi_rtc_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.4.9/linux/drivers/char/epca.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/char/epca.c Sun Sep 9 10:43:02 2001 @@ -610,9 +610,7 @@ ASYNC_CALLOUT_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&ch->close_wait); -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif restore_flags(flags); @@ -700,10 +698,8 @@ shutdown(ch); -#ifdef MODULE if (ch->count) MOD_DEC_USE_COUNT; -#endif /* MODULE */ ch->tty = NULL; @@ -1397,12 +1393,9 @@ return(-ENODEV); } -#ifdef MODULE MOD_INC_USE_COUNT; -#endif - ch = &digi_channels[line]; boardnum = ch->boardnum; @@ -4106,3 +4099,5 @@ } /* End init_PCI */ #endif /* ENABLE_PCI */ + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/esp.c linux/drivers/char/esp.c --- v2.4.9/linux/drivers/char/esp.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/esp.c Thu Sep 13 15:21:32 2001 @@ -83,6 +83,8 @@ static unsigned int rx_timeout = ESP_RX_TMOUT; static unsigned int pio_threshold = ESP_PIO_THRESHOLD; +MODULE_LICENSE("GPL"); + MODULE_PARM(irq, "1-8i"); MODULE_PARM(divisor, "1-8i"); MODULE_PARM(dma, "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/ftape/compressor/zftape-compress.c linux/drivers/char/ftape/compressor/zftape-compress.c --- v2.4.9/linux/drivers/char/ftape/compressor/zftape-compress.c Tue Nov 23 10:29:15 1999 +++ linux/drivers/char/ftape/compressor/zftape-compress.c Thu Sep 13 15:21:32 2001 @@ -1258,14 +1258,13 @@ TRACE_EXIT 0; } - #ifdef MODULE -#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18) + MODULE_AUTHOR( "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de"); MODULE_DESCRIPTION( "Compression routines for zftape. Uses the lzrw3 algorithm by Ross Williams"); -#endif +MODULE_LICENSE("GPL"); #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18) static int can_unload(void) diff -u --recursive --new-file v2.4.9/linux/drivers/char/ftape/lowlevel/ftape-calibr.c linux/drivers/char/ftape/lowlevel/ftape-calibr.c --- v2.4.9/linux/drivers/char/ftape/lowlevel/ftape-calibr.c Fri Sep 22 14:21:16 2000 +++ linux/drivers/char/ftape/lowlevel/ftape-calibr.c Fri Sep 14 14:40:00 2001 @@ -31,7 +31,7 @@ #include #if defined(__alpha__) # include -#elif defined(__i386__) +#elif defined(__i386__) || defined(__x86_64__) # include #endif #include @@ -41,7 +41,7 @@ #undef DEBUG -#if !defined(__alpha__) && !defined(__i386__) +#if !defined(__alpha__) && !defined(__i386__) && !defined(__x86_64__) # error Ftape is not implemented for this architecture! #endif @@ -70,7 +70,7 @@ asm volatile ("rpcc %0" : "=r" (r)); return r; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__x86_64__) unsigned long flags; __u16 lo; __u16 hi; @@ -90,7 +90,7 @@ { #if defined(__alpha__) return ftape_timestamp(); -#elif defined(__i386__) +#elif defined(__i386__) || defined(__x86_64__) unsigned int count; unsigned long flags; @@ -108,7 +108,7 @@ { #if defined(__alpha__) return (t1 <= t0) ? t1 + (1UL << 32) - t0 : t1 - t0; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__x86_64__) /* * This is tricky: to work for both short and full ftape_timestamps * we'll have to discriminate between these. @@ -124,7 +124,7 @@ { #if defined(__alpha__) return (ps_per_cycle * count) / 1000000UL; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__x86_64__) return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100); #endif } @@ -164,7 +164,7 @@ static void init_clock(void) { -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) unsigned int t; int i; TRACE_FUN(ft_t_any); @@ -214,7 +214,7 @@ unsigned int tc = 0; unsigned int count; unsigned int time; -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) unsigned int old_tc = 0; unsigned int old_count = 1; unsigned int old_time = 1; @@ -265,7 +265,7 @@ if (time >= 100*1000) { break; } -#elif defined(__i386__) +#elif defined(__i386__) || defined(__x86_64__) /* * increase the count until the resulting time nears 2/HZ, * then the tc will drop sharply because we lose LATCH counts. diff -u --recursive --new-file v2.4.9/linux/drivers/char/ftape/lowlevel/ftape-init.c linux/drivers/char/ftape/lowlevel/ftape-init.c --- v2.4.9/linux/drivers/char/ftape/lowlevel/ftape-init.c Tue Nov 23 10:29:15 1999 +++ linux/drivers/char/ftape/lowlevel/ftape-init.c Thu Sep 13 15:21:32 2001 @@ -153,6 +153,7 @@ "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)"); MODULE_DESCRIPTION( "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives."); +MODULE_LICENSE("GPL"); #endif /* Called by modules package when installing the driver diff -u --recursive --new-file v2.4.9/linux/drivers/char/ftape/zftape/zftape-init.c linux/drivers/char/ftape/zftape/zftape-init.c --- v2.4.9/linux/drivers/char/ftape/zftape/zftape-init.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/ftape/zftape/zftape-init.c Thu Sep 13 15:21:32 2001 @@ -59,6 +59,7 @@ "Support for QIC-113 compatible volume table " "and builtin compression (lzrw3 algorithm)"); MODULE_SUPPORTED_DEVICE("char-major-27"); +MODULE_LICENSE("GPL"); /* Global vars. */ diff -u --recursive --new-file v2.4.9/linux/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c --- v2.4.9/linux/drivers/char/generic_serial.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/generic_serial.c Thu Sep 13 15:21:32 2001 @@ -1088,3 +1088,5 @@ EXPORT_SYMBOL(gs_setserial); EXPORT_SYMBOL(gs_getserial); EXPORT_SYMBOL(gs_got_break); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/h8.c linux/drivers/char/h8.c --- v2.4.9/linux/drivers/char/h8.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/h8.c Thu Sep 13 15:21:32 2001 @@ -1176,3 +1176,6 @@ h8_event_mask &= (~mask); restore_flags(flags); } + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/hp600_keyb.c linux/drivers/char/hp600_keyb.c --- v2.4.9/linux/drivers/char/hp600_keyb.c Wed Apr 11 21:24:52 2001 +++ linux/drivers/char/hp600_keyb.c Thu Sep 13 15:21:32 2001 @@ -336,3 +336,4 @@ #endif +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c --- v2.4.9/linux/drivers/char/i810-tco.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/i810-tco.c Thu Sep 13 15:21:32 2001 @@ -363,3 +363,5 @@ module_init(watchdog_init); module_exit(watchdog_cleanup); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/ip2.c linux/drivers/char/ip2.c --- v2.4.9/linux/drivers/char/ip2.c Thu Apr 12 12:16:35 2001 +++ linux/drivers/char/ip2.c Thu Sep 13 15:21:32 2001 @@ -71,6 +71,8 @@ { } +MODULE_LICENSE("GPL"); + #else // !MODULE #ifndef NULL diff -u --recursive --new-file v2.4.9/linux/drivers/char/ip2main.c linux/drivers/char/ip2main.c --- v2.4.9/linux/drivers/char/ip2main.c Fri Feb 16 16:02:35 2001 +++ linux/drivers/char/ip2main.c Thu Sep 13 15:21:32 2001 @@ -418,6 +418,7 @@ rirqs[iindx++] = irq; } +#ifdef MODULE static int __init clear_requested_irq( char irq ) { @@ -430,6 +431,7 @@ } return 0; } +#endif static int __init have_requested_irq( char irq ) diff -u --recursive --new-file v2.4.9/linux/drivers/char/isicom.c linux/drivers/char/isicom.c --- v2.4.9/linux/drivers/char/isicom.c Fri Apr 6 10:42:55 2001 +++ linux/drivers/char/isicom.c Thu Sep 13 15:21:32 2001 @@ -1927,6 +1927,7 @@ MODULE_AUTHOR("MultiTech"); MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); +MODULE_LICENSE("GPL"); MODULE_PARM(io, "1-4i"); MODULE_PARM_DESC(io, "I/O ports for the cards"); MODULE_PARM(irq, "1-4i"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/ite_gpio.c linux/drivers/char/ite_gpio.c --- v2.4.9/linux/drivers/char/ite_gpio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/ite_gpio.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,430 @@ +/* + * FILE NAME ite_gpio.c + * + * BRIEF MODULE DESCRIPTION + * API for ITE GPIO device. + * Driver for ITE GPIO device. + * + * Author: MontaVista Software, Inc. + * Hai-Pao Fan + * + * Copyright 2001 MontaVista Software 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 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ite_gpio_base 0x14013800 + +#define ITE_GPADR (*(volatile __u8 *)(0x14013800 + KSEG1)) +#define ITE_GPBDR (*(volatile __u8 *)(0x14013808 + KSEG1)) +#define ITE_GPCDR (*(volatile __u8 *)(0x14013810 + KSEG1)) +#define ITE_GPACR (*(volatile __u16 *)(0x14013802 + KSEG1)) +#define ITE_GPBCR (*(volatile __u16 *)(0x1401380a + KSEG1)) +#define ITE_GPCCR (*(volatile __u16 *)(0x14013812 + KSEG1)) +#define ITE_GPAICR (*(volatile __u16 *)(0x14013804 + KSEG1)) +#define ITE_GPBICR (*(volatile __u16 *)(0x1401380c + KSEG1)) +#define ITE_GPCICR (*(volatile __u16 *)(0x14013814 + KSEG1)) +#define ITE_GPAISR (*(volatile __u8 *)(0x14013806 + KSEG1)) +#define ITE_GPBISR (*(volatile __u8 *)(0x1401380e + KSEG1)) +#define ITE_GPCISR (*(volatile __u8 *)(0x14013816 + KSEG1)) +#define ITE_GCR (*(volatile __u8 *)(0x14013818 + KSEG1)) + +#define MAX_GPIO_LINE 21 +static int ite_gpio_irq=IT8172_GPIO_IRQ; + +static long ite_irq_counter[MAX_GPIO_LINE]; +wait_queue_head_t ite_gpio_wait[MAX_GPIO_LINE]; +static int ite_gpio_irq_pending[MAX_GPIO_LINE]; + +static int ite_gpio_debug=0; +#define DEB(x) if (ite_gpio_debug>=1) x + +int ite_gpio_in(__u32 device, __u32 mask, volatile __u32 *data) +{ + DEB(printk("ite_gpio_in mask=0x%x\n",mask)); + + switch (device) { + case ITE_GPIO_PORTA: + ITE_GPACR = (__u16)mask; /* 0xffff */ + *data = ITE_GPADR; + break; + case ITE_GPIO_PORTB: + ITE_GPBCR = (__u16)mask; /* 0xffff */ + *data = ITE_GPBDR; + break; + case ITE_GPIO_PORTC: + ITE_GPCCR = (__u16)mask; /* 0x03ff */ + *data = ITE_GPCDR; + break; + default: + return -EFAULT; + } + + return 0; +} + + +int ite_gpio_out(__u32 device, __u32 mask, __u32 data) +{ + switch (device) { + case ITE_GPIO_PORTA: + ITE_GPACR = (__u16)mask; /* 0x5555 */ + ITE_GPADR = (__u8)data; + break; + case ITE_GPIO_PORTB: + ITE_GPBCR = (__u16)mask; /* 0x5555 */ + ITE_GPBDR = (__u8)data; + break; + case ITE_GPIO_PORTC: + ITE_GPCCR = (__u16)mask; /* 0x0155 */ + ITE_GPCDR = (__u8)data; + break; + default: + return -EFAULT; + } + + return 0; +} + +int ite_gpio_int_ctrl(__u32 device, __u32 mask, __u32 data) +{ + switch (device) { + case ITE_GPIO_PORTA: + ITE_GPAICR = (ITE_GPAICR & ~mask) | (data & mask); + break; + case ITE_GPIO_PORTB: + ITE_GPBICR = (ITE_GPBICR & ~mask) | (data & mask); + break; + case ITE_GPIO_PORTC: + ITE_GPCICR = (ITE_GPCICR & ~mask) | (data & mask); + break; + default: + return -EFAULT; + } + + return 0; +} + +int ite_gpio_in_status(__u32 device, __u32 mask, volatile __u32 *data) +{ + int ret=-1; + + if (MAX_GPIO_LINE > *data >= 0) + ret=ite_gpio_irq_pending[*data]; + + DEB(printk("ite_gpio_in_status %d ret=%d\n",*data, ret)); + + switch (device) { + case ITE_GPIO_PORTA: + *data = ITE_GPAISR & mask; + break; + case ITE_GPIO_PORTB: + *data = ITE_GPBISR & mask; + break; + case ITE_GPIO_PORTC: + *data = ITE_GPCISR & mask; + break; + default: + return -EFAULT; + } + + return ret; +} + +int ite_gpio_out_status(__u32 device, __u32 mask, __u32 data) +{ + switch (device) { + case ITE_GPIO_PORTA: + ITE_GPAISR = (ITE_GPAISR & ~mask) | (data & mask); + break; + case ITE_GPIO_PORTB: + ITE_GPBISR = (ITE_GPBISR & ~mask) | (data & mask); + break; + case ITE_GPIO_PORTC: + ITE_GPCISR = (ITE_GPCISR & ~mask) | (data & mask); + break; + default: + return -EFAULT; + } + + return 0; +} + +int ite_gpio_gen_ctrl(__u32 device, __u32 mask, __u32 data) +{ + ITE_GCR = (ITE_GCR & ~mask) | (data & mask); + + return 0; +} + +int ite_gpio_int_wait (__u32 device, __u32 mask, __u32 data) +{ + int i,line=0, ret=0; + unsigned long flags; + + switch (device) { + case ITE_GPIO_PORTA: + line = data & mask; + break; + case ITE_GPIO_PORTB: + line = (data & mask) <<8; + break; + case ITE_GPIO_PORTC: + line = (data & mask) <<16; + break; + } + for (i=MAX_GPIO_LINE-1; i >= 0; i--) { + if ( (line) & (1 << i)) + break; + } + + DEB(printk("wait device=0x%d mask=0x%x data=0x%x index %d\n", + device, mask, data, i)); + + if (line & ~(1<i_rdev); + if (minor != GPIO_MINOR) + return -ENODEV; + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + + return 0; +} + + +static int ite_gpio_release(struct inode *inode, struct file *file) +{ + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + + return 0; +} + + +static int ite_gpio_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + + static struct ite_gpio_ioctl_data ioctl_data; + + if (copy_from_user(&ioctl_data, (struct ite_gpio_ioctl_data *)arg, + sizeof(ioctl_data))) + return -EFAULT; + if ((ioctl_data.device < ITE_GPIO_PORTA) || + (ioctl_data.device > ITE_GPIO_PORTC) ) + return -EFAULT; + + switch(cmd) { + case ITE_GPIO_IN: + if (ite_gpio_in(ioctl_data.device, ioctl_data.mask, + &ioctl_data.data)) + return -EFAULT; + + if (copy_to_user((struct ite_gpio_ioctl_data *)arg, + &ioctl_data, sizeof(ioctl_data))) + return -EFAULT; + break; + + case ITE_GPIO_OUT: + return ite_gpio_out(ioctl_data.device, + ioctl_data.mask, ioctl_data.data); + break; + + case ITE_GPIO_INT_CTRL: + return ite_gpio_int_ctrl(ioctl_data.device, + ioctl_data.mask, ioctl_data.data); + break; + + case ITE_GPIO_IN_STATUS: + if (ite_gpio_in_status(ioctl_data.device, ioctl_data.mask, + &ioctl_data.data)) + return -EFAULT; + if (copy_to_user((struct ite_gpio_ioctl_data *)arg, + &ioctl_data, sizeof(ioctl_data))) + return -EFAULT; + break; + + case ITE_GPIO_OUT_STATUS: + return ite_gpio_out_status(ioctl_data.device, + ioctl_data.mask, ioctl_data.data); + break; + + case ITE_GPIO_GEN_CTRL: + return ite_gpio_gen_ctrl(ioctl_data.device, + ioctl_data.mask, ioctl_data.data); + break; + + case ITE_GPIO_INT_WAIT: + return ite_gpio_int_wait(ioctl_data.device, + ioctl_data.mask, ioctl_data.data); + break; + + default: + return -ENOIOCTLCMD; + + } + return 0; +} + +static void ite_gpio_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs) +{ + int i,line; + + line = ITE_GPCISR & 0x1f; + for (i=4; i >=0; i--) { + if ( line & (1 << i)) { + ++ite_irq_counter[i+16]; + ite_gpio_irq_pending[i+16] = 2; + wake_up_interruptible(&ite_gpio_wait[i+16]); + +DEB(printk("interrupt 0x%x %d\n", &ite_gpio_wait[i+16], i+16)); + + ITE_GPCISR = ITE_GPCISR & (1<= 0; i--) { + if ( line & (1 << i)) { + ++ite_irq_counter[i+8]; + ite_gpio_irq_pending[i+8] = 2; + wake_up_interruptible(&ite_gpio_wait[i+8]); + +DEB(printk("interrupt 0x%x %d\n",ITE_GPBISR, i+8)); + + ITE_GPBISR = ITE_GPBISR & (1<= 0; i--) { + if ( line & (1 << i)) { + ++ite_irq_counter[i]; + ite_gpio_irq_pending[i] = 2; + wake_up_interruptible(&ite_gpio_wait[i]); + +DEB(printk("interrupt 0x%x %d\n",ITE_GPAISR, i)); + + ITE_GPAISR = ITE_GPAISR & (1<driver; + struct a3d *a3d = gameport->private; int i; for (i = 0; i < 4; i++) axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1; @@ -205,7 +205,7 @@ int a3d_adc_open(struct gameport *gameport, int mode) { - struct a3d *a3d = gameport->driver; + struct a3d *a3d = gameport->private; if (mode != GAMEPORT_MODE_COOKED) return -1; if (!a3d->used++) @@ -219,7 +219,7 @@ static void a3d_adc_close(struct gameport *gameport) { - struct a3d *a3d = gameport->driver; + struct a3d *a3d = gameport->private; if (!--a3d->used) del_timer(&a3d->timer); } @@ -323,12 +323,11 @@ a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE); - a3d->adc.driver = a3d; + a3d->adc.private = a3d; a3d->adc.open = a3d_adc_open; a3d->adc.close = a3d_adc_close; a3d->adc.cooked_read = a3d_adc_cooked_read; a3d->adc.fuzz = 1; - a3d->adc.type = GAMEPORT_EXT; a3d_read(a3d, data); @@ -385,3 +384,5 @@ module_init(a3d_init); module_exit(a3d_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/adi.c linux/drivers/char/joystick/adi.c --- v2.4.9/linux/drivers/char/joystick/adi.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/adi.c Wed Sep 12 15:34:06 2001 @@ -553,3 +553,5 @@ module_init(adi_init); module_exit(adi_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/amijoy.c linux/drivers/char/joystick/amijoy.c --- v2.4.9/linux/drivers/char/joystick/amijoy.c Fri Feb 16 16:02:35 2001 +++ linux/drivers/char/joystick/amijoy.c Wed Sep 12 15:34:06 2001 @@ -42,6 +42,7 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_PARM(amijoy, "1-2i"); +MODULE_LICENSE("GPL"); static int amijoy[2] = { 0, 1 }; static int amijoy_used[2] = { 0, 0 }; diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/analog.c linux/drivers/char/joystick/analog.c --- v2.4.9/linux/drivers/char/joystick/analog.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/analog.c Fri Sep 14 14:40:00 2001 @@ -39,9 +39,11 @@ #include #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Analog joystick and gamepad driver for Linux"); +MODULE_LICENSE("GPL"); /* * Option parsing. @@ -135,27 +137,25 @@ */ #ifdef __i386__ -#ifdef CONFIG_X86_TSC -#define GET_TIME(x) __asm__ __volatile__ ( "rdtsc" : "=a" (x) : : "dx" ) +#define TSC_PRESENT (test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability)) +#define GET_TIME(x) do { if (TSC_PRESENT) rdtscl(x); else outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0) +#define DELTA(x,y) (TSC_PRESENT?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0))) +#define TIME_NAME (TSC_PRESENT?"TSC":"PIT") +#elif __x86_64__ +#define GET_TIME(x) rdtscl(x) #define DELTA(x,y) ((y)-(x)) -#define TIME_NAME "TSC" -#else -#define GET_TIME(x) do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0) -#define DELTA(x,y) ((x)-(y)+((x)<(y)?1193180L/HZ:0)) -#define TIME_NAME "PIT" -#endif +#define TIME_NAME "TSC" #elif __alpha__ -#define GET_TIME(x) __asm__ __volatile__ ( "rpcc %0" : "=r" (x) ) +#define GET_TIME(x) get_cycles(x) #define DELTA(x,y) ((y)-(x)) -#define TIME_NAME "PCC" -#endif - -#ifndef GET_TIME +#define TIME_NAME "PCC" +#else #define FAKE_TIME static unsigned long analog_faketime = 0; #define GET_TIME(x) do { x = analog_faketime++; } while(0) #define DELTA(x,y) ((y)-(x)) -#define TIME_NAME "Unreliable" +#define TIME_NAME "Unreliable" +#warning Precise timer not defined for this architecture. #endif /* @@ -497,7 +497,7 @@ if (port->cooked) printk(" [ADC port]\n"); else - printk(" ["TIME_NAME" timer, %d %sHz clock, %d ns res]\n", + printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME, port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed, port->speed > 10000 ? "M" : "k", (port->loop * 1000000) / port->speed); } diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/cobra.c linux/drivers/char/joystick/cobra.c --- v2.4.9/linux/drivers/char/joystick/cobra.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/cobra.c Wed Sep 12 15:34:06 2001 @@ -248,3 +248,5 @@ module_init(cobra_init); module_exit(cobra_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/cs461x.c linux/drivers/char/joystick/cs461x.c --- v2.4.9/linux/drivers/char/joystick/cs461x.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/cs461x.c Wed Sep 12 15:34:06 2001 @@ -10,21 +10,24 @@ #include #include +#include #include #include #include #include MODULE_AUTHOR("Victor Krapivin "); +MODULE_LICENSE("GPL"); /* These options are experimental -#define COOKED_MODE #define CS461X_FULL_MAP - */ +#define COOKED_MODE + + #ifndef PCI_VENDOR_ID_CIRRUS #define PCI_VENDOR_ID_CIRRUS 0x1013 #endif @@ -281,8 +284,6 @@ } memset(port, 0, sizeof(struct gameport)); - port->io = -1; - port->size = -1; pdev->driver_data = port; port->open = cs461x_gameport_open; @@ -297,9 +298,8 @@ gameport_register_port(port); - printk(KERN_INFO "gameport%d: CS461x PCI", port->number); - if (port->size > 1) printk(" size %d", port->size); - printk(" speed %d kHz\n", port->speed); + printk(KERN_INFO "gameport%d: CS461x Gameport speed %d kHz\n", + port->number, port->speed); return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/db9.c linux/drivers/char/joystick/db9.c --- v2.4.9/linux/drivers/char/joystick/db9.c Mon Aug 14 13:55:01 2000 +++ linux/drivers/char/joystick/db9.c Wed Sep 12 15:34:06 2001 @@ -41,6 +41,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_LICENSE("GPL"); MODULE_PARM(db9, "2i"); MODULE_PARM(db9_2, "2i"); MODULE_PARM(db9_3, "2i"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/emu10k1-gp.c linux/drivers/char/joystick/emu10k1-gp.c --- v2.4.9/linux/drivers/char/joystick/emu10k1-gp.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/joystick/emu10k1-gp.c Wed Sep 12 15:34:06 2001 @@ -0,0 +1,125 @@ +/* + * $Id: emu10k1-gp.c,v 1.2 2001/04/24 07:48:56 vojtech Exp $ + * + * Copyright (c) 2001 Vojtech Pavlik + * + * Sponsored by SuSE + */ + +/* + * EMU10k1 - SB Live! - gameport driver for Linux + */ + +/* + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_LICENSE("GPL"); + +struct emu { + struct pci_dev *dev; + struct emu *next; + struct gameport gameport; + int size; +}; + +static struct pci_device_id emu_tbl[] __devinitdata = { + { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live! gameport */ + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, emu_tbl); + +static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int ioport, iolen; + int rc; + struct emu *port; + + rc = pci_enable_device(pdev); + if (rc) { + printk(KERN_ERR "emu10k1-gp: Cannot enable emu10k1 gameport (bus %d, devfn %d) error=%d\n", + pdev->bus->number, pdev->devfn, rc); + return rc; + } + + ioport = pci_resource_start(pdev, 0); + iolen = pci_resource_len(pdev, 0); + + if (!request_region(ioport, iolen, "emu10k1-gp")) + return -EBUSY; + + if (!(port = kmalloc(sizeof(struct emu), GFP_KERNEL))) { + printk(KERN_ERR "emu10k1-gp: Memory allocation failed.\n"); + release_region(ioport, iolen); + return -ENOMEM; + } + memset(port, 0, sizeof(struct emu)); + + port->gameport.io = ioport; + port->size = iolen; + port->dev = pdev; + pdev->driver_data = port; + + gameport_register_port(&port->gameport); + + printk(KERN_INFO "gameport%d: Emu10k1 Gameport at %#x size %d speed %d kHz\n", + port->gameport.number, port->gameport.io, iolen, port->gameport.speed); + + return 0; +} + +static void __devexit emu_remove(struct pci_dev *pdev) +{ + struct emu *port = (struct emu *)pdev->driver_data; + gameport_unregister_port(&port->gameport); + release_region(port->gameport.io, port->size); + kfree(port); +} + +static struct pci_driver emu_driver = { + name: "Emu10k1 Gameport", + id_table: emu_tbl, + probe: emu_probe, + remove: emu_remove, +}; + +int __init emu_init(void) +{ + return pci_module_init(&emu_driver); +} + +void __exit emu_exit(void) +{ + pci_unregister_driver(&emu_driver); +} + +module_init(emu_init); +module_exit(emu_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/gamecon.c linux/drivers/char/joystick/gamecon.c --- v2.4.9/linux/drivers/char/joystick/gamecon.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/gamecon.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: gamecon.c,v 1.11 2000/11/01 12:38:53 vojtech Exp $ + * $Id: gamecon.c,v 1.14 2001/04/29 22:42:14 vojtech Exp $ * - * Copyright (c) 1999-2000 Vojtech Pavlik + * Copyright (c) 1999-2001 Vojtech Pavlik * * Based on the work of: * Andree Borrmann John Dahlstrom @@ -42,6 +42,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_LICENSE("GPL"); MODULE_PARM(gc, "2-6i"); MODULE_PARM(gc_2,"2-6i"); MODULE_PARM(gc_3,"2-6i"); @@ -62,7 +63,7 @@ struct pardevice *pd; struct input_dev dev[5]; struct timer_list timer; - unsigned char pads[GC_PSX + 1]; + unsigned char pads[GC_MAX + 1]; int used; }; @@ -231,7 +232,7 @@ static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y }; static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, - BTN_START, BTN_SELECT, BTN_THUMB, BTN_THUMB2 }; + BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR }; /* * gc_psx_command() writes 8bit command and reads 8bit data from @@ -345,8 +346,8 @@ s = gc_status_bit[i]; if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) { - input_report_abs(dev + i, ABS_X, ! - !(s & data[6]) - !(s & data[7])); - input_report_abs(dev + i, ABS_Y, ! - !(s & data[4]) - !(s & data[5])); + input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7])); + input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5])); } if (s & gc->pads[GC_NES]) diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/gameport.c linux/drivers/char/joystick/gameport.c --- v2.4.9/linux/drivers/char/joystick/gameport.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/gameport.c Fri Sep 14 14:40:00 2001 @@ -41,6 +41,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_LICENSE("GPL"); EXPORT_SYMBOL(gameport_register_port); EXPORT_SYMBOL(gameport_unregister_port); @@ -61,7 +62,7 @@ static int gameport_measure_speed(struct gameport *gameport) { -#ifdef __i386__ +#if defined(__i386__) || defined(__x86_64__) #define GET_TIME(x) do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0) #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193180L/HZ:0)) diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/gf2k.c linux/drivers/char/joystick/gf2k.c --- v2.4.9/linux/drivers/char/joystick/gf2k.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/gf2k.c Wed Sep 12 15:34:06 2001 @@ -357,3 +357,5 @@ module_init(gf2k_init); module_exit(gf2k_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/grip.c linux/drivers/char/joystick/grip.c --- v2.4.9/linux/drivers/char/joystick/grip.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/grip.c Wed Sep 12 15:34:06 2001 @@ -421,3 +421,5 @@ module_init(grip_init); module_exit(grip_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/iforce.c linux/drivers/char/joystick/iforce.c --- v2.4.9/linux/drivers/char/joystick/iforce.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/iforce.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,8 @@ /* - * $Id: iforce.c,v 1.7 2000/06/04 14:03:36 vojtech Exp $ + * $Id: iforce.c,v 1.56 2001/05/27 14:41:26 jdeneux Exp $ * - * Copyright (c) 2000 Vojtech Pavlik + * Copyright (c) 2000-2001 Vojtech Pavlik + * Copyright (c) 2001 Johann Deneux * * USB/RS232 I-Force joysticks and wheels. * @@ -11,18 +12,18 @@ /* * 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 + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic @@ -38,46 +39,216 @@ #include #include -MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver"); +/* FF: This module provides arbitrary resource management routines. + * I use it to manage the device's memory. + * Despite the name of this module, I am *not* going to access the ioports. + */ +#include -#define USB_VENDOR_ID_LOGITECH 0x046d -#define USB_DEVICE_ID_LOGITECH_WMFORCE 0xc281 +MODULE_AUTHOR("Vojtech Pavlik , Johann Deneux "); +MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver"); +MODULE_LICENSE("GPL"); -#define IFORCE_MAX_LENGTH 16 +#define IFORCE_MAX_LENGTH 16 #if defined(CONFIG_INPUT_IFORCE_232) || defined(CONFIG_INPUT_IFORCE_232_MODULE) -#define IFORCE_232 +#define IFORCE_232 1 #endif #if defined(CONFIG_INPUT_IFORCE_USB) || defined(CONFIG_INPUT_IFORCE_USB_MODULE) -#define IFORCE_USB +#define IFORCE_USB 2 #endif +#define FF_EFFECTS_MAX 32 + +/* Each force feedback effect is made of one core effect, which can be + * associated to at most to effect modifiers + */ +#define FF_MOD1_IS_USED 0 +#define FF_MOD2_IS_USED 1 +#define FF_CORE_IS_USED 2 +#define FF_CORE_IS_PLAYED 3 +#define FF_MODCORE_MAX 3 + +struct iforce_core_effect { + /* Information about where modifiers are stored in the device's memory */ + struct resource mod1_chunk; + struct resource mod2_chunk; + unsigned long flags[NBITS(FF_MODCORE_MAX)]; +}; + +#define FF_CMD_EFFECT 0x010e +#define FF_CMD_SHAPE 0x0208 +#define FF_CMD_MAGNITUDE 0x0303 +#define FF_CMD_PERIOD 0x0407 +#define FF_CMD_INTERACT 0x050a + +#define FF_CMD_AUTOCENTER 0x4002 +#define FF_CMD_PLAY 0x4103 +#define FF_CMD_ENABLE 0x4201 +#define FF_CMD_GAIN 0x4301 + +#define FF_CMD_QUERY 0xff01 + +static signed short btn_joystick[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, + BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, BTN_DEAD, -1 }; +static signed short btn_wheel[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, + BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 }; +static signed short abs_joystick[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 }; +static signed short abs_wheel[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, -1 }; +static signed short ff_iforce[] = { FF_PERIODIC, FF_CONSTANT, FF_SPRING, FF_FRICTION, + FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP, FF_SAW_DOWN, FF_GAIN, FF_AUTOCENTER, -1 }; + +static struct iforce_device { + u16 idvendor; + u16 idproduct; + char *name; + signed short *btn; + signed short *abs; + signed short *ff; +} iforce_device[] = { + { 0x046d, 0xc281, "Logitech WingMan Force", btn_joystick, abs_joystick, ff_iforce }, + { 0x046d, 0xc291, "Logitech WingMan Formula Force", btn_wheel, abs_wheel, ff_iforce }, + { 0x05ef, 0x020a, "AVB Top Shot Pegasus", btn_joystick, abs_joystick, ff_iforce }, + { 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_wheel, abs_wheel, ff_iforce }, + { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, + { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } +}; + struct iforce { - signed char data[IFORCE_MAX_LENGTH]; - struct usb_device *usbdev; - struct input_dev dev; - struct urb irq; + struct input_dev dev; /* Input device interface */ + struct iforce_device *type; + char name[64]; int open; + int bus; + + unsigned char data[IFORCE_MAX_LENGTH]; + unsigned char edata[IFORCE_MAX_LENGTH]; + u16 ecmd; + u16 expect_packet; + +#ifdef IFORCE_232 + struct serio *serio; /* RS232 transfer */ int idx, pkt, len, id; unsigned char csum; +#endif +#ifdef IFORCE_USB + struct usb_device *usbdev; /* USB transfer */ + struct urb irq, out, ctrl; + devrequest dr; +#endif + /* Force Feedback */ + wait_queue_head_t wait; + struct resource device_memory; + struct iforce_core_effect core_effects[FF_EFFECTS_MAX]; }; static struct { - __s32 x; - __s32 y; + __s32 x; + __s32 y; } iforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; -static char *iforce_name = "I-Force joystick/wheel"; +/* Get hi and low bytes of a 16-bits int */ +#define HI(a) ((unsigned char)((a) >> 8)) +#define LO(a) ((unsigned char)((a) & 0xff)) + +/* Encode a time value */ +#define TIME_SCALE(a) ((a) == 0xffff ? 0xffff : (a) * 1000 / 256) -static void iforce_process_packet(struct input_dev *dev, unsigned char id, int idx, unsigned char *data) +static void dump_packet(char *msg, u16 cmd, unsigned char *data) { - switch (id) { + int i; - case 1: /* joystick position data */ - case 3: /* wheel position data */ + printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd); + for (i = 0; i < LO(cmd); i++) + printk("%02x ", data[i]); + printk(")\n"); +} - if (id == 1) { +/* + * Send a packet of bytes to the device + */ +static void send_packet(struct iforce *iforce, u16 cmd, unsigned char* data) +{ + switch (iforce->bus) { + +#ifdef IFORCE_232 + case IFORCE_232: { + + int i; + unsigned char csum = 0x2b ^ HI(cmd) ^ LO(cmd); + + serio_write(iforce->serio, 0x2b); + serio_write(iforce->serio, HI(cmd)); + serio_write(iforce->serio, LO(cmd)); + + for (i = 0; i < LO(cmd); i++) { + serio_write(iforce->serio, data[i]); + csum = csum ^ data[i]; + } + + serio_write(iforce->serio, csum); + return; + } +#endif +#ifdef IFORCE_USB + case IFORCE_USB: { + + DECLARE_WAITQUEUE(wait, current); + int timeout = HZ; /* 1 second */ + + memcpy(iforce->out.transfer_buffer + 1, data, LO(cmd)); + ((char*)iforce->out.transfer_buffer)[0] = HI(cmd); + iforce->out.transfer_buffer_length = LO(cmd) + 2; + iforce->out.dev = iforce->usbdev; + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&iforce->wait, &wait); + + if (usb_submit_urb(&iforce->out)) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&iforce->wait, &wait); + return; + } + + while (timeout && iforce->out.status == -EINPROGRESS) + timeout = schedule_timeout(timeout); + + set_current_state(TASK_RUNNING); + remove_wait_queue(&iforce->wait, &wait); + + if (!timeout) + usb_unlink_urb(&iforce->out); + + return; + } +#endif + } +} + +static void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) +{ + struct input_dev *dev = &iforce->dev; + int i; + +#ifdef IFORCE_232 + if (HI(iforce->expect_packet) == HI(cmd)) { + iforce->expect_packet = 0; + iforce->ecmd = cmd; + memcpy(iforce->edata, data, IFORCE_MAX_LENGTH); + if (waitqueue_active(&iforce->wait)) + wake_up(&iforce->wait); + } +#endif + + if (!iforce->type) + return; + + switch (HI(cmd)) { + + case 0x01: /* joystick position data */ + case 0x03: /* wheel position data */ + + if (HI(cmd) == 1) { input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0])); input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2])); input_report_abs(dev, ABS_THROTTLE, 255 - data[4]); @@ -90,37 +261,95 @@ input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x); input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y); - input_report_key(dev, BTN_TRIGGER, data[5] & 0x01); - input_report_key(dev, BTN_TOP, data[5] & 0x02); - input_report_key(dev, BTN_THUMB, data[5] & 0x04); - input_report_key(dev, BTN_TOP2, data[5] & 0x08); - input_report_key(dev, BTN_BASE, data[5] & 0x10); - input_report_key(dev, BTN_BASE2, data[5] & 0x20); - input_report_key(dev, BTN_BASE3, data[5] & 0x40); - input_report_key(dev, BTN_BASE4, data[5] & 0x80); - input_report_key(dev, BTN_BASE5, data[6] & 0x01); - input_report_key(dev, BTN_A, data[6] & 0x02); - input_report_key(dev, BTN_B, data[6] & 0x04); - input_report_key(dev, BTN_C, data[6] & 0x08); + for (i = 0; iforce->type->btn[i] >= 0; i++) + input_report_key(dev, iforce->type->btn[i], data[(i >> 3) + 5] & (1 << (i & 7))); + break; - case 2: /* force feedback effect status */ + case 0x02: /* status report */ + + input_report_key(dev, BTN_DEAD, data[0] & 0x02); break; } } +static int get_id_packet(struct iforce *iforce, char *packet) +{ + DECLARE_WAITQUEUE(wait, current); + int timeout = HZ; /* 1 second */ + + switch (iforce->bus) { + #ifdef IFORCE_USB + case IFORCE_USB: + + iforce->dr.request = packet[0]; + iforce->ctrl.dev = iforce->usbdev; + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&iforce->wait, &wait); + + if (usb_submit_urb(&iforce->ctrl)) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&iforce->wait, &wait); + return -1; + } + + while (timeout && iforce->ctrl.status == -EINPROGRESS) + timeout = schedule_timeout(timeout); + + set_current_state(TASK_RUNNING); + remove_wait_queue(&iforce->wait, &wait); + + if (!timeout) { + usb_unlink_urb(&iforce->ctrl); + return -1; + } + + break; +#endif +#ifdef IFORCE_232 + case IFORCE_232: + + iforce->expect_packet = FF_CMD_QUERY; + send_packet(iforce, FF_CMD_QUERY, packet); + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&iforce->wait, &wait); + + while (timeout && iforce->expect_packet) + timeout = schedule_timeout(timeout); + + set_current_state(TASK_RUNNING); + remove_wait_queue(&iforce->wait, &wait); + + if (!timeout) { + iforce->expect_packet = 0; + return -1; + } + + break; +#endif + } + + return -(iforce->edata[0] != packet[0]); +} static int iforce_open(struct input_dev *dev) { struct iforce *iforce = dev->private; - if (dev->idbus == BUS_USB && !iforce->open++) { - iforce->irq.dev = iforce->usbdev; - if (usb_submit_urb(&iforce->irq)) - return -EIO; + switch (iforce->bus) { +#ifdef IFORCE_USB + case IFORCE_USB: + if (iforce->open++) + break; + iforce->irq.dev = iforce->usbdev; + if (usb_submit_urb(&iforce->irq)) + return -EIO; + break; +#endif } - return 0; } @@ -128,48 +357,632 @@ { struct iforce *iforce = dev->private; - if (dev->idbus == BUS_USB && !--iforce->open) - usb_unlink_urb(&iforce->irq); + switch (iforce->bus) { +#ifdef IFORCE_USB + case IFORCE_USB: + if (!--iforce->open) + usb_unlink_urb(&iforce->irq); + break; +#endif + } } -#endif +/* + * Start or stop playing an effect + */ + +static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + struct iforce* iforce = (struct iforce*)(dev->private); + unsigned char data[3]; + + printk(KERN_DEBUG "iforce.c: input_event(type = %d, code = %d, value = %d)\n", type, code, value); + + if (type != EV_FF) + return -1; + + switch (code) { + + case FF_GAIN: + + data[0] = value >> 9; + send_packet(iforce, FF_CMD_GAIN, data); + + return 0; + + case FF_AUTOCENTER: + + data[0] = 0x03; + data[1] = value >> 9; + send_packet(iforce, FF_CMD_AUTOCENTER, data); + + data[0] = 0x04; + data[1] = 0x01; + send_packet(iforce, FF_CMD_AUTOCENTER, data); + + return 0; + + default: /* Play an effect */ + + if (code >= iforce->dev.ff_effects_max) + return -1; + + data[0] = LO(code); + data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0; + data[2] = LO(value); + send_packet(iforce, FF_CMD_PLAY, data); + + return 0; + } + + return -1; +} + +/* + * Set the magnitude of a constant force effect + * Return error code + * + * Note: caller must ensure exclusive access to device + */ + +static int make_magnitude_modifier(struct iforce* iforce, + struct resource* mod_chunk, __s16 level) +{ + unsigned char data[3]; + + if (allocate_resource(&(iforce->device_memory), mod_chunk, 2, + iforce->device_memory.start, iforce->device_memory.end, 2L, + NULL, NULL)) { + return -ENOMEM; + } + + data[0] = LO(mod_chunk->start); + data[1] = HI(mod_chunk->start); + data[2] = HI(level); + + send_packet(iforce, FF_CMD_MAGNITUDE, data); + + return 0; +} + +/* + * Upload the component of an effect dealing with the period, phase and magnitude + */ + +static int make_period_modifier(struct iforce* iforce, struct resource* mod_chunk, + __s16 magnitude, __s16 offset, u16 period, u16 phase) +{ + unsigned char data[7]; + + period = TIME_SCALE(period); + + if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c, + iforce->device_memory.start, iforce->device_memory.end, 2L, + NULL, NULL)) { + return -ENOMEM; + } + + data[0] = LO(mod_chunk->start); + data[1] = HI(mod_chunk->start); + + data[2] = HI(magnitude); + data[3] = HI(offset); + data[4] = HI(phase); + + data[5] = LO(period); + data[6] = HI(period); + + send_packet(iforce, FF_CMD_PERIOD, data); + + return 0; +} + +/* + * Uploads the part of an effect setting the shape of the force + */ + +static int make_shape_modifier(struct iforce* iforce, struct resource* mod_chunk, + u16 attack_duration, __s16 initial_level, + u16 fade_duration, __s16 final_level) +{ + unsigned char data[8]; + + attack_duration = TIME_SCALE(attack_duration); + fade_duration = TIME_SCALE(fade_duration); + + if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e, + iforce->device_memory.start, iforce->device_memory.end, 2L, + NULL, NULL)) { + return -ENOMEM; + } + + data[0] = LO(mod_chunk->start); + data[1] = HI(mod_chunk->start); + + data[2] = LO(attack_duration); + data[3] = HI(attack_duration); + data[4] = HI(initial_level); + + data[5] = LO(fade_duration); + data[6] = HI(fade_duration); + data[7] = HI(final_level); + + send_packet(iforce, FF_CMD_SHAPE, data); + + return 0; +} + +/* + * Component of spring, friction, inertia... effects + */ + +static int make_interactive_modifier(struct iforce* iforce, + struct resource* mod_chunk, + __s16 rsat, __s16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center) +{ + unsigned char data[10]; + + if (allocate_resource(&(iforce->device_memory), mod_chunk, 8, + iforce->device_memory.start, iforce->device_memory.end, 2L, + NULL, NULL)) { + return -ENOMEM; + } + + data[0] = LO(mod_chunk->start); + data[1] = HI(mod_chunk->start); + + data[2] = HI(rk); + data[3] = HI(lk); + + data[4] = LO(center); + data[5] = HI(center); + + data[6] = LO(db); + data[7] = HI(db); -static void iforce_input_setup(struct iforce *iforce) + data[8] = HI(rsat); + data[9] = HI(lsat); + + send_packet(iforce, FF_CMD_INTERACT, data); + + return 0; +} + +static unsigned char find_button(struct iforce *iforce, signed short button) { int i; + for (i = 1; iforce->type->btn[i] >= 0; i++) + if (iforce->type->btn[i] == button) + return i + 1; + return 0; +} + +/* + * Send the part common to all effects to the device + */ + +static int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2, + u8 effect_type, u8 axes, u16 duration, u16 delay, u16 button, + u16 interval, u16 direction) +{ + unsigned char data[14]; + + duration = TIME_SCALE(duration); + delay = TIME_SCALE(delay); + interval = TIME_SCALE(interval); + + data[0] = LO(id); + data[1] = effect_type; + data[2] = LO(axes) | find_button(iforce, button); + + data[3] = LO(duration); + data[4] = HI(duration); + + data[5] = HI(direction); + + data[6] = LO(interval); + data[7] = HI(interval); - iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - iforce->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_TOP) | BIT(BTN_THUMB) | BIT(BTN_TOP2) | - BIT(BTN_BASE) | BIT(BTN_BASE2) | BIT(BTN_BASE3) | BIT(BTN_BASE4) | BIT(BTN_BASE5); - iforce->dev.keybit[LONG(BTN_GAMEPAD)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C); - iforce->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) - | BIT(ABS_WHEEL) | BIT(ABS_GAS) | BIT(ABS_BRAKE); - - for (i = ABS_X; i <= ABS_Y; i++) { - iforce->dev.absmax[i] = 1920; - iforce->dev.absmin[i] = -1920; - iforce->dev.absflat[i] = 128; - iforce->dev.absfuzz[i] = 16; - } - - for (i = ABS_THROTTLE; i <= ABS_RUDDER; i++) { - iforce->dev.absmax[i] = 255; - iforce->dev.absmin[i] = 0; - } - - for (i = ABS_HAT0X; i <= ABS_HAT0Y; i++) { - iforce->dev.absmax[i] = 1; - iforce->dev.absmin[i] = -1; + data[8] = LO(mod_id1); + data[9] = HI(mod_id1); + data[10] = LO(mod_id2); + data[11] = HI(mod_id2); + + data[12] = LO(delay); + data[13] = HI(delay); + + send_packet(iforce, FF_CMD_EFFECT, data); + + return 0; +} + +/* + * Upload a periodic effect to the device + */ + +static int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect) +{ + u8 wave_code; + int core_id = effect->id; + struct iforce_core_effect* core_effect = iforce->core_effects + core_id; + struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk); + struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk); + int err = 0; + + err = make_period_modifier(iforce, mod1_chunk, + effect->u.periodic.magnitude, effect->u.periodic.offset, + effect->u.periodic.period, effect->u.periodic.phase); + if (err) return err; + set_bit(FF_MOD1_IS_USED, core_effect->flags); + + err = make_shape_modifier(iforce, mod2_chunk, + effect->u.periodic.shape.attack_length, + effect->u.periodic.shape.attack_level, + effect->u.periodic.shape.fade_length, + effect->u.periodic.shape.fade_level); + if (err) return err; + set_bit(FF_MOD2_IS_USED, core_effect->flags); + + switch (effect->u.periodic.waveform) { + case FF_SQUARE: wave_code = 0x20; break; + case FF_TRIANGLE: wave_code = 0x21; break; + case FF_SINE: wave_code = 0x22; break; + case FF_SAW_UP: wave_code = 0x23; break; + case FF_SAW_DOWN: wave_code = 0x24; break; + default: wave_code = 0x20; break; } - iforce->dev.private = iforce; + err = make_core(iforce, effect->id, + mod1_chunk->start, + mod2_chunk->start, + wave_code, + 0x20, + effect->replay.length, + effect->replay.delay, + effect->trigger.button, + effect->trigger.interval, + effect->u.periodic.direction); -#ifdef IFORCE_USB + return err; +} + +/* + * Upload a constant force effect + */ +static int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect) +{ + int core_id = effect->id; + struct iforce_core_effect* core_effect = iforce->core_effects + core_id; + struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk); + struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk); + int err = 0; + + printk(KERN_DEBUG "iforce.c: make constant effect\n"); + + err = make_magnitude_modifier(iforce, mod1_chunk, effect->u.constant.level); + if (err) return err; + set_bit(FF_MOD1_IS_USED, core_effect->flags); + + err = make_shape_modifier(iforce, mod2_chunk, + effect->u.constant.shape.attack_length, + effect->u.constant.shape.attack_level, + effect->u.constant.shape.fade_length, + effect->u.constant.shape.fade_level); + if (err) return err; + set_bit(FF_MOD2_IS_USED, core_effect->flags); + + err = make_core(iforce, effect->id, + mod1_chunk->start, + mod2_chunk->start, + 0x00, + 0x20, + effect->replay.length, + effect->replay.delay, + effect->trigger.button, + effect->trigger.interval, + effect->u.constant.direction); + + return err; +} + +/* + * Upload an interactive effect. Those are for example friction, inertia, springs... + */ +static int iforce_upload_interactive(struct iforce* iforce, struct ff_effect* effect) +{ + int core_id = effect->id; + struct iforce_core_effect* core_effect = iforce->core_effects + core_id; + struct resource* mod_chunk = &(core_effect->mod1_chunk); + u8 type, axes; + u16 mod1, mod2, direction; + int err = 0; + + printk(KERN_DEBUG "iforce.c: make interactive effect\n"); + + switch (effect->type) { + case FF_SPRING: type = 0x40; break; + case FF_FRICTION: type = 0x41; break; + default: return -1; + } + + err = make_interactive_modifier(iforce, mod_chunk, + effect->u.interactive.right_saturation, + effect->u.interactive.left_saturation, + effect->u.interactive.right_coeff, + effect->u.interactive.left_coeff, + effect->u.interactive.deadband, + effect->u.interactive.center); + if (err) return err; + set_bit(FF_MOD1_IS_USED, core_effect->flags); + + switch ((test_bit(ABS_X, &effect->u.interactive.axis) || + test_bit(ABS_WHEEL, &effect->u.interactive.axis)) | + (!!test_bit(ABS_Y, &effect->u.interactive.axis) << 1)) { + + case 0: /* Only one axis, choose orientation */ + mod1 = mod_chunk->start; + mod2 = 0xffff; + direction = effect->u.interactive.direction; + axes = 0x20; + break; + + case 1: /* Only X axis */ + mod1 = mod_chunk->start; + mod2 = 0xffff; + direction = 0x5a00; + axes = 0x40; + break; + + case 2: /* Only Y axis */ + mod1 = 0xffff; + mod2 = mod_chunk->start; + direction = 0xb400; + axes = 0x80; + break; + + case 3: /* Both X and Y axes */ + /* TODO: same setting for both axes is not mandatory */ + mod1 = mod_chunk->start; + mod2 = mod_chunk->start; + direction = 0x6000; + axes = 0xc0; + break; + + default: + return -1; + } + + err = make_core(iforce, effect->id, + mod1, mod2, + type, axes, + effect->replay.length, effect->replay.delay, + effect->trigger.button, effect->trigger.interval, + direction); + + return err; +} + +/* + * Function called when an ioctl is performed on the event dev entry. + * It uploads an effect to the device + */ +static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect) +{ + struct iforce* iforce = (struct iforce*)(dev->private); + int id; + + printk(KERN_DEBUG "iforce.c: upload effect\n"); + +/* + * Get a free id + */ + + for (id=0; id < FF_EFFECTS_MAX; ++id) + if (!test_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break; + + if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max) + return -ENOMEM; + + effect->id = id; + set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags); + +/* + * Upload the effect + */ + + switch (effect->type) { + + case FF_PERIODIC: + return iforce_upload_periodic(iforce, effect); + + case FF_CONSTANT: + return iforce_upload_constant(iforce, effect); + + case FF_SPRING: + case FF_FRICTION: + return iforce_upload_interactive(iforce, effect); + + default: + return -1; + } +} + +/* + * Erases an effect: it frees the effect id and mark as unused the memory + * allocated for the parameters + */ +static int iforce_erase_effect(struct input_dev *dev, int effect_id) +{ + struct iforce* iforce = (struct iforce*)(dev->private); + int err = 0; + struct iforce_core_effect* core_effect; + + printk(KERN_DEBUG "iforce.c: erase effect %d\n", effect_id); + + if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX) + return -EINVAL; + + core_effect = iforce->core_effects + effect_id; + + if (test_bit(FF_MOD1_IS_USED, core_effect->flags)) + err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk)); + + if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags)) + err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk)); + + /*TODO: remember to change that if more FF_MOD* bits are added */ + core_effect->flags[0] = 0; + + return err; +} +static int iforce_init_device(struct iforce *iforce) +{ + unsigned char c[] = "CEOV"; + int i; + + init_waitqueue_head(&iforce->wait); + iforce->dev.ff_effects_max = 10; + +/* + * Input device fields. + */ + + iforce->dev.idbus = BUS_USB; + iforce->dev.private = iforce; + iforce->dev.name = iforce->name; iforce->dev.open = iforce_open; iforce->dev.close = iforce_close; -#endif + iforce->dev.event = iforce_input_event; + iforce->dev.upload_effect = iforce_upload_effect; + iforce->dev.erase_effect = iforce_erase_effect; + +/* + * On-device memory allocation. + */ + + iforce->device_memory.name = "I-Force device effect memory"; + iforce->device_memory.start = 0; + iforce->device_memory.end = 200; + iforce->device_memory.flags = IORESOURCE_MEM; + iforce->device_memory.parent = NULL; + iforce->device_memory.child = NULL; + iforce->device_memory.sibling = NULL; + +/* + * Wait until device ready - until it sends its first response. + */ + + for (i = 0; i < 20; i++) + if (!get_id_packet(iforce, "O")) + break; + + if (i == 20) { /* 5 seconds */ + printk(KERN_ERR "iforce.c: Timeout waiting for response from device.\n"); + iforce_close(&iforce->dev); + return -1; + } + +/* + * Get device info. + */ + + if (!get_id_packet(iforce, "M")) + iforce->dev.idvendor = (iforce->edata[2] << 8) | iforce->edata[1]; + if (!get_id_packet(iforce, "P")) + iforce->dev.idproduct = (iforce->edata[2] << 8) | iforce->edata[1]; + if (!get_id_packet(iforce, "B")) + iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1]; + if (!get_id_packet(iforce, "N")) + iforce->dev.ff_effects_max = iforce->edata[1]; + +/* + * Display additional info. + */ + + for (i = 0; c[i]; i++) + if (!get_id_packet(iforce, c + i)) + dump_packet("info", iforce->ecmd, iforce->edata); + +/* + * Disable spring, enable force feedback. + * FIXME: We should use iforce_set_autocenter() et al here. + */ + + send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000"); + send_packet(iforce, FF_CMD_ENABLE, "\004"); + +/* + * Find appropriate device entry + */ + + for (i = 0; iforce_device[i].idvendor; i++) + if (iforce_device[i].idvendor == iforce->dev.idvendor && + iforce_device[i].idproduct == iforce->dev.idproduct) + break; + + iforce->type = iforce_device + i; + + sprintf(iforce->name, iforce->type->name, + iforce->dev.idproduct, iforce->dev.idvendor); + +/* + * Set input device bitfields and ranges. + */ + + iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF); + + for (i = 0; iforce->type->btn[i] >= 0; i++) { + signed short t = iforce->type->btn[i]; + set_bit(t, iforce->dev.keybit); + if (t != BTN_DEAD) + set_bit(FF_BTN(t), iforce->dev.ffbit); + } + + for (i = 0; iforce->type->abs[i] >= 0; i++) { + + signed short t = iforce->type->abs[i]; + set_bit(t, iforce->dev.absbit); + + switch (t) { + + case ABS_X: + case ABS_Y: + case ABS_WHEEL: + + iforce->dev.absmax[t] = 1920; + iforce->dev.absmin[t] = -1920; + iforce->dev.absflat[t] = 128; + iforce->dev.absfuzz[t] = 16; + + set_bit(FF_ABS(t), iforce->dev.ffbit); + break; + + case ABS_THROTTLE: + case ABS_GAS: + case ABS_BRAKE: + + iforce->dev.absmax[t] = 255; + iforce->dev.absmin[t] = 0; + break; + + case ABS_HAT0X: + case ABS_HAT0Y: + iforce->dev.absmax[t] = 1; + iforce->dev.absmin[t] = -1; + break; + } + } + + for (i = 0; iforce->type->ff[i] >= 0; i++) + set_bit(iforce->type->ff[i], iforce->dev.ffbit); + +/* + * Register input device. + */ input_register_device(&iforce->dev); + + return 0; } #ifdef IFORCE_USB @@ -178,33 +991,63 @@ { struct iforce *iforce = urb->context; if (urb->status) return; - iforce_process_packet(&iforce->dev, iforce->data[0], 8, iforce->data + 1); + iforce_process_packet(iforce, + (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1); +} + +static void iforce_usb_out(struct urb *urb) +{ + struct iforce *iforce = urb->context; + if (urb->status) return; + if (waitqueue_active(&iforce->wait)) + wake_up(&iforce->wait); +} + +static void iforce_usb_ctrl(struct urb *urb) +{ + struct iforce *iforce = urb->context; + if (urb->status) return; + iforce->ecmd = 0xff00 | urb->actual_length; + if (waitqueue_active(&iforce->wait)) + wake_up(&iforce->wait); } static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id) + const struct usb_device_id *id) { - struct usb_endpoint_descriptor *endpoint; + struct usb_endpoint_descriptor *epirq, *epout; struct iforce *iforce; - endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; + epirq = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; + epout = dev->config[0].interface[ifnum].altsetting[0].endpoint + 1; - if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return NULL; + if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) return NULL; memset(iforce, 0, sizeof(struct iforce)); - iforce->dev.name = iforce_name; - iforce->dev.idbus = BUS_USB; - iforce->dev.idvendor = dev->descriptor.idVendor; - iforce->dev.idproduct = dev->descriptor.idProduct; - iforce->dev.idversion = dev->descriptor.bcdDevice; + iforce->bus = IFORCE_USB; + iforce->usbdev = dev; + + iforce->dr.requesttype = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE; + iforce->dr.index = 0; + iforce->dr.length = 16; + + FILL_INT_URB(&iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress), + iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval); - FILL_INT_URB(&iforce->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), - iforce->data, 8, iforce_usb_irq, iforce, endpoint->bInterval); + FILL_BULK_URB(&iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress), + iforce + 1, 32, iforce_usb_out, iforce); - iforce_input_setup(iforce); + FILL_CONTROL_URB(&iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0), + (void*) &iforce->dr, iforce->edata, 16, iforce_usb_ctrl, iforce); - printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n", - iforce->dev.number, iforce_name, dev->bus->busnum, dev->devnum, ifnum); + if (iforce_init_device(iforce)) { + kfree(iforce); + return NULL; + } + + printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on usb%d:%d.%d\n", + iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max, + iforce->device_memory.end, dev->bus->busnum, dev->devnum, ifnum); return iforce; } @@ -218,8 +1061,12 @@ } static struct usb_device_id iforce_usb_ids [] = { - { USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WMFORCE) }, - { } /* Terminating entry */ + { USB_DEVICE(0x046d, 0xc281) }, /* Logitech WingMan Force */ + { USB_DEVICE(0x046d, 0xc291) }, /* Logitech WingMan Formula Force */ + { USB_DEVICE(0x05ef, 0x020a) }, /* AVB Top Shot Pegasus */ + { USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */ + { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ + { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, iforce_usb_ids); @@ -237,7 +1084,7 @@ static void iforce_serio_irq(struct serio *serio, unsigned char data, unsigned int flags) { - struct iforce* iforce = serio->private; + struct iforce* iforce = serio->private; if (!iforce->pkt) { if (data != 0x2b) { @@ -247,14 +1094,14 @@ return; } - if (!iforce->id) { - if (data > 3) { + if (!iforce->id) { + if (data > 3 && data != 0xff) { iforce->pkt = 0; return; } - iforce->id = data; + iforce->id = data; return; - } + } if (!iforce->len) { if (data > IFORCE_MAX_LENGTH) { @@ -266,37 +1113,32 @@ return; } - if (iforce->idx < iforce->len) { - iforce->csum += iforce->data[iforce->idx++] = data; + if (iforce->idx < iforce->len) { + iforce->csum += iforce->data[iforce->idx++] = data; return; } - if (iforce->idx == iforce->len) { - iforce_process_packet(&iforce->dev, iforce->id, iforce->idx, iforce->data); + if (iforce->idx == iforce->len) { + iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data); iforce->pkt = 0; iforce->id = 0; - iforce->len = 0; - iforce->idx = 0; + iforce->len = 0; + iforce->idx = 0; iforce->csum = 0; - } + } } static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev) { struct iforce *iforce; - if (serio->type != (SERIO_RS232 | SERIO_IFORCE)) return; if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return; memset(iforce, 0, sizeof(struct iforce)); - iforce->dev.name = iforce_name; - iforce->dev.idbus = BUS_RS232; - iforce->dev.idvendor = SERIO_IFORCE; - iforce->dev.idproduct = 0x0001; - iforce->dev.idversion = 0x0100; - + iforce->bus = IFORCE_232; + iforce->serio = serio; serio->private = iforce; if (serio_open(serio, dev)) { @@ -304,15 +1146,21 @@ return; } - iforce_input_setup(iforce); + if (iforce_init_device(iforce)) { + serio_close(serio); + kfree(iforce); + return; + } - printk(KERN_INFO "input%d: %s on serio%d\n", - iforce->dev.number, iforce_name, serio->number); + printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on serio%d\n", + iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max, + iforce->device_memory.end, serio->number); } static void iforce_serio_disconnect(struct serio *serio) { struct iforce* iforce = serio->private; + input_unregister_device(&iforce->dev); serio_close(serio); kfree(iforce); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/interact.c linux/drivers/char/joystick/interact.c --- v2.4.9/linux/drivers/char/joystick/interact.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/interact.c Wed Sep 12 15:34:06 2001 @@ -304,3 +304,5 @@ module_init(interact_init); module_exit(interact_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/lightning.c linux/drivers/char/joystick/lightning.c --- v2.4.9/linux/drivers/char/joystick/lightning.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/lightning.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: lightning.c,v 1.7 2000/05/24 19:36:03 vojtech Exp $ + * $Id: lightning.c,v 1.13 2001/04/26 10:24:46 vojtech Exp $ * - * Copyright (c) 1998-2000 Vojtech Pavlik + * Copyright (c) 1998-2001 Vojtech Pavlik * * Sponsored by SuSE */ @@ -52,6 +52,7 @@ #define L4_TIMEOUT 80 /* 80 us */ MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_LICENSE("GPL"); struct l4 { struct gameport gameport; @@ -76,7 +77,7 @@ static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - struct l4 *l4 = gameport->driver; + struct l4 *l4 = gameport->private; unsigned char status; int i, result = -1; @@ -109,7 +110,7 @@ static int l4_open(struct gameport *gameport, int mode) { - struct l4 *l4 = gameport->driver; + struct l4 *l4 = gameport->private; if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED) return -1; outb(L4_SELECT_ANALOG, L4_PORT); @@ -187,7 +188,7 @@ { int i, t; int cal[4]; - struct l4 *l4 = gameport->driver; + struct l4 *l4 = gameport->private; if (l4_getcal(l4->port, cal)) return -1; @@ -247,16 +248,13 @@ l4->port = i * 4 + j; gameport = &l4->gameport; - gameport->driver = l4; + gameport->private = l4; gameport->open = l4_open; gameport->cooked_read = l4_cooked_read; gameport->calibrate = l4_calibrate; - gameport->type = GAMEPORT_EXT; - if (!i && !j) { + if (!i && !j) gameport->io = L4_PORT; - gameport->size = 1; - } if (rev > 0x28) /* on 2.9+ the setcal command works correctly */ l4_setcal(l4->port, cal); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/magellan.c linux/drivers/char/joystick/magellan.c --- v2.4.9/linux/drivers/char/joystick/magellan.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/magellan.c Wed Sep 12 15:34:06 2001 @@ -208,3 +208,5 @@ module_init(magellan_init); module_exit(magellan_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/ns558.c linux/drivers/char/joystick/ns558.c --- v2.4.9/linux/drivers/char/joystick/ns558.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/ns558.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: ns558.c,v 1.27 2001/03/28 09:25:05 vojtech Exp $ + * $Id: ns558.c,v 1.29 2001/04/24 07:48:56 vojtech Exp $ * - * Copyright (c) 1999-2000 Vojtech Pavlik + * Copyright (c) 1999-2001 Vojtech Pavlik * Copyright (c) 1999 Brian Gerst * * Sponsored by SuSE @@ -42,23 +42,23 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_LICENSE("GPL"); #define NS558_ISA 1 #define NS558_PNP 2 -#define NS558_PCI 3 static int ns558_isa_portlist[] = { 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209, 0x20b, 0x20c, 0x20e, 0x20f, 0x211, 0x219, 0x101, 0 }; struct ns558 { int type; + int size; struct pci_dev *dev; struct ns558 *next; struct gameport gameport; }; static struct ns558 *ns558; -static int ns558_pci; /* * ns558_isa_probe() tries to find an isa gameport at the @@ -132,122 +132,43 @@ i--; if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) { - printk(KERN_ERR "Memory allocation failed.\n"); + printk(KERN_ERR "ns558: Memory allocation failed.\n"); return next; } memset(port, 0, sizeof(struct ns558)); port->next = next; port->type = NS558_ISA; + port->size = (1 << i); port->gameport.io = io & (-1 << i); - port->gameport.size = (1 << i); - request_region(port->gameport.io, port->gameport.size, "ns558-isa"); + request_region(port->gameport.io, (1 << i), "ns558-isa"); gameport_register_port(&port->gameport); printk(KERN_INFO "gameport%d: NS558 ISA at %#x", port->gameport.number, port->gameport.io); - if (port->gameport.size > 1) printk(" size %d", port->gameport.size); + if (port->size > 1) printk(" size %d", port->size); printk(" speed %d kHz\n", port->gameport.speed); return port; } -#ifdef CONFIG_PCI -static struct pci_device_id ns558_pci_tbl[] __devinitdata = { - { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB Live! gameport */ - { 0x125d, 0x1969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, /* ESS Solo 1 */ - { 0x5333, 0xca00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, /* S3 SonicVibes */ - { 0, } -}; -MODULE_DEVICE_TABLE(pci, ns558_pci_tbl); - -static int __devinit ns558_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int ioport, iolen; - int rc; - struct ns558 *port; - - rc = pci_enable_device(pdev); - if (rc) { - printk(KERN_ERR "ns558: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", - pdev->bus->number, pdev->devfn, rc); - return rc; - } - - ioport = pci_resource_start(pdev, ent->driver_data); - iolen = pci_resource_len(pdev, ent->driver_data); - - if (!request_region(ioport, iolen, "ns558-pci")) - return -EBUSY; - - if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) { - printk(KERN_ERR "Memory allocation failed.\n"); - release_region(ioport, iolen); - return -ENOMEM; - } - memset(port, 0, sizeof(struct ns558)); - - port->type = NS558_PCI; - port->gameport.io = ioport; - port->gameport.size = iolen; - port->dev = pdev; - - pdev->driver_data = port; - - gameport_register_port(&port->gameport); - - printk(KERN_INFO "gameport%d: NS558 PCI at %#x", port->gameport.number, port->gameport.io); - if (port->gameport.size > 1) printk(" size %d", port->gameport.size); - printk(" speed %d kHz\n", port->gameport.speed); - - return 0; -} - -static void __devexit ns558_pci_remove(struct pci_dev *pdev) -{ - struct ns558 *port = (struct ns558 *)pdev->driver_data; - release_region(port->gameport.io, port->gameport.size); - kfree(port); -} - -static struct pci_driver ns558_pci_driver = { - name: "PCI Gameport", - id_table: ns558_pci_tbl, - probe: ns558_pci_probe, - remove: ns558_pci_remove, -}; -#else -static struct pci_driver ns558_pci_driver; -#endif /* CONFIG_PCI */ - - #if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE)) #define NSS558_ISAPNP #endif #ifdef NSS558_ISAPNP -/* - * PnP IDs: - * - * @P@0001 - ALS 100 (no comp. ID) - * CTL00c1 - SB AWE32 PnP - * CTL00c3 - SB AWE64 PnP - * CTL00f0 - SB16 PnP / Vibra 16x - * CTL7001 - SB Vibra16C PnP (no comp. ID) - * CTL7002 - SB AWE32 (no comp. ID) - * CSC0b35 - Crystal (no comp. ID) - * TER1141 - Terratec AD1818 - * YMM0800 - Yamaha OPL3-SA3 - * - * PNPb02f - Generic gameport - */ static struct isapnp_device_id pnp_devids[] = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x0001), 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x2001), 0 }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x7001), 0 }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x7002), 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0010), 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0110), 0 }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0b35), 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0010), 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0110), 0 }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P','N','P'), ISAPNP_DEVICE(0xb02f), 0 }, { 0, }, }; @@ -263,12 +184,12 @@ return next; if (!(dev->resource[0].flags & IORESOURCE_IO)) { - printk(KERN_WARNING "No i/o ports on a gameport? Weird\n"); + printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n"); return next; } if (dev->activate && dev->activate(dev) < 0) { - printk(KERN_ERR "PnP resource allocation failed\n"); + printk(KERN_ERR "ns558: PnP resource allocation failed\n"); return next; } @@ -279,7 +200,7 @@ goto deactivate; if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) { - printk(KERN_ERR "Memory allocation failed.\n"); + printk(KERN_ERR "ns558: Memory allocation failed.\n"); goto deactivate; } memset(port, 0, sizeof(struct ns558)); @@ -287,13 +208,13 @@ port->next = next; port->type = NS558_PNP; port->gameport.io = ioport; - port->gameport.size = iolen; + port->size = iolen; port->dev = dev; gameport_register_port(&port->gameport); printk(KERN_INFO "gameport%d: NS558 PnP at %#x", port->gameport.number, port->gameport.io); - if (port->gameport.size > 1) printk(" size %d", port->gameport.size); + if (iolen > 1) printk(" size %d", iolen); printk(" speed %d kHz\n", port->gameport.speed); return port; @@ -309,18 +230,11 @@ { int i = 0; #ifdef NSS558_ISAPNP - struct pci_dev *dev = NULL; struct isapnp_device_id *devid; + struct pci_dev *dev = NULL; #endif /* - * Probe for PCI ports. Always probe for PCI first, - * it is the least-invasive probe. - */ - - ns558_pci = !pci_module_init(&ns558_pci_driver); - -/* * Probe for ISA ports. */ @@ -339,7 +253,7 @@ } #endif - return (ns558 || ns558_pci) ? 0 : -ENODEV; + return ns558 ? 0 : -ENODEV; } void __exit ns558_exit(void) @@ -358,7 +272,7 @@ #endif case NS558_ISA: - release_region(port->gameport.io, port->gameport.size); + release_region(port->gameport.io, port->size); break; default: @@ -369,9 +283,6 @@ kfree(port); port = next; } - - if (ns558_pci) - pci_unregister_driver(&ns558_pci_driver); } module_init(ns558_init); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/pcigame.c linux/drivers/char/joystick/pcigame.c --- v2.4.9/linux/drivers/char/joystick/pcigame.c Fri Sep 22 14:21:17 2000 +++ linux/drivers/char/joystick/pcigame.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: pcigame.c,v 1.6 2000/05/25 12:05:24 vojtech Exp $ + * $Id: pcigame.c,v 1.10 2001/04/26 10:24:46 vojtech Exp $ * - * Copyright (c) 2000 Vojtech Pavlik + * Copyright (c) 2000-2001 Vojtech Pavlik * * Based on the work of: * Raymond Ingles @@ -76,19 +76,19 @@ static unsigned char pcigame_read(struct gameport *gameport) { - struct pcigame *pcigame = gameport->driver; + struct pcigame *pcigame = gameport->private; return readb(pcigame->base + pcigame->data->legacy); } static void pcigame_trigger(struct gameport *gameport) { - struct pcigame *pcigame = gameport->driver; + struct pcigame *pcigame = gameport->private; writeb(0xff, pcigame->base + pcigame->data->legacy); } static int pcigame_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - struct pcigame *pcigame = gameport->driver; + struct pcigame *pcigame = gameport->private; int i; *buttons = (~readb(pcigame->base + pcigame->data->legacy) >> 4) & 0xf; @@ -103,7 +103,7 @@ static int pcigame_open(struct gameport *gameport, int mode) { - struct pcigame *pcigame = gameport->driver; + struct pcigame *pcigame = gameport->private; switch (mode) { case GAMEPORT_MODE_COOKED: @@ -135,8 +135,7 @@ pcigame->dev = dev; dev->driver_data = pcigame; - pcigame->gameport.driver = pcigame; - pcigame->gameport.type = GAMEPORT_EXT; + pcigame->gameport.private = pcigame; pcigame->gameport.fuzz = 64; pcigame->gameport.read = pcigame_read; @@ -196,3 +195,5 @@ module_init(pcigame_init); module_exit(pcigame_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/serio.c linux/drivers/char/joystick/serio.c --- v2.4.9/linux/drivers/char/joystick/serio.c Mon Oct 16 12:58:51 2000 +++ linux/drivers/char/joystick/serio.c Wed Sep 12 15:34:06 2001 @@ -35,6 +35,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_LICENSE("GPL"); EXPORT_SYMBOL(serio_register_port); EXPORT_SYMBOL(serio_unregister_port); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/serport.c linux/drivers/char/joystick/serport.c --- v2.4.9/linux/drivers/char/joystick/serport.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/serport.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: serport.c,v 1.4 2000/05/29 10:54:53 vojtech Exp $ + * $Id: serport.c,v 1.7 2001/05/25 19:00:27 jdeneux Exp $ * - * Copyright (c) 1999-2000 Vojtech Pavlik + * Copyright (c) 1999-2001 Vojtech Pavlik * * Sponsored by SuSE */ @@ -148,7 +148,11 @@ DECLARE_WAITQUEUE(wait, current); char name[32]; +#ifdef CONFIG_DEVFS_FS sprintf(name, tty->driver.name, MINOR(tty->device) - tty->driver.minor_start); +#else + sprintf(name, "%s%d", tty->driver.name, MINOR(tty->device) - tty->driver.minor_start); +#endif serio_register_port(&serport->serio); @@ -218,3 +222,5 @@ module_init(serport_init); module_exit(serport_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/sidewinder.c linux/drivers/char/joystick/sidewinder.c --- v2.4.9/linux/drivers/char/joystick/sidewinder.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/sidewinder.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: sidewinder.c,v 1.18 2001/02/28 07:09:30 vojtech Exp $ + * $Id: sidewinder.c,v 1.20 2001/05/19 08:14:54 vojtech Exp $ * - * Copyright (c) 1998-2000 Vojtech Pavlik + * Copyright (c) 1998-2001 Vojtech Pavlik * * Sponsored by SuSE */ @@ -582,6 +582,9 @@ if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) goto fail1; + dbg("Init 0: Opened gameport %d, io %#x, speed %d", + gameport->number, gameport->io, gameport->speed); + i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read normal packet */ m |= sw_guess_mode(buf, i); /* Data packet (1-bit) can carry mode info [FSP] */ udelay(SW_TIMEOUT); @@ -754,3 +757,5 @@ module_init(sw_init); module_exit(sw_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/spaceball.c linux/drivers/char/joystick/spaceball.c --- v2.4.9/linux/drivers/char/joystick/spaceball.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/spaceball.c Wed Sep 12 15:34:06 2001 @@ -234,3 +234,5 @@ module_init(spaceball_init); module_exit(spaceball_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/spaceorb.c linux/drivers/char/joystick/spaceorb.c --- v2.4.9/linux/drivers/char/joystick/spaceorb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/spaceorb.c Wed Sep 12 15:34:06 2001 @@ -223,3 +223,5 @@ module_init(spaceorb_init); module_exit(spaceorb_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/stinger.c linux/drivers/char/joystick/stinger.c --- v2.4.9/linux/drivers/char/joystick/stinger.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/stinger.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: stinger.c,v 1.1 2000/07/17 10:42:14 vojtech Exp $ + * $Id: stinger.c,v 1.4 2001/05/23 09:25:02 vojtech Exp $ * - * Copyright (c) 2000 Vojtech Pavlik + * Copyright (c) 2000-2001 Vojtech Pavlik * Copyright (c) 2000 Mark Fletcher * * Sponsored by SuSE @@ -79,8 +79,8 @@ input_report_key(dev, BTN_SELECT, ((data[3] & 0x02) >> 1)); input_report_key(dev, BTN_START, (data[3] & 0x01)); - input_report_abs(dev, ABS_X, ((data[1] & 0x3F) - ((data[0] & 0x01) << 6))); - input_report_abs(dev, ABS_Y, ((data[2] & 0x3F) - ((data[0] & 0x02) << 5))); + input_report_abs(dev, ABS_X, (data[1] & 0x3F) - ((data[0] & 0x01) << 6)); + input_report_abs(dev, ABS_Y, ((data[0] & 0x02) << 5) - (data[2] & 0x3F)); return; } @@ -198,3 +198,5 @@ module_init(stinger_init); module_exit(stinger_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/tmdc.c linux/drivers/char/joystick/tmdc.c --- v2.4.9/linux/drivers/char/joystick/tmdc.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/char/joystick/tmdc.c Wed Sep 12 15:34:06 2001 @@ -374,3 +374,5 @@ module_init(tmdc_init); module_exit(tmdc_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/turbografx.c linux/drivers/char/joystick/turbografx.c --- v2.4.9/linux/drivers/char/joystick/turbografx.c Wed Jun 21 08:22:21 2000 +++ linux/drivers/char/joystick/turbografx.c Wed Sep 12 15:34:06 2001 @@ -40,6 +40,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_LICENSE("GPL"); MODULE_PARM(tgfx, "2-8i"); MODULE_PARM(tgfx_2, "2-8i"); MODULE_PARM(tgfx_3, "2-8i"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/joystick/warrior.c linux/drivers/char/joystick/warrior.c --- v2.4.9/linux/drivers/char/joystick/warrior.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/joystick/warrior.c Wed Sep 12 15:34:06 2001 @@ -210,3 +210,5 @@ module_init(warrior_init); module_exit(warrior_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v2.4.9/linux/drivers/char/keyboard.c Mon Oct 16 12:58:51 2000 +++ linux/drivers/char/keyboard.c Tue Sep 18 13:39:51 2001 @@ -205,15 +205,12 @@ char raw_mode; pm_access(pm_kbd); - - do_poke_blanked_console = 1; - tasklet_schedule(&console_tasklet); add_keyboard_randomness(scancode | up_flag); tty = ttytab? ttytab[fg_console]: NULL; if (tty && (!tty->driver_data)) { /* - * We touch the tty structure via the the ttytab array + * We touch the tty structure via the ttytab array * without knowing whether or not tty is open, which * is inherently dangerous. We currently rely on that * fact that console_open sets tty->driver_data when @@ -233,7 +230,7 @@ * Convert scancode to keycode */ if (!kbd_translate(scancode, &keycode, raw_mode)) - return; + goto out; /* * At this point the variable `keycode' contains the keycode. @@ -252,11 +249,11 @@ #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ if (keycode == SYSRQ_KEY) { sysrq_pressed = !up_flag; - return; + goto out; } else if (sysrq_pressed) { if (!up_flag) { handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty); - return; + goto out; } } #endif @@ -298,7 +295,7 @@ if (type >= 0xf0) { type -= 0xf0; if (raw_mode && ! (TYPES_ALLOWED_IN_RAW_MODE & (1 << type))) - return; + goto out; if (type == KT_LETTER) { type = KT_LATIN; if (vc_kbd_led(kbd, VC_CAPSLOCK)) { @@ -322,13 +319,16 @@ compute_shiftstate(); kbd->slockstate = 0; /* play it safe */ #else - keysym = U(plain_map[keycode]); + keysym = U(plain_map[keycode]); type = KTYP(keysym); if (type == KT_SHIFT) (*key_handler[type])(keysym & 0xff, up_flag); #endif } } +out: + do_poke_blanked_console = 1; + schedule_console_callback(); } @@ -911,6 +911,10 @@ EXPORT_SYMBOL(keyboard_tasklet); DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); +typedef void (pm_kbd_func) (void); + +pm_callback pm_kbd_request_override = NULL; + int __init kbd_init(void) { int i; @@ -934,7 +938,7 @@ tasklet_enable(&keyboard_tasklet); tasklet_schedule(&keyboard_tasklet); - pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, NULL); + pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override); return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/char/logibusmouse.c linux/drivers/char/logibusmouse.c --- v2.4.9/linux/drivers/char/logibusmouse.c Mon Jun 19 13:25:06 2000 +++ linux/drivers/char/logibusmouse.c Thu Sep 13 15:21:32 2001 @@ -158,3 +158,6 @@ module_init(logi_busmouse_init); module_exit(logi_busmouse_cleanup); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.4.9/linux/drivers/char/lp.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/lp.c Sun Sep 16 21:23:03 2001 @@ -543,7 +543,7 @@ * non-zero to get the latter behaviour. */ #define CONSOLE_LP_STRICT 1 -/* The console_lock must be held when we get here. */ +/* The console must be locked when we get here. */ static void lp_console_write (struct console *co, const char *s, unsigned count) @@ -838,3 +838,6 @@ __setup("lp=", lp_setup); module_init(lp_init_module); module_exit(lp_cleanup_module); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/machzwd.c linux/drivers/char/machzwd.c --- v2.4.9/linux/drivers/char/machzwd.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/machzwd.c Thu Sep 13 15:21:32 2001 @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include @@ -99,6 +99,7 @@ MODULE_AUTHOR("Fernando Fuganti "); MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(action, "i"); MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.4.9/linux/drivers/char/mem.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/mem.c Fri Sep 14 14:04:07 2001 @@ -41,9 +41,6 @@ #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) extern void tapechar_init(void); #endif -#if defined(CONFIG_ADB) -extern void adbdev_init(void); -#endif static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp, const char * buf, size_t count, loff_t *ppos) @@ -134,7 +131,7 @@ { unsigned long prot = pgprot_val(_prot); -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) /* On PPro and successors, PCD alone doesn't always mean uncached because of interactions with the MTRRs. PCD | PWT means definitely uncached. */ @@ -153,8 +150,6 @@ /* Use no-cache mode, serialized */ else if (MMU_IS_040 || MMU_IS_060) prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S; -#elif defined(__mips__) - prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED; #endif return __pgprot(prot); @@ -640,9 +635,6 @@ #endif #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) tapechar_init(); -#endif -#if defined(CONFIG_ADB) - adbdev_init(); #endif return 0; } 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/mixcomwd.c linux/drivers/char/mixcomwd.c --- v2.4.9/linux/drivers/char/mixcomwd.c Tue May 22 10:23:16 2001 +++ linux/drivers/char/mixcomwd.c Thu Sep 13 15:21:32 2001 @@ -269,3 +269,6 @@ module_init(mixcomwd_init); module_exit(mixcomwd_exit); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/moxa.c linux/drivers/char/moxa.c --- v2.4.9/linux/drivers/char/moxa.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/moxa.c Sun Sep 9 10:43:02 2001 @@ -205,6 +205,7 @@ MODULE_AUTHOR("William Chen"); MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(type, "1-4i"); MODULE_PARM(baseaddr, "1-4i"); MODULE_PARM(numports, "1-4i"); @@ -212,6 +213,8 @@ MODULE_PARM(calloutmajor, "i"); MODULE_PARM(verbose, "i"); +EXPORT_NO_SYMBOLS; + #endif //MODULE static struct tty_driver moxaDriver; @@ -1717,27 +1720,6 @@ if(copy_to_user((void *)arg, temp_queue, sizeof(struct moxaq_str) * MAX_PORTS)) return -EFAULT; return (0); - case MOXA_LOAD_BIOS: - if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str))) - return -EFAULT; - i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len); - return (i); - case MOXA_FIND_BOARD: - if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str))) - return -EFAULT; - return moxafindcard(dltmp.cardno); - case MOXA_LOAD_C320B: - if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str))) - return -EFAULT; - moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len); - return (0); - case MOXA_LOAD_CODE: - if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str))) - return -EFAULT; - i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len); - if (i == -1) - return (-EFAULT); - return (i); case MOXA_GET_OQUEUE: i = MoxaPortTxQueue(port); return put_user(i, (unsigned long *) arg); @@ -1778,9 +1760,38 @@ if(copy_to_user((void *)arg, GMStatus, sizeof(struct mxser_mstatus) * MAX_PORTS)) return -EFAULT; return 0; + default: + return (-ENOIOCTLCMD); + case MOXA_LOAD_BIOS: + case MOXA_FIND_BOARD: + case MOXA_LOAD_C320B: + case MOXA_LOAD_CODE: + break; + } + + if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str))) + return -EFAULT; + if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS) + return -EINVAL; + + switch(cmd) + { + case MOXA_LOAD_BIOS: + i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len); + return (i); + case MOXA_FIND_BOARD: + return moxafindcard(dltmp.cardno); + case MOXA_LOAD_C320B: + moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len); + default: /* to keep gcc happy */ + return (0); + case MOXA_LOAD_CODE: + i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len); + if (i == -1) + return (-EFAULT); + return (i); } - return (-ENOIOCTLCMD); } int MoxaDriverPoll(void) diff -u --recursive --new-file v2.4.9/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c --- v2.4.9/linux/drivers/char/msbusmouse.c Mon Jun 19 13:25:06 2000 +++ linux/drivers/char/msbusmouse.c Thu Sep 13 15:21:32 2001 @@ -167,3 +167,6 @@ module_init(ms_bus_mouse_init) module_exit(ms_bus_mouse_exit) + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/mxser.c linux/drivers/char/mxser.c --- v2.4.9/linux/drivers/char/mxser.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/mxser.c Thu Sep 13 15:21:32 2001 @@ -180,10 +180,13 @@ MODULE_AUTHOR("William Chen"); MODULE_DESCRIPTION("MOXA Smartio Family Multiport Board Device Driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(ioaddr, "1-4i"); MODULE_PARM(ttymajor, "i"); MODULE_PARM(calloutmajor, "i"); MODULE_PARM(verbose, "i"); + +EXPORT_NO_SYMBOLS; struct mxser_hwconf { int board_type; diff -u --recursive --new-file v2.4.9/linux/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c --- v2.4.9/linux/drivers/char/n_hdlc.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/n_hdlc.c Thu Sep 13 15:21:32 2001 @@ -1031,3 +1031,6 @@ module_init(n_hdlc_init); module_exit(n_hdlc_exit); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/n_r3964.c linux/drivers/char/n_r3964.c --- v2.4.9/linux/drivers/char/n_r3964.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/n_r3964.c Thu Sep 13 15:21:32 2001 @@ -1473,3 +1473,7 @@ return -1; } + +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/nvram.c linux/drivers/char/nvram.c --- v2.4.9/linux/drivers/char/nvram.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/nvram.c Fri Sep 14 14:40:00 2001 @@ -43,7 +43,7 @@ /* select machine configuration */ #if defined(CONFIG_ATARI) #define MACH ATARI -#elif defined(__i386__) || defined(__arm__) /* and others?? */ +#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */ #define MACH PC #else #error Cannot build nvram driver for this machine configuration. @@ -695,9 +695,14 @@ #endif /* MACH == ATARI */ +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; + /* * Local variables: * c-indent-level: 4 * tab-width: 4 * End: */ + diff -u --recursive --new-file v2.4.9/linux/drivers/char/nwbutton.c linux/drivers/char/nwbutton.c --- v2.4.9/linux/drivers/char/nwbutton.c Sun Aug 13 09:54:15 2000 +++ linux/drivers/char/nwbutton.c Fri Sep 14 14:04:07 2001 @@ -47,6 +47,8 @@ * Because callbacks can be unregistered at random the list can become * fragmented, so we need to search through the list until we find the first * free entry. + * + * FIXME: Has anyone spotted any locking functions int his code recently ?? */ int button_add_callback (void (*callback) (void), int count) @@ -236,6 +238,9 @@ misc_deregister (&button_misc_device); } + +MODULE_AUTHOR("Alex Holden"); +MODULE_LICENSE("GPL"); EXPORT_NO_SYMBOLS; module_init(nwbutton_init); diff -u --recursive --new-file v2.4.9/linux/drivers/char/nwflash.c linux/drivers/char/nwflash.c --- v2.4.9/linux/drivers/char/nwflash.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/char/nwflash.c Thu Sep 13 15:21:32 2001 @@ -688,6 +688,8 @@ EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); + MODULE_PARM(flashdebug, "i"); module_init(nwflash_init); 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 Mon Sep 17 22:52:35 2001 @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include #include @@ -395,6 +397,32 @@ return 0200; } +void pckbd_pm_resume(void) +{ +#if defined CONFIG_PSMOUSE + unsigned long flags; + + if (queue) { /* Aux port detected */ + if (aux_count == 0) { /* Mouse not in use */ + spin_lock_irqsave(&kbd_controller_lock, flags); + /* + * Dell Lat. C600 A06 enables mouse after resume. + * When user touches the pad, it posts IRQ 12 + * (which we do not process), thus holding keyboard. + */ + kbd_write_command(KBD_CCMD_MOUSE_DISABLE); + /* kbd_write_cmd(AUX_INTS_OFF); */ /* Config & lock */ + kb_wait(); + kbd_write_command(KBD_CCMD_WRITE_MODE); + kb_wait(); + kbd_write_output(AUX_INTS_OFF); + spin_unlock_irqrestore(&kbd_controller_lock, flags); + } + } +#endif +} + + static inline void handle_mouse_event(unsigned char scancode) { #ifdef CONFIG_PSMOUSE @@ -519,7 +547,7 @@ mdelay(1); if (!--timeout) { #ifdef KBD_REPORT_TIMEOUTS - printk(KERN_WARNING "keyboard: Timeout - AT keyboard not present?\n"); + printk(KERN_WARNING "keyboard: Timeout - AT keyboard not present?(%02x)\n", data); #endif return 0; } @@ -602,7 +630,7 @@ return 1; } -int pckbd_rate(struct kbd_repeat *rep) +static int pckbd_rate(struct kbd_repeat *rep) { if (rep == NULL) return -EINVAL; @@ -705,6 +733,53 @@ spin_unlock_irqrestore(&kbd_controller_lock, flags); } +#if defined(__alpha__) +/* + * Some Alphas cannot mask some/all interrupts, so we have to + * make sure not to allow interrupts AT ALL when polling for + * specific return values from the keyboard. + * + * I think this should work on any architecture, but for now, only Alpha. + */ +static int kbd_write_command_w_and_wait(int data) +{ + unsigned long flags; + int input; + + spin_lock_irqsave(&kbd_controller_lock, flags); + kb_wait(); + kbd_write_command(data); + input = kbd_wait_for_input(); + spin_unlock_irqrestore(&kbd_controller_lock, flags); + return input; +} + +static int kbd_write_output_w_and_wait(int data) +{ + unsigned long flags; + int input; + + spin_lock_irqsave(&kbd_controller_lock, flags); + kb_wait(); + kbd_write_output(data); + input = kbd_wait_for_input(); + spin_unlock_irqrestore(&kbd_controller_lock, flags); + return input; +} +#else +static int kbd_write_command_w_and_wait(int data) +{ + kbd_write_command_w(data); + return kbd_wait_for_input(); +} + +static int kbd_write_output_w_and_wait(int data) +{ + kbd_write_output_w(data); + return kbd_wait_for_input(); +} +#endif /* __alpha__ */ + #if defined CONFIG_PSMOUSE static void kbd_write_cmd(int cmd) { @@ -788,8 +863,8 @@ | KBD_MODE_KCC); /* ibm powerpc portables need this to use scan-code set 1 -- Cort */ - kbd_write_command_w(KBD_CCMD_READ_MODE); - if (!(kbd_wait_for_input() & KBD_MODE_KCC)) { + if (!(kbd_write_command_w_and_wait(KBD_CCMD_READ_MODE) & KBD_MODE_KCC)) + { /* * If the controller does not support conversion, * Set the keyboard to scan-code set 1. @@ -800,20 +875,16 @@ kbd_wait_for_input(); } - - kbd_write_output_w(KBD_CMD_ENABLE); - if (kbd_wait_for_input() != KBD_REPLY_ACK) + if (kbd_write_output_w_and_wait(KBD_CMD_ENABLE) != KBD_REPLY_ACK) return "Enable keyboard: no ACK"; /* * Finally, set the typematic rate to maximum. */ - kbd_write_output_w(KBD_CMD_SET_RATE); - if (kbd_wait_for_input() != KBD_REPLY_ACK) - return "Set rate: no ACK"; - kbd_write_output_w(0x00); - if (kbd_wait_for_input() != KBD_REPLY_ACK) + if (kbd_write_output_w_and_wait(KBD_CMD_SET_RATE) != KBD_REPLY_ACK) return "Set rate: no ACK"; + if (kbd_write_output_w_and_wait(0x00) != KBD_REPLY_ACK) + return "Set rate: no 2nd ACK"; return NULL; } @@ -835,6 +906,8 @@ psaux_init(); #endif + kbd_rate = pckbd_rate; + /* Ok, finally allocate the IRQ, and off we go.. */ kbd_request_irq(keyboard_interrupt); } @@ -1105,13 +1178,20 @@ static int __init psaux_init(void) { + int retval; + if (!detect_auxiliary_port()) return -EIO; - misc_register(&psaux_mouse); + if ((retval = misc_register(&psaux_mouse))) + return retval; + queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); - if (queue == NULL) - panic("psaux_init(): out of memory"); + if (queue == NULL) { + printk(KERN_ERR "psaux_init(): out of memory\n"); + misc_deregister(&psaux_mouse); + return -ENOMEM; + } memset(queue, 0, sizeof(*queue)); queue->head = queue->tail = 0; init_waitqueue_head(&queue->proc_list); diff -u --recursive --new-file v2.4.9/linux/drivers/char/pcmcia/serial_cs.c linux/drivers/char/pcmcia/serial_cs.c --- v2.4.9/linux/drivers/char/pcmcia/serial_cs.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/pcmcia/serial_cs.c Thu Sep 13 15:21:32 2001 @@ -663,3 +663,5 @@ module_init(init_serial_cs); module_exit(exit_serial_cs); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c --- v2.4.9/linux/drivers/char/pcwd.c Thu May 24 15:14:08 2001 +++ linux/drivers/char/pcwd.c Thu Sep 13 15:21:32 2001 @@ -656,3 +656,7 @@ module_init(pcwatchdog_init); module_exit(pcwatchdog_exit); + +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c --- v2.4.9/linux/drivers/char/pcxx.c Tue May 22 10:23:16 2001 +++ linux/drivers/char/pcxx.c Thu Sep 13 15:21:32 2001 @@ -113,6 +113,7 @@ # if (LINUX_VERSION_CODE > 0x020111) MODULE_AUTHOR("Bernhard Kaindl"); MODULE_DESCRIPTION("Digiboard PC/X{i,e,eve} driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(verbose, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(io, "1-4i"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c --- v2.4.9/linux/drivers/char/ppdev.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/ppdev.c Thu Sep 13 15:21:32 2001 @@ -118,7 +118,7 @@ return -EINVAL; } - kbuffer = kmalloc(min(unsigned int, count, PP_BUFFER_SIZE), GFP_KERNEL); + kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL); if (!kbuffer) { return -ENOMEM; } @@ -126,7 +126,7 @@ mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); while (bytes_read < count) { - ssize_t need = min(unsigned long, count - bytes_read, PP_BUFFER_SIZE); + ssize_t need = min_t(unsigned long, count - bytes_read, PP_BUFFER_SIZE); if (mode == IEEE1284_MODE_EPP) { /* various specials for EPP mode */ @@ -198,7 +198,7 @@ return -EINVAL; } - kbuffer = kmalloc(min(unsigned int, count, PP_BUFFER_SIZE), GFP_KERNEL); + kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL); if (!kbuffer) { return -ENOMEM; } @@ -206,7 +206,7 @@ mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); while (bytes_written < count) { - ssize_t n = min(unsigned long, count - bytes_written, PP_BUFFER_SIZE); + ssize_t n = min_t(unsigned long, count - bytes_written, PP_BUFFER_SIZE); if (copy_from_user (kbuffer, buf + bytes_written, n)) { bytes_written = -EFAULT; @@ -754,3 +754,7 @@ module_init(ppdev_init); module_exit(ppdev_cleanup); + +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; 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/qtronix.c linux/drivers/char/qtronix.c --- v2.4.9/linux/drivers/char/qtronix.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/char/qtronix.c Sun Sep 9 10:43:02 2001 @@ -6,7 +6,7 @@ * * Copyright 2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * ppopov@mvista.com or support@mvista.com + * ppopov@mvista.com or source@mvista.com * * * The bottom portion of this driver was take from @@ -71,7 +71,7 @@ #include #include #include -#include +#include #include #include #include @@ -353,19 +353,19 @@ static unsigned char handle_kbd_event(void); -int pckbd_setkeycode(unsigned int scancode, unsigned int keycode) +int kbd_setkeycode(unsigned int scancode, unsigned int keycode) { - printk("pckbd_setkeycode scancode %x keycode %x\n", scancode, keycode); + printk("kbd_setkeycode scancode %x keycode %x\n", scancode, keycode); return 0; } -int pckbd_getkeycode(unsigned int scancode) +int kbd_getkeycode(unsigned int scancode) { return scancode; } -int pckbd_translate(unsigned char scancode, unsigned char *keycode, +int kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) { static int prev_scancode = 0; @@ -406,9 +406,9 @@ return 1; } -char pckbd_unexpected_up(unsigned char keycode) +char kbd_unexpected_up(unsigned char keycode) { - //printk("pckbd_unexpected_up\n"); + //printk("kbd_unexpected_up\n"); return 0; } @@ -422,12 +422,12 @@ } -void pckbd_leds(unsigned char leds) +void kbd_leds(unsigned char leds) { } /* dummy */ -void pckbd_init_hw(void) +void kbd_init_hw(void) { } diff -u --recursive --new-file v2.4.9/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.4.9/linux/drivers/char/random.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/char/random.c Mon Sep 17 22:52:35 2001 @@ -717,6 +717,10 @@ } else { time = jiffies; } +#elif defined (__x86_64__) + __u32 high; + rdtsc(time, high); + num ^= high; #else time = jiffies; #endif @@ -1587,12 +1591,9 @@ return -EPERM; p = (int *) arg; ent_count = random_state->entropy_count; - if (put_user(ent_count, p++)) - return -EFAULT; - - if (get_user(size, p)) - return -EFAULT; - if (put_user(random_state->poolinfo.poolwords, p++)) + if (put_user(ent_count, p++) || + get_user(size, p) || + put_user(random_state->poolinfo.poolwords, p++)) return -EFAULT; if (size < 0) return -EINVAL; @@ -1805,13 +1806,13 @@ if (uuid[8] == 0) generate_random_uuid(uuid); - get_user(len, oldlenp); + if (get_user(len, oldlenp)) + return -EFAULT; if (len) { if (len > 16) len = 16; - if (copy_to_user(oldval, uuid, len)) - return -EFAULT; - if (put_user(len, oldlenp)) + if (copy_to_user(oldval, uuid, len) || + put_user(len, oldlenp)) return -EFAULT; } return 1; diff -u --recursive --new-file v2.4.9/linux/drivers/char/raw.c linux/drivers/char/raw.c --- v2.4.9/linux/drivers/char/raw.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/char/raw.c Mon Sep 17 13:25:21 2001 @@ -20,8 +20,6 @@ #define dprintk(x...) typedef struct raw_device_data_s { - struct kiobuf * iobuf; - long iobuf_lock; struct block_device *binding; int inuse, sector_size, sector_bits; struct semaphore mutex; @@ -87,6 +85,12 @@ return 0; } + if (!filp->f_iobuf) { + err = alloc_kiovec(1, &filp->f_iobuf); + if (err) + return err; + } + down(&raw_devices[minor].mutex); /* * No, it is a normal raw device. All we need to do on open is @@ -113,19 +117,6 @@ goto out; /* - * We'll just use one kiobuf - */ - - err = alloc_kiovec(1, &raw_devices[minor].iobuf); - if (err) { - raw_devices[minor].inuse--; - up(&raw_devices[minor].mutex); - blkdev_put(bdev, BDEV_RAW); - return err; - } - - - /* * Don't interfere with mounted devices: we cannot safely set * the blocksize on a device which is already mounted. */ @@ -160,8 +151,7 @@ minor = MINOR(inode->i_rdev); down(&raw_devices[minor].mutex); bdev = raw_devices[minor].binding; - if (!--raw_devices[minor].inuse) - free_kiovec(1, &raw_devices[minor].iobuf); + raw_devices[minor].inuse--; up(&raw_devices[minor].mutex); blkdev_put(bdev, BDEV_RAW); return 0; @@ -300,8 +290,8 @@ minor = MINOR(filp->f_dentry->d_inode->i_rdev); new_iobuf = 0; - iobuf = raw_devices[minor].iobuf; - if (test_and_set_bit(0, &raw_devices[minor].iobuf_lock)) { + iobuf = filp->f_iobuf; + if (test_and_set_bit(0, &filp->f_iobuf_lock)) { /* * A parallel read/write is using the preallocated iobuf * so just run slow and allocate a new one. @@ -384,7 +374,7 @@ out_free: if (!new_iobuf) - clear_bit(0, &raw_devices[minor].iobuf_lock); + clear_bit(0, &filp->f_iobuf_lock); else free_kiovec(1, &iobuf); out: 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/rio/riointr.c linux/drivers/char/rio/riointr.c --- v2.4.9/linux/drivers/char/rio/riointr.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/rio/riointr.c Mon Sep 10 09:04:53 2001 @@ -819,7 +819,7 @@ ** and available space. */ - transCount = min(unsigned int, PacketP->len & PKT_LEN_MASK, + transCount = min_t(unsigned int, PacketP->len & PKT_LEN_MASK, TTY_FLIPBUF_SIZE - TtyP->flip.count); rio_dprintk (RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount); diff -u --recursive --new-file v2.4.9/linux/drivers/char/rio/riotable.c linux/drivers/char/rio/riotable.c --- v2.4.9/linux/drivers/char/rio/riotable.c Wed Jul 25 17:10:19 2001 +++ linux/drivers/char/rio/riotable.c Fri Sep 14 14:39:59 2001 @@ -445,7 +445,7 @@ int Next = 0; struct Map *MapP; struct Host *HostP; - int oldspl; + long oldspl; disable(oldspl); /* strange but true! */ diff -u --recursive --new-file v2.4.9/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c --- v2.4.9/linux/drivers/char/riscom8.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/riscom8.c Thu Sep 13 15:21:32 2001 @@ -1906,6 +1906,8 @@ MODULE_PARM(iobase1, "i"); MODULE_PARM(iobase2, "i"); MODULE_PARM(iobase3, "i"); + +MODULE_LICENSE("GPL"); #endif /* MODULE */ /* diff -u --recursive --new-file v2.4.9/linux/drivers/char/rocket.c linux/drivers/char/rocket.c --- v2.4.9/linux/drivers/char/rocket.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/char/rocket.c Thu Sep 13 15:21:32 2001 @@ -157,6 +157,7 @@ #if ((LINUX_VERSION_CODE > 0x020111) && defined(MODULE)) MODULE_AUTHOR("Theodore Ts'o"); MODULE_DESCRIPTION("Comtrol Rocketport driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(board1, "i"); MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1"); MODULE_PARM(board2, "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/rtc.c linux/drivers/char/rtc.c --- v2.4.9/linux/drivers/char/rtc.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/rtc.c Sun Sep 9 10:43:02 2001 @@ -40,9 +40,10 @@ * 1.10b Andrew Morton: SMP lock fix * 1.10c Cesar Barros: SMP locking fixes and cleanup * 1.10d Paul Gortmaker: delete paranoia check in rtc_exit + * 1.10e Maciej W. Rozycki: Handle DECstation's year weirdness. */ -#define RTC_VERSION "1.10d" +#define RTC_VERSION "1.10e" #define RTC_IO_EXTENT 0x10 /* Only really two ports, but... */ @@ -361,6 +362,9 @@ unsigned char mon, day, hrs, min, sec, leap_yr; unsigned char save_control, save_freq_select; unsigned int yrs; +#ifdef CONFIG_DECSTATION + unsigned int real_yrs; +#endif if (!capable(CAP_SYS_TIME)) return -EACCES; @@ -394,6 +398,20 @@ return -EINVAL; spin_lock_irq(&rtc_lock); +#ifdef CONFIG_DECSTATION + real_yrs = yrs; + yrs = 72; + + /* + * We want to keep the year set to 73 until March + * for non-leap years, so that Feb, 29th is handled + * correctly. + */ + if (!leap_yr && mon < 3) { + real_yrs--; + yrs = 73; + } +#endif if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { if (yrs > 169) { @@ -416,6 +434,9 @@ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); +#ifdef CONFIG_DECSTATION + CMOS_WRITE(real_yrs, RTC_DEC_YEAR); +#endif CMOS_WRITE(yrs, RTC_YEAR); CMOS_WRITE(mon, RTC_MONTH); CMOS_WRITE(day, RTC_DAY_OF_MONTH); @@ -469,7 +490,7 @@ spin_unlock_irq(&rtc_lock); return 0; } -#elif !defined(CONFIG_DECSTATION) +#endif case RTC_EPOCH_READ: /* Read the epoch. */ { return put_user (epoch, (unsigned long *)arg); @@ -488,7 +509,6 @@ epoch = arg; return 0; } -#endif default: return -EINVAL; } @@ -709,12 +729,12 @@ } else if (year >= 20 && year < 48) { epoch = 1980; guess = "ARC console"; - } else if (year >= 48 && year < 70) { + } else if (year >= 48 && year < 72) { epoch = 1952; guess = "Digital UNIX"; #if defined(__mips__) - } else if (year >= 70 && year < 100) { - epoch = 1928; + } else if (year >= 72 && year < 74) { + epoch = 2000; guess = "Digital DECstation"; #else } else if (year >= 70) { @@ -911,6 +931,9 @@ { unsigned long uip_watchdog = jiffies; unsigned char ctrl; +#ifdef CONFIG_DECSTATION + unsigned int real_year; +#endif /* * read RTC once any update in progress is done. The update @@ -939,6 +962,9 @@ rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); rtc_tm->tm_year = CMOS_READ(RTC_YEAR); +#ifdef CONFIG_DECSTATION + real_year = CMOS_READ(RTC_DEC_YEAR); +#endif ctrl = CMOS_READ(RTC_CONTROL); spin_unlock_irq(&rtc_lock); @@ -952,6 +978,10 @@ BCD_TO_BIN(rtc_tm->tm_year); } +#ifdef CONFIG_DECSTATION + rtc_tm->tm_year += real_year - 72; +#endif + /* * Account for differences between how the RTC uses the values * and how they are defined in a struct rtc_time; @@ -1024,3 +1054,6 @@ spin_unlock_irq(&rtc_lock); } #endif + +MODULE_AUTHOR("Paul Gortmaker"); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/sbc60xxwdt.c linux/drivers/char/sbc60xxwdt.c --- v2.4.9/linux/drivers/char/sbc60xxwdt.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/sbc60xxwdt.c Thu Sep 13 15:21:32 2001 @@ -340,3 +340,6 @@ module_init(sbc60xxwdt_init); module_exit(sbc60xxwdt_unload); + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; 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/ser_a2232.c linux/drivers/char/ser_a2232.c --- v2.4.9/linux/drivers/char/ser_a2232.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/char/ser_a2232.c Thu Sep 13 15:21:32 2001 @@ -878,3 +878,7 @@ } #endif /***************************** End of Functions *********************/ + +MODULE_AUTHOR("Enver Haase"); +MODULE_DESCRIPTION("Amiga A2232 multi-serial board driver"); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.4.9/linux/drivers/char/serial.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/serial.c Mon Sep 17 13:16:30 2001 @@ -1766,11 +1766,13 @@ if (I_IGNPAR(info->tty)) info->ignore_status_mask |= UART_LSR_OE; } +#if 0 /* breaks serial console during boot stage */ /* * !!! ignore all characters if CREAD is not set */ if ((cflag & CREAD) == 0) info->ignore_status_mask |= UART_LSR_DR; +#endif save_flags(flags); cli(); if (uart_config[info->state->type].flags & UART_STARTECH) { serial_outp(info, UART_LCR, 0xBF); @@ -5719,6 +5721,7 @@ module_exit(rs_fini); MODULE_DESCRIPTION("Standard/generic (dumb) serial driver"); MODULE_AUTHOR("Theodore Ts'o "); +MODULE_LICENSE("GPL"); /* @@ -5762,7 +5765,7 @@ * Print a string to the serial port trying not to disturb * any possible real use of the port... * - * The console_lock must be held when we get here. + * The console must be locked when we get here. */ static void serial_console_write(struct console *co, const char *s, unsigned count) diff -u --recursive --new-file v2.4.9/linux/drivers/char/serial167.c linux/drivers/char/serial167.c --- v2.4.9/linux/drivers/char/serial167.c Wed May 16 10:31:27 2001 +++ linux/drivers/char/serial167.c Sun Sep 16 21:23:07 2001 @@ -2743,7 +2743,7 @@ * Of course, once the console has been registered, we had better ensure * that serial167_init() doesn't leave the chip non-functional. * - * The console_lock must be held when we get here. + * The console must be locked when we get here. */ void serial167_console_write(struct console *co, const char *str, unsigned count) @@ -3084,3 +3084,5 @@ } /* debug_setup */ #endif + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/serial_21285.c linux/drivers/char/serial_21285.c --- v2.4.9/linux/drivers/char/serial_21285.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/serial_21285.c Thu Sep 13 15:21:32 2001 @@ -505,3 +505,6 @@ } #endif /* CONFIG_SERIAL_21285_CONSOLE */ + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/char/serial_amba.c linux/drivers/char/serial_amba.c --- v2.4.9/linux/drivers/char/serial_amba.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/serial_amba.c Sun Sep 16 21:23:14 2001 @@ -1881,7 +1881,7 @@ * Print a string to the serial port trying not to disturb * any possible real use of the port... * - * The console_lock must be held when we get here. + * The console must be locked when we get here. */ static void ambauart_console_write(struct console *co, const char *s, u_int count) { @@ -2027,3 +2027,6 @@ } #endif /* CONFIG_SERIAL_AMBA_CONSOLE */ + +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; 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 Fri Sep 14 14:04:08 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 = { @@ -909,13 +911,10 @@ (unsigned int *) arg); break; case TIOCSSOFTCAR: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(int))) == 0) { - get_user(ival, (unsigned int *) arg); + if ((rc = get_user(ival, (unsigned int *) arg)) == 0) tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); - } break; case TIOCGSERIAL: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, @@ -929,35 +928,23 @@ (struct serial_struct *) arg); break; case TIOCMGET: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int))) == 0) { - ival = sci_getsignals(port); - put_user(ival, (unsigned int *) arg); - } + ival = sci_getsignals(port); + rc = put_user(ival, (unsigned int *) arg); break; case TIOCMBIS: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *) arg); + if ((rc = get_user(ival, (unsigned int *) arg)) == 0) sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), ((ival & TIOCM_RTS) ? 1 : -1)); - } break; case TIOCMBIC: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *) arg); + if ((rc = get_user(ival, (unsigned int *) arg)) == 0) sci_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), ((ival & TIOCM_RTS) ? 0 : -1)); - } break; case TIOCMSET: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *)arg); + if ((rc = get_user(ival, (unsigned int *)arg)) == 0) sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), ((ival & TIOCM_RTS) ? 1 : 0)); - } break; default: @@ -1144,22 +1131,25 @@ } } +static char banner[] __initdata[] = + KERN_INFO "SuperH SCI(F) driver initialized\n"; + int __init sci_init(void) { struct sci_port *port; int j; - printk("SuperH SCI(F) driver initialized\n"); + printk("%s", banner); for (j=0; jbase, + printk(KERN_INFO "ttySC%d at 0x%08x is a %s\n", j, port->base, (port->type == PORT_SCI) ? "SCI" : "SCIF"); } 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/sonypi.c linux/drivers/char/sonypi.c --- v2.4.9/linux/drivers/char/sonypi.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/char/sonypi.c Mon Sep 17 22:52:35 2001 @@ -48,6 +48,7 @@ static int verbose; /* = 0 */ static int fnkeyinit; /* = 0 */ static int camera; /* = 0 */ +extern int is_sony_vaio_laptop; /* set in DMI table parse routines */ /* Inits the queue */ static inline void sonypi_initq(void) { @@ -108,32 +109,23 @@ } static void sonypi_ecrset(u16 addr, u16 value) { - int n = 100; - while (n-- && (inw_p(SONYPI_CST_IOPORT) & 3)) - udelay(1); + wait_on_command(inw_p(SONYPI_CST_IOPORT) & 3); outw_p(0x81, SONYPI_CST_IOPORT); - while (inw_p(SONYPI_CST_IOPORT) & 2) - udelay(1); + wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2); outw_p(addr, SONYPI_DATA_IOPORT); - while (inw_p(SONYPI_CST_IOPORT) & 2) - udelay(1); + wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2); outw_p(value, SONYPI_DATA_IOPORT); - while (inw_p(SONYPI_CST_IOPORT) & 2) - udelay(1); + wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2); } static u16 sonypi_ecrget(u16 addr) { - int n = 100; - while (n-- && (inw_p(SONYPI_CST_IOPORT) & 3)) - udelay(1); + wait_on_command(inw_p(SONYPI_CST_IOPORT) & 3); outw_p(0x80, SONYPI_CST_IOPORT); - while (inw_p(SONYPI_CST_IOPORT) & 2) - udelay(1); + wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2); outw_p(addr, SONYPI_DATA_IOPORT); - while (inw_p(SONYPI_CST_IOPORT) & 2) - udelay(1); + wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2); return inw_p(SONYPI_DATA_IOPORT); } @@ -189,8 +181,7 @@ static u8 sonypi_call1(u8 dev) { u8 v1, v2; - while (inb_p(sonypi_device.ioport2) & 2) - udelay(1); + wait_on_command(inb_p(sonypi_device.ioport2) & 2); outb(dev, sonypi_device.ioport2); v1 = inb_p(sonypi_device.ioport2); v2 = inb_p(sonypi_device.ioport1); @@ -200,14 +191,10 @@ static u8 sonypi_call2(u8 dev, u8 fn) { u8 v1; - while (inb_p(sonypi_device.ioport2) & 2) - udelay(1); + wait_on_command(inb_p(sonypi_device.ioport2) & 2); outb(dev, sonypi_device.ioport2); - - while (inb_p(sonypi_device.ioport2) & 2) - udelay(1); + wait_on_command(inb_p(sonypi_device.ioport2) & 2); outb(fn, sonypi_device.ioport1); - v1 = inb_p(sonypi_device.ioport1); return v1; } @@ -215,18 +202,12 @@ static u8 sonypi_call3(u8 dev, u8 fn, u8 v) { u8 v1; - while (inb_p(sonypi_device.ioport2) & 2) - udelay(1); + wait_on_command(inb_p(sonypi_device.ioport2) & 2); outb(dev, sonypi_device.ioport2); - - while (inb_p(sonypi_device.ioport2) & 2) - udelay(1); + wait_on_command(inb_p(sonypi_device.ioport2) & 2); outb(fn, sonypi_device.ioport1); - - while (inb_p(sonypi_device.ioport2) & 2) - udelay(1); + wait_on_command(inb_p(sonypi_device.ioport2) & 2); outb(v, sonypi_device.ioport1); - v1 = inb_p(sonypi_device.ioport1); return v1; } @@ -246,11 +227,8 @@ /* Set brightness, hue etc */ static void sonypi_set(u8 fn, u8 v) { - int n = 100; - while (n--) - if (sonypi_call3(0x90, fn, v) == 0) - break; + wait_on_command(sonypi_call3(0x90, fn, v)); } /* Tests if the camera is ready */ @@ -325,6 +303,13 @@ v1 = inb_p(sonypi_device.ioport1); v2 = inb_p(sonypi_device.ioport2); + if ((v2 & SONYPI_NORMAL_PKEY_EV) == SONYPI_NORMAL_PKEY_EV) { + for (i = 0; sonypi_pkeyev[i].event; i++) + if (sonypi_pkeyev[i].data == v1) { + event = sonypi_pkeyev[i].event; + goto found; + } + } if ((v2 & sonypi_jogger_ev) == sonypi_jogger_ev) { for (i = 0; sonypi_joggerev[i].event; i++) if (sonypi_joggerev[i].data == v1) { @@ -608,7 +593,7 @@ for (i = 0; irq_list[i].irq; i++) { if (!request_irq(irq_list[i].irq, sonypi_irq, - SA_INTERRUPT, "sonypi", sonypi_irq)) { + SA_SHIRQ, "sonypi", sonypi_irq)) { sonypi_device.irq = irq_list[i].irq; sonypi_device.bits = irq_list[i].bits; break; @@ -690,7 +675,10 @@ }; static int __init sonypi_init_module(void) { - return pci_module_init(&sonypi_driver); + if (is_sony_vaio_laptop) + return pci_module_init(&sonypi_driver); + else + return -ENODEV; } static void __exit sonypi_cleanup_module(void) { @@ -703,6 +691,8 @@ MODULE_AUTHOR("Stelian Pop "); MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver"); +MODULE_LICENSE("GPL"); + MODULE_PARM(minor,"i"); MODULE_PARM_DESC(minor, "minor number of the misc device, default is -1 (automatic)"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/sonypi.h linux/drivers/char/sonypi.h --- v2.4.9/linux/drivers/char/sonypi.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/char/sonypi.h Mon Sep 17 22:52:35 2001 @@ -35,7 +35,7 @@ #ifdef __KERNEL__ #define SONYPI_DRIVER_MAJORVERSION 1 -#define SONYPI_DRIVER_MINORVERSION 2 +#define SONYPI_DRIVER_MINORVERSION 5 #include #include @@ -138,6 +138,7 @@ #define SONYPI_NORMAL_FNKEY_EV 0x20 #define SONYPI_R505_FNKEY_EV 0x08 #define SONYPI_BLUETOOTH_EV 0x30 +#define SONYPI_NORMAL_PKEY_EV 0x40 struct sonypi_event { u8 data; @@ -189,6 +190,14 @@ { 0x00, 0x00 } }; +/* The set of possible program key events */ +static struct sonypi_event sonypi_pkeyev[] = { + { 0x01, SONYPI_EVENT_PKEY_P1 }, + { 0x02, SONYPI_EVENT_PKEY_P2 }, + { 0x04, SONYPI_EVENT_PKEY_P3 }, + { 0x00, 0x00 } +}; + /* The set of possible bluetooth events */ static struct sonypi_event sonypi_blueev[] = { { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED }, @@ -222,6 +231,14 @@ int open_count; int model; }; + +#define wait_on_command(command) { \ + unsigned int n = 10000; \ + while (--n && (command)) \ + udelay(1); \ + if (!n) \ + printk(KERN_WARNING "sonypi command failed at " __FILE__ " : " __FUNCTION__ "(line %d)\n", __LINE__); \ +} #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/drivers/char/specialix.c linux/drivers/char/specialix.c --- v2.4.9/linux/drivers/char/specialix.c Wed May 16 10:31:27 2001 +++ linux/drivers/char/specialix.c Thu Sep 13 15:21:32 2001 @@ -2440,3 +2440,5 @@ } #endif /* MODULE */ + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/char/stallion.c linux/drivers/char/stallion.c --- v2.4.9/linux/drivers/char/stallion.c Fri Mar 2 11:12:07 2001 +++ linux/drivers/char/stallion.c Thu Sep 13 15:21:32 2001 @@ -314,6 +314,7 @@ */ MODULE_AUTHOR("Greg Ungerer"); MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(board0, "1-4s"); MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]"); 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/synclink.c linux/drivers/char/synclink.c --- v2.4.9/linux/drivers/char/synclink.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/synclink.c Fri Sep 14 14:39:59 2001 @@ -934,6 +934,8 @@ }; MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); +MODULE_LICENSE("GPL"); + static struct pci_driver synclink_pci_driver = { name: "synclink", id_table: synclink_pci_tbl, @@ -8013,7 +8015,8 @@ int mgsl_sppp_open(struct net_device *d) { struct mgsl_struct *info = d->priv; - int err, flags; + int err; + long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("mgsl_sppp_open(%s)\n",info->netname); @@ -8056,7 +8059,7 @@ void mgsl_sppp_tx_timeout(struct net_device *dev) { struct mgsl_struct *info = dev->priv; - int flags; + long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("mgsl_sppp_tx_timeout(%s)\n",info->netname); diff -u --recursive --new-file v2.4.9/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- v2.4.9/linux/drivers/char/sysrq.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/sysrq.c Mon Sep 17 22:52:35 2001 @@ -6,6 +6,10 @@ * * (c) 1997 Martin Mares * based on ideas by Pavel Machek + * + * (c) 2000 Crutcher Dunnavant + * overhauled to use key registration + * based upon discusions in irc://irc.openprojects.net/#kernelnewbies */ #include @@ -24,8 +28,11 @@ #include #include +#include + #include +extern void wakeup_bdflush(int); extern void reset_vc(unsigned int); extern struct list_head super_blocks; @@ -35,136 +42,83 @@ /* Machine specific power off function */ void (*sysrq_power_off)(void); -EXPORT_SYMBOL(sysrq_power_off); - -/* Send a signal to all user processes */ +/* Loglevel sysrq handler */ +static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + int i; + i = key - '0'; + console_loglevel = 7; + printk("%d\n", i); + console_loglevel = i; +} +static struct sysrq_key_op sysrq_loglevel_op = { + handler: sysrq_handle_loglevel, + help_msg: "loglevel0-8", + action_msg: "Loglevel set to ", +}; -static void send_sig_all(int sig, int even_init) -{ - struct task_struct *p; - for_each_task(p) { - if (p->mm) { /* Not swapper nor kernel thread */ - if (p->pid == 1 && even_init) /* Ugly hack to kill init */ - p->pid = 0x8000; - force_sig(sig, p); - } - } +/* SAK sysrq handler */ +#ifdef CONFIG_VT +static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + if (tty) + do_SAK(tty); + reset_vc(fg_console); } +static struct sysrq_key_op sysrq_SAK_op = { + handler: sysrq_handle_SAK, + help_msg: "saK", + action_msg: "SAK\n", +}; +#endif -/* - * This function is called by the keyboard handler when SysRq is pressed - * and any other keycode arrives. - */ -void handle_sysrq(int key, struct pt_regs *pt_regs, - struct kbd_struct *kbd, struct tty_struct *tty) -{ - int orig_log_level = console_loglevel; +/* unraw sysrq handler */ +static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + if (kbd) + kbd->kbdmode = VC_XLATE; +} +static struct sysrq_key_op sysrq_unraw_op = { + handler: sysrq_handle_unraw, + help_msg: "unRaw", + action_msg: "Keyboard mode set to XLATE\n", +}; - if (!sysrq_enabled) - return; - if (!key) - return; +/* reboot sysrq handler */ +static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + machine_restart(NULL); +} +static struct sysrq_key_op sysrq_reboot_op = { + handler: sysrq_handle_reboot, + help_msg: "reBoot", + action_msg: "Resetting\n", +}; - console_loglevel = 7; - printk(KERN_INFO "SysRq: "); - switch (key) { - case 'r': /* R -- Reset raw mode */ - if (kbd) { - kbd->kbdmode = VC_XLATE; - printk("Keyboard mode set to XLATE\n"); - } - break; -#ifdef CONFIG_VT - case 'k': /* K -- SAK */ - printk("SAK\n"); - if (tty) - do_SAK(tty); - reset_vc(fg_console); - break; -#endif - case 'b': /* B -- boot immediately */ - printk("Resetting\n"); - machine_restart(NULL); - break; - case 'o': /* O -- power off */ - if (sysrq_power_off) { - printk("Power off\n"); - sysrq_power_off(); - } - break; - case 's': /* S -- emergency sync */ - printk("Emergency Sync\n"); - emergency_sync_scheduled = EMERG_SYNC; - wakeup_bdflush(); - break; - case 'u': /* U -- emergency remount R/O */ - printk("Emergency Remount R/O\n"); - emergency_sync_scheduled = EMERG_REMOUNT; - wakeup_bdflush(); - break; - case 'p': /* P -- show PC */ - printk("Show Regs\n"); - if (pt_regs) - show_regs(pt_regs); - break; - case 't': /* T -- show task info */ - printk("Show State\n"); - show_state(); - break; - case 'm': /* M -- show memory info */ - printk("Show Memory\n"); - show_mem(); - break; - case '0' ... '9': /* 0-9 -- set console logging level */ - orig_log_level = key - '0'; - printk("Log level set to %d\n", orig_log_level); - break; - case 'e': /* E -- terminate all user processes */ - printk("Terminate All Tasks\n"); - send_sig_all(SIGTERM, 0); - orig_log_level = 8; /* We probably have killed syslogd */ - break; - case 'i': /* I -- kill all user processes */ - printk("Kill All Tasks\n"); - send_sig_all(SIGKILL, 0); - orig_log_level = 8; - break; - case 'l': /* L -- kill all processes including init */ - printk("Kill ALL Tasks (even init)\n"); - send_sig_all(SIGKILL, 1); - orig_log_level = 8; - break; - default: /* Unknown: help */ - if (kbd) - printk("unRaw "); -#ifdef CONFIG_VT - if (tty) - printk("saK "); -#endif - printk("Boot "); - if (sysrq_power_off) - printk("Off "); - printk("Sync Unmount showPc showTasks showMem loglevel0-8 tErm kIll killalL\n"); - /* Don't use 'A' as it's handled specially on the Sparc */ - } - console_loglevel = orig_log_level; -} -/* Aux routines for the syncer */ +/* SYNC SYSRQ HANDLERS BLOCK */ -static int is_local_disk(kdev_t dev) /* Guess if the device is a local hard drive */ -{ - unsigned int major = MAJOR(dev); +/* do_emergency_sync helper function */ +/* Guesses if the device is a local hard drive */ +static int is_local_disk(kdev_t dev) { + unsigned int major; + major = MAJOR(dev); switch (major) { case IDE0_MAJOR: case IDE1_MAJOR: case IDE2_MAJOR: case IDE3_MAJOR: + case IDE4_MAJOR: + case IDE5_MAJOR: + case IDE6_MAJOR: + case IDE7_MAJOR: + case IDE8_MAJOR: + case IDE9_MAJOR: case SCSI_DISK0_MAJOR: case SCSI_DISK1_MAJOR: case SCSI_DISK2_MAJOR: @@ -173,19 +127,24 @@ case SCSI_DISK5_MAJOR: case SCSI_DISK6_MAJOR: case SCSI_DISK7_MAJOR: + case XT_DISK_MAJOR: return 1; default: return 0; } } +/* do_emergency_sync helper function */ static void go_sync(struct super_block *sb, int remount_flag) { + int orig_loglevel; + orig_loglevel = console_loglevel; + console_loglevel = 7; printk(KERN_INFO "%sing device %s ... ", remount_flag ? "Remount" : "Sync", kdevname(sb->s_dev)); - if (remount_flag) { /* Remount R/O */ + if (remount_flag) { /* Remount R/O */ int ret, flags; struct list_head *p; @@ -215,12 +174,12 @@ } } else printk("nothing to do\n"); - } else { - fsync_dev(sb->s_dev); /* Sync only */ + } else { /* Sync only */ + fsync_dev(sb->s_dev); printk("OK\n"); } + console_loglevel = orig_loglevel; } - /* * Emergency Sync or Unmount. We cannot do it directly, so we set a special * flag and wake up the bdflush kernel thread which immediately calls this function. @@ -230,10 +189,10 @@ int emergency_sync_scheduled; -void do_emergency_sync(void) -{ +void do_emergency_sync(void) { struct super_block *sb; int remount_flag; + int orig_loglevel; lock_kernel(); remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT); @@ -252,5 +211,277 @@ go_sync(sb, remount_flag); unlock_kernel(); + + orig_loglevel = console_loglevel; + console_loglevel = 7; printk(KERN_INFO "Done.\n"); + console_loglevel = orig_loglevel; +} + +static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + emergency_sync_scheduled = EMERG_SYNC; + wakeup_bdflush(0); +} +static struct sysrq_key_op sysrq_sync_op = { + handler: sysrq_handle_sync, + help_msg: "Sync", + action_msg: "Emergency Sync\n", +}; + +static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + emergency_sync_scheduled = EMERG_REMOUNT; + wakeup_bdflush(0); +} +static struct sysrq_key_op sysrq_mountro_op = { + handler: sysrq_handle_mountro, + help_msg: "Unmount", + action_msg: "Emergency Remount R/0\n", +}; + +/* END SYNC SYSRQ HANDLERS BLOCK */ + + +/* SHOW SYSRQ HANDLERS BLOCK */ + +static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + if (pt_regs) + show_regs(pt_regs); +} +static struct sysrq_key_op sysrq_showregs_op = { + handler: sysrq_handle_showregs, + help_msg: "showPc", + action_msg: "Show Regs\n", +}; + + +static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + show_state(); +} +static struct sysrq_key_op sysrq_showstate_op = { + handler: sysrq_handle_showstate, + help_msg: "showTasks", + action_msg: "Show State\n", +}; + + +static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + show_mem(); +} +static struct sysrq_key_op sysrq_showmem_op = { + handler: sysrq_handle_showmem, + help_msg: "showMem", + action_msg: "Show Memory\n", +}; + +/* SHOW SYSRQ HANDLERS BLOCK */ + + +/* SIGNAL SYSRQ HANDLERS BLOCK */ + +/* signal sysrq helper function + * Sends a signal to all user processes */ +static void send_sig_all(int sig, int even_init) +{ + struct task_struct *p; + + for_each_task(p) { + if (p->mm) { /* Not swapper nor kernel thread */ + if (p->pid == 1 && even_init) + /* Ugly hack to kill init */ + p->pid = 0x8000; + if (p->pid != 1) + force_sig(sig, p); + } + } +} + +static void sysrq_handle_term(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + send_sig_all(SIGTERM, 0); + console_loglevel = 8; +} +static struct sysrq_key_op sysrq_term_op = { + handler: sysrq_handle_term, + help_msg: "tErm", + action_msg: "Terminate All Tasks\n", +}; + +static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + send_sig_all(SIGKILL, 0); + console_loglevel = 8; +} +static struct sysrq_key_op sysrq_kill_op = { + handler: sysrq_handle_kill, + help_msg: "kIll", + action_msg: "Kill All Tasks\n", +}; + +static void sysrq_handle_killall(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + send_sig_all(SIGKILL, 1); + console_loglevel = 8; +} +static struct sysrq_key_op sysrq_killall_op = { + handler: sysrq_handle_killall, + help_msg: "killalL", + action_msg: "Kill All Tasks (even init)\n", +}; + +/* END SIGNAL SYSRQ HANDLERS BLOCK */ + + +/* Key Operations table and lock */ +spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED; +#define SYSRQ_KEY_TABLE_LENGTH 36 +static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { +/* 0 */ &sysrq_loglevel_op, +/* 1 */ &sysrq_loglevel_op, +/* 2 */ &sysrq_loglevel_op, +/* 3 */ &sysrq_loglevel_op, +/* 4 */ &sysrq_loglevel_op, +/* 5 */ &sysrq_loglevel_op, +/* 6 */ &sysrq_loglevel_op, +/* 7 */ &sysrq_loglevel_op, +/* 8 */ &sysrq_loglevel_op, +/* 9 */ &sysrq_loglevel_op, +/* a */ NULL, /* Don't use for system provided sysrqs, + it is handled specially on the spark + and will never arive */ +/* b */ &sysrq_reboot_op, +/* c */ NULL, +/* d */ NULL, +/* e */ &sysrq_term_op, +/* f */ NULL, +/* g */ NULL, +/* h */ NULL, +/* i */ &sysrq_kill_op, +/* j */ NULL, +#ifdef CONFIG_VT +/* k */ &sysrq_SAK_op, +#else +/* k */ NULL, +#endif +/* l */ &sysrq_killall_op, +/* m */ &sysrq_showmem_op, +/* n */ NULL, +/* o */ NULL, /* This will often be registered + as 'Off' at init time */ +/* p */ &sysrq_showregs_op, +/* q */ NULL, +/* r */ &sysrq_unraw_op, +/* s */ &sysrq_sync_op, +/* t */ &sysrq_showstate_op, +/* u */ &sysrq_mountro_op, +/* v */ NULL, +/* w */ NULL, +/* x */ NULL, +/* w */ NULL, +/* z */ NULL +}; + +/* key2index calculation, -1 on invalid index */ +static __inline__ int sysrq_key_table_key2index(int key) { + int retval; + if ((key >= '0') & (key <= '9')) { + retval = key - '0'; + } else if ((key >= 'a') & (key <= 'z')) { + retval = key + 10 - 'a'; + } else { + retval = -1; + } + return retval; +} + +/* + * table lock and unlocking functions, exposed to modules + */ + +void __sysrq_lock_table (void) { spin_lock(&sysrq_key_table_lock); } + +void __sysrq_unlock_table (void) { spin_unlock(&sysrq_key_table_lock); } + +/* + * get and put functions for the table, exposed to modules. + */ + +struct sysrq_key_op *__sysrq_get_key_op (int key) { + struct sysrq_key_op *op_p; + int i; + + i = sysrq_key_table_key2index(key); + op_p = (i == -1) ? NULL : sysrq_key_table[i]; + return op_p; } + +void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) { + int i; + + i = sysrq_key_table_key2index(key); + if (i != -1) + sysrq_key_table[i] = op_p; +} + +/* + * This function is called by the keyboard handler when SysRq is pressed + * and any other keycode arrives. + */ + +void handle_sysrq(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + if (!sysrq_enabled) + return; + + __sysrq_lock_table(); + __handle_sysrq_nolock(key, pt_regs, kbd, tty); + __sysrq_unlock_table(); +} + +/* + * This is the non-locking version of handle_sysrq + * It must/can only be called by sysrq key handlers, + * as they are inside of the lock + */ + +void __handle_sysrq_nolock(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) { + struct sysrq_key_op *op_p; + int orig_log_level; + int i, j; + + if (!sysrq_enabled) + return; + + orig_log_level = console_loglevel; + console_loglevel = 7; + printk(KERN_INFO "SysRq : "); + + op_p = __sysrq_get_key_op(key); + if (op_p) { + printk ("%s", op_p->action_msg); + op_p->handler(key, pt_regs, kbd, tty); + } else { + printk("HELP : "); + /* Only print the help msg once per handler */ + for (i=0; ihelp_msg); + } + printk ("\n"); + } + console_loglevel = orig_log_level; +} + +EXPORT_SYMBOL(handle_sysrq); +EXPORT_SYMBOL(__handle_sysrq_nolock); +EXPORT_SYMBOL(__sysrq_lock_table); +EXPORT_SYMBOL(__sysrq_unlock_table); +EXPORT_SYMBOL(__sysrq_get_key_op); +EXPORT_SYMBOL(__sysrq_put_key_op); diff -u --recursive --new-file v2.4.9/linux/drivers/char/toshiba.c linux/drivers/char/toshiba.c --- v2.4.9/linux/drivers/char/toshiba.c Fri Apr 6 10:42:55 2001 +++ linux/drivers/char/toshiba.c Thu Sep 13 15:21:32 2001 @@ -82,6 +82,8 @@ MODULE_PARM(tosh_fn, "i"); +MODULE_LICENSE("GPL"); + static int tosh_get_info(char *, char **, off_t, int); static int tosh_ioctl(struct inode *, struct file *, unsigned int, 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 14 14:40:00 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; qdec)); byte_swap_w(&(stp->urc)); #else +#warning Undefined architecture /* should probably swap status bytes #definition */ #endif return stat; -} /* get_status */ +} /* get_status */ #if 0 @@ -782,7 +793,7 @@ */ static int get_ext_status3(void) { - char vus[64]; /* vendor unique status */ + char vus[64]; /* vendor unique status */ int stat, i; tpqputs(TPQD_ALWAYS, "Attempting to read Extended Status 3..."); @@ -791,15 +802,15 @@ return stat; tpqputs(TPQD_ALWAYS, "Returned status bytes:"); - for (i=0; i0) || dma_mode) { + if ((status_cmd_pending > 0) || dma_mode) { /* takes tooo long, shut it down */ status_dead = YES; status_cmd_pending = 0; @@ -1614,7 +1656,7 @@ wake_up(&qic02_tape_transfer); } } -} /* qic02_tape_times_out */ +} /* qic02_tape_times_out */ /* * Interrupt handling: @@ -1647,7 +1689,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 +1705,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 +1735,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 +1770,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 +1812,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 +2010,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 +2096,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 +2179,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 14 14:04:08 2001 @@ -158,6 +158,8 @@ extern void sa1100_rs_console_init(void); extern void sgi_serial_console_init(void); extern void sci_console_init(void); +extern void tx3912_console_init(void); +extern void tx3912_rs_init(void); #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -442,8 +444,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; @@ -2184,6 +2184,9 @@ #ifdef CONFIG_VT con_init(); #endif +#ifdef CONFIG_AU1000_SERIAL_CONSOLE + au1000_serial_console_init(); +#endif #ifdef CONFIG_SERIAL_CONSOLE #if (defined(CONFIG_8xx) || defined(CONFIG_8260)) console_8xx_init(); @@ -2225,9 +2228,15 @@ #ifdef CONFIG_SERIAL_SA1100_CONSOLE sa1100_rs_console_init(); #endif +#ifdef CONFIG_ARC_CONSOLE + arc_console_init(); +#endif #ifdef CONFIG_SERIAL_AMBA_CONSOLE ambauart_console_init(); #endif +#ifdef CONFIG_SERIAL_TX3912_CONSOLE + tx3912_console_init(); +#endif } static struct tty_driver dev_tty_driver, dev_syscons_driver; @@ -2314,6 +2323,9 @@ #endif #if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC) vme_scc_init(); +#endif +#ifdef CONFIG_SERIAL_TX3912 + tx3912_rs_init(); #endif #ifdef CONFIG_COMPUTONE ip2_init(); diff -u --recursive --new-file v2.4.9/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c --- v2.4.9/linux/drivers/char/tty_ioctl.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/tty_ioctl.c Mon Sep 17 22:52:35 2001 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -27,11 +28,6 @@ #undef TTY_DEBUG_WAIT_UNTIL_SENT #undef DEBUG -#ifdef DEBUG -# define PRINTK(x) printk (x) -#else -# define PRINTK(x) /**/ -#endif /* * Internal flag options for termios setting behavior @@ -145,18 +141,19 @@ static int set_termios(struct tty_struct * tty, unsigned long arg, int opt) { struct termios tmp_termios; - int retval; + int retval = tty_check_change(tty); - retval = tty_check_change(tty); if (retval) return retval; if (opt & TERMIOS_TERMIO) { memcpy(&tmp_termios, tty->termios, sizeof(struct termios)); - if (user_termio_to_kernel_termios(&tmp_termios, (struct termio *) arg)) + if (user_termio_to_kernel_termios(&tmp_termios, + (struct termio *) arg)) return -EFAULT; } else { - if (user_termios_to_kernel_termios(&tmp_termios, (struct termios *) arg)) + if (user_termios_to_kernel_termios(&tmp_termios, + (struct termios *) arg)) return -EFAULT; } @@ -232,9 +229,7 @@ tmp.sg_erase = tty->termios->c_cc[VERASE]; tmp.sg_kill = tty->termios->c_cc[VKILL]; tmp.sg_flags = get_sgflags(tty); - if (copy_to_user(sgttyb, &tmp, sizeof(tmp))) - return -EFAULT; - return 0; + return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; } static void set_sgflags(struct termios * termios, int flags) @@ -247,7 +242,8 @@ termios->c_lflag &= ~ICANON; } if (flags & 0x08) { /* echo */ - termios->c_lflag |= ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; + termios->c_lflag |= ECHO | ECHOE | ECHOK | + ECHOCTL | ECHOKE | IEXTEN; } if (flags & 0x10) { /* crmod */ termios->c_oflag |= OPOST | ONLCR; @@ -293,9 +289,7 @@ tmp.t_stopc = tty->termios->c_cc[VSTOP]; tmp.t_eofc = tty->termios->c_cc[VEOF]; tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ - if (copy_to_user(tchars, &tmp, sizeof(tmp))) - return -EFAULT; - return 0; + return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; } static int set_tchars(struct tty_struct * tty, struct tchars * tchars) @@ -325,9 +319,7 @@ tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */ tmp.t_werasc = tty->termios->c_cc[VWERASE]; tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; - if (copy_to_user(ltchars, &tmp, sizeof(tmp))) - return -EFAULT; - return 0; + return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; } static int set_ltchars(struct tty_struct * tty, struct ltchars * ltchars) @@ -480,7 +472,7 @@ return 0; case TIOCSLCKTRMIOS: - if (!suser()) + if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios *) arg)) return -EFAULT; @@ -493,9 +485,8 @@ if (tty->driver.type != TTY_DRIVER_TYPE_PTY || tty->driver.subtype != PTY_TYPE_MASTER) return -ENOTTY; - retval = get_user(pktmode, (int *) arg); - if (retval) - return retval; + if (get_user(pktmode, (int *) arg)) + return -EFAULT; if (pktmode) { if (!tty->packet) { tty->packet = 1; @@ -508,9 +499,8 @@ case TIOCGSOFTCAR: return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); case TIOCSSOFTCAR: - retval = get_user(arg, (unsigned int *) arg); - if (retval) - return retval; + if (get_user(arg, (unsigned int *) arg)) + return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); @@ -519,3 +509,5 @@ return -ENOIOCTLCMD; } } + +EXPORT_SYMBOL(n_tty_ioctl); diff -u --recursive --new-file v2.4.9/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c --- v2.4.9/linux/drivers/char/vc_screen.c Mon Oct 16 12:58:51 2000 +++ linux/drivers/char/vc_screen.c Sun Sep 16 21:22:40 2001 @@ -109,7 +109,7 @@ /* Select the proper current console and verify * sanity of the situation under the console lock. */ - spin_lock_irq(&console_lock); + acquire_console_sem(); attr = (currcons & 128); currcons = (currcons & 127); @@ -232,13 +232,16 @@ } } - /* Finally, temporarily drop the console lock and push + /* Finally, release the console semaphore while we push * all the data to userspace from our temporary buffer. + * + * AKPM: Even though it's a semaphore, we should drop it because + * the pagefault handling code may want to call printk(). */ - spin_unlock_irq(&console_lock); + release_console_sem(); ret = copy_to_user(buf, con_buf_start, orig_count); - spin_lock_irq(&console_lock); + acquire_console_sem(); if (ret) { read += (orig_count - ret); @@ -254,7 +257,7 @@ if (read) ret = read; unlock_out: - spin_unlock_irq(&console_lock); + release_console_sem(); up(&con_buf_sem); return ret; } @@ -276,7 +279,7 @@ /* Select the proper current console and verify * sanity of the situation under the console lock. */ - spin_lock_irq(&console_lock); + acquire_console_sem(); attr = (currcons & 128); currcons = (currcons & 127); @@ -310,9 +313,9 @@ /* Temporarily drop the console lock so that we can read * in the write data from userspace safely. */ - spin_unlock_irq(&console_lock); + release_console_sem(); ret = copy_from_user(con_buf, buf, this_round); - spin_lock_irq(&console_lock); + acquire_console_sem(); if (ret) { this_round -= ret; @@ -436,7 +439,7 @@ ret = written; unlock_out: - spin_unlock_irq(&console_lock); + release_console_sem(); up(&con_buf_sem); 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/vme_scc.c linux/drivers/char/vme_scc.c --- v2.4.9/linux/drivers/char/vme_scc.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/vme_scc.c Sun Sep 16 21:22:50 2001 @@ -1047,7 +1047,7 @@ *p = ch; } -/* The console_lock must be held when we get here. */ +/* The console must be locked when we get here. */ static void scc_console_write (struct console *co, const char *str, unsigned count) { 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 Mon Sep 17 22:52:35 2001 @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -93,8 +92,9 @@ */ #if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \ - || (defined(__mips__) && !defined(CONFIG_SGI_IP22)) \ - || (defined(__arm__) && defined(CONFIG_HOST_FOOTBRIDGE)) + || (defined(__mips__) && defined(CONFIG_ISA)) \ + || (defined(__arm__) && defined(CONFIG_HOST_FOOTBRIDGE)) \ + || defined(__x86_64__) static void kd_nosound(unsigned long ignored) @@ -145,8 +145,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 +509,6 @@ { struct kbd_repeat kbrep; - if (!kbd_rate) return( -EINVAL ); if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -832,9 +836,9 @@ * make sure we are atomic with respect to * other console switches.. */ - spin_lock_irq(&console_lock); + acquire_console_sem(); complete_change_console(newvt); - spin_unlock_irq(&console_lock); + release_console_sem(); } } @@ -1158,7 +1162,8 @@ vt_cons[new_console]->vt_mode.frsig = 0; vt_cons[new_console]->vt_pid = -1; vt_cons[new_console]->vt_newvt = -1; - reset_palette (new_console) ; + if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ + reset_palette(new_console) ; } /* diff -u --recursive --new-file v2.4.9/linux/drivers/char/w83877f_wdt.c linux/drivers/char/w83877f_wdt.c --- v2.4.9/linux/drivers/char/w83877f_wdt.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/w83877f_wdt.c Thu Sep 13 15:21:32 2001 @@ -340,3 +340,5 @@ module_init(w83877f_wdt_init); module_exit(w83877f_wdt_unload); + +MODULE_LICENSE("GPL"); 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/fc4/fc.c linux/drivers/fc4/fc.c --- v2.4.9/linux/drivers/fc4/fc.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/fc4/fc.c Fri Sep 14 14:04:08 2001 @@ -1155,14 +1155,3 @@ kfree(p); return status; } - -#ifdef MODULE -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{ -} -#endif diff -u --recursive --new-file v2.4.9/linux/drivers/fc4/soc.c linux/drivers/fc4/soc.c --- v2.4.9/linux/drivers/fc4/soc.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/fc4/soc.c Fri Sep 14 14:04:08 2001 @@ -565,14 +565,10 @@ (long)socs, (long)soc_intr, (long)soc_hw_enque)) if (version_printed++ == 0) printk (version); -#ifdef MODULE - s->port[0].fc.module = &__this_module; - s->port[1].fc.module = &__this_module; -#else - s->port[0].fc.module = NULL; - s->port[1].fc.module = NULL; -#endif - + + s->port[0].fc.module = THIS_MODULE; + s->port[1].fc.module = THIS_MODULE; + s->next = socs; socs = s; s->port[0].fc.dev = sdev; @@ -713,11 +709,7 @@ SOD(("Enabled SOC\n")) } -#ifndef MODULE -int __init soc_probe(void) -#else -int init_module(void) -#endif +static int __init soc_probe(void) { struct sbus_bus *sbus; struct sbus_dev *sdev = 0; @@ -741,10 +733,7 @@ return 0; } -EXPORT_NO_SYMBOLS; - -#ifdef MODULE -void cleanup_module(void) +static void __exit sco_cleanup(void) { struct soc *s; int irq; @@ -770,4 +759,8 @@ s->req_cpu, s->req_dvma); } } -#endif + +EXPORT_NO_SYMBOLS; + +module_init(soc_probe); +module_exit(soc_cleanup); diff -u --recursive --new-file v2.4.9/linux/drivers/fc4/socal.c linux/drivers/fc4/socal.c --- v2.4.9/linux/drivers/fc4/socal.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/fc4/socal.c Fri Sep 14 14:04:08 2001 @@ -673,14 +673,10 @@ (long)socals, (long)socal_intr, (long)socal_hw_enque)) if (version_printed++ == 0) printk (version); -#ifdef MODULE - s->port[0].fc.module = &__this_module; - s->port[1].fc.module = &__this_module; -#else - s->port[0].fc.module = NULL; - s->port[1].fc.module = NULL; -#endif - + + s->port[0].fc.module = THIS_MODULE; + s->port[1].fc.module = THIS_MODULE; + s->next = socals; socals = s; s->port[0].fc.dev = sdev; @@ -850,11 +846,7 @@ SOD(("Enabled SOCAL\n")) } -#ifndef MODULE -int __init socal_probe(void) -#else -int init_module(void) -#endif +static int __init socal_probe(void) { struct sbus_bus *sbus; struct sbus_dev *sdev = 0; @@ -880,10 +872,7 @@ return 0; } -EXPORT_NO_SYMBOLS; - -#ifdef MODULE -void cleanup_module(void) +static void __exit socal_cleanup(void) { struct socal *s; int irq; @@ -910,4 +899,8 @@ s->req_cpu, s->req_dvma); } } -#endif + +EXPORT_NO_SYMBOLS; + +module_init(socal_probe); +module_exit(socal_cleanup); diff -u --recursive --new-file v2.4.9/linux/drivers/i2c/Config.in linux/drivers/i2c/Config.in --- v2.4.9/linux/drivers/i2c/Config.in Mon Jul 31 10:21:58 2000 +++ linux/drivers/i2c/Config.in Fri Sep 14 14:04:07 2001 @@ -20,6 +20,13 @@ dep_tristate ' Elektor ISA card' CONFIG_I2C_ELEKTOR $CONFIG_I2C_ALGOPCF fi + if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then + dep_tristate 'ITE I2C Algorithm' CONFIG_ITE_I2C_ALGO $CONFIG_I2C + if [ "$CONFIG_ITE_I2C_ALGO" != "n" ]; then + dep_tristate ' ITE I2C Adapter' CONFIG_ITE_I2C_ADAP $CONFIG_ITE_I2C_ALGO + fi + fi + # This is needed for automatic patch generation: sensors code starts here # This is needed for automatic patch generation: sensors code ends here diff -u --recursive --new-file v2.4.9/linux/drivers/i2c/i2c-adap-ite.c linux/drivers/i2c/i2c-adap-ite.c --- v2.4.9/linux/drivers/i2c/i2c-adap-ite.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/i2c/i2c-adap-ite.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,319 @@ +/* + ------------------------------------------------------------------------- + i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system + ------------------------------------------------------------------------- + Hai-Pao Fan, MontaVista Software, Inc. + hpfan@mvista.com or source@mvista.com + + Copyright 2001 MontaVista Software Inc. + + ---------------------------------------------------------------------------- + This file was highly leveraged from i2c-elektor.c, which was created + by Simon G. Vogl and Hans Berglund: + + + Copyright (C) 1995-97 Simon G. Vogl + 1998-99 Hans Berglund + + 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. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and even + Frodo Looijaard */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "i2c-ite.h" + +#define DEFAULT_BASE 0x14014030 +#define ITE_IIC_IO_SIZE 0x40 +#define DEFAULT_IRQ 0 +#define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */ +#define DEFAULT_OWN 0x55 + +static int base = 0; +static int irq = 0; +static int clock = 0; +static int own = 0; + +static int i2c_debug=0; +static struct iic_ite gpi; +#if (LINUX_VERSION_CODE < 0x020301) +static struct wait_queue *iic_wait = NULL; +#else +static wait_queue_head_t iic_wait; +#endif +static int iic_pending; + +/* ----- global defines ----------------------------------------------- */ +#define DEB(x) if (i2c_debug>=1) x +#define DEB2(x) if (i2c_debug>=2) x +#define DEB3(x) if (i2c_debug>=3) x +#define DEBE(x) x /* error messages */ + + +/* ----- local functions ---------------------------------------------- */ + +static void iic_ite_setiic(void *data, int ctl, short val) +{ + unsigned long j = jiffies + 10; + + DEB3(printk(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff)); + DEB3({while (jiffies < j) schedule();}) + outw(val,ctl); +} + +static short iic_ite_getiic(void *data, int ctl) +{ + short val; + + val = inw(ctl); + DEB3(printk("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff)); + return (val); +} + +/* Return our slave address. This is the address + * put on the I2C bus when another master on the bus wants to address us + * as a slave + */ +static int iic_ite_getown(void *data) +{ + return (gpi.iic_own); +} + + +static int iic_ite_getclock(void *data) +{ + return (gpi.iic_clock); +} + + +#if 0 +static void iic_ite_sleep(unsigned long timeout) +{ + schedule_timeout( timeout * HZ); +} +#endif + + +/* Put this process to sleep. We will wake up when the + * IIC controller interrupts. + */ +static void iic_ite_waitforpin(void) { + + int timeout = 2; + + /* If interrupts are enabled (which they are), then put the process to + * sleep. This process will be awakened by two events -- either the + * the IIC peripheral interrupts or the timeout expires. + * If interrupts are not enabled then delay for a reasonable amount + * of time and return. + */ + if (gpi.iic_irq > 0) { + cli(); + if (iic_pending == 0) { + interruptible_sleep_on_timeout(&iic_wait, timeout*HZ ); + } else + iic_pending = 0; + sti(); + } else { + udelay(100); + } +} + + +static void iic_ite_handler(int this_irq, void *dev_id, struct pt_regs *regs) +{ + + iic_pending = 1; + + DEB2(printk("iic_ite_handler: in interrupt handler\n")); + wake_up_interruptible(&iic_wait); +} + + +/* Lock the region of memory where I/O registers exist. Request our + * interrupt line and register its associated handler. + */ +static int iic_hw_resrc_init(void) +{ + if (check_region(gpi.iic_base, ITE_IIC_IO_SIZE) < 0 ) { + return -ENODEV; + } else { + request_region(gpi.iic_base, ITE_IIC_IO_SIZE, + "i2c (i2c bus adapter)"); + } + if (gpi.iic_irq > 0) { + if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0) { + gpi.iic_irq = 0; + } else + DEB3(printk("Enabled IIC IRQ %d\n", gpi.iic_irq)); + enable_irq(gpi.iic_irq); + } + return 0; +} + + +static void iic_ite_release(void) +{ + if (gpi.iic_irq > 0) { + disable_irq(gpi.iic_irq); + free_irq(gpi.iic_irq, 0); + } + release_region(gpi.iic_base , 2); +} + + +static int iic_ite_reg(struct i2c_client *client) +{ + return 0; +} + + +static int iic_ite_unreg(struct i2c_client *client) +{ + return 0; +} + + +static void iic_ite_inc_use(struct i2c_adapter *adap) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif +} + + +static void iic_ite_dec_use(struct i2c_adapter *adap) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_iic_data iic_ite_data = { + NULL, + iic_ite_setiic, + iic_ite_getiic, + iic_ite_getown, + iic_ite_getclock, + iic_ite_waitforpin, + 80, 80, 100, /* waits, timeout */ +}; + +static struct i2c_adapter iic_ite_ops = { + "ITE IIC adapter", + I2C_HW_I_IIC, + NULL, + &iic_ite_data, + iic_ite_inc_use, + iic_ite_dec_use, + iic_ite_reg, + iic_ite_unreg, +}; + +/* Called when the module is loaded. This function starts the + * cascade of calls up through the heirarchy of i2c modules (i.e. up to the + * algorithm layer and into to the core layer) + */ +static int __init iic_ite_init(void) +{ + + struct iic_ite *piic = &gpi; + + printk(KERN_INFO "Initialize ITE IIC adapter module\n"); + if (base == 0) + piic->iic_base = DEFAULT_BASE; + else + piic->iic_base = base; + + if (irq == 0) + piic->iic_irq = DEFAULT_IRQ; + else + piic->iic_irq = irq; + + if (clock == 0) + piic->iic_clock = DEFAULT_CLOCK; + else + piic->iic_clock = clock; + + if (own == 0) + piic->iic_own = DEFAULT_OWN; + else + piic->iic_own = own; + + iic_ite_data.data = (void *)piic; +#if (LINUX_VERSION_CODE >= 0x020301) + init_waitqueue_head(&iic_wait); +#endif + if (iic_hw_resrc_init() == 0) { + if (i2c_iic_add_bus(&iic_ite_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + printk(KERN_INFO " found device at %#x irq %d.\n", + piic->iic_base, piic->iic_irq); + return 0; +} + + +static void iic_ite_exit(void) +{ + i2c_iic_del_bus(&iic_ite_ops); + iic_ite_release(); +} + +EXPORT_NO_SYMBOLS; + +/* If modules is NOT defined when this file is compiled, then the MODULE_* + * macros will resolve to nothing + */ +MODULE_AUTHOR("MontaVista Software "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter"); + +MODULE_PARM(base, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(clock, "i"); +MODULE_PARM(own, "i"); +MODULE_PARM(i2c_debug,"i"); + + +/* Called when module is loaded or when kernel is intialized. + * If MODULES is defined when this file is compiled, then this function will + * resolve to init_module (the function called when insmod is invoked for a + * module). Otherwise, this function is called early in the boot, when the + * kernel is intialized. Check out /include/init.h to see how this works. + */ +module_init(iic_ite_init); + +/* Resolves to module_cleanup when MODULES is defined. */ +module_exit(iic_ite_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/i2c/i2c-algo-ite.c linux/drivers/i2c/i2c-algo-ite.c --- v2.4.9/linux/drivers/i2c/i2c-algo-ite.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/i2c/i2c-algo-ite.c Sun Sep 9 10:43:02 2001 @@ -0,0 +1,872 @@ +/* + ------------------------------------------------------------------------- + i2c-algo-ite.c i2c driver algorithms for ITE adapters + + Hai-Pao Fan, MontaVista Software, Inc. + hpfan@mvista.com or source@mvista.com + + Copyright 2000 MontaVista Software Inc. + + --------------------------------------------------------------------------- + This file was highly leveraged from i2c-algo-pcf.c, which was created + by Simon G. Vogl and Hans Berglund: + + + Copyright (C) 1995-1997 Simon G. Vogl + 1998-2000 Hans Berglund + + 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. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and + Frodo Looijaard ,and also from Martin Bailey + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "i2c-ite.h" + +#define PM_DSR IT8172_PCI_IO_BASE + IT_PM_DSR +#define PM_IBSR IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04 +#define GPIO_CCR IT8172_PCI_IO_BASE + IT_GPCCR + +/* ----- global defines ----------------------------------------------- */ +#define DEB(x) if (i2c_debug>=1) x +#define DEB2(x) if (i2c_debug>=2) x +#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/ +#define DEBPROTO(x) if (i2c_debug>=9) x; + /* debug the protocol by showing transferred bits */ +#define DEF_TIMEOUT 16 + +/* debugging - slow down transfer to have a look at the data .. */ +/* I use this with two leds&resistors, each one connected to sda,scl */ +/* respectively. This makes sure that the algorithm works. Some chips */ +/* might not like this, as they have an internal timeout of some mils */ +/* +#define SLO_IO jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\ + if (need_resched) schedule(); +*/ + + +/* ----- global variables --------------------------------------------- */ + +#ifdef SLO_IO + int jif; +#endif + +/* module parameters: + */ +static int i2c_debug=1; +static int iic_test=0; /* see if the line-setting functions work */ +static int iic_scan=0; /* have a look at what's hanging 'round */ + +/* --- setting states on the bus with the right timing: --------------- */ + +#define get_clock(adap) adap->getclock(adap->data) +#define iic_outw(adap, reg, val) adap->setiic(adap->data, reg, val) +#define iic_inw(adap, reg) adap->getiic(adap->data, reg) + + +/* --- other auxiliary functions -------------------------------------- */ + +static void iic_start(struct i2c_algo_iic_data *adap) +{ + iic_outw(adap,ITE_I2CHCR,ITE_CMD); +} + +static void iic_stop(struct i2c_algo_iic_data *adap) +{ + iic_outw(adap,ITE_I2CHCR,0); + iic_outw(adap,ITE_I2CHSR,ITE_I2CHSR_TDI); +} + +static void iic_reset(struct i2c_algo_iic_data *adap) +{ + iic_outw(adap, PM_IBSR, iic_inw(adap, PM_IBSR) | 0x80); +} + + +static int wait_for_bb(struct i2c_algo_iic_data *adap) +{ + int timeout = DEF_TIMEOUT; + short status; + + status = iic_inw(adap, ITE_I2CHSR); +#ifndef STUB_I2C + while (timeout-- && (status & ITE_I2CHSR_HB)) { + udelay(1000); /* How much is this? */ + status = iic_inw(adap, ITE_I2CHSR); + } +#endif + if (timeout<=0) { + printk(KERN_ERR "Timeout, host is busy\n"); + iic_reset(adap); + } + return(timeout<=0); +} + +/* + * Puts this process to sleep for a period equal to timeout + */ +static inline void iic_sleep(unsigned long timeout) +{ + schedule_timeout( timeout * HZ); +} + +/* After we issue a transaction on the IIC bus, this function + * is called. It puts this process to sleep until we get an interrupt from + * from the controller telling us that the transaction we requested in complete. + */ +static int wait_for_pin(struct i2c_algo_iic_data *adap, short *status) { + + int timeout = DEF_TIMEOUT; + + timeout = wait_for_bb(adap); + if (timeout) { + DEB2(printk("Timeout waiting for host not busy\n");) + return -EIO; + } + timeout = DEF_TIMEOUT; + + *status = iic_inw(adap, ITE_I2CHSR); +#ifndef STUB_I2C + while (timeout-- && !(*status & ITE_I2CHSR_TDI)) { + adap->waitforpin(); + *status = iic_inw(adap, ITE_I2CHSR); + } +#endif + if (timeout <= 0) + return(-1); + else + return(0); +} + +static int wait_for_fe(struct i2c_algo_iic_data *adap, short *status) +{ + int timeout = DEF_TIMEOUT; + + *status = iic_inw(adap, ITE_I2CFSR); +#ifndef STUB_I2C + while (timeout-- && (*status & ITE_I2CFSR_FE)) { + udelay(1000); + iic_inw(adap, ITE_I2CFSR); + } +#endif + if (timeout <= 0) + return(-1); + else + return(0); +} + +static int iic_init (struct i2c_algo_iic_data *adap) +{ + short i; + + /* Clear bit 7 to set I2C to normal operation mode */ + i=iic_inw(adap, PM_DSR)& 0xff7f; + iic_outw(adap, PM_DSR, i); + + /* set IT_GPCCR port C bit 2&3 as function 2 */ + i = iic_inw(adap, GPIO_CCR) & 0xfc0f; + iic_outw(adap,GPIO_CCR,i); + + /* Clear slave address/sub-address */ + iic_outw(adap,ITE_I2CSAR, 0); + iic_outw(adap,ITE_I2CSSAR, 0); + + /* Set clock counter register */ + iic_outw(adap,ITE_I2CCKCNT, get_clock(adap)); + + /* Set START/reSTART/STOP time registers */ + iic_outw(adap,ITE_I2CSHDR, 0x0a); + iic_outw(adap,ITE_I2CRSUR, 0x0a); + iic_outw(adap,ITE_I2CPSUR, 0x0a); + + /* Enable interrupts on completing the current transaction */ + iic_outw(adap,ITE_I2CHCR, ITE_I2CHCR_IE | ITE_I2CHCR_HCE); + + /* Clear transfer count */ + iic_outw(adap,ITE_I2CFBCR, 0x0); + + DEB2(printk("iic_init: Initialized IIC on ITE 0x%x\n", + iic_inw(adap, ITE_I2CHSR))); + return 0; +} + + +/* + * Sanity check for the adapter hardware - check the reaction of + * the bus lines only if it seems to be idle. + */ +static int test_bus(struct i2c_algo_iic_data *adap, char *name) { +#if 0 + int scl,sda; + sda=getsda(adap); + if (adap->getscl==NULL) { + printk("test_bus: Warning: Adapter can't read from clock line - skipping test.\n"); + return 0; + } + scl=getscl(adap); + printk("test_bus: Adapter: %s scl: %d sda: %d -- testing...\n", + name,getscl(adap),getsda(adap)); + if (!scl || !sda ) { + printk("test_bus: %s seems to be busy.\n",adap->name); + goto bailout; + } + sdalo(adap); + printk("test_bus:1 scl: %d sda: %d \n",getscl(adap), + getsda(adap)); + if ( 0 != getsda(adap) ) { + printk("test_bus: %s SDA stuck high!\n",name); + sdahi(adap); + goto bailout; + } + if ( 0 == getscl(adap) ) { + printk("test_bus: %s SCL unexpected low while pulling SDA low!\n", + name); + goto bailout; + } + sdahi(adap); + printk("test_bus:2 scl: %d sda: %d \n",getscl(adap), + getsda(adap)); + if ( 0 == getsda(adap) ) { + printk("test_bus: %s SDA stuck low!\n",name); + sdahi(adap); + goto bailout; + } + if ( 0 == getscl(adap) ) { + printk("test_bus: %s SCL unexpected low while SDA high!\n", + adap->name); + goto bailout; + } + scllo(adap); + printk("test_bus:3 scl: %d sda: %d \n",getscl(adap), + getsda(adap)); + if ( 0 != getscl(adap) ) { + + sclhi(adap); + goto bailout; + } + if ( 0 == getsda(adap) ) { + printk("test_bus: %s SDA unexpected low while pulling SCL low!\n", + name); + goto bailout; + } + sclhi(adap); + printk("test_bus:4 scl: %d sda: %d \n",getscl(adap), + getsda(adap)); + if ( 0 == getscl(adap) ) { + printk("test_bus: %s SCL stuck low!\n",name); + sclhi(adap); + goto bailout; + } + if ( 0 == getsda(adap) ) { + printk("test_bus: %s SDA unexpected low while SCL high!\n", + name); + goto bailout; + } + printk("test_bus: %s passed test.\n",name); + return 0; +bailout: + sdahi(adap); + sclhi(adap); + return -ENODEV; +#endif + return (0); +} + +/* ----- Utility functions + */ + + +/* Verify the device we want to talk to on the IIC bus really exists. */ +static inline int try_address(struct i2c_algo_iic_data *adap, + unsigned int addr, int retries) +{ + int i, ret = -1; + short status; + + for (i=0;iudelay); + } + DEB2(if (i) printk("try_address: needed %d retries for 0x%x\n",i, + addr)); + return ret; +} + + +static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf, + int count) +{ + struct i2c_algo_iic_data *adap = i2c_adap->algo_data; + int wrcount=0, timeout; + short status; + int loops, remainder, i, j; + union { + char byte[2]; + unsigned short word; + } tmp; + + iic_outw(adap, ITE_I2CSSAR, (unsigned short)buf[wrcount++]); + count--; + if (count == 0) + return -EIO; + + loops = count / 32; /* 32-byte FIFO */ + remainder = count % 32; + + if(loops) { + for(i=0; iname); + return -EREMOTEIO; /* got a better one ?? */ + } + if (status & ITE_I2CHSR_DB) { + iic_stop(adap); + printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name); + return -EREMOTEIO; /* got a better one ?? */ + } + } + } + if(remainder) { + iic_outw(adap, ITE_I2CFBCR, remainder); + for(i=0; iname); + return -EREMOTEIO; /* got a better one ?? */ + } +#ifndef STUB_I2C + if (status & ITE_I2CHSR_DB) { + iic_stop(adap); + printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name); + return -EREMOTEIO; /* got a better one ?? */ + } +#endif + } + iic_stop(adap); + return wrcount; +} + + +static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count, + int sread) +{ + int rdcount=0, i, timeout; + short status; + struct i2c_algo_iic_data *adap = i2c_adap->algo_data; + int loops, remainder, j; + union { + char byte[2]; + unsigned short word; + } tmp; + + loops = count / 32; /* 32-byte FIFO */ + remainder = count % 32; + + if(loops) { + for(i=0; iname); + return (-1); + } +#ifndef STUB_I2C + if (status & ITE_I2CHSR_DB) { + iic_stop(adap); + printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name); + return (-1); + } +#endif + + timeout = wait_for_fe(adap, &status); + if(timeout) { + iic_stop(adap); + printk("iic_readbytes: %s FIFO is empty\n", i2c_adap->name); + return (-1); + } + + for(j=0; j<32/2; j++) { + tmp.word = iic_inw(adap, ITE_I2CFDR); + buf[rdcount++] = tmp.byte[1]; + buf[rdcount++] = tmp.byte[0]; + } + + /* status FIFO underrun */ + iic_inw(adap, ITE_I2CFSR); + + } + } + + + if(remainder) { + remainder=(remainder+1)/2 * 2; + iic_outw(adap, ITE_I2CFBCR, remainder); + if (sread) + iic_outw(adap, ITE_I2CHCR, ITE_SREAD); + else + iic_outw(adap, ITE_I2CHCR, ITE_READ); /* Issue READ command */ + + timeout = wait_for_pin(adap, &status); + if(timeout) { + iic_stop(adap); + printk("iic_readbytes: %s read timeout.\n", i2c_adap->name); + return (-1); + } +#ifndef STUB_I2C + if (status & ITE_I2CHSR_DB) { + iic_stop(adap); + printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name); + return (-1); + } +#endif + timeout = wait_for_fe(adap, &status); + if(timeout) { + iic_stop(adap); + printk("iic_readbytes: %s FIFO is empty\n", i2c_adap->name); + return (-1); + } + + for(i=0; i<(remainder+1)/2; i++) { + tmp.word = iic_inw(adap, ITE_I2CFDR); + buf[rdcount++] = tmp.byte[1]; + buf[rdcount++] = tmp.byte[0]; + } + + /* status FIFO underrun */ + iic_inw(adap, ITE_I2CFSR); + + } + + iic_stop(adap); + return rdcount; +} + + +/* This function implements combined transactions. Combined + * transactions consist of combinations of reading and writing blocks of data. + * Each transfer (i.e. a read or a write) is separated by a repeated start + * condition. + */ +#if 0 +static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +{ + int i; + struct i2c_msg *pmsg; + int ret; + + DEB2(printk("Beginning combined transaction\n")); + + for(i=0; i<(num-1); i++) { + pmsg = &msgs[i]; + if(pmsg->flags & I2C_M_RD) { + DEB2(printk(" This one is a read\n")); + ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER); + } + else if(!(pmsg->flags & I2C_M_RD)) { + DEB2(printk("This one is a write\n")); + ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER); + } + } + /* Last read or write segment needs to be terminated with a stop */ + pmsg = &msgs[i]; + + if(pmsg->flags & I2C_M_RD) { + DEB2(printk("Doing the last read\n")); + ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER); + } + else if(!(pmsg->flags & I2C_M_RD)) { + DEB2(printk("Doing the last write\n")); + ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER); + } + + return ret; +} +#endif + + +/* Whenever we initiate a transaction, the first byte clocked + * onto the bus after the start condition is the address (7 bit) of the + * device we want to talk to. This function manipulates the address specified + * so that it makes sense to the hardware when written to the IIC peripheral. + * + * Note: 10 bit addresses are not supported in this driver, although they are + * supported by the hardware. This functionality needs to be implemented. + */ +static inline int iic_doAddress(struct i2c_algo_iic_data *adap, + struct i2c_msg *msg, int retries) +{ + unsigned short flags = msg->flags; + unsigned int addr; + int ret; + +/* Ten bit addresses not supported right now */ + if ( (flags & I2C_M_TEN) ) { +#if 0 + addr = 0xf0 | (( msg->addr >> 7) & 0x03); + DEB2(printk("addr0: %d\n",addr)); + ret = try_address(adap, addr, retries); + if (ret!=1) { + printk("iic_doAddress: died at extended address code.\n"); + return -EREMOTEIO; + } + iic_outw(adap,msg->addr & 0x7f); + if (ret != 1) { + printk("iic_doAddress: died at 2nd address code.\n"); + return -EREMOTEIO; + } + if ( flags & I2C_M_RD ) { + i2c_repstart(adap); + addr |= 0x01; + ret = try_address(adap, addr, retries); + if (ret!=1) { + printk("iic_doAddress: died at extended address code.\n"); + return -EREMOTEIO; + } + } +#endif + } else { + + addr = ( msg->addr << 1 ); + +#if 0 + if (flags & I2C_M_RD ) + addr |= 1; + if (flags & I2C_M_REV_DIR_ADDR ) + addr ^= 1; +#endif + + if (iic_inw(adap, ITE_I2CSAR) != addr) { + iic_outw(adap, ITE_I2CSAR, addr); + ret = try_address(adap, addr, retries); + if (ret!=1) { + printk("iic_doAddress: died at address code.\n"); + return -EREMOTEIO; + } + } + + } + + return 0; +} + + +/* Description: Prepares the controller for a transaction (clearing status + * registers, data buffers, etc), and then calls either iic_readbytes or + * iic_sendbytes to do the actual transaction. + * + * still to be done: Before we issue a transaction, we should + * verify that the bus is not busy or in some unknown state. + */ +static int iic_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], + int num) +{ + struct i2c_algo_iic_data *adap = i2c_adap->algo_data; + struct i2c_msg *pmsg; + int i = 0; + int ret, timeout; + + pmsg = &msgs[i]; + + if(!pmsg->len) { + DEB2(printk("iic_xfer: read/write length is 0\n");) + return -EIO; + } + if(!(pmsg->flags & I2C_M_RD) && (!(pmsg->len)%2) ) { + DEB2(printk("iic_xfer: write buffer length is not odd\n");) + return -EIO; + } + + /* Wait for any pending transfers to complete */ + timeout = wait_for_bb(adap); + if (timeout) { + DEB2(printk("iic_xfer: Timeout waiting for host not busy\n");) + return -EIO; + } + + /* Flush FIFO */ + iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH); + + /* Load address */ + ret = iic_doAddress(adap, pmsg, i2c_adap->retries); + if (ret) + return -EIO; + +#if 0 + /* Combined transaction (read and write) */ + if(num > 1) { + DEB2(printk("iic_xfer: Call combined transaction\n")); + ret = iic_combined_transaction(i2c_adap, msgs, num); + } +#endif + + DEB3(printk("iic_xfer: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", + i, msgs[i].addr, msgs[i].flags, msgs[i].len);) + + if(pmsg->flags & I2C_M_RD) /* Read */ + ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, 0); + else { /* Write */ + udelay(1000); + ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len); + } + + if (ret != pmsg->len) + DEB3(printk("iic_xfer: error or fail on read/write %d bytes.\n",ret)); + else + DEB3(printk("iic_xfer: read/write %d bytes.\n",ret)); + + return ret; +} + + +/* Implements device specific ioctls. Higher level ioctls can + * be found in i2c-core.c and are typical of any i2c controller (specifying + * slave address, timeouts, etc). These ioctls take advantage of any hardware + * features built into the controller for which this algorithm-adapter set + * was written. These ioctls allow you to take control of the data and clock + * lines and set the either high or low, + * similar to a GPIO pin. + */ +static int algo_control(struct i2c_adapter *adapter, + unsigned int cmd, unsigned long arg) +{ + + struct i2c_algo_iic_data *adap = adapter->algo_data; + struct i2c_iic_msg s_msg; + char *buf; + int ret; + + if (cmd == I2C_SREAD) { + if(copy_from_user(&s_msg, (struct i2c_iic_msg *)arg, + sizeof(struct i2c_iic_msg))) + return -EFAULT; + buf = kmalloc(s_msg.len, GFP_KERNEL); + if (buf== NULL) + return -ENOMEM; + + /* Flush FIFO */ + iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH); + + /* Load address */ + iic_outw(adap, ITE_I2CSAR,s_msg.addr<<1); + iic_outw(adap, ITE_I2CSSAR,s_msg.waddr & 0xff); + + ret = iic_readbytes(adapter, buf, s_msg.len, 1); + if (ret>=0) { + if(copy_to_user( s_msg.buf, buf, s_msg.len) ) + ret = -EFAULT; + } + kfree(buf); + } + return 0; +} + + +static u32 iic_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_PROTOCOL_MANGLING; +} + +/* -----exported algorithm data: ------------------------------------- */ + +static struct i2c_algorithm iic_algo = { + "ITE IIC algorithm", + I2C_ALGO_IIC, + iic_xfer, /* master_xfer */ + NULL, /* smbus_xfer */ + NULL, /* slave_xmit */ + NULL, /* slave_recv */ + algo_control, /* ioctl */ + iic_func, /* functionality */ +}; + + +/* + * registering functions to load algorithms at runtime + */ +int i2c_iic_add_bus(struct i2c_adapter *adap) +{ + int i; + short status; + struct i2c_algo_iic_data *iic_adap = adap->algo_data; + + if (iic_test) { + int ret = test_bus(iic_adap, adap->name); + if (ret<0) + return -ENODEV; + } + + DEB2(printk("i2c-algo-ite: hw routines for %s registered.\n", + adap->name)); + + /* register new adapter to i2c module... */ + + adap->id |= iic_algo.id; + adap->algo = &iic_algo; + + adap->timeout = 100; /* default values, should */ + adap->retries = 3; /* be replaced by defines */ + adap->flags = 0; + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + + i2c_add_adapter(adap); + iic_init(iic_adap); + + /* scan bus */ + /* By default scanning the bus is turned off. */ + if (iic_scan) { + printk(KERN_INFO " i2c-algo-ite: scanning bus %s.\n", + adap->name); + for (i = 0x00; i < 0xff; i+=2) { + iic_outw(iic_adap, ITE_I2CSAR, i); + iic_start(iic_adap); + if ( (wait_for_pin(iic_adap, &status) == 0) && + ((status & ITE_I2CHSR_DNE) == 0) ) { + printk(KERN_INFO "\n(%02x)\n",i>>1); + } else { + printk(KERN_INFO "."); + iic_reset(iic_adap); + } + udelay(iic_adap->udelay); + } + } + return 0; +} + + +int i2c_iic_del_bus(struct i2c_adapter *adap) +{ + int res; + if ((res = i2c_del_adapter(adap)) < 0) + return res; + DEB2(printk("i2c-algo-ite: adapter unregistered: %s\n",adap->name)); + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + return 0; +} + + +int __init i2c_algo_iic_init (void) +{ + printk(KERN_INFO "ITE iic (i2c) algorithm module\n"); + return 0; +} + + +void i2c_algo_iic_exit(void) +{ + return; +} + + +EXPORT_SYMBOL(i2c_iic_add_bus); +EXPORT_SYMBOL(i2c_iic_del_bus); + +/* The MODULE_* macros resolve to nothing if MODULES is not defined + * when this file is compiled. + */ +MODULE_AUTHOR("MontaVista Software "); +MODULE_DESCRIPTION("ITE iic algorithm"); + +MODULE_PARM(iic_test, "i"); +MODULE_PARM(iic_scan, "i"); +MODULE_PARM(i2c_debug,"i"); + +MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available"); +MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus"); +MODULE_PARM_DESC(i2c_debug, + "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); + + +/* This function resolves to init_module (the function invoked when a module + * is loaded via insmod) when this file is compiled with MODULES defined. + * Otherwise (i.e. if you want this driver statically linked to the kernel), + * a pointer to this function is stored in a table and called + * during the intialization of the kernel (in do_basic_setup in /init/main.c) + * + * All this functionality is complements of the macros defined in linux/init.h + */ +module_init(i2c_algo_iic_init); + + +/* If MODULES is defined when this file is compiled, then this function will + * resolved to cleanup_module. + */ +module_exit(i2c_algo_iic_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/i2c/i2c-ite.h linux/drivers/i2c/i2c-ite.h --- v2.4.9/linux/drivers/i2c/i2c-ite.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/i2c/i2c-ite.h Sun Sep 9 10:43:02 2001 @@ -0,0 +1,117 @@ +/* + -------------------------------------------------------------------- + i2c-ite.h: Global defines for the I2C controller on board the + ITE MIPS processor. + -------------------------------------------------------------------- + Hai-Pao Fan, MontaVista Software, Inc. + hpfan@mvista.com or source@mvista.com + + Copyright 2001 MontaVista Software 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 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. + + */ + +#ifndef I2C_ITE_H +#define I2C_ITE_H 1 + +#include + +/* I2C Registers */ +#define ITE_I2CHCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x30 +#define ITE_I2CHSR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x34 +#define ITE_I2CSAR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x38 +#define ITE_I2CSSAR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x3c +#define ITE_I2CCKCNT IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x48 +#define ITE_I2CSHDR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x4c +#define ITE_I2CRSUR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x50 +#define ITE_I2CPSUR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x54 + +#define ITE_I2CFDR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x70 +#define ITE_I2CFBCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x74 +#define ITE_I2CFCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x78 +#define ITE_I2CFSR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x7c + + +/* Host Control Register ITE_I2CHCR */ +#define ITE_I2CHCR_HCE 0x01 /* Enable I2C Host Controller */ +#define ITE_I2CHCR_IE 0x02 /* Enable the interrupt after completing + the current transaction */ +#define ITE_I2CHCR_CP_W 0x00 /* bit2-4 000 - Write */ +#define ITE_I2CHCR_CP_R 0x08 /* 010 - Current address read */ +#define ITE_I2CHCR_CP_S 0x10 /* 100 - Sequential read */ +#define ITE_I2CHCR_ST 0x20 /* Initiates the I2C host controller to execute + the command and send the data programmed in + all required registers to I2C bus */ +#define ITE_CMD ITE_I2CHCR_HCE | ITE_I2CHCR_IE | ITE_I2CHCR_ST +#define ITE_WRITE ITE_CMD | ITE_I2CHCR_CP_W +#define ITE_READ ITE_CMD | ITE_I2CHCR_CP_R +#define ITE_SREAD ITE_CMD | ITE_I2CHCR_CP_S + +/* Host Status Register ITE_I2CHSR */ +#define ITE_I2CHSR_DB 0x01 /* Device is busy, receives NACK response except + in the first and last bytes */ +#define ITE_I2CHSR_DNE 0x02 /* Target address on I2C bus does not exist */ +#define ITE_I2CHSR_TDI 0x04 /* R/W Transaction on I2C bus was completed */ +#define ITE_I2CHSR_HB 0x08 /* Host controller is processing transactions */ +#define ITE_I2CHSR_FER 0x10 /* Error occurs in the FIFO */ + +/* Slave Address Register ITE_I2CSAR */ +#define ITE_I2CSAR_SA_MASK 0xfe /* Target I2C device address */ +#define ITE_I2CSAR_ASO 0x0100 /* Output 1/0 to I2CAS port when the + next slave address is addressed */ + +/* Slave Sub-address Register ITE_I2CSSAR */ +#define ITE_I2CSSAR_SUBA_MASK 0xff /* Target I2C device sub-address */ + +/* Clock Counter Register ITE_I2CCKCNT */ +#define ITE_I2CCKCNT_STOP 0x00 /* stop I2C clock */ +#define ITE_I2CCKCNT_HPCC_MASK 0x7f /* SCL high period counter */ +#define ITE_I2CCKCNT_LPCC_MASK 0x7f00 /* SCL low period counter */ + +/* START Hold Time Register ITE_I2CSHDR */ +/* value is counted based on 16 MHz internal clock */ +#define ITE_I2CSHDR_FM 0x0a /* START condition at fast mode */ +#define ITE_I2CSHDR_SM 0x47 /* START contition at standard mode */ + +/* (Repeated) START Setup Time Register ITE_I2CRSUR */ +/* value is counted based on 16 MHz internal clock */ +#define ITE_I2CRSUR_FM 0x0a /* repeated START condition at fast mode */ +#define ITE_I2CRSUR_SM 0x50 /* repeated START condition at standard mode */ + +/* STOP setup Time Register ITE_I2CPSUR */ + +/* FIFO Data Register ITE_I2CFDR */ +#define ITE_I2CFDR_MASK 0xff + +/* FIFO Byte Count Register ITE_I2CFBCR */ +#define ITE_I2CFBCR_MASK 0x3f + +/* FIFO Control Register ITE_I2CFCR */ +#define ITE_I2CFCR_FLUSH 0x01 /* Flush FIFO and reset the FIFO point + and I2CFSR */ +/* FIFO Status Register ITE_I2CFSR */ +#define ITE_I2CFSR_FO 0x01 /* FIFO is overrun when write */ +#define ITE_I2CFSR_FU 0x02 /* FIFO is underrun when read */ +#define ITE_I2CFSR_FF 0x04 /* FIFO is full when write */ +#define ITE_I2CFSR_FE 0x08 /* FIFO is empty when read */ + +#endif /* I2C_ITE_H */ 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 Mon Sep 10 12:42:31 2001 @@ -1141,6 +1141,8 @@ switch (cmd) { case BLKGETSIZE: return put_user(i2ob[minor].nr_sects, (long *) arg); + case BLKGETSIZE64: + return put_user((u64)i2ob[minor].nr_sects << 9, (u64 *)arg); case HDIO_GETGEO: { @@ -1195,9 +1197,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--; @@ -1857,16 +1856,14 @@ static struct gendisk i2ob_gendisk = { - MAJOR_NR, - "i2o/hd", - 4, - 1<<4, - i2ob, - i2ob_sizes, - MAX_I2OB, - NULL, - NULL, - &i2ob_fops, + major: MAJOR_NR, + major_name: "i2o/hd", + minor_shift: 4, + max_p: 1<<4, + part: i2ob, + sizes: i2ob_sizes, + nr_real: MAX_I2OB, + fops: &i2ob_fops, }; @@ -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 Mon Sep 17 23:23:40 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 @@ -187,5 +187,9 @@ else define_bool CONFIG_BLK_DEV_IDE_MODES n fi + +dep_tristate 'Support for IDE Raid controllers' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL +dep_tristate ' Support Promise software RAID (Fasttrak(tm))' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID +dep_tristate ' Highpoint 370 software RAID' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID endmenu 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 Mon Sep 17 23:23:40 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 @@ -65,6 +65,12 @@ ide-obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o ide-obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o ide-obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o + +# The virtualised raid layers MUST come after the ide itself or bad stuff +# will happen. +obj-$(CONFIG_BLK_DEV_ATARAID) += ataraid.o +obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o +obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o ide-obj-$(CONFIG_PROC_FS) += ide-proc.o diff -u --recursive --new-file v2.4.9/linux/drivers/ide/amd7409.c linux/drivers/ide/amd7409.c --- v2.4.9/linux/drivers/ide/amd7409.c Sat May 19 17:43:06 2001 +++ linux/drivers/ide/amd7409.c Wed Dec 31 16:00:00 1969 @@ -1,471 +0,0 @@ -/* - * linux/drivers/ide/amd7409.c Version 0.05 June 9, 2000 - * - * Copyright (C) 1999-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" - -#define DISPLAY_VIPER_TIMINGS - -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int amd7409_get_info(char *, char **, off_t, int); -extern int (*amd7409_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int amd7409_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n AMD 7409 VIPER Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte amd7409_proc = 0; - -extern char *ide_xfer_verbose (byte xfer_rate); - -static unsigned int amd7409_swdma_check (struct pci_dev *dev) -{ - unsigned int class_rev; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - return ((int) (class_rev >= 7) ? 1 : 0); -} - -static int amd7409_swdma_error(ide_drive_t *drive) -{ - printk("%s: single-word DMA not support (revision < C4)\n", drive->name); - return 0; -} - -/* - * Here is where all the hard work goes to program the chipset. - * - */ -static int amd7409_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int err = 0; - byte unit = (drive->select.b.unit & 0x01); -#ifdef CONFIG_BLK_DEV_IDEDMA - unsigned long dma_base = hwif->dma_base; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - byte drive_pci = 0x00; - byte drive_pci2 = 0x00; - byte ultra_timing = 0x00; - byte dma_pio_timing = 0x00; - byte pio_timing = 0x00; - - switch (drive->dn) { - case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break; - case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break; - case 2: drive_pci = 0x51; drive_pci2 = 0x49; break; - case 3: drive_pci = 0x50; drive_pci2 = 0x48; break; - default: - return -1; - } - - pci_read_config_byte(dev, drive_pci, &ultra_timing); - pci_read_config_byte(dev, drive_pci2, &dma_pio_timing); - pci_read_config_byte(dev, 0x4c, &pio_timing); - -#ifdef DEBUG - printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", - drive->name, ultra_timing, dma_pio_timing, pio_timing); -#endif - - ultra_timing &= ~0xC7; - dma_pio_timing &= ~0xFF; - pio_timing &= ~(0x03 << drive->dn); - -#ifdef DEBUG - printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", - ultra_timing, dma_pio_timing, pio_timing); -#endif - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_4: - ultra_timing |= 0x45; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_3: - ultra_timing |= 0x44; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_2: - ultra_timing |= 0x40; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_1: - ultra_timing |= 0x41; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_0: - ultra_timing |= 0x42; - dma_pio_timing |= 0x20; - break; - case XFER_MW_DMA_2: - dma_pio_timing |= 0x20; - break; - case XFER_MW_DMA_1: - dma_pio_timing |= 0x21; - break; - case XFER_MW_DMA_0: - dma_pio_timing |= 0x77; - break; - case XFER_SW_DMA_2: - if (!amd7409_swdma_check(dev)) - return amd7409_swdma_error(drive); - dma_pio_timing |= 0x42; - break; - case XFER_SW_DMA_1: - if (!amd7409_swdma_check(dev)) - return amd7409_swdma_error(drive); - dma_pio_timing |= 0x65; - break; - case XFER_SW_DMA_0: - if (!amd7409_swdma_check(dev)) - return amd7409_swdma_error(drive); - dma_pio_timing |= 0xA8; - break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - dma_pio_timing |= 0x20; - break; - case XFER_PIO_3: - dma_pio_timing |= 0x22; - break; - case XFER_PIO_2: - dma_pio_timing |= 0x42; - break; - case XFER_PIO_1: - dma_pio_timing |= 0x65; - break; - case XFER_PIO_0: - default: - dma_pio_timing |= 0xA8; - break; - } - - pio_timing |= (0x03 << drive->dn); - - if (!drive->init_speed) - drive->init_speed = speed; - -#ifdef CONFIG_BLK_DEV_IDEDMA - pci_write_config_byte(dev, drive_pci, ultra_timing); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - pci_write_config_byte(dev, drive_pci2, dma_pio_timing); - pci_write_config_byte(dev, 0x4c, pio_timing); - -#ifdef DEBUG - printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n", - ultra_timing, dma_pio_timing, pio_timing); -#endif - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (speed > XFER_PIO_4) { - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - } else { - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return (err); -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : - (drive->id->tPIO & 2) ? 0x02 : - (drive->id->tPIO & 1) ? 0x01 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } - (void) amd7409_tune_chipset(drive, speed); - drive->current_speed = speed; -} - -static void amd7409_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; - } - (void) amd7409_tune_chipset(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte udma_66 = eighty_ninty_three(drive); - byte udma_100 = 0; - byte speed = 0x00; - int rval; - - if ((id->dma_ultra & 0x0020) && (udma_66)&& (udma_100)) { - speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && (udma_66)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (udma_66)) { - speed = XFER_UDMA_3; - } else if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - (void) amd7409_tune_chipset(drive, speed); - - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - - return rval; -} - - - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x002F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - ((id->dma_1word & 0x007) && - (amd7409_swdma_check(HWIF(drive)->pci_dev)))) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - - config_chipset_for_pio(drive); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * amd7409_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ - -int amd7409_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -unsigned int __init pci_init_amd7409 (struct pci_dev *dev, const char *name) -{ - unsigned long fixdma_base = pci_resource_start(dev, 4); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (!amd7409_swdma_check(dev)) - printk("%s: disabling single-word DMA support (revision < C4)\n", name); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (!fixdma_base) { - /* - * - */ - } else { - /* - * enable DMA capable bit, and "not" simplex only - */ - outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); - - if (inb(fixdma_base+2) & 0x80) - printk("%s: simplex device: DMA will fail!!\n", name); - } -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) - if (!amd7409_proc) { - amd7409_proc = 1; - bmide_dev = dev; - amd7409_display_info = &amd7409_get_info; - } -#endif /* DISPLAY_VIPER_TIMINGS && CONFIG_PROC_FS */ - - return 0; -} - -unsigned int __init ata66_amd7409 (ide_hwif_t *hwif) -{ -#ifdef CONFIG_AMD7409_OVERRIDE - byte ata66 = 1; -#else - byte ata66 = 0; -#endif /* CONFIG_AMD7409_OVERRIDE */ - -#if 0 - pci_read_config_byte(hwif->pci_dev, 0x48, &ata66); - return ((ata66 & 0x02) ? 0 : 1); -#endif - return ata66; -} - -void __init ide_init_amd7409 (ide_hwif_t *hwif) -{ - hwif->tuneproc = &amd7409_tune_drive; - hwif->speedproc = &amd7409_tune_chipset; - -#ifndef CONFIG_BLK_DEV_IDEDMA - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - return; -#else - - if (hwif->dma_base) { - hwif->dmaproc = &amd7409_dmaproc; - if (!noautodma) - hwif->autodma = 1; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} - -void __init ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase) -{ - ide_setup_dma(hwif, dmabase, 8); -} diff -u --recursive --new-file v2.4.9/linux/drivers/ide/ataraid.c linux/drivers/ide/ataraid.c --- v2.4.9/linux/drivers/ide/ataraid.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/ide/ataraid.c Mon Sep 17 23:23:40 2001 @@ -0,0 +1,320 @@ +/* + ataraid.c Copyright (C) 2001 Red Hat, Inc. All rights reserved. + + 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. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Authors: Arjan van de Ven + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ataraid.h" + + +static int ataraid_hardsect_size[256]; +static int ataraid_blksize_size[256]; + +static struct raid_device_operations* ataraid_ops[16]; + +static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int ataraid_open(struct inode * inode, struct file * filp); +static int ataraid_release(struct inode * inode, struct file * filp); +static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh); + + +struct gendisk ataraid_gendisk; +static int ataraid_gendisk_sizes[256]; +static int ataraid_readahead[256]; + +static struct block_device_operations ataraid_fops = { + open: ataraid_open, + release: ataraid_release, + ioctl: ataraid_ioctl, +}; + + + +static DECLARE_MUTEX(ataraid_sem); + +/* Bitmap for the devices currently in use */ +static unsigned int ataraiduse; + +/* structure for the splitting of bufferheads */ + +struct ataraid_bh_private { + struct buffer_head *parent; + atomic_t count; +}; + +/* stub fops functions */ + +static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int minor; + minor = MINOR(inode->i_rdev)>>SHIFT; + + if ((ataraid_ops[minor])&&(ataraid_ops[minor]->ioctl)) + return (ataraid_ops[minor]->ioctl)(inode,file,cmd,arg); + return -EINVAL; +} + +static int ataraid_open(struct inode * inode, struct file * filp) +{ + int minor; + minor = MINOR(inode->i_rdev)>>SHIFT; + + if ((ataraid_ops[minor])&&(ataraid_ops[minor]->open)) + return (ataraid_ops[minor]->open)(inode,filp); + return -EINVAL; +} + + +static int ataraid_release(struct inode * inode, struct file * filp) +{ + int minor; + minor = MINOR(inode->i_rdev)>>SHIFT; + + if ((ataraid_ops[minor])&&(ataraid_ops[minor]->release)) + return (ataraid_ops[minor]->release)(inode,filp); + return -EINVAL; +} + +static int ataraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + int minor; + int retval; + minor = MINOR(bh->b_rdev)>>SHIFT; + + if ((ataraid_ops[minor])&&(ataraid_ops[minor]->make_request)) { + + retval= (ataraid_ops[minor]->make_request)(q,rw,bh); + if (retval == -1) { + ataraid_split_request(q,rw,bh); + return 0; + } else + return retval; + } + return -EINVAL; +} + +static struct buffer_head *get_bhead(void) +{ + void *ptr = NULL; + while (!ptr) { + ptr=kmalloc(sizeof(struct buffer_head),GFP_NOIO); + if (!ptr) { + __set_current_state(TASK_RUNNING); + current->policy |= SCHED_YIELD; + schedule(); + } + } + return ptr; +} + +static struct ataraid_bh_private *get_private(void) +{ + void *ptr = NULL; + while (!ptr) { + ptr=kmalloc(sizeof(struct ataraid_bh_private),GFP_NOIO); + if (!ptr) { + __set_current_state(TASK_RUNNING); + current->policy |= SCHED_YIELD; + schedule(); + } + } + return ptr; +} + +static void ataraid_end_request(struct buffer_head *bh, int uptodate) +{ + struct ataraid_bh_private *private = bh->b_private; + + if (private==NULL) + BUG(); + + if (atomic_dec_and_test(&private->count)) { + private->parent->b_end_io(private->parent,uptodate); + private->parent = NULL; + kfree(private); + } + kfree(bh); +} + +static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh) +{ + struct buffer_head *bh1,*bh2; + struct ataraid_bh_private *private; + bh1=get_bhead(); + bh2=get_bhead(); + + /* If either of those ever fails we're doomed */ + if ((!bh1)||(!bh2)) + BUG(); + private = get_private(); + if (private==NULL) + BUG(); + + memcpy(bh1, bh, sizeof(*bh)); + memcpy(bh2, bh, sizeof(*bh)); + + bh1->b_end_io = ataraid_end_request; + bh2->b_end_io = ataraid_end_request; + + bh2->b_rsector += bh->b_size >> 10; + bh1->b_size /= 2; + bh2->b_size /= 2; + private->parent = bh; + + bh1->b_private = private; + bh2->b_private = private; + atomic_set(&private->count,2); + + bh2->b_data += bh->b_size/2; + + generic_make_request(rw,bh1); + generic_make_request(rw,bh2); +} + + + + +/* device register / release functions */ + + +int ataraid_get_device(struct raid_device_operations *fops) +{ + int bit; + MOD_INC_USE_COUNT; + down(&ataraid_sem); + if (ataraiduse==~0U) { + up(&ataraid_sem); + MOD_DEC_USE_COUNT; + return -ENODEV; + } + bit=ffz(ataraiduse); + ataraiduse |= 1< + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define ATAMAJOR 114 +#define SHIFT 4 +#define MINOR_MASK 15 +#define MAJOR_MASK 15 + + +/* raid_device_operations is a light struct block_device_operations with an + added method for make_request */ +struct raid_device_operations { + int (*open) (struct inode *, struct file *); + int (*release) (struct inode *, struct file *); + int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); + int (*make_request) (request_queue_t *q, int rw, struct buffer_head * bh); +}; + + +struct geom { + unsigned char heads; + unsigned int cylinders; + unsigned char sectors; +}; + + +extern struct gendisk ataraid_gendisk; + +extern int ataraid_get_device(struct raid_device_operations *fops); +extern void ataraid_release_device(int device); +extern int get_blocksize(kdev_t dev); +extern void ataraid_register_disk(int device,long size); + diff -u --recursive --new-file v2.4.9/linux/drivers/ide/buddha.c linux/drivers/ide/buddha.c --- v2.4.9/linux/drivers/ide/buddha.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/ide/buddha.c Thu Sep 13 15:21:32 2001 @@ -43,7 +43,7 @@ #define BUDDHA_BASE2 0xa00 #define BUDDHA_BASE3 0xc00 -static const u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = { +static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = { BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 }; @@ -76,7 +76,7 @@ #define BUDDHA_IRQ2 0xf40 /* interrupt */ #define BUDDHA_IRQ3 0xf80 -static const int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = { +static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = { BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3 }; 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 Mon Sep 10 12:42:31 2001 @@ -639,9 +639,11 @@ } case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; return put_user(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg); + case BLKGETSIZE64: + return put_user((u64)hd[MINOR(inode->i_rdev)].nr_sects << 9, + (u64 *) arg); case BLKRRPART: /* Re-read partition tables */ if (!capable(CAP_SYS_ADMIN)) @@ -688,16 +690,13 @@ extern struct block_device_operations hd_fops; static struct gendisk hd_gendisk = { - MAJOR_NR, /* Major number */ - "hd", /* Major name */ - 6, /* Bits to shift to get real from partition */ - 1 << 6, /* Number of partitions per real */ - hd, /* hd struct */ - hd_sizes, /* block sizes */ - 0, /* number */ - NULL, /* internal use, not presently used */ - NULL, /* next */ - &hd_fops, /* file operations */ + major: MAJOR_NR, + major_name: "hd", + minor_shift: 6, + max_p: 1 << 6, + part: hd, + sizes: hd_sizes, + fops: &hd_fops, }; static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -842,8 +841,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); init_timer(&device_timer); device_timer.function = hd_times_out; hd_geninit(); diff -u --recursive --new-file v2.4.9/linux/drivers/ide/hptraid.c linux/drivers/ide/hptraid.c --- v2.4.9/linux/drivers/ide/hptraid.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/ide/hptraid.c Mon Sep 17 23:23:40 2001 @@ -0,0 +1,434 @@ +/* + hptraid.c Copyright (C) 2001 Red Hat, Inc. All rights reserved. + + 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. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Authors: Arjan van de Ven + + Based on work + Copyleft (C) 2001 by Wilfried Weissmann + Copyright (C) 1994-96 Marc ZYNGIER + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ataraid.h" + +static int hptraid_open(struct inode * inode, struct file * filp); +static int hptraid_release(struct inode * inode, struct file * filp); +static int hptraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int hptraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh); + + + +struct hptdisk { + kdev_t device; + unsigned long sectors; + struct block_device *bdev; +}; + +struct hptraid { + unsigned int stride; + unsigned int disks; + unsigned long sectors; + struct geom geom; + + struct hptdisk disk[8]; + + unsigned long cutoff[8]; + unsigned int cutoff_disks[8]; +}; + +static struct raid_device_operations hptraid_ops = { + open: hptraid_open, + release: hptraid_release, + ioctl: hptraid_ioctl, + make_request: hptraid_make_request +}; + +static struct hptraid raid[16]; + +static int hptraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + unsigned int minor; + unsigned char val; + unsigned long sectors; + + if (!inode || !inode->i_rdev) + return -EINVAL; + + minor = MINOR(inode->i_rdev)>>SHIFT; + + switch (cmd) { + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects; + if (MINOR(inode->i_rdev)&15) + return put_user(sectors, (long *) arg); + return put_user(raid[minor].sectors , (long *) arg); + break; + + + case HDIO_GETGEO: + { + struct hd_geometry *loc = (struct hd_geometry *) arg; + unsigned short bios_cyl; + + if (!loc) return -EINVAL; + val = 255; + if (put_user(val, (byte *) &loc->heads)) return -EFAULT; + val=63; + if (put_user(val, (byte *) &loc->sectors)) return -EFAULT; + bios_cyl = raid[minor].sectors/63/255; + if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + case HDIO_GETGEO_BIG: + { + struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; + unsigned int bios_cyl; + if (!loc) return -EINVAL; + val = 255; + if (put_user(val, (byte *) &loc->heads)) return -EFAULT; + val = 63; + if (put_user(val, (byte *) &loc->sectors)) return -EFAULT; + bios_cyl = raid[minor].sectors/63/255; + if (put_user(bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + case BLKROSET: + case BLKROGET: + case BLKSSZGET: + return blk_ioctl(inode->i_rdev, cmd, arg); + + default: + return -EINVAL; + }; + + return 0; +} + + +static int hptraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + unsigned long rsect; + unsigned long rsect_left,rsect_accum = 0; + unsigned long block; + unsigned int disk=0,real_disk=0; + int i; + int device; + struct hptraid *thisraid; + + rsect = bh->b_rsector; + + /* Ok. We need to modify this sector number to a new disk + new sector number. + * If there are disks of different sizes, this gets tricky. + * Example with 3 disks (1Gb, 4Gb and 5 GB): + * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. + * Then things get interesting. The next 2Gb (RAID view) are spread across disk 2 and 3 + * and the last 1Gb is disk 3 only. + * + * the way this is solved is like this: We have a list of "cutoff" points where everytime + * a disk falls out of the "higher" count, we mark the max sector. So once we pass a cutoff + * point, we have to divide by one less. + */ + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + thisraid = &raid[device]; + if (thisraid->stride==0) + thisraid->stride=1; + + /* Partitions need adding of the start sector of the partition to the requested sector */ + + rsect += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; + + /* Woops we need to split the request to avoid crossing a stride barrier */ + if ((rsect/thisraid->stride) != ((rsect+(bh->b_size/512)-1)/thisraid->stride)) { + return -1; + } + + rsect_left = rsect; + + for (i=0;i<8;i++) { + if (thisraid->cutoff_disks[i]==0) + break; + if (rsect > thisraid->cutoff[i]) { + /* we're in the wrong area so far */ + rsect_left -= thisraid->cutoff[i]; + rsect_accum += thisraid->cutoff[i]/thisraid->cutoff_disks[i]; + } else { + block = rsect_left / thisraid->stride; + disk = block % thisraid->cutoff_disks[i]; + block = (block / thisraid->cutoff_disks[i]) * thisraid->stride; + rsect = rsect_accum + (rsect_left % thisraid->stride) + block; + break; + } + } + + for (i=0;i<8;i++) { + if ((disk==0) && (thisraid->disk[i].sectors > rsect_accum)) { + real_disk = i; + break; + } + if ((disk>0) && (thisraid->disk[i].sectors >= rsect_accum)) { + disk--; + } + + } + disk = real_disk; + + /* All but the first disk have a 10 sector offset */ + if (i>0) + rsect+=10; + + + /* + * The new BH_Lock semantics in ll_rw_blk.c guarantee that this + * is the only IO operation happening on this bh. + */ + + bh->b_rdev = thisraid->disk[disk].device; + bh->b_rsector = rsect; + + /* + * Let the main block layer submit the IO and resolve recursion: + */ + return 1; +} + + +#include "hptraid.h" + +static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize) +{ + int ret = -EINVAL; + struct buffer_head *bh = NULL; + kdev_t dev = MKDEV(major,minor); + + if (blksize_size[major]==NULL) /* device doesn't exist */ + return -EINVAL; + + + /* Superblock is at 4096+412 bytes */ + set_blocksize (dev, 4096); + bh = bread (dev, 1, 4096); + + + if (bh) { + memcpy (buffer, bh->b_data, bufsize); + } else { + printk(KERN_ERR "hptraid: Error reading superblock.\n"); + goto abort; + } + ret = 0; +abort: + if (bh) + brelse (bh); + return ret; +} + +static unsigned long maxsectors (int major,int minor) +{ + unsigned long lba = 0; + kdev_t dev; + ide_drive_t *ideinfo; + + dev = MKDEV(major,minor); + ideinfo = get_info_ptr (dev); + if (ideinfo==NULL) + return 0; + + + /* first sector of the last cluster */ + if (ideinfo->head==0) + return 0; + if (ideinfo->sect==0) + return 0; + lba = (ideinfo->capacity); + + return lba; +} + +static void __init probedisk(int major, int minor,int device) +{ + int i; + struct highpoint_raid_conf *prom; + static unsigned char block[4096]; + + if (maxsectors(major,minor)==0) + return; + + if (read_disk_sb(major,minor,(unsigned char*)&block,sizeof(block))) + return; + + prom = (struct highpoint_raid_conf*)&block[512]; + + if (prom->magic!= 0x5a7816f0) + return; + if (prom->type) { + printk(KERN_INFO "hptraid: only RAID0 is supported currently\n"); + return; + } + + i = prom->disk_number; + if (i<0) + return; + if (i>8) + return; + + raid[device].disk[i].bdev = bdget(MKDEV(major,minor)); + if (raid[device].disk[i].bdev != NULL) { + int j=0; + struct gendisk *gd; + /* This is supposed to prevent others from stealing our underlying disks */ + blkdev_get(raid[device].disk[i].bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW); + /* now blank the /proc/partitions table for the wrong partition table, + so that scripts don't accidentally mount it and crash the kernel */ + /* XXX: the 0 is an utter hack --hch */ + gd=get_gendisk(MKDEV(major, 0)); + if (gd!=NULL) { + for (j=1+(minor<minor_shift);j<((minor+1)<minor_shift);j++) + gd->part[j].nr_sects=0; + put_gendisk(gd); + } + } + raid[device].disk[i].device = MKDEV(major,minor); + raid[device].disk[i].sectors = maxsectors(major,minor); + raid[device].stride = (1<raid0_shift); + raid[device].disks = prom->raid_disks; + raid[device].sectors = prom->total_secs; + +} + +static void __init fill_cutoff(int device) +{ + int i,j; + unsigned long smallest; + unsigned long bar; + int count; + + bar = 0; + for (i=0;i<8;i++) { + smallest = ~0; + for (j=0;j<8;j++) + if ((raid[device].disk[j].sectors < smallest) && (raid[device].disk[j].sectors>bar)) + smallest = raid[device].disk[j].sectors; + count = 0; + for (j=0;j<8;j++) + if (raid[device].disk[j].sectors >= smallest) + count++; + + smallest = smallest * count; + bar = smallest; + raid[device].cutoff[i] = smallest; + raid[device].cutoff_disks[i] = count; + + } +} + + +static __init int hptraid_init_one(int device) +{ + int i,count; + + probedisk(IDE0_MAJOR, 0, device); + probedisk(IDE0_MAJOR, 64, device); + probedisk(IDE1_MAJOR, 0, device); + probedisk(IDE1_MAJOR, 64, device); + probedisk(IDE2_MAJOR, 0, device); + probedisk(IDE2_MAJOR, 64, device); + probedisk(IDE3_MAJOR, 0, device); + probedisk(IDE3_MAJOR, 64, device); + + fill_cutoff(device); + + /* Initialize the gendisk structure */ + + ataraid_register_disk(device,raid[device].sectors); + + count=0; + printk(KERN_INFO "Highpoint HPT370 Softwareraid driver for linux version 0.01\n"); + + for (i=0;i<8;i++) { + if (raid[device].disk[i].device!=0) { + printk(KERN_INFO "Drive %i is %li Mb \n", + i,raid[device].disk[i].sectors/2048); + count++; + } + } + if (count) { + printk(KERN_INFO "Raid array consists of %i drives. \n",count); + return 0; + } else { + printk(KERN_INFO "No raid array found\n"); + return -ENODEV; + } + +} + +static __init int hptraid_init(void) +{ + int retval,device; + + device=ataraid_get_device(&hptraid_ops); + if (device<0) + return -ENODEV; + retval = hptraid_init_one(device); + if (retval) + ataraid_release_device(device); + return retval; +} + +static void __exit hptraid_exit (void) +{ + int i,device; + for (device = 0; device<16; device++) { + for (i=0;i<8;i++) + if (raid[device].disk[i].bdev) { + blkdev_put(raid[device].disk[i].bdev, BDEV_RAW); + bdput(raid[device].disk[i].bdev); + raid[device].disk[i].bdev = NULL; + } + if (raid[device].sectors) + ataraid_release_device(device); + } +} + +static int hptraid_open(struct inode * inode, struct file * filp) +{ + MOD_INC_USE_COUNT; + return 0; +} +static int hptraid_release(struct inode * inode, struct file * filp) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +module_init(hptraid_init); +module_exit(hptraid_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/ide/hptraid.h linux/drivers/ide/hptraid.h --- v2.4.9/linux/drivers/ide/hptraid.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/ide/hptraid.h Mon Sep 17 23:23:40 2001 @@ -0,0 +1,49 @@ + +struct highpoint_raid_conf +{ + int8_t filler1[32]; + u_int32_t magic; +#define HPT_MAGIC_OK 0x5a7816f0 +#define HPT_MAGIC_BAD 0x5a7816fd + + u_int32_t magic_0; + u_int32_t magic_1; + u_int32_t order; +#define HPT_O_MIRROR 0x01 +#define HPT_O_STRIPE 0x02 +#define HPT_O_OK 0x04 + + u_int8_t raid_disks; + u_int8_t raid0_shift; + u_int8_t type; +#define HPT_T_RAID_0 0x00 +#define HPT_T_RAID_1 0x01 +#define HPT_T_RAID_01_RAID_0 0x02 +#define HPT_T_SPAN 0x03 +#define HPT_T_RAID_3 0x04 +#define HPT_T_RAID_5 0x05 +#define HPT_T_SINGLEDISK 0x06 +#define HPT_T_RAID_01_RAID_1 0x07 + + u_int8_t disk_number; + u_int32_t total_secs; + u_int32_t disk_mode; + u_int32_t boot_mode; + u_int8_t boot_disk; + u_int8_t boot_protect; + u_int8_t error_log_entries; + u_int8_t error_log_index; + struct + { + u_int32_t timestamp; + u_int8_t reason; +#define HPT_R_REMOVED 0xfe +#define HPT_R_BROKEN 0xff + + u_int8_t disk; + u_int8_t status; + u_int8_t sectors; + u_int32_t lba; + } errorlog[32]; + u_int8_t filler[60]; +}; diff -u --recursive --new-file v2.4.9/linux/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c --- v2.4.9/linux/drivers/ide/ide-dma.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/ide-dma.c Sun Sep 9 10:43:02 2001 @@ -130,10 +130,30 @@ { "WDC AC23200L" , "21.10N21" }, { "Compaq CRD-8241B" , "ALL" }, { "CRD-8400B" , "ALL" }, + { "CRD-8480B", "ALL" }, + { "CRD-8480C", "ALL" }, + { "CRD-8482B", "ALL" }, + { "CRD-84" , "ALL" }, + { "SanDisk SDP3B" , "ALL" }, + { "SanDisk SDP3B-64" , "ALL" }, + { "SANYO CD-ROM CRD" , "ALL" }, + { "HITACHI CDR-8" , "ALL" }, + { "HITACHI CDR-8335" , "ALL" }, + { "HITACHI CDR-8435" , "ALL" }, + { "Toshiba CD-ROM XM-6202B" , "ALL" }, + { "CD-532E-A" , "ALL" }, + { "E-IDE CD-ROM CR-840", "ALL" }, + { "CD-ROM Drive/F5A", "ALL" }, + { "RICOH CD-R/RW MP7083A", "ALL" }, + { "WPI CDD-820", "ALL" }, + { "SAMSUNG CD-ROM SC-148C", "ALL" }, + { "SAMSUNG CD-ROM SC-148F", "ALL" }, + { "SAMSUNG CD-ROM SC", "ALL" }, { "SanDisk SDP3B-64" , "ALL" }, { "SAMSUNG CD-ROM SN-124", "ALL" }, { "PLEXTOR CD-R PX-W8432T", "ALL" }, { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, + { "_NEC DV5800A", "ALL" }, { 0 , 0 } }; 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-pci.c linux/drivers/ide/ide-pci.c --- v2.4.9/linux/drivers/ide/ide-pci.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/ide-pci.c Sun Sep 9 10:43:02 2001 @@ -38,6 +38,7 @@ #define DEVID_PIIX4U3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9}) #define DEVID_PIIX4U4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8}) #define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) +#define DEVID_MR_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1}) #define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) #define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) #define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) @@ -385,6 +386,7 @@ {DEVID_PIIX4U3, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4U4, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_MR_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, #ifdef CONFIG_PDC202XX_FORCE {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, @@ -758,6 +760,7 @@ IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || IDE_PCI_DEVID_EQ(d->devid, DEVID_VIA_IDE) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_MR_IDE) || IDE_PCI_DEVID_EQ(d->devid, DEVID_VP_IDE)) autodma = 0; if (autodma) @@ -767,6 +770,7 @@ IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268R) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) || 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 Mon Sep 17 13:16:30 2001 @@ -931,7 +931,7 @@ cur & 0xf, IN_BYTE(IDE_SECTOR_REG)); } - if (HWGROUP(drive)->rq) + if (HWGROUP(drive) && HWGROUP(drive)->rq) printk(", sector=%ld", HWGROUP(drive)->rq->sector); } } @@ -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 */ @@ -2663,6 +2660,8 @@ case BLKGETSIZE: /* Return device size */ return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (long *) arg); + case BLKGETSIZE64: + return put_user((u64)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects << 9, (u64 *) arg); case BLKRRPART: /* Re-read partition tables */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -2788,6 +2787,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 +2988,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 +3156,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 +3223,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/pdcraid.c linux/drivers/ide/pdcraid.c --- v2.4.9/linux/drivers/ide/pdcraid.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/ide/pdcraid.c Mon Sep 17 23:23:40 2001 @@ -0,0 +1,445 @@ +/* + pdcraid.c Copyright (C) 2001 Red Hat, Inc. All rights reserved. + + 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. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Authors: Arjan van de Ven + + + + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ataraid.h" + +static int pdcraid_open(struct inode * inode, struct file * filp); +static int pdcraid_release(struct inode * inode, struct file * filp); +static int pdcraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int pdcraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh); + + + +struct pdcdisk { + kdev_t device; + unsigned long sectors; + struct block_device *bdev; +}; + +struct pdcraid { + unsigned int stride; + unsigned int disks; + unsigned long sectors; + struct geom geom; + + struct pdcdisk disk[8]; + + unsigned long cutoff[8]; + unsigned int cutoff_disks[8]; +}; + +static struct raid_device_operations pdcraid_ops = { + open: pdcraid_open, + release: pdcraid_release, + ioctl: pdcraid_ioctl, + make_request: pdcraid_make_request +}; + +static struct pdcraid raid[16]; + +static int pdcraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + unsigned int minor; + unsigned long sectors; + + if (!inode || !inode->i_rdev) + return -EINVAL; + + minor = MINOR(inode->i_rdev)>>SHIFT; + + switch (cmd) { + + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects; + if (MINOR(inode->i_rdev)&15) + return put_user(sectors, (long *) arg); + return put_user(raid[minor].sectors , (long *) arg); + break; + + + case HDIO_GETGEO: + { + struct hd_geometry *loc = (struct hd_geometry *) arg; + unsigned short bios_cyl = raid[minor].geom.cylinders; /* truncate */ + + if (!loc) return -EINVAL; + if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT; + if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + case HDIO_GETGEO_BIG: + { + struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; + if (!loc) return -EINVAL; + if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT; + if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(raid[minor].geom.cylinders, (unsigned int *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + + case BLKROSET: + case BLKROGET: + case BLKSSZGET: + return blk_ioctl(inode->i_rdev, cmd, arg); + + default: + return -EINVAL; + }; + + return 0; +} + + +static int pdcraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + unsigned long rsect; + unsigned long rsect_left,rsect_accum = 0; + unsigned long block; + unsigned int disk=0,real_disk=0; + int i; + int device; + struct pdcraid *thisraid; + + rsect = bh->b_rsector; + + /* Ok. We need to modify this sector number to a new disk + new sector number. + * If there are disks of different sizes, this gets tricky. + * Example with 3 disks (1Gb, 4Gb and 5 GB): + * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. + * Then things get interesting. The next 2Gb (RAID view) are spread across disk 2 and 3 + * and the last 1Gb is disk 3 only. + * + * the way this is solved is like this: We have a list of "cutoff" points where everytime + * a disk falls out of the "higher" count, we mark the max sector. So once we pass a cutoff + * point, we have to divide by one less. + */ + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + thisraid = &raid[device]; + if (thisraid->stride==0) + thisraid->stride=1; + + /* Partitions need adding of the start sector of the partition to the requested sector */ + + rsect += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; + + /* Woops we need to split the request to avoid crossing a stride barrier */ + if ((rsect/thisraid->stride) != ((rsect+(bh->b_size/512)-1)/thisraid->stride)) { + return -1; + } + + rsect_left = rsect; + + for (i=0;i<8;i++) { + if (thisraid->cutoff_disks[i]==0) + break; + if (rsect > thisraid->cutoff[i]) { + /* we're in the wrong area so far */ + rsect_left -= thisraid->cutoff[i]; + rsect_accum += thisraid->cutoff[i]/thisraid->cutoff_disks[i]; + } else { + block = rsect_left / thisraid->stride; + disk = block % thisraid->cutoff_disks[i]; + block = (block / thisraid->cutoff_disks[i]) * thisraid->stride; + rsect = rsect_accum + (rsect_left % thisraid->stride) + block; + break; + } + } + + for (i=0;i<8;i++) { + if ((disk==0) && (thisraid->disk[i].sectors > rsect_accum)) { + real_disk = i; + break; + } + if ((disk>0) && (thisraid->disk[i].sectors >= rsect_accum)) { + disk--; + } + + } + disk = real_disk; + + + /* + * The new BH_Lock semantics in ll_rw_blk.c guarantee that this + * is the only IO operation happening on this bh. + */ + bh->b_rdev = thisraid->disk[disk].device; + bh->b_rsector = rsect; + + /* + * Let the main block layer submit the IO and resolve recursion: + */ + return 1; +} + + +#include "pdcraid.h" + +static unsigned long calc_pdcblock_offset (int major,int minor) +{ + unsigned long lba = 0; + kdev_t dev; + ide_drive_t *ideinfo; + + dev = MKDEV(major,minor); + ideinfo = get_info_ptr (dev); + if (ideinfo==NULL) + return 0; + + + /* first sector of the last cluster */ + if (ideinfo->head==0) + return 0; + if (ideinfo->sect==0) + return 0; + lba = (ideinfo->capacity / (ideinfo->head*ideinfo->sect)); + lba = lba * (ideinfo->head*ideinfo->sect); + lba = lba - ideinfo->sect; + + return lba; +} + + +static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize) +{ + int ret = -EINVAL; + struct buffer_head *bh = NULL; + kdev_t dev = MKDEV(major,minor); + unsigned long sb_offset; + + if (blksize_size[major]==NULL) /* device doesn't exist */ + return -EINVAL; + + + /* + * Calculate the position of the superblock, + * it's at first sector of the last cylinder + */ + sb_offset = calc_pdcblock_offset(major,minor)/8; + /* The /8 transforms sectors into 4Kb blocks */ + + if (sb_offset==0) + return -1; + + set_blocksize (dev, 4096); + + bh = bread (dev, sb_offset, 4096); + + if (bh) { + memcpy (buffer, bh->b_data, bufsize); + } else { + printk(KERN_ERR "pdcraid: Error reading superblock.\n"); + goto abort; + } + ret = 0; +abort: + if (bh) + brelse (bh); + return ret; +} + +static unsigned int calc_sb_csum (unsigned int* ptr) +{ + unsigned int sum; + int count; + + sum = 0; + for (count=0;count<511;count++) + sum += *ptr++; + + return sum; +} + +static void __init probedisk(int major, int minor,int device) +{ + int i; + struct promise_raid_conf *prom; + static unsigned char block[4096]; + + if (read_disk_sb(major,minor,(unsigned char*)&block,sizeof(block))) + return; + + prom = (struct promise_raid_conf*)&block[512]; + + /* the checksums must match */ + if (prom->checksum != calc_sb_csum((unsigned int*)prom)) + return; + if (prom->raid.type!=0x00) /* Only raid 0 is supported right now */ + return; + + + /* This looks evil. But basically, we have to search for our adapternumber + in the arraydefinition, both of which are in the superblock */ + for (i=0;(iraid.total_disks)&&(i<8);i++) { + if ( (prom->raid.disk[i].channel== prom->raid.channel) && + (prom->raid.disk[i].device == prom->raid.device) ) { + raid[device].disk[i].bdev = bdget(MKDEV(major,minor)); + if (raid[device].disk[i].bdev != NULL) { + struct gendisk *gd; + int j; + /* This is supposed to prevent others from stealing our underlying disks */ + blkdev_get(raid[device].disk[i].bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW); + gd=get_gendisk(major); + if (gd!=NULL) { + for (j=1+(minor<minor_shift);j<((minor+1)<minor_shift);j++) + gd->part[j].nr_sects=0; + put_gendisk(gd); + } + } + raid[device].disk[i].device = MKDEV(major,minor); + raid[device].disk[i].sectors = prom->raid.disk_secs; + raid[device].stride = (1<raid.raid0_shift); + raid[device].disks = prom->raid.total_disks; + raid[device].sectors = prom->raid.total_secs; + raid[device].geom.heads = prom->raid.heads+1; + raid[device].geom.sectors = prom->raid.sectors; + raid[device].geom.cylinders = prom->raid.cylinders+1; + + } + } + +} + +static void __init fill_cutoff(int device) +{ + int i,j; + unsigned long smallest; + unsigned long bar; + int count; + + bar = 0; + for (i=0;i<8;i++) { + smallest = ~0; + for (j=0;j<8;j++) + if ((raid[device].disk[j].sectors < smallest) && (raid[device].disk[j].sectors>bar)) + smallest = raid[device].disk[j].sectors; + count = 0; + for (j=0;j<8;j++) + if (raid[device].disk[j].sectors >= smallest) + count++; + + smallest = smallest * count; + bar = smallest; + raid[device].cutoff[i] = smallest; + raid[device].cutoff_disks[i] = count; + } +} + +static __init int pdcraid_init_one(int device) +{ + int i,count; + + probedisk(IDE0_MAJOR, 0, device); + probedisk(IDE0_MAJOR, 64, device); + probedisk(IDE1_MAJOR, 0, device); + probedisk(IDE1_MAJOR, 64, device); + probedisk(IDE2_MAJOR, 0, device); + probedisk(IDE2_MAJOR, 64, device); + probedisk(IDE3_MAJOR, 0, device); + probedisk(IDE3_MAJOR, 64, device); + + fill_cutoff(device); + + /* Initialize the gendisk structure */ + + ataraid_register_disk(device,raid[device].sectors); + + count=0; + printk(KERN_INFO "Promise Fasttrak(tm) Softwareraid driver for linux version 0.02\n"); + + for (i=0;i<8;i++) { + if (raid[device].disk[i].device!=0) { + printk(KERN_INFO "Drive %i is %li Mb \n", + i,raid[device].disk[i].sectors/2048); + count++; + } + } + if (count) { + printk(KERN_INFO "Raid array consists of %i drives. \n",count); + return 0; + } else { + printk(KERN_INFO "No raid array found\n"); + return -ENODEV; + } +} + +static __init int pdcraid_init(void) +{ + int retval,device; + + device=ataraid_get_device(&pdcraid_ops); + if (device<0) + return -ENODEV; + retval = pdcraid_init_one(device); + if (retval) + ataraid_release_device(device); + return retval; +} + +static void __exit pdcraid_exit (void) +{ + int i,device; + for (device = 0; device<16; device++) { + for (i=0;i<8;i++) + if (raid[device].disk[i].bdev) { + blkdev_put(raid[device].disk[i].bdev, BDEV_RAW); + bdput(raid[device].disk[i].bdev); + raid[device].disk[i].bdev = NULL; + + } + if (raid[device].sectors) + ataraid_release_device(device); + } +} + +static int pdcraid_open(struct inode * inode, struct file * filp) +{ + MOD_INC_USE_COUNT; + return 0; +} +static int pdcraid_release(struct inode * inode, struct file * filp) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +module_init(pdcraid_init); +module_exit(pdcraid_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/ide/pdcraid.h linux/drivers/ide/pdcraid.h --- v2.4.9/linux/drivers/ide/pdcraid.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/ide/pdcraid.h Mon Sep 17 23:23:40 2001 @@ -0,0 +1,47 @@ +struct promise_raid_conf { + char promise_id[24]; + + u32 dummy_0; + u32 magic_0; + u32 dummy_1; + u32 magic_1; + u16 dummy_2; + u8 filler1[470]; + struct { + u32 flags; /* 0x200 */ + u8 dummy_0; + u8 disk_number; + u8 channel; + u8 device; + u32 magic_0; + u32 dummy_1; + u32 dummy_2; /* 0x210 */ + u32 disk_secs; + u32 dummy_3; + u16 dummy_4; + u8 status; + u8 type; + u8 total_disks; /* 0x220 */ + u8 raid0_shift; + u8 raid0_disks; + u8 array_number; + u32 total_secs; + u16 cylinders; + u8 heads; + u8 sectors; + u32 magic_1; + u32 dummy_5; /* 0x230 */ + struct { + u16 dummy_0; + u8 channel; + u8 device; + u32 magic_0; + u32 disk_number; + } disk[8]; + } raid; + u32 filler2[346]; + u32 checksum; +}; + +#define PR_MAGIC "Promise Technology, Inc." + 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/serverworks.c linux/drivers/ide/serverworks.c --- v2.4.9/linux/drivers/ide/serverworks.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/serverworks.c Sun Sep 9 10:43:02 2001 @@ -544,8 +544,33 @@ return 0; } +/* On Dell PowerEdge servers with a CSB5, the top two bits of the subsystem + * device ID indicate presence of an 80-pin cable. + * Bit 15 clear = secondary IDE channel does not have 80-pin cable. + * Bit 15 set = secondary IDE channel has 80-pin cable. + * Bit 14 clear = primary IDE channel does not have 80-pin cable. + * Bit 14 set = primary IDE channel has 80-pin cable. + */ + +static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && + dev->vendor == PCI_VENDOR_ID_SERVERWORKS && + dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) + return ((1 << (hwif->channel + 14)) & + dev->subsystem_device) ? 1 : 0; + + return 0; + +} + unsigned int __init ata66_svwks (ide_hwif_t *hwif) { + struct pci_dev *dev = hwif->pci_dev; + if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) + return ata66_svwks_dell (hwif); + return 0; } 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 Tue Sep 11 08:40:36 2001 @@ -1,5 +1,5 @@ /* - * $Id: via82cxxx.c,v 3.23 2001/03/09 09:30:00 vojtech Exp $ + * $Id: via82cxxx.c,v 3.29 2001/09/10 10:06: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 @@ -87,8 +90,7 @@ #define VIA_BAD_PREQ 0x010 /* Crashes if PREQ# till DDACK# set */ #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 */ +#define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */ /* * 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, 0x00, 0x2f, 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 | VIA_NO_UNMASK }, { NULL } }; @@ -154,7 +161,7 @@ via_print("----------VIA BusMastering IDE Configuration----------------"); - via_print("Driver Version: 3.23"); + via_print("Driver Version: 3.29"); 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; } @@ -424,7 +431,7 @@ } if (via_config->flags & VIA_BAD_CLK66) { /* Disable Clk66 */ - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Would cause trouble on 596a */ + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Would cause trouble on 596a and 686 */ pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); } @@ -453,9 +460,6 @@ } } - if (via_config->flags & VIA_SET_THRESH) /* 1/2 FIFO full to trigger xmit */ - t = (t & 0xf0) | 0x0a; - pci_write_config_byte(dev, VIA_FIFO_CONFIG, t); /* @@ -509,7 +513,7 @@ for (i = 0; i < 2; i++) { hwif->drives[i].io_32bit = 1; - hwif->drives[i].unmask = 1; + hwif->drives[i].unmask = (via_config->flags & VIA_NO_UNMASK) ? 0 : 1; hwif->drives[i].autotune = 1; hwif->drives[i].dn = hwif->channel * 2 + i; } 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/ieee1394/nodemgr.c linux/drivers/ieee1394/nodemgr.c --- v2.4.9/linux/drivers/ieee1394/nodemgr.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ieee1394/nodemgr.c Mon Sep 17 22:52:35 2001 @@ -352,7 +352,7 @@ { struct hpsb_host *host = (struct hpsb_host *)data; struct selfid *sid = (struct selfid *)host->topology_map; - struct list_head *lh; + struct list_head *lh,*spare; struct node_entry *ne; int nodecount = host->node_count; nodeid_t nodeid = LOCAL_BUS; @@ -442,7 +442,7 @@ /* Now check to see if we have any nodes that aren't referenced * any longer. */ write_lock_irqsave(&node_lock, flags); - list_for_each(lh, &node_list) { + list_for_each_safe(lh, spare, &node_list) { ne = list_entry(lh, struct node_entry, list); /* Only checking this host */ diff -u --recursive --new-file v2.4.9/linux/drivers/ieee1394/video1394.c linux/drivers/ieee1394/video1394.c --- v2.4.9/linux/drivers/ieee1394/video1394.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ieee1394/video1394.c Thu Sep 13 15:21:32 2001 @@ -103,7 +103,7 @@ int ctxMatch; wait_queue_head_t waitq; spinlock_t lock; - unsigned int syt_offset; + unsigned int syt_offset; int flags; }; diff -u --recursive --new-file v2.4.9/linux/drivers/input/Config.in linux/drivers/input/Config.in --- v2.4.9/linux/drivers/input/Config.in Tue Aug 22 11:41:14 2000 +++ linux/drivers/input/Config.in Wed Sep 12 15:34:06 2001 @@ -6,15 +6,13 @@ comment 'Input core support' tristate 'Input core support' CONFIG_INPUT -if [ "$CONFIG_INPUT" != "n" ]; then - dep_tristate ' Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT - dep_tristate ' Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT - if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then - int ' Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 - int ' Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768 - fi - dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_INPUT - dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_INPUT +dep_tristate ' Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT +dep_tristate ' Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT +if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then + int ' Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 + int ' Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768 fi +dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_INPUT +dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_INPUT endmenu diff -u --recursive --new-file v2.4.9/linux/drivers/input/evdev.c linux/drivers/input/evdev.c --- v2.4.9/linux/drivers/input/evdev.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/input/evdev.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: evdev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $ + * $Id: evdev.c,v 1.27 2001/05/28 09:06:44 vojtech Exp $ * - * Copyright (c) 1999-2000 Vojtech Pavlik + * Copyright (c) 1999-2001 Vojtech Pavlik * * Event char devices, giving access to raw input device events. * @@ -11,18 +11,18 @@ /* * 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 + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic @@ -72,7 +72,7 @@ list->buffer[list->head].code = code; list->buffer[list->head].value = value; list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1); - + kill_fasync(&list->fasync, SIGIO, POLL_IN); list = list->next; @@ -104,7 +104,7 @@ if (!--list->evdev->open) { if (list->evdev->exist) { - input_close_device(&list->evdev->handle); + input_close_device(&list->evdev->handle); } else { input_unregister_minor(list->evdev->devfs); evdev_table[list->evdev->minor] = NULL; @@ -138,14 +138,26 @@ if (!list->evdev->open++) if (list->evdev->exist) - input_open_device(&list->evdev->handle); + input_open_device(&list->evdev->handle); return 0; } static ssize_t evdev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos) { - return -EINVAL; + struct evdev_list *list = file->private_data; + struct input_event event; + int retval = 0; + + while (retval < count) { + + if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) + return -EFAULT; + input_event(list->evdev->handle.dev, event.type, event.code, event.value); + retval += sizeof(struct input_event); + } + + return retval; } static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_t *ppos) @@ -161,6 +173,10 @@ while (list->head == list->tail) { + if (!list->evdev->exist) { + retval = -ENODEV; + break; + } if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; @@ -187,7 +203,7 @@ retval += sizeof(struct input_event); } - return retval; + return retval; } /* No kernel lock - fine */ @@ -219,6 +235,32 @@ if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval; return 0; + case EVIOCSFF: + if (dev->upload_effect) { + struct ff_effect effect; + int err; + + if (copy_from_user((void*)(&effect), (void*)arg, sizeof(effect))) { + return -EINVAL; + } + err = dev->upload_effect(dev, &effect); + if (put_user(effect.id, &(((struct ff_effect*)arg)->id))) { + return -EINVAL; + } + return err; + } + else return -ENOSYS; + + case EVIOCRMFF: + if (dev->erase_effect) { + return dev->erase_effect(dev, (int)arg); + } + else return -ENOSYS; + + case EVIOCGEFFECTS: + put_user(dev->ff_effects_max, (int*) arg); + return 0; + default: if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) @@ -236,6 +278,7 @@ case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; case EV_LED: bits = dev->ledbit; len = LED_MAX; break; case EV_SND: bits = dev->sndbit; len = SND_MAX; break; + case EV_FF: bits = dev->ffbit; len = FF_MAX; break; default: return -EINVAL; } len = NBITS(len) * sizeof(long); @@ -310,7 +353,7 @@ evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE); - printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number); +// printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number); return &evdev->handle; } @@ -323,13 +366,14 @@ if (evdev->open) { input_close_device(handle); + wake_up_interruptible(&evdev->wait); } else { input_unregister_minor(evdev->devfs); evdev_table[evdev->minor] = NULL; kfree(evdev); } } - + static struct input_handler evdev_handler = { event: evdev_event, connect: evdev_connect, diff -u --recursive --new-file v2.4.9/linux/drivers/input/input.c linux/drivers/input/input.c --- v2.4.9/linux/drivers/input/input.c Fri Nov 17 16:52:23 2000 +++ linux/drivers/input/input.c Wed Sep 12 15:34:06 2001 @@ -1,7 +1,7 @@ /* - * $Id: input.c,v 1.7 2000/05/28 17:31:36 vojtech Exp $ + * $Id: input.c,v 1.20 2001/05/17 15:50:27 vojtech Exp $ * - * Copyright (c) 1999-2000 Vojtech Pavlik + * Copyright (c) 1999-2001 Vojtech Pavlik * * The input layer module itself * @@ -124,6 +124,13 @@ break; + case EV_MSC: + + if (code > MSC_MAX || !test_bit(code, dev->mscbit)) + return; + + break; + case EV_LED: if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value) @@ -152,14 +159,11 @@ if (dev->event) dev->event(dev, type, code, value); break; - } -/* - * Add randomness. - */ -#if 0 /* BUG */ - add_input_randomness(((unsigned long) dev) ^ (type << 24) ^ (code << 16) ^ value); -#endif + case EV_FF: + if (dev->event) dev->event(dev, type, code, value); + break; + } /* * Distribute the event to handler modules. diff -u --recursive --new-file v2.4.9/linux/drivers/input/keybdev.c linux/drivers/input/keybdev.c --- v2.4.9/linux/drivers/input/keybdev.c Wed Apr 25 14:35:25 2001 +++ linux/drivers/input/keybdev.c Tue Sep 18 14:10:43 2001 @@ -39,7 +39,8 @@ #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \ defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH) || \ - defined(CONFIG_PPC) || defined(__mc68000__) + defined(CONFIG_PPC) || defined(__mc68000__) || defined(__hppa__) || \ + defined(__arm__) static int x86_sysrq_alt = 0; #ifdef CONFIG_SPARC64 @@ -47,6 +48,8 @@ extern void batten_down_hatches(void); #endif +static int jp_kbd_109 = 1; /* Yes, .jp is the default. See 51142. */ + static unsigned short x86_keycodes[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, @@ -197,14 +200,14 @@ input_open_device(handle); - printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number); +// printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number); return handle; } static void keybdev_disconnect(struct input_handle *handle) { - printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number); +// printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number); input_close_device(handle); kfree(handle); } @@ -219,6 +222,15 @@ { input_register_handler(&keybdev_handler); kbd_ledfunc = keybdev_ledfunc; + + if (jp_kbd_109) { + x86_keycodes[0xb5] = 0x73; /* backslash, underscore */ + x86_keycodes[0xb6] = 0x70; + x86_keycodes[0xb7] = 0x7d; /* Yen, pipe */ + x86_keycodes[0xb8] = 0x79; + x86_keycodes[0xb9] = 0x7b; + } + return 0; } @@ -233,3 +245,4 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Input driver to keyboard driver binding"); +MODULE_PARM(jp_kbd_109, "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/input/mousedev.c linux/drivers/input/mousedev.c --- v2.4.9/linux/drivers/input/mousedev.c Sun Mar 25 18:14:20 2001 +++ linux/drivers/input/mousedev.c Wed Sep 12 15:34:06 2001 @@ -1,9 +1,9 @@ /* - * $Id: mousedev.c,v 1.15 2000/08/14 21:05:26 vojtech Exp $ + * $Id: mousedev.c,v 1.24 2000/11/15 10:57:45 vojtech Exp $ * * Copyright (c) 1999-2000 Vojtech Pavlik * - * Input driver to PS/2 or ImPS/2 device driver module. + * Input driver to ImExPS/2 device driver module. * * Sponsored by SuSE */ @@ -66,20 +66,22 @@ signed char ps2[6]; unsigned long buttons; unsigned char ready, buffer, bufsiz; - unsigned char mode, genseq, impseq; + unsigned char mode, imexseq, impsseq; }; -#define MOUSEDEV_GENIUS_LEN 5 -#define MOUSEDEV_IMPS_LEN 6 +#define MOUSEDEV_SEQ_LEN 6 -static unsigned char mousedev_genius_seq[] = { 0xe8, 3, 0xe6, 0xe6, 0xe6 }; static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; +static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; static struct input_handler mousedev_handler; static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; static struct mousedev mousedev_mix; +static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X; +static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; + static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL }; @@ -99,12 +101,12 @@ switch (code) { case ABS_X: size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]; - list->dx += (value * CONFIG_INPUT_MOUSEDEV_SCREEN_X - list->oldx) / size; + list->dx += (value * xres - list->oldx) / size; list->oldx += list->dx * size; break; case ABS_Y: size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y]; - list->dy -= (value * CONFIG_INPUT_MOUSEDEV_SCREEN_Y - list->oldy) / size; + list->dy -= (value * yres - list->oldy) / size; list->oldy -= list->dy * size; break; } @@ -124,12 +126,12 @@ case BTN_TOUCH: case BTN_LEFT: index = 0; break; case BTN_4: - case BTN_EXTRA: if (list->mode > 1) { index = 4; break; } + case BTN_EXTRA: if (list->mode == 2) { index = 4; break; } case BTN_STYLUS: case BTN_1: case BTN_RIGHT: index = 1; break; case BTN_3: - case BTN_SIDE: if (list->mode > 1) { index = 3; break; } + case BTN_SIDE: if (list->mode == 2) { index = 3; break; } case BTN_2: case BTN_STYLUS2: case BTN_MIDDLE: index = 2; break; @@ -257,14 +259,19 @@ list->dy -= list->ps2[off + 2]; list->bufsiz = off + 3; - if (list->mode > 1) - list->ps2[off] |= ((list->buttons & 0x18) << 3); + if (list->mode == 2) { + list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz)); + list->dz -= list->ps2[off + 3]; + list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1); + list->bufsiz++; + } - if (list->mode) { + if (list->mode == 1) { list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz)); - list->bufsiz++; list->dz -= list->ps2[off + 3]; + list->bufsiz++; } + if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0; list->buffer = list->bufsiz; } @@ -278,27 +285,26 @@ for (i = 0; i < count; i++) { - if (get_user(c, &buffer[i])) + if (get_user(c, buffer + i)) return -EFAULT; - if (c == mousedev_genius_seq[list->genseq]) { - if (++list->genseq == MOUSEDEV_GENIUS_LEN) { - list->genseq = 0; - list->ready = 1; + if (c == mousedev_imex_seq[list->imexseq]) { + if (++list->imexseq == MOUSEDEV_SEQ_LEN) { + list->imexseq = 0; list->mode = 2; } - } else list->genseq = 0; + } else list->imexseq = 0; - if (c == mousedev_imps_seq[list->impseq]) { - if (++list->impseq == MOUSEDEV_IMPS_LEN) { - list->impseq = 0; - list->ready = 1; + if (c == mousedev_imps_seq[list->impsseq]) { + if (++list->impsseq == MOUSEDEV_SEQ_LEN) { + list->impsseq = 0; list->mode = 1; } - } else list->impseq = 0; + } else list->impsseq = 0; list->ps2[0] = 0xfa; list->bufsiz = 1; + list->ready = 1; switch (c) { @@ -307,16 +313,16 @@ break; case 0xf2: /* Get ID */ - list->ps2[1] = (list->mode == 1) ? 3 : 0; + switch (list->mode) { + case 0: list->ps2[1] = 0; + case 1: list->ps2[1] = 3; + case 2: list->ps2[1] = 4; + } list->bufsiz = 2; break; case 0xe9: /* Get info */ - if (list->mode == 2) { - list->ps2[1] = 0x00; list->ps2[2] = 0x33; list->ps2[3] = 0x55; - } else { - list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200; - } + list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200; list->bufsiz = 4; break; } @@ -434,7 +440,7 @@ if (mousedev_mix.open) input_open_device(&mousedev->handle); - printk(KERN_INFO "mouse%d: PS/2 mouse device for input%d\n", minor, dev->number); +// printk(KERN_INFO "mouse%d: PS/2 mouse device for input%d\n", minor, dev->number); return &mousedev->handle; } @@ -491,3 +497,7 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver"); +MODULE_PARM(xres, "i"); +MODULE_PARM_DESC(xres, "Horizontal screen resolution"); +MODULE_PARM(yres, "i"); +MODULE_PARM_DESC(yres, "Vertical screen resolution"); diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/Config.in linux/drivers/isdn/Config.in --- v2.4.9/linux/drivers/isdn/Config.in Mon Aug 27 12:41:41 2001 +++ linux/drivers/isdn/Config.in Sun Sep 9 10:45:43 2001 @@ -76,8 +76,11 @@ bool ' Am7930' CONFIG_HISAX_AMD7930 fi fi + bool ' HiSax debugging' CONFIG_HISAX_DEBUG + dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA + dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL fi endmenu diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/act2000/act2000_isa.c linux/drivers/isdn/act2000/act2000_isa.c --- v2.4.9/linux/drivers/isdn/act2000/act2000_isa.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/isdn/act2000/act2000_isa.c Sun Sep 9 10:43:02 2001 @@ -418,7 +418,7 @@ int act2000_isa_download(act2000_card * card, act2000_ddef * cb) { - int length; + unsigned int length; int ret; int l; int c; @@ -431,9 +431,8 @@ if (!act2000_isa_reset(card->port)) return -ENXIO; act2000_isa_delay(HZ / 2); - if ((ret = verify_area(VERIFY_READ, (void *) cb, sizeof(cblock)))) - return ret; - copy_from_user(&cblock, (char *) cb, sizeof(cblock)); + if(copy_from_user(&cblock, (char *) cb, sizeof(cblock))) + return -EFAULT; length = cblock.length; p = cblock.buffer; if ((ret = verify_area(VERIFY_READ, (void *) p, length))) diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/divert/divert_init.c linux/drivers/isdn/divert/divert_init.c --- v2.4.9/linux/drivers/isdn/divert/divert_init.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/divert/divert_init.c Fri Sep 14 14:39:59 2001 @@ -70,7 +70,7 @@ /* Module deinit code */ /**********************/ static void __exit divert_exit(void) -{ int flags; +{ long flags; int i; save_flags(flags); diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c --- v2.4.9/linux/drivers/isdn/divert/divert_procfs.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/isdn/divert/divert_procfs.c Fri Sep 14 14:39:59 2001 @@ -50,7 +50,7 @@ put_info_buffer(char *cp) { struct divert_info *ib; - int flags; + long flags; if (if_used <= 0) return; @@ -145,7 +145,7 @@ static int isdn_divert_open(struct inode *ino, struct file *filep) { - int flags; + long flags; lock_kernel(); save_flags(flags); @@ -168,7 +168,7 @@ isdn_divert_close(struct inode *ino, struct file *filep) { struct divert_info *inf; - int flags; + long flags; lock_kernel(); save_flags(flags); @@ -198,7 +198,8 @@ uint cmd, ulong arg) { divert_ioctl dioctl; - int i, flags; + int i; + long flags; divert_rule *rulep; char *cp; diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/divert/isdn_divert.c linux/drivers/isdn/divert/isdn_divert.c --- v2.4.9/linux/drivers/isdn/divert/isdn_divert.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/divert/isdn_divert.c Fri Sep 14 14:39:59 2001 @@ -67,7 +67,7 @@ /* timer callback function */ /***************************/ static void deflect_timer_expire(ulong arg) -{ int flags; +{ long flags; struct call_struc *cs = (struct call_struc *) arg; save_flags(flags); @@ -125,7 +125,8 @@ int cf_command(int drvid, int mode, u_char proc, char *msn, u_char service, char *fwd_nr, ulong *procid) -{ int retval,msnlen,flags; +{ long flags; + int retval,msnlen; int fwd_len; char *p,*ielenp,tmp[60]; struct call_struc *cs; @@ -220,7 +221,7 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) { struct call_struc *cs; isdn_ctrl ic; - int flags; + long flags; int i; if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */ @@ -291,7 +292,7 @@ /********************************/ int insertrule(int idx, divert_rule *newrule) { struct deflect_struc *ds,*ds1=NULL; - int flags; + long flags; if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc), GFP_KERNEL))) @@ -337,7 +338,7 @@ /***********************************/ int deleterule(int idx) { struct deflect_struc *ds,*ds1; - int flags; + long flags; if (idx < 0) { save_flags(flags); @@ -405,7 +406,7 @@ /*************************************************/ int isdn_divert_icall(isdn_ctrl *ic) { int retval = 0; - int flags; + long flags; struct call_struc *cs = NULL; struct deflect_struc *dv; char *p,*p1; @@ -557,7 +558,7 @@ void deleteprocs(void) { struct call_struc *cs, *cs1; - int flags; + long flags; save_flags(flags); cli(); @@ -714,7 +715,8 @@ /*********************************************/ int prot_stat_callback(isdn_ctrl *ic) { struct call_struc *cs, *cs1; - int i,flags; + int i; + long flags; cs = divert_head; /* start of list */ cs1 = NULL; @@ -805,7 +807,8 @@ /***************************/ int isdn_divert_stat_callback(isdn_ctrl *ic) { struct call_struc *cs, *cs1; - int flags, retval; + long flags; + int retval; retval = -1; cs = divert_head; /* start of list */ diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/eicon/Divas_mod.c linux/drivers/isdn/eicon/Divas_mod.c --- v2.4.9/linux/drivers/isdn/eicon/Divas_mod.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/eicon/Divas_mod.c Thu Sep 13 12:55:23 2001 @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include "adapter.h" #include "uxio.h" diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/eicon/idi.c linux/drivers/isdn/eicon/idi.c --- v2.4.9/linux/drivers/isdn/eicon/idi.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/eicon/idi.c Sun Sep 9 10:45:43 2001 @@ -431,7 +431,9 @@ i = this->XCurrent; X = PTR_X(a,this); while(iXNum && length<270) { - clength = MIN((word)(270-length),X[i].PLength-this->XOffset); + clength = (word)(270-length); + if (clength > X[i].PLength-this->XOffset) + clength = X[i].PLength-this->XOffset; a->ram_out_buffer(a, &ReqOut->XBuffer.P[length], PTR_P(a,this,&X[i].P[this->XOffset]), @@ -837,8 +839,9 @@ this->ROffset = 0; this->RCurrent++; } - clength = MIN(a->ram_inw(a, &RBuffer->length)-offset, - R[this->RCurrent].PLength-this->ROffset); + clength = a->ram_inw(a, &RBuffer->length)-offset; + if (clength > R[this->RCurrent].PLength-this->ROffset) + clength = R[this->RCurrent].PLength-this->ROffset; if(R[this->RCurrent].P) { a->ram_in_buffer(a, &RBuffer->P[offset], diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/eicon/kprintf.c linux/drivers/isdn/eicon/kprintf.c --- v2.4.9/linux/drivers/isdn/eicon/kprintf.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/isdn/eicon/kprintf.c Sun Sep 9 10:45:43 2001 @@ -30,8 +30,6 @@ #include "eicon.h" #include "sys.h" #include -#undef MAX -#undef MIN #include "divas.h" #include "divalog.h" diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/eicon/linio.c linux/drivers/isdn/eicon/linio.c --- v2.4.9/linux/drivers/isdn/eicon/linio.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/eicon/linio.c Fri Sep 14 14:39:59 2001 @@ -683,7 +683,7 @@ kfree(ptr); } -int UxCardLock(ux_diva_card_t *card) +long UxCardLock(ux_diva_card_t *card) { unsigned long flags; @@ -695,7 +695,7 @@ } -void UxCardUnlock(ux_diva_card_t *card, int ipl) +void UxCardUnlock(ux_diva_card_t *card, long ipl) { //spin_unlock_irqrestore(&diva_lock, ipl); diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/eicon/pc.h linux/drivers/isdn/eicon/pc.h --- v2.4.9/linux/drivers/isdn/eicon/pc.h Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/eicon/pc.h Sun Sep 9 10:45:43 2001 @@ -29,12 +29,6 @@ #define byte unsigned char #define word unsigned short #define dword unsigned long -#if !defined(MIN) -#define MIN(a,b) ((a)>(b) ? (b) : (a)) -#endif -#if !defined(MAX) -#define MAX(a,b) ((a)>(b) ? (a) : (b)) -#endif /*------------------------------------------------------------------*/ /* buffer definition */ diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/eicon/sys.h linux/drivers/isdn/eicon/sys.h --- v2.4.9/linux/drivers/isdn/eicon/sys.h Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/eicon/sys.h Sun Sep 9 10:45:43 2001 @@ -54,15 +54,6 @@ #define NULL ((void *) 0) #endif -/* MIN and MAX */ - -#if !defined(MIN) -#define MIN(a,b) ((a)>(b) ? (b) : (a)) -#endif -#if !defined(MAX) -#define MAX(a,b) ((a)>(b) ? (a) : (b)) -#endif - /* Return the dimension of an array */ #if !defined(DIM) @@ -85,6 +76,8 @@ /* void HwAssert(char *file, int line, char *condition); */ #include +#include + #define _PRINTK printk #define _PRINTF DivasPrintf diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/eicon/uxio.h linux/drivers/isdn/eicon/uxio.h --- v2.4.9/linux/drivers/isdn/eicon/uxio.h Mon Aug 27 12:41:41 2001 +++ linux/drivers/isdn/eicon/uxio.h Fri Sep 14 14:39:59 2001 @@ -75,8 +75,8 @@ * Lock and unlock access to a card */ -int UxCardLock(ux_diva_card_t *card); -void UxCardUnlock(ux_diva_card_t *card, int ipl); +long UxCardLock(ux_diva_card_t *card); +void UxCardUnlock(ux_diva_card_t *card, long ipl); /* * Set the mapping address for PCI cards diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/Makefile linux/drivers/isdn/hisax/Makefile --- v2.4.9/linux/drivers/isdn/hisax/Makefile Sun Aug 12 13:27:59 2001 +++ linux/drivers/isdn/hisax/Makefile Sun Sep 9 10:45:43 2001 @@ -2,20 +2,21 @@ # The target object and module list name. -O_TARGET := vmlinux-obj.o +O_TARGET := vmlinux-obj.o # Objects that export symbols. -export-objs := config.o +export-objs := config.o fsm.o # Multipart objects. -list-multi := hisax.o -hisax-objs := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \ - lmgr.o q931.o callc.o fsm.o cert.o +list-multi := hisax.o hisax_st5481.o +hisax-objs := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \ + lmgr.o q931.o callc.o fsm.o cert.o +hisax_st5481-objs := st5481_init.o st5481_usb.o st5481_d.o st5481_b.o \ + st5481_hdlc.o # Optional parts of multipart objects. - hisax-objs-$(CONFIG_HISAX_EURO) += l3dss1.o hisax-objs-$(CONFIG_HISAX_NI1) += l3ni1.o hisax-objs-$(CONFIG_HISAX_1TR6) += l3_1tr6.o @@ -27,7 +28,6 @@ hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o -hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o @@ -54,9 +54,10 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o +obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o -obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o +obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o +obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?) CFLAGS_cert.o := -DCERTIFICATION=$(CERT) @@ -67,3 +68,6 @@ hisax.o: $(hisax-objs) $(LD) -r -o $@ $(hisax-objs) + +hisax_st5481.o: $(hisax_st5481-objs) + $(LD) -r -o $@ $(hisax_st5481-objs) diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/callc.c linux/drivers/isdn/hisax/callc.c --- v2.4.9/linux/drivers/isdn/hisax/callc.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/isdn/hisax/callc.c Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.51.6.4 2001/06/09 15:14:17 kai Exp $ +/* $Id: callc.c,v 2.51.6.5 2001/08/23 19:44:23 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -20,12 +20,12 @@ #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) #endif /* MODULE */ -const char *lli_revision = "$Revision: 2.51.6.4 $"; +const char *lli_revision = "$Revision: 2.51.6.5 $"; extern struct IsdnCard cards[]; extern int nrcards; -extern void HiSax_mod_dec_use_count(void); -extern void HiSax_mod_inc_use_count(void); +extern void HiSax_mod_dec_use_count(struct IsdnCardState *cs); +extern void HiSax_mod_inc_use_count(struct IsdnCardState *cs); static int init_b_st(struct Channel *chanp, int incoming); static void release_b_st(struct Channel *chanp); @@ -1584,7 +1584,7 @@ } break; case (ISDN_CMD_LOCK): - HiSax_mod_inc_use_count(); + HiSax_mod_inc_use_count(csta); #ifdef MODULE if (csta->channel[0].debug & 0x400) HiSax_putstatus(csta, " LOCK ", "modcnt %lx", @@ -1592,7 +1592,7 @@ #endif /* MODULE */ break; case (ISDN_CMD_UNLOCK): - HiSax_mod_dec_use_count(); + HiSax_mod_dec_use_count(csta); #ifdef MODULE if (csta->channel[0].debug & 0x400) HiSax_putstatus(csta, " UNLOCK ", "modcnt %lx", @@ -1624,11 +1624,11 @@ break; case (3): for (i = 0; i < *(unsigned int *) ic->parm.num; i++) - HiSax_mod_dec_use_count(); + HiSax_mod_dec_use_count(NULL); break; case (4): for (i = 0; i < *(unsigned int *) ic->parm.num; i++) - HiSax_mod_inc_use_count(); + HiSax_mod_inc_use_count(NULL); break; case (5): /* set card in leased mode */ num = *(unsigned int *) ic->parm.num; @@ -1698,7 +1698,7 @@ #ifdef MODULE case (55): MOD_USE_COUNT = 0; - HiSax_mod_inc_use_count(); + HiSax_mod_inc_use_count(NULL); break; #endif /* MODULE */ case (11): @@ -1810,6 +1810,7 @@ cli(); nskb = skb_clone(skb, GFP_ATOMIC); if (nskb) { + nskb->truesize = nskb->len; if (!ack) nskb->pkt_type = PACKET_NOACK; if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I) diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c --- v2.4.9/linux/drivers/isdn/hisax/config.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/isdn/hisax/config.c Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: config.c,v 2.57.6.16 2001/07/13 09:01:00 kai Exp $ +/* $Id: config.c,v 2.57.6.18 2001/08/27 22:19:05 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -313,7 +313,8 @@ #define DEFAULT_PROTO_NAME "UNKNOWN" #endif #ifndef DEFAULT_CARD -#error "HiSax: No cards configured" +#define DEFAULT_CARD 0 +#define DEFAULT_CFG {0,0,0,0} #endif int hisax_init_pcmcia(void *, int *, struct IsdnCard *); @@ -423,16 +424,6 @@ certification_check(1); } -void HiSax_mod_dec_use_count(void) -{ - MOD_DEC_USE_COUNT; -} - -void HiSax_mod_inc_use_count(void) -{ - MOD_INC_USE_COUNT; -} - #ifndef MODULE #define MAX_ARG (HISAX_MAX_CARDS*5) static int __init HiSax_setup(char *line) @@ -840,8 +831,9 @@ if (csta->DC_Close != NULL) { csta->DC_Close(csta); } - csta->cardmsg(csta, CARD_RELEASE, NULL); - if (csta->dbusytimer.function != NULL) + if (csta->cardmsg) + csta->cardmsg(csta, CARD_RELEASE, NULL); + if (csta->dbusytimer.function != NULL) // FIXME? del_timer(&csta->dbusytimer); ll_unload(csta); } @@ -1137,6 +1129,9 @@ ret = setup_netjet_u(card); break; #endif + case ISDN_CTYPE_DYNAMIC: + ret = 2; + break; default: printk(KERN_WARNING "HiSax: Support for %s Card not selected\n", @@ -1165,7 +1160,17 @@ init_bcstate(cs, 0); init_bcstate(cs, 1); - ret = init_card(cs); + + /* init_card only handles interrupts which are not */ + /* used here for the loadable driver */ + switch (card->typ) { + case ISDN_CTYPE_DYNAMIC: + ret = 0; + break; + default: + ret = init_card(cs); + break; + } if (ret) { closecard(cardnr); ret = 0; @@ -1343,6 +1348,8 @@ #ifdef MODULE if (!type[0]) { /* We 'll register drivers later, but init basic functions */ + for (i = 0; i < HISAX_MAX_CARDS; i++) + cards[i].typ = 0; return 0; } #ifdef CONFIG_HISAX_ELSA @@ -1572,7 +1579,6 @@ { #ifdef MODULE int i; - int nzproto = 0; nrcards = 0; /* Initialize all structs, even though we only accept @@ -1584,14 +1590,12 @@ cards[i].typ = type[i]; if (protocol[i]) { cards[i].protocol = protocol[i]; - nzproto++; } } cards[0].para[0] = pcm_irq; cards[0].para[1] = (int) pcm_iob; cards[0].protocol = prot; cards[0].typ = ISDN_CTYPE_HFC_SP_PCMCIA; - nzproto = 1; if (!HiSax_id) HiSax_id = HiSaxID; @@ -1615,7 +1619,6 @@ { #ifdef MODULE int i; - int nzproto = 0; nrcards = 0; /* Initialize all structs, even though we only accept @@ -1627,14 +1630,12 @@ cards[i].typ = type[i]; if (protocol[i]) { cards[i].protocol = protocol[i]; - nzproto++; } } cards[0].para[0] = pcm_irq; cards[0].para[1] = (int) pcm_iob; cards[0].protocol = prot; cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; - nzproto = 1; if (!HiSax_id) HiSax_id = HiSaxID; @@ -1658,7 +1659,6 @@ { #ifdef MODULE int i; - int nzproto = 0; nrcards = 0; /* Initialize all structs, even though we only accept @@ -1670,14 +1670,12 @@ cards[i].typ = type[i]; if (protocol[i]) { cards[i].protocol = protocol[i]; - nzproto++; } } cards[0].para[0] = pcm_irq; cards[0].para[1] = (int) pcm_iob; cards[0].protocol = prot; cards[0].typ = ISDN_CTYPE_A1_PCMCIA; - nzproto = 1; if (!HiSax_id) HiSax_id = HiSaxID; @@ -1715,11 +1713,362 @@ return ret; } +#include "hisax_if.h" + +EXPORT_SYMBOL(hisax_register); +EXPORT_SYMBOL(hisax_unregister); + +static void hisax_d_l1l2(struct hisax_if *ifc, int pr, void *arg); +static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg); +static void hisax_d_l2l1(struct PStack *st, int pr, void *arg); +static void hisax_b_l2l1(struct PStack *st, int pr, void *arg); +static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg); +static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs); +static void hisax_bc_close(struct BCState *bcs); +static void hisax_bh(struct IsdnCardState *cs); +static void EChannel_proc_rcv(struct hisax_d_if *d_if); + +int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], + char *name, int protocol) +{ + int i, retval; + char id[20]; + struct IsdnCardState *cs; + + for (i = 0; i < HISAX_MAX_CARDS; i++) { + if (!cards[i].typ) + break; + } + + if (i >= HISAX_MAX_CARDS) + return -EBUSY; + + cards[i].typ = ISDN_CTYPE_DYNAMIC; + cards[i].protocol = protocol; + sprintf(id, "%s%d", name, i); + nrcards++; + retval = checkcard(i, id, 0); + if (retval == 0) { // yuck + cards[i].typ = 0; + nrcards--; + return retval; + } + cs = cards[i].cs; + hisax_d_if->cs = cs; + cs->hw.hisax_d_if = hisax_d_if; + cs->cardmsg = hisax_cardmsg; + cs->tqueue.routine = (void *) (void *) hisax_bh; + cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1; + for (i = 0; i < 2; i++) { + cs->bcs[i].BC_SetStack = hisax_bc_setstack; + cs->bcs[i].BC_Close = hisax_bc_close; + + b_if[i]->ifc.l1l2 = hisax_b_l1l2; + + hisax_d_if->b_if[i] = b_if[i]; + } + hisax_d_if->ifc.l1l2 = hisax_d_l1l2; + skb_queue_head_init(&hisax_d_if->erq); + clear_bit(0, &hisax_d_if->ph_state); + + return 0; +} + +void hisax_unregister(struct hisax_d_if *hisax_d_if) +{ + cards[hisax_d_if->cs->cardnr].typ = 0; + HiSax_closecard(hisax_d_if->cs->cardnr); + skb_queue_purge(&hisax_d_if->erq); +} + +#include "isdnl1.h" + +static void hisax_sched_event(struct IsdnCardState *cs, int event) +{ + cs->event |= 1 << event; + queue_task(&cs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +static void hisax_bh(struct IsdnCardState *cs) +{ + struct PStack *st; + int pr; + + if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) + DChannel_proc_rcv(cs); + if (test_and_clear_bit(E_RCVBUFREADY, &cs->event)) + EChannel_proc_rcv(cs->hw.hisax_d_if); + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { + if (test_bit(0, &cs->hw.hisax_d_if->ph_state)) + pr = PH_ACTIVATE | INDICATION; + else + pr = PH_DEACTIVATE | INDICATION; + for (st = cs->stlist; st; st = st->next) + st->l1.l1l2(st, pr, NULL); + + } +} + +static void hisax_b_sched_event(struct BCState *bcs, int event) +{ + bcs->event |= 1 << event; + queue_task(&bcs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg) +{ + struct hisax_if *ifc = (struct hisax_if *) d_if; + ifc->l2l1(ifc, pr, arg); +} + +static inline void B_L2L1(struct hisax_b_if *b_if, int pr, void *arg) +{ + struct hisax_if *ifc = (struct hisax_if *) b_if; + ifc->l2l1(ifc, pr, arg); +} + +static void hisax_d_l1l2(struct hisax_if *ifc, int pr, void *arg) +{ + struct hisax_d_if *d_if = (struct hisax_d_if *) ifc; + struct IsdnCardState *cs = d_if->cs; + struct PStack *st; + struct sk_buff *skb; + + switch (pr) { + case PH_ACTIVATE | INDICATION: + set_bit(0, &d_if->ph_state); + hisax_sched_event(cs, D_L1STATECHANGE); + break; + case PH_DEACTIVATE | INDICATION: + clear_bit(0, &d_if->ph_state); + hisax_sched_event(cs, D_L1STATECHANGE); + break; + case PH_DATA | INDICATION: + skb_queue_tail(&cs->rq, arg); + hisax_sched_event(cs, D_RCVBUFREADY); + break; + case PH_DATA | CONFIRM: + skb = skb_dequeue(&cs->sq); + if (skb) { + D_L2L1(d_if, PH_DATA | REQUEST, skb); + break; + } + clear_bit(FLG_L1_DBUSY, &cs->HW_Flags); + for (st = cs->stlist; st; st = st->next) { + if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) { + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + break; + } + } + break; + case PH_DATA_E | INDICATION: + skb_queue_tail(&d_if->erq, arg); + hisax_sched_event(cs, E_RCVBUFREADY); + break; + default: + printk("pr %#x\n", pr); + break; + } +} + +static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg) +{ + struct hisax_b_if *b_if = (struct hisax_b_if *) ifc; + struct BCState *bcs = b_if->bcs; + struct PStack *st = bcs->st; + struct sk_buff *skb; + + // FIXME use isdnl1? + switch (pr) { + case PH_ACTIVATE | INDICATION: + st->l1.l1l2(st, pr, NULL); + break; + case PH_DEACTIVATE | INDICATION: + st->l1.l1l2(st, pr, NULL); + bcs->hw.b_if = NULL; + break; + case PH_DATA | INDICATION: + skb_queue_tail(&bcs->rqueue, arg); + hisax_b_sched_event(bcs, B_RCVBUFREADY); + break; + case PH_DATA | CONFIRM: + bcs->tx_cnt -= (int) arg; + if (bcs->st->lli.l1writewakeup) + bcs->st->lli.l1writewakeup(bcs->st, (int) arg); + skb = skb_dequeue(&bcs->squeue); + if (skb) { + B_L2L1(b_if, PH_DATA | REQUEST, skb); + break; + } + clear_bit(BC_FLG_BUSY, &bcs->Flag); + if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) { + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } + break; + default: + printk("hisax_b_l1l2 pr %#x\n", pr); + break; + } +} + +static void hisax_d_l2l1(struct PStack *st, int pr, void *arg) +{ + struct IsdnCardState *cs = st->l1.hardware; + struct hisax_d_if *hisax_d_if = cs->hw.hisax_d_if; + struct sk_buff *skb = arg; + + switch (pr) { + case PH_DATA | REQUEST: + case PH_PULL | INDICATION: + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + Logl2Frame(cs, skb, "PH_DATA_REQ", 0); + // FIXME lock? + if (!test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + D_L2L1(hisax_d_if, PH_DATA | REQUEST, skb); + else + skb_queue_tail(&cs->sq, skb); + break; + case PH_PULL | REQUEST: + if (!test_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + else + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + default: + D_L2L1(hisax_d_if, pr, arg); + break; + } +} + +static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg) +{ + return 0; +} + +static void hisax_b_l2l1(struct PStack *st, int pr, void *arg) +{ + struct BCState *bcs = st->l1.bcs; + struct hisax_b_if *b_if = bcs->hw.b_if; + + switch (pr) { + case PH_ACTIVATE | REQUEST: + B_L2L1(b_if, pr, (void *) st->l1.mode); + break; + case PH_DATA | REQUEST: + case PH_PULL | INDICATION: + // FIXME lock? + if (!test_and_set_bit(BC_FLG_BUSY, &bcs->Flag)) { + B_L2L1(b_if, PH_DATA | REQUEST, arg); + } else { + skb_queue_tail(&bcs->squeue, arg); + } + break; + case PH_PULL | REQUEST: + if (!test_bit(BC_FLG_BUSY, &bcs->Flag)) + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + else + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + default: + B_L2L1(b_if, pr, arg); + break; + } +} + +static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs) +{ + struct IsdnCardState *cs = st->l1.hardware; + struct hisax_d_if *hisax_d_if = cs->hw.hisax_d_if; + + bcs->channel = st->l1.bc; + + bcs->hw.b_if = hisax_d_if->b_if[st->l1.bc]; + hisax_d_if->b_if[st->l1.bc]->bcs = bcs; + + st->l1.bcs = bcs; + st->l2.l2l1 = hisax_b_l2l1; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + return 0; +} + +static void hisax_bc_close(struct BCState *bcs) +{ + struct hisax_b_if *b_if = bcs->hw.b_if; + + if (b_if) + B_L2L1(b_if, PH_DEACTIVATE | REQUEST, NULL); +} + +static void EChannel_proc_rcv(struct hisax_d_if *d_if) +{ + struct IsdnCardState *cs = d_if->cs; + u_char *ptr; + struct sk_buff *skb; + + while ((skb = skb_dequeue(&d_if->erq)) != NULL) { + if (cs->debug & DEB_DLOG_HEX) { + ptr = cs->dlog; + if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) { + *ptr++ = 'E'; + *ptr++ = 'C'; + *ptr++ = 'H'; + *ptr++ = 'O'; + *ptr++ = ':'; + ptr += QuickHex(ptr, skb->data, skb->len); + ptr--; + *ptr++ = '\n'; + *ptr = 0; + HiSax_putstatus(cs, NULL, cs->dlog); + } else + HiSax_putstatus(cs, "LogEcho: ", + "warning Frame too big (%d)", + skb->len); + } + dev_kfree_skb_any(skb); + } +} + +void HiSax_mod_dec_use_count(struct IsdnCardState *cs) +{ + struct module *mod; + + if (cs && cs->cardmsg == hisax_cardmsg) { + mod = cs->hw.hisax_d_if->owner; + if (mod) + __MOD_DEC_USE_COUNT(mod); + } else { + MOD_DEC_USE_COUNT; + } +} + +void HiSax_mod_inc_use_count(struct IsdnCardState *cs) +{ + struct module *mod; + + if (cs && cs->cardmsg == hisax_cardmsg) { + mod = cs->hw.hisax_d_if->owner; + if (mod) + // hope we do win the race... + try_inc_mod_count(mod); + } else { + MOD_INC_USE_COUNT; + } +} + #include static struct pci_device_id hisax_pci_tbl[] __initdata = { #ifdef CONFIG_HISAX_FRITZPCI - {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID}, #endif #ifdef CONFIG_HISAX_DIEHLDIVA {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID}, diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/elsa_ser.c linux/drivers/isdn/hisax/elsa_ser.c --- v2.4.9/linux/drivers/isdn/hisax/elsa_ser.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/isdn/hisax/elsa_ser.c Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: elsa_ser.c,v 2.10.6.2 2001/06/09 15:14:17 kai Exp $ +/* $Id: elsa_ser.c,v 2.10.6.3 2001/08/17 12:34:26 kai Exp $ * * stuff for the serial modem on ELSA cards * @@ -14,10 +14,6 @@ #define RS_ISR_PASS_LIMIT 256 #define BASE_BAUD ( 1843200 / 16 ) -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - //#define SERIAL_DEBUG_OPEN 1 //#define SERIAL_DEBUG_INTR 1 //#define SERIAL_DEBUG_FLOW 1 @@ -257,7 +253,7 @@ write_modem(struct BCState *bcs) { int ret=0; struct IsdnCardState *cs = bcs->cs; - int count, len, fp, buflen; + int count, len, fp; long flags; if (!bcs->tx_skb) @@ -266,12 +262,14 @@ return 0; save_flags(flags); cli(); - buflen = MAX_MODEM_BUF - cs->hw.elsa.transcnt; - len = MIN(buflen, bcs->tx_skb->len); + len = bcs->tx_skb->len; + if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt) + len = MAX_MODEM_BUF - cs->hw.elsa.transcnt; fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp; fp &= (MAX_MODEM_BUF -1); - count = MIN(len, MAX_MODEM_BUF - fp); - if (count < len) { + count = len; + if (count > MAX_MODEM_BUF - fp) { + count = MAX_MODEM_BUF - fp; memcpy(cs->hw.elsa.transbuf + fp, bcs->tx_skb->data, count); skb_pull(bcs->tx_skb, count); cs->hw.elsa.transcnt += count; @@ -472,8 +470,9 @@ } fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp; fp &= (MAX_MODEM_BUF -1); - count = MIN(len, MAX_MODEM_BUF - fp); - if (count < len) { + count = len; + if (count > MAX_MODEM_BUF - fp) { + count = MAX_MODEM_BUF - fp; memcpy(cs->hw.elsa.transbuf + fp, msg, count); cs->hw.elsa.transcnt += count; msg += count; diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/fsm.c linux/drivers/isdn/hisax/fsm.c --- v2.4.9/linux/drivers/isdn/hisax/fsm.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/isdn/hisax/fsm.c Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: fsm.c,v 1.14.6.2 2001/05/26 15:19:57 kai Exp $ +/* $Id: fsm.c,v 1.14.6.3 2001/08/23 19:44:23 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -14,6 +14,14 @@ #include "hisax.h" #define FSM_TIMER_DEBUG 0 + +EXPORT_SYMBOL(FsmNew); +EXPORT_SYMBOL(FsmFree); +EXPORT_SYMBOL(FsmEvent); +EXPORT_SYMBOL(FsmChangeState); +EXPORT_SYMBOL(FsmInitTimer); +EXPORT_SYMBOL(FsmDelTimer); +EXPORT_SYMBOL(FsmRestartTimer); int __init FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount) diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/fsm.h linux/drivers/isdn/hisax/fsm.h --- v2.4.9/linux/drivers/isdn/hisax/fsm.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/fsm.h Sun Sep 9 10:45:43 2001 @@ -0,0 +1,48 @@ +#ifndef __FSM_H__ +#define __FSM_H__ + +#include + +struct FsmInst; + +typedef void (* FSMFNPTR)(struct FsmInst *, int, void *); + +struct Fsm { + FSMFNPTR *jumpmatrix; + int state_count, event_count; + char **strEvent, **strState; +}; + +struct FsmInst { + struct Fsm *fsm; + int state; + int debug; + void *userdata; + int userint; + void (*printdebug) (struct FsmInst *, char *, ...); +}; + +struct FsmNode { + int state, event; + void (*routine) (struct FsmInst *, int, void *); +}; + +struct FsmTimer { + struct FsmInst *fi; + struct timer_list tl; + int event; + void *arg; +}; + +int FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount); +void FsmFree(struct Fsm *fsm); +int FsmEvent(struct FsmInst *fi, int event, void *arg); +void FsmChangeState(struct FsmInst *fi, int newstate); +void FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft); +int FsmAddTimer(struct FsmTimer *ft, int millisec, int event, + void *arg, int where); +void FsmRestartTimer(struct FsmTimer *ft, int millisec, int event, + void *arg, int where); +void FsmDelTimer(struct FsmTimer *ft, int where); + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c --- v2.4.9/linux/drivers/isdn/hisax/hfc_pci.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/isdn/hisax/hfc_pci.c Fri Sep 14 14:39:59 2001 @@ -84,7 +84,7 @@ void release_io_hfcpci(struct IsdnCardState *cs) { - int flags; + long flags; save_flags(flags); cli(); @@ -299,7 +299,8 @@ u_char *ptr, *ptr1, new_f2; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; - int flags, total, maxlen, new_z2; + long flags; + int total, maxlen, new_z2; z_type *zp; save_flags(flags); @@ -633,7 +634,8 @@ hfcpci_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int flags, maxlen, fcnt; + long flags; + int maxlen, fcnt; int count, new_z1; bzfifo_type *bz; u_char *bdata; @@ -810,7 +812,7 @@ static int hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { - int flags; + long flags; int i = *(unsigned int *) ic->parm.num; if ((ic->arg == 98) && @@ -1160,7 +1162,7 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - int flags; + long flags; switch (pr) { case (PH_DATA | REQUEST): @@ -1314,7 +1316,8 @@ mode_hfcpci(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int flags, fifo2; + long flags; + int fifo2; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d", @@ -1548,7 +1551,7 @@ static void hfcpci_bh(struct IsdnCardState *cs) { - int flags; + long flags; /* struct PStack *stptr; */ if (!cs) diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/hfc_sx.c linux/drivers/isdn/hisax/hfc_sx.c --- v2.4.9/linux/drivers/isdn/hisax/hfc_sx.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/isdn/hisax/hfc_sx.c Fri Sep 14 14:39:59 2001 @@ -73,7 +73,7 @@ /******************************/ static inline void Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val) -{ register int flags; +{ long flags; save_flags(flags); cli(); @@ -84,8 +84,8 @@ static inline u_char Read_hfc(struct IsdnCardState *cs, u_char regnum) -{ register int flags; - register u_char ret; +{ long flags; + u_char ret; save_flags(flags); cli(); @@ -101,7 +101,7 @@ /**************************************************/ static void fifo_select(struct IsdnCardState *cs, u_char fifo) -{ int flags; +{ long flags; if (fifo == cs->hw.hfcsx.last_fifo) return; /* still valid */ @@ -123,7 +123,7 @@ /******************************************/ static void reset_fifo(struct IsdnCardState *cs, u_char fifo) -{ int flags; +{ long flags; save_flags(flags); cli(); @@ -337,7 +337,7 @@ void release_io_hfcsx(struct IsdnCardState *cs) { - int flags; + long flags; save_flags(flags); cli(); @@ -599,7 +599,7 @@ hfcsx_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int flags; + long flags; if (!bcs->tx_skb) return; @@ -670,7 +670,7 @@ static int hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { - int flags; + long flags; int i = *(unsigned int *) ic->parm.num; if ((ic->arg == 98) && @@ -729,7 +729,7 @@ static void receive_emsg(struct IsdnCardState *cs) { - int flags; + long flags; int count = 5; u_char *ptr; struct sk_buff *skb; @@ -961,7 +961,7 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - int flags; + long flags; switch (pr) { case (PH_DATA | REQUEST): @@ -1115,7 +1115,8 @@ mode_hfcsx(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int flags, fifo2; + long flags; + int fifo2; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HFCSX bchannel mode %d bchan %d/%d", @@ -1338,7 +1339,7 @@ static void hfcsx_bh(struct IsdnCardState *cs) { - int flags; + long flags; /* struct PStack *stptr; */ if (!cs) @@ -1478,7 +1479,7 @@ { struct IsdnCardState *cs = card->cs; char tmp[64]; - int flags; + long flags; strcpy(tmp, hfcsx_revision); printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp)); diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h --- v2.4.9/linux/drivers/isdn/hisax/hisax.h Wed Jul 25 17:10:20 2001 +++ linux/drivers/isdn/hisax/hisax.h Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: hisax.h,v 2.52.6.7 2001/07/18 16:02:15 kai Exp $ +/* $Id: hisax.h,v 2.52.6.8 2001/08/23 19:44:23 kai Exp $ * * Basic declarations, defines and prototypes * @@ -455,7 +455,6 @@ struct tq_struct tq_xmt; }; - #define BC_FLG_INIT 1 #define BC_FLG_ACTIV 2 #define BC_FLG_BUSY 3 @@ -512,6 +511,7 @@ struct tiger_hw tiger; struct amd7930_hw amd7930; struct w6692B_hw w6692; + struct hisax_b_if *b_if; } hw; }; @@ -897,6 +897,7 @@ struct bkm_hw ax; struct gazel_hw gazel; struct w6692_hw w6692; + struct hisax_d_if *hisax_d_if; } hw; int myid; isdn_if iif; @@ -991,7 +992,8 @@ #define ISDN_CTYPE_HFC_SX 37 #define ISDN_CTYPE_NETJET_U 38 #define ISDN_CTYPE_HFC_SP_PCMCIA 39 -#define ISDN_CTYPE_COUNT 39 +#define ISDN_CTYPE_DYNAMIC 40 +#define ISDN_CTYPE_COUNT 40 #ifdef ISDN_CHIP_ISAC diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/hisax_debug.h linux/drivers/isdn/hisax/hisax_debug.h --- v2.4.9/linux/drivers/isdn/hisax/hisax_debug.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/hisax_debug.h Sun Sep 9 10:45:43 2001 @@ -0,0 +1,80 @@ +/* + * Common debugging macros for use with the hisax driver + * + * Author Frode Isaksen + * Copyright 2001 by Frode Isaksen + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +/* + * How to use: + * + * Before including this file, you need to + * #define __debug_variable my_debug + * where my_debug is a variable in your code which + * determines the debug bitmask. + * + * If CONFIG_HISAX_DEBUG is not set, all macros evaluate to nothing + */ + +#ifndef __HISAX_DEBUG_H__ +#define __HISAX_DEBUG_H__ + +#ifdef CONFIG_HISAX_DEBUG + +#define DBG(level, format, arg...) do { \ +if (level & __debug_variable) \ +printk(KERN_DEBUG __FUNCTION__ ": " format "\n" , ## arg); \ +} while (0) + +#define DBG_PACKET(level,data,count) \ + if (level & __debug_variable) dump_packet(__FUNCTION__,data,count) + +#define DBG_SKB(level,skb) \ + if ((level & __debug_variable) && skb) dump_packet(__FUNCTION__,skb->data,skb->len) + + +static void __attribute__((unused)) +dump_packet(const char *name,const u_char *data,int pkt_len) +{ +#define DUMP_HDR_SIZE 20 +#define DUMP_TLR_SIZE 8 + if (pkt_len) { + int i,len1,len2; + + printk(KERN_DEBUG "%s: length=%d,data=",name,pkt_len); + + if (pkt_len > DUMP_HDR_SIZE+ DUMP_TLR_SIZE) { + len1 = DUMP_HDR_SIZE; + len2 = DUMP_TLR_SIZE; + } else { + len1 = pkt_len > DUMP_HDR_SIZE ? DUMP_HDR_SIZE : pkt_len; + len2 = 0; + } + for (i = 0; i < len1; ++i) { + printk ("%.2x", data[i]); + } + if (len2) { + printk (".."); + for (i = pkt_len-DUMP_TLR_SIZE; i < pkt_len; ++i) { + printk ("%.2x", data[i]); + } + } + printk ("\n"); + } +#undef DUMP_HDR_SIZE +#undef DUMP_TLR_SIZE +} + +#else + +#define DBG(level, format, arg...) do {} while (0) +#define DBG_PACKET(level,data,count) do {} while (0) +#define DBG_SKB(level,skb) do {} while (0) + +#endif + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/hisax_if.h linux/drivers/isdn/hisax/hisax_if.h --- v2.4.9/linux/drivers/isdn/hisax/hisax_if.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/hisax_if.h Sun Sep 9 10:45:43 2001 @@ -0,0 +1,54 @@ +#ifndef __HISAX_IF_H__ +#define __HISAX_IF_H__ + +#include + +#define REQUEST 0 +#define CONFIRM 1 +#define INDICATION 2 +#define RESPONSE 3 + +#define PH_ACTIVATE 0x0100 +#define PH_DEACTIVATE 0x0110 +#define PH_DATA 0x0120 +#define PH_PULL 0x0130 +#define PH_DATA_E 0x0140 + +#define L1_MODE_NULL 0 +#define L1_MODE_TRANS 1 +#define L1_MODE_HDLC 2 +#define L1_MODE_EXTRN 3 +#define L1_MODE_HDLC_56K 4 +#define L1_MODE_MODEM 7 +#define L1_MODE_V32 8 +#define L1_MODE_FAX 9 + +struct hisax_if { + void *priv; // private to driver + void (*l1l2)(struct hisax_if *, int pr, void *arg); + void (*l2l1)(struct hisax_if *, int pr, void *arg); +}; + +struct hisax_b_if { + struct hisax_if ifc; + + // private to hisax + struct BCState *bcs; +}; + +struct hisax_d_if { + struct hisax_if ifc; + + // private to hisax + struct module *owner; + struct IsdnCardState *cs; + struct hisax_b_if *b_if[2]; + struct sk_buff_head erq; + long ph_state; +}; + +int hisax_register(struct hisax_d_if *hisax_if, struct hisax_b_if *b_if[], + char *name, int protocol); +void hisax_unregister(struct hisax_d_if *hisax_if); + +#endif 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/hisax/isdnl1.c linux/drivers/isdn/hisax/isdnl1.c --- v2.4.9/linux/drivers/isdn/hisax/isdnl1.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/isdn/hisax/isdnl1.c Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.c,v 2.41.6.3 2001/05/26 15:19:57 kai Exp $ +/* $Id: isdnl1.c,v 2.41.6.4 2001/08/23 19:44:23 kai Exp $ * * isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards * based on the teles driver from Jan den Ouden @@ -15,7 +15,7 @@ * */ -const char *l1_revision = "$Revision: 2.41.6.3 $"; +const char *l1_revision = "$Revision: 2.41.6.4 $"; #define __NO_VERSION__ #include @@ -895,7 +895,8 @@ setstack_manager(st); st->l1.stlistp = &(cs->stlist); st->l2.l2l1 = dch_l2l1; - cs->setstack_d(st, cs); + if (cs->setstack_d) + cs->setstack_d(st, cs); } void diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/isdnl1.h linux/drivers/isdn/hisax/isdnl1.h --- v2.4.9/linux/drivers/isdn/hisax/isdnl1.h Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/isdnl1.h Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.h,v 2.9.6.1 2001/02/16 16:43:27 kai Exp $ +/* $Id: isdnl1.h,v 2.9.6.2 2001/08/23 19:44:23 kai Exp $ * * Layer 1 defines * @@ -14,6 +14,7 @@ #define D_RX_MON1 5 #define D_TX_MON0 6 #define D_TX_MON1 7 +#define E_RCVBUFREADY 8 #define B_RCVBUFREADY 0 #define B_XMTBUFREADY 1 diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/l3dss1.c linux/drivers/isdn/hisax/l3dss1.c --- v2.4.9/linux/drivers/isdn/hisax/l3dss1.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/l3dss1.c Fri Sep 14 14:39:59 2001 @@ -44,7 +44,8 @@ static unsigned char new_invoke_id(struct PStack *p) { unsigned char retval; - int flags,i; + long flags; + int i; i = 32; /* maximum search depth */ @@ -72,7 +73,7 @@ /* free a used invoke id */ /*************************/ static void free_invoke_id(struct PStack *p, unsigned char id) -{ int flags; +{ long flags; if (!id) return; /* 0 = invalid value */ diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/l3ni1.c linux/drivers/isdn/hisax/l3ni1.c --- v2.4.9/linux/drivers/isdn/hisax/l3ni1.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/l3ni1.c Fri Sep 14 14:39:59 2001 @@ -48,7 +48,8 @@ static unsigned char new_invoke_id(struct PStack *p) { unsigned char retval; - int flags,i; + long flags; + int i; i = 32; /* maximum search depth */ @@ -76,7 +77,7 @@ /* free a used invoke id */ /*************************/ static void free_invoke_id(struct PStack *p, unsigned char id) -{ int flags; +{ long flags; if (!id) return; /* 0 = invalid value */ diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/st5481.h linux/drivers/isdn/hisax/st5481.h --- v2.4.9/linux/drivers/isdn/hisax/st5481.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/st5481.h Sun Sep 9 10:45:43 2001 @@ -0,0 +1,533 @@ +/* + * Driver for ST5481 USB ISDN modem + * + * Author Frode Isaksen + * Copyright 2001 by Frode Isaksen + * 2001 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#ifndef _ST5481_H_ +#define _ST5481_H_ + +// USB IDs, the Product Id is in the range 0x4810-0x481F + +#define ST_VENDOR_ID 0x0483 +#define ST5481_PRODUCT_ID 0x4810 +#define ST5481_PRODUCT_ID_MASK 0xFFF0 + +// ST5481 endpoints when using alternative setting 3 (2B+D). +// To get the endpoint address, OR with 0x80 for IN endpoints. + +#define EP_CTRL 0x00U /* Control endpoint */ +#define EP_INT 0x01U /* Interrupt endpoint */ +#define EP_B1_OUT 0x02U /* B1 channel out */ +#define EP_B1_IN 0x03U /* B1 channel in */ +#define EP_B2_OUT 0x04U /* B2 channel out */ +#define EP_B2_IN 0x05U /* B2 channel in */ +#define EP_D_OUT 0x06U /* D channel out */ +#define EP_D_IN 0x07U /* D channel in */ + +// Number of isochronous packets. With 20 packets we get +// 50 interrupts/sec for each endpoint. + +#define NUM_ISO_PACKETS_D 20 +#define NUM_ISO_PACKETS_B 20 + +// Size of each isochronous packet. +// In outgoing direction we need to match ISDN data rates: +// D: 2 bytes / msec -> 16 kbit / s +// B: 16 bytes / msec -> 64 kbit / s +#define SIZE_ISO_PACKETS_D_IN 16 +#define SIZE_ISO_PACKETS_D_OUT 2 +#define SIZE_ISO_PACKETS_B_IN 32 +#define SIZE_ISO_PACKETS_B_OUT 8 + +// If we overrun/underrun, we send one packet with +/- 2 bytes +#define B_FLOW_ADJUST 2 + +// Registers that are written using vendor specific device request +// on endpoint 0. + +#define LBA 0x02 /* S loopback */ +#define SET_DEFAULT 0x06 /* Soft reset */ +#define LBB 0x1D /* S maintenance loopback */ +#define STT 0x1e /* S force transmission signals */ +#define SDA_MIN 0x20 /* SDA-sin minimal value */ +#define SDA_MAX 0x21 /* SDA-sin maximal value */ +#define SDELAY_VALUE 0x22 /* Delay between Tx and Rx clock */ +#define IN_D_COUNTER 0x36 /* D receive channel fifo counter */ +#define OUT_D_COUNTER 0x37 /* D transmit channel fifo counter */ +#define IN_B1_COUNTER 0x38 /* B1 receive channel fifo counter */ +#define OUT_B1_COUNTER 0x39 /* B1 transmit channel fifo counter */ +#define IN_B2_COUNTER 0x3a /* B2 receive channel fifo counter */ +#define OUT_B2_COUNTER 0x3b /* B2 transmit channel fifo counter */ +#define FFCTRL_IN_D 0x3C /* D receive channel fifo threshold low */ +#define FFCTRH_IN_D 0x3D /* D receive channel fifo threshold high */ +#define FFCTRL_OUT_D 0x3E /* D transmit channel fifo threshold low */ +#define FFCTRH_OUT_D 0x3F /* D transmit channel fifo threshold high */ +#define FFCTRL_IN_B1 0x40 /* B1 receive channel fifo threshold low */ +#define FFCTRH_IN_B1 0x41 /* B1 receive channel fifo threshold high */ +#define FFCTRL_OUT_B1 0x42 /* B1 transmit channel fifo threshold low */ +#define FFCTRH_OUT_B1 0x43 /* B1 transmit channel fifo threshold high */ +#define FFCTRL_IN_B2 0x44 /* B2 receive channel fifo threshold low */ +#define FFCTRH_IN_B2 0x45 /* B2 receive channel fifo threshold high */ +#define FFCTRL_OUT_B2 0x46 /* B2 transmit channel fifo threshold low */ +#define FFCTRH_OUT_B2 0x47 /* B2 transmit channel fifo threshold high */ +#define MPMSK 0x4A /* Multi purpose interrupt MASK register */ +#define FFMSK_D 0x4c /* D fifo interrupt MASK register */ +#define FFMSK_B1 0x4e /* B1 fifo interrupt MASK register */ +#define FFMSK_B2 0x50 /* B2 fifo interrupt MASK register */ +#define GPIO_DIR 0x52 /* GPIO pins direction registers */ +#define GPIO_OUT 0x53 /* GPIO pins output register */ +#define GPIO_IN 0x54 /* GPIO pins input register */ +#define TXCI 0x56 /* CI command to be transmitted */ + + +// Format of the interrupt packet received on endpoint 1: +// +// +--------+--------+--------+--------+--------+--------+ +// !MPINT !FFINT_D !FFINT_B1!FFINT_B2!CCIST !GPIO_INT! +// +--------+--------+--------+--------+--------+--------+ + +// Offsets in the interrupt packet + +#define MPINT 0 +#define FFINT_D 1 +#define FFINT_B1 2 +#define FFINT_B2 3 +#define CCIST 4 +#define GPIO_INT 5 +#define INT_PKT_SIZE 6 + +// MPINT +#define LSD_INT 0x80 /* S line activity detected */ +#define RXCI_INT 0x40 /* Indicate primitive arrived */ +#define DEN_INT 0x20 /* Signal enabling data out of D Tx fifo */ +#define DCOLL_INT 0x10 /* D channel collision */ +#define AMIVN_INT 0x04 /* AMI violation number reached 2 */ +#define INFOI_INT 0x04 /* INFOi changed */ +#define DRXON_INT 0x02 /* Reception channel active */ +#define GPCHG_INT 0x01 /* GPIO pin value changed */ + +// FFINT_x +#define IN_OVERRUN 0x80 /* In fifo overrun */ +#define OUT_UNDERRUN 0x40 /* Out fifo underrun */ +#define IN_UP 0x20 /* In fifo thresholdh up-crossed */ +#define IN_DOWN 0x10 /* In fifo thresholdl down-crossed */ +#define OUT_UP 0x08 /* Out fifo thresholdh up-crossed */ +#define OUT_DOWN 0x04 /* Out fifo thresholdl down-crossed */ +#define IN_COUNTER_ZEROED 0x02 /* In down-counter reached 0 */ +#define OUT_COUNTER_ZEROED 0x01 /* Out down-counter reached 0 */ + +#define ANY_REC_INT (IN_OVERRUN+IN_UP+IN_DOWN+IN_COUNTER_ZEROED) +#define ANY_XMIT_INT (OUT_UNDERRUN+OUT_UP+OUT_DOWN+OUT_COUNTER_ZEROED) + + +// Level 1 commands that are sent using the TXCI device request +#define ST5481_CMD_DR 0x0 /* Deactivation Request */ +#define ST5481_CMD_RES 0x1 /* state machine RESet */ +#define ST5481_CMD_TM1 0x2 /* Test Mode 1 */ +#define ST5481_CMD_TM2 0x3 /* Test Mode 2 */ +#define ST5481_CMD_PUP 0x7 /* Power UP */ +#define ST5481_CMD_AR8 0x8 /* Activation Request class 1 */ +#define ST5481_CMD_AR10 0x9 /* Activation Request class 2 */ +#define ST5481_CMD_ARL 0xA /* Activation Request Loopback */ +#define ST5481_CMD_PDN 0xF /* Power DoWn */ + +// Turn on/off the LEDs using the GPIO device request. +// To use the B LEDs, number_of_leds must be set to 4 +#define B1_LED 0x10U +#define B2_LED 0x20U +#define GREEN_LED 0x40U +#define RED_LED 0x80U + +// D channel out states +enum { + ST_DOUT_NONE, + + ST_DOUT_SHORT_INIT, + ST_DOUT_SHORT_WAIT_DEN, + + ST_DOUT_LONG_INIT, + ST_DOUT_LONG_WAIT_DEN, + ST_DOUT_NORMAL, + + ST_DOUT_WAIT_FOR_UNDERRUN, + ST_DOUT_WAIT_FOR_NOT_BUSY, + ST_DOUT_WAIT_FOR_STOP, + ST_DOUT_WAIT_FOR_RESET, +}; + +#define DOUT_STATE_COUNT (ST_DOUT_WAIT_FOR_RESET + 1) + +// D channel out events +enum { + EV_DOUT_START_XMIT, + EV_DOUT_COMPLETE, + EV_DOUT_DEN, + EV_DOUT_RESETED, + EV_DOUT_STOPPED, + EV_DOUT_COLL, + EV_DOUT_UNDERRUN, +}; + +#define DOUT_EVENT_COUNT (EV_DOUT_UNDERRUN + 1) + +// ---------------------------------------------------------------------- + +enum { + ST_L1_F3, + ST_L1_F4, + ST_L1_F6, + ST_L1_F7, + ST_L1_F8, +}; + +#define L1_STATE_COUNT (ST_L1_F8+1) + +// The first 16 entries match the Level 1 indications that +// are found at offset 4 (CCIST) in the interrupt packet + +enum { + EV_IND_DP, // 0000 Deactivation Pending + EV_IND_1, // 0001 + EV_IND_2, // 0010 + EV_IND_3, // 0011 + EV_IND_RSY, // 0100 ReSYnchronizing + EV_IND_5, // 0101 + EV_IND_6, // 0110 + EV_IND_7, // 0111 + EV_IND_AP, // 1000 Activation Pending + EV_IND_9, // 1001 + EV_IND_10, // 1010 + EV_IND_11, // 1011 + EV_IND_AI8, // 1100 Activation Indication class 8 + EV_IND_AI10,// 1101 Activation Indication class 10 + EV_IND_AIL, // 1110 Activation Indication Loopback + EV_IND_DI, // 1111 Deactivation Indication + EV_PH_ACTIVATE_REQ, + EV_PH_DEACTIVATE_REQ, + EV_TIMER3, +}; + +#define L1_EVENT_COUNT (EV_TIMER3 + 1) + +#define ERR(format, arg...) \ +printk(KERN_ERR __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg) + +#define WARN(format, arg...) \ +printk(KERN_WARNING __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg) + +#define INFO(format, arg...) \ +printk(KERN_INFO __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg) + +#include "st5481_hdlc.h" +#include "fsm.h" +#include "hisax_if.h" +#include + +/* ====================================================================== + * FIFO handling + */ + +/* Generic FIFO structure */ +struct fifo { + u_char r,w,count,size; + spinlock_t lock; +}; + +/* + * Init an FIFO + */ +static inline void fifo_init(struct fifo *fifo, int size) +{ + fifo->r = fifo->w = fifo->count = 0; + fifo->size = size; + spin_lock_init(&fifo->lock); +} + +/* + * Add an entry to the FIFO + */ +static inline int fifo_add(struct fifo *fifo) +{ + unsigned long flags; + int index; + + if (!fifo) { + return -1; + } + + spin_lock_irqsave(&fifo->lock, flags); + if (fifo->count == fifo->size) { + // FIFO full + index = -1; + } else { + // Return index where to get the next data to add to the FIFO + index = fifo->w++ & (fifo->size-1); + fifo->count++; + } + spin_unlock_irqrestore(&fifo->lock, flags); + return index; +} + +/* + * Remove an entry from the FIFO with the index returned. + */ +static inline int fifo_remove(struct fifo *fifo) +{ + unsigned long flags; + int index; + + if (!fifo) { + return -1; + } + + spin_lock_irqsave(&fifo->lock, flags); + if (!fifo->count) { + // FIFO empty + index = -1; + } else { + // Return index where to get the next data from the FIFO + index = fifo->r++ & (fifo->size-1); + fifo->count--; + } + spin_unlock_irqrestore(&fifo->lock, flags); + + return index; +} + +/* ====================================================================== + * control pipe + */ +typedef void (*ctrl_complete_t)(void *); + +typedef struct ctrl_msg { + devrequest dr; + ctrl_complete_t complete; + void *context; +} ctrl_msg; + +/* FIFO of ctrl messages waiting to be sent */ +#define MAX_EP0_MSG 16 +struct ctrl_msg_fifo { + struct fifo f; + struct ctrl_msg data[MAX_EP0_MSG]; +}; + +#define MAX_DFRAME_LEN_L1 300 +#define HSCX_BUFMAX 4096 + +struct st5481_ctrl { + struct ctrl_msg_fifo msg_fifo; + unsigned long busy; + struct urb *urb; +}; + +struct st5481_intr { + // struct evt_fifo evt_fifo; + struct urb *urb; +}; + +struct st5481_d_out { + struct hdlc_vars hdlc_state; + struct urb *urb[2]; /* double buffering */ + unsigned long busy; + struct sk_buff *tx_skb; + struct FsmInst fsm; +}; + +struct st5481_b_out { + struct hdlc_vars hdlc_state; + struct urb *urb[2]; /* double buffering */ + u_char flow_event; + u_long busy; + struct sk_buff *tx_skb; +}; + +struct st5481_in { + struct hdlc_vars hdlc_state; + struct urb *urb[2]; /* double buffering */ + int mode; + int bufsize; + unsigned int num_packets; + unsigned int packet_size; + unsigned char ep, counter; + unsigned char *rcvbuf; + struct st5481_adapter *adapter; + struct hisax_if *hisax_if; +}; + +int st5481_setup_in(struct st5481_in *in); +void st5481_release_in(struct st5481_in *in); +void st5481_in_mode(struct st5481_in *in, int mode); + +struct st5481_bcs { + struct hisax_b_if b_if; + struct st5481_adapter *adapter; + struct st5481_in b_in; + struct st5481_b_out b_out; + int channel; + int mode; +}; + +struct st5481_adapter { + struct list_head list; + int number_of_leds; + struct usb_device *usb_dev; + struct hisax_d_if hisax_d_if; + + struct st5481_ctrl ctrl; + struct st5481_intr intr; + struct st5481_in d_in; + struct st5481_d_out d_out; + + unsigned char leds; + unsigned int led_counter; + + unsigned long event; + + struct FsmInst l1m; + struct FsmTimer timer; + + struct st5481_bcs bcs[2]; +}; + +#define TIMER3_VALUE 7000 + +/* ====================================================================== + * + */ + +/* + * Submit an URB with error reporting. This is a macro so + * the __FUNCTION__ returns the caller function name. + */ +#define SUBMIT_URB(urb) \ +({ \ + int status; \ + if ((status = usb_submit_urb(urb)) < 0) { \ + WARN("usb_submit_urb failed,status=%d", status); \ + } \ + status; \ +}) + +/* + * USB double buffering, return the URB index (0 or 1). + */ +static inline int get_buf_nr(struct urb *urbs[], struct urb *urb) +{ + return (urbs[0]==urb ? 0 : 1); +} + +/* ---------------------------------------------------------------------- */ + +/* B Channel */ + +int st5481_setup_b(struct st5481_bcs *bcs); +void st5481_release_b(struct st5481_bcs *bcs); +void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg); + +/* D Channel */ + +int st5481_setup_d(struct st5481_adapter *adapter); +void st5481_release_d(struct st5481_adapter *adapter); +void st5481_b_l2l1(struct hisax_if *b_if, int pr, void *arg); +int st5481_d_init(void); +void st5481_d_exit(void); + +/* USB */ +void st5481_ph_command(struct st5481_adapter *adapter, unsigned int command); +int st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, + unsigned int pipe, int num_packets, + int packet_size, int buf_size, + usb_complete_t complete, void *context); +void st5481_release_isocpipes(struct urb* urb[2]); + +int st5481_isoc_flatten(struct urb *urb); +void st5481_usb_pipe_reset(struct st5481_adapter *adapter, + u_char pipe, ctrl_complete_t complete, void *context); +void st5481_usb_ctrl_msg(struct st5481_adapter *adapter, + u8 request, u8 requesttype, u16 value, u16 index, + ctrl_complete_t complete, void *context); +void st5481_usb_device_ctrl_msg(struct st5481_adapter *adapter, + u8 request, u16 value, + ctrl_complete_t complete, void *context); +int st5481_setup_usb(struct st5481_adapter *adapter); +void st5481_release_usb(struct st5481_adapter *adapter); +void st5481_start(struct st5481_adapter *adapter); +void st5481_stop(struct st5481_adapter *adapter); + +// ---------------------------------------------------------------------- +// debugging macros + +#define __debug_variable st5481_debug +#include "hisax_debug.h" + +#ifdef CONFIG_HISAX_DEBUG + +extern int st5481_debug; + +#define DBG_ISO_PACKET(level,urb) \ + if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb) + +static void __attribute__((unused)) +dump_iso_packet(const char *name,urb_t *urb) +{ + int i,j; + int len,ofs; + u_char *data; + + printk(KERN_DEBUG "%s: packets=%d,errors=%d\n", + name,urb->number_of_packets,urb->error_count); + for (i = 0; i < urb->number_of_packets; ++i) { + if (urb->pipe & USB_DIR_IN) { + len = urb->iso_frame_desc[i].actual_length; + } else { + len = urb->iso_frame_desc[i].length; + } + ofs = urb->iso_frame_desc[i].offset; + printk(KERN_DEBUG "len=%.2d,ofs=%.3d ",len,ofs); + if (len) { + data = urb->transfer_buffer+ofs; + for (j=0; j < len; j++) { + printk ("%.2x", data[j]); + } + } + printk("\n"); + } +} + +static inline const char *ST5481_CMD_string(int evt) +{ + static char s[16]; + + switch (evt) { + case ST5481_CMD_DR: return "DR"; + case ST5481_CMD_RES: return "RES"; + case ST5481_CMD_TM1: return "TM1"; + case ST5481_CMD_TM2: return "TM2"; + case ST5481_CMD_PUP: return "PUP"; + case ST5481_CMD_AR8: return "AR8"; + case ST5481_CMD_AR10: return "AR10"; + case ST5481_CMD_ARL: return "ARL"; + case ST5481_CMD_PDN: return "PDN"; + }; + + sprintf(s,"0x%x",evt); + return s; +} + +#else + +#define DBG_ISO_PACKET(level,urb) do {} while (0) + +#endif + + + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/st5481_b.c linux/drivers/isdn/hisax/st5481_b.c --- v2.4.9/linux/drivers/isdn/hisax/st5481_b.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/st5481_b.c Sun Sep 9 10:45:43 2001 @@ -0,0 +1,367 @@ +/* + * Driver for ST5481 USB ISDN modem + * + * Author Frode Isaksen + * Copyright 2001 by Frode Isaksen + * 2001 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#include +#include +#include +#include +#include +#include +#include "st5481.h" + +static inline void B_L1L2(struct st5481_bcs *bcs, int pr, void *arg) +{ + struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if; + + ifc->l1l2(ifc, pr, arg); +} + +/* + * Encode and transmit next frame. + */ +static void usb_b_out(struct st5481_bcs *bcs,int buf_nr) +{ + struct st5481_b_out *b_out = &bcs->b_out; + struct st5481_adapter *adapter = bcs->adapter; + struct urb *urb; + unsigned int packet_size,offset; + int len,buf_size,bytes_sent; + int i; + struct sk_buff *skb; + + if (test_and_set_bit(buf_nr, &b_out->busy)) { + DBG(4,"ep %d urb %d busy",(bcs->channel+1)*2,buf_nr); + return; + } + urb = b_out->urb[buf_nr]; + + // Adjust isoc buffer size according to flow state + if(b_out->flow_event & (OUT_DOWN | OUT_UNDERRUN)) { + buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT + B_FLOW_ADJUST; + packet_size = SIZE_ISO_PACKETS_B_OUT + B_FLOW_ADJUST; + DBG(4,"B%d,adjust flow,add %d bytes",bcs->channel+1,B_FLOW_ADJUST); + } else if(b_out->flow_event & OUT_UP){ + buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT - B_FLOW_ADJUST; + packet_size = SIZE_ISO_PACKETS_B_OUT - B_FLOW_ADJUST; + DBG(4,"B%d,adjust flow,remove %d bytes",bcs->channel+1,B_FLOW_ADJUST); + } else { + buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT; + packet_size = 8; + } + b_out->flow_event = 0; + + len = 0; + while (len < buf_size) { + if ((skb = b_out->tx_skb)) { + DBG_SKB(0x100, skb); + DBG(4,"B%d,len=%d",bcs->channel+1,skb->len); + + if (bcs->mode == L1_MODE_TRANS) { + bytes_sent = buf_size - len; + if (skb->len < bytes_sent) + bytes_sent = skb->len; + + memcpy(urb->transfer_buffer+len, skb->data, bytes_sent); + + len += bytes_sent; + } else { + len += hdlc_encode(&b_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer+len, buf_size-len); + } + + skb_pull(skb, bytes_sent); + + if (!skb->len) { + // Frame sent + b_out->tx_skb = NULL; + B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize); + dev_kfree_skb_any(skb); + +/* if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */ +/* st5481B_sched_event(bcs, B_XMTBUFREADY); */ +/* } */ + } + } else { + if (bcs->mode == L1_MODE_TRANS) { + memset(urb->transfer_buffer+len, 0xff, buf_size-len); + len = buf_size; + } else { + // Send flags + len += hdlc_encode(&b_out->hdlc_state, + NULL, 0, &bytes_sent, + urb->transfer_buffer+len, buf_size-len); + } + } + } + + // Prepare the URB + for (i = 0, offset = 0; offset < len; i++) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = packet_size; + offset += packet_size; + packet_size = SIZE_ISO_PACKETS_B_OUT; + } + urb->transfer_buffer_length = len; + urb->number_of_packets = i; + urb->dev = adapter->usb_dev; + + DBG_ISO_PACKET(0x200,urb); + + SUBMIT_URB(urb); +} + +/* + * Start transfering (flags or data) on the B channel, since + * FIFO counters has been set to a non-zero value. + */ +static void st5481B_start_xfer(void *context) +{ + struct st5481_bcs *bcs = context; + + DBG(4,"B%d",bcs->channel+1); + + // Start transmitting (flags or data) on B channel + + usb_b_out(bcs,0); + usb_b_out(bcs,1); +} + +/* + * If the adapter has only 2 LEDs, the green + * LED will blink with a rate depending + * on the number of channels opened. + */ +static void led_blink(struct st5481_adapter *adapter) +{ + u_char leds = adapter->leds; + + // 50 frames/sec for each channel + if (++adapter->led_counter % 50) { + return; + } + + if (adapter->led_counter % 100) { + leds |= GREEN_LED; + } else { + leds &= ~GREEN_LED; + } + + st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, leds, NULL, NULL); +} + +static void usb_b_out_complete(struct urb *urb) +{ + struct st5481_bcs *bcs = urb->context; + struct st5481_b_out *b_out = &bcs->b_out; + struct st5481_adapter *adapter = bcs->adapter; + int buf_nr; + + buf_nr = get_buf_nr(b_out->urb, urb); + test_and_clear_bit(buf_nr, &b_out->busy); + + if (urb->status < 0) { + if (urb->status != USB_ST_URB_KILLED) { + WARN("urb status %d",urb->status); + if (b_out->busy == 0) { + st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); + } + } else { + DBG(1,"urb killed"); + return; // Give up + } + } + + usb_b_out(bcs,buf_nr); + + if (adapter->number_of_leds == 2) + led_blink(adapter); +} + +/* + * Start or stop the transfer on the B channel. + */ +static void st5481B_mode(struct st5481_bcs *bcs, int mode) +{ + struct st5481_b_out *b_out = &bcs->b_out; + struct st5481_adapter *adapter = bcs->adapter; + + DBG(4,"B%d,mode=%d", bcs->channel + 1, mode); + + if (bcs->mode == mode) + return; + + bcs->mode = mode; + + // Cancel all USB transfers on this B channel + usb_unlink_urb(b_out->urb[0]); + usb_unlink_urb(b_out->urb[1]); + b_out->busy = 0; + + st5481_in_mode(&bcs->b_in, mode); + if (bcs->mode != L1_MODE_NULL) { + // Open the B channel + if (bcs->mode != L1_MODE_TRANS) { + hdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K); + } + st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL); + + // Enable B channel interrupts + st5481_usb_device_ctrl_msg(adapter, FFMSK_B1+(bcs->channel*2), + OUT_UP+OUT_DOWN+OUT_UNDERRUN, NULL, NULL); + + // Enable B channel FIFOs + st5481_usb_device_ctrl_msg(adapter, OUT_B1_COUNTER+(bcs->channel*2), 32, st5481B_start_xfer, bcs); + if (adapter->number_of_leds == 4) { + if (bcs->channel == 0) { + adapter->leds |= B1_LED; + } else { + adapter->leds |= B2_LED; + } + } + } else { + // Disble B channel interrupts + st5481_usb_device_ctrl_msg(adapter, FFMSK_B1+(bcs->channel*2), 0, NULL, NULL); + + // Disable B channel FIFOs + st5481_usb_device_ctrl_msg(adapter, OUT_B1_COUNTER+(bcs->channel*2), 0, NULL, NULL); + + if (adapter->number_of_leds == 4) { + if (bcs->channel == 0) { + adapter->leds &= ~B1_LED; + } else { + adapter->leds &= ~B2_LED; + } + } else { + st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL); + } + if (b_out->tx_skb) { + dev_kfree_skb_any(b_out->tx_skb); + b_out->tx_skb = NULL; + } + + } +} + +static int __devinit st5481_setup_b_out(struct st5481_bcs *bcs) +{ + struct usb_device *dev = bcs->adapter->usb_dev; + struct usb_interface_descriptor *altsetting; + struct usb_endpoint_descriptor *endpoint; + struct st5481_b_out *b_out = &bcs->b_out; + + DBG(4,""); + + altsetting = &(dev->config->interface[0].altsetting[3]); + + // Allocate URBs and buffers for the B channel out + endpoint = &altsetting->endpoint[EP_B1_OUT - 1 + bcs->channel * 2]; + + DBG(4,"endpoint address=%02x,packet size=%d", + endpoint->bEndpointAddress,endpoint->wMaxPacketSize); + + // Allocate memory for 8000bytes/sec + extra bytes if underrun + return st5481_setup_isocpipes(b_out->urb, dev, + usb_sndisocpipe(dev, endpoint->bEndpointAddress), + NUM_ISO_PACKETS_B, SIZE_ISO_PACKETS_B_OUT, + NUM_ISO_PACKETS_B * SIZE_ISO_PACKETS_B_OUT + B_FLOW_ADJUST, + usb_b_out_complete, bcs); +} + +static void __devexit st5481_release_b_out(struct st5481_bcs *bcs) +{ + struct st5481_b_out *b_out = &bcs->b_out; + + DBG(4,""); + + st5481_release_isocpipes(b_out->urb); +} + +int __devinit st5481_setup_b(struct st5481_bcs *bcs) +{ + int retval; + + DBG(4,""); + + retval = st5481_setup_b_out(bcs); + if (retval) + goto err; + bcs->b_in.bufsize = HSCX_BUFMAX; + bcs->b_in.num_packets = NUM_ISO_PACKETS_B; + bcs->b_in.packet_size = SIZE_ISO_PACKETS_B_IN; + bcs->b_in.ep = (bcs->channel ? EP_B2_IN : EP_B1_IN) | USB_DIR_IN; + bcs->b_in.counter = bcs->channel ? IN_B2_COUNTER : IN_B1_COUNTER; + bcs->b_in.adapter = bcs->adapter; + bcs->b_in.hisax_if = &bcs->b_if.ifc; + retval = st5481_setup_in(&bcs->b_in); + if (retval) + goto err_b_out; + + + return 0; + + err_b_out: + st5481_release_b_out(bcs); + err: + return retval; +} + +/* + * Release buffers and URBs for the B channels + */ +void __devexit st5481_release_b(struct st5481_bcs *bcs) +{ + DBG(4,""); + + st5481_release_in(&bcs->b_in); + st5481_release_b_out(bcs); +} + +/* + * st5481_b_l2l1 is the entry point for upper layer routines that want to + * transmit on the B channel. PH_DATA | REQUEST is a normal packet that + * we either start transmitting (if idle) or queue (if busy). + * PH_PULL | REQUEST can be called to request a callback message + * (PH_PULL | CONFIRM) + * once the link is idle. After a "pull" callback, the upper layer + * routines can use PH_PULL | INDICATION to send data. + */ +void st5481_b_l2l1(struct hisax_if *ifc, int pr, void *arg) +{ + struct st5481_bcs *bcs = ifc->priv; + struct sk_buff *skb = arg; + int mode; + + DBG(4, ""); + + switch (pr) { + case PH_DATA | REQUEST: + if (bcs->b_out.tx_skb) + BUG(); + + bcs->b_out.tx_skb = skb; + break; + case PH_ACTIVATE | REQUEST: + mode = (int) arg; + DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode); + st5481B_mode(bcs, mode); + B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL); + break; + case PH_DEACTIVATE | REQUEST: + DBG(4,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1); + st5481B_mode(bcs, L1_MODE_NULL); + B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL); + break; + default: + WARN("pr %#x\n", pr); + } +} diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/st5481_d.c linux/drivers/isdn/hisax/st5481_d.c --- v2.4.9/linux/drivers/isdn/hisax/st5481_d.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/st5481_d.c Sun Sep 9 10:45:43 2001 @@ -0,0 +1,774 @@ +/* + * Driver for ST5481 USB ISDN modem + * + * Author Frode Isaksen + * Copyright 2001 by Frode Isaksen + * 2001 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#include +#include +#include +#include +#include +#include +#include "st5481.h" + +static void ph_connect(struct st5481_adapter *adapter); +static void ph_disconnect(struct st5481_adapter *adapter); + +static struct Fsm l1fsm; + +static char *strL1State[] = +{ + "ST_L1_F3", + "ST_L1_F4", + "ST_L1_F6", + "ST_L1_F7", + "ST_L1_F8", +}; + +static char *strL1Event[] = +{ + "EV_IND_DP", + "EV_IND_1", + "EV_IND_2", + "EV_IND_3", + "EV_IND_RSY", + "EV_IND_5", + "EV_IND_6", + "EV_IND_7", + "EV_IND_AP", + "EV_IND_9", + "EV_IND_10", + "EV_IND_11", + "EV_IND_AI8", + "EV_IND_AI10", + "EV_IND_AIL", + "EV_IND_DI", + "EV_PH_ACTIVATE_REQ", + "EV_PH_DEACTIVATE_REQ", + "EV_TIMER3", +}; + +static inline void D_L1L2(struct st5481_adapter *adapter, int pr, void *arg) +{ + struct hisax_if *ifc = (struct hisax_if *) &adapter->hisax_d_if; + + ifc->l1l2(ifc, pr, arg); +} + +static void +l1_go_f3(struct FsmInst *fi, int event, void *arg) +{ + struct st5481_adapter *adapter = fi->userdata; + + if (fi->state == ST_L1_F7) + ph_disconnect(adapter); + + FsmChangeState(fi, ST_L1_F3); + D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL); +} + +static void +l1_go_f6(struct FsmInst *fi, int event, void *arg) +{ + struct st5481_adapter *adapter = fi->userdata; + + if (fi->state == ST_L1_F7) + ph_disconnect(adapter); + + FsmChangeState(fi, ST_L1_F6); +} + +static void +l1_go_f7(struct FsmInst *fi, int event, void *arg) +{ + struct st5481_adapter *adapter = fi->userdata; + + FsmDelTimer(&adapter->timer, 0); + ph_connect(adapter); + FsmChangeState(fi, ST_L1_F7); + D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL); +} + +static void +l1_go_f8(struct FsmInst *fi, int event, void *arg) +{ + struct st5481_adapter *adapter = fi->userdata; + + if (fi->state == ST_L1_F7) + ph_disconnect(adapter); + + FsmChangeState(fi, ST_L1_F8); +} + +static void +l1_timer3(struct FsmInst *fi, int event, void *arg) +{ + struct st5481_adapter *adapter = fi->userdata; + + st5481_ph_command(adapter, ST5481_CMD_DR); + FsmChangeState(fi, ST_L1_F3); + D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL); +} + +static void +l1_ignore(struct FsmInst *fi, int event, void *arg) +{ +} + +static void +l1_activate(struct FsmInst *fi, int event, void *arg) +{ + struct st5481_adapter *adapter = fi->userdata; + + st5481_ph_command(adapter, ST5481_CMD_DR); + st5481_ph_command(adapter, ST5481_CMD_PUP); + FsmRestartTimer(&adapter->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2); + st5481_ph_command(adapter, ST5481_CMD_AR8); + FsmChangeState(fi, ST_L1_F4); +} + +static struct FsmNode L1FnList[] __initdata = +{ + {ST_L1_F3, EV_IND_DP, l1_ignore}, + {ST_L1_F3, EV_IND_AP, l1_go_f6}, + {ST_L1_F3, EV_IND_AI8, l1_go_f7}, + {ST_L1_F3, EV_IND_AI10, l1_go_f7}, + {ST_L1_F3, EV_PH_ACTIVATE_REQ, l1_activate}, + + {ST_L1_F4, EV_TIMER3, l1_timer3}, + {ST_L1_F4, EV_IND_DP, l1_go_f3}, + {ST_L1_F4, EV_IND_AP, l1_go_f6}, + {ST_L1_F4, EV_IND_AI8, l1_go_f7}, + {ST_L1_F4, EV_IND_AI10, l1_go_f7}, + + {ST_L1_F6, EV_TIMER3, l1_timer3}, + {ST_L1_F6, EV_IND_DP, l1_go_f3}, + {ST_L1_F6, EV_IND_AP, l1_ignore}, + {ST_L1_F6, EV_IND_AI8, l1_go_f7}, + {ST_L1_F6, EV_IND_AI10, l1_go_f7}, + {ST_L1_F7, EV_IND_RSY, l1_go_f8}, + + {ST_L1_F7, EV_IND_DP, l1_go_f3}, + {ST_L1_F7, EV_IND_AP, l1_go_f6}, + {ST_L1_F7, EV_IND_AI8, l1_ignore}, + {ST_L1_F7, EV_IND_AI10, l1_ignore}, + {ST_L1_F7, EV_IND_RSY, l1_go_f8}, + + {ST_L1_F8, EV_TIMER3, l1_timer3}, + {ST_L1_F8, EV_IND_DP, l1_go_f3}, + {ST_L1_F8, EV_IND_AP, l1_go_f6}, + {ST_L1_F8, EV_IND_AI8, l1_go_f8}, + {ST_L1_F8, EV_IND_AI10, l1_go_f8}, + {ST_L1_F8, EV_IND_RSY, l1_ignore}, +}; + +static void l1m_debug(struct FsmInst *fi, char *fmt, ...) +{ + va_list args; + char buf[256]; + + va_start(args, fmt); + vsprintf(buf, fmt, args); + printk("buf %s\n", buf); + DBG(8, "%s", buf); + va_end(args); +} + +/* ====================================================================== + * D-Channel out + */ + +/* + D OUT state machine: + ==================== + + Transmit short frame (< 16 bytes of encoded data): + + L1 FRAME D_OUT_STATE USB D CHANNEL + -------- ----------- --- --------- + + FIXME + + -> [xx..xx] SHORT_INIT -> [7Exx..xxC1C27EFF] + SHORT_WAIT_DEN <> OUT_D_COUNTER=16 + + END_OF_SHORT <- DEN_EVENT -> 7Exx + xxxx + xxxx + xxxx + xxxx + xxxx + C1C1 + 7EFF + WAIT_FOR_RESET_IDLE <- D_UNDERRUN <- (8ms) + IDLE <> Reset pipe + + + + Transmit long frame (>= 16 bytes of encoded data): + + L1 FRAME D_OUT_STATE USB D CHANNEL + -------- ----------- --- --------- + + -> [xx...xx] IDLE + WAIT_FOR_STOP <> OUT_D_COUNTER=0 + WAIT_FOR_RESET <> Reset pipe + STOP + INIT_LONG_FRAME -> [7Exx..xx] + WAIT_DEN <> OUT_D_COUNTER=16 + OUT_NORMAL <- DEN_EVENT -> 7Exx + END_OF_FRAME_BUSY -> [xxxx] xxxx + END_OF_FRAME_NOT_BUSY -> [xxxx] xxxx + -> [xxxx] xxxx + -> [C1C2] xxxx + -> [7EFF] xxxx + xxxx + xxxx + .... + xxxx + C1C2 + 7EFF + <- D_UNDERRUN <- (> 8ms) + WAIT_FOR_STOP <> OUT_D_COUNTER=0 + WAIT_FOR_RESET <> Reset pipe + STOP + +*/ + +static struct Fsm dout_fsm; + +static char *strDoutState[] = +{ + "ST_DOUT_NONE", + + "ST_DOUT_SHORT_INIT", + "ST_DOUT_SHORT_WAIT_DEN", + + "ST_DOUT_LONG_INIT", + "ST_DOUT_LONG_WAIT_DEN", + "ST_DOUT_NORMAL", + + "ST_DOUT_WAIT_FOR_UNDERRUN", + "ST_DOUT_WAIT_FOR_NOT_BUSY", + "ST_DOUT_WAIT_FOR_STOP", + "ST_DOUT_WAIT_FOR_RESET", +}; + +static char *strDoutEvent[] = +{ + "EV_DOUT_START_XMIT", + "EV_DOUT_COMPLETE", + "EV_DOUT_DEN", + "EV_DOUT_RESETED", + "EV_DOUT_STOPPED", + "EV_DOUT_COLL", + "EV_DOUT_UNDERRUN", +}; + +static void dout_debug(struct FsmInst *fi, char *fmt, ...) +{ + va_list args; + char buf[256]; + + va_start(args, fmt); + vsprintf(buf, fmt, args); + DBG(0x2, "%s", buf); + va_end(args); +} + +static void dout_stop_event(void *context) +{ + struct st5481_adapter *adapter = context; + + FsmEvent(&adapter->d_out.fsm, EV_DOUT_STOPPED, NULL); +} + +/* + * Start the transfer of a D channel frame. + */ +static void usb_d_out(struct st5481_adapter *adapter, int buf_nr) +{ + struct st5481_d_out *d_out = &adapter->d_out; + struct urb *urb; + unsigned int num_packets, packet_offset; + int len, buf_size, bytes_sent; + struct sk_buff *skb; + iso_packet_descriptor_t *desc; + + if (d_out->fsm.state != ST_DOUT_NORMAL) + return; + + if (test_and_set_bit(buf_nr, &d_out->busy)) { + DBG(2, "ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy); + return; + } + urb = d_out->urb[buf_nr]; + + skb = d_out->tx_skb; + + buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT; + + if (skb) { + len = hdlc_encode(&d_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer, buf_size); + skb_pull(skb,bytes_sent); + } else { + // Send flags or idle + len = hdlc_encode(&d_out->hdlc_state, + NULL, 0, &bytes_sent, + urb->transfer_buffer, buf_size); + } + + if (len < buf_size) { + FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN); + } + if (skb && !skb->len) { + d_out->tx_skb = NULL; + D_L1L2(adapter, PH_DATA | CONFIRM, NULL); + dev_kfree_skb_any(skb); + } + + // Prepare the URB + urb->transfer_buffer_length = len; + num_packets = 0; + packet_offset = 0; + while (packet_offset < len) { + desc = &urb->iso_frame_desc[num_packets]; + desc->offset = packet_offset; + desc->length = SIZE_ISO_PACKETS_D_OUT; + if (len - packet_offset < desc->length) + desc->length = len - packet_offset; + num_packets++; + packet_offset += desc->length; + } + urb->number_of_packets = num_packets; + + // Prepare the URB + urb->dev = adapter->usb_dev; + // Need to transmit the next buffer 2ms after the DEN_EVENT + urb->transfer_flags = 0; + urb->start_frame = usb_get_current_frame_number(adapter->usb_dev)+2; + + DBG_ISO_PACKET(0x20,urb); + + if (usb_submit_urb(urb) < 0) { + // There is another URB queued up + urb->transfer_flags = USB_ISO_ASAP; + SUBMIT_URB(urb); + } +} + +static void fifo_reseted(void *context) +{ + struct st5481_adapter *adapter = context; + + FsmEvent(&adapter->d_out.fsm, EV_DOUT_RESETED, NULL); +} + +static void usb_d_out_complete(struct urb *urb) +{ + struct st5481_adapter *adapter = urb->context; + struct st5481_d_out *d_out = &adapter->d_out; + int buf_nr; + + DBG(2, ""); + + buf_nr = get_buf_nr(d_out->urb, urb); + test_and_clear_bit(buf_nr, &d_out->busy); + + if (urb->status < 0) { + if (urb->status != USB_ST_URB_KILLED) { + WARN("urb status %d",urb->status); + if (d_out->busy == 0) { + st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); + } + return; + } else { + DBG(1,"urb killed"); + return; // Give up + } + } + + FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr); +} + +/* ====================================================================== */ + +static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg) +{ + // FIXME unify? + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + struct urb *urb; + int len, bytes_sent; + struct sk_buff *skb; + int buf_nr = 0; + + skb = d_out->tx_skb; + + DBG(2,"len=%d",skb->len); + + hdlc_out_init(&d_out->hdlc_state, 1, 0); + + if (test_and_set_bit(buf_nr, &d_out->busy)) { + WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy); + return; + } + urb = d_out->urb[buf_nr]; + + DBG_SKB(0x10, skb); + len = hdlc_encode(&d_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer, 16); + skb_pull(skb, bytes_sent); + + if(len < 16) + FsmChangeState(&d_out->fsm, ST_DOUT_SHORT_INIT); + else + FsmChangeState(&d_out->fsm, ST_DOUT_LONG_INIT); + + if (skb->len == 0) { + d_out->tx_skb = NULL; + D_L1L2(adapter, PH_DATA | CONFIRM, NULL); + dev_kfree_skb_any(skb); + } + +// Prepare the URB + urb->transfer_buffer_length = len; + + urb->iso_frame_desc[0].offset = 0; + urb->iso_frame_desc[0].length = len; + urb->number_of_packets = 1; + + // Prepare the URB + urb->dev = adapter->usb_dev; + urb->transfer_flags = USB_ISO_ASAP; + + DBG_ISO_PACKET(0x20,urb); + SUBMIT_URB(urb); +} + +static void dout_short_fifo(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + FsmChangeState(&d_out->fsm, ST_DOUT_SHORT_WAIT_DEN); + st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 16, NULL, NULL); +} + +static void dout_end_short_frame(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN); +} + +static void dout_long_enable_fifo(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 16, NULL, NULL); + FsmChangeState(&d_out->fsm, ST_DOUT_LONG_WAIT_DEN); +} + +static void dout_long_den(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + FsmChangeState(&d_out->fsm, ST_DOUT_NORMAL); + usb_d_out(adapter, 0); + usb_d_out(adapter, 1); +} + +static void dout_reset(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_RESET); + st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); +} + +static void dout_stop(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_STOP); + st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 0, dout_stop_event, adapter); +} + +static void dout_underrun(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + if (test_bit(0, &d_out->busy) || test_bit(1, &d_out->busy)) { + FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_NOT_BUSY); + } else { + dout_stop(fsm, event, arg); + } +} + +static void dout_check_busy(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + if (!test_bit(0, &d_out->busy) && !test_bit(1, &d_out->busy)) + dout_stop(fsm, event, arg); +} + +static void dout_reseted(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + struct st5481_d_out *d_out = &adapter->d_out; + + FsmChangeState(&d_out->fsm, ST_DOUT_NONE); + // FIXME locking + if (d_out->tx_skb) + FsmEvent(&d_out->fsm, EV_DOUT_START_XMIT, NULL); +} + +static void dout_complete(struct FsmInst *fsm, int event, void *arg) +{ + struct st5481_adapter *adapter = fsm->userdata; + int buf_nr = (int) arg; + + usb_d_out(adapter, buf_nr); +} + +static void dout_ignore(struct FsmInst *fsm, int event, void *arg) +{ +} + +static struct FsmNode DoutFnList[] __initdata = +{ + {ST_DOUT_NONE, EV_DOUT_START_XMIT, dout_start_xmit}, + + {ST_DOUT_SHORT_INIT, EV_DOUT_COMPLETE, dout_short_fifo}, + + {ST_DOUT_SHORT_WAIT_DEN, EV_DOUT_DEN, dout_end_short_frame}, + {ST_DOUT_SHORT_WAIT_DEN, EV_DOUT_UNDERRUN, dout_underrun}, + + {ST_DOUT_LONG_INIT, EV_DOUT_COMPLETE, dout_long_enable_fifo}, + + {ST_DOUT_LONG_WAIT_DEN, EV_DOUT_DEN, dout_long_den}, + {ST_DOUT_LONG_WAIT_DEN, EV_DOUT_UNDERRUN, dout_underrun}, + + {ST_DOUT_NORMAL, EV_DOUT_UNDERRUN, dout_underrun}, + {ST_DOUT_NORMAL, EV_DOUT_COMPLETE, dout_complete}, + + {ST_DOUT_WAIT_FOR_UNDERRUN, EV_DOUT_UNDERRUN, dout_underrun}, + {ST_DOUT_WAIT_FOR_UNDERRUN, EV_DOUT_COMPLETE, dout_ignore}, + + {ST_DOUT_WAIT_FOR_NOT_BUSY, EV_DOUT_COMPLETE, dout_check_busy}, + + {ST_DOUT_WAIT_FOR_STOP, EV_DOUT_STOPPED, dout_reset}, + + {ST_DOUT_WAIT_FOR_RESET, EV_DOUT_RESETED, dout_reseted}, +}; + +void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) +{ + struct st5481_adapter *adapter = hisax_d_if->priv; + struct sk_buff *skb = arg; + + switch (pr) { + case PH_ACTIVATE | REQUEST: + FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL); + break; + case PH_DEACTIVATE | REQUEST: + FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL); + break; + case PH_DATA | REQUEST: + DBG(2, "PH_DATA REQUEST len %d", skb->len); + if (adapter->d_out.tx_skb) + BUG(); + + adapter->d_out.tx_skb = skb; + FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL); + break; + default: + WARN("pr %#x\n", pr); + break; + } +} + +/* ====================================================================== + */ + +/* + * Start receiving on the D channel since entered state F7. + */ +static void ph_connect(struct st5481_adapter *adapter) +{ + struct st5481_d_out *d_out = &adapter->d_out; + struct st5481_in *d_in = &adapter->d_in; + + DBG(8,""); + + FsmChangeState(&d_out->fsm, ST_DOUT_NONE); + + // st5481_usb_device_ctrl_msg(adapter, FFMSK_D, OUT_UNDERRUN, NULL, NULL); + st5481_usb_device_ctrl_msg(adapter, FFMSK_D, 0xfc, NULL, NULL); + st5481_in_mode(d_in, L1_MODE_HDLC); + +#if LOOPBACK + // Turn loopback on (data sent on B and D looped back) + st5481_usb_device_ctrl_msg(cs, LBB, 0x04, NULL, NULL); +#endif + + st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, NULL, NULL); + + // Turn on the green LED to tell that we are in state F7 + adapter->leds |= GREEN_LED; + st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL); +} + +/* + * Stop receiving on the D channel since not in state F7. + */ +static void ph_disconnect(struct st5481_adapter *adapter) +{ + DBG(8,""); + + st5481_in_mode(&adapter->d_in, L1_MODE_NULL); + + // Turn off the green LED to tell that we left state F7 + adapter->leds &= ~GREEN_LED; + st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL); +} + +static int __devinit st5481_setup_d_out(struct st5481_adapter *adapter) +{ + struct usb_device *dev = adapter->usb_dev; + struct usb_interface_descriptor *altsetting; + struct usb_endpoint_descriptor *endpoint; + struct st5481_d_out *d_out = &adapter->d_out; + + DBG(2,""); + + altsetting = &(dev->config->interface[0].altsetting[3]); + + // Allocate URBs and buffers for the D channel out + endpoint = &altsetting->endpoint[EP_D_OUT-1]; + + DBG(2,"endpoint address=%02x,packet size=%d", + endpoint->bEndpointAddress,endpoint->wMaxPacketSize); + + return st5481_setup_isocpipes(d_out->urb, dev, + usb_sndisocpipe(dev, endpoint->bEndpointAddress), + NUM_ISO_PACKETS_D, SIZE_ISO_PACKETS_D_OUT, + NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT, + usb_d_out_complete, adapter); +} + +static void __devexit st5481_release_d_out(struct st5481_adapter *adapter) +{ + struct st5481_d_out *d_out = &adapter->d_out; + + DBG(2,""); + + st5481_release_isocpipes(d_out->urb); +} + +int __devinit st5481_setup_d(struct st5481_adapter *adapter) +{ + int retval; + + DBG(2,""); + + retval = st5481_setup_d_out(adapter); + if (retval) + goto err; + adapter->d_in.bufsize = MAX_DFRAME_LEN_L1; + adapter->d_in.num_packets = NUM_ISO_PACKETS_D; + adapter->d_in.packet_size = SIZE_ISO_PACKETS_D_IN; + adapter->d_in.ep = EP_D_IN | USB_DIR_IN; + adapter->d_in.counter = IN_D_COUNTER; + adapter->d_in.adapter = adapter; + adapter->d_in.hisax_if = &adapter->hisax_d_if.ifc; + retval = st5481_setup_in(&adapter->d_in); + if (retval) + goto err_d_out; + + adapter->l1m.fsm = &l1fsm; + adapter->l1m.state = ST_L1_F3; + adapter->l1m.debug = 1; + adapter->l1m.userdata = adapter; + adapter->l1m.printdebug = l1m_debug; + FsmInitTimer(&adapter->l1m, &adapter->timer); + + adapter->d_out.fsm.fsm = &dout_fsm; + adapter->d_out.fsm.state = ST_DOUT_NONE; + adapter->d_out.fsm.debug = 1; + adapter->d_out.fsm.userdata = adapter; + adapter->d_out.fsm.printdebug = dout_debug; + + return 0; + + err_d_out: + st5481_release_d_out(adapter); + err: + return retval; +} + +void __devexit st5481_release_d(struct st5481_adapter *adapter) +{ + DBG(2,""); + + st5481_release_in(&adapter->d_in); + st5481_release_d_out(adapter); +} + +/* ====================================================================== + * init / exit + */ + +int __init st5481_d_init(void) +{ + int retval; + + l1fsm.state_count = L1_STATE_COUNT; + l1fsm.event_count = L1_EVENT_COUNT; + l1fsm.strEvent = strL1Event; + l1fsm.strState = strL1State; + retval = FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList)); + if (retval) + goto err; + + dout_fsm.state_count = DOUT_STATE_COUNT; + dout_fsm.event_count = DOUT_EVENT_COUNT; + dout_fsm.strEvent = strDoutEvent; + dout_fsm.strState = strDoutState; + retval = FsmNew(&dout_fsm, DoutFnList, ARRAY_SIZE(DoutFnList)); + if (retval) + goto err_l1; + + return 0; + + err_l1: + FsmFree(&l1fsm); + err: + return retval; +} + +// can't be __exit +void st5481_d_exit(void) +{ + FsmFree(&l1fsm); + FsmFree(&dout_fsm); +} diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/st5481_hdlc.c linux/drivers/isdn/hisax/st5481_hdlc.c --- v2.4.9/linux/drivers/isdn/hisax/st5481_hdlc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/st5481_hdlc.c Sun Sep 9 10:45:43 2001 @@ -0,0 +1,620 @@ +/* + * Driver for ST5481 USB ISDN modem + * + * Author Frode Isaksen + * Copyright 2001 by Frode Isaksen + * 2001 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#include "st5481_hdlc.h" + +static const unsigned short int crc16_tab[] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +}; + + + +enum { + HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7, + HDLC_GET_DATA,HDLC_FAST_FLAG +}; + +enum { + HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG, + HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG, + HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0, + HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED +}; + +void +hdlc_rcv_init(struct hdlc_vars *hdlc, int do_adapt56) +{ + hdlc->bit_shift = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->ffbit_shift = 0; + hdlc->data_received = 0; + hdlc->state = HDLC_GET_DATA; + hdlc->do_adapt56 = do_adapt56; + hdlc->dchannel = 0; + hdlc->crc = 0; + hdlc->cbin = 0; + hdlc->shift_reg = 0; + hdlc->ffvalue = 0; + hdlc->dstpos = 0; +} + +void +hdlc_out_init(struct hdlc_vars *hdlc, int is_d_channel, int do_adapt56) +{ + hdlc->bit_shift = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->ffbit_shift = 0; + hdlc->data_received = 0; + hdlc->do_closing = 0; + hdlc->ffvalue = 0; + if (is_d_channel) { + hdlc->dchannel = 1; + hdlc->state = HDLC_SEND_FIRST_FLAG; + } else { + hdlc->dchannel = 0; + hdlc->state = HDLC_SEND_FAST_FLAG; + hdlc->ffvalue = 0x7e; + } + hdlc->cbin = 0x7e; + hdlc->bit_shift = 0; + if(do_adapt56){ + hdlc->do_adapt56 = 1; + hdlc->data_bits = 0; + hdlc->state = HDLC_SENDFLAG_B0; + } else { + hdlc->do_adapt56 = 0; + hdlc->data_bits = 8; + } + hdlc->shift_reg = 0; +} + +/* + hdlc_decode - decodes HDLC frames from a transparent bit stream. + + The source buffer is scanned for valid HDLC frames looking for + flags (01111110) to indicate the start of a frame. If the start of + the frame is found, the bit stuffing is removed (0 after 5 1's). + When a new flag is found, the complete frame has been received + and the CRC is checked. + If a valid frame is found, the function returns the frame length + excluding the CRC with the bit HDLC_END_OF_FRAME set. + If the beginning of a valid frame is found, the function returns + the length. + If a framing error is found (too many 1s and not a flag) the function + returns the length with the bit HDLC_FRAMING_ERROR set. + If a CRC error is found the function returns the length with the + bit HDLC_CRC_ERROR set. + If the frame length exceeds the destination buffer size, the function + returns the length with the bit HDLC_LENGTH_ERROR set. + + src - source buffer + slen - source buffer length + count - number of bytes removed (decoded) from the source buffer + dst _ destination buffer + dsize - destination buffer size + returns - number of decoded bytes in the destination buffer and status + flag. + */ +int hdlc_decode(struct hdlc_vars *hdlc, const unsigned char *src, + int slen, int *count, unsigned char *dst, int dsize) +{ + int status=0; + + static const unsigned char fast_flag[]={ + 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f + }; + + static const unsigned char fast_flag_value[]={ + 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f + }; + + static const unsigned char fast_abort[]={ + 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff + }; + + *count = slen; + + while(slen > 0){ + if(hdlc->bit_shift==0){ + hdlc->cbin = *src++; + slen--; + hdlc->bit_shift = 8; + if(hdlc->do_adapt56){ + hdlc->bit_shift --; + } + } + + switch(hdlc->state){ + case STOPPED: + return 0; + case HDLC_FAST_IDLE: + if(hdlc->cbin == 0xff){ + hdlc->bit_shift = 0; + break; + } + hdlc->state = HDLC_GET_FLAG_B0; + hdlc->hdlc_bits1 = 0; + hdlc->bit_shift = 8; + break; + case HDLC_GET_FLAG_B0: + if(!(hdlc->cbin & 0x80)) { + hdlc->state = HDLC_GETFLAG_B1A6; + hdlc->hdlc_bits1 = 0; + } else { + if(!hdlc->do_adapt56){ + if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1) + hdlc->state = HDLC_FAST_IDLE; + } + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GETFLAG_B1A6: + if(hdlc->cbin & 0x80){ + hdlc->hdlc_bits1++; + if(hdlc->hdlc_bits1==6){ + hdlc->state = HDLC_GETFLAG_B7; + } + } else { + hdlc->hdlc_bits1 = 0; + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GETFLAG_B7: + if(hdlc->cbin & 0x80) { + hdlc->state = HDLC_GET_FLAG_B0; + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->crc = 0xffff; + hdlc->shift_reg = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->data_received = 0; + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GET_DATA: + if(hdlc->cbin & 0x80){ + hdlc->hdlc_bits1++; + switch(hdlc->hdlc_bits1){ + case 6: + break; + case 7: + if(hdlc->data_received) { + // bad frame + status = -HDLC_FRAMING_ERROR; + } + if(!hdlc->do_adapt56){ + if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){ + hdlc->state = HDLC_FAST_IDLE; + hdlc->bit_shift=1; + break; + } + } else { + hdlc->state = HDLC_GET_FLAG_B0; + } + break; + default: + hdlc->shift_reg>>=1; + hdlc->shift_reg |= 0x80; + hdlc->data_bits++; + break; + } + } else { + switch(hdlc->hdlc_bits1){ + case 5: + break; + case 6: + if(hdlc->data_received){ + if (hdlc->dstpos < 2) { + status = -HDLC_FRAMING_ERROR; + } else if (hdlc->crc != 0xf0b8){ + // crc error + status = -HDLC_CRC_ERROR; + } else { + // remove CRC + hdlc->dstpos -= 2; + // good frame + status = hdlc->dstpos; + } + } + hdlc->crc = 0xffff; + hdlc->shift_reg = 0; + hdlc->data_bits = 0; + if(!hdlc->do_adapt56){ + if(hdlc->cbin==fast_flag[hdlc->bit_shift]){ + hdlc->ffvalue = fast_flag_value[hdlc->bit_shift]; + hdlc->state = HDLC_FAST_FLAG; + hdlc->ffbit_shift = hdlc->bit_shift; + hdlc->bit_shift = 1; + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + break; + default: + hdlc->shift_reg>>=1; + hdlc->data_bits++; + break; + } + hdlc->hdlc_bits1 = 0; + } + if (status) { + hdlc->dstpos = 0; + *count -= slen; + hdlc->cbin <<= 1; + hdlc->bit_shift--; + return status; + } + if(hdlc->data_bits==8){ + unsigned cval; + + hdlc->data_bits = 0; + hdlc->data_received = 1; + cval = (hdlc->crc^hdlc->shift_reg) & 0xff; + hdlc->crc = (hdlc->crc>>8)^crc16_tab[cval]; + // good byte received + if (dsize--) { + dst[hdlc->dstpos++] = hdlc->shift_reg; + } else { + // frame too long + status = -HDLC_LENGTH_ERROR; + hdlc->dstpos = 0; + } + } + hdlc->cbin <<= 1; + hdlc->bit_shift--; + break; + case HDLC_FAST_FLAG: + if(hdlc->cbin==hdlc->ffvalue){ + hdlc->bit_shift = 0; + break; + } else { + if(hdlc->cbin == 0xff){ + hdlc->state = HDLC_FAST_IDLE; + hdlc->bit_shift=0; + } else if(hdlc->ffbit_shift==8){ + hdlc->state = HDLC_GETFLAG_B7; + break; + } else { + hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1]; + hdlc->hdlc_bits1 = hdlc->ffbit_shift-2; + if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0; + hdlc->data_bits = hdlc->ffbit_shift-1; + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + } + break; + default: + break; + } + } + *count -= slen; + return 0; +} + +/* + hdlc_encode - encodes HDLC frames to a transparent bit stream. + + The bit stream starts with a beginning flag (01111110). After + that each byte is added to the bit stream with bit stuffing added + (0 after 5 1's). + When the last byte has been removed from the source buffer, the + CRC (2 bytes is added) and the frame terminates with the ending flag. + For the dchannel, the idle character (all 1's) is also added at the end. + If this function is called with empty source buffer (slen=0), flags or + idle character will be generated. + + src - source buffer + slen - source buffer length + count - number of bytes removed (encoded) from source buffer + dst _ destination buffer + dsize - destination buffer size + returns - number of encoded bytes in the destination buffer +*/ +int hdlc_encode(struct hdlc_vars *hdlc, const unsigned char *src, + unsigned short slen, int *count, + unsigned char *dst, int dsize) +{ + static const unsigned char xfast_flag_value[] = { + 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e + }; + + int len = 0; + + *count = slen; + + while (dsize > 0) { + if(hdlc->bit_shift==0){ + if(slen && !hdlc->do_closing){ + hdlc->shift_reg = *src++; + slen--; + if (slen == 0) + hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */ + hdlc->bit_shift = 8; + } else { + if(hdlc->state == HDLC_SEND_DATA){ + if(hdlc->data_received){ + hdlc->state = HDLC_SEND_CRC1; + hdlc->crc ^= 0xffff; + hdlc->bit_shift = 8; + hdlc->shift_reg = hdlc->crc & 0xff; + } else if(!hdlc->do_adapt56){ + hdlc->state = HDLC_SEND_FAST_FLAG; + } else { + hdlc->state = HDLC_SENDFLAG_B0; + } + } + + } + } + + switch(hdlc->state){ + case STOPPED: + while (dsize--) + *dst++ = 0xff; + + return dsize; + case HDLC_SEND_FAST_FLAG: + hdlc->do_closing = 0; + if(slen == 0){ + *dst++ = hdlc->ffvalue; + len++; + dsize--; + break; + } + if(hdlc->bit_shift==8){ + hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits); + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + hdlc->data_received = 1; + } + break; + case HDLC_SENDFLAG_B0: + hdlc->do_closing = 0; + hdlc->cbin <<= 1; + hdlc->data_bits++; + hdlc->hdlc_bits1 = 0; + hdlc->state = HDLC_SENDFLAG_B1A6; + break; + case HDLC_SENDFLAG_B1A6: + hdlc->cbin <<= 1; + hdlc->data_bits++; + hdlc->cbin++; + if(++hdlc->hdlc_bits1 == 6) + hdlc->state = HDLC_SENDFLAG_B7; + break; + case HDLC_SENDFLAG_B7: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(slen == 0){ + hdlc->state = HDLC_SENDFLAG_B0; + break; + } + if(hdlc->bit_shift==8){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + hdlc->data_received = 1; + } + break; + case HDLC_SEND_FIRST_FLAG: + hdlc->data_received = 1; + if(hdlc->data_bits==8){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + break; + } + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->shift_reg & 0x01) + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + } + break; + case HDLC_SEND_DATA: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->bit_shift==8){ + unsigned cval; + + cval = (hdlc->crc^hdlc->shift_reg) & 0xff; + hdlc->crc = (hdlc->crc>>8)^crc16_tab[cval]; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + break; + case HDLC_SEND_CRC1: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + if(hdlc->bit_shift==0){ + hdlc->shift_reg = (hdlc->crc >> 8); + hdlc->state = HDLC_SEND_CRC2; + hdlc->bit_shift = 8; + } + break; + case HDLC_SEND_CRC2: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + if(hdlc->bit_shift==0){ + hdlc->shift_reg = 0x7e; + hdlc->state = HDLC_SEND_CLOSING_FLAG; + hdlc->bit_shift = 8; + } + break; + case HDLC_SEND_CLOSING_FLAG: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->cbin++; + } + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; + if(hdlc->dchannel){ + hdlc->ffvalue = 0x7e; + hdlc->state = HDLC_SEND_IDLE1; + hdlc->bit_shift = 8-hdlc->data_bits; + if(hdlc->bit_shift==0) + hdlc->state = HDLC_SEND_FAST_IDLE; + } else { + if(!hdlc->do_adapt56){ + hdlc->state = HDLC_SEND_FAST_FLAG; + hdlc->data_received = 0; + } else { + hdlc->state = HDLC_SENDFLAG_B0; + hdlc->data_received = 0; + } + // Finished with this frame, send flags + if (dsize > 1) dsize = 1; + } + } + break; + case HDLC_SEND_IDLE1: + hdlc->do_closing = 0; + hdlc->cbin <<= 1; + hdlc->cbin++; + hdlc->data_bits++; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->state = HDLC_SEND_FAST_IDLE; + hdlc->bit_shift = 0; + } + break; + case HDLC_SEND_FAST_IDLE: + hdlc->do_closing = 0; + hdlc->cbin = 0xff; + hdlc->data_bits = 8; + if(hdlc->bit_shift == 8){ + hdlc->cbin = 0x7e; + hdlc->state = HDLC_SEND_FIRST_FLAG; + } else { + *dst++ = hdlc->cbin; + hdlc->bit_shift = hdlc->data_bits = 0; + len++; + dsize = 0; + } + break; + default: + break; + } + if(hdlc->do_adapt56){ + if(hdlc->data_bits==7){ + hdlc->cbin <<= 1; + hdlc->cbin++; + hdlc->data_bits++; + } + } + if(hdlc->data_bits==8){ + *dst++ = hdlc->cbin; + hdlc->data_bits = 0; + len++; + dsize--; + } + } + *count -= slen; + + return len; +} + diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/st5481_hdlc.h linux/drivers/isdn/hisax/st5481_hdlc.h --- v2.4.9/linux/drivers/isdn/hisax/st5481_hdlc.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/st5481_hdlc.h Sun Sep 9 10:45:43 2001 @@ -0,0 +1,62 @@ +/* + * Driver for ST5481 USB ISDN modem + * + * Author Frode Isaksen + * Copyright 2001 by Frode Isaksen + * 2001 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#ifndef __ST5481_HDLC_H__ +#define __ST5481_HDLC_H__ + +struct hdlc_vars { + int bit_shift; + int hdlc_bits1; + int data_bits; + int ffbit_shift; // encoding only + int state; + int dstpos; + + int data_received:1; // set if transferring data + int dchannel:1; // set if D channel (send idle instead of flags) + int do_adapt56:1; // set if 56K adaptation + int do_closing:1; // set if in closing phase (need to send CRC + flag + + unsigned short crc; + + unsigned char cbin; + unsigned char shift_reg; + unsigned char ffvalue; + +}; + + +/* + The return value from hdlc_decode is + the frame length, 0 if no complete frame was decoded, + or a negative error number +*/ + +#define HDLC_FRAMING_ERROR 1 +#define HDLC_CRC_ERROR 2 +#define HDLC_LENGTH_ERROR 3 + +void +hdlc_rcv_init(struct hdlc_vars *hdlc, int do_adapt56); + +int +hdlc_decode(struct hdlc_vars *hdlc, const unsigned char *src, int slen,int *count, + unsigned char *dst, int dsize); + +void +hdlc_out_init(struct hdlc_vars *hdlc,int is_d_channel,int do_adapt56); + +int +hdlc_encode(struct hdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count, + unsigned char *dst,int dsize); + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/st5481_init.c linux/drivers/isdn/hisax/st5481_init.c --- v2.4.9/linux/drivers/isdn/hisax/st5481_init.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/st5481_init.c Sun Sep 9 10:45:43 2001 @@ -0,0 +1,215 @@ +/* + * Driver for ST5481 USB ISDN modem + * + * Author Frode Isaksen + * Copyright 2001 by Frode Isaksen + * 2001 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +/* + * TODO: + * + * b layer1 delay? + * hdlc as module + * hotplug / unregister issues + * mod_inc/dec_use_count + * unify parts of d/b channel usb handling + * file header + * avoid copy to isoc buffer? + * improve usb delay? + * merge l1 state machines? + * clean up debug + */ + +#include +#include +#include +#include +#include +#include "st5481.h" + +MODULE_AUTHOR("Frode Isaksen "); +MODULE_DESCRIPTION("ST5481 USB ISDN modem driver"); + +static int protocol = 2; /* EURO-ISDN Default */ +MODULE_PARM(protocol, "i"); + +static int number_of_leds = 2; /* 2 LEDs on the adpater default */ +MODULE_PARM(number_of_leds, "i"); + +#ifdef CONFIG_HISAX_DEBUG +static int debug = 0x1; +MODULE_PARM(debug, "i"); +int st5481_debug; +#endif + +static LIST_HEAD(adapter_list); + +/* ====================================================================== + * registration/deregistration with the USB layer + */ + +/* + * This function will be called when the adapter is plugged + * into the USB bus. + */ +static void * __devinit probe_st5481(struct usb_device *dev, + unsigned int ifnum, + const struct usb_device_id *id) +{ + struct st5481_adapter *adapter; + struct hisax_b_if *b_if[2]; + int retval, i; + + printk(KERN_INFO "st541: found adapter VendorId %04x, ProductId %04x, LEDs %d\n", + dev->descriptor.idVendor, dev->descriptor.idProduct, + number_of_leds); + + adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL); + if (!adapter) + return NULL; + + memset(adapter, 0, sizeof(struct st5481_adapter)); + + adapter->number_of_leds = number_of_leds; + adapter->usb_dev = dev; + + SET_MODULE_OWNER(&adapter->hisax_d_if); + adapter->hisax_d_if.ifc.priv = adapter; + adapter->hisax_d_if.ifc.l2l1 = st5481_d_l2l1; + + for (i = 0; i < 2; i++) { + adapter->bcs[i].adapter = adapter; + adapter->bcs[i].channel = i; + adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i]; + adapter->bcs[i].b_if.ifc.l2l1 = st5481_b_l2l1; + } + list_add(&adapter->list, &adapter_list); + + retval = st5481_setup_usb(adapter); + if (retval < 0) + goto err; + + retval = st5481_setup_d(adapter); + if (retval < 0) + goto err_usb; + + retval = st5481_setup_b(&adapter->bcs[0]); + if (retval < 0) + goto err_d; + + retval = st5481_setup_b(&adapter->bcs[1]); + if (retval < 0) + goto err_b; + + for (i = 0; i < 2; i++) + b_if[i] = &adapter->bcs[i].b_if; + + hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", protocol); + st5481_start(adapter); + + return adapter; + + err_b: + st5481_release_b(&adapter->bcs[0]); + err_d: + st5481_release_d(adapter); + err_usb: + st5481_release_usb(adapter); + err: + return NULL; +} + +/* + * This function will be called when the adapter is removed + * from the USB bus. + */ +static void __devexit disconnect_st5481(struct usb_device *dev, void *arg) +{ + struct st5481_adapter *adapter = arg; + + DBG(1,""); + + list_del(&adapter->list); + + st5481_stop(adapter); + st5481_release_b(&adapter->bcs[1]); + st5481_release_b(&adapter->bcs[0]); + st5481_release_d(adapter); + // we would actually better wait for completion of outstanding urbs + mdelay(2); + st5481_release_usb(adapter); + + hisax_unregister(&adapter->hisax_d_if); + + kfree(adapter); +} + +/* + * The last 4 bits in the Product Id is set with 4 pins on the chip. + */ +static struct usb_device_id st5481_ids[] = { + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x0) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x1) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x2) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x3) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x4) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x5) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x6) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x7) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x8) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x9) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xA) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xB) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xC) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xD) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xE) }, + { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xF) }, + { } +}; +MODULE_DEVICE_TABLE (usb, st5481_ids); + +static struct usb_driver st5481_usb_driver = { + name: "st5481_usb", + probe: probe_st5481, + disconnect: disconnect_st5481, + id_table: st5481_ids, +}; + +static int __init st5481_usb_init(void) +{ + int retval; + +#ifdef CONFIG_HISAX_DEBUG + st5481_debug = debug; +#endif + + printk(KERN_INFO "hiax_st5481: ST5481 USB ISDN driver v0.1.0\n"); + + retval = st5481_d_init(); + if (retval < 0) + goto out; + + retval = usb_register(&st5481_usb_driver); + if (retval < 0) + goto out_d_exit; + + return 0; + + out_d_exit: + st5481_d_exit(); + out: + return retval; +} + +static void __exit st5481_usb_exit(void) +{ + usb_deregister(&st5481_usb_driver); +} + +module_init(st5481_usb_init); +module_exit(st5481_usb_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/hisax/st5481_usb.c linux/drivers/isdn/hisax/st5481_usb.c --- v2.4.9/linux/drivers/isdn/hisax/st5481_usb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/st5481_usb.c Sun Sep 9 10:45:43 2001 @@ -0,0 +1,639 @@ +/* + * Driver for ST5481 USB ISDN modem + * + * Author Frode Isaksen + * Copyright 2001 by Frode Isaksen + * 2001 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#include +#include +#include +#include +#include +#include "st5481.h" + +/* ====================================================================== + * control pipe + */ + +/* + * Send the next endpoint 0 request stored in the FIFO. + * Called either by the completion or by usb_ctrl_msg. + */ +static void usb_next_ctrl_msg(struct urb *urb, + struct st5481_adapter *adapter) +{ + struct st5481_ctrl *ctrl = &adapter->ctrl; + int r_index; + + if (test_and_set_bit(0, &ctrl->busy)) { + return; + } + + if ((r_index = fifo_remove(&ctrl->msg_fifo.f)) < 0) { + test_and_clear_bit(0,&ctrl->busy); + return; + } + urb->setup_packet = + (unsigned char *)&ctrl->msg_fifo.data[r_index]; + + DBG(1,"request=0x%02x,value=0x%04x,index=%x", + ((struct ctrl_msg *)urb->setup_packet)->dr.request, + ((struct ctrl_msg *)urb->setup_packet)->dr.value, + ((struct ctrl_msg *)urb->setup_packet)->dr.index); + + // Prepare the URB + urb->dev = adapter->usb_dev; + + SUBMIT_URB(urb); +} + +/* + * Asynchronous endpoint 0 request (async version of usb_control_msg). + * The request will be queued up in a FIFO if the endpoint is busy. + */ +void usb_ctrl_msg(struct st5481_adapter *adapter, + u8 request, u8 requesttype, u16 value, u16 index, + ctrl_complete_t complete, void *context) +{ + struct st5481_ctrl *ctrl = &adapter->ctrl; + int w_index; + struct ctrl_msg *ctrl_msg; + + if ((w_index = fifo_add(&ctrl->msg_fifo.f)) < 0) { + WARN("control msg FIFO full"); + return; + } + ctrl_msg = &ctrl->msg_fifo.data[w_index]; + + ctrl_msg->dr.requesttype = requesttype; + ctrl_msg->dr.request = request; + ctrl_msg->dr.value = cpu_to_le16p(&value); + ctrl_msg->dr.index = cpu_to_le16p(&index); + ctrl_msg->dr.length = 0; + ctrl_msg->complete = complete; + ctrl_msg->context = context; + + usb_next_ctrl_msg(ctrl->urb, adapter); +} + +/* + * Asynchronous endpoint 0 device request. + */ +void st5481_usb_device_ctrl_msg(struct st5481_adapter *adapter, + u8 request, u16 value, + ctrl_complete_t complete, void *context) +{ + usb_ctrl_msg(adapter, request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, 0, complete, context); +} + +/* + * Asynchronous pipe reset (async version of usb_clear_halt). + */ +void st5481_usb_pipe_reset(struct st5481_adapter *adapter, + u_char pipe, + ctrl_complete_t complete, void *context) +{ + DBG(1,"pipe=%02x",pipe); + + usb_ctrl_msg(adapter, + USB_REQ_CLEAR_FEATURE, USB_DIR_OUT | USB_RECIP_ENDPOINT, + 0, pipe, complete, context); +} + + +/* + Physical level functions +*/ + +void st5481_ph_command(struct st5481_adapter *adapter, unsigned int command) +{ + DBG(8,"command=%s", ST5481_CMD_string(command)); + + st5481_usb_device_ctrl_msg(adapter, TXCI, command, NULL, NULL); +} + +/* + * The request on endpoint 0 has completed. + * Call the user provided completion routine and try + * to send the next request. + */ +static void usb_ctrl_complete(struct urb *urb) +{ + struct st5481_adapter *adapter = urb->context; + struct st5481_ctrl *ctrl = &adapter->ctrl; + struct ctrl_msg *ctrl_msg; + + if (urb->status < 0) { + if (urb->status != USB_ST_URB_KILLED) { + WARN("urb status %d",urb->status); + } else { + DBG(1,"urb killed"); + return; // Give up + } + } + + ctrl_msg = (struct ctrl_msg *)urb->setup_packet; + + if (ctrl_msg->dr.request == USB_REQ_CLEAR_FEATURE) { + /* Special case handling for pipe reset */ + le16_to_cpus(&ctrl_msg->dr.index); + usb_endpoint_running(adapter->usb_dev, + ctrl_msg->dr.index & ~USB_DIR_IN, + (ctrl_msg->dr.index & USB_DIR_IN) == 0); + + /* toggle is reset on clear */ + usb_settoggle(adapter->usb_dev, + ctrl_msg->dr.index & ~USB_DIR_IN, + (ctrl_msg->dr.index & USB_DIR_IN) == 0, + 0); + + + } + + if (ctrl_msg->complete) + ctrl_msg->complete(ctrl_msg->context); + + clear_bit(0, &ctrl->busy); + + // Try to send next control message + usb_next_ctrl_msg(urb, adapter); + return; +} + +/* ====================================================================== + * interrupt pipe + */ + +/* + * The interrupt endpoint will be called when any + * of the 6 registers changes state (depending on masks). + * Decode the register values and schedule a private event. + * Called at interrupt. + */ +static void usb_int_complete(struct urb *urb) +{ + u_char *data = urb->transfer_buffer; + u_char irqbyte; + struct st5481_adapter *adapter = urb->context; + int j; + + if (urb->status < 0) { + if (urb->status != USB_ST_URB_KILLED) { + WARN("urb status %d",urb->status); + urb->actual_length = 0; + } else { + DBG(1,"urb killed"); + return; // Give up + } + } + + DBG_PACKET(1, data, INT_PKT_SIZE); + + if (urb->actual_length == 0) { + return; + } + + irqbyte = data[MPINT]; + if (irqbyte & DEN_INT) + FsmEvent(&adapter->d_out.fsm, EV_DOUT_DEN, NULL); + + if (irqbyte & DCOLL_INT) + FsmEvent(&adapter->d_out.fsm, EV_DOUT_COLL, NULL); + + irqbyte = data[FFINT_D]; + if (irqbyte & OUT_UNDERRUN) + FsmEvent(&adapter->d_out.fsm, EV_DOUT_UNDERRUN, NULL); + + if (irqbyte & OUT_DOWN) +;// printk("OUT_DOWN\n"); + + irqbyte = data[MPINT]; + if (irqbyte & RXCI_INT) + FsmEvent(&adapter->l1m, data[CCIST] & 0x0f, NULL); + + for (j = 0; j < 2; j++) + adapter->bcs[j].b_out.flow_event |= data[FFINT_B1 + j]; + + urb->actual_length = 0; +} + +/* ====================================================================== + * initialization + */ + +int __devinit st5481_setup_usb(struct st5481_adapter *adapter) +{ + struct usb_device *dev = adapter->usb_dev; + struct st5481_ctrl *ctrl = &adapter->ctrl; + struct st5481_intr *intr = &adapter->intr; + struct usb_interface_descriptor *altsetting; + struct usb_endpoint_descriptor *endpoint; + int status; + urb_t *urb; + u_char *buf; + + DBG(1,""); + + if ((status = usb_set_configuration (dev,dev->config[0].bConfigurationValue)) < 0) { + WARN("set_configuration failed,status=%d",status); + return status; + } + + + altsetting = &(dev->config->interface[0].altsetting[3]); + + // Check if the config is sane + if ( altsetting->bNumEndpoints != 7 ) { + WARN("expecting 7 got %d endpoints!", altsetting->bNumEndpoints); + return -EINVAL; + } + + // The descriptor is wrong for some early samples of the ST5481 chip + altsetting->endpoint[3].wMaxPacketSize = 32; + altsetting->endpoint[4].wMaxPacketSize = 32; + + // Use alternative setting 3 on interface 0 to have 2B+D + if ((status = usb_set_interface (dev, 0, 3)) < 0) { + WARN("usb_set_interface failed,status=%d",status); + return status; + } + + // Allocate URB for control endpoint + urb = usb_alloc_urb(0); + if (!urb) { + return -ENOMEM; + } + ctrl->urb = urb; + + // Fill the control URB + FILL_CONTROL_URB (urb, dev, + usb_sndctrlpipe(dev, 0), + NULL, NULL, 0, usb_ctrl_complete, adapter); + + + fifo_init(&ctrl->msg_fifo.f, ARRAY_SIZE(ctrl->msg_fifo.data)); + + // Allocate URBs and buffers for interrupt endpoint + urb = usb_alloc_urb(0); + if (!urb) { + return -ENOMEM; + } + intr->urb = urb; + + buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL); + if (!buf) { + return -ENOMEM; + } + + endpoint = &altsetting->endpoint[EP_INT-1]; + + // Fill the interrupt URB + FILL_INT_URB(urb, dev, + usb_rcvintpipe(dev, endpoint->bEndpointAddress), + buf, INT_PKT_SIZE, + usb_int_complete, adapter, + endpoint->bInterval); + + return 0; +} + +/* + * Release buffers and URBs for the interrupt and control + * endpoint. + */ +void __devexit st5481_release_usb(struct st5481_adapter *adapter) +{ + struct st5481_intr *intr = &adapter->intr; + struct st5481_ctrl *ctrl = &adapter->ctrl; + + DBG(1,""); + + // Stop and free Control and Interrupt URBs + usb_unlink_urb(ctrl->urb); + if (ctrl->urb->transfer_buffer) + kfree(ctrl->urb->transfer_buffer); + usb_free_urb(ctrl->urb); + + usb_unlink_urb(intr->urb); + if (intr->urb->transfer_buffer) + kfree(intr->urb->transfer_buffer); + usb_free_urb(intr->urb); +} + +/* + * Initialize the adapter. + */ +void __devinit st5481_start(struct st5481_adapter *adapter) +{ + static const u8 init_cmd_table[]={ + SET_DEFAULT,0, + STT,0, + SDA_MIN,0x0d, + SDA_MAX,0x29, + SDELAY_VALUE,0x14, + GPIO_DIR,0x01, + GPIO_OUT,RED_LED, +// FFCTRL_OUT_D,4, +// FFCTRH_OUT_D,12, + FFCTRL_OUT_B1,6, + FFCTRH_OUT_B1,20, + FFCTRL_OUT_B2,6, + FFCTRH_OUT_B2,20, + MPMSK,RXCI_INT+DEN_INT+DCOLL_INT, + 0 + }; + struct st5481_intr *intr = &adapter->intr; + int i = 0; + u8 request,value; + + DBG(8,""); + + adapter->leds = RED_LED; + + // Start receiving on the interrupt endpoint + SUBMIT_URB(intr->urb); + + while ((request = init_cmd_table[i++])) { + value = init_cmd_table[i++]; + st5481_usb_device_ctrl_msg(adapter, request, value, NULL, NULL); + } + st5481_ph_command(adapter, ST5481_CMD_PUP); +} + +/* + * Reset the adapter to default values. + */ +void __devexit st5481_stop(struct st5481_adapter *adapter) +{ + DBG(8,""); + + st5481_usb_device_ctrl_msg(adapter, SET_DEFAULT, 0, NULL, NULL); +} + +/* ====================================================================== + * isochronous USB helpers + */ + +static void __devinit +fill_isoc_urb(struct urb *urb, struct usb_device *dev, + unsigned int pipe, void *buf, int num_packets, + int packet_size, usb_complete_t complete, + void *context) +{ + int k; + + spin_lock_init(&urb->lock); + urb->dev=dev; + urb->pipe=pipe; + urb->transfer_buffer=buf; + urb->number_of_packets = num_packets; + urb->transfer_buffer_length=num_packets*packet_size; + urb->actual_length = 0; + urb->complete=complete; + urb->context=context; + urb->transfer_flags=USB_ISO_ASAP; + for (k = 0; k < num_packets; k++) { + urb->iso_frame_desc[k].offset = packet_size * k; + urb->iso_frame_desc[k].length = packet_size; + urb->iso_frame_desc[k].actual_length = 0; + } +} + +int __devinit +st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, + unsigned int pipe, int num_packets, + int packet_size, int buf_size, + usb_complete_t complete, void *context) +{ + int j, retval; + unsigned char *buf; + + for (j = 0; j < 2; j++) { + retval = -ENOMEM; + urb[j] = usb_alloc_urb(num_packets); + if (!urb[j]) + goto err; + + // Allocate memory for 2000bytes/sec (16Kb/s) + buf = kmalloc(buf_size, GFP_KERNEL); + if (!buf) + goto err; + + // Fill the isochronous URB + fill_isoc_urb(urb[j], dev, pipe, buf, + num_packets, packet_size, complete, + context); + } + return 0; + + err: + for (j = 0; j < 2; j++) { + if (urb[j]) { + if (urb[j]->transfer_buffer) + kfree(urb[j]->transfer_buffer); + usb_free_urb(urb[j]); + } + } + return retval; +} + +void __devexit st5481_release_isocpipes(struct urb* urb[2]) +{ + int j; + + for (j = 0; j < 2; j++) { + usb_unlink_urb(urb[j]); + if (urb[j]->transfer_buffer) + kfree(urb[j]->transfer_buffer); + usb_free_urb(urb[j]); + } +} + +/* + * Decode frames received on the B/D channel. + * Note that this function will be called continously + * with 64Kbit/s / 16Kbit/s of data and hence it will be + * called 50 times per second with 20 ISOC descriptors. + * Called at interrupt. + */ +static void usb_in_complete(struct urb *urb) +{ + struct st5481_in *in = urb->context; + unsigned char *ptr; + struct sk_buff *skb; + int len, count, status; + + if (urb->status < 0) { + if (urb->status != USB_ST_URB_KILLED) { + WARN("urb status %d",urb->status); + } else { + DBG(1,"urb killed"); + return; // Give up + } + } + + DBG_ISO_PACKET(0x80,urb); + + len = st5481_isoc_flatten(urb); + ptr = urb->transfer_buffer; + while (len > 0) { + if (in->mode == L1_MODE_TRANS) { + memcpy(in->rcvbuf, ptr, len); + status = len; + len = 0; + } else { + status = hdlc_decode(&in->hdlc_state, ptr, len, &count, + in->rcvbuf, in->bufsize); + ptr += count; + len -= count; + } + + if (status > 0) { + // Good frame received + DBG(4,"count=%d",status); + DBG_PACKET(0x400, in->rcvbuf, status); + if (!(skb = dev_alloc_skb(status))) { + WARN("receive out of memory\n"); + break; + } + memcpy(skb_put(skb, status), in->rcvbuf, status); + in->hisax_if->l1l2(in->hisax_if, PH_DATA | INDICATION, skb); + } else if (status == -HDLC_CRC_ERROR) { + INFO("CRC error"); + } else if (status == -HDLC_FRAMING_ERROR) { + INFO("framing error"); + } else if (status == -HDLC_LENGTH_ERROR) { + INFO("length error"); + } + } + + // Prepare URB for next transfer + urb->dev = in->adapter->usb_dev; + urb->actual_length = 0; + + SUBMIT_URB(urb); +} + +int __devinit st5481_setup_in(struct st5481_in *in) +{ + struct usb_device *dev = in->adapter->usb_dev; + int retval; + + DBG(4,""); + + in->rcvbuf = kmalloc(in->bufsize, GFP_KERNEL); + retval = -ENOMEM; + if (!in->rcvbuf) + goto err; + + retval = st5481_setup_isocpipes(in->urb, dev, + usb_rcvisocpipe(dev, in->ep), + in->num_packets, in->packet_size, + in->num_packets * in->packet_size, + usb_in_complete, in); + if (retval) + goto err_free; + return 0; + + err_free: + kfree(in->rcvbuf); + err: + return retval; +} + +void __devexit st5481_release_in(struct st5481_in *in) +{ + DBG(2,""); + + st5481_release_isocpipes(in->urb); +} + +/* + * Make the transfer_buffer contiguous by + * copying from the iso descriptors if necessary. + */ +int st5481_isoc_flatten(struct urb *urb) +{ + piso_packet_descriptor_t pipd,pend; + unsigned char *src,*dst; + unsigned int len; + + if (urb->status < 0) { + return urb->status; + } + for (pipd = &urb->iso_frame_desc[0], + pend = &urb->iso_frame_desc[urb->number_of_packets], + dst = urb->transfer_buffer; + pipd < pend; + pipd++) { + + if (pipd->status < 0) { + return (pipd->status); + } + + len = pipd->actual_length; + pipd->actual_length = 0; + src = urb->transfer_buffer+pipd->offset; + + if (src != dst) { + // Need to copy since isoc buffers not full + while (len--) { + *dst++ = *src++; + } + } else { + // No need to copy, just update destination buffer + dst += len; + } + } + // Return size of flattened buffer + return (dst - (unsigned char *)urb->transfer_buffer); +} + +static void st5481_start_rcv(void *context) +{ + struct st5481_in *in = context; + struct st5481_adapter *adapter = in->adapter; + + DBG(4,""); + + in->urb[0]->dev = adapter->usb_dev; + SUBMIT_URB(in->urb[0]); + + in->urb[1]->dev = adapter->usb_dev; + SUBMIT_URB(in->urb[1]); +} + +void st5481_in_mode(struct st5481_in *in, int mode) +{ + if (in->mode == mode) + return; + + in->mode = mode; + + usb_unlink_urb(in->urb[0]); + usb_unlink_urb(in->urb[1]); + + if (in->mode != L1_MODE_NULL) { + if (in->mode != L1_MODE_TRANS) + hdlc_rcv_init(&in->hdlc_state, + in->mode == L1_MODE_HDLC_56K); + + st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL); + st5481_usb_device_ctrl_msg(in->adapter, in->counter, + in->packet_size, + NULL, NULL); + st5481_start_rcv(in); + } else { + st5481_usb_device_ctrl_msg(in->adapter, in->counter, + 0, NULL, NULL); + } +} + 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 14 14:39:59 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 *); @@ -607,7 +607,7 @@ int left; u_char c; int ch; - int flags; + long flags; int i; u_char *p; isdn_ctrl cmd; @@ -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/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.4.9/linux/drivers/isdn/isdn_common.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/isdn/isdn_common.c Fri Sep 14 14:39:59 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.114.6.13 2001/08/13 07:46:15 kai Exp $ +/* $Id: isdn_common.c,v 1.114.6.14 2001/08/17 12:34:25 kai Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -51,7 +51,7 @@ isdn_dev *dev; -static char *isdn_revision = "$Revision: 1.114.6.13 $"; +static char *isdn_revision = "$Revision: 1.114.6.14 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; @@ -280,7 +280,7 @@ } if (tf) { - int flags; + long flags; save_flags(flags); cli(); @@ -292,7 +292,8 @@ void isdn_timer_ctrl(int tf, int onoff) { - int flags, old_tflags; + long flags; + int old_tflags; save_flags(flags); cli(); @@ -792,7 +793,6 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep) { - int left; int count; int count_pull; int count_put; @@ -808,10 +808,11 @@ else return 0; } - left = MIN(len, dev->drv[di]->rcvcount[channel]); + if (len > dev->drv[di]->rcvcount[channel]) + len = dev->drv[di]->rcvcount[channel]; cp = buf; count = 0; - while (left) { + while (len) { if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel]))) break; #ifdef CONFIG_ISDN_AUDIO @@ -824,8 +825,8 @@ dflag = 0; count_pull = count_put = 0; - while ((count_pull < skb->len) && (left > 0)) { - left--; + while ((count_pull < skb->len) && (len > 0)) { + len--; if (dev->drv[di]->DLEflag & DLEmask) { *cp++ = DLE; dev->drv[di]->DLEflag &= ~DLEmask; @@ -846,14 +847,14 @@ #endif /* No DLE's in buff, so simply copy it */ dflag = 1; - if ((count_pull = skb->len) > left) { - count_pull = left; + if ((count_pull = skb->len) > len) { + count_pull = len; dflag = 0; } count_put = count_pull; memcpy(cp, skb->data, count_put); cp += count_put; - left -= count_put; + len -= count_put; #ifdef CONFIG_ISDN_AUDIO } #endif @@ -1048,12 +1049,15 @@ } interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq)); } - if (dev->drv[drvidx]->interface->readstat) + if (dev->drv[drvidx]->interface->readstat) { + if (count > dev->drv[drvidx]->stavail) + count = dev->drv[drvidx]->stavail; len = dev->drv[drvidx]->interface-> - readstat(buf, MIN(count, dev->drv[drvidx]->stavail), - 1, drvidx, isdn_minor2chan(minor)); - else + readstat(buf, count, 1, drvidx, + isdn_minor2chan(minor)); + } else { len = 0; + } save_flags(flags); cli(); if (len) @@ -2393,7 +2397,7 @@ */ static void __exit isdn_exit(void) { - int flags; + long flags; int i; #ifdef CONFIG_ISDN_PPP diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c --- v2.4.9/linux/drivers/isdn/isdn_net.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/isdn/isdn_net.c Fri Sep 14 14:39:59 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_net.c,v 1.140.6.7 2001/07/27 11:15:53 kai Exp $ +/* $Id: isdn_net.c,v 1.140.6.8 2001/08/14 14:04:21 kai Exp $ * Linux ISDN subsystem, network interfaces and related functions (linklevel). * @@ -190,7 +190,7 @@ static void isdn_net_ciscohdlck_connected(isdn_net_local *lp); static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp); -char *isdn_net_revision = "$Revision: 1.140.6.7 $"; +char *isdn_net_revision = "$Revision: 1.140.6.8 $"; /* * Code for raw-networking over ISDN @@ -583,7 +583,7 @@ isdn_net_dev *p = dev->netdev; int anymore = 0; int i; - int flags; + ulong flags; isdn_ctrl cmd; while (p) { @@ -1755,6 +1755,11 @@ case CISCO_TYPE_SLARP: isdn_net_ciscohdlck_slarp_in(lp, skb); goto out_free; + case CISCO_TYPE_CDP: + if (lp->cisco_debserint) + printk(KERN_DEBUG "%s: Received CDP packet. use " + "\"no cdp enable\" on cisco.\n", lp->name); + goto out_free; default: printk(KERN_WARNING "%s: Unknown Cisco type 0x%04x\n", lp->name, type); @@ -2787,7 +2792,7 @@ chidx = lp->pre_channel; } if (cfg->exclusive > 0) { - int flags; + ulong flags; /* If binding is exclusive, try to grab the channel */ save_flags(flags); @@ -3043,7 +3048,7 @@ int inout = phone->outgoing & 1; isdn_net_phone *n; isdn_net_phone *m; - int flags; + ulong flags; if (p) { save_flags(flags); @@ -3079,7 +3084,7 @@ { isdn_net_phone *n; isdn_net_phone *m; - int flags; + ulong flags; int i; save_flags(flags); @@ -3128,7 +3133,7 @@ static int isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) { - int flags; + ulong flags; save_flags(flags); cli(); @@ -3214,7 +3219,7 @@ int isdn_net_rmall(void) { - int flags; + ulong flags; int ret; /* Walk through netdev-chain */ diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/isdn_net.h linux/drivers/isdn/isdn_net.h --- v2.4.9/linux/drivers/isdn/isdn_net.h Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/isdn_net.h Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_net.h,v 1.19.6.1 2001/04/20 02:41:58 keil Exp $ +/* $Id: isdn_net.h,v 1.19.6.2 2001/08/14 14:04:21 kai Exp $ * header for Linux ISDN subsystem, network related functions (linklevel). * @@ -36,6 +36,7 @@ #define CISCO_ADDR_UNICAST 0x0f #define CISCO_ADDR_BROADCAST 0x8f #define CISCO_CTRL 0x00 +#define CISCO_TYPE_CDP 0x2000 #define CISCO_TYPE_INET 0x0800 #define CISCO_TYPE_SLARP 0x8035 #define CISCO_SLARP_REPLY 0 diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c --- v2.4.9/linux/drivers/isdn/isdn_tty.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/isdn/isdn_tty.c Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.c,v 1.94.6.4 2001/07/27 11:15:53 kai Exp $ +/* $Id: isdn_tty.c,v 1.94.6.7 2001/08/27 22:19:04 kai Exp $ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * @@ -66,7 +66,7 @@ static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; -char *isdn_tty_revision = "$Revision: 1.94.6.4 $"; +char *isdn_tty_revision = "$Revision: 1.94.6.7 $"; /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() @@ -727,9 +727,19 @@ isdn_tty_modem_hup(modem_info * info, int local) { isdn_ctrl cmd; + int di, ch; if (!info) return; + + di = info->isdn_driver; + ch = info->isdn_channel; + if (di < 0 || ch < 0) + return; + + info->isdn_driver = -1; + info->isdn_channel = -1; + #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "Mhup ttyI%d\n", info->line); #endif @@ -770,19 +780,18 @@ isdn_tty_modem_result(RESULT_RUNG, info); info->msr &= ~(UART_MSR_DCD | UART_MSR_RI); info->lsr |= UART_LSR_TEMT; - if (info->isdn_driver >= 0) { - if (local) { - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_HANGUP; - cmd.arg = info->isdn_channel; - isdn_command(&cmd); - } - isdn_all_eaz(info->isdn_driver, info->isdn_channel); - info->emu.mdmreg[REG_RINGCNT] = 0; - isdn_free_channel(info->isdn_driver, info->isdn_channel, 0); + + if (local) { + cmd.driver = di; + cmd.command = ISDN_CMD_HANGUP; + cmd.arg = ch; + isdn_command(&cmd); } - info->isdn_driver = -1; - info->isdn_channel = -1; + + isdn_all_eaz(di, ch); + info->emu.mdmreg[REG_RINGCNT] = 0; + isdn_free_channel(di, ch, 0); + if (info->drv_index >= 0) { dev->m_idx[info->drv_index] = -1; info->drv_index = -1; @@ -1187,9 +1196,11 @@ /* See isdn_tty_senddown() */ atomic_inc(&info->xmit_lock); while (1) { - c = MIN(count, info->xmit_size - info->xmit_count); - if (info->isdn_driver >= 0) - c = MIN(c, dev->drv[info->isdn_driver]->maxbufsize); + c = count; + if (c > info->xmit_size - info->xmit_count) + c = info->xmit_size - info->xmit_count; + if (info->isdn_driver >= 0 && c > dev->drv[info->isdn_driver]->maxbufsize) + c = dev->drv[info->isdn_driver]->maxbufsize; if (c <= 0) break; if ((info->online > 1) @@ -2709,6 +2720,10 @@ if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) { isdn_tty_at_cout("\r\nCALLER NUMBER: ", info); isdn_tty_at_cout(dev->num[info->drv_index], info); + if (m->mdmreg[REG_CDN] & BIT_CDN) { + isdn_tty_at_cout("\r\nCALLED NUMBER: ", info); + isdn_tty_at_cout(info->emu.cpn, info); + } } } isdn_tty_at_cout("\r\n", info); @@ -2734,6 +2749,10 @@ isdn_tty_at_cout("\r\n", info); isdn_tty_at_cout("CALLER NUMBER: ", info); isdn_tty_at_cout(dev->num[info->drv_index], info); + if (m->mdmreg[REG_CDN] & BIT_CDN) { + isdn_tty_at_cout("\r\nCALLED NUMBER: ", info); + isdn_tty_at_cout(info->emu.cpn, info); + } } break; case RESULT_NO_CARRIER: diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/isdn_tty.h linux/drivers/isdn/isdn_tty.h --- v2.4.9/linux/drivers/isdn/isdn_tty.h Mon Dec 11 13:21:44 2000 +++ linux/drivers/isdn/isdn_tty.h Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.h,v 1.22 2000/06/21 09:54:29 keil Exp $ +/* $Id: isdn_tty.h,v 1.22.6.1 2001/08/14 14:12:18 kai Exp $ * header for Linux ISDN subsystem, tty related functions (linklevel). * @@ -85,7 +85,10 @@ #define REG_CPN 23 #define BIT_CPN 1 +#define REG_CPNFCON 23 #define BIT_CPNFCON 2 +#define REG_CDN 23 +#define BIT_CDN 4 /* defines for result codes */ #define RESULT_OK 0 diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/isdn_ttyfax.c linux/drivers/isdn/isdn_ttyfax.c --- v2.4.9/linux/drivers/isdn/isdn_ttyfax.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/isdn_ttyfax.c Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_ttyfax.c,v 1.7 2000/05/11 22:29:21 kai Exp $ +/* $Id: isdn_ttyfax.c,v 1.7.6.1 2001/08/14 14:12:18 kai Exp $ * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel). * @@ -33,7 +33,7 @@ #include "isdn_ttyfax.h" -static char *isdn_tty_fax_revision = "$Revision: 1.7 $"; +static char *isdn_tty_fax_revision = "$Revision: 1.7.6.1 $"; #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; } @@ -86,7 +86,7 @@ break; case 2: /* +FCON */ /* Append CPN, if enabled */ - if ((m->mdmreg[REG_CPN] & BIT_CPNFCON) && + if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) && (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { sprintf(rs, "/%s", m->cpn); isdn_tty_at_cout(rs, info); diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/isdnloop/isdnloop.c linux/drivers/isdn/isdnloop/isdnloop.c --- v2.4.9/linux/drivers/isdn/isdnloop/isdnloop.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/isdn/isdnloop/isdnloop.c Fri Sep 14 14:39:59 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnloop.c,v 1.11.6.4 2001/07/13 09:20:12 kai Exp $ +/* $Id: isdnloop.c,v 1.11.6.5 2001/08/17 12:34:27 kai Exp $ * ISDN low-level module implementing a dummy loop driver. * @@ -26,7 +26,7 @@ #include "isdnloop.h" static char -*revision = "$Revision: 1.11.6.4 $"; +*revision = "$Revision: 1.11.6.5 $"; static int isdnloop_addcard(char *); @@ -323,7 +323,7 @@ int left; u_char c; int ch; - int flags; + unsigned long flags; u_char *p; isdn_ctrl cmd; @@ -985,10 +985,12 @@ isdn_ctrl cmd; while (len) { - int count = MIN(255, len); + int count = len; u_char *p; u_char msg[0x100]; + if (count > 255) + count = 255; if (user) copy_from_user(msg, buf, count); else diff -u --recursive --new-file v2.4.9/linux/drivers/isdn/isdnloop/isdnloop.h linux/drivers/isdn/isdnloop/isdnloop.h --- v2.4.9/linux/drivers/isdn/isdnloop/isdnloop.h Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/isdnloop/isdnloop.h Sun Sep 9 10:45:43 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnloop.h,v 1.5.6.1 2001/02/10 14:41:23 kai Exp $ +/* $Id: isdnloop.h,v 1.5.6.2 2001/08/17 12:34:27 kai Exp $ * Loopback lowlevel module for testing of linklevel. * @@ -128,8 +128,6 @@ /* Utility-Macros */ #define CID (card->interface.id) -#define MIN(a,b) ((ab)?a:b) #endif /* defined(__KERNEL__) || defined(__DEBUGVAR__) */ #endif /* isdnloop_h */ 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 - -inline char *strcpy(char *, const char *); +#include int dbg_level = 0; static char dbg_funcname[255]; @@ -45,19 +44,6 @@ strcpy(dbg_funcname, func); if(dbg_level) printk("--> Entering function %s\n", dbg_funcname); -} - -inline char *strcpy(char *dest, const char *src) -{ - char *i = dest; - char *j = (char *) src; - - while(*j) { - *i = *j; - i++; j++; - } - *(++i) = 0; - return dest; } inline void pullphone(char *dn, char *str) diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile --- v2.4.9/linux/drivers/macintosh/Makefile Sun Feb 4 10:21:25 2001 +++ linux/drivers/macintosh/Makefile Wed Aug 29 20:49:36 2001 @@ -15,7 +15,7 @@ # Objects that export symbols. -export-objs := adb.o rtc.o mac_hid.o +export-objs := adb.o rtc.o mac_hid.o via-pmu.o # Object file lists. diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c --- v2.4.9/linux/drivers/macintosh/adb.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/macintosh/adb.c Tue Sep 18 14:23:14 2001 @@ -13,6 +13,7 @@ * - /proc/adb to list the devices and infos * - more /dev/adb to allow userland to receive the * flow of auto-polling datas from a given device. + * - move bus probe to a kernel thread */ #include @@ -32,6 +33,7 @@ #include #include #include +#include #include #ifdef CONFIG_PPC #include @@ -74,6 +76,11 @@ struct notifier_block *adb_client_list = NULL; static int adb_got_sleep = 0; static int adb_inited = 0; +static pid_t adb_probe_task_pid; +static int adb_probe_task_flag; +static wait_queue_head_t adb_probe_task_wq; +static int sleepy_trackpad; +int __adb_probe_sync; #ifdef CONFIG_PMAC_PBOOK static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when); @@ -84,6 +91,9 @@ #endif static int adb_scan_bus(void); +static int do_adb_reset_bus(void); +static void adbdev_init(void); + static struct adb_handler { void (*handler)(unsigned char *, int, struct pt_regs *, int); @@ -104,6 +114,17 @@ } #endif + +static __inline__ void adb_wait_ms(unsigned int ms) +{ + if (current->pid && adb_probe_task_pid && + adb_probe_task_pid == current->pid) { + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(1 + ms * HZ / 1000); + } else + mdelay(ms); +} + static int adb_scan_bus(void) { int i, highFree=0, noMovement; @@ -201,6 +222,64 @@ return devmask; } +/* + * This kernel task handles ADB probing. It dies once probing is + * completed. + */ +static int +adb_probe_task(void *x) +{ + strcpy(current->comm, "kadbprobe"); + + spin_lock_irq(¤t->sigmask_lock); + sigfillset(¤t->blocked); + flush_signals(current); + spin_unlock_irq(¤t->sigmask_lock); + + printk(KERN_INFO "adb: starting probe task...\n"); + do_adb_reset_bus(); + printk(KERN_INFO "adb: finished probe task...\n"); + + adb_probe_task_pid = 0; + clear_bit(0, &adb_probe_task_flag); + return 0; +} + +static void +__adb_probe_task(void *data) +{ + adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, + SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND); +} + +int +adb_reset_bus(void) +{ + static struct tq_struct tqs = { + routine: __adb_probe_task, + }; + + if (__adb_probe_sync) { + do_adb_reset_bus(); + return 0; + } + + /* We need to get a lock on the probe thread */ + while (test_and_set_bit(0, &adb_probe_task_flag)) + schedule(); + + /* Just wait for PID to be 0 just in case (possible race) */ + while (adb_probe_task_pid != 0) + schedule(); + + /* Create probe thread as a child of keventd */ + if (current_is_keventd()) + __adb_probe_task(NULL); + else + schedule_task(&tqs); + return 0; +} + int __init adb_init(void) { struct adb_driver *driver; @@ -231,11 +310,16 @@ } if ((adb_controller == NULL) || adb_controller->init()) { printk(KERN_WARNING "Warning: no ADB interface detected\n"); + adb_controller = NULL; } else { #ifdef CONFIG_PMAC_PBOOK pmu_register_sleep_notifier(&adb_sleep_notifier); #endif /* CONFIG_PMAC_PBOOK */ - + if (machine_is_compatible("AAPL,PowerBook1998") || + machine_is_compatible("PowerBook1,1")) + sleepy_trackpad = 1; + init_waitqueue_head(&adb_probe_task_wq); + adbdev_init(); adb_reset_bus(); } return 0; @@ -255,6 +339,12 @@ switch (when) { case PBOOK_SLEEP_REQUEST: adb_got_sleep = 1; + /* We need to get a lock on the probe thread */ + while (test_and_set_bit(0, &adb_probe_task_flag)) + schedule(); + /* Just wait for PID to be 0 just in case (possible race) */ + while (adb_probe_task_pid != 0) + schedule(); if (adb_controller->autopoll) adb_controller->autopoll(0); ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL); @@ -264,6 +354,7 @@ case PBOOK_SLEEP_REJECT: if (adb_got_sleep) { adb_got_sleep = 0; + clear_bit(0, &adb_probe_task_flag); adb_reset_bus(); } break; @@ -271,16 +362,17 @@ case PBOOK_SLEEP_NOW: break; case PBOOK_WAKE: - adb_reset_bus(); adb_got_sleep = 0; + clear_bit(0, &adb_probe_task_flag); + adb_reset_bus(); break; } return PBOOK_SLEEP_OK; } #endif /* CONFIG_PMAC_PBOOK */ -int -adb_reset_bus(void) +static int +do_adb_reset_bus(void) { int ret, nret, devs; unsigned long flags; @@ -298,16 +390,27 @@ return -EBUSY; } + if (sleepy_trackpad) { + /* Let the trackpad settle down */ + adb_wait_ms(500); + } + save_flags(flags); cli(); memset(adb_handler, 0, sizeof(adb_handler)); restore_flags(flags); - + + /* That one is still a bit synchronous, oh well... */ if (adb_controller->reset_bus) ret = adb_controller->reset_bus(); else ret = 0; + if (sleepy_trackpad) { + /* Let the trackpad settle down */ + adb_wait_ms(1500); + } + if (!ret) { devs = adb_scan_bus(); if (adb_controller->autopoll) @@ -329,24 +432,40 @@ adb_controller->poll(); } +static void +adb_probe_wakeup(struct adb_request *req) +{ + wake_up(&adb_probe_task_wq); +} + +static struct adb_request adb_sreq; +static int adb_sreq_lock; // Use semaphore ! */ int adb_request(struct adb_request *req, void (*done)(struct adb_request *), int flags, int nbytes, ...) { va_list list; - int i; - struct adb_request sreq; + int i, use_sreq; + int rc; if ((adb_controller == NULL) || (adb_controller->send_request == NULL)) return -ENXIO; if (nbytes < 1) return -EINVAL; + if (req == NULL && (flags & ADBREQ_NOSEND)) + return -EINVAL; if (req == NULL) { - req = &sreq; + if (test_and_set_bit(0,&adb_sreq_lock)) { + printk("adb.c: Warning: contention on static request !\n"); + return -EPERM; + } + req = &adb_sreq; flags |= ADBREQ_SYNC; - } + use_sreq = 1; + } else + use_sreq = 0; req->nbytes = nbytes+1; req->done = done; req->reply_expected = flags & ADBREQ_REPLY; @@ -359,7 +478,36 @@ if (flags & ADBREQ_NOSEND) return 0; - return adb_controller->send_request(req, flags & ADBREQ_SYNC); + /* Synchronous requests send from the probe thread cause it to + * block. Beware that the "done" callback will be overriden ! + */ + if ((flags & ADBREQ_SYNC) && + (current->pid && adb_probe_task_pid && + adb_probe_task_pid == current->pid)) { + DECLARE_WAITQUEUE(wait, current); + req->done = adb_probe_wakeup; + add_wait_queue(&adb_probe_task_wq, &wait); + rc = adb_controller->send_request(req, 0); + if (rc || req->complete) + goto bail; + for (;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (req->complete) + break; + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&adb_probe_task_wq, &wait); + rc = 0; + goto bail; + } + + rc = adb_controller->send_request(req, flags & ADBREQ_SYNC); +bail: + if (use_sreq) + clear_bit(0, &adb_sreq_lock); + + return rc; } /* Ultimately this should return the number of devices with @@ -463,8 +611,6 @@ #define ADB_MAJOR 56 /* major number for /dev/adb */ -extern void adbdev_init(void); - struct adbdev_state { spinlock_t lock; atomic_t n_pending; @@ -636,7 +782,7 @@ the controller */ if ((req->data[0] == ADB_PACKET)&&(count > 1) &&(req->data[1] == ADB_BUSRESET)) { - ret = adb_reset_bus(); + ret = do_adb_reset_bus(); atomic_dec(&state->n_pending); goto out; } else { @@ -667,17 +813,9 @@ release: adb_release, }; -void adbdev_init() +static void +adbdev_init(void) { -#ifdef CONFIG_PPC - if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) - return; -#endif -#ifdef CONFIG_MAC - if (!MACH_IS_MAC) - return; -#endif - if (devfs_register_chrdev(ADB_MAJOR, "adb", &adb_fops)) printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR); else diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/adbhid.c linux/drivers/macintosh/adbhid.c --- v2.4.9/linux/drivers/macintosh/adbhid.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/macintosh/adbhid.c Tue Sep 18 14:23:14 2001 @@ -690,12 +690,13 @@ printk(" (trackpad)"); adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, - ADB_READREG(id,1)); + ADB_READREG(id,1)); if (req.reply_len < 8) printk("bad length for reg. 1\n"); else { memcpy(r1_buffer, &req.reply[1], 8); + adb_request(&req, NULL, ADBREQ_SYNC, 9, ADB_WRITEREG(id,1), r1_buffer[0], @@ -704,7 +705,7 @@ r1_buffer[3], r1_buffer[4], r1_buffer[5], - 0x0d, /*r1_buffer[6],*/ + 0x0d, r1_buffer[7]); adb_request(&req, NULL, ADBREQ_SYNC, 9, @@ -717,7 +718,7 @@ 0x8a, 0x1b, 0x50); - + adb_request(&req, NULL, ADBREQ_SYNC, 9, ADB_WRITEREG(id,1), r1_buffer[0], @@ -728,6 +729,9 @@ r1_buffer[5], 0x03, /*r1_buffer[6],*/ r1_buffer[7]); + + /* Without this flush, the trackpad may be locked up */ + adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); } } diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.4.9/linux/drivers/macintosh/mac_keyb.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/macintosh/mac_keyb.c Tue Sep 18 14:23:14 2001 @@ -908,6 +908,9 @@ r1_buffer[5], 0x03, /*r1_buffer[6],*/ r1_buffer[7]); + + /* Without this flush, the trackpad may be locked up */ + adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); } } diff -u --recursive --new-file v2.4.9/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c --- v2.4.9/linux/drivers/macintosh/macserial.c Tue Jul 3 17:08:19 2001 +++ linux/drivers/macintosh/macserial.c Sat Sep 8 12:38:42 2001 @@ -32,7 +32,7 @@ #endif #include -#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/Config.in linux/drivers/md/Config.in --- v2.4.9/linux/drivers/md/Config.in Mon Jan 29 13:16:00 2001 +++ linux/drivers/md/Config.in Fri Sep 14 14:22:18 2001 @@ -11,6 +11,7 @@ dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +dep_tristate ' Multipath I/O support' CONFIG_MD_MULTIPATH $CONFIG_BLK_DEV_MD dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD diff -u --recursive --new-file v2.4.9/linux/drivers/md/Makefile linux/drivers/md/Makefile --- v2.4.9/linux/drivers/md/Makefile Fri Dec 29 14:07:22 2000 +++ linux/drivers/md/Makefile Fri Sep 14 14:22:18 2001 @@ -17,6 +17,7 @@ obj-$(CONFIG_MD_RAID0) += raid0.o obj-$(CONFIG_MD_RAID1) += raid1.o obj-$(CONFIG_MD_RAID5) += raid5.o xor.o +obj-$(CONFIG_MD_MULTIPATH) += multipath.o obj-$(CONFIG_BLK_DEV_MD) += md.o obj-$(CONFIG_BLK_DEV_LVM) += lvm-mod.o diff -u --recursive --new-file v2.4.9/linux/drivers/md/lvm-snap.c linux/drivers/md/lvm-snap.c --- v2.4.9/linux/drivers/md/lvm-snap.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/md/lvm-snap.c Mon Sep 10 08:00:55 2001 @@ -386,8 +386,8 @@ blksize_org = lvm_get_blksize(org_phys_dev); blksize_snap = lvm_get_blksize(snap_phys_dev); - max_blksize = max(int, blksize_org, blksize_snap); - min_blksize = min(int, blksize_org, blksize_snap); + max_blksize = max(blksize_org, blksize_snap); + min_blksize = min(blksize_org, blksize_snap); max_sectors = KIO_MAX_SECTORS * (min_blksize>>9); if (chunk_size % (max_blksize>>9)) @@ -395,7 +395,7 @@ while (chunk_size) { - nr_sectors = min(int, chunk_size, max_sectors); + nr_sectors = min(chunk_size, max_sectors); chunk_size -= nr_sectors; iobuf->length = nr_sectors << 9; @@ -503,7 +503,7 @@ buckets = lv->lv_remap_end; max_buckets = calc_max_buckets(); - buckets = min(unsigned long, buckets, max_buckets); + buckets = min(buckets, max_buckets); while (buckets & (buckets-1)) buckets &= (buckets-1); 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 Mon Sep 17 13:25:26 2001 @@ -197,9 +197,13 @@ #include "lvm-snap.h" -#define LVM_CORRECT_READ_AHEAD( a) \ - if ( a < LVM_MIN_READ_AHEAD || \ - a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD; +#define LVM_CORRECT_READ_AHEAD(a) \ +do { \ + if ((a) < LVM_MIN_READ_AHEAD || \ + (a) > LVM_MAX_READ_AHEAD) \ + (a) = LVM_DEFAULT_READ_AHEAD; \ + read_ahead[MAJOR_NR] = (a); \ +} while(0) #ifndef WRITEA # define WRITEA WRITE @@ -376,17 +380,13 @@ {0,}; static struct gendisk lvm_gendisk = { - MAJOR_NR, /* major # */ - LVM_NAME, /* name of major */ - 0, /* number of times minor is shifted - to get real minor */ - 1, /* maximum partitions per device */ - lvm_hd_struct, /* partition table */ - lvm_size, /* device size in blocks, copied - to block_size[] */ - MAX_LV, /* number or real devices */ - NULL, /* internal */ - NULL, /* pointer to next gendisk struct (internal) */ + major: MAJOR_NR, + major_name: LVM_NAME, + minor_shift: 0, + max_p: 1, + part: lvm_hd_struct, + sizes: lvm_size, + nr_real: MAX_LV, }; /* @@ -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; @@ -906,6 +881,11 @@ return -EFAULT; break; + case BLKGETSIZE64: + if (put_user((u64)lv_ptr->lv_size << 9, (u64 *)arg)) + return -EFAULT; + break; + case BLKFLSBUF: /* flush buffer cache */ @@ -929,6 +909,7 @@ (long) arg > LVM_MAX_READ_AHEAD) return -EINVAL; lv_ptr->lv_read_ahead = (long) arg; + read_ahead[MAJOR_NR] = lv_ptr->lv_read_ahead; break; @@ -1059,7 +1040,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 Sun Sep 16 17:31:35 2001 @@ -46,9 +46,6 @@ #include -extern asmlinkage int sys_sched_yield(void); -extern asmlinkage long sys_setsid(void); - #define MAJOR_NR MD_MAJOR #define MD_DRIVER @@ -114,7 +111,7 @@ int md_size[MAX_MD_DEVS]; -extern struct block_device_operations md_fops; +static struct block_device_operations md_fops; static devfs_handle_t devfs_handle; static struct gendisk md_gendisk= @@ -222,18 +219,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 +266,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 +554,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; @@ -656,10 +641,9 @@ bdev = bdget(rdev->dev); if (bdev == NULL) return -ENOMEM; - err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FILE); - if (!err) { + err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW); + if (!err) rdev->bdev = bdev; - } return err; } @@ -667,7 +651,7 @@ { if (!rdev->bdev) MD_BUG(); - blkdev_put(rdev->bdev, BDEV_FILE); + blkdev_put(rdev->bdev, BDEV_RAW); bdput(rdev->bdev); rdev->bdev = NULL; } @@ -783,8 +767,10 @@ mdp_disk_t *desc; desc = sb->disks + i; - printk("md: D %2d: ", i); - print_desc(desc); + if (desc->number || desc->major || desc->minor || desc->raid_disk || (desc->state && (desc->state != 4))) { + printk(" D %2d: ", i); + print_desc(desc); + } } printk("md: THIS: "); print_desc(&sb->this_disk); @@ -842,6 +828,7 @@ if (!tmp1 || !tmp2) { ret = 0; + printk(KERN_INFO "md.c: sb1 is not equal to sb2!\n"); goto abort; } @@ -921,17 +908,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; } @@ -992,7 +981,7 @@ struct md_list_head *tmp; ITERATE_RDEV(mddev,rdev,tmp) { - if (rdev->faulty) + if (rdev->faulty || rdev->alias_device) continue; sb = rdev->sb; *sb = *mddev->sb; @@ -1039,8 +1028,11 @@ printk("md: "); if (rdev->faulty) printk("(skipping faulty "); + if (rdev->alias_device) + printk("(skipping alias "); + printk("%s ", partition_name(rdev->dev)); - if (!rdev->faulty) { + if (!rdev->faulty && !rdev->alias_device) { printk("[events: %08lx]", (unsigned long)rdev->sb->events_lo); err += write_disk_sb(rdev); @@ -1125,9 +1117,14 @@ goto abort_free; } - rdev->old_dev = MKDEV(rdev->sb->this_disk.major, - rdev->sb->this_disk.minor); - rdev->desc_nr = rdev->sb->this_disk.number; + if (rdev->sb->level != -4) { + rdev->old_dev = MKDEV(rdev->sb->this_disk.major, + rdev->sb->this_disk.minor); + rdev->desc_nr = rdev->sb->this_disk.number; + } else { + rdev->old_dev = MKDEV(0, 0); + rdev->desc_nr = -1; + } } md_list_add(&rdev->all, &all_raid_disks); MD_INIT_LIST_HEAD(&rdev->pending); @@ -1167,7 +1164,7 @@ static int analyze_sbs (mddev_t * mddev) { - int out_of_date = 0, i; + int out_of_date = 0, i, first; struct md_list_head *tmp, *tmp2; mdk_rdev_t *rdev, *rdev2, *freshest; mdp_super_t *sb; @@ -1261,7 +1258,7 @@ */ ITERATE_RDEV(mddev,rdev,tmp) { /* - * Kick all non-fresh devices faulty + * Kick all non-fresh devices */ __u64 ev1, ev2; ev1 = md_event(rdev->sb); @@ -1279,9 +1276,10 @@ * Fix up changed device names ... but only if this disk has a * recent update time. Use faulty checksum ones too. */ + if (mddev->sb->level != -4) ITERATE_RDEV(mddev,rdev,tmp) { __u64 ev1, ev2, ev3; - if (rdev->faulty) { /* REMOVEME */ + if (rdev->faulty || rdev->alias_device) { MD_BUG(); goto abort; } @@ -1290,7 +1288,7 @@ ev3 = ev2; --ev3; if ((rdev->dev != rdev->old_dev) && - ((ev1 == ev2) || (ev1 == ev3))) { + ((ev1 == ev2) || (ev1 == ev3))) { mdp_disk_t *desc; printk("md: device name has changed from %s to %s since last import!\n", partition_name(rdev->old_dev), partition_name(rdev->dev)); @@ -1329,8 +1327,13 @@ /* * We kick faulty devices/descriptors immediately. + * + * Note: multipath devices are a special case. Since we + * were able to read the superblock on the path, we don't + * care if it was previously marked as faulty, it's up now + * so enable it. */ - if (disk_faulty(desc)) { + if (disk_faulty(desc) && mddev->sb->level != -4) { found = 0; ITERATE_RDEV(mddev,rdev,tmp) { if (rdev->desc_nr != desc->number) @@ -1349,6 +1352,15 @@ } remove_descriptor(desc, sb); continue; + } else if (disk_faulty(desc)) { + /* + * multipath entry marked as faulty, unfaulty it + */ + rdev = find_rdev(mddev, dev); + if(rdev) + mark_disk_spare(desc); + else + remove_descriptor(desc, sb); } if (dev == MKDEV(0,0)) @@ -1358,6 +1370,17 @@ */ found = 0; ITERATE_RDEV(mddev,rdev,tmp) { + /* + * Multi-path IO special-case: since we have no + * this_disk descriptor at auto-detect time, + * we cannot check rdev->number. + * We can check the device though. + */ + if ((sb->level == -4) && (rdev->dev == + MKDEV(desc->major,desc->minor))) { + found = 1; + break; + } if (rdev->desc_nr == desc->number) { found = 1; break; @@ -1374,6 +1397,7 @@ * Double check wether all devices mentioned in the * superblock are in the rdev ring. */ + first = 1; for (i = 0; i < MD_SB_DISKS; i++) { mdp_disk_t *desc; kdev_t dev; @@ -1394,35 +1418,63 @@ MD_BUG(); goto abort; } - } - - /* - * Do a final reality check. - */ - ITERATE_RDEV(mddev,rdev,tmp) { - if (rdev->desc_nr == -1) { - MD_BUG(); - goto abort; - } /* - * is the desc_nr unique? + * In the case of Multipath-IO, we have no + * other information source to find out which + * disk is which, only the position of the device + * in the superblock: */ - ITERATE_RDEV(mddev,rdev2,tmp2) { - if ((rdev2 != rdev) && - (rdev2->desc_nr == rdev->desc_nr)) { + if (mddev->sb->level == -4) { + if ((rdev->desc_nr != -1) && (rdev->desc_nr != i)) { MD_BUG(); goto abort; } + rdev->desc_nr = i; + if (!first) + rdev->alias_device = 1; + else + first = 0; } - /* - * is the device unique? - */ - ITERATE_RDEV(mddev,rdev2,tmp2) { - if ((rdev2 != rdev) && - (rdev2->dev == rdev->dev)) { + } + + /* + * Kick all rdevs that are not in the + * descriptor array: + */ + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr == -1) + kick_rdev_from_array(rdev); + } + + /* + * Do a final reality check. + */ + if (mddev->sb->level != -4) { + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr == -1) { MD_BUG(); goto abort; } + /* + * is the desc_nr unique? + */ + ITERATE_RDEV(mddev,rdev2,tmp2) { + if ((rdev2 != rdev) && + (rdev2->desc_nr == rdev->desc_nr)) { + MD_BUG(); + goto abort; + } + } + /* + * is the device unique? + */ + ITERATE_RDEV(mddev,rdev2,tmp2) { + if ((rdev2 != rdev) && + (rdev2->dev == rdev->dev)) { + MD_BUG(); + goto abort; + } + } } } @@ -1483,6 +1535,9 @@ } switch (sb->level) { + case -4: + data_disks = 1; + break; case -3: data_disks = 1; break; @@ -1517,6 +1572,7 @@ if (readahead < data_disks * (MAX_SECTORS>>(PAGE_SHIFT-9))*2) readahead = data_disks * (MAX_SECTORS>>(PAGE_SHIFT-9))*2; } else { + // (no multipath branch - it uses the default setting) if (sb->level == -3) readahead = 0; } @@ -1579,38 +1635,41 @@ mddev->param.chunk_size = chunk_size; mddev->param.personality = pnum; - if (chunk_size > MAX_CHUNK_SIZE) { - printk(TOO_BIG_CHUNKSIZE, chunk_size, MAX_CHUNK_SIZE); - return -EINVAL; - } - /* - * chunk-size has to be a power of 2 and multiples of PAGE_SIZE - */ - if ( (1 << ffz(~chunk_size)) != chunk_size) { - MD_BUG(); - return -EINVAL; - } - if (chunk_size < PAGE_SIZE) { - printk(TOO_SMALL_CHUNKSIZE, chunk_size, PAGE_SIZE); - return -EINVAL; - } + if ((pnum != MULTIPATH) && (pnum != RAID1)) { + if (!chunk_size) { + /* + * 'default chunksize' in the old md code used to + * be PAGE_SIZE, baaad. + * we abort here to be on the safe side. We dont + * want to continue the bad practice. + */ + printk(BAD_CHUNKSIZE); + return -EINVAL; + } + if (chunk_size > MAX_CHUNK_SIZE) { + printk(TOO_BIG_CHUNKSIZE, chunk_size, MAX_CHUNK_SIZE); + return -EINVAL; + } + /* + * chunk-size has to be a power of 2 and multiples of PAGE_SIZE + */ + if ( (1 << ffz(~chunk_size)) != chunk_size) { + MD_BUG(); + return -EINVAL; + } + if (chunk_size < PAGE_SIZE) { + printk(TOO_SMALL_CHUNKSIZE, chunk_size, PAGE_SIZE); + return -EINVAL; + } + } else + if (chunk_size) + printk(KERN_INFO "md: RAID level %d does not need chunksize! Continuing anyway.\n", mddev->sb->level); if (pnum >= MAX_PERSONALITY) { MD_BUG(); return -EINVAL; } - if ((pnum != RAID1) && (pnum != LINEAR) && !chunk_size) { - /* - * 'default chunksize' in the old md code used to - * be PAGE_SIZE, baaad. - * we abort here to be on the safe side. We dont - * want to continue the bad practice. - */ - printk(BAD_CHUNKSIZE); - return -EINVAL; - } - if (!pers[pnum]) { #ifdef CONFIG_KMOD @@ -1619,7 +1678,11 @@ request_module (module_name); if (!pers[pnum]) #endif + { + printk(KERN_ERR "md: personality %d is not loaded!\n", + pnum); return -EINVAL; + } } if (device_size_calculation(mddev)) @@ -1637,7 +1700,7 @@ continue; invalidate_device(rdev->dev, 1); if (get_hardsect_size(rdev->dev) - > md_hardsect_sizes[mdidx(mddev)]) + > md_hardsect_sizes[mdidx(mddev)]) md_hardsect_sizes[mdidx(mddev)] = get_hardsect_size(rdev->dev); } @@ -1662,7 +1725,7 @@ */ md_hd_struct[mdidx(mddev)].start_sect = 0; register_disk(&md_gendisk, MKDEV(MAJOR_NR,mdidx(mddev)), - 1, &md_fops, md_size[mdidx(mddev)]<<1); + 1, &md_fops, md_size[mdidx(mddev)]<<1); read_ahead[MD_MAJOR] = 1024; return (0); @@ -1698,8 +1761,11 @@ md_recover_arrays(); if (mddev->pers->restart_resync) mddev->pers->restart_resync(mddev); - } else + } else { + printk (KERN_ERR "md: md%d has no personality assigned.\n", + mdidx(mddev)); err = -EINVAL; + } out: return err; @@ -1820,7 +1886,7 @@ ITERATE_RDEV(mddev,rdev,tmp) { printk("<%s>", partition_name(rdev->dev)); } - printk("\nmd: now!\n"); + printk("\n"); err = do_md_run (mddev); if (err) { @@ -2031,8 +2097,10 @@ { mdu_array_info_t info; - if (!mddev->sb) + if (!mddev->sb) { + MD_BUG(); return -EINVAL; + } SET_FROM_SB(major_version); SET_FROM_SB(minor_version); @@ -2119,7 +2187,7 @@ } if (mddev->nb_dev) { mdk_rdev_t *rdev0 = md_list_entry(mddev->disks.next, - mdk_rdev_t, same_set); + mdk_rdev_t, same_set); if (!uuid_equal(rdev0, rdev)) { printk("md: %s has different UUID to %s\n", partition_name(rdev->dev), partition_name(rdev0->dev)); export_rdev(rdev); @@ -2136,8 +2204,11 @@ } nr = info->number; - if (nr >= mddev->sb->nr_disks) + if (nr >= mddev->sb->nr_disks) { + MD_BUG(); return -EINVAL; + } + SET_SB(number); SET_SB(major); @@ -2165,8 +2236,6 @@ persistent = !mddev->sb->not_persistent; if (!persistent) printk("md: nonpersistent superblock ...\n"); - if (!mddev->sb->chunk_size) - printk("md: no chunksize?\n"); size = calc_dev_size(dev, mddev, persistent); rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent); @@ -2184,6 +2253,43 @@ } #undef SET_SB +static int hot_generate_error (mddev_t * mddev, kdev_t dev) +{ + struct request_queue *q; + mdk_rdev_t *rdev; + mdp_disk_t *disk; + + if (!mddev->pers) + return -ENODEV; + + printk("md: trying to generate %s error in md%d ... \n", + partition_name(dev), mdidx(mddev)); + + rdev = find_rdev(mddev, dev); + if (!rdev) { + MD_BUG(); + return -ENXIO; + } + + if (rdev->desc_nr == -1) { + MD_BUG(); + return -EINVAL; + } + disk = &mddev->sb->disks[rdev->desc_nr]; + if (!disk_active(disk)) + return -ENODEV; + + q = blk_get_queue(rdev->dev); + if (!q) { + MD_BUG(); + return -ENODEV; + } + printk("md: okay, generating error!\n"); +// q->oneshot_error = 1; // disabled for now + + return 0; +} + static int hot_remove_disk (mddev_t * mddev, kdev_t dev) { int err; @@ -2211,16 +2317,20 @@ return -EINVAL; } disk = &mddev->sb->disks[rdev->desc_nr]; - if (disk_active(disk)) + if (disk_active(disk)) { + MD_BUG(); goto busy; + } if (disk_removed(disk)) { MD_BUG(); return -EINVAL; } err = mddev->pers->diskop(mddev, &disk, DISKOP_HOT_REMOVE_DISK); - if (err == -EBUSY) + if (err == -EBUSY) { + MD_BUG(); goto busy; + } if (err) { MD_BUG(); return -EINVAL; @@ -2435,7 +2545,6 @@ { int ret; - fsync_dev(mddev_to_kdev(mddev)); ret = md_error(mddev, dev); return ret; } @@ -2454,8 +2563,10 @@ dev = inode->i_rdev; minor = MINOR(dev); - if (minor >= MAX_MD_DEVS) + if (minor >= MAX_MD_DEVS) { + MD_BUG(); return -EINVAL; + } /* * Commands dealing with the RAID driver but not any @@ -2479,36 +2590,29 @@ goto done; #endif - case BLKGETSIZE: /* Return device size */ + case BLKGETSIZE: /* Return device size */ if (!arg) { err = -EINVAL; + MD_BUG(); goto abort; } err = md_put_user(md_hd_struct[minor].nr_sects, (long *) arg); goto done; - case BLKFLSBUF: - fsync_dev(dev); - invalidate_buffers(dev); + case BLKGETSIZE64: /* Return device size */ + err = md_put_user((u64)md_hd_struct[minor].nr_sects << 9, + (u64 *) arg); 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:; } @@ -2551,7 +2655,7 @@ if (mddev->sb) { printk("md: array md%d already has a superblock!\n", - mdidx(mddev)); + mdidx(mddev)); err = -EBUSY; goto abort_unlock; } @@ -2680,6 +2784,9 @@ err = add_new_disk(mddev, &info); goto done_unlock; } + case HOT_GENERATE_ERROR: + err = hot_generate_error(mddev, (kdev_t)arg); + goto done_unlock; case HOT_REMOVE_DISK: err = hot_remove_disk(mddev, (kdev_t)arg); goto done_unlock; @@ -2780,7 +2887,6 @@ int md_thread(void * arg) { mdk_thread_t *thread = arg; - struct completion *event; md_lock_kernel(); @@ -2826,7 +2932,8 @@ remove_wait_queue(&thread->wqueue, &wait); clear_bit(THREAD_WAKEUP, &thread->flags); - if ((run=thread->run)) { + run = thread->run; + if (run) { run(thread->data); run_task_queue(&tq_disk); } @@ -2921,10 +3028,10 @@ 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) { + || mddev->pers->error_handler(mddev,rdev) <= 0) { free_disk_sb(rrdev); rrdev->faulty = 1; } else @@ -3100,28 +3207,34 @@ int register_md_personality (int pnum, mdk_personality_t *p) { - if (pnum >= MAX_PERSONALITY) + if (pnum >= MAX_PERSONALITY) { + MD_BUG(); return -EINVAL; + } - if (pers[pnum]) + if (pers[pnum]) { + MD_BUG(); return -EBUSY; + } pers[pnum] = p; - printk(KERN_INFO "md: %s personality registered\n", p->name); + printk(KERN_INFO "md: %s personality registered as nr %d\n", p->name, pnum); return 0; } int unregister_md_personality (int pnum) { - if (pnum >= MAX_PERSONALITY) + if (pnum >= MAX_PERSONALITY) { + MD_BUG(); return -EINVAL; + } printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name); pers[pnum] = NULL; return 0; } -static mdp_disk_t *get_spare(mddev_t *mddev) +mdp_disk_t *get_spare(mddev_t *mddev) { mdp_super_t *sb = mddev->sb; mdp_disk_t *disk; @@ -3224,7 +3337,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 +3399,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 +3436,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 +3448,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; @@ -3452,7 +3566,7 @@ mddev_t *mddev; if ((code == MD_SYS_DOWN) || (code == MD_SYS_HALT) - || (code == MD_SYS_POWER_OFF)) { + || (code == MD_SYS_POWER_OFF)) { printk(KERN_INFO "md: stopping all md devices.\n"); @@ -3470,9 +3584,9 @@ } struct notifier_block md_notifier = { - md_notify_reboot, - NULL, - 0 + notifier_call: md_notify_reboot, + next: NULL, + priority: INT_MAX, /* before any real devices */ }; static void md_geninit (void) @@ -3526,9 +3640,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) @@ -3584,7 +3697,7 @@ if (md_import_device(dev,1)) { printk(KERN_ALERT "md: could not import %s!\n", - partition_name(dev)); + partition_name(dev)); continue; } /* @@ -3653,7 +3766,7 @@ case 2: /* could be 0 or -1.. */ if (level == 0 || level == -1) { if (get_option(&str, &factor) != 2 || /* Chunk Size */ - get_option(&str, &fault) != 2) { + get_option(&str, &fault) != 2) { printk("md: Too few arguments supplied to md=.\n"); return 0; } @@ -3717,7 +3830,7 @@ dev = name_to_kdev_t(devname); handle = devfs_find_handle(NULL, devname, MAJOR (dev), MINOR (dev), - DEVFS_SPECIAL_BLK, 1); + DEVFS_SPECIAL_BLK, 1); if (handle != 0) { unsigned major, minor; devfs_get_maj_min(handle, &major, &minor); @@ -3759,7 +3872,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 +3967,6 @@ void cleanup_module (void) { - struct gendisk **gendisk_ptr; - md_unregister_thread(md_recovery_thread); devfs_unregister(devfs_handle); @@ -3865,15 +3976,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; @@ -3903,4 +4008,5 @@ MD_EXPORT_SYMBOL(md_interrupt_thread); MD_EXPORT_SYMBOL(mddev_map); MD_EXPORT_SYMBOL(md_check_ordering); +MD_EXPORT_SYMBOL(get_spare); diff -u --recursive --new-file v2.4.9/linux/drivers/md/multipath.c linux/drivers/md/multipath.c --- v2.4.9/linux/drivers/md/multipath.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/md/multipath.c Fri Sep 14 14:22:18 2001 @@ -0,0 +1,1261 @@ +/* + * multipath.c : Multiple Devices driver for Linux + * + * Copyright (C) 1999, 2000, 2001 Ingo Molnar, Red Hat + * + * Copyright (C) 1996, 1997, 1998 Ingo Molnar, Miguel de Icaza, Gadi Oxman + * + * MULTIPATH management functions. + * + * Better read-balancing code written by Mika Kuoppala , 2000 + * + * Fixes to reconstruction by Jakob Østergaard" + * Various fixes by Neil Brown + * + * 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. + * + * You should have received a copy of the GNU General Public License + * (for example /usr/src/linux/COPYING); if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#define MAJOR_NR MD_MAJOR +#define MD_DRIVER +#define MD_PERSONALITY + +#define MAX_WORK_PER_DISK 128 + +/* + * The following can be used to debug the driver + */ +#define MULTIPATH_DEBUG 0 + +#if MULTIPATH_DEBUG +#define PRINTK(x...) printk(x) +#define inline +#define __inline__ +#else +#define PRINTK(x...) do { } while (0) +#endif + + +static mdk_personality_t multipath_personality; +static md_spinlock_t retry_list_lock = MD_SPIN_LOCK_UNLOCKED; +struct multipath_bh *multipath_retry_list = NULL, **multipath_retry_tail; + +static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state); + +struct buffer_head *multipath_alloc_bh(multipath_conf_t *conf, int cnt) +{ + /* return a linked list of "cnt" struct buffer_heads. + * don't take any off the free list unless we know we can + * get all we need, otherwise we could deadlock + */ + struct buffer_head *bh=NULL; + + while(cnt) { + struct buffer_head *t; + md_spin_lock_irq(&conf->device_lock); + if (conf->freebh_cnt >= cnt) + while (cnt) { + t = conf->freebh; + conf->freebh = t->b_next; + t->b_next = bh; + bh = t; + t->b_state = 0; + conf->freebh_cnt--; + cnt--; + } + md_spin_unlock_irq(&conf->device_lock); + if (cnt == 0) + break; + t = (struct buffer_head *)kmalloc(sizeof(struct buffer_head), GFP_NOIO); + if (t) { + memset(t, 0, sizeof(*t)); + t->b_next = bh; + bh = t; + cnt--; + } else { + PRINTK("waiting for %d bh\n", cnt); + wait_event(conf->wait_buffer, conf->freebh_cnt >= cnt); + } + } + return bh; +} + +static inline void multipath_free_bh(multipath_conf_t *conf, struct buffer_head *bh) +{ + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); + while (bh) { + struct buffer_head *t = bh; + bh=bh->b_next; + if (t->b_pprev == NULL) + kfree(t); + else { + t->b_next= conf->freebh; + conf->freebh = t; + conf->freebh_cnt++; + } + } + spin_unlock_irqrestore(&conf->device_lock, flags); + wake_up(&conf->wait_buffer); +} + +static int multipath_grow_bh(multipath_conf_t *conf, int cnt) +{ + /* allocate cnt buffer_heads, possibly less if kalloc fails */ + int i = 0; + + while (i < cnt) { + struct buffer_head *bh; + bh = kmalloc(sizeof(*bh), GFP_KERNEL); + if (!bh) break; + memset(bh, 0, sizeof(*bh)); + + md_spin_lock_irq(&conf->device_lock); + bh->b_pprev = &conf->freebh; + bh->b_next = conf->freebh; + conf->freebh = bh; + conf->freebh_cnt++; + md_spin_unlock_irq(&conf->device_lock); + + i++; + } + return i; +} + +static int multipath_shrink_bh(multipath_conf_t *conf, int cnt) +{ + /* discard cnt buffer_heads, if we can find them */ + int i = 0; + + md_spin_lock_irq(&conf->device_lock); + while ((i < cnt) && conf->freebh) { + struct buffer_head *bh = conf->freebh; + conf->freebh = bh->b_next; + kfree(bh); + i++; + conf->freebh_cnt--; + } + md_spin_unlock_irq(&conf->device_lock); + return i; +} + + +static struct multipath_bh *multipath_alloc_mpbh(multipath_conf_t *conf) +{ + struct multipath_bh *r1_bh = NULL; + + do { + md_spin_lock_irq(&conf->device_lock); + if (conf->freer1) { + r1_bh = conf->freer1; + conf->freer1 = r1_bh->next_r1; + r1_bh->next_r1 = NULL; + r1_bh->state = 0; + r1_bh->bh_req.b_state = 0; + } + md_spin_unlock_irq(&conf->device_lock); + if (r1_bh) + return r1_bh; + r1_bh = (struct multipath_bh *) kmalloc(sizeof(struct multipath_bh), + GFP_NOIO); + if (r1_bh) { + memset(r1_bh, 0, sizeof(*r1_bh)); + return r1_bh; + } + wait_event(conf->wait_buffer, conf->freer1); + } while (1); +} + +static inline void multipath_free_mpbh(struct multipath_bh *r1_bh) +{ + struct buffer_head *bh = r1_bh->multipath_bh_list; + multipath_conf_t *conf = mddev_to_conf(r1_bh->mddev); + + r1_bh->multipath_bh_list = NULL; + + if (test_bit(MPBH_PreAlloc, &r1_bh->state)) { + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); + r1_bh->next_r1 = conf->freer1; + conf->freer1 = r1_bh; + spin_unlock_irqrestore(&conf->device_lock, flags); + } else { + kfree(r1_bh); + } + multipath_free_bh(conf, bh); +} + +static int multipath_grow_mpbh (multipath_conf_t *conf, int cnt) +{ + int i = 0; + + while (i < cnt) { + struct multipath_bh *r1_bh; + r1_bh = (struct multipath_bh*)kmalloc(sizeof(*r1_bh), GFP_KERNEL); + if (!r1_bh) + break; + memset(r1_bh, 0, sizeof(*r1_bh)); + + md_spin_lock_irq(&conf->device_lock); + set_bit(MPBH_PreAlloc, &r1_bh->state); + r1_bh->next_r1 = conf->freer1; + conf->freer1 = r1_bh; + md_spin_unlock_irq(&conf->device_lock); + + i++; + } + return i; +} + +static void multipath_shrink_mpbh(multipath_conf_t *conf) +{ + md_spin_lock_irq(&conf->device_lock); + while (conf->freer1) { + struct multipath_bh *r1_bh = conf->freer1; + conf->freer1 = r1_bh->next_r1; + kfree(r1_bh); + } + md_spin_unlock_irq(&conf->device_lock); +} + + + +static inline void multipath_free_buf(struct multipath_bh *r1_bh) +{ + unsigned long flags; + struct buffer_head *bh = r1_bh->multipath_bh_list; + multipath_conf_t *conf = mddev_to_conf(r1_bh->mddev); + r1_bh->multipath_bh_list = NULL; + + spin_lock_irqsave(&conf->device_lock, flags); + r1_bh->next_r1 = conf->freebuf; + conf->freebuf = r1_bh; + spin_unlock_irqrestore(&conf->device_lock, flags); + multipath_free_bh(conf, bh); +} + +static int multipath_map (mddev_t *mddev, kdev_t *rdev) +{ + multipath_conf_t *conf = mddev_to_conf(mddev); + int i, disks = MD_SB_DISKS; + + /* + * Later we do read balancing on the read side + * now we use the first available disk. + */ + + for (i = 0; i < disks; i++) { + if (conf->multipaths[i].operational) { + *rdev = conf->multipaths[i].dev; + return (0); + } + } + + printk (KERN_ERR "multipath_map(): no more operational IO paths?\n"); + return (-1); +} + +static void multipath_reschedule_retry (struct multipath_bh *r1_bh) +{ + unsigned long flags; + mddev_t *mddev = r1_bh->mddev; + multipath_conf_t *conf = mddev_to_conf(mddev); + + md_spin_lock_irqsave(&retry_list_lock, flags); + if (multipath_retry_list == NULL) + multipath_retry_tail = &multipath_retry_list; + *multipath_retry_tail = r1_bh; + multipath_retry_tail = &r1_bh->next_r1; + r1_bh->next_r1 = NULL; + md_spin_unlock_irqrestore(&retry_list_lock, flags); + md_wakeup_thread(conf->thread); +} + + +static void inline io_request_done(unsigned long sector, multipath_conf_t *conf, int phase) +{ + unsigned long flags; + spin_lock_irqsave(&conf->segment_lock, flags); + if (sector < conf->start_active) + conf->cnt_done--; + else if (sector >= conf->start_future && conf->phase == phase) + conf->cnt_future--; + else if (!--conf->cnt_pending) + wake_up(&conf->wait_ready); + + spin_unlock_irqrestore(&conf->segment_lock, flags); +} + +static void inline sync_request_done (unsigned long sector, multipath_conf_t *conf) +{ + unsigned long flags; + spin_lock_irqsave(&conf->segment_lock, flags); + if (sector >= conf->start_ready) + --conf->cnt_ready; + else if (sector >= conf->start_active) { + if (!--conf->cnt_active) { + conf->start_active = conf->start_ready; + wake_up(&conf->wait_done); + } + } + spin_unlock_irqrestore(&conf->segment_lock, flags); +} + +/* + * multipath_end_bh_io() is called when we have finished servicing a multipathed + * operation and are ready to return a success/failure code to the buffer + * cache layer. + */ +static void multipath_end_bh_io (struct multipath_bh *r1_bh, int uptodate) +{ + struct buffer_head *bh = r1_bh->master_bh; + + io_request_done(bh->b_rsector, mddev_to_conf(r1_bh->mddev), + test_bit(MPBH_SyncPhase, &r1_bh->state)); + + bh->b_end_io(bh, uptodate); + multipath_free_mpbh(r1_bh); +} + +void multipath_end_request (struct buffer_head *bh, int uptodate) +{ + struct multipath_bh * r1_bh = (struct multipath_bh *)(bh->b_private); + + /* + * this branch is our 'one multipath IO has finished' event handler: + */ + if (!uptodate) + md_error (r1_bh->mddev, bh->b_dev); + else + /* + * Set MPBH_Uptodate in our master buffer_head, so that + * we will return a good error code for to the higher + * levels even if IO on some other multipathed buffer fails. + * + * The 'master' represents the complex operation to + * user-side. So if something waits for IO, then it will + * wait for the 'master' buffer_head. + */ + set_bit (MPBH_Uptodate, &r1_bh->state); + + + if (uptodate) { + multipath_end_bh_io(r1_bh, uptodate); + return; + } + /* + * oops, IO error: + */ + printk(KERN_ERR "multipath: %s: rescheduling block %lu\n", + partition_name(bh->b_dev), bh->b_blocknr); + multipath_reschedule_retry(r1_bh); + return; +} + +/* + * This routine returns the disk from which the requested read should + * be done. It bookkeeps the last read position for every disk + * in array and when new read requests come, the disk which last + * position is nearest to the request, is chosen. + * + * TODO: now if there are 2 multipaths in the same 2 devices, performance + * degrades dramatically because position is multipath, not device based. + * This should be changed to be device based. Also atomic sequential + * reads should be somehow balanced. + */ + +static int multipath_read_balance (multipath_conf_t *conf) +{ + int disk; + + for (disk = 0; disk < conf->raid_disks; disk++) + if (conf->multipaths[disk].operational) + return disk; + BUG(); + return 0; +} + +static int multipath_make_request (mddev_t *mddev, int rw, + struct buffer_head * bh) +{ + multipath_conf_t *conf = mddev_to_conf(mddev); + struct buffer_head *bh_req; + struct multipath_bh * r1_bh; + struct multipath_info *multipath; + + if (!buffer_locked(bh)) + BUG(); + +/* + * make_request() can abort the operation when READA is being + * used and no empty request is available. + * + * Currently, just replace the command with READ/WRITE. + */ + if (rw == READA) + rw = READ; + + r1_bh = multipath_alloc_mpbh (conf); + + spin_lock_irq(&conf->segment_lock); + wait_event_lock_irq(conf->wait_done, + bh->b_rsector < conf->start_active || + bh->b_rsector >= conf->start_future, + conf->segment_lock); + if (bh->b_rsector < conf->start_active) + conf->cnt_done++; + else { + conf->cnt_future++; + if (conf->phase) + set_bit(MPBH_SyncPhase, &r1_bh->state); + } + spin_unlock_irq(&conf->segment_lock); + + /* + * i think the read and write branch should be separated completely, + * since we want to do read balancing on the read side for example. + * Alternative implementations? :) --mingo + */ + + r1_bh->master_bh = bh; + r1_bh->mddev = mddev; + r1_bh->cmd = rw; + + /* + * read balancing logic: + */ + multipath = conf->multipaths + multipath_read_balance(conf); + + bh_req = &r1_bh->bh_req; + memcpy(bh_req, bh, sizeof(*bh)); + bh_req->b_blocknr = bh->b_rsector; + bh_req->b_dev = multipath->dev; + bh_req->b_rdev = multipath->dev; +/* bh_req->b_rsector = bh->n_rsector; */ + bh_req->b_end_io = multipath_end_request; + bh_req->b_private = r1_bh; + generic_make_request (rw, bh_req); + return 0; +} + +static int multipath_status (char *page, mddev_t *mddev) +{ + multipath_conf_t *conf = mddev_to_conf(mddev); + int sz = 0, i; + + sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, + conf->working_disks); + for (i = 0; i < conf->raid_disks; i++) + sz += sprintf (page+sz, "%s", + conf->multipaths[i].operational ? "U" : "_"); + sz += sprintf (page+sz, "]"); + return sz; +} + +#define LAST_DISK KERN_ALERT \ +"multipath: only one IO path left and IO error.\n" + +#define NO_SPARE_DISK KERN_ALERT \ +"multipath: no spare IO path left!\n" + +#define DISK_FAILED KERN_ALERT \ +"multipath: IO failure on %s, disabling IO path. \n" \ +" Operation continuing on %d IO paths.\n" + +static void mark_disk_bad (mddev_t *mddev, int failed) +{ + multipath_conf_t *conf = mddev_to_conf(mddev); + struct multipath_info *multipath = conf->multipaths+failed; + mdp_super_t *sb = mddev->sb; + + multipath->operational = 0; + mark_disk_faulty(sb->disks+multipath->number); + mark_disk_nonsync(sb->disks+multipath->number); + mark_disk_inactive(sb->disks+multipath->number); + sb->active_disks--; + sb->working_disks--; + sb->failed_disks++; + mddev->sb_dirty = 1; + md_wakeup_thread(conf->thread); + conf->working_disks--; + printk (DISK_FAILED, partition_name (multipath->dev), + conf->working_disks); +} + +/* + * Careful, this can execute in IRQ contexts as well! + */ +static int multipath_error (mddev_t *mddev, kdev_t dev) +{ + multipath_conf_t *conf = mddev_to_conf(mddev); + struct multipath_info * multipaths = conf->multipaths; + int disks = MD_SB_DISKS; + int other_paths = 1; + int i; + + if (conf->working_disks == 1) { + other_paths = 0; + for (i = 0; i < disks; i++) { + if (multipaths[i].spare) { + other_paths = 1; + break; + } + } + } + + if (!other_paths) { + /* + * Uh oh, we can do nothing if this is our last path, but + * first check if this is a queued request for a device + * which has just failed. + */ + for (i = 0; i < disks; i++) { + if (multipaths[i].dev==dev && !multipaths[i].operational) + return 0; + } + printk (LAST_DISK); + } else { + /* + * Mark disk as unusable + */ + for (i = 0; i < disks; i++) { + if (multipaths[i].dev==dev && multipaths[i].operational) { + mark_disk_bad(mddev, i); + break; + } + } + if (!conf->working_disks) { + int err = 1; + mdp_disk_t *spare; + mdp_super_t *sb = mddev->sb; + +// MD_BUG(); + spare = get_spare(mddev); + if (spare) { + err = multipath_diskop(mddev, &spare, DISKOP_SPARE_WRITE); + printk("got DISKOP_SPARE_WRITE err: %d. (spare_faulty(): %d)\n", err, disk_faulty(spare)); +// MD_BUG(); + } + if (!err && !disk_faulty(spare)) { + multipath_diskop(mddev, &spare, DISKOP_SPARE_ACTIVE); + mark_disk_sync(spare); + mark_disk_active(spare); + sb->active_disks++; + sb->spare_disks--; +// MD_BUG(); + } + } + } + return 0; +} + +#undef LAST_DISK +#undef NO_SPARE_DISK +#undef DISK_FAILED + + +static void print_multipath_conf (multipath_conf_t *conf) +{ + int i; + struct multipath_info *tmp; + + printk("MULTIPATH conf printout:\n"); + if (!conf) { + printk("(conf==NULL)\n"); + return; + } + printk(" --- wd:%d rd:%d nd:%d\n", conf->working_disks, + conf->raid_disks, conf->nr_disks); + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->multipaths + i; + if (tmp->spare || tmp->operational || tmp->number || + tmp->raid_disk || tmp->used_slot) + printk(" disk%d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", + i, tmp->spare,tmp->operational, + tmp->number,tmp->raid_disk,tmp->used_slot, + partition_name(tmp->dev)); + } +} + +static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state) +{ + int err = 0; + int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; + multipath_conf_t *conf = mddev->private; + struct multipath_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *failed_desc, *spare_desc, *added_desc; + mdk_rdev_t *spare_rdev, *failed_rdev; + + print_multipath_conf(conf); + md_spin_lock_irq(&conf->device_lock); + /* + * find the disk ... + */ + switch (state) { + + case DISKOP_SPARE_ACTIVE: + + /* + * Find the failed disk within the MULTIPATH configuration ... + * (this can only be in the first conf->working_disks part) + */ + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->multipaths + i; + if ((!tmp->operational && !tmp->spare) || + !tmp->used_slot) { + failed_disk = i; + break; + } + } + /* + * When we activate a spare disk we _must_ have a disk in + * the lower (active) part of the array to replace. + */ + if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + /* fall through */ + + case DISKOP_SPARE_WRITE: + case DISKOP_SPARE_INACTIVE: + + /* + * Find the spare disk ... (can only be in the 'high' + * area of the array) + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->multipaths + i; + if (tmp->spare && tmp->number == (*d)->number) { + spare_disk = i; + break; + } + } + if (spare_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_REMOVE_DISK: + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->multipaths + i; + if (tmp->used_slot && (tmp->number == (*d)->number)) { + if (tmp->operational) { + printk(KERN_ERR "hot-remove-disk, slot %d is identified to be the requested disk (number %d), but is still operational!\n", i, (*d)->number); + err = -EBUSY; + goto abort; + } + removed_disk = i; + break; + } + } + if (removed_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_ADD_DISK: + + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->multipaths + i; + if (!tmp->used_slot) { + added_disk = i; + break; + } + } + if (added_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + } + + switch (state) { + /* + * Switch the spare disk to write-only mode: + */ + case DISKOP_SPARE_WRITE: + sdisk = conf->multipaths + spare_disk; + sdisk->operational = 1; + sdisk->write_only = 1; + break; + /* + * Deactivate a spare disk: + */ + case DISKOP_SPARE_INACTIVE: + sdisk = conf->multipaths + spare_disk; + sdisk->operational = 0; + sdisk->write_only = 0; + break; + /* + * Activate (mark read-write) the (now sync) spare disk, + * which means we switch it's 'raid position' (->raid_disk) + * with the failed disk. (only the first 'conf->nr_disks' + * slots are used for 'real' disks and we must preserve this + * property) + */ + case DISKOP_SPARE_ACTIVE: + sdisk = conf->multipaths + spare_disk; + fdisk = conf->multipaths + failed_disk; + + spare_desc = &sb->disks[sdisk->number]; + failed_desc = &sb->disks[fdisk->number]; + + if (spare_desc != *d) { + MD_BUG(); + err = 1; + goto abort; + } + + if (spare_desc->raid_disk != sdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (sdisk->raid_disk != spare_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (failed_desc->raid_disk != fdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (fdisk->raid_disk != failed_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + /* + * do the switch finally + */ + spare_rdev = find_rdev_nr(mddev, spare_desc->number); + failed_rdev = find_rdev_nr(mddev, failed_desc->number); + xchg_values(spare_rdev->desc_nr, failed_rdev->desc_nr); +// if (failed_rdev->alias_device) +// MD_BUG(); +// if (!spare_rdev->alias_device) +// MD_BUG(); + spare_rdev->alias_device = 0; + failed_rdev->alias_device = 1; + + xchg_values(*spare_desc, *failed_desc); + xchg_values(*fdisk, *sdisk); + + /* + * (careful, 'failed' and 'spare' are switched from now on) + * + * we want to preserve linear numbering and we want to + * give the proper raid_disk number to the now activated + * disk. (this means we switch back these values) + */ + + xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); + xchg_values(sdisk->raid_disk, fdisk->raid_disk); + xchg_values(spare_desc->number, failed_desc->number); + xchg_values(sdisk->number, fdisk->number); + + *d = failed_desc; + + if (sdisk->dev == MKDEV(0,0)) + sdisk->used_slot = 0; + /* + * this really activates the spare. + */ + fdisk->spare = 0; + fdisk->write_only = 0; + + /* + * if we activate a spare, we definitely replace a + * non-operational disk slot in the 'low' area of + * the disk array. + */ + + conf->working_disks++; + + break; + + case DISKOP_HOT_REMOVE_DISK: + rdisk = conf->multipaths + removed_disk; + + if (rdisk->spare && (removed_disk < conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + rdisk->dev = MKDEV(0,0); + rdisk->used_slot = 0; + conf->nr_disks--; + break; + + case DISKOP_HOT_ADD_DISK: + adisk = conf->multipaths + added_disk; + added_desc = *d; + + if (added_disk != added_desc->number) { + MD_BUG(); + err = 1; + goto abort; + } + + adisk->number = added_desc->number; + adisk->raid_disk = added_desc->raid_disk; + adisk->dev = MKDEV(added_desc->major,added_desc->minor); + + adisk->operational = 0; + adisk->write_only = 0; + adisk->spare = 1; + adisk->used_slot = 1; + adisk->head_position = 0; + conf->nr_disks++; + + break; + + default: + MD_BUG(); + err = 1; + goto abort; + } +abort: + md_spin_unlock_irq(&conf->device_lock); + + print_multipath_conf(conf); + return err; +} + + +#define IO_ERROR KERN_ALERT \ +"multipath: %s: unrecoverable IO read error for block %lu\n" + +#define REDIRECT_SECTOR KERN_ERR \ +"multipath: %s: redirecting sector %lu to another IO path\n" + +/* + * This is a kernel thread which: + * + * 1. Retries failed read operations on working multipaths. + * 2. Updates the raid superblock when problems encounter. + * 3. Performs writes following reads for array syncronising. + */ + +static void multipathd (void *data) +{ + struct multipath_bh *r1_bh; + struct buffer_head *bh; + unsigned long flags; + mddev_t *mddev; + kdev_t dev; + + + for (;;) { + md_spin_lock_irqsave(&retry_list_lock, flags); + r1_bh = multipath_retry_list; + if (!r1_bh) + break; + multipath_retry_list = r1_bh->next_r1; + md_spin_unlock_irqrestore(&retry_list_lock, flags); + + mddev = r1_bh->mddev; + if (mddev->sb_dirty) { + printk(KERN_INFO "dirty sb detected, updating.\n"); + mddev->sb_dirty = 0; + md_update_sb(mddev); + } + bh = &r1_bh->bh_req; + dev = bh->b_dev; + + multipath_map (mddev, &bh->b_dev); + if (bh->b_dev == dev) { + printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr); + multipath_end_bh_io(r1_bh, 0); + } else { + printk (REDIRECT_SECTOR, + partition_name(bh->b_dev), bh->b_blocknr); + bh->b_rdev = bh->b_dev; + bh->b_rsector = bh->b_blocknr; + generic_make_request (r1_bh->cmd, bh); + } + } + md_spin_unlock_irqrestore(&retry_list_lock, flags); +} +#undef IO_ERROR +#undef REDIRECT_SECTOR + +/* + * This will catch the scenario in which one of the multipaths was + * mounted as a normal device rather than as a part of a raid set. + * + * check_consistency is very personality-dependent, eg. RAID5 cannot + * do this check, it uses another method. + */ +static int __check_consistency (mddev_t *mddev, int row) +{ + multipath_conf_t *conf = mddev_to_conf(mddev); + int disks = MD_SB_DISKS; + kdev_t dev; + struct buffer_head *bh = NULL; + int i, rc = 0; + char *buffer = NULL; + + for (i = 0; i < disks; i++) { + if (!conf->multipaths[i].operational) + continue; + printk("(checking disk %d)\n",i); + dev = conf->multipaths[i].dev; + set_blocksize(dev, 4096); + if ((bh = bread(dev, row / 4, 4096)) == NULL) + break; + if (!buffer) { + buffer = (char *) __get_free_page(GFP_KERNEL); + if (!buffer) + break; + memcpy(buffer, bh->b_data, 4096); + } else if (memcmp(buffer, bh->b_data, 4096)) { + rc = 1; + break; + } + bforget(bh); + fsync_dev(dev); + invalidate_buffers(dev); + bh = NULL; + } + if (buffer) + free_page((unsigned long) buffer); + if (bh) { + dev = bh->b_dev; + bforget(bh); + fsync_dev(dev); + invalidate_buffers(dev); + } + return rc; +} + +static int check_consistency (mddev_t *mddev) +{ + if (__check_consistency(mddev, 0)) +/* + * we do not do this currently, as it's perfectly possible to + * have an inconsistent array when it's freshly created. Only + * newly written data has to be consistent. + */ + return 0; + + return 0; +} + +#define INVALID_LEVEL KERN_WARNING \ +"multipath: md%d: raid level not set to multipath IO (%d)\n" + +#define NO_SB KERN_ERR \ +"multipath: disabled IO path %s (couldn't access raid superblock)\n" + +#define ERRORS KERN_ERR \ +"multipath: disabled IO path %s (errors detected)\n" + +#define NOT_IN_SYNC KERN_ERR \ +"multipath: making IO path %s a spare path (not in sync)\n" + +#define INCONSISTENT KERN_ERR \ +"multipath: disabled IO path %s (inconsistent descriptor)\n" + +#define ALREADY_RUNNING KERN_ERR \ +"multipath: disabled IO path %s (multipath %d already operational)\n" + +#define OPERATIONAL KERN_INFO \ +"multipath: device %s operational as IO path %d\n" + +#define MEM_ERROR KERN_ERR \ +"multipath: couldn't allocate memory for md%d\n" + +#define SPARE KERN_INFO \ +"multipath: spare IO path %s\n" + +#define NONE_OPERATIONAL KERN_ERR \ +"multipath: no operational IO paths for md%d\n" + +#define SB_DIFFERENCES KERN_ERR \ +"multipath: detected IO path differences!\n" + +#define ARRAY_IS_ACTIVE KERN_INFO \ +"multipath: array md%d active with %d out of %d IO paths (%d spare IO paths)\n" + +#define THREAD_ERROR KERN_ERR \ +"multipath: couldn't allocate thread for md%d\n" + +static int multipath_run (mddev_t *mddev) +{ + multipath_conf_t *conf; + int i, j, disk_idx; + struct multipath_info *disk, *disk2; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *desc, *desc2; + mdk_rdev_t *rdev, *def_rdev = NULL; + struct md_list_head *tmp; + int start_recovery = 0, num_rdevs = 0; + + MOD_INC_USE_COUNT; + + if (sb->level != -4) { + printk(INVALID_LEVEL, mdidx(mddev), sb->level); + goto out; + } + /* + * copy the already verified devices into our private MULTIPATH + * bookkeeping area. [whatever we allocate in multipath_run(), + * should be freed in multipath_stop()] + */ + + conf = kmalloc(sizeof(multipath_conf_t), GFP_KERNEL); + mddev->private = conf; + if (!conf) { + printk(MEM_ERROR, mdidx(mddev)); + goto out; + } + memset(conf, 0, sizeof(*conf)); + + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) { + /* this is a "should never happen" case and if it */ + /* ever does happen, a continue; won't help */ + printk(ERRORS, partition_name(rdev->dev)); + continue; + } else { + /* this is a "should never happen" case and if it */ + /* ever does happen, a continue; won't help */ + if (!rdev->sb) { + MD_BUG(); + continue; + } + } + if (rdev->desc_nr == -1) { + MD_BUG(); + continue; + } + + desc = &sb->disks[rdev->desc_nr]; + disk_idx = desc->raid_disk; + disk = conf->multipaths + disk_idx; + + if (!disk_sync(desc)) + printk(NOT_IN_SYNC, partition_name(rdev->dev)); + + /* + * Mark all disks as spare to start with, then pick our + * active disk. If we have a disk that is marked active + * in the sb, then use it, else use the first rdev. + */ + disk->number = desc->number; + disk->raid_disk = desc->raid_disk; + disk->dev = rdev->dev; + disk->sect_limit = MAX_WORK_PER_DISK; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 1; + disk->used_slot = 1; + disk->head_position = 0; + mark_disk_sync(desc); + + if (disk_active(desc)) { + if(!conf->working_disks) { + printk(OPERATIONAL, partition_name(rdev->dev), + desc->raid_disk); + disk->operational = 1; + disk->spare = 0; + conf->working_disks++; + def_rdev = rdev; + } else { + mark_disk_spare(desc); + } + } else + mark_disk_spare(desc); + + if(!num_rdevs++) def_rdev = rdev; + } + if(!conf->working_disks && num_rdevs) { + desc = &sb->disks[def_rdev->desc_nr]; + disk = conf->multipaths + desc->raid_disk; + printk(OPERATIONAL, partition_name(def_rdev->dev), + disk->raid_disk); + disk->operational = 1; + disk->spare = 0; + conf->working_disks++; + mark_disk_active(desc); + } + /* + * Make sure our active path is in desc spot 0 + */ + if(def_rdev->desc_nr != 0) { + rdev = find_rdev_nr(mddev, 0); + desc = &sb->disks[def_rdev->desc_nr]; + desc2 = sb->disks; + disk = conf->multipaths + desc->raid_disk; + disk2 = conf->multipaths + desc2->raid_disk; + xchg_values(*desc2,*desc); + xchg_values(*disk2,*disk); + xchg_values(desc2->number, desc->number); + xchg_values(disk2->number, disk->number); + xchg_values(desc2->raid_disk, desc->raid_disk); + xchg_values(disk2->raid_disk, disk->raid_disk); + if(rdev) { + xchg_values(def_rdev->desc_nr,rdev->desc_nr); + } else { + def_rdev->desc_nr = 0; + } + } + conf->raid_disks = sb->raid_disks = sb->active_disks = 1; + conf->nr_disks = sb->nr_disks = sb->working_disks = num_rdevs; + sb->failed_disks = 0; + sb->spare_disks = num_rdevs - 1; + mddev->sb_dirty = 1; + conf->mddev = mddev; + conf->device_lock = MD_SPIN_LOCK_UNLOCKED; + + conf->segment_lock = MD_SPIN_LOCK_UNLOCKED; + init_waitqueue_head(&conf->wait_buffer); + init_waitqueue_head(&conf->wait_done); + init_waitqueue_head(&conf->wait_ready); + + if (!conf->working_disks) { + printk(NONE_OPERATIONAL, mdidx(mddev)); + goto out_free_conf; + } + + + /* pre-allocate some buffer_head structures. + * As a minimum, 1 mpbh and raid_disks buffer_heads + * would probably get us by in tight memory situations, + * but a few more is probably a good idea. + * For now, try 16 mpbh and 16*raid_disks bufferheads + * This will allow at least 16 concurrent reads or writes + * even if kmalloc starts failing + */ + if (multipath_grow_mpbh(conf, 16) < 16 || + multipath_grow_bh(conf, 16*conf->raid_disks)< 16*conf->raid_disks) { + printk(MEM_ERROR, mdidx(mddev)); + goto out_free_conf; + } + + if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN))) { + /* + * we do sanity checks even if the device says + * it's clean ... + */ + if (check_consistency(mddev)) { + printk(SB_DIFFERENCES); + sb->state &= ~(1 << MD_SB_CLEAN); + } + } + + { + const char * name = "multipathd"; + + conf->thread = md_register_thread(multipathd, conf, name); + if (!conf->thread) { + printk(THREAD_ERROR, mdidx(mddev)); + goto out_free_conf; + } + } + + /* + * Regenerate the "device is in sync with the raid set" bit for + * each device. + */ + for (i = 0; i < MD_SB_DISKS; i++) { + mark_disk_nonsync(sb->disks+i); + for (j = 0; j < sb->raid_disks; j++) { + if (sb->disks[i].number == conf->multipaths[j].number) + mark_disk_sync(sb->disks+i); + } + } + + printk(ARRAY_IS_ACTIVE, mdidx(mddev), sb->active_disks, + sb->raid_disks, sb->spare_disks); + /* + * Ok, everything is just fine now + */ + return 0; + +out_free_conf: + multipath_shrink_mpbh(conf); + multipath_shrink_bh(conf, conf->freebh_cnt); + kfree(conf); + mddev->private = NULL; +out: + MOD_DEC_USE_COUNT; + return -EIO; +} + +#undef INVALID_LEVEL +#undef NO_SB +#undef ERRORS +#undef NOT_IN_SYNC +#undef INCONSISTENT +#undef ALREADY_RUNNING +#undef OPERATIONAL +#undef SPARE +#undef NONE_OPERATIONAL +#undef SB_DIFFERENCES +#undef ARRAY_IS_ACTIVE + +static int multipath_stop (mddev_t *mddev) +{ + multipath_conf_t *conf = mddev_to_conf(mddev); + + md_unregister_thread(conf->thread); + multipath_shrink_mpbh(conf); + multipath_shrink_bh(conf, conf->freebh_cnt); + kfree(conf); + mddev->private = NULL; + MOD_DEC_USE_COUNT; + return 0; +} + +static mdk_personality_t multipath_personality= +{ + name: "multipath", + make_request: multipath_make_request, + run: multipath_run, + stop: multipath_stop, + status: multipath_status, + error_handler: multipath_error, + diskop: multipath_diskop, +}; + +static int md__init multipath_init (void) +{ + return register_md_personality (MULTIPATH, &multipath_personality); +} + +static void multipath_exit (void) +{ + unregister_md_personality (MULTIPATH); +} + +module_init(multipath_init); +module_exit(multipath_exit); + 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/saa7111.c linux/drivers/media/video/saa7111.c --- v2.4.9/linux/drivers/media/video/saa7111.c Sat May 19 17:43:06 2001 +++ linux/drivers/media/video/saa7111.c Thu Sep 13 15:21:32 2001 @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/media/video/saa7185.c linux/drivers/media/video/saa7185.c --- v2.4.9/linux/drivers/media/video/saa7185.c Sat May 19 17:43:06 2001 +++ linux/drivers/media/video/saa7185.c Thu Sep 13 15:21:32 2001 @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include 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/media/video/zr36067.c linux/drivers/media/video/zr36067.c --- v2.4.9/linux/drivers/media/video/zr36067.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/media/video/zr36067.c Sun Sep 9 10:45:43 2001 @@ -3734,7 +3734,6 @@ zr->window.chromakey = 0; zr->window.flags = 0; // RJ: Is this intended for interlace on/off ? zr->window.clips = NULL; - zr->window.clipcount = vw.clipcount; /* * If an overlay is running, we have to switch it off @@ -3775,7 +3774,8 @@ write_overlay_mask(zr, vcp, vw.clipcount); vfree(vcp); } - + zr->window.clipcount = vw.clipcount; + if (on) zr36057_overlay(zr, 1); zr->window_set = 1; diff -u --recursive --new-file v2.4.9/linux/drivers/media/video/zr36120.c linux/drivers/media/video/zr36120.c --- v2.4.9/linux/drivers/media/video/zr36120.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/media/video/zr36120.c Sun Sep 9 10:45:43 2001 @@ -1056,7 +1056,7 @@ DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm)); /* too many inputs? no decoder -> no channels */ - if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs) + if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs || v.channel < 0) return -EINVAL; if (v.norm != VIDEO_MODE_PAL && 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/chips/amd_flash.c linux/drivers/mtd/chips/amd_flash.c --- v2.4.9/linux/drivers/mtd/chips/amd_flash.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/mtd/chips/amd_flash.c Thu Sep 13 15:21:32 2001 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/mtd/devices/docecc.c linux/drivers/mtd/devices/docecc.c --- v2.4.9/linux/drivers/mtd/devices/docecc.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/mtd/devices/docecc.c Mon Sep 10 09:04:53 2001 @@ -402,7 +402,7 @@ den = 0; /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ - for (i = min(int, deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) { + for (i = min_t(int, deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) { if(lambda[i+1] != A0) den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])]; } diff -u --recursive --new-file v2.4.9/linux/drivers/mtd/devices/docprobe.c linux/drivers/mtd/devices/docprobe.c --- v2.4.9/linux/drivers/mtd/devices/docprobe.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/mtd/devices/docprobe.c Fri Sep 14 14:40:00 2001 @@ -70,7 +70,7 @@ static unsigned long __initdata doc_locations[] = { -#if defined (__alpha__) || defined(__i386__) +#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) #ifdef CONFIG_MTD_DOCPROBE_HIGH 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, 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 Mon Sep 10 12:42:32 2001 @@ -1174,10 +1174,10 @@ put_user(ftl_hd[minor].start_sect, (u_long *)&geo->start); break; case BLKGETSIZE: - ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(long)); - if (ret) return ret; - put_user(ftl_hd[minor].nr_sects, - (long *)arg); + ret = put_user(ftl_hd[minor].nr_sects, (long *)arg); + break; + case BLKGETSIZE64: + ret = put_user((u64)ftl_hd[minor].nr_sects << 9, (u64 *)arg); break; case BLKRRPART: ret = ftl_reread_partitions(minor); @@ -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/maps/Config.in linux/drivers/mtd/maps/Config.in --- v2.4.9/linux/drivers/mtd/maps/Config.in Tue Jul 3 17:08:20 2001 +++ linux/drivers/mtd/maps/Config.in Mon Sep 17 22:52:35 2001 @@ -13,19 +13,27 @@ int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2 fi -dep_tristate ' Sun Microsystems userflash support' CONFIG_MTD_SUN_UFLASH $CONFIG_SPARC64 -dep_tristate ' CFI Flash device mapped on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI +if [ "$CONFIG_SPARC" = "y" -o "$CONFIG_SPARC64" = "y" ]; then + dep_tristate ' Sun Microsystems userflash support' CONFIG_MTD_SUN_UFLASH $CONFIG_SPARC64 +fi +if [ "$CONFIG_ARM" = "y" ]; then + dep_tristate ' CFI Flash device mapped on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI +fi dep_tristate ' CFI Flash device mapped on Photron PNC-2000' CONFIG_MTD_PNC2000 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS dep_tristate ' CFI Flash device mapped on RPX Lite or CLLF' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI -dep_tristate ' CFI Flash device mapped on AMD SC520 CDP' CONFIG_MTD_SC520CDP $CONFIG_MTD_CFI -dep_tristate ' CFI Flash device mapped on AMD NetSc520' CONFIG_MTD_NETSC520 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS +if [ "$CONFIG_X86" = "y" ]; then + dep_tristate ' CFI Flash device mapped on AMD SC520 CDP' CONFIG_MTD_SC520CDP $CONFIG_MTD_CFI + dep_tristate ' CFI Flash device mapped on AMD NetSc520' CONFIG_MTD_NETSC520 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS +fi dep_tristate ' CFI Flash device mapped on Arcom SBC-GXx boards' CONFIG_MTD_SBC_GXX $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS dep_tristate ' CFI Flash device mapped on Arcom ELAN-104NC' CONFIG_MTD_ELAN_104NC $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS +if [ "$CONFIG_ARM" = "y" ]; then dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS dep_bool ' Support for RedBoot partition tables on SA11x0' CONFIG_MTD_SA1100_REDBOOT_PARTITIONS $CONFIG_MTD_SA1100 $CONFIG_MTD_REDBOOT_PARTS dep_bool ' Support for Compaq bootldr partition tables on SA11x0' CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS $CONFIG_MTD_SA1100 $CONFIG_MTD_BOOTLDR_PARTS -dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE $CONFIG_MTD_PARTITIONS -dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_XSCALE_IQ80310 + dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE $CONFIG_MTD_PARTITIONS + dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_XSCALE_IQ80310 +fi dep_tristate ' CFI Flash device mapped on D-Box2' CONFIG_MTD_DBOX2 $CONFIG_MTD_CFI_INTELSTD $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI_AMDSTD dep_tristate ' Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board' CONFIG_MTD_CSTM_MIPS_IXX $CONFIG_MTD_CFI $CONFIG_MTD_JEDEC $CONFIG_MTD_PARTITIONS if [ "$CONFIG_MTD_CSTM_MIPS_IXX" = "y" -o "$CONFIG_MTD_CSTM_MIPS_IXX" = "m" ]; then diff -u --recursive --new-file v2.4.9/linux/drivers/mtd/mtdblock.c linux/drivers/mtd/mtdblock.c --- v2.4.9/linux/drivers/mtd/mtdblock.c Sat Apr 28 11:27:54 2001 +++ linux/drivers/mtd/mtdblock.c Mon Sep 10 12:42:32 2001 @@ -529,10 +529,9 @@ switch (cmd) { case BLKGETSIZE: /* Return device size */ - if (!arg) - return -EFAULT; - return put_user((mtdblk->mtd->size >> 9), - (long *) arg)?-EFAULT:0; + return put_user((mtdblk->mtd->size >> 9), (long *) arg); + case BLKGETSIZE64: + return put_user((u64)mtdblk->mtd->size, (u64 *)arg); case BLKFLSBUF: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) diff -u --recursive --new-file v2.4.9/linux/drivers/mtd/mtdblock_ro.c linux/drivers/mtd/mtdblock_ro.c --- v2.4.9/linux/drivers/mtd/mtdblock_ro.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/mtd/mtdblock_ro.c Mon Sep 10 12:42:32 2001 @@ -211,9 +211,9 @@ switch (cmd) { case BLKGETSIZE: /* Return device size */ - if (!arg) return -EFAULT; - return Put_user((mtd->size >> 9), - (long *) arg); + return put_user((mtd->size >> 9), (long *) arg); + case BLKGETSIZE64: + return put_user((u64)mtd->size, (u64 *)arg); case BLKFLSBUF: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) diff -u --recursive --new-file v2.4.9/linux/drivers/mtd/nand/Config.in linux/drivers/mtd/nand/Config.in --- v2.4.9/linux/drivers/mtd/nand/Config.in Tue Jul 3 17:08:20 2001 +++ linux/drivers/mtd/nand/Config.in Mon Sep 17 22:52:35 2001 @@ -8,8 +8,8 @@ dep_tristate ' NAND Device Support' CONFIG_MTD_NAND $CONFIG_MTD if [ "$CONFIG_MTD_NAND" = "y" -o "$CONFIG_MTD_NAND" = "m" ]; then - bool ' Enable ECC correction algorithm' CONFIG_MTD_NAND_ECC y - bool ' Verify NAND page writes' CONFIG_MTD_NAND_VERIFY_WRITE y + bool ' Enable ECC correction algorithm' CONFIG_MTD_NAND_ECC + bool ' Verify NAND page writes' CONFIG_MTD_NAND_VERIFY_WRITE fi if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_P720T" = "y" ]; then dep_tristate ' NAND Flash device on SPIA board' CONFIG_MTD_NAND_SPIA $CONFIG_MTD_NAND 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 Mon Sep 10 12:42:32 2001 @@ -791,9 +791,11 @@ return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; } case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, (long *) arg); + case BLKGETSIZE64: + return put_user((u64)part_table[MINOR(inode->i_rdev)].nr_sects << 9, + (u64 *)arg); case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -1024,11 +1026,6 @@ * ****************************************************************************/ -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_nftl init_module -#define cleanup_nftl cleanup_module -#endif - static struct mtd_notifier nftl_notifier = { add: NFTL_notify_add, remove: NFTL_notify_remove @@ -1045,22 +1042,19 @@ #endif if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){ - printk("unable to register NFTL block device on major %d\n", MAJOR_NR); + printk("unable to register NFTL block device on major %d\n", + MAJOR_NR); return -EBUSY; } else { -#if LINUX_VERSION_CODE < 0x20320 - blk_dev[MAJOR_NR].request_fn = nftl_request; -#else blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); -#endif + /* set block size to 1kB each */ for (i = 0; i < 256; i++) { nftl_blocksizes[i] = 1024; } blksize_size[MAJOR_NR] = nftl_blocksizes; - nftl_gendisk.next = gendisk_head; - gendisk_head = &nftl_gendisk; + add_gendisk(&nftl_gendisk); } register_mtd_user(&nftl_notifier); @@ -1070,24 +1064,12 @@ static void __exit cleanup_nftl(void) { - struct gendisk *gd, **gdp; - unregister_mtd_user(&nftl_notifier); unregister_blkdev(MAJOR_NR, "nftl"); -#if LINUX_VERSION_CODE < 0x20320 - blk_dev[MAJOR_NR].request_fn = 0; -#else blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -#endif - /* 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/3c59x.c linux/drivers/net/3c59x.c --- v2.4.9/linux/drivers/net/3c59x.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/3c59x.c Mon Sep 17 13:16:30 2001 @@ -1299,14 +1299,9 @@ /* The 3c59x-specific entries in the device structure. */ dev->open = vortex_open; if (vp->full_bus_master_tx) { - struct sysinfo sysinfo; - dev->hard_start_xmit = boomerang_start_xmit; - si_meminfo(&sysinfo); - if (sysinfo.totalhigh == 0) { - /* Actually, it still should work with iommu. */ - dev->features |= NETIF_F_SG; - } + /* Actually, it still should work with iommu. */ + dev->features |= NETIF_F_SG; if (((hw_checksums[card_idx] == -1) && (vp->drv_flags & HAS_HWCKSM)) || (hw_checksums[card_idx] == 1)) { dev->features |= NETIF_F_IP_CSUM; 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/Config.in linux/drivers/net/Config.in --- v2.4.9/linux/drivers/net/Config.in Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/Config.in Mon Sep 17 22:52:35 2001 @@ -25,12 +25,13 @@ mainmenu_option next_comment comment 'Ethernet (10 or 100Mbit)' - bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET if [ "$CONFIG_NET_ETHERNET" = "y" ]; then - dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110 - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - source drivers/acorn/net/Config.in + if [ "$CONFIG_ARM" = "y" ]; then + dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110 + if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + source drivers/acorn/net/Config.in + fi fi if [ "$CONFIG_PPC" = "y" ]; then tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE @@ -48,12 +49,18 @@ tristate ' A2065 support' CONFIG_A2065 tristate ' Hydra support' CONFIG_HYDRA fi + if [ "$CONFIG_PARISC" = "y" ]; then + dep_tristate ' Lasi ethernet' CONFIG_LASI_82596 $CONFIG_GSC_LASI + fi if [ "$CONFIG_MIPS_JAZZ" = "y" ]; then tristate ' MIPS JAZZ onboard SONIC Ethernet support' CONFIG_MIPS_JAZZ_SONIC fi if [ "$CONFIG_MIPS_GT96100" = "y" ]; then bool ' MIPS GT96100 Ethernet support' CONFIG_MIPS_GT96100ETH fi + if [ "$CONFIG_MIPS_AU1000" = "y" ]; then + bool ' MIPS AU1000 Ethernet support' CONFIG_MIPS_AU1000_ENET + fi if [ "$CONFIG_SGI_IP27" = "y" ]; then bool ' SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH fi @@ -105,7 +112,7 @@ dep_tristate ' NI6510 support' CONFIG_NI65 $CONFIG_ISA fi if [ "$CONFIG_ISA" = "y" -o "$CONFIG_MCA" = "y" ]; then - dep_tristate ' AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 $CONFIG_EXPERIMENTAL + dep_tristate ' AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 $CONFIG_EXPERIMENTAL fi if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" -o "$CONFIG_MCA" = "y" ]; then tristate ' DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA @@ -124,6 +131,7 @@ fi tristate ' HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS tristate ' HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN + tristate ' LP486E on board Ethernet' CONFIG_LP486E tristate ' ICL EtherTeam 16i/32 support' CONFIG_ETH16I tristate ' NE2000/NE1000 support' CONFIG_NE2000 if [ "$CONFIG_OBSOLETE" = "y" ]; then @@ -138,10 +146,10 @@ tristate ' NE/2 (ne2000 MCA version) support' CONFIG_NE2_MCA tristate ' IBM LAN Adapter/A support' CONFIG_IBMLANA fi - if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then - bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" -o "$CONFIG_PCI" = "y" ]; then + bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI else - define_bool CONFIG_NET_PCI n + define_bool CONFIG_NET_PCI n fi if [ "$CONFIG_NET_PCI" = "y" ]; then dep_tristate ' AMD PCnet32 PCI support' CONFIG_PCNET32 $CONFIG_PCI @@ -153,8 +161,10 @@ dep_tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT $CONFIG_ISA dep_tristate ' CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA dep_tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI - dep_mbool ' New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL $CONFIG_TULIP - dep_mbool ' Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO $CONFIG_TULIP + if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then + dep_bool ' New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL + bool ' Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO + fi if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5 tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS @@ -182,7 +192,7 @@ if [ "$CONFIG_OBSOLETE" = "y" ]; then dep_bool ' Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET $CONFIG_ISA fi - if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ORION" = "y" ]; then + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' Philips SAA9730 Ethernet support (EXPERIMENTAL)' CONFIG_LAN_SAA9730 fi fi @@ -194,6 +204,15 @@ dep_tristate ' D-Link DE600 pocket adapter support' CONFIG_DE600 $CONFIG_ISA dep_tristate ' D-Link DE620 pocket adapter support' CONFIG_DE620 $CONFIG_ISA fi + if [ "$CONFIG_SGI_IP22" = "y" ]; then + bool ' SGI Seeq ethernet controller support' CONFIG_SGISEEQ + fi + if [ "$CONFIG_DECSTATION" = "y" ]; then + bool ' DEC LANCE ethernet controller support' CONFIG_DECLANCE + fi + if [ "$CONFIG_BAGET_MIPS" = "y" ]; then + tristate ' Baget AMD LANCE support' CONFIG_BAGETLANCE + fi fi endmenu @@ -206,15 +225,22 @@ comment 'Ethernet (1000 Mbit)' dep_tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC $CONFIG_PCI -dep_mbool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I $CONFIG_ACENIC +if [ "$CONFIG_ACENIC" != "n" ]; then + bool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I +fi dep_tristate 'D-Link DL2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI dep_tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS +dep_tristate 'National Semiconduct DP83820 support' CONFIG_NS83820 $CONFIG_PCI dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI endmenu +if [ "$CONFIG_PPC_ISERIES" = "y" ]; then + dep_tristate 'iSeries Virtual Ethernet driver support' CONFIG_VETH $CONFIG_PPC_ISERIES +fi + bool 'FDDI driver support' CONFIG_FDDI if [ "$CONFIG_FDDI" = "y" ]; then if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then @@ -245,7 +271,9 @@ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP - dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP $CONFIG_EXPERIMENTAL + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP + fi fi tristate 'SLIP (serial line) support' CONFIG_SLIP 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 Mon Sep 17 22:52:35 2001 @@ -74,7 +74,9 @@ obj-$(CONFIG_DM9102) += dmfe.o obj-$(CONFIG_YELLOWFIN) += yellowfin.o obj-$(CONFIG_ACENIC) += acenic.o +obj-$(CONFIG_VETH) += veth.o obj-$(CONFIG_NATSEMI) += natsemi.o +obj-$(CONFIG_NS83820) += ns83820.o obj-$(CONFIG_STNIC) += stnic.o 8390.o obj-$(CONFIG_FEALNX) += fealnx.o @@ -137,17 +139,11 @@ 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 -obj-$(CONFIG_DE650) += de650.o 8390.o -obj-$(CONFIG_3C589) += 3c589.o obj-$(CONFIG_DUMMY) += dummy.o obj-$(CONFIG_BONDING) += bonding.o obj-$(CONFIG_DE600) += de600.o @@ -184,8 +180,13 @@ obj-$(CONFIG_ELPLUS) += 3c505.o obj-$(CONFIG_AC3200) += ac3200.o 8390.o obj-$(CONFIG_APRICOT) += 82596.o +obj-$(CONFIG_LASI_82596) += lasi_82596.o obj-$(CONFIG_MVME16x_NET) += 82596.o obj-$(CONFIG_BVME6000_NET) += 82596.o + +# This is also a 82596 and should probably be merged +obj-$(CONFIG_LP486E) += lp486e.o + obj-$(CONFIG_ETH16I) += eth16i.o obj-$(CONFIG_ARIADNE2) += ariadne2.o 8390.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o @@ -193,6 +194,7 @@ obj-$(CONFIG_EQUALIZER) += eql.o obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o +obj-$(CONFIG_MIPS_AU1000_ENET) += au1000_eth.o obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o obj-$(CONFIG_BAGETLANCE) += bagetlance.o obj-$(CONFIG_DECLANCE) += declance.o diff -u --recursive --new-file v2.4.9/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.4.9/linux/drivers/net/Space.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/Space.c Thu Sep 13 15:21:32 2001 @@ -102,15 +102,11 @@ extern int mac89x0_probe(struct net_device *dev); extern int mc32_probe(struct net_device *dev); -/* Gigabit Ethernet adapters */ -extern int yellowfin_probe(struct net_device *dev); - /* Detachable devices ("pocket adaptors") */ extern int de600_probe(struct net_device *); extern int de620_probe(struct net_device *); /* FDDI adapters */ -extern int apfddi_init(struct net_device *dev); extern int skfp_probe(struct net_device *dev); /* Fibre Channel adapters */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/acenic.c linux/drivers/net/acenic.c --- v2.4.9/linux/drivers/net/acenic.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/acenic.c Mon Sep 10 08:06:32 2001 @@ -2995,8 +2995,8 @@ return; while (size > 0) { - tsize = min(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1), - min(u32, size, ACE_WINDOW_SIZE)); + tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1), + min_t(u32, size, ACE_WINDOW_SIZE)); tdest = (unsigned long)®s->Window + (dest & (ACE_WINDOW_SIZE - 1)); writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); @@ -3026,8 +3026,8 @@ return; while (size > 0) { - tsize = min(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1), - min(u32, size, ACE_WINDOW_SIZE)); + tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1), + min_t(u32, size, ACE_WINDOW_SIZE)); tdest = (unsigned long)®s->Window + (dest & (ACE_WINDOW_SIZE - 1)); writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); diff -u --recursive --new-file v2.4.9/linux/drivers/net/aironet4500_card.c linux/drivers/net/aironet4500_card.c --- v2.4.9/linux/drivers/net/aironet4500_card.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/aironet4500_card.c Mon Sep 17 22:52:35 2001 @@ -59,6 +59,13 @@ #include +static struct pci_device_id aironet4500_card_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_AIRONET, PCI_DEVICE_AIRONET_4800_1, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_AIRONET, PCI_DEVICE_AIRONET_4800, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_AIRONET, PCI_DEVICE_AIRONET_4500, PCI_ANY_ID, PCI_ANY_ID, }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, aironet4500_card_pci_tbl); static int reverse_probe; @@ -168,6 +175,13 @@ allocd_dev = 1; } dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL ); + if (!dev->priv) { + if (allocd_dev) { + unregister_netdev(dev); + kfree(dev); + } + return -ENOMEM; + } memset(dev->priv,0,sizeof(struct awc_private)); if (!dev->priv) { printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n"); @@ -488,6 +502,14 @@ } +static struct isapnp_device_id id_table[] = { + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('A','W','L'), ISAPNP_DEVICE(1), 0 }, + {0} +}; + +MODULE_DEVICE_TABLE(isapnp, id_table); + #endif //MODULE #endif /* CONFIG_AIRONET4500_PNP */ @@ -634,7 +656,7 @@ #endif /* CONFIG_AIRONET4500_ISA */ -#ifdef CONFIG_AIRONET4500_365 +#ifdef CONFIG_AIRONET4500_I365 #define port_range 0x40 @@ -954,7 +976,7 @@ } -#endif /* CONFIG_AIRONET4500_365 */ +#endif /* CONFIG_AIRONET4500_I365 */ #ifdef MODULE int init_module(void) diff -u --recursive --new-file v2.4.9/linux/drivers/net/aironet4500_core.c linux/drivers/net/aironet4500_core.c --- v2.4.9/linux/drivers/net/aironet4500_core.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/aironet4500_core.c Mon Sep 17 22:52:35 2001 @@ -2564,7 +2564,6 @@ #if LINUX_VERSION_CODE >= 0x20100 MODULE_PARM(awc_debug,"i"); -MODULE_PARM(rx_queue_len,"i"); MODULE_PARM(tx_rate,"i"); MODULE_PARM(channel,"i"); //MODULE_PARM(tx_full_rate,"i"); @@ -2600,7 +2599,6 @@ EXPORT_SYMBOL(awc_private_init); EXPORT_SYMBOL(awc_tx_timeout); EXPORT_SYMBOL(awc_start_xmit); -//EXPORT_SYMBOL(awc_rx); EXPORT_SYMBOL(awc_interrupt); EXPORT_SYMBOL(awc_get_stats); EXPORT_SYMBOL(awc_change_mtu); @@ -2976,7 +2974,7 @@ awc_reset(dev); - udelay(10000); + mdelay(10); AWC_LOCK_COMMAND_ISSUING(priv); @@ -3072,31 +3070,7 @@ return retval; } -inline int awc_rx(struct net_device *dev, struct awc_fid * rx_fid) { - -// struct awc_private *lp = (struct awc_private *)dev->priv; - - DEBUG(3, "%s: in rx_packet \n",dev->name); - - if (!rx_fid ){ - DEBUG(3, "%s: not rx_buff in rx_packet \n",dev->name); - return -1; - }; - if ( !rx_fid->skb){ - DEBUG(3, "%s: not rx_buff->skb in rx_packet \n",dev->name); - return -1; - }; - - - rx_fid->skb->protocol = eth_type_trans(rx_fid->skb,dev); - netif_rx(rx_fid->skb); - rx_fid = NULL; - - return 0; -} - - - void awc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +void awc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct awc_private *priv; @@ -3115,8 +3089,6 @@ awc_interrupt_process(dev); spin_unlock_irqrestore(&priv->interrupt_spinlock, flags); - - return; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/aironet4500_proc.c linux/drivers/net/aironet4500_proc.c --- v2.4.9/linux/drivers/net/aironet4500_proc.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/aironet4500_proc.c Mon Sep 17 22:52:35 2001 @@ -59,7 +59,7 @@ char proc_name[10]; }; static char awc_drive_info[AWC_STR_SIZE]="Zcom \n\0"; -static char awc_proc_buff[AWC_STR_SIZE]="\0"; +static char awc_proc_buff[AWC_STR_SIZE]; static int awc_int_buff; static struct awc_proc_private awc_proc_priv[MAX_AWCS]; @@ -403,7 +403,7 @@ {0} }; -struct ctl_table_header * awc_driver_sysctl_header = NULL; +struct ctl_table_header * awc_driver_sysctl_header; const char awc_procname[]= "awc5"; diff -u --recursive --new-file v2.4.9/linux/drivers/net/appletalk/cops.c linux/drivers/net/appletalk/cops.c --- v2.4.9/linux/drivers/net/appletalk/cops.c Wed May 16 10:31:27 2001 +++ linux/drivers/net/appletalk/cops.c Sun Sep 9 10:45:43 2001 @@ -1013,6 +1013,8 @@ #ifdef MODULE static struct net_device cops0_dev = { init: cops_probe }; + +MODULE_LICENSE("GPL"); MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(board_type, "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/net/appletalk/ipddp.c linux/drivers/net/appletalk/ipddp.c --- v2.4.9/linux/drivers/net/appletalk/ipddp.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/appletalk/ipddp.c Sun Sep 9 10:45:43 2001 @@ -283,6 +283,7 @@ static struct net_device dev_ipddp; +MODULE_LICENSE("GPL"); MODULE_PARM(ipddp_mode, "i"); static int __init ipddp_init_module(void) diff -u --recursive --new-file v2.4.9/linux/drivers/net/appletalk/ltpc.c linux/drivers/net/appletalk/ltpc.c --- v2.4.9/linux/drivers/net/appletalk/ltpc.c Wed Apr 18 14:40:05 2001 +++ linux/drivers/net/appletalk/ltpc.c Sun Sep 9 10:45:43 2001 @@ -1255,6 +1255,8 @@ static struct net_device dev_ltpc; #ifdef MODULE + +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/net/au1000_eth.c linux/drivers/net/au1000_eth.c --- v2.4.9/linux/drivers/net/au1000_eth.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/au1000_eth.c Sun Sep 9 10:43:01 2001 @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/net/bmac.c linux/drivers/net/bmac.c --- v2.4.9/linux/drivers/net/bmac.c Wed May 16 09:58:36 2001 +++ linux/drivers/net/bmac.c Tue Sep 18 14:23:14 2001 @@ -76,6 +76,8 @@ struct net_device_stats stats; struct timer_list tx_timeout; int timeout_active; + int sleeping; + int opened; unsigned short hash_use_count[64]; unsigned short hash_table_mask[4]; struct net_device *next_bmac; @@ -466,11 +468,15 @@ bmac_sleep_notify(struct pmu_sleep_notifier *self, int when) { struct bmac_data *bp; - + unsigned long flags; + unsigned short config; + struct net_device* dev = bmac_devs; + int i; + if (bmac_devs == 0) return PBOOK_SLEEP_OK; - bp = (struct bmac_data *) bmac_devs->priv; + bp = (struct bmac_data *) dev->priv; switch (when) { case PBOOK_SLEEP_REQUEST: @@ -478,21 +484,57 @@ case PBOOK_SLEEP_REJECT: break; case PBOOK_SLEEP_NOW: + netif_device_detach(dev); /* prolly should wait for dma to finish & turn off the chip */ - disable_irq(bmac_devs->irq); + save_flags(flags); cli(); + if (bp->timeout_active) { + del_timer(&bp->tx_timeout); + bp->timeout_active = 0; + } + disable_irq(dev->irq); disable_irq(bp->tx_dma_intr); disable_irq(bp->rx_dma_intr); + bp->sleeping = 1; + restore_flags(flags); + if (bp->opened) { + volatile struct dbdma_regs *rd = bp->rx_dma; + volatile struct dbdma_regs *td = bp->tx_dma; + + config = bmread(dev, RXCFG); + bmwrite(dev, RXCFG, (config & ~RxMACEnable)); + config = bmread(dev, TXCFG); + bmwrite(dev, TXCFG, (config & ~TxMACEnable)); + bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */ + /* disable rx and tx dma */ + st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ + st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ + /* free some skb's */ + for (i=0; irx_bufs[i] != NULL) { + dev_kfree_skb(bp->rx_bufs[i]); + bp->rx_bufs[i] = NULL; + } + } + for (i = 0; itx_bufs[i] != NULL) { + dev_kfree_skb(bp->tx_bufs[i]); + bp->tx_bufs[i] = NULL; + } + } + } feature_set(bp->node, FEATURE_BMac_reset); - udelay(10000); + mdelay(10); feature_clear(bp->node, FEATURE_BMac_IO_enable); - udelay(10000); + mdelay(10); break; case PBOOK_WAKE: /* see if this is enough */ - bmac_reset_and_enable(bmac_devs); - enable_irq(bmac_devs->irq); + if (bp->opened) + bmac_reset_and_enable(dev); + enable_irq(dev->irq); enable_irq(bp->tx_dma_intr); enable_irq(bp->rx_dma_intr); + netif_device_attach(dev); break; } return PBOOK_SLEEP_OK; @@ -975,6 +1017,9 @@ unsigned short rx_cfg; int i; + if (bp->sleeping) + return; + XXDEBUG(("bmac: enter bmac_set_multicast, n_addrs=%d\n", num_addrs)); if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { @@ -1228,7 +1273,8 @@ bmac_init_chip(dev); bmac_start_chip(dev); bmwrite(dev, INTDISABLE, EnableNormal); - + bp->sleeping = 0; + /* * It seems that the bmac can't receive until it's transmitted * a packet. So we give it a dummy packet to transmit. @@ -1396,8 +1442,10 @@ static int bmac_open(struct net_device *dev) { + struct bmac_data *bp = (struct bmac_data *) dev->priv; /* XXDEBUG(("bmac: enter open\n")); */ /* reset the chip */ + bp->opened = 1; bmac_reset_and_enable(dev); dev->flags |= IFF_RUNNING; return 0; @@ -1443,6 +1491,8 @@ } XXDEBUG(("bmac: all bufs freed\n")); + bp->opened = 0; + return 0; } @@ -1454,6 +1504,9 @@ struct sk_buff *skb; unsigned long flags; + if (bp->sleeping) + return; + save_flags(flags); cli(); while (1) { i = bp->tx_fill + 1; diff -u --recursive --new-file v2.4.9/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c --- v2.4.9/linux/drivers/net/cs89x0.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/cs89x0.c Sun Sep 9 10:45:43 2001 @@ -1111,7 +1111,7 @@ (unsigned long)lp->dma_buff, (unsigned long)virt_to_bus(lp->dma_buff)); } - if ((unsigned long)virt_to_bus(lp->dma_buff) >= MAX_DMA_ADDRESS || + if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS || !dma_page_eq(lp->dma_buff, lp->dma_buff+lp->dmasize*1024-1)) { printk(KERN_ERR "%s: not usable as DMA buffer\n", dev->name); goto release_irq; diff -u --recursive --new-file v2.4.9/linux/drivers/net/de600.c linux/drivers/net/de600.c --- v2.4.9/linux/drivers/net/de600.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/de600.c Mon Sep 10 08:06:32 2001 @@ -814,7 +814,7 @@ */ if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf-2*DE600_MIN_WINDOW) return(0); - amt = min(int, (sk->rcvbuf-atomic_read(&sk->rmem_alloc))/2/*-DE600_MIN_WINDOW*/, DE600_MAX_WINDOW); + amt = min_t(int, (sk->rcvbuf-atomic_read(&sk->rmem_alloc))/2/*-DE600_MIN_WINDOW*/, DE600_MAX_WINDOW); if (amt < 0) return(0); return(amt); } diff -u --recursive --new-file v2.4.9/linux/drivers/net/declance.c linux/drivers/net/declance.c --- v2.4.9/linux/drivers/net/declance.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/declance.c Sun Sep 9 10:45:43 2001 @@ -1006,7 +1006,7 @@ lance_set_multicast(dev); } -static int __init dec_lance_init(const int type) +static int __init dec_lance_init(struct net_device *dev, const int type) { static unsigned version_printed; struct net_device *dev; @@ -1015,7 +1015,6 @@ int i, ret; unsigned long esar_base; unsigned char *esar; - struct net_device *dev; #ifndef CONFIG_TC system_base = KN01_LANCE_BASE; @@ -1026,12 +1025,12 @@ if (dec_lance_debug && version_printed++ == 0) printk(version); - dev = init_etherdev(NULL, sizeof(struct lance_private)); + dev = init_etherdev(0, sizeof(struct lance_private)); if (!dev) return -ENOMEM; /* init_etherdev ensures the data structures used by the LANCE are aligned. */ - lp = dev->priv; + lp = (struct lance_private *) dev->priv; spin_lock_init(&lp->lock); switch (type) { @@ -1217,6 +1216,7 @@ /* Find all the lance cards on the system and initialize them */ static int __init dec_lance_probe(void) { + struct net_device *dev = NULL; static int called; #ifdef MODULE @@ -1255,7 +1255,7 @@ } #endif - return dec_lance_init(type); + return dec_lance_init(dev, type); } static void __exit dec_lance_cleanup(void) diff -u --recursive --new-file v2.4.9/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c --- v2.4.9/linux/drivers/net/dgrs.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/dgrs.c Mon Sep 10 08:06:32 2001 @@ -733,7 +733,7 @@ goto no_resources; } - amt = min(unsigned int, len, rbdp->size - count); + amt = min_t(unsigned int, len, rbdp->size - count); memcpy( (char *) S2H(rbdp->buf) + count, skb->data + i, amt); i += amt; count += amt; @@ -1292,6 +1292,7 @@ if (!devN) goto fail; memcpy(devN, dev, dev_size); + memset(devN->name, 0, sizeof(devN->name)); devN->priv = ((void *)devN) + sizeof(struct net_device); privN = (DGRS_PRIV *)devN->priv; /* ... and zero out VM areas */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/dl2k.c linux/drivers/net/dl2k.c --- v2.4.9/linux/drivers/net/dl2k.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/dl2k.c Fri Sep 14 14:39:59 2001 @@ -470,7 +470,7 @@ unsigned entry; u32 ioaddr; int tx_shift; - unsigned flags; + unsigned long flags; ioaddr = dev->base_addr; entry = np->cur_tx % TX_RING_SIZE; diff -u --recursive --new-file v2.4.9/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c --- v2.4.9/linux/drivers/net/dmfe.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/dmfe.c Sun Sep 9 10:45:43 2001 @@ -61,7 +61,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.4.9/linux/drivers/net/eepro100.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/eepro100.c Mon Sep 17 21:32:48 2001 @@ -349,14 +349,17 @@ /* Clear CmdSuspend (1<<30) avoiding interference with the card access to the status bits. Previous driver versions used separate 16 bit fields for commands and statuses. --SAW - FIXME: it may not work on non-IA32 architectures. */ -#if defined(__LITTLE_ENDIAN) -#define clear_suspend(cmd) ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x4000 -#elif defined(__BIG_ENDIAN) -#define clear_suspend(cmd) ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x0040 +#if defined(__alpha__) +# define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status); #else -#error Unsupported byteorder +# if defined(__LITTLE_ENDIAN) +# define clear_suspend(cmd) ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x4000 +# elif defined(__BIG_ENDIAN) +# define clear_suspend(cmd) ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x0040 +# else +# error Unsupported byteorder +# endif #endif enum SCBCmdBits { diff -u --recursive --new-file v2.4.9/linux/drivers/net/eql.c linux/drivers/net/eql.c --- v2.4.9/linux/drivers/net/eql.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/eql.c Thu Sep 13 16:04:43 2001 @@ -121,7 +121,7 @@ #include -static const char version[] __initdata = +static char version[] __initdata = "Equalizer1996: $Revision: 1.2.1 $ $Date: 1996/09/22 13:52:00 $ Simon Janes (simon@ncm.com)\n"; #ifndef EQL_DEBUG diff -u --recursive --new-file v2.4.9/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v2.4.9/linux/drivers/net/ewrk3.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/ewrk3.c Thu Sep 13 16:04:43 2001 @@ -164,7 +164,7 @@ #include "ewrk3.h" -static const char version[] __initdata = +static char version[] __initdata = "ewrk3.c:v0.43a 2001/02/04 davies@maniac.ultranet.com\n"; #ifdef EWRK3_DEBUG diff -u --recursive --new-file v2.4.9/linux/drivers/net/fc/iph5526.c linux/drivers/net/fc/iph5526.c --- v2.4.9/linux/drivers/net/fc/iph5526.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/fc/iph5526.c Thu Sep 13 16:04:43 2001 @@ -118,6 +118,8 @@ }; MODULE_DEVICE_TABLE(pci, iph5526_pci_tbl); +MODULE_LICENSE("GPL"); + #define MAX_FC_CARDS 2 static struct fc_info *fc[MAX_FC_CARDS+1]; static unsigned int pci_irq_line; diff -u --recursive --new-file v2.4.9/linux/drivers/net/fealnx.c linux/drivers/net/fealnx.c --- v2.4.9/linux/drivers/net/fealnx.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/fealnx.c Fri Sep 14 14:40:00 2001 @@ -892,7 +892,7 @@ // np->bcrvalue=0x04 | 0x0x38; /* big-endian, 256 burst length */ np->bcrvalue = 0x04 | 0x10; /* big-endian, tx 8 burst length */ np->crvalue = 0xe00; /* rx 128 burst length */ -#elif defined(__alpha__) +#elif defined(__alpha__) || defined(__x86_64__) // 89/9/1 modify, // np->bcrvalue=0x38; /* little-endian, 256 burst length */ np->bcrvalue = 0x10; /* little-endian, 8 burst length */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/gmac.c linux/drivers/net/gmac.c --- v2.4.9/linux/drivers/net/gmac.c Wed May 16 09:58:36 2001 +++ linux/drivers/net/gmac.c Tue Sep 18 14:23:14 2001 @@ -12,7 +12,10 @@ * BenH - 03/09/2000 * - Add support for new PHYs * - Add some PowerBook sleep code - * + * BenH - ??/??/???? + * - PHY updates + * BenH - 08/08/2001 + * - Add more PHYs, fixes to sleep code */ #include @@ -46,8 +49,8 @@ #define DEBUG_PHY -/* Driver version 1.3, kernel 2.4.x */ -#define GMAC_VERSION "v1.4k4" +/* Driver version 1.5, kernel 2.4.x */ +#define GMAC_VERSION "v1.5k4" #define DUMMY_BUF_LEN RX_BUF_ALLOC_SIZE + RX_OFFSET + GMAC_BUFFER_ALIGN static unsigned char *dummy_buf; @@ -213,7 +216,7 @@ int link_100 = 0; int gigabit = 0; #ifdef DEBUG_PHY - printk("%s: Link state change, phy_status: 0x%04x\n", + printk(KERN_INFO "%s: Link state change, phy_status: 0x%04x\n", gm->dev->name, phy_status); #endif gm->phy_status = phy_status; @@ -228,37 +231,49 @@ /* Link ? Check for speed and duplex */ if ((phy_status & MII_SR_LKS) && (phy_status & MII_SR_ASSC)) { int restart = 0; - if (gm->phy_type == PHY_B5201) { - int aux_stat = mii_read(gm, gm->phy_addr, MII_BCM5201_AUXCTLSTATUS); + int aux_stat, link; + switch (gm->phy_type) { + case PHY_B5201: + case PHY_B5221: + aux_stat = mii_read(gm, gm->phy_addr, MII_BCM5201_AUXCTLSTATUS); #ifdef DEBUG_PHY - printk(" Link up ! BCM5201 aux_stat: 0x%04x\n", aux_stat); + printk(KERN_INFO "%s: Link up ! BCM5201/5221 aux_stat: 0x%04x\n", + gm->dev->name, aux_stat); #endif full_duplex = ((aux_stat & MII_BCM5201_AUXCTLSTATUS_DUPLEX) != 0); link_100 = ((aux_stat & MII_BCM5201_AUXCTLSTATUS_SPEED) != 0); - } else if (gm->phy_type == PHY_B5400) { - int aux_stat = mii_read(gm, gm->phy_addr, MII_BCM5400_AUXSTATUS); - int link = (aux_stat & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >> + break; + case PHY_B5400: + case PHY_B5401: + case PHY_B5411: + aux_stat = mii_read(gm, gm->phy_addr, MII_BCM5400_AUXSTATUS); + link = (aux_stat & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >> MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT; #ifdef DEBUG_PHY - printk(" Link up ! BCM5400 aux_stat: 0x%04x (link mode: %d)\n", - aux_stat, link); + printk(KERN_INFO "%s: Link up ! BCM54xx aux_stat: 0x%04x (link mode: %d)\n", + gm->dev->name, aux_stat, link); #endif full_duplex = phy_BCM5400_link_table[link][0]; link_100 = phy_BCM5400_link_table[link][1]; gigabit = phy_BCM5400_link_table[link][2]; - } else if (gm->phy_type == PHY_LXT971) { - int stat2 = mii_read(gm, gm->phy_addr, MII_LXT971_STATUS2); + break; + case PHY_LXT971: + aux_stat = mii_read(gm, gm->phy_addr, MII_LXT971_STATUS2); #ifdef DEBUG_PHY - printk(" Link up ! LXT971 stat2: 0x%04x\n", stat2); + printk(KERN_INFO "%s: Link up ! LXT971 stat2: 0x%04x\n", + gm->dev->name, aux_stat); #endif - full_duplex = ((stat2 & MII_LXT971_STATUS2_FULLDUPLEX) != 0); - link_100 = ((stat2 & MII_LXT971_STATUS2_SPEED) != 0); - } else { + full_duplex = ((aux_stat & MII_LXT971_STATUS2_FULLDUPLEX) != 0); + link_100 = ((aux_stat & MII_LXT971_STATUS2_SPEED) != 0); + break; + default: full_duplex = (lpar_ability & MII_ANLPA_FDAM) != 0; link_100 = (lpar_ability & MII_ANLPA_100M) != 0; + break; } #ifdef DEBUG_PHY - printk(" full_duplex: %d, speed: %s\n", full_duplex, + printk(KERN_INFO "%s: Full Duplex: %d, Speed: %s\n", + gm->dev->name, full_duplex, gigabit ? "1000" : (link_100 ? "100" : "10")); #endif if (gigabit != gm->gigabit) { @@ -275,13 +290,15 @@ gmac_start_dma(gm); } else if (!(phy_status & MII_SR_LKS)) { #ifdef DEBUG_PHY - printk(" Link down !\n"); + printk(KERN_INFO "%s: Link down !\n", gm->dev->name); #endif } } } /* Power management: stop PHY chip for suspend mode + * + * TODO: This will have to be modified is WOL is to be supported. */ static void gmac_suspend(struct gmac* gm) @@ -290,7 +307,7 @@ unsigned long flags; gm->sleeping = 1; - netif_stop_queue(gm->dev); + netif_device_detach(gm->dev); spin_lock_irqsave(&gm->lock, flags); @@ -318,7 +335,7 @@ } /* Clear interrupts on 5201 */ - if (gm->phy_type == PHY_B5201) + if (gm->phy_type == PHY_B5201 || gm->phy_type == PHY_B5221) mii_write(gm, gm->phy_addr, MII_BCM5201_INTERRUPT, 0); /* Drive MDIO high */ @@ -328,12 +345,6 @@ data = mii_read(gm, gm->phy_addr, MII_ANLPA); mii_write(gm, gm->phy_addr, MII_ANLPA, data); - /* Put MDIO in sane state */ - GM_OUT(GM_MIF_CFG, GM_MIF_CFGBB); - GM_OUT(GM_MIF_BB_CLOCK, 0); - GM_OUT(GM_MIF_BB_DATA, 0); - GM_OUT(GM_MIF_BB_OUT_ENABLE, 0); - /* Stop everything */ GM_OUT(GM_MAC_RX_CONFIG, 0); GM_OUT(GM_MAC_TX_CONFIG, 0); @@ -341,7 +352,7 @@ GM_OUT(GM_TX_CONF, 0); GM_OUT(GM_RX_CONF, 0); - /* Set reset state */ + /* Set MAC in reset state */ GM_OUT(GM_RESET, GM_RESET_TX | GM_RESET_RX); for (timeout = 100; timeout > 0; --timeout) { mdelay(10); @@ -352,11 +363,23 @@ GM_OUT(GM_MAC_RX_RESET, GM_MAC_RX_RESET_NOW); /* Superisolate PHY */ - if (gm->phy_type == PHY_B5201) + if (gm->phy_type == PHY_B5201 || gm->phy_type == PHY_B5221) mii_write(gm, gm->phy_addr, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE); - /* Unclock chip */ + /* Put MDIO in sane electric state. According to an obscure + * Apple comment, not doing so may let them drive some current + * during sleep and possibly damage BCM PHYs. + */ + GM_OUT(GM_MIF_CFG, GM_MIF_CFGBB); + GM_OUT(GM_MIF_BB_CLOCK, 0); + GM_OUT(GM_MIF_BB_DATA, 0); + GM_OUT(GM_MIF_BB_OUT_ENABLE, 0); + GM_OUT(GM_MAC_XIF_CONFIG, + GM_MAC_XIF_CONF_GMII_MODE|GM_MAC_XIF_CONF_MII_INT_LOOP); + (void)GM_IN(GM_MAC_XIF_CONFIG); + + /* Unclock the GMAC chip */ gmac_set_power(gm, 0); } @@ -390,7 +413,7 @@ mdelay(20); GM_BIS(GM_MAC_RX_CONFIG, GM_MAC_RX_CONF_ENABLE); mdelay(20); - if (gm->phy_type == PHY_B5201) { + if (gm->phy_type == PHY_B5201 || gm->phy_type == PHY_B5221) { data = mii_read(gm, gm->phy_addr, MII_BCM5201_MULTIPHY); mii_write(gm, gm->phy_addr, MII_BCM5201_MULTIPHY, data & ~MII_BCM5201_MULTIPHY_SUPERISOLATE); @@ -402,7 +425,7 @@ mii_interrupt(gm); /* restart DMA operations */ gmac_start_dma(gm); - netif_start_queue(gm->dev); + netif_device_attach(gm->dev); enable_irq(gm->dev->irq); } else { /* Driver not opened, just leave things off. Note that @@ -446,11 +469,19 @@ return 0; } +/* Here's a bunch of configuration routines for + * Broadcom PHYs used on various Mac models. Unfortunately, + * except for the 5201, Broadcom never sent me any documentation, + * so this is from my understanding of Apple's Open Firmware + * drivers and Darwin's implementation + */ + static void mii_init_BCM5400(struct gmac *gm) { int data; + /* Configure for gigabit full duplex */ data = mii_read(gm, gm->phy_addr, MII_BCM5400_AUXCONTROL); data |= MII_BCM5400_AUXCONTROL_PWR10BASET; mii_write(gm, gm->phy_addr, MII_BCM5400_AUXCONTROL, data); @@ -460,6 +491,8 @@ mii_write(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL, data); mdelay(10); + + /* Reset and configure cascaded 10/100 PHY */ mii_do_reset_phy(gm, 0x1f); data = mii_read(gm, 0x1f, MII_BCM5201_MULTIPHY); @@ -479,7 +512,14 @@ rev = mii_read(gm, gm->phy_addr, MII_ID1) & 0x000f; if (rev == 0 || rev == 3) { - /* A bit of black magic from Apple */ + /* Some revisions of 5401 appear to need this + * initialisation sequence to disable, according + * to OF, "tap power management" + * + * WARNING ! OF and Darwin don't agree on the + * register addresses. OF seem to interpret the + * register numbers below as decimal + */ mii_write(gm, gm->phy_addr, 0x18, 0x0c20); mii_write(gm, gm->phy_addr, 0x17, 0x0012); mii_write(gm, gm->phy_addr, 0x15, 0x1804); @@ -493,11 +533,14 @@ mii_write(gm, gm->phy_addr, 0x15, 0x0a20); } + /* Configure for gigabit full duplex */ data = mii_read(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL); data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; mii_write(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL, data); mdelay(10); + + /* Reset and configure cascaded 10/100 PHY */ mii_do_reset_phy(gm, 0x1f); data = mii_read(gm, 0x1f, MII_BCM5201_MULTIPHY); @@ -505,6 +548,34 @@ mii_write(gm, 0x1f, MII_BCM5201_MULTIPHY, data); } +static void +mii_init_BCM5411(struct gmac *gm) +{ + int data; + + /* Here's some more Apple black magic to setup + * some voltage stuffs. + */ + mii_write(gm, gm->phy_addr, 0x1c, 0x8c23); + mii_write(gm, gm->phy_addr, 0x1c, 0x8ca3); + mii_write(gm, gm->phy_addr, 0x1c, 0x8c23); + + /* Here, Apple seems to want to reset it, do + * it as well + */ + mii_write(gm, gm->phy_addr, MII_CR, MII_CR_RST); + + /* Start autoneg */ + mii_write(gm, gm->phy_addr, MII_CR, + MII_CR_ASSE|MII_CR_FDM| /* Autospeed, full duplex */ + MII_CR_RAN| + MII_CR_SPEEDSEL2 /* chip specific, gigabit enable ? */); + + data = mii_read(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL); + data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; + mii_write(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL, data); +} + static int mii_lookup_and_reset(struct gmac *gm) { @@ -536,29 +607,34 @@ gm->phy_id = (mii_read(gm, gm->phy_addr, MII_ID0) << 16) | mii_read(gm, gm->phy_addr, MII_ID1); #ifdef DEBUG_PHY - printk("%s PHY ID: 0x%08x\n", gm->dev->name, gm->phy_id); + printk(KERN_INFO "%s: PHY ID: 0x%08x\n", gm->dev->name, gm->phy_id); #endif if ((gm->phy_id & MII_BCM5400_MASK) == MII_BCM5400_ID) { gm->phy_type = PHY_B5400; - printk(KERN_ERR "%s Found Broadcom BCM5400 PHY (Gigabit)\n", + printk(KERN_INFO "%s: Found Broadcom BCM5400 PHY (Gigabit)\n", gm->dev->name); mii_init_BCM5400(gm); } else if ((gm->phy_id & MII_BCM5401_MASK) == MII_BCM5401_ID) { gm->phy_type = PHY_B5401; - printk(KERN_ERR "%s Found Broadcom BCM5401 PHY (Gigabit)\n", + printk(KERN_INFO "%s: Found Broadcom BCM5401 PHY (Gigabit)\n", gm->dev->name); mii_init_BCM5401(gm); + } else if ((gm->phy_id & MII_BCM5411_MASK) == MII_BCM5411_ID) { + gm->phy_type = PHY_B5411; + printk(KERN_INFO "%s: Found Broadcom BCM5411 PHY (Gigabit)\n", + gm->dev->name); + mii_init_BCM5411(gm); } else if ((gm->phy_id & MII_BCM5201_MASK) == MII_BCM5201_ID) { gm->phy_type = PHY_B5201; - printk(KERN_INFO "%s Found Broadcom BCM5201 PHY\n", gm->dev->name); + printk(KERN_INFO "%s: Found Broadcom BCM5201 PHY\n", gm->dev->name); } else if ((gm->phy_id & MII_BCM5221_MASK) == MII_BCM5221_ID) { - gm->phy_type = PHY_B5201; /* Same as 5201 for now */ - printk(KERN_INFO "%s Found Broadcom BCM5221 PHY\n", gm->dev->name); + gm->phy_type = PHY_B5221; + printk(KERN_INFO "%s: Found Broadcom BCM5221 PHY\n", gm->dev->name); } else if ((gm->phy_id & MII_LXT971_MASK) == MII_LXT971_ID) { gm->phy_type = PHY_LXT971; - printk(KERN_INFO "%s Found LevelOne LX971 PHY\n", gm->dev->name); + printk(KERN_INFO "%s: Found LevelOne LX971 PHY\n", gm->dev->name); } else { - printk(KERN_ERR "%s: Warning ! Unknown PHY ID 0x%08x, using generic mode...\n", + printk(KERN_WARNING "%s: Warning ! Unknown PHY ID 0x%08x, using generic mode...\n", gm->dev->name, gm->phy_id); } diff -u --recursive --new-file v2.4.9/linux/drivers/net/gmac.h linux/drivers/net/gmac.h --- v2.4.9/linux/drivers/net/gmac.h Wed May 16 09:58:36 2001 +++ linux/drivers/net/gmac.h Tue Sep 18 14:23:14 2001 @@ -667,18 +667,18 @@ /* ** MII Management Control Register */ -#define MII_CR_RST 0x8000 /* RESET the PHY chip */ -#define MII_CR_LPBK 0x4000 /* Loopback enable */ -#define MII_CR_SPD 0x2000 /* 0: 10Mb/s; 1: 100Mb/s */ -#define MII_CR_10 0x0000 /* Set 10Mb/s */ -#define MII_CR_100 0x2000 /* Set 100Mb/s */ -#define MII_CR_ASSE 0x1000 /* Auto Speed Select Enable */ -#define MII_CR_PD 0x0800 /* Power Down */ -#define MII_CR_ISOL 0x0400 /* Isolate Mode */ -#define MII_CR_RAN 0x0200 /* Restart Auto Negotiation */ -#define MII_CR_FDM 0x0100 /* Full Duplex Mode */ -#define MII_CR_CTE 0x0080 /* Collision Test Enable */ - +#define MII_CR_RST 0x8000 /* RESET the PHY chip */ +#define MII_CR_LPBK 0x4000 /* Loopback enable */ +#define MII_CR_SPD 0x2000 /* 0: 10Mb/s; 1: 100Mb/s */ +#define MII_CR_10 0x0000 /* Set 10Mb/s */ +#define MII_CR_100 0x2000 /* Set 100Mb/s */ +#define MII_CR_ASSE 0x1000 /* Auto Speed Select Enable */ +#define MII_CR_PD 0x0800 /* Power Down */ +#define MII_CR_ISOL 0x0400 /* Isolate Mode */ +#define MII_CR_RAN 0x0200 /* Restart Auto Negotiation */ +#define MII_CR_FDM 0x0100 /* Full Duplex Mode */ +#define MII_CR_CTE 0x0080 /* Collision Test Enable */ +#define MII_CR_SPEEDSEL2 0x0040 /* Speed selection 2 on BCM */ /* ** MII Management Status Register */ @@ -739,7 +739,9 @@ /* Supported PHYs (phy_type field ) */ #define PHY_B5400 0x5400 #define PHY_B5401 0x5401 +#define PHY_B5411 0x5411 #define PHY_B5201 0x5201 +#define PHY_B5221 0x5221 #define PHY_LXT971 0x0971 #define PHY_UNKNOWN 0 @@ -764,6 +766,11 @@ #define MII_BCM5401_REV 0x01 #define MII_BCM5401_ID ((MII_BCM5401_OUI << 10) | (MII_BCM5401_MODEL << 4)) #define MII_BCM5401_MASK 0xfffffff0 +#define MII_BCM5411_OUI 0x000818 +#define MII_BCM5411_MODEL 0x07 +#define MII_BCM5411_REV 0x01 +#define MII_BCM5411_ID ((MII_BCM5411_OUI << 10) | (MII_BCM5411_MODEL << 4)) +#define MII_BCM5411_MASK 0xfffffff0 #define MII_LXT971_OUI 0x0004de #define MII_LXT971_MODEL 0x0e #define MII_LXT971_REV 0x00 diff -u --recursive --new-file v2.4.9/linux/drivers/net/gt96100eth.c linux/drivers/net/gt96100eth.c --- v2.4.9/linux/drivers/net/gt96100eth.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/net/gt96100eth.c Sun Sep 9 10:45:43 2001 @@ -1,7 +1,7 @@ /* * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * stevel@mvista.com or support@mvista.com + * stevel@mvista.com or source@mvista.com * * ######################################################################## * @@ -29,7 +29,6 @@ #endif -#include #include #include #include @@ -38,7 +37,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/net/gt96100eth.h linux/drivers/net/gt96100eth.h --- v2.4.9/linux/drivers/net/gt96100eth.h Fri Apr 13 20:26:07 2001 +++ linux/drivers/net/gt96100eth.h Sun Sep 9 10:45:43 2001 @@ -1,7 +1,7 @@ /* * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * stevel@mvista.com or support@mvista.com + * stevel@mvista.com or source@mvista.com * * ######################################################################## * @@ -27,7 +27,6 @@ #ifndef _GT96100ETH_H #define _GT96100ETH_H -#include #include /* Keep the ring sizes a power of two for efficiency. */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/hamradio/6pack.c linux/drivers/net/hamradio/6pack.c --- v2.4.9/linux/drivers/net/hamradio/6pack.c Wed Apr 18 14:40:06 2001 +++ linux/drivers/net/hamradio/6pack.c Thu Sep 13 16:04:43 2001 @@ -699,10 +699,10 @@ /* Initialize 6pack control device -- register 6pack line discipline */ -static const char msg_banner[] __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n"; -static const char msg_invparm[] __initdata = KERN_ERR "6pack: sixpack_maxdev parameter too large.\n"; -static const char msg_nomem[] __initdata = KERN_ERR "6pack: can't allocate sixpack_ctrls[] array! No 6pack available.\n"; -static const char msg_regfail[] __initdata = KERN_ERR "6pack: can't register line discipline (err = %d)\n"; +static char msg_banner[] __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n"; +static char msg_invparm[] __initdata = KERN_ERR "6pack: sixpack_maxdev parameter too large.\n"; +static char msg_nomem[] __initdata = KERN_ERR "6pack: can't allocate sixpack_ctrls[] array! No 6pack available.\n"; +static char msg_regfail[] __initdata = KERN_ERR "6pack: can't register line discipline (err = %d)\n"; static int __init sixpack_init_driver(void) { diff -u --recursive --new-file v2.4.9/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c --- v2.4.9/linux/drivers/net/hamradio/baycom_epp.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/hamradio/baycom_epp.c Mon Sep 10 09:04:53 2001 @@ -610,7 +610,7 @@ while (cnt > 0) { switch (bc->hdlctx.state) { case tx_keyup: - i = min(int, cnt, bc->hdlctx.flags); + i = min_t(int, cnt, bc->hdlctx.flags); cnt -= i; bc->hdlctx.flags -= i; if (bc->hdlctx.flags <= 0) @@ -633,7 +633,7 @@ break; } } - i = min(int, cnt, bc->hdlctx.bufcnt); + i = min_t(int, cnt, bc->hdlctx.bufcnt); bc->hdlctx.bufcnt -= i; cnt -= i; if (i != pp->ops->epp_write_data(pp, bc->hdlctx.bufptr, i, 0)) @@ -647,7 +647,7 @@ bc->hdlctx.state = tx_data; break; } - i = min(int, cnt, bc->hdlctx.flags); + i = min_t(int, cnt, bc->hdlctx.flags); if (i) { cnt -= i; bc->hdlctx.flags -= i; @@ -664,7 +664,7 @@ default: /* fall through */ if (bc->hdlctx.calibrate <= 0) return 0; - i = min(int, cnt, bc->hdlctx.calibrate); + i = min_t(int, cnt, bc->hdlctx.calibrate); cnt -= i; bc->hdlctx.calibrate -= i; memset(tmp, 0, sizeof(tmp)); diff -u --recursive --new-file v2.4.9/linux/drivers/net/hamradio/bpqether.c linux/drivers/net/hamradio/bpqether.c --- v2.4.9/linux/drivers/net/hamradio/bpqether.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/hamradio/bpqether.c Thu Sep 13 16:04:43 2001 @@ -87,7 +87,7 @@ #include -static const char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n"; +static char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n"; static unsigned char ax25_bcast[AX25_ADDR_LEN] = {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1}; diff -u --recursive --new-file v2.4.9/linux/drivers/net/hamradio/mkiss.c linux/drivers/net/hamradio/mkiss.c --- v2.4.9/linux/drivers/net/hamradio/mkiss.c Wed Apr 18 14:40:06 2001 +++ linux/drivers/net/hamradio/mkiss.c Thu Sep 13 16:04:43 2001 @@ -54,7 +54,7 @@ #include #endif -static const char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n"; +static char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n"; #define NR_MKISS 4 #define MKISS_SERIAL_TYPE_NORMAL 1 diff -u --recursive --new-file v2.4.9/linux/drivers/net/hamradio/scc.c linux/drivers/net/hamradio/scc.c --- v2.4.9/linux/drivers/net/hamradio/scc.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/net/hamradio/scc.c Thu Sep 13 16:04:43 2001 @@ -184,7 +184,7 @@ #include #include -static const char banner[] __initdata = KERN_INFO "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n"; +static char banner[] __initdata = KERN_INFO "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n"; static void t_dwait(unsigned long); static void t_txdelay(unsigned long); diff -u --recursive --new-file v2.4.9/linux/drivers/net/hamradio/yam.c linux/drivers/net/hamradio/yam.c --- v2.4.9/linux/drivers/net/hamradio/yam.c Wed Apr 18 14:40:06 2001 +++ linux/drivers/net/hamradio/yam.c Thu Sep 13 16:04:43 2001 @@ -81,7 +81,7 @@ /* --------------------------------------------------------------------- */ static const char yam_drvname[] = "yam"; -static const char yam_drvinfo[] __initdata = KERN_INFO "YAM driver version 0.8 by F1OAT/F6FBB\n"; +static char yam_drvinfo[] __initdata = KERN_INFO "YAM driver version 0.8 by F1OAT/F6FBB\n"; /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c --- v2.4.9/linux/drivers/net/ioc3-eth.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/ioc3-eth.c Thu Sep 13 16:04:43 2001 @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/net/irda/ali-ircc.c linux/drivers/net/irda/ali-ircc.c --- v2.4.9/linux/drivers/net/irda/ali-ircc.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/net/irda/ali-ircc.c Thu Sep 13 16:26:52 2001 @@ -1344,6 +1344,7 @@ { struct ali_ircc_cb *self; int iobase; + char hwname[32]; IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); @@ -1380,11 +1381,14 @@ /* Ready to play! */ netif_start_queue(dev); //benjamin by irport + /* Give self a hardware name */ + sprintf(hwname, "ALI-FIR @ 0x%03x", self->io.fir_base); + /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ - self->irlap = irlap_open(dev, &self->qos); + self->irlap = irlap_open(dev, &self->qos, hwname); MOD_INC_USE_COUNT; 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 Mon Sep 17 22:52:35 2001 @@ -1,14 +1,14 @@ /***************************************************************************** * * Filename: irda-usb.c - * Version: 0.9 + * Version: 0.9a * Description: IrDA-USB Driver * Status: Experimental * Author: Dag Brattli * + * Copyright (C) 2000, Roman Weissgaerber * Copyright (C) 2001, Dag Brattli * Copyright (C) 2001, Jean Tourrilhes - * Copyright (C) 2000, Roman Weissgaerber * * 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 @@ -44,26 +44,8 @@ #include -static u32 min_turn_times[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */ static int qos_mtt_bits = 0; -static void irda_usb_dump_class_desc(struct irda_class_desc *desc); -static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum); -static void irda_usb_disconnect(struct usb_device *dev, void *ptr); -static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); -static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *dev); -static int irda_usb_open(struct irda_usb_cb *self); -static int irda_usb_close(struct irda_usb_cb *self); -static void irda_usb_write_bulk(struct irda_usb_cb *self, purb_t purb); -static void write_bulk_callback(purb_t purb); -static void irda_usb_receive(purb_t purb); -static int irda_usb_net_init(struct net_device *dev); -static int irda_usb_net_open(struct net_device *dev); -static int irda_usb_net_close(struct net_device *dev); -static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void irda_usb_net_timeout(struct net_device *dev); -static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev); - /* Master instance for each hardware found */ #define NIRUSB 4 /* Max number of USB-IrDA dongles */ static struct irda_usb_cb irda_instance[NIRUSB]; @@ -76,7 +58,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, }, @@ -85,697 +68,649 @@ MODULE_DEVICE_TABLE(usb, dongles); +/*------------------------------------------------------------------*/ + +static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum); +static void irda_usb_disconnect(struct usb_device *dev, void *ptr); +static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); +static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *dev); +static int irda_usb_open(struct irda_usb_cb *self); +static int irda_usb_close(struct irda_usb_cb *self); +static void speed_bulk_callback(purb_t purb); +static void write_bulk_callback(purb_t purb); +static void irda_usb_receive(purb_t purb); +static int irda_usb_net_init(struct net_device *dev); +static int irda_usb_net_open(struct net_device *dev); +static int irda_usb_net_close(struct net_device *dev); +static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static void irda_usb_net_timeout(struct net_device *dev); +static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev); + +/************************ TRANSMIT ROUTINES ************************/ /* - * This routine is called by the USB subsystem for each new device - * in the system. We need to check if the device is ours, and in - * this case start handling it. - * Note : it might be worth protecting this function by a global - * spinlock... + * Receive packets from the IrDA stack and send them on the USB pipe. + * Handle speed change, timeout and lot's of uglyness... */ -static void *irda_usb_probe(struct usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id) -{ - struct irda_usb_cb *self = NULL; - struct usb_interface_descriptor *interface; - struct usb_endpoint_descriptor *endpoint; - struct irda_class_desc *irda_desc; - int capability = id->driver_info; - int ret; - int ep; - int i; - - IRDA_DEBUG(0, "Vendor: %x, Product: %x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); - - MESSAGE("IRDA-USB found at address %d\n", dev->devnum); - /* Try to cleanup all instance that have a pending disconnect - * Instance will be in this state is the disconnect() occurs - * before the net_close(). - * Jean II */ - for (i = 0; i < NIRUSB; i++) { - struct irda_usb_cb *irda = &irda_instance[i]; - if ((irda->usbdev != NULL) && - (irda->present == 0) && - (irda->netopen == 0)) { - IRDA_DEBUG(0, __FUNCTION__ "(), found a zombie instance !!!\n"); - irda_usb_disconnect(irda->usbdev, (void *) irda); +/*------------------------------------------------------------------*/ +/* + * Function irda_usb_build_header(self, skb, header) + * + * Builds USB-IrDA outbound header + * + * When we send an IrDA frame over an USB pipe, we add to it a 1 byte + * header. This function create this header with the proper values. + * + * Important note : the USB-IrDA spec 1.0 say very clearly in chapter 5.4.2.2 + * that the setting of the link speed and xbof number in this outbound header + * should be applied *AFTER* the frame has been sent. + * Unfortunately, some devices are not compliant with that... It seems that + * reading the spec is far too difficult... + * Jean II + */ +static void irda_usb_build_header(struct irda_usb_cb *self, + __u8 *header, + int force) +{ + /* Set the negotiated link speed */ + if (self->new_speed != -1) { + /* Hum... Ugly hack :-( + * Some device are not compliant with the spec and change + * parameters *before* sending the frame. - Jean II + */ + if ((self->capability & IUC_SPEED_BUG) && + (!force) && (self->speed != -1)) { + /* No speed and xbofs change here + * (we'll do it later in the write callback) */ + IRDA_DEBUG(2, __FUNCTION__ "(), not changing speed yet\n"); + *header = 0; + return; } - } - /* Find an free instance to handle this new device... */ - self = NULL; - for (i = 0; i < NIRUSB; i++) { - if(irda_instance[i].usbdev == NULL) { - self = &irda_instance[i]; + IRDA_DEBUG(2, __FUNCTION__ "(), changing speed to %d\n", self->new_speed); + self->speed = self->new_speed; + self->new_speed = -1; + + switch (self->speed) { + case 2400: + *header = SPEED_2400; + break; + default: + case 9600: + *header = SPEED_9600; + break; + case 19200: + *header = SPEED_19200; + break; + case 38400: + *header = SPEED_38400; + break; + case 57600: + *header = SPEED_57600; + break; + case 115200: + *header = SPEED_115200; + break; + case 576000: + *header = SPEED_576000; + break; + case 1152000: + *header = SPEED_1152000; + break; + case 4000000: + *header = SPEED_4000000; + self->new_xbofs = 0; break; } - } - if (self == NULL) { - IRDA_DEBUG(0, "Too many USB IrDA devices !!! (max = %d)\n", - NIRUSB); - return NULL; - } - - /* Reset the instance */ - self->present = 0; - self->netopen = 0; - - /* Is this really necessary? */ - if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) { - err("set_configuration failed"); - return NULL; - } + } else + /* No change */ + *header = 0; - /* Is this really necessary? */ - ret = usb_set_interface(dev, ifnum, 0); - IRDA_DEBUG(0, "usb-irda: set interface result %d\n", ret); - switch (ret) { - case USB_ST_NOERROR: /* 0 */ + /* Set the negotiated additional XBOFS */ + if (self->new_xbofs != -1) { + IRDA_DEBUG(2, __FUNCTION__ "(), changing xbofs to %d\n", self->new_xbofs); + self->xbofs = self->new_xbofs; + self->new_xbofs = -1; + + switch (self->xbofs) { + case 48: + *header |= 0x10; break; - case USB_ST_STALL: /* -EPIPE = -32 */ - usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); - IRDA_DEBUG(0, __FUNCTION__ "(), Clearing stall on control interface\n" ); + case 28: + case 24: /* USB spec 1.0 says 24 */ + *header |= 0x20; break; default: - IRDA_DEBUG(0, __FUNCTION__ "(), Unknown error %d\n", ret); - return NULL; + case 12: + *header |= 0x30; break; + case 5: /* Bug in IrLAP spec? (should be 6) */ + case 6: + *header |= 0x40; + break; + case 3: + *header |= 0x50; + break; + case 2: + *header |= 0x60; + break; + case 1: + *header |= 0x70; + break; + case 0: + *header |= 0x80; + break; + } } - - /* Find our endpoints */ - interface = &dev->actconfig->interface[ifnum].altsetting[0]; - endpoint = interface->endpoint; - ep = endpoint[0].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if ((endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) - self->bulk_in_ep = ep; - else { - self->bulk_out_ep = ep; - self->bulk_out_mtu = endpoint[0].wMaxPacketSize; - } - - ep = endpoint[1].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if ((endpoint[1].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) - self->bulk_in_ep = ep; - else { - self->bulk_out_ep = ep; - self->bulk_out_mtu = endpoint[1].wMaxPacketSize; - } - - if (self->bulk_out_ep == 0 || self->bulk_in_ep == 0 || - endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK || - endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK) - { - ERROR(__FUNCTION__ "(), Bogus endpoints"); - return NULL; - } - - /* Find IrDA class descriptor */ - irda_desc = irda_usb_find_class_desc(dev, ifnum); - if (irda_desc == NULL) - return NULL; - - self->irda_desc = irda_desc; - self->present = 1; - self->netopen = 0; - self->capability = capability; - self->usbdev = dev; - ret = irda_usb_open(self); - if (ret) - return NULL; - - return self; } +/*------------------------------------------------------------------*/ /* - * Function irda_usb_find_class_desc(dev, ifnum) - * - * Returns instance of IrDA class descriptor, or NULL if not found - * + * Send a command to change the speed of the dongle */ -static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum) +static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) { - struct usb_interface_descriptor *interface; - struct irda_class_desc *desc, *ptr; + unsigned long flags; + __u8 *frame; + purb_t purb; int ret; - - desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL); - if (desc == NULL) - return NULL; - memset(desc, 0, sizeof(struct irda_class_desc)); - - ret = usb_get_class_descriptor(dev, ifnum, USB_DT_IRDA, 0, (void *) desc, sizeof(struct irda_class_desc)); - IRDA_DEBUG(0, __FUNCTION__ "(), ret=%d\n", ret); - if (ret) { - WARNING("usb-irda: usb_get_class_descriptor failed (0x%x)\n", ret); + + IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, xbofs=%d\n", + self->new_speed, self->new_xbofs); + + /* Grab the speed URB */ + purb = &self->speed_urb; + if (purb->status != USB_ST_NOERROR) { + WARNING(__FUNCTION__ "(), URB still in use!\n"); + return; } - /* Check if we found it? */ - if (desc->bDescriptorType == USB_DT_IRDA) - return desc; + spin_lock_irqsave(&self->lock, flags); - IRDA_DEBUG(0, __FUNCTION__ "(), parsing extra descriptors ...\n"); - - /* Check if the class descriptor is interleaved with standard descriptors */ - interface = &dev->actconfig->interface[ifnum].altsetting[0]; - ret = usb_get_extra_descriptor(interface, USB_DT_IRDA, &ptr); - if (ret) { - kfree(desc); - return NULL; + /* Allocate the fake frame */ + frame = self->speed_buff; + + /* Set the new speed and xbofs in this fake frame */ + irda_usb_build_header(self, frame, 1); + + /* Submit the 0 length IrDA frame to trigger new speed settings */ + FILL_BULK_URB(purb, self->usbdev, + usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), + frame, IRDA_USB_SPEED_MTU, + speed_bulk_callback, self); + purb->transfer_buffer_length = USB_IRDA_HEADER; + purb->transfer_flags = USB_QUEUE_BULK; + purb->timeout = MSECS_TO_JIFFIES(100); + + if ((ret = usb_submit_urb(purb))) { + IRDA_DEBUG(0, __FUNCTION__ "(), failed Speed URB\n"); } - *desc = *ptr; -#if 0 - irda_usb_dump_class_desc(desc); -#endif - return desc; + spin_unlock_irqrestore(&self->lock, flags); } +#ifdef IU_BUG_KICK_TX +/*------------------------------------------------------------------*/ /* - * Function usb_irda_dump_class_desc(desc) - * - * Prints out the contents of the IrDA class descriptor - * + * Send an empty URB to the dongle + * The goal there is to try to resynchronise with the dongle. An empty + * frame signify the end of a Tx frame. Jean II */ -static void irda_usb_dump_class_desc(struct irda_class_desc *desc) +static inline void irda_usb_send_empty(struct irda_usb_cb *self) { - printk("bLength=%x\n", desc->bLength); - printk("bDescriptorType=%x\n", desc->bDescriptorType); - printk("bcdSpecRevision=%x\n", desc->bcdSpecRevision); - printk("bmDataSize=%x\n", desc->bmDataSize); - printk("bmWindowSize=%x\n", desc->bmWindowSize); - printk("bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime); - printk("wBaudRate=%x\n", desc->wBaudRate); - printk("bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs); - printk("bIrdaRateSniff=%x\n", desc->bIrdaRateSniff); - printk("bMaxUnicastList=%x\n", desc->bMaxUnicastList); -} - -static void irda_usb_disconnect(struct usb_device *dev, void *ptr) -{ - struct irda_usb_cb *self = (struct irda_usb_cb *) ptr; - int i; + purb_t purb; + int ret; IRDA_DEBUG(0, __FUNCTION__ "()\n"); - /* Oups ! We are not there any more */ - self->present = 0; - - /* Hum... Check if networking is still active */ - if (self->netopen) { - /* Accept no more transmissions */ - /*netif_device_detach(self->netdev);*/ - netif_stop_queue(self->netdev); - /* Stop all the receive URBs */ - for (i = 0; i < IU_MAX_RX_URBS; i++) - usb_unlink_urb(&(self->rx_urb[i])); - /* Cancel Tx and speed URB */ - usb_unlink_urb(&(self->tx_urb)); - usb_unlink_urb(&(self->speed_urb)); - - IRDA_DEBUG(0, __FUNCTION__ "(), postponing disconnect, network is still active...\n"); - /* better not do anything just yet, usb_irda_cleanup() - * will do whats needed */ + /* Grab the empty URB */ + purb = &self->empty_urb; + if (purb->status != USB_ST_NOERROR) { + WARNING(__FUNCTION__ "(), Empty URB still in use!\n"); return; } - /* Cleanup the device stuff */ - irda_usb_close(self); - /* No longer attached to USB bus */ - self->usbdev = NULL; - IRDA_DEBUG(0, __FUNCTION__ "(), USB IrDA Disconnected\n"); -} + /* Submit the Empty URB */ + FILL_BULK_URB(purb, self->usbdev, + usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), + self->speed_buff, IRDA_USB_SPEED_MTU, + speed_bulk_callback, self); + purb->transfer_buffer_length = 0; + purb->transfer_flags = USB_QUEUE_BULK; + purb->timeout = MSECS_TO_JIFFIES(100); -static struct usb_driver irda_driver = { - name: "irda-usb", - probe: irda_usb_probe, - disconnect: irda_usb_disconnect, - id_table: dongles, -}; + if ((ret = usb_submit_urb(purb))) { + IRDA_DEBUG(0, __FUNCTION__ "(), failed Empty URB\n"); + } +} +#endif /* IU_BUG_KICK_TX */ -static void irda_usb_init_qos(struct irda_usb_cb *self) +/*------------------------------------------------------------------*/ +/* + * Note : this function will be called with both speed_urb and empty_urb... + */ +static void speed_bulk_callback(purb_t purb) { - struct irda_class_desc *desc; - - desc = self->irda_desc; + struct irda_usb_cb *self = purb->context; - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&self->qos); - - self->qos.baud_rate.bits = desc->wBaudRate; - self->qos.min_turn_time.bits = desc->bmMinTurnaroundTime; - self->qos.additional_bofs.bits = desc->bmAdditionalBOFs; - self->qos.window_size.bits = desc->bmWindowSize; - self->qos.data_size.bits = desc->bmDataSize; + IRDA_DEBUG(2, __FUNCTION__ "()\n"); - IRDA_DEBUG(0, __FUNCTION__ "(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits); + /* We should always have a context */ + if (self == NULL) { + IRDA_DEBUG(0, __FUNCTION__ "(), Bug : self == NULL\n"); + return; + } - /* Don't always trust what the dongle tell us */ - if (self->capability & IUC_SIR_ONLY) - self->qos.baud_rate.bits &= 0xff; - if (self->capability & IUC_SMALL_PKT) - self->qos.data_size.bits = 0x07; - if (self->capability & IUC_NO_WINDOW) - self->qos.window_size.bits = 0x01; - if (self->capability & IUC_MAX_WINDOW) - self->qos.window_size.bits = 0x7f; - if (self->capability & IUC_MAX_XBOFS) - self->qos.additional_bofs.bits = 0x01; + /* Check for timeout and other USB nasties */ + if(purb->status != USB_ST_NOERROR) { + /* I get a lot of -ECONNABORTED = -103 here - Jean II */ + WARNING(__FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags); + + /* Don't do anything here, that might confuse the USB layer. + * Instead, we will wait for irda_usb_net_timeout(), the + * network layer watchdog, to fix the situation. + * Jean II */ + /* A reset of the dongle might be welcomed here - Jean II */ + return; + } -#if 1 - /* Module parameter can override the rx window size */ - if (qos_mtt_bits) - self->qos.min_turn_time.bits = qos_mtt_bits; -#endif - /* - * Note : most of those values apply only for the receive path, - * the transmit path will be set differently - Jean II - */ - irda_qos_bits_to_value(&self->qos); + /* urb is now available */ + purb->status = USB_ST_NOERROR; - self->flags |= IFF_SIR; - if (self->qos.baud_rate.value > 115200) - self->flags |= IFF_MIR; - if (self->qos.baud_rate.value > 1152000) - self->flags |= IFF_FIR; - if (self->qos.baud_rate.value > 4000000) - self->flags |= IFF_VFIR; + /* If it was the speed URB, allow the stack to send more packets */ + if(purb == &self->speed_urb) { + netif_wake_queue(self->netdev); + } } -static int irda_usb_open(struct irda_usb_cb *self) +/*------------------------------------------------------------------*/ +/* + * Send an IrDA frame to the USB dongle (for transmission) + */ +static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) { - struct net_device *netdev; - int err; + struct irda_usb_cb *self = netdev->priv; + purb_t purb = &self->tx_urb; + unsigned long flags; + s32 speed; + s16 xbofs; + int res, mtt; - IRDA_DEBUG(0, __FUNCTION__ "()\n"); + /* Check if the device is still there */ + if ((!self) || (!self->present)) { + IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n"); + return 1; /* Failed */ + } - spin_lock_init(&self->lock); + netif_stop_queue(netdev); - irda_usb_init_qos(self); - - self->tx_list = hashbin_new(HB_GLOBAL); + /* Check if we need to change the number of xbofs */ + xbofs = irda_get_next_xbofs(skb); + if ((xbofs != self->xbofs) && (xbofs != -1)) { + self->new_xbofs = xbofs; + } - /* Create a network device for us */ - if (!(netdev = dev_alloc("irda%d", &err))) { - ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); - return -1; + /* Check if we need to change the speed */ + speed = irda_get_next_speed(skb); + if ((speed != self->speed) && (speed != -1)) { + /* Set the desired speed */ + self->new_speed = speed; + + /* Check for empty frame */ + if (!skb->len) { + /* IrLAP send us an empty frame to make us change the + * speed. Changing speed with the USB adapter is in + * fact sending an empty frame to the adapter, so we + * could just let the present function do its job. + * However, we would wait for min turn time, + * do an extra memcpy and increment packet counters... + * Jean II */ + irda_usb_change_speed_xbofs(self); + netdev->trans_start = jiffies; + dev_kfree_skb(skb); + /* Will netif_wake_queue() in callback */ + return 0; + } } - self->netdev = netdev; - netdev->priv = (void *) self; - /* Override the network functions we need to use */ - netdev->init = irda_usb_net_init; - netdev->hard_start_xmit = irda_usb_hard_xmit; - netdev->tx_timeout = irda_usb_net_timeout; - netdev->watchdog_timeo = 110*HZ/1000; /* 110 ms > USB timeout */ - netdev->open = irda_usb_net_open; - netdev->stop = irda_usb_net_close; - netdev->get_stats = irda_usb_net_get_stats; - netdev->do_ioctl = irda_usb_net_ioctl; + if (purb->status != USB_ST_NOERROR) { + WARNING(__FUNCTION__ "(), URB still in use!\n"); + dev_kfree_skb(skb); + return 0; + } - rtnl_lock(); - err = register_netdevice(netdev); - rtnl_unlock(); - if (err) { - ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); - return -1; + /* Make room for IrDA-USB header (note skb->len += USB_IRDA_HEADER) */ + if (skb_cow(skb, USB_IRDA_HEADER)) { + dev_kfree_skb(skb); + return 0; } - MESSAGE("IrDA: Registered device %s\n", netdev->name); - return 0; -} + spin_lock_irqsave(&self->lock, flags); -static int irda_usb_close(struct irda_usb_cb *self) -{ - IRDA_DEBUG(0, __FUNCTION__ "()\n"); + /* Change setting for next frame */ + irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0); - ASSERT(self != NULL, return -1;); + /* FIXME: Make macro out of this one */ + ((struct irda_skb_cb *)skb->cb)->context = self; - /* Remove netdevice */ - if (self->netdev) { - rtnl_lock(); - unregister_netdevice(self->netdev); - self->netdev = NULL; - rtnl_unlock(); + FILL_BULK_URB(purb, self->usbdev, + usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), + skb->data, IRDA_USB_MAX_MTU, + write_bulk_callback, skb); + purb->transfer_buffer_length = skb->len; + purb->transfer_flags = USB_QUEUE_BULK; +#ifdef IU_USE_USB_ZERO_FLAG + /* This flag indicates that what we send is not a continuous stream + * of data but separate frames. In this case, the USB layer will + * insert empty packet to separate our frames. + * This flag was previously called USB_DISABLE_SPD - Jean II */ + purb->transfer_flags |= USB_ZERO_PACKET; +#endif /* IU_USE_USB_ZERO_FLAG */ + purb->timeout = MSECS_TO_JIFFIES(100); + + /* Generate min turn time. FIXME: can we do better than this? */ + /* Trying to a turnaround time at this level is trying to measure + * processor clock cycle with a watch, approximate at best... + * + * What we know is the last time we received a frame over USB. + * Due to latency over USB that depend on the USB load, we don't + * know when this frame was received over IrDA (a few ms before ?) + * Then, same story for our outgoing frame... + * + * In theory, the USB dongle is supposed to handle the turnaround + * by itself (spec 1.0, chater 4, page 6). Who knows ??? That's + * why this code is enabled only for dongles that doesn't meet + * the spec. + * Jean II */ + if (self->capability & IUC_NO_TURN) { + mtt = irda_get_mtt(skb); + if (mtt) { + int diff; + get_fast_time(&self->now); + diff = self->now.tv_usec - self->stamp.tv_usec; + if (diff < 0) + diff += 1000000; + + /* Check if the mtt is larger than the time we have + * already used by all the protocol processing + */ + if (mtt > diff) { + mtt -= diff; + if (mtt > 1000) + mdelay(mtt/1000); + else + udelay(mtt); + } + } } - hashbin_delete(self->tx_list, (FREE_FUNC) &dev_kfree_skb_any); + + if ((res = usb_submit_urb(purb))) { + IRDA_DEBUG(0, __FUNCTION__ "(), failed Tx URB\n"); + self->stats.tx_errors++; + /* Let USB recover : We will catch that in the watchdog */ + /*netif_start_queue(netdev);*/ + } else { + /* Increment packet stats */ + self->stats.tx_packets++; + self->stats.tx_bytes += skb->len; + + netdev->trans_start = jiffies; + +#ifdef IU_BUG_KICK_TX + /* Kick Tx? + * If the packet is a multiple of 64, the USB layer + * should send an empty frame (a short packet) to signal + * the end of frame (that's part of the USB spec). + * If we enable USB_ZERO_PACKET, the USB layer will just do + * that (more efficiently) and this code is useless. + * Better keep this code until USB code clear up this mess... + * + * Note : we can't use the speed URB, because the frame + * might contain a speed change that may be deferred + * (so we have hard_xmit => tx_urb+empty_urb+speed_urb). + * Jean II */ + if ((skb->len % self->bulk_out_mtu) == 0) { + IRDA_DEBUG(2, __FUNCTION__ "(), Kick Tx...\n"); + irda_usb_send_empty(self); + } +#endif /* IU_BUG_KICK_TX */ + } + spin_unlock_irqrestore(&self->lock, flags); return 0; } +/*------------------------------------------------------------------*/ /* - * Function irda_usb_build_header(self, skb, header) - * - * Builds USB-IrDA outbound header - * - * Important note : the USB-IrDA spec 1.0 say very clearly in chapter 5.4.2.2 - * that the setting of the link speed and xbof number in this outbound header - * should be applied *AFTER* the frame has been sent. - * Unfortunately, some devices are not compliant with that... It seems that - * reading the spec is far too difficult... - * Jean II + * Note : this function will be called only for tx_urb... */ -static void irda_usb_build_header(struct irda_usb_cb *self, u8 *header, - int force) +static void write_bulk_callback(purb_t purb) { - /* Set the negotiated link speed */ - if (self->new_speed != -1) { - /* Hum... Ugly hack :-( - * Some device are not compliant with the spec and change - * parameters *before* sending the frame. - Jean II - */ - if ((self->capability & IUC_SPEED_BUG) && - (!force) && (self->speed != -1)) - { - /* No speed and xbofs change here - * (we'll do it later in the write callback) */ - IRDA_DEBUG(2, __FUNCTION__ "(), not changing speed yet\n"); - *header = 0; - return; - } + struct sk_buff *skb = purb->context; + struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context; + + IRDA_DEBUG(2, __FUNCTION__ "()\n"); - IRDA_DEBUG(2, __FUNCTION__ "(), changing speed to %d\n", self->new_speed); - self->speed = self->new_speed; - self->new_speed = -1; + /* We should always have a context */ + if (self == NULL) { + IRDA_DEBUG(0, __FUNCTION__ "(), Bug : self == NULL\n"); + return; + } - switch (self->speed) { - case 2400: - *header = SPEED_2400; - break; - default: - case 9600: - *header = SPEED_9600; - break; - case 19200: - *header = SPEED_19200; - break; - case 38400: - *header = SPEED_38400; - break; - case 57600: - *header = SPEED_57600; - break; - case 115200: - *header = SPEED_115200; - break; - case 576000: - *header = SPEED_576000; - break; - case 1152000: - *header = SPEED_1152000; - break; - case 4000000: - *header = SPEED_4000000; - self->new_xbofs = 0; - break; - } - } else - /* No change */ - *header = 0; - - /* Set the negotiated additional XBOFS */ - if (self->new_xbofs != -1) { - IRDA_DEBUG(0, __FUNCTION__ "(), changing xbofs to %d\n", self->new_xbofs); - self->xbofs = self->new_xbofs; - self->new_xbofs = -1; + /* Free up the skb */ + dev_kfree_skb_any(skb); + purb->context = NULL; - switch (self->xbofs) { - case 48: - *header |= 0x10; - break; - case 28: - case 24: /* USB spec 1.0 says 24 */ - *header |= 0x20; - break; - default: - case 12: - *header |= 0x30; - break; - case 5: /* Bug in IrLAP spec? (should be 6) */ - case 6: - *header |= 0x40; - break; - case 3: - *header |= 0x50; - break; - case 2: - *header |= 0x60; - break; - case 1: - *header |= 0x70; - break; - case 0: - *header |= 0x80; - break; - } + /* Check for timeout and other USB nasties */ + if(purb->status != USB_ST_NOERROR) { + /* I get a lot of -ECONNABORTED = -103 here - Jean II */ + WARNING(__FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags); + + /* Don't do anything here, that might confuse the USB layer, + * and we could go in recursion and blow the kernel stack... + * Instead, we will wait for irda_usb_net_timeout(), the + * network layer watchdog, to fix the situation. + * Jean II */ + /* A reset of the dongle might be welcomed here - Jean II */ + return; } -} - -static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) -{ - struct sk_buff *skb; - unsigned long flags; - purb_t purb; - int ret; - IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, xbofs=%d\n", - self->new_speed, self->new_xbofs); + /* urb is now available */ + purb->status = USB_ST_NOERROR; - purb = &self->speed_urb; - if (purb->status != USB_ST_NOERROR) { - WARNING(__FUNCTION__ "(), URB still in use!\n"); + /* If the network is closed, stop everything */ + if ((!self->netopen) || (!self->present)) { + IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone...\n"); return; } - spin_lock_irqsave(&self->lock, flags); - - /* Allocate the fake frame */ - skb = dev_alloc_skb(IRDA_USB_SPEED_MTU); - if (!skb) - return; - ((struct irda_skb_cb *)skb->cb)->context = self; - - /* Set the new speed and xbofs in this fake frame */ - irda_usb_build_header(self, skb_put(skb, USB_IRDA_HEADER), 1); - - /* Submit the 0 length IrDA frame to trigger new speed settings */ - FILL_BULK_URB(purb, self->usbdev, - usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), - skb->data, IRDA_USB_MAX_MTU, - write_bulk_callback, skb); - purb->transfer_buffer_length = skb->len; - purb->transfer_flags |= USB_QUEUE_BULK; - purb->timeout = MSECS_TO_JIFFIES(100); - if ((ret = usb_submit_urb(purb))) { - IRDA_DEBUG(0, __FUNCTION__ "(), failed Speed URB\n"); + /* If we need to change the speed or xbofs, do it now */ + if ((self->new_speed != -1) || (self->new_xbofs != -1)) { + IRDA_DEBUG(0, __FUNCTION__ "(), Changing speed now...\n"); + irda_usb_change_speed_xbofs(self); + } else { + /* Otherwise, allow the stack to send more packets */ + netif_wake_queue(self->netdev); } - spin_unlock_irqrestore(&self->lock, flags); } -static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) +/*------------------------------------------------------------------*/ +/* + * Watchdog timer from the network layer. + * After a predetermined timeout, if we don't give confirmation that + * the packet has been sent (i.e. no call to netif_wake_queue()), + * the network layer will call this function. + * Note that URB that we submit have also a timeout. When the URB timeout + * expire, the normal URB callback is called (write_bulk_callback()). + */ +static void irda_usb_net_timeout(struct net_device *netdev) { struct irda_usb_cb *self = netdev->priv; - purb_t purb = &self->tx_urb; - unsigned long flags; - s32 speed; - s16 xbofs; - int mtt; + purb_t purb; + int done = 0; /* If we have made any progress */ + + IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n"); - /* Check if the device is still there */ if ((!self) || (!self->present)) { - IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n"); - return 1; /* Failed */ + WARNING(__FUNCTION__ "(), device not present!\n"); + netif_stop_queue(netdev); + return; } - netif_stop_queue(netdev); +#ifdef IU_BUG_KICK_TX + /* Check empty URB */ + purb = &(self->empty_urb); + if (purb->status != USB_ST_NOERROR) { + WARNING("%s: Empty change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags); - /* Check if we need to change the number of xbofs */ - xbofs = irda_get_next_xbofs(skb); - if ((xbofs != self->xbofs) && (xbofs != -1)) { - self->new_xbofs = xbofs; + switch (purb->status) { + case -ECONNABORTED: /* -103 */ + case -ECONNRESET: /* -104 */ + case -ENOENT: /* -2 */ + purb->status = USB_ST_NOERROR; + done = 1; + break; + case USB_ST_URB_PENDING: /* -EINPROGRESS == -115 */ + usb_unlink_urb(purb); + /* Note : above will *NOT* call netif_wake_queue() + * in completion handler - Jean II */ + done = 1; + break; + default: + /* ??? */ + break; + } } +#endif /* IU_BUG_KICK_TX */ - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->speed) && (speed != -1)) { - /* Set the desired speed */ - self->new_speed = speed; + /* Check speed URB */ + purb = &(self->speed_urb); + if (purb->status != USB_ST_NOERROR) { + WARNING("%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags); - /* Check for empty frame */ - if (!skb->len) { - /* IrLAP send us an empty frame to make us change the - * speed. Changing speed with the USB adapter is in - * fact sending an empty frame to the adapter, so we - * could just let the present function do its job. - * However, we would wait for min turn time, - * do an extra memcpy and increment packet counters... - * Jean II */ - irda_usb_change_speed_xbofs(self); - netdev->trans_start = jiffies; - dev_kfree_skb(skb); - /* Will netif_wake_queue() in callback */ - return 0; + switch (purb->status) { + case -ECONNABORTED: /* -103 */ + case -ECONNRESET: /* -104 */ + case -ENOENT: /* -2 */ + purb->status = USB_ST_NOERROR; + netif_wake_queue(self->netdev); + done = 1; + break; + case USB_ST_URB_PENDING: /* -EINPROGRESS == -115 */ + usb_unlink_urb(purb); + /* Note : above will call netif_wake_queue() + * in completion handler - Jean II */ + done = 1; + break; + default: + /* ??? */ + break; } } + /* Check Tx URB */ + purb = &(self->tx_urb); if (purb->status != USB_ST_NOERROR) { - WARNING(__FUNCTION__ "(), URB still in use!\n"); - dev_kfree_skb(skb); - return 0; - } - - /* Make room for IrDA-USB header */ - if (skb_cow(skb, USB_IRDA_HEADER)) { - dev_kfree_skb(skb); - return 0; - } + struct sk_buff *skb = purb->context; - spin_lock_irqsave(&self->lock, flags); - - /* Change setting for next frame */ - irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0); + WARNING("%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags); - /* FIXME: Make macro out of this one */ - ((struct irda_skb_cb *)skb->cb)->context = self; + /* Increase error count */ + self->stats.tx_errors++; - FILL_BULK_URB(purb, self->usbdev, - usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), - skb->data, IRDA_USB_MAX_MTU, - write_bulk_callback, skb); - purb->transfer_buffer_length = skb->len; - purb->transfer_flags |= USB_QUEUE_BULK; - purb->timeout = MSECS_TO_JIFFIES(100); - - /* Generate min turn time */ - mtt = irda_get_mtt(skb); - if (mtt) { - int diff; - get_fast_time(&self->now); - diff = self->now.tv_usec - self->stamp.tv_usec; - if (diff < 0) - diff += 1000000; +#ifdef IU_BUG_KICK_TIMEOUT + /* Can't be a bad idea to reset the speed ;-) - Jean II */ + if(self->new_speed == -1) + self->new_speed = self->speed; + if(self->new_xbofs == -1) + self->new_xbofs = self->xbofs; + irda_usb_change_speed_xbofs(self); +#endif /* IU_BUG_KICK_TIMEOUT */ - /* Check if the mtt is larger than the time we have - * already used by all the protocol processing - */ - if (mtt > diff) { - mtt -= diff; - if (mtt > 1000) { - /* - * FIXME: can we do better than this? Maybe call - * a function which sends a frame to a non - * existing device, or change the speed to the - * current one a number of times just to burn - * time a better way. - */ - mdelay(mtt/1000); - irda_usb_write_bulk(self, purb); - goto out; - } else - udelay(mtt); + switch (purb->status) { + case -ECONNABORTED: /* -103 */ + case -ECONNRESET: /* -104 */ + case -ENOENT: /* -2 */ + if(skb != NULL) { + dev_kfree_skb_any(skb); + purb->context = NULL; + } + purb->status = USB_ST_NOERROR; + netif_wake_queue(self->netdev); + done = 1; + break; + case USB_ST_URB_PENDING: /* -EINPROGRESS == -115 */ + usb_unlink_urb(purb); + /* Note : above will call netif_wake_queue() + * in completion handler - Jean II */ + done = 1; + break; + default: + /* ??? */ + break; } - } - irda_usb_write_bulk(self, purb); -out: - spin_unlock_irqrestore(&self->lock, flags); - - return 0; -} + } -static void irda_usb_write_bulk(struct irda_usb_cb *self, purb_t purb) -{ - int len = purb->transfer_buffer_length; - int res; - - if ((res = usb_submit_urb(purb))) { - IRDA_DEBUG(0, __FUNCTION__ "(), failed Tx URB\n"); - self->stats.tx_errors++; - netif_start_queue(self->netdev); + /* Maybe we need a reset */ + /* Note : Some drivers seem to use a usb_set_interface() when they + * need to reset the hardware. Hum... + */ - return; - } - self->stats.tx_packets++; - self->stats.tx_bytes += len; - self->netdev->trans_start = jiffies; - - /* Send empty frame if size if a multiple of the USB max packet size */ - ASSERT(self->bulk_out_mtu == 64, return;); - if ((len % self->bulk_out_mtu) == 0) { - /* Borrow speed urb */ - purb = &self->speed_urb; - FILL_BULK_URB(purb, self->usbdev, - usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), - self, /* Anything not on the stack will do */ - IRDA_USB_MAX_MTU, NULL, NULL); - purb->transfer_buffer_length = 0; - purb->transfer_flags |= USB_QUEUE_BULK; - res = usb_submit_urb(purb); - } + /* if(done == 0) */ } +/************************* RECEIVE ROUTINES *************************/ /* - * Note : this function will be called with both tx_urb and speed_urb... + * Receive packets from the USB layer stack and pass them to the IrDA stack. + * Try to work around USB failures... */ -static void write_bulk_callback(purb_t purb) -{ - struct sk_buff *skb = purb->context; - struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context; - - /* We should always have a context */ - if (self == NULL) { - IRDA_DEBUG(0, __FUNCTION__ "(), Bug : self == NULL\n"); - return; - } - /* urb is now available */ - purb->status = USB_ST_NOERROR; +/*------------------------------------------------------------------*/ +/* + * Submit a Rx URB to the USB layer to handle reception of a frame + * + * Important note : + * The function process_urb() in usb-uhci.c contains the following code : + * > urb->complete ((struct urb *) urb); + * > // Re-submit the URB if ring-linked + * > if (is_ring && (urb->status != -ENOENT) && !contains_killed) { + * > urb->dev=usb_dev; + * > uhci_submit_urb (urb); + * > } + * The way I see it is that if we submit more than one Rx URB at a + * time, the Rx URB can be automatically re-submitted after the + * completion handler is called. + * We make sure to disable this feature by setting urb->next to NULL + * + * My take is that it's a questionable feature, and quite difficult + * to control and to make work effectively. + * The outcome (re-submited or not) depend on various complex + * test ('is_ring' and 'contains_killed'), and the completion handler + * don't have this information, so basically the driver has no way + * to know if URB are resubmitted or not. Yuck ! + * If everything is perfect, it's cool, but the problem is when + * an URB is killed (timeout, call to unlink_urb(), ...), things get + * messy... + * The other problem is that this scheme deal only with the URB + * and ignore everything about the associated buffer. So, it would + * resubmit URB even if the buffer is still in use or non-existent. + * On the other hand, submitting ourself in the completion callback + * is quite trivial and work well (this function). + * Moreover, this scheme doesn't allow to have an idle URB, which is + * necessary to overcome some URB failures. + * + * Jean II + */ +static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, purb_t purb) +{ + struct irda_skb_cb *cb; + int ret; - dev_kfree_skb_any(skb); - purb->context = NULL; + IRDA_DEBUG(2, __FUNCTION__ "()\n"); - /* Check for timeout and other USB nasties */ - if (purb->status != USB_ST_NOERROR) { - /* I get a lot of -ECONNABORTED = -103 here - Jean II */ - WARNING(__FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", - purb->status, purb->transfer_flags); - /* Don't do anything here, that might confuse the USB layer, - * and we could go in recursion and blow the kernel stack... - * Instead, we will wait for irda_usb_net_timeout(), the - * network layer watchdog, to fix the situation. - * Jean II */ - /* A reset of the dongle might be welcomed here - Jean II */ - return; - } - - - /* URB is now available */ - purb->status = USB_ST_NOERROR; - - /* If the network is closed, stop everything */ - if ((!self->netopen) || (!self->present)) { - IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone...\n"); - return; - } - - /* If we need to change the speed or xbofs, do it now */ - if ((self->new_speed != -1) || (self->new_xbofs != -1)) { - IRDA_DEBUG(0, __FUNCTION__ "(), Changing speed now...\n"); - irda_usb_change_speed_xbofs(self); - } else { - /* Otherwise, allow the stack to send more packets */ - netif_wake_queue(self->netdev); - } -} - -static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, purb_t purb) -{ - struct irda_skb_cb *cb; - int ret; - - IRDA_DEBUG(2, __FUNCTION__ "()\n"); - - /* Check that we have an urb */ - if (!purb) { - IRDA_DEBUG(0, __FUNCTION__ "(), Bug : purb == NULL\n"); - return; + /* Check that we have an urb */ + if (!purb) { + IRDA_DEBUG(0, __FUNCTION__ "(), Bug : purb == NULL\n"); + return; } /* Allocate new skb if it has not been recycled */ @@ -804,9 +739,9 @@ usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep), skb->data, skb->truesize, irda_usb_receive, skb); - purb->transfer_flags |= USB_QUEUE_BULK; + purb->transfer_flags = USB_QUEUE_BULK; purb->status = USB_ST_NOERROR; - purb->next = NULL; /* Make sure we don't auto resubmit */ + purb->next = NULL; /* Don't auto resubmit URBs */ ret = usb_submit_urb(purb); if (ret) { @@ -816,6 +751,7 @@ } } +/*------------------------------------------------------------------*/ /* * Function irda_usb_receive(purb) * @@ -829,6 +765,8 @@ struct irda_skb_cb *cb; struct sk_buff *new; + IRDA_DEBUG(2, __FUNCTION__ "(), len=%d\n", purb->actual_length); + /* Find ourselves */ cb = (struct irda_skb_cb *) skb->cb; ASSERT(cb != NULL, return;); @@ -843,25 +781,25 @@ } /* Check the status */ - if (purb->status != USB_ST_NOERROR) { + if(purb->status != USB_ST_NOERROR) { switch (purb->status) { case USB_ST_CRC: /* -EILSEQ */ self->stats.rx_errors++; self->stats.rx_crc_errors++; break; - case -ECONNRESET: - WARNING(__FUNCTION__ "(), Connection Reset !!!\n"); + case -ECONNRESET: /* -104 */ + WARNING(__FUNCTION__ "(), Connection Reset (-104), transfer_flags 0x%04X \n", purb->transfer_flags); /* uhci_cleanup_unlink() is going to kill the Rx * URB just after we return. No problem, at this * point the URB will be idle ;-) - Jean II */ break; default: - WARNING(__FUNCTION__ "(), RX status %d\n", purb->status); + WARNING(__FUNCTION__ "(), RX status %d,transfer_flags 0x%04X \n", purb->status, purb->transfer_flags); break; } goto done; } - + /* Check for empty frames */ if (purb->actual_length <= USB_IRDA_HEADER) { WARNING(__FUNCTION__ "(), empty frame!\n"); @@ -892,7 +830,7 @@ /* Copy packet, so we can recycle the original */ memcpy(skb_put(new, skb->len), skb->data, skb->len); - /* We will cleanup the skb in irda_usb_submit */ + /* We will cleanup the skb in irda_usb_submit() */ } else { /* Deliver the original skb */ new = skb; @@ -907,17 +845,65 @@ new->mac.raw = new->data; new->protocol = htons(ETH_P_IRDA); netif_rx(new); + done: - /* Recycle Rx URB (and possible the skb as well) */ - irda_usb_submit(self, skb, self->rx_idle_urb); + /* Note : at this point, the URB we've just received (purb) + * is still referenced by the USB layer. For example, if we + * have received a -ECONNRESET, uhci_cleanup_unlink() will + * continue to process it (in fact, cleaning it up). + * If we were to submit this URB, disaster would ensue. + * Therefore, we submit our idle URB, and put this URB in our + * idle slot.... + * Jean II */ + /* Note : with this scheme, we could submit the idle URB before + * processing the Rx URB. Another time... Jean II */ - /* Recycle Rx URB : Now, the idle URB is the present one */ - self->rx_idle_urb = purb; + /* Submit the idle URB to replace the URB we've just received */ + irda_usb_submit(self, skb, self->idle_rx_urb); + /* Recycle Rx URB : Now, the idle URB is the present one */ + self->idle_rx_urb = purb; purb->context = NULL; - /* Prevent the USB layer playing games with our URBs */ - purb->status = -ENOENT; } +/*------------------------------------------------------------------*/ +/* + * Callbak from IrDA layer. IrDA wants to know if we have + * started receiving anything. + */ +static int irda_usb_is_receiving(struct irda_usb_cb *self) +{ + /* Note : because of the way UHCI works, it's almost impossible + * to get this info. The Controller DMA directly to memory and + * signal only when the whole frame is finished. To know if the + * first TD of the URB has been filled or not seems hard work... + * + * The other solution would be to use the "receiving" command + * on the default decriptor with a usb_control_msg(), but that + * would add USB traffic and would return result only in the + * next USB frame (~1ms). + * + * I've been told that current dongles send status info on their + * interrupt endpoint, and that's what the Windows driver uses + * to know this info. Unfortunately, this is not yet in the spec... + * + * Jean II + */ + + return 0; /* For now */ +} + +/********************** IRDA DEVICE CALLBACKS **********************/ +/* + * Main calls from the IrDA/Network subsystem. + * Mostly registering a new irda-usb device and removing it.... + * We only deal with the IrDA side of the business, the USB side will + * be dealt with below... + */ + +/*------------------------------------------------------------------*/ +/* + * Callback when a new IrDA device is created. + */ static int irda_usb_net_init(struct net_device *dev) { IRDA_DEBUG(0, __FUNCTION__ "()\n"); @@ -930,6 +916,7 @@ return 0; } +/*------------------------------------------------------------------*/ /* * Function irda_usb_net_open (dev) * @@ -940,6 +927,7 @@ static int irda_usb_net_open(struct net_device *netdev) { struct irda_usb_cb *self; + char hwname[16]; int i; IRDA_DEBUG(0, __FUNCTION__ "()\n"); @@ -970,174 +958,597 @@ * Open new IrLAP layer instance to take care of us... * Note : will send immediately a speed change... */ - self->irlap = irlap_open(netdev, &self->qos); + sprintf(hwname, "usb#%d", self->usbdev->devnum); + self->irlap = irlap_open(netdev, &self->qos, hwname); ASSERT(self->irlap != NULL, return -1;); /* Allow IrLAP to send data to us */ netif_start_queue(netdev); - /* Now that we can pass data to IrLAP, allow the USB layer - * to send us some data... */ - for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) - irda_usb_submit(self, NULL, &(self->rx_urb[i])); - /* Note : we submit all the Rx URB except for one - Jean II */ - self->rx_idle_urb = &(self->rx_urb[IU_MAX_ACTIVE_RX_URBS]); - self->rx_idle_urb->context = NULL; + /* Now that we can pass data to IrLAP, allow the USB layer + * to send us some data... */ + for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) + irda_usb_submit(self, NULL, &(self->rx_urb[i])); + /* Note : we submit all the Rx URB except for one - Jean II */ + self->idle_rx_urb = &(self->rx_urb[IU_MAX_ACTIVE_RX_URBS]); + self->idle_rx_urb->context = NULL; + + /* Ready to play !!! */ + MOD_INC_USE_COUNT; + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Function irda_usb_net_close (self) + * + * Network device is taken down. Usually this is done by + * "ifconfig irda0 down" + */ +static int irda_usb_net_close(struct net_device *netdev) +{ + struct irda_usb_cb *self; + int i; + + IRDA_DEBUG(0, __FUNCTION__ "()\n"); + + ASSERT(netdev != NULL, return -1;); + self = (struct irda_usb_cb *) netdev->priv; + ASSERT(self != NULL, return -1;); + + /* Clear this flag *before* unlinking the urbs and *before* + * stopping the network Tx queue - Jean II */ + self->netopen = 0; + + /* Stop network Tx queue */ + netif_stop_queue(netdev); + + /* Deallocate all the Rx path buffers (URBs and skb) */ + for (i = 0; i < IU_MAX_RX_URBS; i++) { + purb_t purb = &(self->rx_urb[i]); + struct sk_buff *skb = (struct sk_buff *) purb->context; + /* Cancel the receive command */ + usb_unlink_urb(purb); + /* The skb is ours, free it */ + if(skb) { + dev_kfree_skb(skb); + purb->context = NULL; + } + } + /* Cancel Tx and speed URB */ + usb_unlink_urb(&(self->tx_urb)); + usb_unlink_urb(&(self->speed_urb)); + + /* Stop and remove instance of IrLAP */ + if (self->irlap) + irlap_close(self->irlap); + self->irlap = NULL; + + MOD_DEC_USE_COUNT; + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * IOCTLs : Extra out-of-band network commands... + */ +static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct if_irda_req *irq = (struct if_irda_req *) rq; + struct irda_usb_cb *self; + int ret = 0; + + ASSERT(dev != NULL, return -1;); + self = dev->priv; + ASSERT(self != NULL, return -1;); + + IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + + /* Check if the device is still there */ + if(!self->present) + return -EFAULT; + + switch (cmd) { + case SIOCSBANDWIDTH: /* Set bandwidth */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + /* Set the desired speed */ + self->new_speed = irq->ifr_baudrate; + irda_usb_change_speed_xbofs(self); + /* Note : will spinlock in above function */ + break; + case SIOCSMEDIABUSY: /* Set media busy */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + irda_device_set_media_busy(self->netdev, TRUE); + break; + case SIOCGRECEIVING: /* Check if we are receiving right now */ + irq->ifr_receiving = irda_usb_is_receiving(self); + break; + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +/*------------------------------------------------------------------*/ +/* + * Get device stats (for /proc/net/dev and ifconfig) + */ +static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev) +{ + struct irda_usb_cb *self = dev->priv; + return &self->stats; +} + +/********************* IRDA CONFIG SUBROUTINES *********************/ +/* + * Various subroutines dealing with IrDA and network stuff we use to + * configure and initialise each irda-usb instance. + * These functions are used below in the main calls of the driver... + */ + +/*------------------------------------------------------------------*/ +/* + * Set proper values in the IrDA QOS structure + */ +static inline void irda_usb_init_qos(struct irda_usb_cb *self) +{ + struct irda_class_desc *desc; + + IRDA_DEBUG(3, __FUNCTION__ "()\n"); + + desc = self->irda_desc; + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies(&self->qos); + + self->qos.baud_rate.bits = desc->wBaudRate; + self->qos.min_turn_time.bits = desc->bmMinTurnaroundTime; + self->qos.additional_bofs.bits = desc->bmAdditionalBOFs; + self->qos.window_size.bits = desc->bmWindowSize; + self->qos.data_size.bits = desc->bmDataSize; + + IRDA_DEBUG(0, __FUNCTION__ "(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits); + + /* Don't always trust what the dongle tell us */ + if(self->capability & IUC_SIR_ONLY) + self->qos.baud_rate.bits &= 0xff; + if(self->capability & IUC_SMALL_PKT) + self->qos.data_size.bits = 0x07; + if(self->capability & IUC_NO_WINDOW) + self->qos.window_size.bits = 0x01; + if(self->capability & IUC_MAX_WINDOW) + self->qos.window_size.bits = 0x7f; + if(self->capability & IUC_MAX_XBOFS) + self->qos.additional_bofs.bits = 0x01; + +#if 1 + /* Module parameter can override the rx window size */ + if (qos_mtt_bits) + self->qos.min_turn_time.bits = qos_mtt_bits; +#endif + /* + * Note : most of those values apply only for the receive path, + * the transmit path will be set differently - Jean II + */ + irda_qos_bits_to_value(&self->qos); + + self->flags |= IFF_SIR; + if (self->qos.baud_rate.value > 115200) + self->flags |= IFF_MIR; + if (self->qos.baud_rate.value > 1152000) + self->flags |= IFF_FIR; + if (self->qos.baud_rate.value > 4000000) + self->flags |= IFF_VFIR; +} + +/*------------------------------------------------------------------*/ +/* + * Initialise the network side of the irda-usb instance + * Called when a new USB instance is registered in irda_usb_probe() + */ +static inline int irda_usb_open(struct irda_usb_cb *self) +{ + struct net_device *netdev; + int err; + + IRDA_DEBUG(0, __FUNCTION__ "()\n"); + + spin_lock_init(&self->lock); + + irda_usb_init_qos(self); + + /* Initialise list of skb beeing curently transmitted */ + self->tx_list = hashbin_new(HB_GLOBAL); + + /* Allocate the buffer for speed changes */ + /* Don't change this buffer size and allocation without doing + * some heavy and complete testing. Don't ask why :-( + * Jean II */ + self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); + if (self->speed_buff == NULL) + return -1; + memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU); + + /* Create a network device for us */ + if (!(netdev = dev_alloc("irda%d", &err))) { + ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); + return -1; + } + self->netdev = netdev; + netdev->priv = (void *) self; + + /* Override the network functions we need to use */ + netdev->init = irda_usb_net_init; + netdev->hard_start_xmit = irda_usb_hard_xmit; + netdev->tx_timeout = irda_usb_net_timeout; + netdev->watchdog_timeo = 110*HZ/1000; /* 110 ms > USB timeout */ + netdev->open = irda_usb_net_open; + netdev->stop = irda_usb_net_close; + netdev->get_stats = irda_usb_net_get_stats; + netdev->do_ioctl = irda_usb_net_ioctl; + + rtnl_lock(); + err = register_netdevice(netdev); + rtnl_unlock(); + if (err) { + ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); + return -1; + } + MESSAGE("IrDA: Registered device %s\n", netdev->name); + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Cleanup the network side of the irda-usb instance + * Called when a USB instance is removed in irda_usb_disconnect() + */ +static inline int irda_usb_close(struct irda_usb_cb *self) +{ + IRDA_DEBUG(0, __FUNCTION__ "()\n"); + + ASSERT(self != NULL, return -1;); + + /* Remove netdevice */ + if (self->netdev) { + rtnl_lock(); + unregister_netdevice(self->netdev); + self->netdev = NULL; + rtnl_unlock(); + } + /* Delete all pending skbs */ + hashbin_delete(self->tx_list, (FREE_FUNC) &dev_kfree_skb_any); + /* Remove the speed buffer */ + if (self->speed_buff != NULL) { + kfree(self->speed_buff); + self->speed_buff = NULL; + } + + return 0; +} + +/********************** USB CONFIG SUBROUTINES **********************/ +/* + * Various subroutines dealing with USB stuff we use to configure and + * initialise each irda-usb instance. + * These functions are used below in the main calls of the driver... + */ + +/*------------------------------------------------------------------*/ +/* + * Function irda_usb_parse_endpoints(dev, ifnum) + * + * Parse the various endpoints and find the one we need. + * + * The endpoint are the pipes used to communicate with the USB device. + * The spec defines 2 endpoints of type bulk transfer, one in, and one out. + * These are used to pass frames back and forth with the dongle. + * Most dongle have also an interrupt endpoint, that will be probably + * documented in the next spec... + */ +static inline int irda_usb_parse_endpoints(struct irda_usb_cb *self, struct usb_endpoint_descriptor *endpoint, int ennum) +{ + int i; /* Endpoint index in table */ + + /* Init : no endpoints */ + self->bulk_in_ep = 0; + self->bulk_out_ep = 0; + self->bulk_int_ep = 0; + + /* Let's look at all those endpoints */ + for(i = 0; i < ennum; i++) { + /* All those variables will get optimised by the compiler, + * so let's aim for clarity... - Jean II */ + __u8 ep; /* Endpoint address */ + __u8 dir; /* Endpoint direction */ + __u8 attr; /* Endpoint attribute */ + __u16 psize; /* Endpoint max packet size in bytes */ + + /* Get endpoint address, direction and attribute */ + ep = endpoint[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + dir = endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK; + attr = endpoint[i].bmAttributes; + psize = endpoint[i].wMaxPacketSize; + + /* Is it a bulk endpoint ??? */ + if(attr == USB_ENDPOINT_XFER_BULK) { + /* We need to find an IN and an OUT */ + if(dir == USB_DIR_IN) { + /* This is our Rx endpoint */ + self->bulk_in_ep = ep; + } else { + /* This is our Tx endpoint */ + self->bulk_out_ep = ep; + self->bulk_out_mtu = psize; + } + } else { + if((attr == USB_ENDPOINT_XFER_INT) && + (dir == USB_DIR_IN)) { + /* This is our interrupt endpoint */ + self->bulk_int_ep = ep; + } else { + ERROR(__FUNCTION__ "(), Unrecognised endpoint %02X.\n", ep); + } + } + } + + IRDA_DEBUG(0, __FUNCTION__ "(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n", self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep); + /* Should be 8, 16, 32 or 64 bytes */ + ASSERT(self->bulk_out_mtu == 64, ;); + + return((self->bulk_in_ep != 0) && (self->bulk_out_ep != 0)); +} + +#ifdef IU_DUMP_CLASS_DESC +/*------------------------------------------------------------------*/ +/* + * Function usb_irda_dump_class_desc(desc) + * + * Prints out the contents of the IrDA class descriptor + * + */ +static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc) +{ + printk("bLength=%x\n", desc->bLength); + printk("bDescriptorType=%x\n", desc->bDescriptorType); + printk("bcdSpecRevision=%x\n", desc->bcdSpecRevision); + printk("bmDataSize=%x\n", desc->bmDataSize); + printk("bmWindowSize=%x\n", desc->bmWindowSize); + printk("bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime); + printk("wBaudRate=%x\n", desc->wBaudRate); + printk("bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs); + printk("bIrdaRateSniff=%x\n", desc->bIrdaRateSniff); + printk("bMaxUnicastList=%x\n", desc->bMaxUnicastList); +} +#endif /* IU_DUMP_CLASS_DESC */ + +/*------------------------------------------------------------------*/ +/* + * Function irda_usb_find_class_desc(dev, ifnum) + * + * Returns instance of IrDA class descriptor, or NULL if not found + * + * The class descriptor is some extra info that IrDA USB devices will + * offer to us, describing their IrDA characteristics. We will use that in + * irda_usb_init_qos() + */ +static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum) +{ + struct usb_interface_descriptor *interface; + struct irda_class_desc *desc, *ptr; + int ret; + + desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL); + if (desc == NULL) + return NULL; + memset(desc, 0, sizeof(struct irda_class_desc)); + + ret = usb_get_class_descriptor(dev, ifnum, USB_DT_IRDA, 0, (void *) desc, sizeof(struct irda_class_desc)); + IRDA_DEBUG(0, __FUNCTION__ "(), ret=%d\n", ret); + if (ret) { + WARNING("usb-irda: usb_get_class_descriptor failed (0x%x)\n", ret); + } + + /* Check if we found it? */ + if (desc->bDescriptorType == USB_DT_IRDA) + return desc; - /* Ready to play !!! */ - MOD_INC_USE_COUNT; - return 0; + IRDA_DEBUG(0, __FUNCTION__ "(), parsing extra descriptors ...\n"); + + /* Check if the class descriptor is interleaved with standard descriptors */ + interface = &dev->actconfig->interface[ifnum].altsetting[0]; + ret = usb_get_extra_descriptor(interface, USB_DT_IRDA, &ptr); + if (ret) { + kfree(desc); + return NULL; + } + *desc = *ptr; +#ifdef IU_DUMP_CLASS_DESC + irda_usb_dump_class_desc(desc); +#endif /* IU_DUMP_CLASS_DESC */ + return desc; } +/*********************** USB DEVICE CALLBACKS ***********************/ /* - * Function irda_usb_net_close (self) - * - * Network device is taken down. Usually this is done by - * "ifconfig irda0 down" + * Main calls from the USB subsystem. + * Mostly registering a new irda-usb device and removing it.... */ -static int irda_usb_net_close(struct net_device *netdev) + +/*------------------------------------------------------------------*/ +/* + * This routine is called by the USB subsystem for each new device + * in the system. We need to check if the device is ours, and in + * this case start handling it. + * Note : it might be worth protecting this function by a global + * spinlock... Or not, because maybe USB already deal with that... + */ +static void *irda_usb_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { - struct irda_usb_cb *self; + struct irda_usb_cb *self = NULL; + struct usb_interface_descriptor *interface; + struct irda_class_desc *irda_desc; + int ret; int i; - IRDA_DEBUG(0, __FUNCTION__ "()\n"); - - ASSERT(netdev != NULL, return -1;); - self = (struct irda_usb_cb *) netdev->priv; - ASSERT(self != NULL, return -1;); - - /* Clear this flag *before* unlinking the urbs and *before* - * stopping the network Tx queue - Jean II */ - self->netopen = 0; + /* Note : the probe make sure to call us only for devices that + * matches the list of dongle (top of the file). So, we + * don't need to check if the dongle is really ours. + * Jean II */ - /* Stop network Tx queue */ - netif_stop_queue(netdev); + IRDA_DEBUG(0, "Vendor: %x, Product: %x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); + + MESSAGE("IRDA-USB found at address %d\n", dev->devnum); - /* Deallocate all the Rx path buffers (URBs and skb) */ - for (i = 0; i < IU_MAX_RX_URBS; i++) { - purb_t purb = &(self->rx_urb[i]); - struct sk_buff *skb = (struct sk_buff *) purb->context; - /* Cancel the receive command */ - usb_unlink_urb(purb); - /* The skb is ours, free it */ - if (skb) { - dev_kfree_skb(skb); - purb->context = NULL; + /* Try to cleanup all instance that have a pending disconnect + * Instance will be in this state is the disconnect() occurs + * before the net_close(). + * Jean II */ + for (i = 0; i < NIRUSB; i++) { + struct irda_usb_cb *irda = &irda_instance[i]; + if((irda->usbdev != NULL) && + (irda->present == 0) && + (irda->netopen == 0)) { + IRDA_DEBUG(0, __FUNCTION__ "(), found a zombie instance !!!\n"); + irda_usb_disconnect(irda->usbdev, (void *) irda); } } - /* Cancel Tx and speed URB */ - usb_unlink_urb(&self->tx_urb); - usb_unlink_urb(&self->speed_urb); - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; - - MOD_DEC_USE_COUNT; - - return 0; -} -static void irda_usb_net_timeout(struct net_device *netdev) -{ - struct irda_usb_cb *self = netdev->priv; - int done = 0; /* If we have made any progress */ - purb_t purb; + /* Find an free instance to handle this new device... */ + self = NULL; + for (i = 0; i < NIRUSB; i++) { + if(irda_instance[i].usbdev == NULL) { + self = &irda_instance[i]; + break; + } + } + if(self == NULL) { + IRDA_DEBUG(0, "Too many USB IrDA devices !!! (max = %d)\n", + NIRUSB); + return NULL; + } - IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n"); + /* Reset the instance */ + self->present = 0; + self->netopen = 0; - if (!self || !self->present) { - WARNING(__FUNCTION__ "(), device not present!\n"); - netif_stop_queue(netdev); - return; + /* Is this really necessary? */ + if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) { + err("set_configuration failed"); + return NULL; } - WARNING("%s: Tx timed out\n", netdev->name); - /* Check Tx URB */ - purb = &self->tx_urb; - switch (purb->status) { - case -ECONNABORTED: /* Can't find proper USB_ST_* code */ - purb->status = USB_ST_NOERROR; - netif_wake_queue(self->netdev); - done = 1; + /* Is this really necessary? */ + /* Note : some driver do hardcode the interface number, some others + * specify an alternate, but very few driver do like this. + * Jean II */ + ret = usb_set_interface(dev, ifnum, 0); + IRDA_DEBUG(0, "usb-irda: set interface %d result %d\n", ifnum, ret); + switch (ret) { + case USB_ST_NOERROR: /* 0 */ break; - case USB_ST_URB_PENDING: /* -EINPROGRESS == -115 */ - usb_unlink_urb(purb); - done = 1; + case USB_ST_STALL: /* -EPIPE = -32 */ + usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); + IRDA_DEBUG(0, __FUNCTION__ "(), Clearing stall on control interface\n" ); break; default: + IRDA_DEBUG(0, __FUNCTION__ "(), Unknown error %d\n", ret); + return NULL; break; } - /* Check speed URB */ - purb = &self->speed_urb; - switch (purb->status) { - case -ECONNABORTED: /* Can't find proper USB_ST_* code */ - purb->status = USB_ST_NOERROR; - netif_wake_queue(self->netdev); - done = 1; - break; - case USB_ST_URB_PENDING: /* -EINPROGRESS */ - usb_unlink_urb(purb); - done = 1; - break; - default: - break; + + /* Find our endpoints */ + interface = &dev->actconfig->interface[ifnum].altsetting[0]; + if(!irda_usb_parse_endpoints(self, interface->endpoint, + interface->bNumEndpoints)) { + ERROR(__FUNCTION__ "(), Bogus endpoints...\n"); + return NULL; } - /* Maybe we need a reset */ - /* if(done == 0) */ -} -static int irda_usb_is_receiving(struct irda_usb_cb *self) -{ - return 0; /* For now */ + /* Find IrDA class descriptor */ + irda_desc = irda_usb_find_class_desc(dev, ifnum); + if (irda_desc == NULL) + return NULL; + + self->irda_desc = irda_desc; + self->present = 1; + self->netopen = 0; + self->capability = id->driver_info; + self->usbdev = dev; + ret = irda_usb_open(self); + if (ret) + return NULL; + + return self; } -static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +/*------------------------------------------------------------------*/ +/* + * The current irda-usb device is removed, the USB layer tell us + * to shut it down... + */ +static void irda_usb_disconnect(struct usb_device *dev, void *ptr) { - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct irda_usb_cb *self; - int ret = 0; + struct irda_usb_cb *self = (struct irda_usb_cb *) ptr; + int i; - ASSERT(dev != NULL, return -1;); - self = dev->priv; - ASSERT(self != NULL, return -1;); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); - IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + /* Oups ! We are not there any more */ + self->present = 0; - /* Check if the device is still there */ - if (!self->present) - return -EFAULT; + /* Hum... Check if networking is still active */ + if (self->netopen) { + /* Accept no more transmissions */ + /*netif_device_detach(self->netdev);*/ + netif_stop_queue(self->netdev); + /* Stop all the receive URBs */ + for (i = 0; i < IU_MAX_RX_URBS; i++) + usb_unlink_urb(&(self->rx_urb[i])); + /* Cancel Tx and speed URB */ + usb_unlink_urb(&(self->tx_urb)); + usb_unlink_urb(&(self->speed_urb)); - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - /* Set the desired speed */ - self->new_speed = irq->ifr_baudrate; - irda_usb_change_speed_xbofs(self); - /* Note : will spinlock in above function */ - break; - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - irda_device_set_media_busy(self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - irq->ifr_receiving = irda_usb_is_receiving(self); - break; - default: - ret = -EOPNOTSUPP; + IRDA_DEBUG(0, __FUNCTION__ "(), postponing disconnect, network is still active...\n"); + /* better not do anything just yet, usb_irda_cleanup() + * will do whats needed */ + return; } - return ret; -} -static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev) -{ - struct irda_usb_cb *self = dev->priv; - return &self->stats; + /* Cleanup the device stuff */ + irda_usb_close(self); + /* No longer attached to USB bus */ + self->usbdev = NULL; + IRDA_DEBUG(0, __FUNCTION__ "(), USB IrDA Disconnected\n"); } +/*------------------------------------------------------------------*/ +/* + * USB device callbacks + */ +static struct usb_driver irda_driver = { + name: "irda-usb", + probe: irda_usb_probe, + disconnect: irda_usb_disconnect, + id_table: dongles, +}; + +/************************* MODULE CALLBACKS *************************/ +/* + * Deal with module insertion/removal + * Mostly tell USB about our existence + */ + +/*------------------------------------------------------------------*/ +/* + * Module insertion + */ int __init usb_irda_init(void) { if (usb_register(&irda_driver) < 0) @@ -1148,10 +1559,14 @@ } module_init(usb_irda_init); +/*------------------------------------------------------------------*/ +/* + * Module removal + */ void __exit usb_irda_cleanup(void) { struct irda_usb_cb *irda = NULL; - int i; + int i; /* Find zombie instances and kill them... */ for (i = 0; i < NIRUSB; i++) { @@ -1162,15 +1577,17 @@ irda_usb_disconnect(irda->usbdev, (void *) irda); } } + /* Deregister the driver and remove all pending instances */ usb_deregister(&irda_driver); } module_exit(usb_irda_cleanup); +/*------------------------------------------------------------------*/ +/* + * Module parameters + */ MODULE_PARM(qos_mtt_bits, "i"); MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); MODULE_AUTHOR("Roman Weissgaerber , Dag Brattli and Jean Tourrilhes "); MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); - - - diff -u --recursive --new-file v2.4.9/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c --- v2.4.9/linux/drivers/net/irda/irport.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/irda/irport.c Thu Sep 13 16:26:52 2001 @@ -774,6 +774,7 @@ { struct irport_cb *self; int iobase; + char hwname[16]; IRDA_DEBUG(0, __FUNCTION__ "()\n"); @@ -792,11 +793,14 @@ irport_start(self); + /* Give self a hardware name */ + sprintf(hwname, "SIR @ 0x%03x", self->io.sir_base); + /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ - self->irlap = irlap_open(dev, &self->qos); + self->irlap = irlap_open(dev, &self->qos, hwname); /* FIXME: change speed of dongle */ /* Ready to play! */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- v2.4.9/linux/drivers/net/irda/irtty.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/irda/irtty.c Thu Sep 13 16:26:52 2001 @@ -895,6 +895,8 @@ static int irtty_net_open(struct net_device *dev) { struct irtty_cb *self = (struct irtty_cb *) dev->priv; + struct tty_struct *tty = self->tty; + char hwname[16]; ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRTTY_MAGIC, return -1;); @@ -907,11 +909,16 @@ /* Make sure we can receive more data */ irtty_stop_receiver(self, FALSE); + /* Give self a hardware name */ + sprintf(hwname, "%s%d", tty->driver.name, + MINOR(tty->device) - tty->driver.minor_start + + tty->driver.name_base); + /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ - self->irlap = irlap_open(dev, &self->qos); + self->irlap = irlap_open(dev, &self->qos, hwname); MOD_INC_USE_COUNT; diff -u --recursive --new-file v2.4.9/linux/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c --- v2.4.9/linux/drivers/net/irda/nsc-ircc.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/irda/nsc-ircc.c Thu Sep 13 16:26:52 2001 @@ -1836,6 +1836,7 @@ { struct nsc_ircc_cb *self; int iobase; + char hwname[32]; __u8 bank; IRDA_DEBUG(4, __FUNCTION__ "()\n"); @@ -1874,14 +1875,16 @@ outb(bank, iobase+BSR); /* Ready to play! */ - netif_start_queue(dev); + /* Give self a hardware name */ + sprintf(hwname, "NSC-FIR @ 0x%03x", self->io.fir_base); + /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ - self->irlap = irlap_open(dev, &self->qos); + self->irlap = irlap_open(dev, &self->qos, hwname); MOD_INC_USE_COUNT; diff -u --recursive --new-file v2.4.9/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c --- v2.4.9/linux/drivers/net/irda/toshoboe.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/irda/toshoboe.c Thu Sep 13 16:26:52 2001 @@ -510,6 +510,7 @@ toshoboe_net_open (struct net_device *dev) { struct toshoboe_cb *self; + char hwname[32]; IRDA_DEBUG (4, __FUNCTION__ "()\n"); @@ -537,11 +538,13 @@ /* Ready to play! */ netif_start_queue(dev); + /* Give self a hardware name */ + sprintf(hwname, "Toshiba-FIR @ 0x%03x", self->base); /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ - self->irlap = irlap_open(dev, &self->qos); + self->irlap = irlap_open(dev, &self->qos, hwname); self->open = 1; @@ -695,7 +698,6 @@ { struct toshoboe_cb *self; struct net_device *dev; - struct pm_dev *pmdev; int i = 0; int ok = 0; int err; @@ -844,11 +846,6 @@ goto freebufs; } pci_set_drvdata(pci_dev,self); - -/* pmdev = pm_register (PM_PCI_DEV, PM_PCI_ID(pci_dev), toshoboe_pmproc); - if (pmdev) - pmdev->data = self; - */ printk (KERN_WARNING "ToshOboe: Using "); #ifdef ONETASK diff -u --recursive --new-file v2.4.9/linux/drivers/net/irda/vlsi_ir.c linux/drivers/net/irda/vlsi_ir.c --- v2.4.9/linux/drivers/net/irda/vlsi_ir.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/net/irda/vlsi_ir.c Fri Sep 14 14:39:59 2001 @@ -728,7 +728,7 @@ u8 irintr; int boguscount = 20; int no_speed_check = 0; - unsigned flags; + unsigned long flags; iobase = ndev->base_addr; @@ -776,6 +776,7 @@ { vlsi_irda_dev_t *idev = ndev->priv; struct pci_dev *pdev = idev->pdev; + char hwname[32]; int err; MOD_INC_USE_COUNT; /* still needed? - we have SET_MODULE_OWNER! */ @@ -824,7 +825,8 @@ (idev->mode==IFF_SIR)?"SIR":((idev->mode==IFF_MIR)?"MIR":"FIR"), (sirpulse)?"3/16 bittime":"short"); - idev->irlap = irlap_open(ndev,&idev->qos); + sprintf(hwname, "VLSI-FIR"); + idev->irlap = irlap_open(ndev,&idev->qos,hwname); netif_start_queue(ndev); diff -u --recursive --new-file v2.4.9/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c --- v2.4.9/linux/drivers/net/irda/w83977af_ir.c Tue Mar 20 12:04:59 2001 +++ linux/drivers/net/irda/w83977af_ir.c Thu Sep 13 16:26:52 2001 @@ -1210,6 +1210,7 @@ { struct w83977af_ir *self; int iobase; + char hwname[32]; __u8 set; IRDA_DEBUG(0, __FUNCTION__ "()\n"); @@ -1251,11 +1252,14 @@ /* Ready to play! */ netif_start_queue(dev); + /* Give self a hardware name */ + sprintf(hwname, "w83977af @ 0x%03x", self->io.fir_base); + /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ - self->irlap = irlap_open(dev, &self->qos); + self->irlap = irlap_open(dev, &self->qos, hwname); MOD_INC_USE_COUNT; diff -u --recursive --new-file v2.4.9/linux/drivers/net/jazzsonic.c linux/drivers/net/jazzsonic.c --- v2.4.9/linux/drivers/net/jazzsonic.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/jazzsonic.c Sun Sep 9 10:43:01 2001 @@ -47,11 +47,12 @@ /* * Macros to access SONIC registers */ -#define SONIC_READ(reg) \ - *((volatile unsigned int *)base_addr+reg) +#define SONIC_READ(reg) (*((volatile unsigned int *)base_addr+reg)) -#define SONIC_WRITE(reg,val) \ - *((volatile unsigned int *)base_addr+reg) = val +#define SONIC_WRITE(reg,val) \ +do { \ + *((volatile unsigned int *)base_addr+reg) = val; \ +} /* use 0 for production, 1 for verification, >2 for debug */ @@ -65,8 +66,8 @@ * Base address and interrupt of the SONIC controller on JAZZ boards */ static struct { - unsigned int port; - unsigned int irq; + unsigned int port; + unsigned int irq; } sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}}; /* @@ -76,14 +77,15 @@ */ static unsigned short known_revisions[] = { - 0x04, /* Mips Magnum 4000 */ - 0xffff /* end of list */ + 0x04, /* Mips Magnum 4000 */ + 0xffff /* end of list */ }; /* Index to functions, as function prototypes. */ extern int sonic_probe(struct net_device *dev); -static int sonic_probe1(struct net_device *dev, unsigned int base_addr, unsigned int irq); +static int sonic_probe1(struct net_device *dev, unsigned int base_addr, + unsigned int irq); /* @@ -92,164 +94,170 @@ */ int __init sonic_probe(struct net_device *dev) { - unsigned int base_addr = dev ? dev->base_addr : 0; - int i; + unsigned int base_addr = dev ? dev->base_addr : 0; + int i; - /* - * Don't probe if we're not running on a Jazz board. - */ - if (mips_machgroup != MACH_GROUP_JAZZ) + /* + * Don't probe if we're not running on a Jazz board. + */ + if (mips_machgroup != MACH_GROUP_JAZZ) + return -ENODEV; + if (base_addr >= KSEG0) /* Check a single specified location. */ + return sonic_probe1(dev, base_addr, dev->irq); + else if (base_addr != 0) /* Don't probe at all. */ + return -ENXIO; + + for (i = 0; sonic_portlist[i].port; i++) { + int base_addr = sonic_portlist[i].port; + if (check_region(base_addr, 0x100)) + continue; + if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0) + return 0; + } return -ENODEV; - if (base_addr >= KSEG0) /* Check a single specified location. */ - return sonic_probe1(dev, base_addr, dev->irq); - else if (base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - for (i = 0; sonic_portlist[i].port; i++) { - int base_addr = sonic_portlist[i].port; - if (check_region(base_addr, 0x100)) - continue; - if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0) - return 0; - } - return -ENODEV; } -static int __init sonic_probe1(struct net_device *dev, - unsigned int base_addr, unsigned int irq) +static int __init sonic_probe1(struct net_device *dev, unsigned int base_addr, + unsigned int irq) { - static unsigned version_printed; - unsigned int silicon_revision; - unsigned int val; - struct sonic_local *lp; - int i; - - /* - * get the Silicon Revision ID. If this is one of the known - * one assume that we found a SONIC ethernet controller at - * the expected location. - */ - silicon_revision = SONIC_READ(SONIC_SR); - if (sonic_debug > 1) - printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); - - i = 0; - while ((known_revisions[i] != 0xffff) && - (known_revisions[i] != silicon_revision)) - i++; - - if (known_revisions[i] == 0xffff) { - printk("SONIC ethernet controller not found (0x%4x)\n", - silicon_revision); - return -ENODEV; - } - - if (!request_region(base_addr, 0x100, dev->name)) - return -EBUSY; - - if (sonic_debug && version_printed++ == 0) - printk(version); - - printk("%s: %s found at 0x%08x, ", - dev->name, "SONIC ethernet", base_addr); + static unsigned version_printed; + unsigned int silicon_revision; + unsigned int val; + struct sonic_local *lp; + int i; - /* Fill in the 'dev' fields. */ - dev->base_addr = base_addr; - dev->irq = irq; - - /* - * Put the sonic into software reset, then - * retrieve and print the ethernet address. - */ - SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); - SONIC_WRITE(SONIC_CEP,0); - for (i=0; i<3; i++) { - val = SONIC_READ(SONIC_CAP0-i); - dev->dev_addr[i*2] = val; - dev->dev_addr[i*2+1] = val >> 8; - } - - printk("HW Address "); - for (i = 0; i < 6; i++) { - printk("%2.2x", dev->dev_addr[i]); - if (i<5) - printk(":"); - } - - printk(" IRQ %d\n", irq); - - /* Initialize the device structure. */ - if (dev->priv == NULL) { /* - * the memory be located in the same 64kb segment + * get the Silicon Revision ID. If this is one of the known + * one assume that we found a SONIC ethernet controller at + * the expected location. */ - lp = NULL; + silicon_revision = SONIC_READ(SONIC_SR); + if (sonic_debug > 1) + printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); + i = 0; - do { - lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL); - if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) { - /* FIXME, free the memory later */ - kfree (lp); - lp = NULL; - } - } while (lp == NULL && i++ < 20); - - if (lp == NULL) { - printk ("%s: couldn't allocate memory for descriptors\n", - dev->name); - return -ENOMEM; + while (known_revisions[i] != 0xffff + && known_revisions[i] != silicon_revision) + i++; + + if (known_revisions[i] == 0xffff) { + printk("SONIC ethernet controller not found (0x%4x)\n", + silicon_revision); + return -ENODEV; } - - memset(lp, 0, sizeof(struct sonic_local)); - - /* get the virtual dma address */ - lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp)); - if (lp->cda_laddr == ~0UL) { - printk ("%s: couldn't get DMA page entry for descriptors\n", - dev->name); - return -ENOMEM; + + if (!request_region(base_addr, 0x100, dev->name)) + return -EBUSY; + + if (sonic_debug && version_printed++ == 0) + printk(version); + + printk("%s: Sonic ethernet found at 0x%08lx, ", dev->name, base_addr); + + /* Fill in the 'dev' fields. */ + dev->base_addr = base_addr; + dev->irq = irq; + + /* + * Put the sonic into software reset, then + * retrieve and print the ethernet address. + */ + SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); + SONIC_WRITE(SONIC_CEP,0); + for (i=0; i<3; i++) { + val = SONIC_READ(SONIC_CAP0-i); + dev->dev_addr[i*2] = val; + dev->dev_addr[i*2+1] = val >> 8; } - lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda); - lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda); - lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra); - - /* allocate receive buffer area */ - /* FIXME, maybe we should use skbs */ - if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) { - printk ("%s: couldn't allocate receive buffers\n",dev->name); - return -ENOMEM; + printk("HW Address "); + for (i = 0; i < 6; i++) { + printk("%2.2x", dev->dev_addr[i]); + if (i<5) + printk(":"); } - - /* get virtual dma address */ - if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) { - printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name); - return -ENOMEM; + + printk(" IRQ %d\n", irq); + + /* Initialize the device structure. */ + if (dev->priv == NULL) { + /* + * the memory be located in the same 64kb segment + */ + lp = NULL; + i = 0; + do { + lp = kmalloc(sizeof(*lp), GFP_KERNEL); + if ((unsigned long) lp >> 16 + != ((unsigned long)lp + sizeof(*lp) ) >> 16) { + /* FIXME, free the memory later */ + kfree(lp); + lp = NULL; + } + } while (lp == NULL && i++ < 20); + + if (lp == NULL) { + printk("%s: couldn't allocate memory for descriptors\n", + dev->name); + return -ENOMEM; + } + + memset(lp, 0, sizeof(struct sonic_local)); + + /* get the virtual dma address */ + lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp)); + if (lp->cda_laddr == ~0UL) { + printk("%s: couldn't get DMA page entry for " + "descriptors\n", dev->name); + return -ENOMEM; + } + + lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda); + lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda); + lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra); + + /* allocate receive buffer area */ + /* FIXME, maybe we should use skbs */ + lp->rba = kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL); + if (!lp->rba) { + printk("%s: couldn't allocate receive buffers\n", + dev->name); + return -ENOMEM; + } + + /* get virtual dma address */ + lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba), + SONIC_NUM_RRS * SONIC_RBSIZE); + if (lp->rba_laddr == ~0UL) { + printk("%s: couldn't get DMA page entry for receive " + "buffers\n",dev->name); + return -ENOMEM; + } + + /* now convert pointer to KSEG1 pointer */ + lp->rba = (char *)KSEG1ADDR(lp->rba); + flush_cache_all(); + dev->priv = (struct sonic_local *)KSEG1ADDR(lp); } - - /* now convert pointer to KSEG1 pointer */ - lp->rba = (char *)KSEG1ADDR(lp->rba); - flush_cache_all(); - dev->priv = (struct sonic_local *)KSEG1ADDR(lp); - } - - lp = (struct sonic_local *)dev->priv; - dev->open = sonic_open; - dev->stop = sonic_close; - dev->hard_start_xmit = sonic_send_packet; - dev->get_stats = sonic_get_stats; - dev->set_multicast_list = &sonic_multicast_list; - - /* - * clear tally counter - */ - SONIC_WRITE(SONIC_CRCT,0xffff); - SONIC_WRITE(SONIC_FAET,0xffff); - SONIC_WRITE(SONIC_MPT,0xffff); - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - return 0; + + lp = (struct sonic_local *)dev->priv; + dev->open = sonic_open; + dev->stop = sonic_close; + dev->hard_start_xmit = sonic_send_packet; + dev->get_stats = sonic_get_stats; + dev->set_multicast_list = &sonic_multicast_list; + dev->watchdog_timeo = TX_TIMEOUT; + + /* + * clear tally counter + */ + SONIC_WRITE(SONIC_CRCT,0xffff); + SONIC_WRITE(SONIC_FAET,0xffff); + SONIC_WRITE(SONIC_MPT,0xffff); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + return 0; } /* diff -u --recursive --new-file v2.4.9/linux/drivers/net/lp486e.c linux/drivers/net/lp486e.c --- v2.4.9/linux/drivers/net/lp486e.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/lp486e.c Sun Sep 9 10:45:43 2001 @@ -7,7 +7,7 @@ Written 1993 by Donald Becker. Copyright 1993 United States Government as represented by the Director, National Security Agency. This software may only be used and - distributed according to the terms of the GNU Public License + distributed according to the terms of the GNU General Public License as modified by SRC, incorporated herein by reference. The author may be reached as becker@scyld.com, or C/O @@ -67,7 +67,7 @@ #include #include #include -#include +#include #include #include #include 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/ncr885e.c linux/drivers/net/ncr885e.c --- v2.4.9/linux/drivers/net/ncr885e.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/ncr885e.c Thu Sep 13 16:04:43 2001 @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include 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/ns83820.c linux/drivers/net/ns83820.c --- v2.4.9/linux/drivers/net/ns83820.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/ns83820.c Mon Sep 17 19:33:39 2001 @@ -0,0 +1,1426 @@ +#define VERSION "0.11" +/* ns83820.c by Benjamin LaHaise + * + * $Revision: 1.34.2.2 $ + * + * Copyright 2001 Benjamin LaHaise. + * Copyright 2001 Red Hat. + * + * Mmmm, chocolate vanilla mocha... + * + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * ChangeLog + * ========= + * 20010414 0.1 - created + * 20010622 0.2 - basic rx and tx. + * 20010711 0.3 - added duplex and link state detection support. + * 20010713 0.4 - zero copy, no hangs. + * 0.5 - 64 bit dma support (davem will hate me for this) + * - disable jumbo frames to avoid tx hangs + * - work around tx deadlocks on my 1.02 card via + * fiddling with TXCFG + * 20010810 0.6 - use pci dma api for ringbuffers, work on ia64 + * 20010816 0.7 - misc cleanups + * 20010826 0.8 - fix critical zero copy bugs + * 0.9 - internal experiment + * 20010827 0.10 - fix ia64 unaligned access. + * 20010906 0.11 - accept all packets with checksum errors as + * otherwise fragments get lost + - fix >> 32 bugs + * + * Driver Overview + * =============== + * + * This driver was originally written for the National Semiconductor + * 83820 chip, a 10/100/1000 Mbps 64 bit PCI ethernet NIC. Hopefully + * this code will turn out to be a) clean, b) correct, and c) fast. + * With that in mind, I'm aiming to split the code up as much as + * reasonably possible. At present there are X major sections that + * break down into a) packet receive, b) packet transmit, c) link + * management, d) initialization and configuration. Where possible, + * these code paths are designed to run in parallel. + * + * This driver has been tested and found to work with the following + * cards (in no particular order): + * + * Cameo SOHO-GA2000T SOHO-GA2500T + * D-Link DGE-500T + * PureData PDP8023Z-TG + * SMC SMC9462TX + * + * Reports of success or failure would be greatly appreciated. + */ +//#define dprintk printk +#define dprintk(x...) do { } while (0) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for iph */ +#include /* for IPPROTO_... */ +#include +#include +//#include + +/* Dprintk is used for more interesting debug events */ +#undef Dprintk +#define Dprintk dprintk + +#ifdef CONFIG_HIGHMEM64G +#define USE_64BIT_ADDR +#elif defined(__ia64__) +#define USE_64BIT_ADDR +#endif + +/* Tell davem to fix the pci dma api. Grrr. */ +/* stolen from acenic.c */ +#ifdef CONFIG_HIGHMEM +#if defined(CONFIG_X86) +#define DMAADDR_OFFSET 0 +#if defined(CONFIG_HIGHMEM64G) +typedef u64 dmaaddr_high_t; +#else +typedef u32 dmaaddr_high_t; +#endif +#elif defined(CONFIG_PPC) +#define DMAADDR_OFFSET PCI_DRAM_OFFSET +typedef unsigned long dmaaddr_high_t; +#endif + +static inline dmaaddr_high_t +pci_map_single_high(struct pci_dev *hwdev, struct page *page, + int offset, size_t size, int dir) +{ + u64 phys; + phys = page - mem_map; + phys <<= PAGE_SHIFT; + phys += offset; + phys += DMAADDR_OFFSET; + return phys; +} +#else + +typedef unsigned long dmaaddr_high_t; + +static inline dmaaddr_high_t +pci_map_single_high(struct pci_dev *hwdev, struct page *page, + int offset, size_t size, int dir) +{ + return pci_map_single(hwdev, page_address(page) + offset, size, dir); +} +#endif + +/* tunables */ +#define RX_BUF_SIZE 6144 /* 8192 */ +#define NR_RX_DESC 256 + +#define NR_TX_DESC 256 + +/* register defines */ +#define CFGCS 0x04 + +#define CR_TXE 0x00000001 +#define CR_TXD 0x00000002 +#define CR_RXE 0x00000004 +#define CR_RXD 0x00000008 +#define CR_TXR 0x00000010 +#define CR_RXR 0x00000020 +#define CR_SWI 0x00000080 +#define CR_RST 0x00000100 + +#define PTSCR_EEBIST_EN 0x00000002 +#define PTSCR_EELOAD_EN 0x00000004 + +#define ISR_TXDESC3 0x40000000 +#define ISR_TXDESC2 0x20000000 +#define ISR_TXDESC1 0x10000000 +#define ISR_TXDESC0 0x08000000 +#define ISR_RXDESC3 0x04000000 +#define ISR_RXDESC2 0x02000000 +#define ISR_RXDESC1 0x01000000 +#define ISR_RXDESC0 0x00800000 +#define ISR_TXRCMP 0x00400000 +#define ISR_RXRCMP 0x00200000 +#define ISR_DPERR 0x00100000 +#define ISR_SSERR 0x00080000 +#define ISR_RMABT 0x00040000 +#define ISR_RTABT 0x00020000 +#define ISR_RXSOVR 0x00010000 +#define ISR_HIBINT 0x00008000 +#define ISR_PHY 0x00004000 +#define ISR_PME 0x00002000 +#define ISR_SWI 0x00001000 +#define ISR_MIB 0x00000800 +#define ISR_TXURN 0x00000400 +#define ISR_TXIDLE 0x00000200 +#define ISR_TXERR 0x00000100 +#define ISR_TXDESC 0x00000080 +#define ISR_TXOK 0x00000040 +#define ISR_RXORN 0x00000020 +#define ISR_RXIDLE 0x00000010 +#define ISR_RXEARLY 0x00000008 +#define ISR_RXERR 0x00000004 +#define ISR_RXDESC 0x00000002 +#define ISR_RXOK 0x00000001 + +#define TXCFG_CSI 0x80000000 +#define TXCFG_HBI 0x40000000 +#define TXCFG_MLB 0x20000000 +#define TXCFG_ATP 0x10000000 +#define TXCFG_ECRETRY 0x00800000 +#define TXCFG_BRST_DIS 0x00080000 +#define TXCFG_MXDMA1024 0x00000000 +#define TXCFG_MXDMA512 0x00700000 +#define TXCFG_MXDMA256 0x00600000 +#define TXCFG_MXDMA128 0x00500000 +#define TXCFG_MXDMA64 0x00400000 +#define TXCFG_MXDMA32 0x00300000 +#define TXCFG_MXDMA16 0x00200000 +#define TXCFG_MXDMA8 0x00100000 + +#define CFG_LNKSTS 0x80000000 +#define CFG_SPDSTS 0x60000000 +#define CFG_SPDSTS1 0x40000000 +#define CFG_SPDSTS0 0x20000000 +#define CFG_DUPSTS 0x10000000 +#define CFG_TBI_EN 0x01000000 +#define CFG_MODE_1000 0x00400000 +#define CFG_PINT_CTL 0x001c0000 +#define CFG_PINT_DUPSTS 0x00100000 +#define CFG_PINT_LNKSTS 0x00080000 +#define CFG_PINT_SPDSTS 0x00040000 +#define CFG_TMRTEST 0x00020000 +#define CFG_MRM_DIS 0x00010000 +#define CFG_MWI_DIS 0x00008000 +#define CFG_T64ADDR 0x00004000 +#define CFG_PCI64_DET 0x00002000 +#define CFG_DATA64_EN 0x00001000 +#define CFG_M64ADDR 0x00000800 +#define CFG_PHY_RST 0x00000400 +#define CFG_PHY_DIS 0x00000200 +#define CFG_EXTSTS_EN 0x00000100 +#define CFG_REQALG 0x00000080 +#define CFG_SB 0x00000040 +#define CFG_POW 0x00000020 +#define CFG_EXD 0x00000010 +#define CFG_PESEL 0x00000008 +#define CFG_BROM_DIS 0x00000004 +#define CFG_EXT_125 0x00000002 +#define CFG_BEM 0x00000001 + +#define EXTSTS_UDPPKT 0x00200000 +#define EXTSTS_TCPPKT 0x00080000 +#define EXTSTS_IPPKT 0x00020000 + +#define SPDSTS_POLARITY (CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS) + +#define MIBC_MIBS 0x00000008 +#define MIBC_ACLR 0x00000004 +#define MIBC_FRZ 0x00000002 +#define MIBC_WRN 0x00000001 + +#define RXCFG_AEP 0x80000000 +#define RXCFG_ARP 0x40000000 +#define RXCFG_STRIPCRC 0x20000000 +#define RXCFG_RX_FD 0x10000000 +#define RXCFG_ALP 0x08000000 +#define RXCFG_AIRL 0x04000000 +#define RXCFG_MXDMA 0x00700000 +#define RXCFG_MXDMA0 0x00100000 +#define RXCFG_MXDMA64 0x00600000 +#define RXCFG_DRTH 0x0000003e +#define RXCFG_DRTH0 0x00000002 + +#define RFCR_RFEN 0x80000000 +#define RFCR_AAB 0x40000000 +#define RFCR_AAM 0x20000000 +#define RFCR_AAU 0x10000000 +#define RFCR_APM 0x08000000 +#define RFCR_APAT 0x07800000 +#define RFCR_APAT3 0x04000000 +#define RFCR_APAT2 0x02000000 +#define RFCR_APAT1 0x01000000 +#define RFCR_APAT0 0x00800000 +#define RFCR_AARP 0x00400000 +#define RFCR_MHEN 0x00200000 +#define RFCR_UHEN 0x00100000 +#define RFCR_ULM 0x00080000 + +#define VRCR_RUDPE 0x00000080 +#define VRCR_RTCPE 0x00000040 +#define VRCR_RIPE 0x00000020 +#define VRCR_IPEN 0x00000010 +#define VRCR_DUTF 0x00000008 +#define VRCR_DVTF 0x00000004 +#define VRCR_VTREN 0x00000002 +#define VRCR_VTDEN 0x00000001 + +#define VTCR_PPCHK 0x00000008 +#define VTCR_GCHK 0x00000004 +#define VTCR_VPPTI 0x00000002 +#define VTCR_VGTI 0x00000001 + +#define CR 0x00 +#define CFG 0x04 +#define MEAR 0x08 +#define PTSCR 0x0c +#define ISR 0x10 +#define IMR 0x14 +#define IER 0x18 +#define IHR 0x1c +#define TXDP 0x20 +#define TXDP_HI 0x24 +#define TXCFG 0x28 +#define GPIOR 0x2c +#define RXDP 0x30 +#define RXDP_HI 0x34 +#define RXCFG 0x38 +#define PQCR 0x3c +#define WCSR 0x40 +#define PCR 0x44 +#define RFCR 0x48 +#define RFDR 0x4c + +#define SRR 0x58 + +#define VRCR 0xbc +#define VTCR 0xc0 +#define VDR 0xc4 +#define CCSR 0xcc + +#define __kick_rx(dev) writel(CR_RXE, dev->base + CR) + +#define kick_rx(dev) do { \ + dprintk("kick_rx: maybe kicking\n"); \ + if (test_and_clear_bit(0, &dev->rx_info.idle)) { \ + dprintk("actually kicking\n"); \ + writel(dev->rx_info.phy_descs + (4 * DESC_SIZE * dev->rx_info.next_rx), dev->base + RXDP); \ + if (dev->rx_info.next_rx == dev->rx_info.next_empty) \ + printk(KERN_DEBUG "%s: uh-oh: next_rx == next_empty???\n", dev->net_dev.name);\ + __kick_rx(dev); \ + } \ +} while(0) + +#ifdef USE_64BIT_ADDR +typedef u64 hw_addr_t; +#else +typedef u32 hw_addr_t; +#endif + +#define HW_ADDR_LEN (sizeof(hw_addr_t)) + +#define LINK 0 +#define BUFPTR (LINK + HW_ADDR_LEN/4) +#define CMDSTS (BUFPTR + HW_ADDR_LEN/4) +#define EXTSTS (CMDSTS + 4/4) +#define DRV_NEXT (EXTSTS + 4/4) + +#define CMDSTS_OWN 0x80000000 +#define CMDSTS_MORE 0x40000000 +#define CMDSTS_INTR 0x20000000 +#define CMDSTS_ERR 0x10000000 +#define CMDSTS_OK 0x08000000 + +#define CMDSTS_DEST_MASK 0x01800000 +#define CMDSTS_DEST_SELF 0x00800000 +#define CMDSTS_DEST_MULTI 0x01000000 + +#define DESC_SIZE 8 /* Should be cache line sized */ + +struct rx_info { + spinlock_t lock; + int up; + long idle; + + struct sk_buff *skbs[NR_RX_DESC]; + + unsigned next_rx, next_empty; + + u32 *descs; + dma_addr_t phy_descs; +}; + + +struct ns83820 { + struct net_device net_dev; + u8 *base; + + struct pci_dev *pci_dev; + struct ns83820 *next_dev; + + struct rx_info rx_info; + + unsigned ihr; + struct tq_struct tq_refill; + + /* protects everything below. irqsave when using. */ + spinlock_t misc_lock; + + u32 CFG_cache; + + u32 MEAR_cache; + u32 IMR_cache; + struct eeprom ee; + + + spinlock_t tx_lock; + + long tx_idle; + u32 tx_done_idx; + u32 tx_idx; + volatile u32 tx_free_idx; /* idx of free desc chain */ + u32 tx_intr_idx; + + struct sk_buff *tx_skbs[NR_TX_DESC]; + + char pad[16] __attribute__((aligned(16))); + u32 *tx_descs; + dma_addr_t tx_phy_descs; +}; + +//free = (tx_done_idx + NR_TX_DESC-2 - free_idx) % NR_TX_DESC +#define start_tx_okay(dev) \ + (((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > NR_TX_DESC/2) + +static struct ns83820 *ns83820_chain; + + +/* Packet Receiver + * + * The hardware supports linked lists of receive descriptors for + * which ownership is transfered back and forth by means of an + * ownership bit. While the hardware does support the use of a + * ring for receive descriptors, we only make use of a chain in + * an attempt to reduce bus traffic under heavy load scenarios. + * This will also make bugs a bit more obvious. The current code + * only makes use of a single rx chain; I hope to implement + * priority based rx for version 1.0. Goal: even under overload + * conditions, still route realtime traffic with as low jitter as + * possible. + */ +#ifdef USE_64BIT_ADDR +static inline void build_rx_desc64(struct ns83820 *dev, u32 *desc, u64 link, u64 buf, u32 cmdsts, u32 extsts) +{ + desc[0] = link; + desc[1] = link >> 32; + desc[2] = buf; + desc[3] = buf >> 32; + desc[5] = extsts; + mb(); + desc[4] = cmdsts; +} + +#define build_rx_desc build_rx_desc64 +#else + +static inline void build_rx_desc32(struct ns83820 *dev, u32 *desc, u32 link, u32 buf, u32 cmdsts, u32 extsts) +{ + desc[0] = link; + desc[1] = buf; + desc[3] = extsts; + mb(); + desc[2] = cmdsts; +} + +#define build_rx_desc build_rx_desc32 +#endif + +#define nr_rx_empty(dev) ((NR_RX_DESC-2 + dev->rx_info.next_rx - dev->rx_info.next_empty) % NR_RX_DESC) +static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) +{ + unsigned next_empty; + u32 cmdsts; + u32 *sg; + hw_addr_t buf; + + next_empty = dev->rx_info.next_empty; + + /* don't overrun last rx marker */ + if (nr_rx_empty(dev) <= 2) { + kfree_skb(skb); + return 1; + } + +#if 0 + dprintk("next_empty[%d] nr_used[%d] next_rx[%d]\n", + dev->rx_info.next_empty, + dev->rx_info.nr_used, + dev->rx_info.next_rx + ); +#endif + + sg = dev->rx_info.descs + (next_empty * DESC_SIZE); + if (dev->rx_info.skbs[next_empty]) + BUG(); + dev->rx_info.skbs[next_empty] = skb; + + dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; + cmdsts = RX_BUF_SIZE | CMDSTS_INTR; + buf = pci_map_single(dev->pci_dev, skb->tail, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + build_rx_desc(dev, sg, 0, buf, cmdsts, 0); + /* update link of previous rx */ + if (next_empty != dev->rx_info.next_rx) + dev->rx_info.descs[((NR_RX_DESC + next_empty - 1) % NR_RX_DESC) * DESC_SIZE] = dev->rx_info.phy_descs + (next_empty * DESC_SIZE * 4); + + return 0; +} + +static int rx_refill(struct ns83820 *dev, int gfp) +{ + unsigned i; + long flags = 0; + + dprintk("rx_refill(%p)\n", dev); + if (gfp == GFP_ATOMIC) + spin_lock_irqsave(&dev->rx_info.lock, flags); + for (i=0; itail & 0xf; + res = 0x10 - res; + res &= 0xf; + skb_reserve(skb, res); + + skb->dev = &dev->net_dev; + if (gfp != GFP_ATOMIC) + spin_lock_irqsave(&dev->rx_info.lock, flags); + res = ns83820_add_rx_skb(dev, skb); + if (gfp != GFP_ATOMIC) + spin_unlock_irqrestore(&dev->rx_info.lock, flags); + if (res) { + i = 1; + break; + } + } + if (gfp == GFP_ATOMIC) + spin_unlock_irqrestore(&dev->rx_info.lock, flags); + + return i ? 0 : -ENOMEM; +} + +/* REFILL */ +static inline void queue_refill(void *_dev) +{ + struct ns83820 *dev = _dev; + + rx_refill(dev, GFP_KERNEL); + if (dev->rx_info.up) + kick_rx(dev); +} + +static inline void clear_rx_desc(struct ns83820 *dev, unsigned i) +{ + build_rx_desc(dev, dev->rx_info.descs + (DESC_SIZE * i), 0, 0, CMDSTS_OWN, 0); +} + +static void phy_intr(struct ns83820 *dev) +{ + static char *speeds[] = { "10", "100", "1000", "1000(?)" }; + u32 cfg, new_cfg; + + new_cfg = dev->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS); + cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY; + + if (cfg & CFG_SPDSTS1) + new_cfg |= CFG_MODE_1000 | CFG_SB; + else + new_cfg &= ~CFG_MODE_1000 | CFG_SB; + + if ((cfg & CFG_LNKSTS) && ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) { + writel(new_cfg, dev->base + CFG); + dev->CFG_cache = new_cfg; + } + + dev->CFG_cache &= ~CFG_SPDSTS; + dev->CFG_cache |= cfg & CFG_SPDSTS; + + if (cfg & CFG_LNKSTS) { + netif_start_queue(&dev->net_dev); + netif_wake_queue(&dev->net_dev); + } else { + netif_stop_queue(&dev->net_dev); + } + + if (cfg & CFG_LNKSTS) + printk(KERN_INFO "%s: link now %s mbps, %s duplex and up.\n", + dev->net_dev.name, + speeds[((cfg / CFG_SPDSTS0) & 3)], + (cfg & CFG_DUPSTS) ? "full" : "half"); + else + printk(KERN_INFO "%s: link now down.\n", dev->net_dev.name); +} + +static int ns83820_setup_rx(struct ns83820 *dev) +{ + unsigned i; + int ret; + + dprintk("ns83820_setup_rx(%p)\n", dev); + + dev->rx_info.idle = 1; + dev->rx_info.next_rx = 0; + dev->rx_info.next_empty = 0; + + for (i=0; ibase + RXDP_HI); + writel(dev->rx_info.phy_descs, dev->base + RXDP); + + ret = rx_refill(dev, GFP_KERNEL); + if (!ret) { + dprintk("starting receiver\n"); + /* prevent the interrupt handler from stomping on us */ + spin_lock_irq(&dev->rx_info.lock); + + writel(0x0001, dev->base + CCSR); + writel(0, dev->base + RFCR); + writel(0x7fc00000, dev->base + RFCR); + writel(0xffc00000, dev->base + RFCR); + + dev->rx_info.up = 1; + + phy_intr(dev); + + /* Okay, let it rip */ + spin_lock(&dev->misc_lock); + dev->IMR_cache |= ISR_PHY; + dev->IMR_cache |= ISR_RXRCMP; + //dev->IMR_cache |= ISR_RXERR; + //dev->IMR_cache |= ISR_RXOK; + dev->IMR_cache |= ISR_RXORN; + dev->IMR_cache |= ISR_RXSOVR; + dev->IMR_cache |= ISR_RXDESC; + dev->IMR_cache |= ISR_RXIDLE; + dev->IMR_cache |= ISR_TXDESC; + //dev->IMR_cache |= ISR_TXIDLE; + + writel(dev->IMR_cache, dev->base + IMR); + writel(1, dev->base + IER); + spin_unlock(&dev->misc_lock); + + kick_rx(dev); + + spin_unlock_irq(&dev->rx_info.lock); + } + return ret; +} + +static void ns83820_cleanup_rx(struct ns83820 *dev) +{ + unsigned i; + long flags; + + dprintk("ns83820_cleanup_rx(%p)\n", dev); + + /* disable receive interrupts */ + spin_lock_irqsave(&dev->misc_lock, flags); + dev->IMR_cache &= ~(ISR_RXOK | ISR_RXDESC | ISR_RXERR | ISR_RXEARLY | ISR_RXIDLE); + writel(dev->IMR_cache, dev->base + IMR); + spin_unlock_irqrestore(&dev->misc_lock, flags); + + /* synchronize with the interrupt handler and kill it */ + dev->rx_info.up = 0; + synchronize_irq(); + + /* touch the pci bus... */ + readl(dev->base + IMR); + + /* assumes the transmitter is already disabled and reset */ + writel(0, dev->base + RXDP_HI); + writel(0, dev->base + RXDP); + + for (i=0; irx_info.skbs[i]; + dev->rx_info.skbs[i] = NULL; + clear_rx_desc(dev, i); + if (skb) + kfree_skb(skb); + } +} + +/* rx_irq + * + */ +static void FASTCALL(rx_irq(struct ns83820 *dev)); +static void rx_irq(struct ns83820 *dev) +{ + struct rx_info *info = &dev->rx_info; + unsigned next_rx; + u32 cmdsts, *desc; + long flags; + int nr = 0; + + dprintk("rx_irq(%p)\n", dev); + dprintk("rxdp: %08x, descs: %08lx next_rx[%d]: %p next_empty[%d]: %p\n", + readl(dev->base + RXDP), + (dev->rx_info.phy_descs), + dev->rx_info.next_rx, + (dev->rx_info.descs + (DESC_SIZE * dev->rx_info.next_rx)), + dev->rx_info.next_empty, + (dev->rx_info.descs + (DESC_SIZE * dev->rx_info.next_empty)) + ); + + spin_lock_irqsave(&info->lock, flags); + if (!info->up) + goto out; + + dprintk("walking descs\n"); + next_rx = info->next_rx; + desc = info->descs + (DESC_SIZE * next_rx); + while ((CMDSTS_OWN & (cmdsts = desc[CMDSTS])) && + (cmdsts != CMDSTS_OWN)) { + struct sk_buff *skb; + u32 extsts = desc[EXTSTS]; + dmaaddr_high_t bufptr = *(hw_addr_t *)(desc + BUFPTR); + + dprintk("cmdsts: %08x\n", cmdsts); + dprintk("link: %08x\n", desc[LINK]); + dprintk("extsts: %08x\n", desc[EXTSTS]); + + skb = info->skbs[next_rx]; + info->skbs[next_rx] = NULL; + info->next_rx = (next_rx + 1) % NR_RX_DESC; + + barrier(); + clear_rx_desc(dev, next_rx); + + pci_unmap_single(dev->pci_dev, bufptr, + RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + if (CMDSTS_OK & cmdsts) { +#ifndef __i386__ + struct sk_buff *tmp; +#endif + int len = cmdsts & 0xffff; + if (!skb) + BUG(); + skb_put(skb, len); +#ifndef __i386__ /* I hate the network stack sometimes */ + tmp = __dev_alloc_skb(RX_BUF_SIZE+16, GFP_ATOMIC); + if (!tmp) + goto done; + tmp->dev = &dev->net_dev; + skb_reserve(tmp, 2); + memcpy(skb_put(tmp, len), skb->data, len); + kfree_skb(skb); + skb = tmp; +#endif + if ((extsts & 0x002a0000) && !(extsts & 0x00540000)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb->ip_summed = CHECKSUM_NONE; + } + skb->protocol = eth_type_trans(skb, &dev->net_dev); + switch (netif_rx(skb)) { + case NET_RX_SUCCESS: + dev->ihr = 3; + break; + case NET_RX_CN_LOW: + dev->ihr = 3; + break; + case NET_RX_CN_MOD: + dev->ihr = dev->ihr + 1; + break; + case NET_RX_CN_HIGH: + dev->ihr += dev->ihr/2 + 1; + break; + case NET_RX_DROP: + dev->ihr = 255; + break; + } + if (dev->ihr > 255) + dev->ihr = 255; +#ifndef __i386__ + done:; +#endif + } else { + static int err; + if (err++ < 20) { + Dprintk("error packet: cmdsts: %08x extsts: %08x\n", cmdsts, extsts); + } + kfree_skb(skb); + } + + nr++; + next_rx = info->next_rx; + desc = info->descs + (DESC_SIZE * next_rx); + } + info->next_rx = next_rx; + +out: + if (0 && !nr) { + Dprintk("dazed: cmdsts_f: %08x\n", cmdsts); + } + + spin_unlock_irqrestore(&info->lock, flags); +} + + +/* Packet Transmit code + */ +static inline void kick_tx(struct ns83820 *dev) +{ + dprintk("kick_tx(%p): tx_idle=%ld, tx_idx=%d free_idx=%d\n", + dev, dev->tx_idle, dev->tx_idx, dev->tx_free_idx); + writel(CR_TXE, dev->base + CR); +} + +/* no spinlock needed on the transmit irq path as the interrupt handler is serialized */ +static void do_tx_done(struct ns83820 *dev) +{ + u32 cmdsts, tx_done_idx, *desc; + + dprintk("do_tx_done(%p)\n", dev); + tx_done_idx = dev->tx_done_idx; + desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); + + dprintk("tx_done_idx=%d free_idx=%d cmdsts=%08x\n", + tx_done_idx, dev->tx_free_idx, desc[CMDSTS]); + while ((tx_done_idx != dev->tx_free_idx) && + !(CMDSTS_OWN & (cmdsts = desc[CMDSTS])) ) { + struct sk_buff *skb; + + dprintk("tx_done_idx=%d free_idx=%d cmdsts=%08x\n", + tx_done_idx, dev->tx_free_idx, desc[CMDSTS]); + skb = dev->tx_skbs[tx_done_idx]; + dev->tx_skbs[tx_done_idx] = NULL; + dprintk("done(%p)\n", skb); + if (skb) { + pci_unmap_single(dev->pci_dev, + *(hw_addr_t *)(desc + BUFPTR), + skb->len, + PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + } + + tx_done_idx = (tx_done_idx + 1) % NR_TX_DESC; + dev->tx_done_idx = tx_done_idx; + desc[CMDSTS] = 0; + barrier(); + desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); + } + + /* Allow network stack to resume queueing packets after we've + * finished transmitting at least 1/4 of the packets in the queue. + */ + if (netif_queue_stopped(&dev->net_dev) && start_tx_okay(dev)) { + dprintk("start_queue(%p)\n", dev); + netif_start_queue(&dev->net_dev); + netif_wake_queue(&dev->net_dev); + } +} + +static void ns83820_cleanup_tx(struct ns83820 *dev) +{ + unsigned i; + + for (i=0; itx_skbs[i]; + dev->tx_skbs[i] = NULL; + if (skb) + dev_kfree_skb(skb); + } + + memset(dev->tx_descs, 0, NR_TX_DESC * DESC_SIZE * 4); + set_bit(0, &dev->tx_idle); +} + +/* transmit routine. This code relies on the network layer serializing + * its calls in, but will run happily in parallel with the interrupt + * handler. This code currently has provisions for fragmenting tx buffers + * while trying to track down a bug in either the zero copy code or + * the tx fifo (hence the MAX_FRAG_LEN). + */ +#define MAX_FRAG_LEN 8192 /* disabled for now */ +static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *_dev) +{ + struct ns83820 *dev = (struct ns83820 *)_dev; + u32 free_idx, cmdsts, extsts; + int nr_free, nr_frags; + unsigned tx_done_idx; + dmaaddr_high_t buf; + unsigned len; + skb_frag_t *frag; + int stopped = 0; + int do_intr = 0; + volatile u32 *first_desc; + + dprintk("ns83820_hard_start_xmit\n"); + + nr_frags = skb_shinfo(skb)->nr_frags; +again: + if (__builtin_expect(dev->CFG_cache & CFG_LNKSTS, 0)) { + netif_stop_queue(&dev->net_dev); + if (__builtin_expect(dev->CFG_cache & CFG_LNKSTS, 0)) + return 1; + netif_start_queue(&dev->net_dev); + } + + free_idx = dev->tx_free_idx; + tx_done_idx = dev->tx_done_idx; + nr_free = (tx_done_idx + NR_TX_DESC-2 - free_idx) % NR_TX_DESC; + nr_free -= 1; + if ((nr_free <= nr_frags) || (nr_free <= 8192 / MAX_FRAG_LEN)) { + dprintk("stop_queue - not enough(%p)\n", dev); + netif_stop_queue(&dev->net_dev); + + /* Check again: we may have raced with a tx done irq */ + if (dev->tx_done_idx != tx_done_idx) { + dprintk("restart queue(%p)\n", dev); + netif_start_queue(&dev->net_dev); + goto again; + } + return 1; + } + + if (free_idx == dev->tx_intr_idx) { + do_intr = 1; + dev->tx_intr_idx = (dev->tx_intr_idx + NR_TX_DESC/2) % NR_TX_DESC; + } + + nr_free -= nr_frags; + if (nr_free < 1) { + dprintk("stop_queue - last entry(%p)\n", dev); + netif_stop_queue(&dev->net_dev); + stopped = 1; + } + + frag = skb_shinfo(skb)->frags; + if (!nr_frags) + frag = 0; + extsts = 0; + if (skb->ip_summed == CHECKSUM_HW) { + extsts |= EXTSTS_IPPKT; + if (IPPROTO_TCP == skb->nh.iph->protocol) + extsts |= EXTSTS_TCPPKT; + else if (IPPROTO_UDP == skb->nh.iph->protocol) + extsts |= EXTSTS_UDPPKT; + } + + len = skb->len; + if (nr_frags) + len -= skb->data_len; + buf = pci_map_single(dev->pci_dev, skb->data, len, PCI_DMA_TODEVICE); + + first_desc = dev->tx_descs + (free_idx * DESC_SIZE); + + for (;;) { + volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE); + u32 residue = 0; +#if 0 + if (len > MAX_FRAG_LEN) { + residue = len; + /* align the start address of the next fragment */ + len = MAX_FRAG_LEN; + residue -= len; + } +#endif + + dprintk("frag[%3u]: %4u @ 0x%x%08Lx\n", free_idx, len, + (unsigned long long)buf); + free_idx = (free_idx + 1) % NR_TX_DESC; + desc[LINK] = dev->tx_phy_descs + (free_idx * DESC_SIZE * 4); + *(hw_addr_t *)(desc + BUFPTR) = buf; + desc[EXTSTS] = extsts; + + cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0); + cmdsts |= (desc == first_desc) ? 0 : CMDSTS_OWN; + cmdsts |= len; + desc[CMDSTS] = cmdsts; + + if (residue) { + buf += len; + len = residue; + continue; + } + + if (!nr_frags) + break; + + buf = pci_map_single_high(dev->pci_dev, frag->page, 0, + frag->size, PCI_DMA_TODEVICE); + dprintk("frag: buf=%08Lx page=%08lx\n", + (long long)buf, (long)(frag->page - mem_map)); + len = frag->size; + frag++; + nr_frags--; + } + dprintk("done pkt\n"); + dev->tx_skbs[free_idx] = skb; + first_desc[CMDSTS] |= CMDSTS_OWN; + dev->tx_free_idx = free_idx; + kick_tx(dev); + + /* Check again: we may have raced with a tx done irq */ + if (stopped && (dev->tx_done_idx != tx_done_idx) && start_tx_okay(dev)) + netif_start_queue(&dev->net_dev); + + return 0; +} + +static void ns83820_irq(int foo, void *data, struct pt_regs *regs) +{ + struct ns83820 *dev = data; + int count = 0; + u32 isr; + dprintk("ns83820_irq(%p)\n", dev); + + dev->ihr = 0; + + while (count++ < 32 && (isr = readl(dev->base + ISR))) { + dprintk("irq: %08x\n", isr); + + if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC)) + Dprintk("odd isr? 0x%08x\n", isr); + + if ((ISR_RXEARLY | ISR_RXIDLE | ISR_RXORN | ISR_RXDESC | ISR_RXOK | ISR_RXERR) & isr) { + if (ISR_RXIDLE & isr) { + dev->rx_info.idle = 1; + Dprintk("oh dear, we are idle\n"); + } + + if ((ISR_RXDESC) & isr) { + rx_irq(dev); + writel(4, dev->base + IHR); + } + + if (nr_rx_empty(dev) >= NR_RX_DESC/4) { + if (dev->rx_info.up) { + rx_refill(dev, GFP_ATOMIC); + kick_rx(dev); + } + } + + if (dev->rx_info.up && nr_rx_empty(dev) > NR_RX_DESC*3/4) + schedule_task(&dev->tq_refill); + else + kick_rx(dev); + if (dev->rx_info.idle) + Dprintk("BAD\n"); + } + + if (ISR_RXSOVR & isr) + Dprintk("overrun\n"); + if (ISR_RXORN & isr) + Dprintk("overrun\n"); + + if ((ISR_RXRCMP & isr) && dev->rx_info.up) + writel(CR_RXE, dev->base + CR); + + if (ISR_TXIDLE & isr) { + u32 txdp; + txdp = readl(dev->base + TXDP); + dprintk("txdp: %08x\n", txdp); + txdp -= dev->tx_phy_descs; + dev->tx_idx = txdp / (DESC_SIZE * 4); + if (dev->tx_idx >= NR_TX_DESC) { + printk(KERN_ALERT "%s: BUG -- txdp out of range\n", dev->net_dev.name); + dev->tx_idx = 0; + } + if (dev->tx_idx != dev->tx_free_idx) + writel(CR_TXE, dev->base + CR); + //kick_tx(dev); + else + dev->tx_idle = 1; + mb(); + if (dev->tx_idx != dev->tx_free_idx) + kick_tx(dev); + } + + /* Defer tx ring processing until more than a minimum amount of + * work has accumulated + */ + if ((ISR_TXDESC | ISR_TXIDLE) & isr) + do_tx_done(dev); + + if (ISR_PHY & isr) + phy_intr(dev); + } + +#if 0 /* Still working on the interrupt mitigation strategy */ + if (dev->ihr) + writel(dev->ihr, dev->base + IHR); +#endif +} + +static void ns83820_do_reset(struct ns83820 *dev, u32 which) +{ + Dprintk("resetting chip...\n"); + writel(which, dev->base + CR); + do { + schedule(); + } while (readl(dev->base + CR) & which); + Dprintk("okay!\n"); +} + +static int ns83820_stop(struct net_device *_dev) +{ + struct ns83820 *dev = (struct ns83820 *)_dev; + + /* FIXME: protect against interrupt handler? */ + + /* disable interrupts */ + writel(0, dev->base + IMR); + writel(0, dev->base + IER); + readl(dev->base + IER); + + dev->rx_info.up = 0; + synchronize_irq(); + + ns83820_do_reset(dev, CR_RST); + + synchronize_irq(); + + dev->IMR_cache &= ~(ISR_TXURN | ISR_TXIDLE | ISR_TXERR | ISR_TXDESC | ISR_TXOK); + ns83820_cleanup_rx(dev); + ns83820_cleanup_tx(dev); + + return 0; +} + +static int ns83820_open(struct net_device *_dev) +{ + struct ns83820 *dev = (struct ns83820 *)_dev; + unsigned i; + u32 desc; + int ret; + + dprintk("ns83820_open\n"); + + writel(0, dev->base + PQCR); + + ret = ns83820_setup_rx(dev); + if (ret) + goto failed; + + memset(dev->tx_descs, 0, 4 * NR_TX_DESC * DESC_SIZE); + for (i=0; itx_descs + (i * DESC_SIZE) + LINK) + = dev->tx_phy_descs + + ((i+1) % NR_TX_DESC) * DESC_SIZE * 4; + } + + dev->tx_idx = 0; + dev->tx_done_idx = 0; + desc = dev->tx_phy_descs; + writel(0, dev->base + TXDP_HI); + writel(desc, dev->base + TXDP); + +//printk("IMR: %08x / %08x\n", readl(dev->base + IMR), dev->IMR_cache); + + set_bit(0, &dev->tx_idle); + netif_start_queue(&dev->net_dev); /* FIXME: wait for phy to come up */ + + return 0; + +failed: + ns83820_stop(_dev); + return ret; +} + +#if 0 /* FIXME: implement this! */ +static void ns83820_tx_timeout(struct net_device *_dev) +{ + struct ns83820 *dev = (struct ns83820 *)_dev; + + printk("ns83820_tx_timeout\n"); +} +#endif + +static void ns83820_getmac(struct ns83820 *dev, u8 *mac) +{ + unsigned i; + for (i=0; i<3; i++) { + u32 data; +#if 0 /* I've left this in as an example of how to use eeprom.h */ + data = eeprom_readw(&dev->ee, 0xa + 2 - i); +#else + writel(i*2, dev->base + RFCR); + data = readl(dev->base + RFDR); +#endif + *mac++ = data; + *mac++ = data >> 8; + } +} + +static int ns83820_change_mtu(struct net_device *_dev, int new_mtu) +{ + if (new_mtu > RX_BUF_SIZE) + return -EINVAL; + _dev->mtu = new_mtu; + return 0; +} + +static int ns83820_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) +{ + struct ns83820 *dev; + long addr; + int err; + + dev = (struct ns83820 *)alloc_etherdev((sizeof *dev) - (sizeof dev->net_dev)); + err = -ENOMEM; + if (!dev) + goto out; + + spin_lock_init(&dev->rx_info.lock); + spin_lock_init(&dev->tx_lock); + spin_lock_init(&dev->misc_lock); + dev->pci_dev = pci_dev; + + dev->ee.cache = &dev->MEAR_cache; + dev->ee.lock = &dev->misc_lock; + dev->net_dev.owner = THIS_MODULE; + + PREPARE_TQUEUE(&dev->tq_refill, queue_refill, dev); + + err = pci_enable_device(pci_dev); + if (err) { + printk(KERN_INFO "ns83820: pci_enable_dev: %d\n", err); + goto out_free; + } + + pci_set_master(pci_dev); + addr = pci_resource_start(pci_dev, 1); + dev->base = ioremap_nocache(addr, PAGE_SIZE); + dev->tx_descs = pci_alloc_consistent(pci_dev, + 4 * DESC_SIZE * NR_TX_DESC, &dev->tx_phy_descs); + dev->rx_info.descs = pci_alloc_consistent(pci_dev, + 4 * DESC_SIZE * NR_RX_DESC, &dev->rx_info.phy_descs); + err = -ENOMEM; + if (!dev->base || !dev->tx_descs || !dev->rx_info.descs) + goto out_disable; + + dprintk("%p: %08lx %p: %08lx\n", dev->tx_descs, dev->tx_phy_descs, + dev->rx_info.descs, dev->rx_info.phy_descs); + /* disable interrupts */ + writel(0, dev->base + IMR); + writel(0, dev->base + IER); + readl(dev->base + IER); + + dev->IMR_cache = 0; + + setup_ee_mem_bitbanger(&dev->ee, (long)dev->base + MEAR, 3, 2, 1, 0, + 0); + + err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ, + dev->net_dev.name, dev); + if (err) { + printk(KERN_INFO "ns83820: unable to register irq %d\n", + pci_dev->irq); + goto out_unmap; + } + + dev->net_dev.open = ns83820_open; + dev->net_dev.stop = ns83820_stop; + dev->net_dev.hard_start_xmit = ns83820_hard_start_xmit; + dev->net_dev.change_mtu = ns83820_change_mtu; + //FIXME: dev->net_dev.tx_timeout = ns83820_tx_timeout; + + lock_kernel(); + dev->next_dev = ns83820_chain; + ns83820_chain = dev; + unlock_kernel(); + + ns83820_do_reset(dev, CR_RST); + + dprintk("start bist\n"); + writel(PTSCR_EEBIST_EN, dev->base + PTSCR); + do { + schedule(); + } while (readl(dev->base + PTSCR) & PTSCR_EEBIST_EN); + dprintk("done bist\n"); + + dprintk("start eeload\n"); + writel(PTSCR_EELOAD_EN, dev->base + PTSCR); + do { + schedule(); + } while (readl(dev->base + PTSCR) & PTSCR_EELOAD_EN); + dprintk("done eeload\n"); + + /* I love config registers */ + dev->CFG_cache = readl(dev->base + CFG); + + if ((dev->CFG_cache & CFG_PCI64_DET)) { + printk("%s: enabling 64 bit PCI.\n", dev->net_dev.name); + dev->CFG_cache |= CFG_T64ADDR | CFG_DATA64_EN; + } else { + printk("%s: disabling 64 bit PCI.\n", dev->net_dev.name); + dev->CFG_cache &= ~(CFG_T64ADDR | CFG_DATA64_EN); + } + dev->CFG_cache &= (CFG_TBI_EN | CFG_MRM_DIS | CFG_MWI_DIS | + CFG_T64ADDR | CFG_DATA64_EN | CFG_EXT_125 | + CFG_M64ADDR); + dev->CFG_cache |= CFG_PINT_DUPSTS | CFG_PINT_LNKSTS | CFG_PINT_SPDSTS | + CFG_EXTSTS_EN | CFG_EXD | CFG_PESEL; + dev->CFG_cache |= CFG_REQALG; + dev->CFG_cache |= CFG_POW; +#ifdef USE_64BIT_ADDR + dev->CFG_cache |= CFG_M64ADDR; + printk("using 64 bit addressing\n"); +#endif +#ifdef __LITTLE_ENDIAN + dev->CFG_cache &= ~CFG_BEM; +#elif defined(__BIG_ENDIAN) + dev->CFG_cache |= CFG_BEM; +#else +#error This driver only works for big or little endian!!! +#endif + + writel(dev->CFG_cache, dev->base + CFG); + dprintk("CFG: %08x\n", dev->CFG_cache); + + if (readl(dev->base + SRR)) + writel(readl(dev->base+0x20c) | 0xfe00, dev->base + 0x20c); + + /* Note! The DMA burst size interacts with packet + * transmission, such that the largest packet that + * can be transmitted is 8192 - FLTH - burst size. + * If only the transmit fifo was larger... + */ + writel(TXCFG_CSI | TXCFG_HBI | TXCFG_ATP | TXCFG_MXDMA1024 + | ((1600 / 32) * 0x100), + dev->base + TXCFG); + + /* Flush the interrupt holdoff timer */ + writel(0x000, dev->base + IHR); + writel(0x100, dev->base + IHR); + + /* Set Rx to full duplex, don't accept runt, errored, long or length + * range errored packets. Set MXDMA to 7 => 512 word burst + */ + writel(RXCFG_AEP | RXCFG_ARP | RXCFG_AIRL | RXCFG_RX_FD + | RXCFG_ALP + | RXCFG_MXDMA | 0, dev->base + RXCFG); + + /* Disable priority queueing */ + writel(0, dev->base + PQCR); + + /* Enable IP checksum validation and detetion of VLAN headers. + * Note: do not set the reject options as at least the 0x102 + * revision of the chip does not properly accept IP fragments + * at least for UDP. + */ + writel(VRCR_IPEN | VRCR_VTDEN, dev->base + VRCR); + + /* Enable per-packet TCP/UDP/IP checksumming */ + writel(VTCR_PPCHK, dev->base + VTCR); + + /* Disable Pause frames */ + writel(0, dev->base + PCR); + + /* Disable Wake On Lan */ + writel(0, dev->base + WCSR); + + ns83820_getmac(dev, dev->net_dev.dev_addr); + + /* Yes, we support dumb IP checksum on transmit */ + dev->net_dev.features |= NETIF_F_SG; + dev->net_dev.features |= NETIF_F_IP_CSUM; +#if defined(USE_64BIT_ADDR) || defined(CONFIG_HIGHMEM4G) + dev->net_dev.features |= NETIF_F_HIGHDMA; +#endif + + register_netdev(&dev->net_dev); + + printk(KERN_INFO "%s: ns83820.c v" VERSION ": DP83820 %02x:%02x:%02x:%02x:%02x:%02x pciaddr=0x%08lx irq=%d rev 0x%x\n", + dev->net_dev.name, + dev->net_dev.dev_addr[0], dev->net_dev.dev_addr[1], + dev->net_dev.dev_addr[2], dev->net_dev.dev_addr[3], + dev->net_dev.dev_addr[4], dev->net_dev.dev_addr[5], + addr, pci_dev->irq, + (unsigned)readl(dev->base + SRR) + ); + + return 0; + +out_unmap: + iounmap(dev->base); +out_disable: + pci_free_consistent(pci_dev, 4 * DESC_SIZE * NR_TX_DESC, dev->tx_descs, dev->tx_phy_descs); + pci_free_consistent(pci_dev, 4 * DESC_SIZE * NR_RX_DESC, dev->rx_info.descs, dev->rx_info.phy_descs); + pci_disable_device(pci_dev); +out_free: + kfree(dev); +out: + return err; +} + +static struct pci_device_id pci_device_id[] __devinitdata = { + { 0x100b, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + { 0, }, +}; + +static struct pci_driver driver = { + name: "ns83820", + id_table: pci_device_id, + probe: ns83820_probe, +#if 0 /* FIXME: implement */ + remove: , + suspend: , + resume: , +#endif +}; + + +static int __init ns83820_init(void) +{ + printk(KERN_INFO "ns83820.c: National Semiconductor DP83820 10/100/100 driver.\n"); + return pci_module_init(&driver); +} + +static void ns83820_exit(void) +{ + struct ns83820 *dev; + + for (dev = ns83820_chain; dev; ) { + struct ns83820 *next = dev->next_dev; + + writel(0, dev->base + IMR); /* paranoia */ + writel(0, dev->base + IER); + readl(dev->base + IER); + + unregister_netdev(&dev->net_dev); + free_irq(dev->pci_dev->irq, dev); + iounmap(dev->base); + pci_free_consistent(dev->pci_dev, 4 * DESC_SIZE * NR_TX_DESC, + dev->tx_descs, dev->tx_phy_descs); + pci_free_consistent(dev->pci_dev, 4 * DESC_SIZE * NR_RX_DESC, + dev->rx_info.descs, dev->rx_info.phy_descs); + pci_disable_device(dev->pci_dev); + kfree(dev); + dev = next; + } + pci_unregister_driver(&driver); + ns83820_chain = NULL; +} + +MODULE_AUTHOR("Benjamin LaHaise "); +MODULE_DESCRIPTION("National Semiconductor DP83820 10/100/1000 driver"); +MODULE_DEVICE_TABLE(pci, pci_device_id); +module_init(ns83820_init); +module_exit(ns83820_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in --- v2.4.9/linux/drivers/net/pcmcia/Config.in Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/pcmcia/Config.in Mon Sep 17 22:52:35 2001 @@ -20,7 +20,8 @@ fi if [ "$CONFIG_CARDBUS" = "y" ]; then - tristate ' Xircom Tulip-like CardBus support' CONFIG_PCMCIA_XIRTULIP + tristate ' Xircom CardBus support (new driver)' CONFIG_PCMCIA_XIRCOM + tristate ' Xircom Tulip-like CardBus support (old driver)' CONFIG_PCMCIA_XIRTULIP fi bool ' Pcmcia Wireless LAN' CONFIG_NET_PCMCIA_RADIO diff -u --recursive --new-file v2.4.9/linux/drivers/net/pcmcia/Makefile linux/drivers/net/pcmcia/Makefile --- v2.4.9/linux/drivers/net/pcmcia/Makefile Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/pcmcia/Makefile Mon Sep 17 22:52:35 2001 @@ -32,7 +32,9 @@ # Cardbus client drivers obj-$(CONFIG_PCMCIA_XIRTULIP) += xircom_tulip_cb.o +obj-$(CONFIG_PCMCIA_XIRCOM) += xircom_cb.o obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o include $(TOPDIR)/Rules.make + diff -u --recursive --new-file v2.4.9/linux/drivers/net/pcmcia/xirc2ps_cs.c linux/drivers/net/pcmcia/xirc2ps_cs.c --- v2.4.9/linux/drivers/net/pcmcia/xirc2ps_cs.c Wed Apr 18 14:40:05 2001 +++ linux/drivers/net/pcmcia/xirc2ps_cs.c Thu Sep 13 16:04:43 2001 @@ -2084,6 +2084,8 @@ MAYBE_SET(irq_list[2], 8); MAYBE_SET(irq_list[3], 9); #undef MAYBE_SET(X,Y) + + return 0; } __setup("xirc2ps_cs=", setup_xirc2ps_cs); diff -u --recursive --new-file v2.4.9/linux/drivers/net/pcmcia/xircom_cb.c linux/drivers/net/pcmcia/xircom_cb.c --- v2.4.9/linux/drivers/net/pcmcia/xircom_cb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/pcmcia/xircom_cb.c Mon Sep 17 22:52:35 2001 @@ -0,0 +1,1410 @@ +/* + * xircom_cb: A driver for the (tulip-like) Xircom Cardbus ethernet cards + * + * This software is Copyright 2001 by the respective authors, and licensed under the GPL + * License. + * + * Written by Arjan van de Ven for Red Hat, Inc. + * Based on work by Jeff Garzik, Doug Ledford, Donald Becker and Ion Badulescu + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * + * $Id: xircom_cb.c,v 1.11 2001/06/05 09:50:57 fenrus Exp $ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + + +#ifdef DEBUG +#define enter() printk("Enter: %s, %s line %i\n",__FUNCTION__,__FILE__,__LINE__) +#define leave() printk("Leave: %s, %s line %i\n",__FUNCTION__,__FILE__,__LINE__) +#else +#define enter() do {} while (0) +#define leave() do {} while (0) +#endif + + +MODULE_DESCRIPTION("Xircom Cardbus ethernet driver"); +MODULE_AUTHOR("Arjan van de Ven "); + + + +/* IO registers on the card, offsets */ +#define CSR0 0x00 +#define CSR1 0x08 +#define CSR2 0x10 +#define CSR3 0x18 +#define CSR4 0x20 +#define CSR5 0x28 +#define CSR6 0x30 +#define CSR7 0x38 +#define CSR8 0x40 +#define CSR9 0x48 +#define CSR10 0x50 +#define CSR11 0x58 +#define CSR12 0x60 +#define CSR13 0x68 +#define CSR14 0x70 +#define CSR15 0x78 +#define CSR16 0x80 + +/* PCI registers */ +#define PCI_POWERMGMT 0x40 + +/* Offsets of the buffers within the descriptor pages, in bytes */ + +#define NUMDESCRIPTORS 4 +#define RXTXBUFSIZE 8192 +#define MAX_PACKETSIZE 1536 + + +#define DescOwnedCard 0x80000000 +#define DescOwnedDriver 0x00000000 + +#define PromiscBit (1<<6) +#define CollisionBit (1<<8) +#define TxActiveBit (1<<13) +#define RxActiveBit (1<<1) +#define LastDescBit (1<<25) +#define LinkStatusBit (1<<27) + +#define PowerMgmtBits ( (1<<31)|(1<<30) ) + +static const unsigned int bufferoffsets[NUMDESCRIPTORS] = {128,2048,4096,6144}; + +/* note: this struct is assumed to be packed as this is the "hardware" layout */ +struct descriptor { + u32 status; + u32 control; + u32 address1; + u32 address2; +}; + + +struct xircom_private { + /* Send and receive buffers, kernel-addressable and dma addressable forms */ + + unsigned char *rx_buffer; + unsigned char *tx_buffer; + + struct descriptor *rx_desc; + struct descriptor *tx_desc; + + dma_addr_t rx_dma_handle; + dma_addr_t tx_dma_handle; + + struct sk_buff *tx_skb[NUMDESCRIPTORS]; + + unsigned long io_port; + + /* transmit_used is the rotating counter that indicates which transmit + descriptor has to be used next */ + unsigned int transmit_used; + + /* Spinlock to serialize register operations. + It must be helt while manipulating the following registers: + CSR0, CSR6, CSR7, CSR9, CSR10, CSR15 + */ + spinlock_t lock; + + + struct pci_dev *pdev; + struct net_device *dev; + struct net_device_stats stats; +}; + + +/* Function prototypes */ +static int xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id); +static void xircom_remove(struct pci_dev *pdev); +static void xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev); +static int xircom_open(struct net_device *dev); +static int xircom_close(struct net_device *dev); +static void xircom_up(struct xircom_private *card); +static struct net_device_stats *xircom_get_stats(struct net_device *dev); + +static void investigate_rx_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset); +static unsigned int investigate_tx_descriptor(struct net_device *dev, struct xircom_private *card, unsigned int descnr, unsigned int bufferoffset); +static void read_mac_address(struct xircom_private *card); +static void tranceiver_voodoo(struct xircom_private *card); +static void initialize_card(struct xircom_private *card); +static inline void trigger_transmit(struct xircom_private *card); +static inline void trigger_receive(struct xircom_private *card); +static void setup_descriptors(struct xircom_private *card); +static inline void remove_descriptors(struct xircom_private *card); +static inline unsigned int link_status_changed(struct xircom_private *card); +static void activate_receiver(struct xircom_private *card); +static void deactivate_receiver(struct xircom_private *card); +static void activate_transmitter(struct xircom_private *card); +static void deactivate_transmitter(struct xircom_private *card); +static void enable_transmit_interrupt(struct xircom_private *card); +static void enable_receive_interrupt(struct xircom_private *card); +static void enable_link_interrupt(struct xircom_private *card); +static void disable_all_interrupts(struct xircom_private *card); +static inline unsigned int link_status(struct xircom_private *card); +static int mdio_read(struct xircom_private *card, int phy_id, int location); +static void mdio_write(struct xircom_private *card, int phy_id, int location, int value); + + + +static struct pci_device_id xircom_pci_table[] __devinitdata = { + {0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID,}, + {0,}, +}; +MODULE_DEVICE_TABLE(pci, xircom_pci_table); + +static struct pci_driver xircom_ops = { + name: "xircom_cb", + id_table: xircom_pci_table, + probe: xircom_probe, + remove: xircom_remove, +}; + + +#ifdef DEBUG +static void print_binary(unsigned int number) +{ + int i,i2; + char buffer[64]; + memset(buffer,0,64); + i2=0; + for (i=31;i>=0;i--) { + if (number & (1<priv; + if (private==NULL) { + printk(KERN_ERR "xircom_probe: failed to allocate private device struct\n"); + return -ENODEV; + } + + /* Allocate the send/receive buffers */ + private->rx_buffer = pci_alloc_consistent(pdev,RXTXBUFSIZE,&private->rx_dma_handle); + if (private->rx_buffer == NULL) { + printk(KERN_ERR "xircom_probe: no memory for rx buffer \n"); + kfree(private); + return -ENODEV; + } + /* the descriptors are stored in the first bytes of the rx_buffer, hence the ugly cast */ + private->rx_desc = (struct descriptor *)private->rx_buffer; + + private->tx_buffer = pci_alloc_consistent(pdev,RXTXBUFSIZE,&private->tx_dma_handle); + if (private->tx_buffer == NULL) { + printk(KERN_ERR "xircom_probe: no memory for tx buffer \n"); + kfree(private->rx_buffer); + kfree(private); + return -ENODEV; + } + /* the descriptors are stored in the first bytes of the tx_buffer, hence the ugly cast */ + private->tx_desc = (struct descriptor *)private->tx_buffer; + + + printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq); + + private->dev = dev; + private->pdev = pdev; + private->io_port = pci_resource_start(pdev, 0); + private->lock = SPIN_LOCK_UNLOCKED; + dev->irq = pdev->irq; + dev->base_addr = private->io_port; + + + initialize_card(private); + read_mac_address(private); + setup_descriptors(private); + + dev->open = &xircom_open; + dev->hard_start_xmit = &xircom_start_xmit; + dev->stop = &xircom_close; + dev->get_stats = &xircom_get_stats; + dev->priv = private; + pci_set_drvdata(pdev,dev); + + + /* start the transmitter to get a heartbeat; don't do + that when there already is one though; Cisco's + really don't like that. */ + if (!link_status(private)) + tranceiver_voodoo(private); + + spin_lock_irqsave(&private->lock,flags); + activate_transmitter(private); + activate_receiver(private); + spin_unlock_irqrestore(&private->lock,flags); + + /* TODO: send 2 dummy packets here */ + + trigger_receive(private); + + leave(); + return 0; +} + + +/* + xircom_remove is called on module-unload or on device-eject. + it unregisters the irq, io-region and network device. + Interrupts and such are already stopped in the "ifconfig ethX down" + code. + */ +static void __devexit xircom_remove(struct pci_dev *pdev) +{ + struct net_device *dev = pdev->driver_data; + struct xircom_private *card; + enter(); + + card=dev->priv; + + if (card->rx_buffer!=NULL) + pci_free_consistent(pdev,RXTXBUFSIZE,card->rx_buffer,card->rx_dma_handle); + card->rx_buffer = NULL; + card->rx_desc = NULL; + if (card->tx_buffer!=NULL) + pci_free_consistent(pdev,RXTXBUFSIZE,card->tx_buffer,card->tx_dma_handle); + card->tx_buffer = NULL; + card->tx_desc = NULL; + + release_region(dev->base_addr, 128); + unregister_netdev(dev); + kfree(dev); + pci_set_drvdata(pdev,NULL); + leave(); +} + +static void xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device *dev = dev_instance; + struct xircom_private *card = dev->priv; + u32 status; + unsigned int xmit_free_count; + unsigned int i; + + enter(); + + + spin_lock(&card->lock); + status = inl(card->io_port+CSR5); + if (status==0xffffffff) {/* card has been ejected / powered down */ + spin_unlock(&card->lock); + return; + } + + /* Todo: check if there were any events at all; to speed up + returning if we're on a shared interrupt */ + + if (link_status_changed(card)) { + int newlink; + printk(KERN_DEBUG "xircom_cb: Link status has changed \n"); + newlink = link_status(card); + if (newlink) { + printk(KERN_INFO "xircom_cb: Link is %i mbit \n",newlink); + netif_carrier_on(dev); + } else { + printk(KERN_INFO "xircom_cb: Link is absent \n"); + netif_carrier_off(dev); + } + } + + /* Clear all remaining interrupt events */ + status |= 0xffffffff; /* FIXME: make this clear only the + real existing bits */ + outl(status,card->io_port+CSR5); + + xmit_free_count = 0; + + for (i=0;ilock); + leave(); +} + +static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct xircom_private *card; + unsigned long flags; + unsigned int nextdescriptor; + unsigned int desc; + enter(); + + card = (struct xircom_private*)dev->priv; + + spin_lock_irqsave(&card->lock,flags); + + nextdescriptor = (card->transmit_used +1) % (NUMDESCRIPTORS); + desc = card->transmit_used; + + /* only send the packet if the descriptor is free */ + if (card->tx_desc[desc].status==0) { + /* Copy the packet data; zero the memory first as the card + sometimes sends more than you ask it to. */ + + memset(&card->tx_buffer[bufferoffsets[desc]],0,MAX_PACKETSIZE); + memcpy(&(card->tx_buffer[bufferoffsets[desc]]),skb->data,skb->len); + + + /* FIXME: The specification tells us that the length we send HAS to be a multiple of + 4 bytes. */ + + card->tx_desc[desc].control = skb->len; + if (desc == NUMDESCRIPTORS-1) + card->tx_desc[desc].control |= LastDescBit; /* bit 25: last descriptor of the ring */ + + card->tx_desc[desc].control |= 0xF0000000; + /* 0xF0... means want interrupts*/ + card->tx_skb[desc] = skb; + + wmb(); + /* This gives the descriptor to the card */ + card->tx_desc[desc].status = DescOwnedCard; + trigger_transmit(card); + if (((int)card->tx_desc[nextdescriptor].status)<0) { /* next descriptor is occupied... */ + netif_stop_queue(dev); + } + card->transmit_used = nextdescriptor; + spin_unlock_irqrestore(&card->lock,flags); + leave(); + return 0; + } + + + + /* Uh oh... no free descriptor... drop the packet */ + /* This should not happen in theory...*/ + netif_stop_queue(dev); + spin_unlock_irqrestore(&card->lock,flags); + trigger_transmit(card); + leave(); + + return -EIO; +} + + + + +static int xircom_open(struct net_device *dev) +{ + struct xircom_private *xp = (struct xircom_private *) dev->priv; + int retval; + enter(); + printk(KERN_INFO "Xircom cardbus adaptor found, registering as %s, using irq %i \n",dev->name,dev->irq); + retval = request_irq(dev->irq, &xircom_interrupt, SA_SHIRQ, dev->name, dev); + if (retval) { + printk(KERN_ERR "xircom_cb: Unable to aquire IRQ %i, aborting.\n",dev->irq); + leave(); + return retval; + } + + xircom_up(xp); + leave(); + return 0; +} + +static int xircom_close(struct net_device *dev) +{ + struct xircom_private *card; + unsigned long flags; + + enter(); + card = dev->priv; + netif_stop_queue(dev); /* we don't want to send new packets */ + + + spin_lock_irqsave(&card->lock,flags); + + disable_all_interrupts(card); +#if 0 + /* We can enable this again once we send dummy packets on ifconfig ethX up */ + deactivate_receiver(card); + deactivate_transmitter(card); +#endif + remove_descriptors(card); + + spin_unlock_irqrestore(&card->lock,flags); + + free_irq(dev->irq,dev); + + leave(); + + return 0; + +} + + + +static struct net_device_stats *xircom_get_stats(struct net_device *dev) +{ + struct xircom_private *card = (struct xircom_private *)dev->priv; + return &card->stats; +} + + + + +static void initialize_card(struct xircom_private *card) +{ + unsigned int val; + unsigned long flags; + enter(); + + + spin_lock_irqsave(&card->lock, flags); + + /* First: reset the card */ + val = inl(card->io_port + CSR0); + val |= 0x01; /* Software reset */ + outl(val, card->io_port + CSR0); + + udelay(100); /* give the card some time to reset */ + + val = inl(card->io_port + CSR0); + val &= ~0x01; /* disable Software reset */ + outl(val, card->io_port + CSR0); + + + val = 0; /* Value 0x00 is a safe and conservative value + for the PCI configuration settings */ + outl(val, card->io_port + CSR0); + + + disable_all_interrupts(card); + deactivate_receiver(card); + deactivate_transmitter(card); + + spin_unlock_irqrestore(&card->lock, flags); + + leave(); +} + +/* +trigger_transmit causes the card to check for frames to be transmitted. +This is accomplished by writing to the CSR1 port. The documentation +claims that the act of writing is sufficient and that the value is +ignored; I chose zero. +*/ +static inline void trigger_transmit(struct xircom_private *card) +{ + enter(); + outl(0, card->io_port + CSR1); + leave(); +} + +/* +trigger_receive causes the card to check for empty frames in the +descriptor list in which packets can be received. +This is accomplished by writing to the CSR2 port. The documentation +claims that the act of writing is sufficient and that the value is +ignored; I chose zero. +*/ +static inline void trigger_receive(struct xircom_private *card) +{ + enter(); + outl(0, card->io_port + CSR2); + leave(); +} + +/* +setup_descriptors initializes the send and receive buffers to be valid +descriptors and programs the addresses into the card. +*/ +static void setup_descriptors(struct xircom_private *card) +{ + unsigned int val; + u32 address; + unsigned int i; + enter(); + + + if (card->rx_buffer == NULL) + BUG(); + if (card->tx_buffer == NULL) + BUG(); + + /* Receive descriptors */ + memset(card->rx_desc, 0, 128); /* clear the descriptors */ + for (i=0;i 0x80000000 */ + card->rx_desc[i].status = DescOwnedCard; + /* Rx Descr1: buffer 1 is 1536 bytes, buffer 2 is 0 bytes */ + card->rx_desc[i].control = MAX_PACKETSIZE; + if (i==NUMDESCRIPTORS-1) + card->rx_desc[i].control |= LastDescBit; /* bit 25 is "last descriptor" */ + + /* Rx Descr2: address of the buffer + we store the buffer at the 2nd half of the page */ + + address = card->rx_dma_handle; + + card->rx_desc[i].address1 = cpu_to_le32(address + bufferoffsets[i]); + /* Rx Desc3: address of 2nd buffer -> 0 */ + card->rx_desc[i].address2 = 0; + } + + wmb(); + /* Write the receive descriptor ring address to the card */ + address = card->rx_dma_handle; + val = cpu_to_le32(address); + outl(val, card->io_port + CSR3); /* Receive descr list address */ + + + /* transmit descriptors */ + memset(card->tx_desc, 0, 128); /* clear the descriptors */ + + for (i=0;i 0x00000000 */ + card->tx_desc[i].status = DescOwnedDriver; + /* Tx Descr1: buffer 1 is 1536 bytes, buffer 2 is 0 bytes */ + card->tx_desc[i].control = MAX_PACKETSIZE; + if (i==NUMDESCRIPTORS-1) + card->tx_desc[i].control |= LastDescBit; /* bit 25 is "last descriptor" */ + + /* Tx Descr2: address of the buffer + we store the buffer at the 2nd half of the page */ + address = card->tx_dma_handle; + card->tx_desc[i].address1 = cpu_to_le32(address + bufferoffsets[i]); + /* Tx Desc3: address of 2nd buffer -> 0 */ + card->tx_desc[i].address2 = 0; + } + + wmb(); + /* wite the transmit descriptor ring to the card */ + address = card->tx_dma_handle; + val =cpu_to_le32(address); + outl(val, card->io_port + CSR4); /* xmit descr list address */ + + leave(); +} + +/* +remove_descriptors informs the card the descriptors are no longer +valid by setting the address in the card to 0x00. +*/ +static inline void remove_descriptors(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = 0; + outl(val, card->io_port + CSR3); /* Receive descriptor address */ + outl(val, card->io_port + CSR4); /* Send descriptor address */ + + leave(); +} + +/* +link_status_changed returns 1 if the card has indicated that +the link status has changed. The new link status has to be read from CSR12. + +This function also clears the status-bit. +*/ +static inline unsigned int link_status_changed(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = inl(card->io_port + CSR5); /* Status register */ + + if ((val & LinkStatusBit) == 0) { /* no change */ + leave(); + return 0; + } + + /* clear the event by writing a 1 to the bit in the + status register. */ + val = LinkStatusBit; + outl(val, card->io_port + CSR5); + + leave(); + return 1; +} + + +/* +transmit_active returns 1 if the transmitter on the card is +in a non-stopped state. +*/ +static inline int transmit_active(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = inl(card->io_port + CSR5); /* Status register */ + + if ((val & (7 << 20)) == 0) { /* transmitter disabled */ + leave(); + return 0; + } + + leave(); + return 1; +} + +/* +receive_active returns 1 if the receiver on the card is +in a non-stopped state. +*/ +static inline unsigned int receive_active(struct xircom_private *card) +{ + unsigned int val; + enter(); + + + val = inl(card->io_port + CSR5); /* Status register */ + + if ((val & (7 << 17)) == 0) { /* receiver disabled */ + leave(); + return 0; + } + + leave(); + return 1; +} + +/* +activate_receiver enables the receiver on the card. +Before being allowed to active the receiver, the receiver +must be completely de-activated. To achieve this, +this code actually disables the receiver first; then it waits for the +receiver to become inactive, then it activates the receiver and then +it waits for the receiver to be active. + +must be called with the lock held and interrupts disabled. +*/ +static void activate_receiver(struct xircom_private *card) +{ + unsigned int val; + int counter; + enter(); + + + val = inl(card->io_port + CSR6); /* Operation mode */ + + /* If the "active" bit (1) is set and the receiver is already + active, no need to do the expensive thing */ + if ((val& RxActiveBit) && (receive_active(card))) + return; + + + val = val & ~RxActiveBit; /* disable the receiver */ + outl(val, card->io_port + CSR6); + + counter = 10; + while (counter > 0) { + if (!receive_active(card)) + break; + /* wait a while */ + udelay(50); + counter--; + if (counter <= 0) + printk(KERN_ERR "xircom_cb: Receiver failed to deactivate\n"); + } + + /* enable the receiver */ + val = inl(card->io_port + CSR6); /* Operation mode */ + val = val | RxActiveBit; /* enable the receiver */ + outl(val, card->io_port + CSR6); + + /* now wait for the card to activate again */ + counter = 10; + while (counter > 0) { + if (receive_active(card)) + break; + /* wait a while */ + udelay(50); + counter--; + if (counter <= 0) + printk(KERN_ERR "xircom_cb: Receiver failed to re-activate\n"); + } + + leave(); +} + +/* +deactivate_receiver disables the receiver on the card. +To achieve this this code disables the receiver first; +then it waits for the receiver to become inactive. + +must be called with the lock held and interrupts disabled. +*/ +static void deactivate_receiver(struct xircom_private *card) +{ + unsigned int val; + int counter; + enter(); + + val = inl(card->io_port + CSR6); /* Operation mode */ + val = val & ~RxActiveBit; /* disable the receiver */ + outl(val, card->io_port + CSR6); + + counter = 10; + while (counter > 0) { + if (!receive_active(card)) + break; + /* wait a while */ + udelay(50); + counter--; + if (counter <= 0) + printk(KERN_ERR "xircom_cb: Receiver failed to deactivate\n"); + } + + + leave(); +} + + +/* +activate_transmitter enables the transmitter on the card. +Before being allowed to active the transmitter, the transmitter +must be completely de-activated. To achieve this, +this code actually disables the transmitter first; then it waits for the +transmitter to become inactive, then it activates the transmitter and then +it waits for the transmitter to be active again. + +must be called with the lock held and interrupts disabled. +*/ +static void activate_transmitter(struct xircom_private *card) +{ + unsigned int val; + int counter; + enter(); + + + val = inl(card->io_port + CSR6); /* Operation mode */ + + /* If the "active" bit (13) is set and the receiver is already + active, no need to do the expensive thing */ + if ((val & TxActiveBit) && (transmit_active(card))) + return; + + val = val & ~TxActiveBit; /* disable the transmitter */ + outl(val, card->io_port + CSR6); + + counter = 10; + while (counter > 0) { + if (!transmit_active(card)) + break; + /* wait a while */ + udelay(50); + counter--; + if (counter <= 0) + printk(KERN_ERR "xircom_cb: Transmitter failed to deactivate\n"); + } + + /* enable the transmitter */ + val = inl(card->io_port + CSR6); /* Operation mode */ + val = val | TxActiveBit; /* enable the transmitter */ + outl(val, card->io_port + CSR6); + + /* now wait for the card to activate again */ + counter = 10; + while (counter > 0) { + if (transmit_active(card)) + break; + /* wait a while */ + udelay(50); + counter--; + if (counter <= 0) + printk(KERN_ERR "xircom_cb: Transmitter failed to re-activate\n"); + } + + leave(); +} + +/* +deactivate_transmitter disables the transmitter on the card. +To achieve this this code disables the transmitter first; +then it waits for the transmitter to become inactive. + +must be called with the lock held and interrupts disabled. +*/ +static void deactivate_transmitter(struct xircom_private *card) +{ + unsigned int val; + int counter; + enter(); + + val = inl(card->io_port + CSR6); /* Operation mode */ + val = val & ~TxActiveBit; /* disable the transmitter */ + outl(val, card->io_port + CSR6); + + counter = 20; + while (counter > 0) { + if (!transmit_active(card)) + break; + /* wait a while */ + udelay(50); + counter--; + if (counter <= 0) + printk(KERN_ERR "xircom_cb: Transmitter failed to deactivate\n"); + } + + + leave(); +} + + +/* +enable_transmit_interrupt enables the transmit interrupt + +must be called with the lock held and interrupts disabled. +*/ +static void enable_transmit_interrupt(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = inl(card->io_port + CSR7); /* Interrupt enable register */ + val |= 1; /* enable the transmit interrupt */ + outl(val, card->io_port + CSR7); + + leave(); +} + + +/* +enable_receive_interrupt enables the receive interrupt + +must be called with the lock held and interrupts disabled. +*/ +static void enable_receive_interrupt(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = inl(card->io_port + CSR7); /* Interrupt enable register */ + val = val | (1 << 6); /* enable the receive interrupt */ + outl(val, card->io_port + CSR7); + + leave(); +} + +/* +enable_link_interrupt enables the link status change interrupt + +must be called with the lock held and interrupts disabled. +*/ +static void enable_link_interrupt(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = inl(card->io_port + CSR7); /* Interrupt enable register */ + val = val | LinkStatusBit; /* enable the link status chage interrupt */ + outl(val, card->io_port + CSR7); + + leave(); +} + + + +/* +disable_all_interrupts disables all interrupts + +must be called with the lock held and interrupts disabled. +*/ +static void disable_all_interrupts(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = 0; /* disable all interrupts */ + outl(val, card->io_port + CSR7); + + leave(); +} + +/* +enable_common_interrupts enables several weird interrupts + +must be called with the lock held and interrupts disabled. +*/ +static void enable_common_interrupts(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = inl(card->io_port + CSR7); /* Interrupt enable register */ + val |= (1<<16); /* Normal Interrupt Summary */ + val |= (1<<15); /* Abnormal Interrupt Summary */ + val |= (1<<13); /* Fatal bus error */ + val |= (1<<8); /* Receive Process Stopped */ + val |= (1<<7); /* Receive Buffer Unavailable */ + val |= (1<<5); /* Transmit Underflow */ + val |= (1<<2); /* Transmit Buffer Unavailable */ + val |= (1<<1); /* Transmit Process Stopped */ + outl(val, card->io_port + CSR7); + + leave(); +} + +/* +enable_promisc starts promisc mode + +must be called with the lock held and interrupts disabled. +*/ +static inline void enable_promisc(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = inl(card->io_port + CSR6); + val = val | PromiscBit; /* Bit 6 */ + outl(val, card->io_port + CSR6); + + printk(KERN_INFO "xircom_cb: enabling promiscuous mode \n"); + leave(); +} + + + + +/* +link_status() checks the the links status and will return 0 for no link, +10 for 10mbit link and 100 for.. guess what. + +Must be called in locked state with interrupts disabled +*/ +static inline unsigned int link_status(struct xircom_private *card) +{ + unsigned int val; + enter(); + + val = inb(card->io_port + CSR12); + + if (!(val&(1<<2))) /* bit 2 is 0 for 10mbit link, 1 for not an 10mbit link */ + return 10; + if (!(val&(1<<1))) /* bit 1 is 0 for 100mbit link, 1 for not an 100mbit link */ + return 100; + + /* If we get here -> no link at all */ + + leave(); + return 0; +} + + + +/* + +set_half_duplex() sets the card to half duplex mode. In order to do this, +set_half_duplex() has to deactivate the transmitter and receiver first. It +will re-enable the transmitter and receiver if those were active from the +beginning. + +Update: the above is not enough. It doesn't touch the MII, in fact it ensures +the main chipset and the MII are never in sync if a full-duplex connection +is negotiated. The proper fix is to tell the MII to force a half-duplex +connection. -Ion + +Must be called in locked state +*/ +static void set_half_duplex(struct xircom_private *card) +{ + unsigned int val; + int rx,tx,tmp; + enter(); + + rx=receive_active(card); + tx=transmit_active(card); + + deactivate_transmitter(card); + deactivate_receiver(card); + + val = inb(card->io_port + CSR6); + val &= ~(1<<9); + outb(val,card->io_port + CSR6); + + /* tell the MII not to advertise 10/100FDX */ + tmp = mdio_read(card, 0, 4); + printk("xircom_cb: capabilities changed from %#x to %#x\n", + tmp, tmp & ~0x140); + tmp &= ~0x140; + mdio_write(card, 0, 4, tmp); + /* restart autonegotiation */ + tmp = mdio_read(card, 0, 0); + mdio_write(card, 0, 0, tmp | 0x1200); + + if (rx) + activate_receiver(card); + if (tx) + activate_transmitter(card); + + leave(); +} + + +/* + read_mac_address() reads the MAC address from the NIC and stores it in the "dev" structure. + + This function will take the spinlock itself and can, as a result, not be called with the lock helt. + */ +static void read_mac_address(struct xircom_private *card) +{ + unsigned char j, tuple, link, data_id, data_count; + unsigned long flags; + int i; + + enter(); + + spin_lock_irqsave(&card->lock, flags); + + outl(1 << 12, card->io_port + CSR9); /* enable boot rom access */ + for (i = 0x100; i < 0x1f7; i += link + 2) { + outl(i, card->io_port + CSR10); + tuple = inl(card->io_port + CSR9) & 0xff; + outl(i + 1, card->io_port + CSR10); + link = inl(card->io_port + CSR9) & 0xff; + outl(i + 2, card->io_port + CSR10); + data_id = inl(card->io_port + CSR9) & 0xff; + outl(i + 3, card->io_port + CSR10); + data_count = inl(card->io_port + CSR9) & 0xff; + if ((tuple == 0x22) && (data_id == 0x04) && (data_count == 0x06)) { + /* + * This is it. We have the data we want. + */ + for (j = 0; j < 6; j++) { + outl(i + j + 4, card->io_port + CSR10); + card->dev->dev_addr[j] = inl(card->io_port + CSR9) & 0xff; + } + break; + } else if (link == 0) { + break; + } + } + spin_unlock_irqrestore(&card->lock, flags); +#ifdef DEBUG + for (i = 0; i < 6; i++) + printk("%c%2.2X", i ? ':' : ' ', card->dev->dev_addr[i]); + printk("\n"); +#endif + leave(); +} + + +/* MII transceiver control section. + Read and write the MII registers using software-generated serial + MDIO protocol. See the MII specifications or DP83840A data sheet + for details. */ + +/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually + met by back-to-back PCI I/O cycles, but we insert a delay to avoid + "overclocking" issues or future 66Mhz PCI. */ +#define mdio_delay() inl(mdio_addr) + +/* Read and write the MII registers using software-generated serial + MDIO protocol. It is just different enough from the EEPROM protocol + to not share code. The maxium data clock rate is 2.5 Mhz. */ +#define MDIO_SHIFT_CLK 0x10000 +#define MDIO_DATA_WRITE0 0x00000 +#define MDIO_DATA_WRITE1 0x20000 +#define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */ +#define MDIO_ENB_IN 0x40000 +#define MDIO_DATA_READ 0x80000 + +static int mdio_read(struct xircom_private *card, int phy_id, int location) +{ + int i; + int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; + int retval = 0; + long mdio_addr = card->io_port + CSR9; + + /* Establish sync by sending at least 32 logic ones. */ + for (i = 32; i >= 0; i--) { + outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); + mdio_delay(); + outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Shift the read command bits out. */ + for (i = 15; i >= 0; i--) { + int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; + + outl(MDIO_ENB | dataval, mdio_addr); + mdio_delay(); + outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Read the two transition, 16 data, and wire-idle bits. */ + for (i = 19; i > 0; i--) { + outl(MDIO_ENB_IN, mdio_addr); + mdio_delay(); + retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); + outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + return (retval>>1) & 0xffff; +} + +static void mdio_write(struct xircom_private *card, int phy_id, int location, int value) +{ + int i; + int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; + long mdio_addr = card->io_port + CSR9; + + /* Establish sync by sending 32 logic ones. */ + for (i = 32; i >= 0; i--) { + outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); + mdio_delay(); + outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Shift the command bits out. */ + for (i = 31; i >= 0; i--) { + int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; + outl(MDIO_ENB | dataval, mdio_addr); + mdio_delay(); + outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Clear out extra bits. */ + for (i = 2; i > 0; i--) { + outl(MDIO_ENB_IN, mdio_addr); + mdio_delay(); + outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } +} + + +/* + tranceiver_voodoo() enables the external UTP plug thingy. + it's called voodoo as I stole this code and cannot cross-reference + it with the specification. + */ +static void tranceiver_voodoo(struct xircom_private *card) +{ + unsigned long flags; + u32 tmp32; + + enter(); + + /* disable all powermanagement */ + pci_read_config_dword(card->pdev, PCI_POWERMGMT,&tmp32); + tmp32 &= ~PowerMgmtBits; + pci_write_config_dword(card->pdev, PCI_POWERMGMT, tmp32); + + setup_descriptors(card); + + spin_lock_irqsave(&card->lock, flags); + + outl(0x0008, card->io_port + CSR15); + udelay(25); + outl(0xa8050000, card->io_port + CSR15); + udelay(25); + outl(0xa00f0000, card->io_port + CSR15); + udelay(25); + + spin_unlock_irqrestore(&card->lock, flags); + + netif_start_queue(card->dev); + leave(); +} + + +static void xircom_up(struct xircom_private *card) +{ + unsigned long flags; + int i; + u32 tmp32; + + enter(); + + /* disable all powermanagement */ + pci_read_config_dword(card->pdev, PCI_POWERMGMT,&tmp32); + tmp32 &= ~PowerMgmtBits; + pci_write_config_dword(card->pdev, PCI_POWERMGMT, tmp32); + + setup_descriptors(card); + + spin_lock_irqsave(&card->lock, flags); + + + enable_link_interrupt(card); + enable_transmit_interrupt(card); + enable_receive_interrupt(card); + enable_common_interrupts(card); + enable_promisc(card); + + /* The card can have received packets already, read them away now */ + for (i=0;idev,card,i,bufferoffsets[i]); + + + set_half_duplex(card); + spin_unlock_irqrestore(&card->lock, flags); + trigger_receive(card); + trigger_transmit(card); + netif_start_queue(card->dev); + leave(); +} + +static void investigate_rx_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset) +{ + int status; + + enter(); + status = card->rx_desc[descnr].status; + + if ((status > 0)) { /* packet received */ + + /* TODO: discard error packets */ + + short pkt_len = ((status >> 16) & 0x7ff) - 4; /* minus 4, we don't want the CRC */ + struct sk_buff *skb; + + if (pkt_len > 1518) { + printk(KERN_ERR "xircom_cb: Packet length %i is bogus \n",pkt_len); + pkt_len = 1518; + } + + skb = dev_alloc_skb(pkt_len + 2); + if (skb == NULL) { + card->stats.rx_dropped++; + goto out; + } + skb->dev = dev; + skb_reserve(skb, 2); + eth_copy_and_sum(skb, &card->rx_buffer[bufferoffset], pkt_len, 0); + skb_put(skb, pkt_len); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->last_rx = jiffies; + card->stats.rx_packets++; + card->stats.rx_bytes += pkt_len; + + out: + /* give the buffer back to the card */ + card->rx_desc[descnr].status = DescOwnedCard; + trigger_receive(card); + } + + leave(); + +} + + +/* Returns 1 if the descriptor is free or became free */ +static unsigned int investigate_tx_descriptor(struct net_device *dev, struct xircom_private *card, unsigned int descnr, unsigned int bufferoffset) +{ + int status,retval = 0; + enter(); + + status = card->tx_desc[descnr].status; + + if (status == DescOwnedDriver) + return 1; +#if 0 + if (status & 0x8000) { /* Major error */ + printk(KERN_ERR "Major transmit error status %x \n", status); + card->tx_desc[descnr].status = 0; + netif_wake_queue (dev); + } +#endif + if (status > 0) { /* bit 31 is 0 when done */ + card->stats.tx_packets++; + if (card->tx_skb[descnr]!=NULL) { + card->stats.tx_bytes += card->tx_skb[descnr]->len; + dev_kfree_skb_irq(card->tx_skb[descnr]); + } + card->tx_skb[descnr] = NULL; + /* Bit 8 in the status field is 1 if there was a collision */ + if (status & CollisionBit) + card->stats.collisions++; + card->tx_desc[descnr].status = DescOwnedDriver; /* descriptor is free again */ + retval = 1; + } + + leave(); + return retval; +} + + +static int __init xircom_init(void) +{ + pci_register_driver(&xircom_ops); + return 0; +} + +static void __exit xircom_exit(void) +{ + pci_unregister_driver(&xircom_ops); +} + +module_init(xircom_init) +module_exit(xircom_exit) diff -u --recursive --new-file v2.4.9/linux/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c --- v2.4.9/linux/drivers/net/pcmcia/xircom_tulip_cb.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/pcmcia/xircom_tulip_cb.c Fri Sep 14 14:40:00 2001 @@ -67,7 +67,7 @@ ToDo: Non-Intel setting could be better. */ -#if defined(__alpha__) +#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__) static int csr0 = 0x01A00000 | 0xE000; #elif defined(__powerpc__) static int csr0 = 0x01B00000 | 0x8000; diff -u --recursive --new-file v2.4.9/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- v2.4.9/linux/drivers/net/pcnet32.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/pcnet32.c Sun Sep 9 10:50:48 2001 @@ -179,6 +179,7 @@ * v1.25kf Added No Interrupt on successful Tx for some Tx's * v1.26 Converted to pci_alloc_consistent, Jamey Hicks / George France * + * v1.26p Fix oops on rmmod+insmod; plug i/o resource leak - Paul Gortmaker */ @@ -471,7 +472,7 @@ -static int __init +static int __devinit pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) { static int card_idx; @@ -506,10 +507,11 @@ * Called from both pcnet32_probe_vlbus and pcnet_probe_pci. * pdev will be NULL when called from pcnet32_probe_vlbus. */ -static int __init +static int __devinit pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int card_idx, struct pci_dev *pdev) { struct pcnet32_private *lp; + struct resource *res; dma_addr_t lp_dma_addr; int i,media,fdx = 0, mii = 0, fset = 0; #ifdef DO_DXSUFLO @@ -643,7 +645,7 @@ } if( memcmp( promaddr, dev->dev_addr, 6) ) { - printk(" warning PROM address does not match CSR address"); + printk(" warning PROM address does not match CSR address\n"); #if defined(__i386__) printk(KERN_WARNING "%s: Probably a Compaq, using the PROM address of", dev->name); memcpy(dev->dev_addr, promaddr, 6); @@ -682,11 +684,15 @@ } dev->base_addr = ioaddr; - request_region(ioaddr, PCNET32_TOTAL_SIZE, chipname); + res = request_region(ioaddr, PCNET32_TOTAL_SIZE, chipname); + if (res == NULL) + return -EBUSY; /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ - if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) + if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { + release_resource(res); return -ENOMEM; + } memset(lp, 0, sizeof(*lp)); lp->dma_addr = lp_dma_addr; @@ -715,6 +721,7 @@ if (a == NULL) { printk(KERN_ERR "pcnet32: No access methods\n"); pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + release_resource(res); return -ENODEV; } lp->a = *a; @@ -762,6 +769,7 @@ else { printk(", failed to detect IRQ line.\n"); pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + release_resource(res); return -ENODEV; } } @@ -1579,6 +1587,8 @@ next_dev = lp->next; unregister_netdev(pcnet32_dev); release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); + if (lp->pci_dev != NULL) + pci_unregister_driver(&pcnet32_driver); pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); kfree(pcnet32_dev); pcnet32_dev = next_dev; diff -u --recursive --new-file v2.4.9/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c --- v2.4.9/linux/drivers/net/ppp_generic.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/ppp_generic.c Sun Sep 9 10:45:43 2001 @@ -636,7 +636,7 @@ if (copy_from_user(&uprog, (void *) arg, sizeof(uprog))) break; - if (uprog.len > 0) { + if (uprog.len > 0 && uprog.len < 65536) { err = -ENOMEM; len = uprog.len * sizeof(struct sock_filter); code = kmalloc(len, GFP_KERNEL); diff -u --recursive --new-file v2.4.9/linux/drivers/net/sis900.c linux/drivers/net/sis900.c --- v2.4.9/linux/drivers/net/sis900.c Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/sis900.c Sun Sep 9 10:45:43 2001 @@ -600,7 +600,7 @@ /** * sis900_set_capability: - set the media capability of network adapter. * @net_dev : the net device to probe for - * @mii_phy : default PHY + * @phy : default PHY * * Set the media capability of network adapter according to * mii status register. It's necessary before auto-negotiate. @@ -1190,6 +1190,7 @@ /** * sis900_set_mode: - Set the media mode of mac register. + * @ioaddr: the address of the device * @speed : the transmit speed to be determined * @duplex: the duplex mode to be determined * diff -u --recursive --new-file v2.4.9/linux/drivers/net/sk98lin/h/skdrv1st.h linux/drivers/net/sk98lin/h/skdrv1st.h --- v2.4.9/linux/drivers/net/sk98lin/h/skdrv1st.h Wed Jul 25 17:10:21 2001 +++ linux/drivers/net/sk98lin/h/skdrv1st.h Sun Sep 9 10:45:43 2001 @@ -113,7 +113,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/net/sk98lin/skproc.c linux/drivers/net/sk98lin/skproc.c --- v2.4.9/linux/drivers/net/sk98lin/skproc.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/sk98lin/skproc.c Mon Sep 10 09:04:53 2001 @@ -293,7 +293,7 @@ if (buffer_length >= len - offset) { *eof = 1; } - return (min(int, buffer_length, len - offset)); + return (min_t(int, buffer_length, len - offset)); } 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/strip.c linux/drivers/net/strip.c --- v2.4.9/linux/drivers/net/strip.c Sun Feb 4 10:05:30 2001 +++ linux/drivers/net/strip.c Thu Sep 13 16:04:43 2001 @@ -2828,7 +2828,7 @@ * STRIP driver */ -static const char signon[] __initdata = KERN_INFO "STRIP: Version %s (unlimited channels)\n"; +static char signon[] __initdata = KERN_INFO "STRIP: Version %s (unlimited channels)\n"; static int __init strip_init_driver(void) { diff -u --recursive --new-file v2.4.9/linux/drivers/net/sungem.c linux/drivers/net/sungem.c --- v2.4.9/linux/drivers/net/sungem.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/sungem.c Thu Sep 13 16:04:43 2001 @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/net/tokenring/abyss.c linux/drivers/net/tokenring/abyss.c --- v2.4.9/linux/drivers/net/tokenring/abyss.c Fri May 25 09:58:07 2001 +++ linux/drivers/net/tokenring/abyss.c Thu Sep 13 16:04:43 2001 @@ -53,6 +53,8 @@ }; MODULE_DEVICE_TABLE(pci, abyss_pci_tbl); +MODULE_LICENSE("GPL"); + static int abyss_open(struct net_device *dev); static int abyss_close(struct net_device *dev); static void abyss_enable(struct net_device *dev); diff -u --recursive --new-file v2.4.9/linux/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c --- v2.4.9/linux/drivers/net/tokenring/ibmtr.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/net/tokenring/ibmtr.c Thu Sep 13 16:04:43 2001 @@ -1924,6 +1924,8 @@ static int irq[IBMTR_MAX_ADAPTERS]; static int mem[IBMTR_MAX_ADAPTERS]; +MODULE_LICENSE("GPL"); + MODULE_PARM(io, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/net/tokenring/madgemc.c linux/drivers/net/tokenring/madgemc.c --- v2.4.9/linux/drivers/net/tokenring/madgemc.c Fri May 25 09:58:07 2001 +++ linux/drivers/net/tokenring/madgemc.c Thu Sep 13 16:04:43 2001 @@ -793,6 +793,8 @@ } #endif /* MODULE */ +MODULE_LICENSE("GPL"); + /* * Local variables: @@ -804,3 +806,4 @@ * tab-width: 8 * End: */ + diff -u --recursive --new-file v2.4.9/linux/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c --- v2.4.9/linux/drivers/net/tokenring/olympic.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/tokenring/olympic.c Thu Sep 13 16:04:43 2001 @@ -1722,4 +1722,4 @@ module_init(olympic_pci_init) ; module_exit(olympic_pci_cleanup) ; - +MODULE_LICENSE("GPL"); \ No newline at end of file diff -u --recursive --new-file v2.4.9/linux/drivers/net/tokenring/smctr.c linux/drivers/net/tokenring/smctr.c --- v2.4.9/linux/drivers/net/tokenring/smctr.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/tokenring/smctr.c Thu Sep 13 16:04:43 2001 @@ -5733,6 +5733,8 @@ static int irq[SMCTR_MAX_ADAPTERS]; static int mem[SMCTR_MAX_ADAPTERS]; +MODULE_LICENSE("GPL"); + MODULE_PARM(io, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/net/tokenring/tms380tr.c linux/drivers/net/tokenring/tms380tr.c --- v2.4.9/linux/drivers/net/tokenring/tms380tr.c Wed May 16 10:31:27 2001 +++ linux/drivers/net/tokenring/tms380tr.c Thu Sep 13 16:04:43 2001 @@ -71,10 +71,8 @@ static const char version[] = "tms380tr.c: v1.08 14/01/2001 by Christoph Goos, Adam Fritzler\n"; #endif -#ifdef MODULE #include #include -#endif #include #include @@ -2416,6 +2414,8 @@ TMS380_module = NULL; } #endif + +MODULE_LICENSE("GPL"); /* diff -u --recursive --new-file v2.4.9/linux/drivers/net/tokenring/tmsisa.c linux/drivers/net/tokenring/tmsisa.c --- v2.4.9/linux/drivers/net/tokenring/tmsisa.c Fri Apr 20 11:54:22 2001 +++ linux/drivers/net/tokenring/tmsisa.c Thu Sep 13 16:04:43 2001 @@ -372,6 +372,8 @@ static int irq[ISATR_MAX_ADAPTERS]; static int dma[ISATR_MAX_ADAPTERS]; +MODULE_LICENSE("GPL"); + MODULE_PARM(io, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i"); MODULE_PARM(dma, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/net/tokenring/tmspci.c linux/drivers/net/tokenring/tmspci.c --- v2.4.9/linux/drivers/net/tokenring/tmspci.c Fri May 25 09:58:07 2001 +++ linux/drivers/net/tokenring/tmspci.c Thu Sep 13 16:04:43 2001 @@ -67,6 +67,8 @@ }; MODULE_DEVICE_TABLE(pci, tmspci_pci_tbl); +MODULE_LICENSE("GPL"); + static void tms_pci_read_eeprom(struct net_device *dev); static unsigned short tms_pci_setnselout_pins(struct net_device *dev); diff -u --recursive --new-file v2.4.9/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c --- v2.4.9/linux/drivers/net/tulip/tulip_core.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/net/tulip/tulip_core.c Fri Sep 14 14:40:00 2001 @@ -77,7 +77,7 @@ ToDo: Non-Intel setting could be better. */ -#if defined(__alpha__) || defined(__ia64__) +#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__) static int csr0 = 0x01A00000 | 0xE000; #elif defined(__i386__) || defined(__powerpc__) static int csr0 = 0x01A00000 | 0x8000; @@ -1503,6 +1503,10 @@ #ifdef CONFIG_TULIP_MWI if (!force_csr0 && (tp->flags & HAS_PCI_MWI)) tulip_mwi_config (pdev, dev); +#else + /* MWI is broken for DC21143 rev 65... */ + if (chip_idx == DC21143 && chip_rev == 65) + tp->csr0 &= ~MWI; #endif /* Stop the chip's Tx and Rx processes. */ 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/c101.c linux/drivers/net/wan/c101.c --- v2.4.9/linux/drivers/net/wan/c101.c Tue Mar 6 19:44:36 2001 +++ linux/drivers/net/wan/c101.c Thu Sep 13 16:04:43 2001 @@ -371,5 +371,6 @@ MODULE_AUTHOR("Krzysztof Halasa "); MODULE_DESCRIPTION("Moxa C101 serial port driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(hw, "s"); /* hw=irq,ram:irq,... */ EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/comx-hw-comx.c linux/drivers/net/wan/comx-hw-comx.c --- v2.4.9/linux/drivers/net/wan/comx-hw-comx.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/comx-hw-comx.c Thu Sep 13 16:04:43 2001 @@ -63,6 +63,7 @@ MODULE_AUTHOR("Gergely Madarasz , Tivadar Szemethy , Arpad Bakay"); MODULE_DESCRIPTION("Hardware-level driver for the COMX and HICOMX adapters\n"); +MODULE_LICENSE("GPL"); #define COMX_readw(dev, offset) (readw(dev->mem_start + offset + \ (unsigned int)(((struct comx_privdata *)\ @@ -1044,7 +1045,7 @@ if (!(page = (char *)__get_free_page(GFP_KERNEL))) { return -ENOMEM; } - if(copy_from_user(page, buffer, count = (min(int, count, PAGE_SIZE)))) + if(copy_from_user(page, buffer, count = (min_t(int, count, PAGE_SIZE)))) { count = -EFAULT; goto out; @@ -1182,8 +1183,8 @@ len = sprintf(page, "external\n"); } } else if (strcmp(file->name, FILENAME_FIRMWARE) == 0) { - len = min(int, FILE_PAGESIZE, - min(int, count, + len = min_t(int, FILE_PAGESIZE, + min_t(int, count, hw->firmware ? (hw->firmware->len - off) : 0)); if (len < 0) { @@ -1205,7 +1206,7 @@ if (count >= len - off) { *eof = 1; } - return min(int, count, len - off); + return min_t(int, count, len - off); } /* Called on echo comx >boardtype */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/comx-hw-locomx.c linux/drivers/net/wan/comx-hw-locomx.c --- v2.4.9/linux/drivers/net/wan/comx-hw-locomx.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/comx-hw-locomx.c Thu Sep 13 16:04:43 2001 @@ -54,6 +54,7 @@ MODULE_AUTHOR("Gergely Madarasz "); MODULE_DESCRIPTION("Hardware driver for the LoCOMX board"); +MODULE_LICENSE("GPL"); #define RX_DMA 3 #define TX_DMA 1 @@ -324,7 +325,7 @@ if (count >= len - off) { *eof = 1; } - return min(int, count, len - off); + return min_t(int, count, len - off); } static int locomx_write_proc(struct file *file, const char *buffer, @@ -339,7 +340,7 @@ return -ENOMEM; } - copy_from_user(page, buffer, count = min(unsigned long, count, PAGE_SIZE)); + copy_from_user(page, buffer, count = min_t(unsigned long, count, PAGE_SIZE)); if (*(page + count - 1) == '\n') { *(page + count - 1) = 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/comx-hw-mixcom.c linux/drivers/net/wan/comx-hw-mixcom.c --- v2.4.9/linux/drivers/net/wan/comx-hw-mixcom.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/comx-hw-mixcom.c Thu Sep 13 16:04:43 2001 @@ -58,6 +58,7 @@ MODULE_AUTHOR("Gergely Madarasz "); MODULE_DESCRIPTION("Hardware-level driver for the serial port of the MixCom board"); +MODULE_LICENSE("GPL"); #define MIXCOM_DATA(d) ((struct mixcom_privdata *)(COMX_CHANNEL(d)-> \ HW_privdata)) @@ -121,7 +122,7 @@ outsb(dev->base_addr + HSCX_FIFO, - &(hw->sending->data[hw->tx_ptr]), min(unsigned int, to_send, 32)); + &(hw->sending->data[hw->tx_ptr]), min_t(unsigned int, to_send, 32)); if (to_send <= 32) { hscx_cmd(dev, HSCX_XTF | HSCX_XME); kfree_skb(hw->sending); @@ -696,7 +697,7 @@ } *start = page + off; if (count >= len - off) *eof = 1; - return min(int, count, len - off); + return min_t(int, count, len - off); } @@ -763,7 +764,7 @@ return -ENOMEM; } - copy_from_user(page, buffer, count = min(unsigned long, count, PAGE_SIZE)); + copy_from_user(page, buffer, count = min_t(unsigned long, count, PAGE_SIZE)); if (*(page + count - 1) == '\n') { *(page + count - 1) = 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/comx-proto-fr.c linux/drivers/net/wan/comx-proto-fr.c --- v2.4.9/linux/drivers/net/wan/comx-proto-fr.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/comx-proto-fr.c Thu Sep 13 16:04:43 2001 @@ -53,7 +53,8 @@ MODULE_AUTHOR("Author: Tivadar Szemethy "); MODULE_DESCRIPTION("Frame Relay protocol implementation for the COMX drivers" - "for Linux kernel 2.2.X"); + "for Linux kernel 2.4.X"); +MODULE_LICENSE("GPL"); #define FRAD_UI 0x03 #define NLPID_IP 0xcc @@ -634,7 +635,7 @@ *start = page + off; if (count >= len - off) *eof = 1; - return min(int, count, len - off); + return min_t(int, count, len - off); } static int fr_write_proc(struct file *file, const char *buffer, diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/comx-proto-lapb.c linux/drivers/net/wan/comx-proto-lapb.c --- v2.4.9/linux/drivers/net/wan/comx-proto-lapb.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/comx-proto-lapb.c Thu Sep 13 16:04:43 2001 @@ -212,7 +212,7 @@ if (count >= len - off) { *eof = 1; } - return min(int, count, len - off); + return min_t(int, count, len - off); } static int comxlapb_write_proc(struct file *file, const char *buffer, @@ -543,3 +543,5 @@ module_init(comx_proto_lapb_init); #endif module_exit(comx_proto_lapb_exit); + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/comx-proto-ppp.c linux/drivers/net/wan/comx-proto-ppp.c --- v2.4.9/linux/drivers/net/wan/comx-proto-ppp.c Tue Mar 6 19:44:36 2001 +++ linux/drivers/net/wan/comx-proto-ppp.c Thu Sep 13 16:04:43 2001 @@ -49,6 +49,7 @@ MODULE_AUTHOR("Author: Gergely Madarasz "); MODULE_DESCRIPTION("Cisco-HDLC / Synchronous PPP driver for the COMX sync serial boards"); +MODULE_LICENSE("GPL"); static struct comx_protocol syncppp_protocol; static struct comx_protocol hdlc_protocol; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/comx.c linux/drivers/net/wan/comx.c --- v2.4.9/linux/drivers/net/wan/comx.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/comx.c Thu Sep 13 16:04:43 2001 @@ -78,6 +78,7 @@ MODULE_AUTHOR("Gergely Madarasz "); MODULE_DESCRIPTION("Common code for the COMX synchronous serial adapters"); +MODULE_LICENSE("GPL"); extern int comx_hw_comx_init(void); extern int comx_hw_locomx_init(void); @@ -151,8 +152,8 @@ int free = (ch->debug_start - ch->debug_end + ch->debug_size) % ch->debug_size; - to_copy = min(int, free ? free : ch->debug_size, - min(int, ch->debug_size - ch->debug_end, len)); + to_copy = min_t(int, free ? free : ch->debug_size, + min_t(int, ch->debug_size - ch->debug_end, len)); memcpy(ch->debug_area + ch->debug_end, str, to_copy); str += to_copy; len -= to_copy; @@ -567,7 +568,7 @@ if (count >= len - off) { *eof = 1; } - return min(int, count, len - off); + return min_t(int, count, len - off); } @@ -597,7 +598,7 @@ if (count >= len - off) { *eof = 1; } - return min(int, count, len - off); + return min_t(int, count, len - off); } diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c --- v2.4.9/linux/drivers/net/wan/cosa.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/cosa.c Thu Sep 13 16:04:43 2001 @@ -251,6 +251,7 @@ MODULE_AUTHOR("Jan \"Yenya\" Kasprzak, "); MODULE_DESCRIPTION("Modular driver for the COSA or SRP synchronous card"); +MODULE_LICENSE("GPL"); #endif /* I use this mainly for testing purposes */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/cycx_main.c linux/drivers/net/wan/cycx_main.c --- v2.4.9/linux/drivers/net/wan/cycx_main.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/cycx_main.c Thu Sep 13 16:04:43 2001 @@ -56,6 +56,7 @@ MODULE_AUTHOR("Arnaldo Carvalho de Melo"); MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver."); +MODULE_LICENSE("GPL"); MODULE_PARM(cycx_debug, "i"); MODULE_PARM_DESC(cycx_debug, "cyclomx debug level"); @@ -111,8 +112,8 @@ fullname, DRV_VERSION, DRV_RELEASE, copyright); /* Verify number of cards and allocate adapter data space */ - ncards = min(int, ncards, MAX_CARDS); - ncards = max(int, ncards, 1); + ncards = min_t(int, ncards, MAX_CARDS); + ncards = max_t(int, ncards, 1); card_array = kmalloc(sizeof(cycx_t) * ncards, GFP_KERNEL); if (!card_array) goto out; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/cycx_x25.c linux/drivers/net/wan/cycx_x25.c --- v2.4.9/linux/drivers/net/wan/cycx_x25.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/cycx_x25.c Fri Sep 14 14:39:59 2001 @@ -260,13 +260,13 @@ cfg.flags = 0; /* FIXME just reset the 2nd bit */ if (conf->u.x25.hi_pvc) { - card->u.x.hi_pvc = min(unsigned int, conf->u.x25.hi_pvc, 4095); - card->u.x.lo_pvc = min(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc); + card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, 4095); + card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc); } if (conf->u.x25.hi_svc) { - card->u.x.hi_svc = min(unsigned int, conf->u.x25.hi_svc, 4095); - card->u.x.lo_svc = min(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc); + card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, 4095); + card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc); } if (card->u.x.lo_pvc == 255) @@ -277,25 +277,25 @@ cfg.nvc = card->u.x.hi_svc - card->u.x.lo_svc + 1 + cfg.npvc; if (conf->u.x25.hdlc_window) - cfg.n2win = min(unsigned int, conf->u.x25.hdlc_window, 7); + cfg.n2win = min_t(unsigned int, conf->u.x25.hdlc_window, 7); if (conf->u.x25.pkt_window) - cfg.n3win = min(unsigned int, conf->u.x25.pkt_window, 7); + cfg.n3win = min_t(unsigned int, conf->u.x25.pkt_window, 7); if (conf->u.x25.t1) - cfg.t1 = min(unsigned int, conf->u.x25.t1, 30); + cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30); if (conf->u.x25.t2) - cfg.t2 = min(unsigned int, conf->u.x25.t2, 30); + cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 30); if (conf->u.x25.t11_t21) - cfg.t21 = min(unsigned int, conf->u.x25.t11_t21, 30); + cfg.t21 = min_t(unsigned int, conf->u.x25.t11_t21, 30); if (conf->u.x25.t13_t23) - cfg.t23 = min(unsigned int, conf->u.x25.t13_t23, 30); + cfg.t23 = min_t(unsigned int, conf->u.x25.t13_t23, 30); if (conf->u.x25.n2) - cfg.n2 = min(unsigned int, conf->u.x25.n2, 30); + cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30); /* initialize adapter */ if (x25_configure(card, &cfg)) @@ -1347,7 +1347,7 @@ { x25_channel_t *chan = dev->priv; cycx_t *card = chan->card; - u32 flags = 0; + long flags; char *string_state = NULL; spin_lock_irqsave(&card->lock, flags); diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/dlci.c linux/drivers/net/wan/dlci.c --- v2.4.9/linux/drivers/net/wan/dlci.c Fri Apr 20 11:54:22 2001 +++ linux/drivers/net/wan/dlci.c Thu Sep 13 16:04:43 2001 @@ -609,3 +609,7 @@ dlci_ioctl_hook = NULL; } #endif /* MODULE */ + +MODULE_AUTHOR("Mike McLagan"); +MODULE_DESCRIPTION("Frame Relay DLCI layer"); +MODULE_LICENSE("GPL"); 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 Thu Sep 13 16:04:43 2001 @@ -114,6 +114,7 @@ /* Module parameters */ MODULE_AUTHOR("Maintainer: Francois Romieu "); MODULE_DESCRIPTION("Siemens PEB20534 PCI Controller"); +MODULE_LICENSE("GPL"); MODULE_PARM(debug,"i"); /* Structures */ @@ -348,7 +349,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 +429,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 +443,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 +761,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 +1225,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 +1378,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 +1610,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 +1721,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 Sun Sep 9 10:45:53 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; } @@ -1829,3 +1830,4 @@ module_init ( fst_init ); module_exit ( fst_cleanup_module ); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/hdlc.c linux/drivers/net/wan/hdlc.c --- v2.4.9/linux/drivers/net/wan/hdlc.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/wan/hdlc.c Thu Sep 13 16:04:43 2001 @@ -1437,6 +1437,7 @@ MODULE_AUTHOR("Krzysztof Halasa "); MODULE_DESCRIPTION("HDLC support module"); +MODULE_LICENSE("GPL"); EXPORT_SYMBOL(hdlc_netif_rx); EXPORT_SYMBOL(register_hdlc_device); diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/hostess_sv11.c linux/drivers/net/wan/hostess_sv11.c --- v2.4.9/linux/drivers/net/wan/hostess_sv11.c Wed Apr 18 14:40:07 2001 +++ linux/drivers/net/wan/hostess_sv11.c Sun Sep 9 10:50:48 2001 @@ -400,7 +400,6 @@ static int io=0x200; static int irq=9; -#ifdef LINUX_21 MODULE_PARM(io,"i"); MODULE_PARM_DESC(io, "The I/O base of the Comtrol Hostess SV11 card"); MODULE_PARM(dma,"i"); @@ -408,9 +407,9 @@ MODULE_PARM(irq,"i"); MODULE_PARM_DESC(irq, "The interrupt line setting for the Comtrol Hostess SV11 card"); -MODULE_AUTHOR("Bulding Number Three Ltd"); +MODULE_AUTHOR("Alan Cox"); +MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Modular driver for the Comtrol Hostess SV11"); -#endif static struct sv11_device *sv11_unit; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/lapbether.c linux/drivers/net/wan/lapbether.c --- v2.4.9/linux/drivers/net/wan/lapbether.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/wan/lapbether.c Thu Sep 13 16:04:43 2001 @@ -467,7 +467,7 @@ notifier_call: lapbeth_device_event, }; -static const char banner[] __initdata = KERN_INFO "LAPB Ethernet driver version 0.01\n"; +static char banner[] __initdata = KERN_INFO "LAPB Ethernet driver version 0.01\n"; static int __init lapbeth_init_driver(void) { @@ -510,4 +510,6 @@ MODULE_AUTHOR("Jonathan Naylor "); MODULE_DESCRIPTION("The unofficial LAPB over Ethernet driver"); +MODULE_LICENSE("GPL"); + diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/lmc/lmc_main.c linux/drivers/net/wan/lmc/lmc_main.c --- v2.4.9/linux/drivers/net/wan/lmc/lmc_main.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/wan/lmc/lmc_main.c Thu Sep 13 16:04:43 2001 @@ -108,6 +108,8 @@ }; MODULE_DEVICE_TABLE(pci, lmc_pci_tbl); + +MODULE_LICENSE("GPL"); #endif diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/n2.c linux/drivers/net/wan/n2.c --- v2.4.9/linux/drivers/net/wan/n2.c Tue Mar 6 19:44:37 2001 +++ linux/drivers/net/wan/n2.c Thu Sep 13 16:04:43 2001 @@ -586,5 +586,6 @@ MODULE_AUTHOR("Krzysztof Halasa "); MODULE_DESCRIPTION("RISCom/N2 serial port driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(hw, "s"); /* hw=io,irq,ram,ports:io,irq,... */ EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sbni.c linux/drivers/net/wan/sbni.c --- v2.4.9/linux/drivers/net/wan/sbni.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/sbni.c Fri Sep 14 14:40:00 2001 @@ -11,7 +11,7 @@ * at http://www.granch.com (English) or http://www.granch.ru (Russian) * * This software may be used and distributed according to the terms - * of the GNU Public License. + * of the GNU General Public License. * * * 5.0.1 Jun 22 2001 @@ -155,7 +155,9 @@ static int emancipate( struct net_device * ); #endif +#ifdef __i386__ #define ASM_CRC 1 +#endif static const char version[] = "Granch SBNI12 driver ver 5.0.1 Jun 22 2001 Denis I.Timofeev.\n"; @@ -361,7 +363,7 @@ /* store MAC address (generate if that isn't known) */ *(u16 *)dev->dev_addr = htons( 0x00ff ); *(u32 *)(dev->dev_addr + 2) = htonl( 0x01000000 | - ( (mac[num] ? mac[num] : (u32)dev->priv) & 0x00ffffff) ); + ( (mac[num] ? mac[num] : (u32)((long)dev->priv)) & 0x00ffffff) ); /* store link settings (speed, receive level ) */ nl->maxframe = DEFAULT_FRAME_LEN; @@ -659,7 +661,7 @@ struct net_local *nl = (struct net_local *) dev->priv; struct sk_buff *skb = nl->tx_buf_p; - unsigned len = min(unsigned int, skb->len - nl->outpos, nl->framelen); + unsigned len = min_t(unsigned int, skb->len - nl->outpos, nl->framelen); outsb( dev->base_addr + DAT, skb->data + nl->outpos, len ); *crc_p = calc_crc32( *crc_p, skb->data + nl->outpos, len ); @@ -760,7 +762,7 @@ nl->outpos += nl->framelen; if( --nl->tx_frameno ) - nl->framelen = min(unsigned int, + nl->framelen = min_t(unsigned int, nl->maxframe, nl->tx_buf_p->len - nl->outpos); else @@ -1474,6 +1476,8 @@ MODULE_PARM( skip_pci_probe, "i" ); +MODULE_LICENSE("GPL"); + int init_module( void ) @@ -1517,7 +1521,7 @@ #else /* MODULE */ -void __init +static int __init sbni_setup( char *p ) { int n, parm; @@ -1528,7 +1532,7 @@ for( n = 0, parm = 0; *p && n < 8; ) { (*dest[ parm ])[ n ] = simple_strtol( p, &p, 0 ); if( !*p || *p == ')' ) - return; + return 1; if( *p == ';' ) ++p, ++n, parm = 0; else if( *p++ != ',' ) @@ -1539,6 +1543,7 @@ } bad_param: printk( KERN_ERR "Error in sbni kernel parameter!\n" ); + return 0; } __setup( "sbni=", sbni_setup ); diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sdla.c linux/drivers/net/wan/sdla.c --- v2.4.9/linux/drivers/net/wan/sdla.c Wed Apr 18 14:40:07 2001 +++ linux/drivers/net/wan/sdla.c Thu Sep 13 16:04:43 2001 @@ -1665,6 +1665,8 @@ #ifdef MODULE static struct net_device sdla0 = {"sdla0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, sdla_init}; +MODULE_LICENSE("GPL"); + int init_module(void) { int result; 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 Thu Sep 13 16:04:43 2001 @@ -48,6 +48,7 @@ * Aug 07, 1998 David Fong Initial version. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ @@ -505,13 +506,13 @@ /* For Primary Port 0 */ card->wandev.mtu = (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? - min(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) : + min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) : CHDLC_DFLT_DATA_LEN; } else if(port_num == WANOPT_SEC) { /* For Secondary Port 1 */ card->wandev.mtu = (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? - min(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) : + min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) : CHDLC_DFLT_DATA_LEN; } @@ -827,19 +828,19 @@ card->u.c.kpalv_tx = ((conf->keepalive_tx_tmr - MIN_Tx_KPALV_TIMER) >= 0) ? - min(unsigned int, conf->keepalive_tx_tmr,MAX_Tx_KPALV_TIMER) : + min_t(unsigned int, conf->keepalive_tx_tmr,MAX_Tx_KPALV_TIMER) : DEFAULT_Tx_KPALV_TIMER; card->u.c.kpalv_rx = ((conf->keepalive_rx_tmr - MIN_Rx_KPALV_TIMER) >= 0) ? - min(unsigned int, conf->keepalive_rx_tmr,MAX_Rx_KPALV_TIMER) : + min_t(unsigned int, conf->keepalive_rx_tmr,MAX_Rx_KPALV_TIMER) : DEFAULT_Rx_KPALV_TIMER; card->u.c.kpalv_err = ((conf->keepalive_err_margin-MIN_KPALV_ERR_TOL) >= 0) ? - min(unsigned int, conf->keepalive_err_margin, + min_t(unsigned int, conf->keepalive_err_margin, MAX_KPALV_ERR_TOL) : DEFAULT_KPALV_ERR_TOL; } @@ -847,7 +848,7 @@ /* Setup slarp timer to control delay between slarps */ card->u.c.slarp_timer = ((conf->slarp_timer - MIN_SLARP_REQ_TIMER) >= 0) ? - min(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) : + min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) : DEFAULT_SLARP_REQ_TIMER; #ifdef LINUX_2_0 @@ -4740,5 +4741,7 @@ #endif + +MODULE_LICENSE("GPL"); /****** End ****************************************************************/ 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 Thu Sep 13 16:04:43 2001 @@ -138,6 +138,7 @@ * Jan 02, 1997 Gene Kozin Initial version. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ @@ -548,10 +549,10 @@ /* Adjust configuration */ conf->mtu += FR_HEADER_LEN; conf->mtu = (conf->mtu >= MIN_LGTH_FR_DATA_CFG) ? - min(unsigned int, conf->mtu, FR_MAX_NO_DATA_BYTES_IN_FRAME) : + min_t(unsigned int, conf->mtu, FR_MAX_NO_DATA_BYTES_IN_FRAME) : FR_CHANNEL_MTU + FR_HEADER_LEN; - conf->bps = min(unsigned int, conf->bps, 2048000); + conf->bps = min_t(unsigned int, conf->bps, 2048000); /* Initialze the configuration structure sent to the board to zero */ memset(&u.cfg, 0, sizeof(u.cfg)); @@ -618,7 +619,7 @@ * command in fr_configure() routine. */ - card->u.f.dlci_num = min(unsigned int, max(unsigned int, conf->u.fr.dlci_num, 1), 100); + card->u.f.dlci_num = min_t(unsigned int, max_t(unsigned int, conf->u.fr.dlci_num, 1), 100); for ( i = 0; i < card->u.f.dlci_num; i++) { @@ -635,27 +636,27 @@ u.cfg.port |= 0x0002; if (conf->u.fr.t391) - u.cfg.t391 = min(unsigned int, conf->u.fr.t391, 30); + u.cfg.t391 = min_t(unsigned int, conf->u.fr.t391, 30); else u.cfg.t391 = 5; if (conf->u.fr.t392) - u.cfg.t392 = min(unsigned int, conf->u.fr.t392, 30); + u.cfg.t392 = min_t(unsigned int, conf->u.fr.t392, 30); else u.cfg.t392 = 15; if (conf->u.fr.n391) - u.cfg.n391 = min(unsigned int, conf->u.fr.n391, 255); + u.cfg.n391 = min_t(unsigned int, conf->u.fr.n391, 255); else u.cfg.n391 = 2; if (conf->u.fr.n392) - u.cfg.n392 = min(unsigned int, conf->u.fr.n392, 10); + u.cfg.n392 = min_t(unsigned int, conf->u.fr.n392, 10); else u.cfg.n392 = 3; if (conf->u.fr.n393) - u.cfg.n393 = min(unsigned int, conf->u.fr.n393, 10); + u.cfg.n393 = min_t(unsigned int, conf->u.fr.n393, 10); else u.cfg.n393 = 4; @@ -952,8 +953,8 @@ */ if (conf->cir) { - chan->cir = max(unsigned int, 1, - min(unsigned int, conf->cir, 512)); + chan->cir = max_t(unsigned int, 1, + min_t(unsigned int, conf->cir, 512)); chan->cir_status = CIR_ENABLED; @@ -964,8 +965,8 @@ chan->bc = chan->cir; if (conf->be){ - chan->be = max(unsigned int, - 0, min(unsigned int, conf->be, 511)); + chan->be = max_t(unsigned int, + 0, min_t(unsigned int, conf->be, 511)); }else{ conf->be = 0; } @@ -5475,5 +5476,6 @@ +MODULE_LICENSE("GPL"); /****** End *****************************************************************/ 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 Thu Sep 13 16:04:43 2001 @@ -20,29 +20,20 @@ * Aug 07, 1998 David Fong Initial version. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ +#include #include /* offsetof(), etc. */ #include /* return codes */ #include /* inline memset(), etc. */ -#include /* kmalloc(), kfree() */ +#include /* kmalloc(), kfree() */ #include /* WAN router definitions */ #include /* WANPIPE common user API definitions */ #include /* ARPHRD_* defines */ -#if defined(LINUX_2_4) - #include - #include - -#elif defined(LINUX_2_1) - #include - #include - -#else - #include /* Adding new route entries */ - #include - #define test_and_set_bit set_bit -#endif +#include +#include #include /* sockaddr_in */ #include @@ -384,3 +375,4 @@ return 0; } +MODULE_LICENSE("GPL"); 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 Thu Sep 13 16:04:43 2001 @@ -90,6 +90,7 @@ * Jan 06, 1997 Gene Kozin Initial version. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ @@ -400,7 +401,7 @@ printk(KERN_INFO "%s: running PPP firmware v%s\n",card->devname, u.str); /* Adjust configuration and set defaults */ card->wandev.mtu = (conf->mtu) ? - min(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU; + min_t(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU; card->wandev.bps = conf->bps; card->wandev.interface = conf->interface; @@ -629,7 +630,7 @@ dev->init = &if_init; dev->priv = ppp_priv_area; - dev->mtu = min(unsigned int, dev->mtu, card->wandev.mtu); + dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu); /* Initialize the polling task routine */ #ifndef LINUX_2_4 @@ -3720,5 +3721,6 @@ return 0; } +MODULE_LICENSE("GPL"); /****** End *****************************************************************/ 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 Thu Sep 13 16:04:43 2001 @@ -81,6 +81,7 @@ * Includes *=====================================================*/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ @@ -653,13 +654,13 @@ u.cfg.defPktSize = u.cfg.pktMTU = card->wandev.mtu; if (conf->u.x25.hi_pvc){ - card->u.x.hi_pvc = min(unsigned int, conf->u.x25.hi_pvc, MAX_LCN_NUM); - card->u.x.lo_pvc = min(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc); + card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, MAX_LCN_NUM); + card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc); } if (conf->u.x25.hi_svc){ - card->u.x.hi_svc = min(unsigned int, conf->u.x25.hi_svc, MAX_LCN_NUM); - card->u.x.lo_svc = min(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc); + card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, MAX_LCN_NUM); + card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc); } /* Figure out the total number of channels to configure */ @@ -684,38 +685,38 @@ u.cfg.hiTwoWaySVC = card->u.x.hi_svc; if (conf->u.x25.hdlc_window) - u.cfg.hdlcWindow = min(unsigned int, conf->u.x25.hdlc_window, 7); + u.cfg.hdlcWindow = min_t(unsigned int, conf->u.x25.hdlc_window, 7); if (conf->u.x25.pkt_window) - u.cfg.pktWindow = min(unsigned int, conf->u.x25.pkt_window, 7); + u.cfg.pktWindow = min_t(unsigned int, conf->u.x25.pkt_window, 7); if (conf->u.x25.t1) - u.cfg.t1 = min(unsigned int, conf->u.x25.t1, 30); + u.cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30); if (conf->u.x25.t2) - u.cfg.t2 = min(unsigned int, conf->u.x25.t2, 29); + u.cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 29); if (conf->u.x25.t4) - u.cfg.t4 = min(unsigned int, conf->u.x25.t4, 240); + u.cfg.t4 = min_t(unsigned int, conf->u.x25.t4, 240); if (conf->u.x25.n2) - u.cfg.n2 = min(unsigned int, conf->u.x25.n2, 30); + u.cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30); if (conf->u.x25.t10_t20) - u.cfg.t10t20 = min(unsigned int, conf->u.x25.t10_t20,255); + u.cfg.t10t20 = min_t(unsigned int, conf->u.x25.t10_t20,255); if (conf->u.x25.t11_t21) - u.cfg.t11t21 = min(unsigned int, conf->u.x25.t11_t21,255); + u.cfg.t11t21 = min_t(unsigned int, conf->u.x25.t11_t21,255); if (conf->u.x25.t12_t22) - u.cfg.t12t22 = min(unsigned int, conf->u.x25.t12_t22,255); + u.cfg.t12t22 = min_t(unsigned int, conf->u.x25.t12_t22,255); if (conf->u.x25.t13_t23) - u.cfg.t13t23 = min(unsigned int, conf->u.x25.t13_t23,255); + u.cfg.t13t23 = min_t(unsigned int, conf->u.x25.t13_t23,255); if (conf->u.x25.t16_t26) - u.cfg.t16t26 = min(unsigned int, conf->u.x25.t16_t26, 255); + u.cfg.t16t26 = min_t(unsigned int, conf->u.x25.t16_t26, 255); if (conf->u.x25.t28) - u.cfg.t28 = min(unsigned int, conf->u.x25.t28, 255); + u.cfg.t28 = min_t(unsigned int, conf->u.x25.t28, 255); if (conf->u.x25.r10_r20) - u.cfg.r10r20 = min(unsigned int, conf->u.x25.r10_r20,250); + u.cfg.r10r20 = min_t(unsigned int, conf->u.x25.r10_r20,250); if (conf->u.x25.r12_r22) - u.cfg.r12r22 = min(unsigned int, conf->u.x25.r12_r22,250); + u.cfg.r12r22 = min_t(unsigned int, conf->u.x25.r12_r22,250); if (conf->u.x25.r13_r23) - u.cfg.r13r23 = min(unsigned int, conf->u.x25.r13_r23,250); + u.cfg.r13r23 = min_t(unsigned int, conf->u.x25.r13_r23,250); if (conf->u.x25.ccitt_compat) @@ -5568,5 +5569,7 @@ printk(KERN_INFO "DTR DOWN FAILED %x\n",err); } + +MODULE_LICENSE("GPL"); /****** End *****************************************************************/ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sdladrv.c linux/drivers/net/wan/sdladrv.c --- v2.4.9/linux/drivers/net/wan/sdladrv.c Sun May 20 12:11:39 2001 +++ linux/drivers/net/wan/sdladrv.c Thu Sep 13 16:04:43 2001 @@ -213,13 +213,13 @@ * Note: All data must be explicitly initialized!!! */ -#ifdef LINUX_2_4 static struct pci_device_id sdladrv_pci_tbl[] __initdata = { { V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl); -#endif + +MODULE_LICENSE("GPL"); /* private data */ static char modname[] = "sdladrv"; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sdlamain.c linux/drivers/net/wan/sdlamain.c --- v2.4.9/linux/drivers/net/wan/sdlamain.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/sdlamain.c Thu Sep 13 16:04:43 2001 @@ -1440,4 +1440,6 @@ return; } +MODULE_LICENSE("GPL"); + /****** End *********************************************************/ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/sealevel.c linux/drivers/net/wan/sealevel.c --- v2.4.9/linux/drivers/net/wan/sealevel.c Wed Apr 18 14:40:07 2001 +++ linux/drivers/net/wan/sealevel.c Sun Sep 9 10:50:48 2001 @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. * * (c) Copyright 1999 Building Number Three Ltd + * (c) Copyright 2001 Alan Cox. * */ @@ -455,7 +456,8 @@ MODULE_PARM(slow,"i"); MODULE_PARM_DESC(slow, "Set this for an older Sealevel card such as the 4012"); -MODULE_AUTHOR("Bulding Number Three Ltd"); +MODULE_AUTHOR("Alan Cox"); +MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Modular driver for the SeaLevel 4021"); #endif diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/syncppp.c linux/drivers/net/wan/syncppp.c --- v2.4.9/linux/drivers/net/wan/syncppp.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wan/syncppp.c Thu Sep 13 16:04:43 2001 @@ -1397,7 +1397,7 @@ func: sppp_rcv, }; -static const char banner[] __initdata = +static char banner[] __initdata = KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n" KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & " "Jan \"Yenya\" Kasprzak.\n"; @@ -1420,3 +1420,5 @@ module_init(sync_ppp_init); module_exit(sync_ppp_cleanup); MODULE_PARM(debug,"1i"); +MODULE_LICENSE("GPL"); + 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 Thu Sep 13 16:04:43 2001 @@ -17,6 +17,7 @@ * module. *****************************************************************************/ +#include #include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ @@ -375,13 +376,13 @@ /* For Primary Port 0 */ card->wandev.mtu = (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? - min(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) : + min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) : CHDLC_DFLT_DATA_LEN; } else if(port_num == WANOPT_SEC) { /* For Secondary Port 1 */ card->wandev.mtu = (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? - min(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) : + min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) : CHDLC_DFLT_DATA_LEN; } @@ -2472,5 +2473,7 @@ } } + +MODULE_LICENSE("GPL"); /****** End ****************************************************************/ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/x25_asy.c linux/drivers/net/wan/x25_asy.c --- v2.4.9/linux/drivers/net/wan/x25_asy.c Wed Apr 18 14:40:07 2001 +++ linux/drivers/net/wan/x25_asy.c Thu Sep 13 16:04:43 2001 @@ -42,7 +42,9 @@ static x25_asy_ctrl_t **x25_asy_ctrls = NULL; int x25_asy_maxdev = SL_NRUNIT; /* Can be overridden with insmod! */ + MODULE_PARM(x25_asy_maxdev, "i"); +MODULE_LICENSE("GPL"); static struct tty_ldisc x25_ldisc; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wan/z85230.c linux/drivers/net/wan/z85230.c --- v2.4.9/linux/drivers/net/wan/z85230.c Tue Mar 6 19:44:37 2001 +++ linux/drivers/net/wan/z85230.c Sun Sep 9 10:50:48 2001 @@ -1739,7 +1739,7 @@ /* * Module support */ -static const char banner[] __initdata = KERN_INFO "Generic Z85C30/Z85230 interface driver v0.02\n"; +static char banner[] __initdata = KERN_INFO "Generic Z85C30/Z85230 interface driver v0.02\n"; static int __init z85230_init_driver(void) { @@ -1752,3 +1752,7 @@ { } module_exit(z85230_cleanup_driver); + +MODULE_AUTHOR("Red Hat Inc."); +MODULE_DESCRIPTION("Z85x30 synchronous driver core"); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c --- v2.4.9/linux/drivers/net/winbond-840.c Wed Jul 25 17:10:22 2001 +++ linux/drivers/net/winbond-840.c Fri Sep 14 14:40:00 2001 @@ -952,7 +952,7 @@ } else { i |= 0xE000; } -#elif defined(__powerpc__) || defined(__i386__) || defined(__alpha) || defined(__ia64__) +#elif defined(__powerpc__) || defined(__i386__) || defined(__alpha__) || defined(__ia64__) || defined(__x86_64__) i |= 0xE000; #elif defined(__sparc__) i |= 0x4800; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wireless/airo.c linux/drivers/net/wireless/airo.c --- v2.4.9/linux/drivers/net/wireless/airo.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wireless/airo.c Mon Sep 17 22:52:35 2001 @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef CONFIG_PCI static struct pci_device_id card_ids[] = __devinitdata { @@ -69,11 +70,12 @@ /* Include Wireless Extension definition and check version - Jean II */ #include +#define WIRELESS_SPY // enable iwspy support #if WIRELESS_EXT < 9 #warning "Wireless extension v9 or newer required - please upgrade your kernel" #undef WIRELESS_EXT +#undef WIRELESS_SPY #endif -#define WIRELESS_SPY // enable iwspy support #define CISCO_EXT // enable Cisco extensions #ifdef CISCO_EXT @@ -226,6 +228,7 @@ MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \ cards. Direct support for ISA/PCI cards and support \ for PCMCIA when used with airo_cs."); +MODULE_LICENSE("Dual BSD/GPL"); MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340"); MODULE_PARM(io,"1-4i"); MODULE_PARM(irq,"1-4i"); @@ -273,6 +276,7 @@ #define NOP 0x0010 #define MAC_ENABLE 0x0001 #define MAC_DISABLE 0x0002 +#define CMD_LOSE_SYNC 0x0003 /* Not sure what this does... */ #define CMD_ACCESS 0x0021 #define CMD_ALLOCATETX 0x000a #define CMD_TRANSMIT 0x000b @@ -280,6 +284,7 @@ #define CMD_SETMODE 0x0009 #define CMD_ENABLEAUX 0x0111 #define CMD_SOFTRESET 0x0004 +#define CMD_LISTBSS 0x0103 /* Registers */ #define COMMAND 0x00 @@ -351,6 +356,22 @@ #define RID_STATS 0xFF68 #define RID_STATSDELTA 0xFF69 #define RID_STATSDELTACLEAR 0xFF6A +#define RID_BSSLISTFIRST 0xFF72 +#define RID_BSSLISTNEXT 0xFF73 + +typedef struct { + u16 cmd; + u16 parm0; + u16 parm1; + u16 parm2; +} Cmd; + +typedef struct { + u16 status; + u16 rsp0; + u16 rsp1; + u16 rsp2; +} Resp; /* * Rids and endian-ness: The Rids will always be in cpu endian, since @@ -358,6 +379,9 @@ * so all rid access should use the read/writeXXXRid routines. */ +/* This is redundant for x86 archs, but it seems necessary for ARM */ +#pragma pack(1) + /* This structure came from an email sent to me from an engineer at aironet for inclusion into this driver */ typedef struct { @@ -388,20 +412,6 @@ } ModulationRid; typedef struct { - u16 cmd; - u16 parm0; - u16 parm1; - u16 parm2; -} Cmd; - -typedef struct { - u16 status; - u16 rsp0; - u16 rsp1; - u16 rsp2; -} Resp; - -typedef struct { u16 len; /* sizeof(ConfigRid) */ u16 opmode; /* operating mode */ #define MODE_STA_IBSS 0 @@ -496,7 +506,10 @@ u16 rssiThreshold; #define RSSI_DEFAULT 0 u16 modulation; - u16 shortPreamble; +#define PREAMBLE_AUTO 0 +#define PREAMBLE_LONG 1 +#define PREAMBLE_SHORT 2 + u16 preamble; u16 homeProduct; u16 radioSpecific; /*---------- Aironet Extensions ----------*/ @@ -559,6 +572,7 @@ typedef struct { u16 len; char oui[3]; + char zero; u16 prodNum; char manName[32]; char prodName[16]; @@ -583,6 +597,38 @@ u16 requiredHard; } CapabilityRid; +typedef struct { + u16 len; + u16 index; /* First is 0 and 0xffff means end of list */ +#define RADIO_FH 1 /* Frequency hopping radio type */ +#define RADIO_DS 2 /* Direct sequence radio type */ +#define RADIO_TMA 4 /* Proprietary radio used in old cards (2500) */ + u16 radioType; + u8 bssid[6]; /* Mac address of the BSS */ + u8 zero; + u8 ssidLen; + u8 ssid[32]; + u16 rssi; +#define CAP_ESS (1<<0) +#define CAP_IBSS (1<<1) +#define CAP_PRIVACY (1<<4) +#define CAP_SHORTHDR (1<<5) + u16 cap; + u16 beaconInterval; + u8 rates[8]; /* Same as rates for config rid */ + struct { /* For frequency hopping only */ + u16 dwell; + u8 hopSet; + u8 hopPattern; + u8 hopIndex; + u8 fill; + } fh; + u16 dsChannel; + u16 atimWindow; +} BSSListRid; + +#pragma pack() + #define TXCTL_TXOK (1<<1) /* report if tx is ok */ #define TXCTL_TXEX (1<<2) /* report if tx fails */ #define TXCTL_802_3 (0<<3) /* 802.3 packet */ @@ -661,7 +707,7 @@ } wep_key_t; #endif /* WIRELESS_EXT */ -static const char version[] = "airo.c 0.2 (Ben Reed & Javier Achirica)"; +static const char version[] = "airo.c 0.3 (Ben Reed & Javier Achirica)"; struct airo_info; @@ -749,6 +795,35 @@ static int takedown_proc_entry( struct net_device *dev, struct airo_info *apriv ); +static int readBSSListRid(struct airo_info *ai, int first, + BSSListRid *list) { + int rc; + Cmd cmd; + Resp rsp; + + if (first == 1) { + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd=CMD_LISTBSS; + issuecommand(ai, &cmd, &rsp); + /* Let the command take effect */ + set_current_state (TASK_INTERRUPTIBLE); + schedule_timeout (3*HZ); + } + rc = PC4500_readrid(ai, + first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT, + list, sizeof(*list)); + + list->len = le16_to_cpu(list->len); + list->index = le16_to_cpu(list->index); + list->radioType = le16_to_cpu(list->radioType); + list->cap = le16_to_cpu(list->cap); + list->beaconInterval = le16_to_cpu(list->beaconInterval); + list->fh.dwell = le16_to_cpu(list->fh.dwell); + list->dsChannel = le16_to_cpu(list->dsChannel); + list->atimWindow = le16_to_cpu(list->atimWindow); + return rc; +} + static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp) { int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM, wkr, sizeof(*wkr)); @@ -918,7 +993,6 @@ len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* check min length*/ buffer = skb->data; - status = transmit_802_3_packet( priv, fids[i], skb->data, len ); @@ -1167,7 +1241,6 @@ struct airo_info *apriv = (struct airo_info *)dev->priv; u16 savedInterrupts; - if (!netif_device_present(dev)) return; @@ -1228,7 +1301,7 @@ /* Check to see if there is something to receive */ if ( status & EV_RX ) { struct sk_buff *skb = NULL; - int flags; + long flags; u16 fc, len, hdrlen = 0; struct { u16 status, len; @@ -1362,6 +1435,16 @@ if(index!=-1) apriv->stats.tx_bytes += len; } else { + if (bap_setup(apriv, fid, 0x0004, BAP1) == SUCCESS) { + u16 status; + bap_read(apriv, &status, 2, BAP1); + if (le16_to_cpu(status) & 2) + apriv->stats.tx_aborted_errors++; + if (le16_to_cpu(status) & 4) + apriv->stats.tx_heartbeat_errors++; + if (le16_to_cpu(status) & 0x10) + apriv->stats.tx_carrier_errors++; + } apriv->stats.tx_errors++; } } @@ -1559,7 +1642,7 @@ // Im really paranoid about letting it run forever! int max_tries = 600000; int rc = SUCCESS; - int flags; + long flags; spin_lock_irqsave(&ai->cmd_lock, flags); OUT4500(ai, PARAM0, pCmd->parm0); @@ -1664,7 +1747,7 @@ u16 next; int words; int i; - int flags; + long flags; spin_lock_irqsave(&ai->aux_lock, flags); page = IN4500(ai, SWS0+whichbap); @@ -1738,7 +1821,7 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len) { u16 status; - int flags; + long flags; int rc = SUCCESS; spin_lock_irqsave(&ai->bap1_lock, flags); @@ -1753,7 +1836,7 @@ // read the rid length field bap_read(ai, pBuf, 2, BAP1); // length for remaining part of rid - len = min(unsigned int, len, le16_to_cpu(*(u16*)pBuf)) - 2; + len = min_t(unsigned int, len, le16_to_cpu(*(u16*)pBuf)) - 2; if ( len <= 2 ) { printk( KERN_ERR @@ -1780,7 +1863,7 @@ const void *pBuf, int len) { u16 status; - int flags; + long flags; int rc = SUCCESS; spin_lock_irqsave(&ai->bap1_lock, flags); @@ -1810,7 +1893,7 @@ Resp rsp; u16 txFid; u16 txControl; - int flags; + long flags; cmd.cmd = CMD_ALLOCATETX; cmd.parm0 = lenPayload; @@ -1879,12 +1962,6 @@ * like! Feel free to clean it up! */ -/* - * Unfortunately sometime between 2.0 and 2.2 the proc interface changed... - * Unfortunately I dont know when it was... - * Im guessing it is sometime around 0x20155... Anybody know? - */ - static ssize_t proc_read( struct file *file, char *buffer, size_t len, @@ -1901,6 +1978,7 @@ static int proc_status_open( struct inode *inode, struct file *file ); static int proc_SSID_open( struct inode *inode, struct file *file ); static int proc_APList_open( struct inode *inode, struct file *file ); +static int proc_BSSList_open( struct inode *inode, struct file *file ); static int proc_config_open( struct inode *inode, struct file *file ); static int proc_wepkey_open( struct inode *inode, struct file *file ); @@ -1929,6 +2007,13 @@ release: proc_close }; +static struct file_operations proc_BSSList_ops = { + read: proc_read, + write: proc_write, + open: proc_BSSList_open, + release: proc_close +}; + static struct file_operations proc_APList_ops = { read: proc_read, write: proc_write, @@ -1962,6 +2047,10 @@ void (*on_close) (struct inode *, struct file *); }; +#ifndef SETPROC_OPS +#define SETPROC_OPS(entry, ops) (entry)->proc_fops = &(ops) +#endif + static int setup_proc_entry( struct net_device *dev, struct airo_info *apriv ) { struct proc_dir_entry *entry; @@ -1979,11 +2068,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; -/* This is what was needed right up to the last few versions - of 2.3: - entry->ops = &proc_inode_statsdelta_ops; -*/ - entry->proc_fops = &proc_statsdelta_ops; + SETPROC_OPS(entry, proc_statsdelta_ops); /* Setup the Stats */ entry = create_proc_entry("Stats", @@ -1992,7 +2077,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; - entry->proc_fops = &proc_stats_ops; + SETPROC_OPS(entry, proc_stats_ops); /* Setup the Status */ entry = create_proc_entry("Status", @@ -2001,7 +2086,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; - entry->proc_fops = &proc_status_ops; + SETPROC_OPS(entry, proc_status_ops); /* Setup the Config */ entry = create_proc_entry("Config", @@ -2010,7 +2095,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; - entry->proc_fops = &proc_config_ops; + SETPROC_OPS(entry, proc_config_ops); /* Setup the SSID */ entry = create_proc_entry("SSID", @@ -2019,7 +2104,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; - entry->proc_fops = &proc_SSID_ops; + SETPROC_OPS(entry, proc_SSID_ops); /* Setup the APList */ entry = create_proc_entry("APList", @@ -2028,7 +2113,16 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; - entry->proc_fops = &proc_APList_ops; + SETPROC_OPS(entry, proc_APList_ops); + + /* Setup the BSSList */ + entry = create_proc_entry("BSSList", + S_IFREG | proc_perm, + apriv->proc_entry); + entry->uid = proc_uid; + entry->gid = proc_gid; + entry->data = dev; + SETPROC_OPS(entry, proc_BSSList_ops); /* Setup the WepKey */ entry = create_proc_entry("WepKey", @@ -2037,7 +2131,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; - entry->proc_fops = &proc_wepkey_ops; + SETPROC_OPS(entry, proc_wepkey_ops); return 0; } @@ -2051,6 +2145,7 @@ remove_proc_entry("Config",apriv->proc_entry); remove_proc_entry("SSID",apriv->proc_entry); remove_proc_entry("APList",apriv->proc_entry); + remove_proc_entry("BSSList",apriv->proc_entry); remove_proc_entry("WepKey",apriv->proc_entry); remove_proc_entry(dev->name,airo_entry); return 0; @@ -2124,6 +2219,7 @@ struct airo_info *apriv = (struct airo_info *)dev->priv; CapabilityRid cap_rid; StatusRid status_rid; + int i; MOD_INC_USE_COUNT; @@ -2141,7 +2237,17 @@ readStatusRid(apriv, &status_rid); readCapabilityRid(apriv, &cap_rid); - sprintf( data->rbuffer, "Mode: %x\n" + i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n", + status_rid.mode & 1 ? "CFG ": "", + status_rid.mode & 2 ? "ACT ": "", + status_rid.mode & 0x10 ? "SYN ": "", + status_rid.mode & 0x20 ? "LNK ": "", + status_rid.mode & 0x40 ? "LEAP ": "", + status_rid.mode & 0x80 ? "PRIV ": "", + status_rid.mode & 0x100 ? "KEY ": "", + status_rid.mode & 0x200 ? "WEP ": "", + status_rid.mode & 0x8000 ? "ERR ": ""); + sprintf( data->rbuffer+i, "Mode: %x\n" "Signal Strength: %d\n" "Signal Quality: %d\n" "SSID: %-.*s\n" @@ -2425,6 +2531,14 @@ default: printk( KERN_WARNING "airo: Unknown modulation\n" ); } + } else if (!strncmp(line, "Preamble: ", 10)) { + line += 10; + switch(*line) { + case 'a': config.preamble=PREAMBLE_AUTO; break; + case 'l': config.preamble=PREAMBLE_LONG; break; + case 's': config.preamble=PREAMBLE_SHORT; break; + default: printk(KERN_WARNING "airo: Unknown preamble\n"); + } } else { printk( KERN_WARNING "Couldn't figure out %s\n", line ); } @@ -2516,7 +2630,8 @@ "RXDiversity: %s\n" "FragThreshold: %d\n" "WEP: %s\n" - "Modulation: %s\n", + "Modulation: %s\n" + "Preamble: %s\n", (int)config.longRetryLimit, (int)config.shortRetryLimit, (int)config.rtsThres, @@ -2531,7 +2646,10 @@ config.authType == AUTH_SHAREDKEY ? "shared" : "open", config.modulation == 0 ? "default" : config.modulation == MOD_CCK ? "cck" : - config.modulation == MOD_MOK ? "mok" : "error" + config.modulation == MOD_MOK ? "mok" : "error", + config.preamble == PREAMBLE_AUTO ? "auto" : + config.preamble == PREAMBLE_LONG ? "long" : + config.preamble == PREAMBLE_SHORT ? "short" : "error" ); data->readlen = strlen( data->rbuffer ); return 0; @@ -2862,6 +2980,76 @@ return 0; } +static int proc_BSSList_open( struct inode *inode, struct file *file ) { + struct proc_data *data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + char *ptr; + BSSListRid BSSList_rid; + int rc; + /* If doLoseSync is not 1, we won't do a Lose Sync */ + int doLoseSync = -1; + + MOD_INC_USE_COUNT; + + dp = (struct proc_dir_entry *) inode->u.generic_ip; + + if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(file->private_data, 0, sizeof(struct proc_data)); + data = (struct proc_data *)file->private_data; + if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) { + kfree (file->private_data); + return -ENOMEM; + } + data->writelen = 0; + data->maxwritelen = 0; + data->wbuffer = 0; + data->on_close = 0; + + if (file->f_mode & FMODE_WRITE) { + if (!(file->f_mode & FMODE_READ)) { + Cmd cmd; + Resp rsp; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd=CMD_LISTBSS; + issuecommand(ai, &cmd, &rsp); + data->readlen = 0; + return 0; + } + doLoseSync = 1; + } + ptr = data->rbuffer; + /* There is a race condition here if there are concurrent opens. + Since it is a rare condition, we'll just live with it, otherwise + we have to add a spin lock... */ + rc = readBSSListRid(ai, doLoseSync, &BSSList_rid); + while(rc == 0 && BSSList_rid.index != 0xffff) { + ptr += sprintf(ptr, "%02x:%02x:%02x:%02x:%02x:%02x %*s rssi = %d", + (int)BSSList_rid.bssid[0], + (int)BSSList_rid.bssid[1], + (int)BSSList_rid.bssid[2], + (int)BSSList_rid.bssid[3], + (int)BSSList_rid.bssid[4], + (int)BSSList_rid.bssid[5], + (int)BSSList_rid.ssidLen, + BSSList_rid.ssid, + (int)BSSList_rid.rssi); + ptr += sprintf(ptr, " channel = %d %s %s %s %s\n", + (int)BSSList_rid.dsChannel, + BSSList_rid.cap & CAP_ESS ? "ESS" : "", + BSSList_rid.cap & CAP_IBSS ? "adhoc" : "", + BSSList_rid.cap & CAP_PRIVACY ? "wep" : "", + BSSList_rid.cap & CAP_SHORTHDR ? "shorthdr" : ""); + rc = readBSSListRid(ai, 0, &BSSList_rid); + } + *ptr = '\0'; + data->readlen = strlen( data->rbuffer ); + return 0; +} + static int proc_close( struct inode *inode, struct file *file ) { struct proc_data *data = (struct proc_data *)file->private_data; @@ -2971,7 +3159,6 @@ { stop_airo_card(pdev->driver_data, 1); } - #endif static int __init airo_init_module( void ) @@ -3041,14 +3228,13 @@ */ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - int rc = 0; + int i, rc = 0; #ifdef WIRELESS_EXT struct airo_info *local = (struct airo_info*) dev->priv; struct iwreq *wrq = (struct iwreq *) rq; ConfigRid config; /* Configuration info */ CapabilityRid cap_rid; /* Card capability info */ StatusRid status_rid; /* Card status info */ - int i; #ifdef CISCO_EXT if (cmd != SIOCGIWPRIV && cmd != AIROIOCTL && cmd != AIROIDIFC) @@ -3557,31 +3743,50 @@ #endif /* WIRELESS_EXT > 9 */ #if WIRELESS_EXT > 10 - case SIOCGIWRETRY: - wrq->u.retry.disabled = 0; - if ((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) - wrq->u.retry.value = (int)config.txLifetime * 1024; - else { - wrq->u.retry.value = (int)config.shortRetryLimit; - wrq->u.retry.flags = IW_RETRY_LIMIT; - } - break; - - case SIOCSIWRETRY: - if (wrq->u.retry.disabled) { - config.shortRetryLimit = 0; - config.longRetryLimit = 0; - config.txLifetime = 0; - local->need_commit = 1; + case SIOCSIWRETRY: + if(wrq->u.retry.disabled) { + rc = -EINVAL; break; } - if ((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - config.txLifetime = (wrq->u.retry.value + 500) / 1024; + local->need_commit = 0; + if(wrq->u.retry.flags & IW_RETRY_LIMIT) { + if(wrq->u.retry.flags & IW_RETRY_MAX) + config.longRetryLimit = wrq->u.retry.value; + else if (wrq->u.retry.flags & IW_RETRY_MIN) + config.shortRetryLimit = wrq->u.retry.value; + else { + /* No modifier : set both */ + config.longRetryLimit = wrq->u.retry.value; + config.shortRetryLimit = wrq->u.retry.value; + } local->need_commit = 1; - } else if ((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIMIT) { - config.shortRetryLimit = config.longRetryLimit = wrq->u.retry.value; + } + if(wrq->u.retry.flags & IW_RETRY_LIFETIME) { + config.txLifetime = wrq->u.retry.value / 1024; local->need_commit = 1; } + if(local->need_commit == 0) { + rc = -EINVAL; + } + break; + + case SIOCGIWRETRY: + wrq->u.retry.disabled = 0; /* Can't be disabled */ + + /* Note : by default, display the min retry number */ + if((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + wrq->u.retry.flags = IW_RETRY_LIFETIME; + wrq->u.retry.value = (int)config.txLifetime * 1024; + } else if((wrq->u.retry.flags & IW_RETRY_MAX)) { + wrq->u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + wrq->u.retry.value = (int)config.longRetryLimit; + } else { + wrq->u.retry.flags = IW_RETRY_LIMIT; + wrq->u.retry.value = (int)config.shortRetryLimit; + if((int)config.shortRetryLimit != (int)config.longRetryLimit) + wrq->u.retry.flags |= IW_RETRY_MIN; + } + break; #endif /* WIRELESS_EXT > 10 */ @@ -3593,8 +3798,7 @@ int k; wrq->u.data.length = sizeof(range); - /* Should adapt depending on max rate */ - range.throughput = 1.6 * 1024 * 1024; + memset(&range, 0, sizeof(range)); range.min_nwid = 0x0000; range.max_nwid = 0x0000; range.num_channels = 14; @@ -3621,6 +3825,14 @@ } range.num_bitrates = i; + /* Set an indication of the max TCP throughput + * in bit/s that we can expect using this interface. + * May be use for QoS stuff... Jean II */ + if(i > 2) + range.throughput = 5 * 1000 * 1000; + else + range.throughput = 1.5 * 1000 * 1000; + range.min_rts = 0; range.max_rts = 2312; range.min_frag = 256; @@ -3753,15 +3965,53 @@ case SIOCGIWAPLIST: if (wrq->u.data.pointer) { - int i; - struct sockaddr s[4]; - - for (i = 0; i < 4; i++) { - memcpy(s[i].sa_data, status_rid.bssid[i], 6); + int i, rc; + struct sockaddr s[IW_MAX_AP]; + struct iw_quality qual[IW_MAX_AP]; + BSSListRid BSSList; + int loseSync = capable(CAP_NET_ADMIN) ? 1: -1; + for (i = 0; i < IW_MAX_AP; i++) { + if (readBSSListRid(local, loseSync, &BSSList)) + break; + loseSync = 0; + memcpy(s[i].sa_data, BSSList.bssid, 6); s[i].sa_family = ARPHRD_ETHER; + qual[i].level = BSSList.rssi; + qual[i].qual = qual[i].noise = 0; + qual[i].updated = 2; + if (BSSList.index == 0xffff) break; + } + if (!i) { + for (i = 0; + i < min(IW_MAX_AP, 4) && + (status_rid.bssid[i][0] + & status_rid.bssid[i][1] + & status_rid.bssid[i][2] + & status_rid.bssid[i][3] + & status_rid.bssid[i][4] + & status_rid.bssid[i][5])!=-1 && + (status_rid.bssid[i][0] + | status_rid.bssid[i][1] + | status_rid.bssid[i][2] + | status_rid.bssid[i][3] + | status_rid.bssid[i][4] + | status_rid.bssid[i][5]); + i++) { + memcpy(s[i].sa_data, + status_rid.bssid[i], 6); + s[i].sa_family = ARPHRD_ETHER; + } + } else { + wrq->u.data.flags = 1; /* Should be define'd */ + if (copy_to_user(wrq->u.data.pointer + + sizeof(struct sockaddr)*i, + &qual, + sizeof(struct iw_quality)*i)) + rc = -EFAULT; } - wrq->u.data.length = 4; - if (copy_to_user(wrq->u.data.pointer, &s, sizeof(s))) + wrq->u.data.length = i; + if (copy_to_user(wrq->u.data.pointer, &s, + sizeof(struct sockaddr)*i)) rc = -EFAULT; } break; @@ -3997,7 +4247,7 @@ */ if (copy_to_user(comp->data, iobuf, - min(unsigned int, comp->len, sizeof(iobuf)))) + min_t(unsigned int, comp->len, sizeof(iobuf)))) return -EFAULT; return 0; } @@ -4057,7 +4307,7 @@ PC4500_readrid(dev->priv,ridcode,iobuf,sizeof(iobuf)); if (copy_to_user(comp->data, iobuf, - min(unsigned int, comp->len, sizeof(iobuf)))) + min_t(unsigned int, comp->len, sizeof(iobuf)))) return -EFAULT; return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/net/wireless/airo_cs.c linux/drivers/net/wireless/airo_cs.c --- v2.4.9/linux/drivers/net/wireless/airo_cs.c Tue Jul 3 17:08:20 2001 +++ linux/drivers/net/wireless/airo_cs.c Thu Sep 13 16:04:43 2001 @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); -static char *version = "$Revision: 1.1.18.1 $"; +static char *version = "$Revision: 1.2 $"; #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); #else #define DEBUG(n, args...) @@ -75,6 +75,7 @@ MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \ cards. This is the module that links the PCMCIA card \ with the airo module."); +MODULE_LICENSE("Dual BSD/GPL"); MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); MODULE_PARM(irq_mask, "i"); MODULE_PARM(irq_list, "1-4i"); 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 Thu Sep 13 16:04:43 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 @@ -12,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -25,25 +29,37 @@ #include #include #include +#include +#include #include #include +#include #include "hermes.h" #include "orinoco.h" -static const char version[] __initdata = "airport.c 0.06f (Benjamin Herrenschmidt )"; +static char version[] __initdata = "airport.c 0.06f (Benjamin Herrenschmidt )"; MODULE_AUTHOR("Benjamin Herrenschmidt "); MODULE_DESCRIPTION("Driver for the Apple Airport wireless card."); +MODULE_LICENSE("Dual MPL/GPL"); typedef struct dldwd_card { 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 +85,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 +104,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 +126,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 +232,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 +263,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 +287,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 +336,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/net/wireless/hermes.c linux/drivers/net/wireless/hermes.c --- v2.4.9/linux/drivers/net/wireless/hermes.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wireless/hermes.c Mon Sep 17 22:52:35 2001 @@ -30,9 +30,10 @@ #include "hermes.h" -static const char version[] __initdata = "hermes.c: 1 Aug 2001 David Gibson "; +static char version[] __initdata = "hermes.c: 1 Aug 2001 David Gibson "; MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller"); MODULE_AUTHOR("David Gibson "); +MODULE_LICENSE("GPL"); /* These are maximum timeouts. Most often, card wil react much faster */ #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */ @@ -40,7 +41,6 @@ #define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */ #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */ #define BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */ -#define BAP_ERROR_RETRY (10) /* How many times to retry a BAP seek when there is an error */ #define MAX(a, b) ( (a) > (b) ? (a) : (b) ) #define MIN(a, b) ( (a) < (b) ? (a) : (b) ) @@ -66,12 +66,6 @@ #endif /* ! HERMES_DEBUG */ /* - * Prototypes - */ - -static int hermes_issue_cmd(hermes_t *hw, uint16_t cmd, uint16_t param0); - -/* * Internal functions */ @@ -303,7 +297,6 @@ int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0; int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0; int k; - int l = BAP_ERROR_RETRY; uint16_t reg; /* Paranoia.. */ @@ -317,7 +310,6 @@ return -EBUSY; /* Now we actually set up the transfer */ - retry: hermes_write_reg(hw, sreg, id); hermes_write_reg(hw, oreg, offset); @@ -331,19 +323,15 @@ } if (reg & HERMES_OFFSET_BUSY) { - DEBUG(0,"hermes_bap_seek: returning ETIMEDOUT...\n"); + DEBUG(1,"hermes_bap_seek: timeout\n"); return -ETIMEDOUT; } - /* For some reason, seeking the BAP seems to randomly fail somewhere - (firmware bug?). We retry a few times before giving up. */ if (reg & HERMES_OFFSET_ERR) { - if (l--) { - udelay(1); - goto retry; - } else - return -EIO; + DEBUG(1,"hermes_bap_seek: BAP error\n"); + return -EIO; } + return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/wireless/hermes.h linux/drivers/net/wireless/hermes.h --- v2.4.9/linux/drivers/net/wireless/hermes.h Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wireless/hermes.h Mon Sep 17 22:52:35 2001 @@ -210,14 +210,16 @@ * Frame structures and constants */ +#define __PACKED__ __attribute__ ((packed)) + typedef struct hermes_frame_desc { /* Hermes - i.e. little-endian byte-order */ - uint16_t status; /* 0x0 */ - uint16_t res1, res2; /* 0x2, 0x4 */ - uint16_t q_info; /* 0x6 */ - uint16_t res3, res4; /* 0x8, 0xA */ - uint16_t tx_ctl; /* 0xC */ -} __attribute__ ((packed)) hermes_frame_desc_t; + uint16_t status __PACKED__; + uint16_t res1, res2 __PACKED__; + uint16_t q_info __PACKED__; + uint16_t res3, res4 __PACKED__; + uint16_t tx_ctl __PACKED__; +} hermes_frame_desc_t; #define HERMES_RXSTAT_ERR (0x0003) #define HERMES_RXSTAT_MACPORT (0x0700) @@ -246,21 +248,12 @@ uint16_t status, resp0, resp1, resp2; } hermes_response_t; -/* Firmware information structure */ -typedef struct hermes_identity { - uint16_t id, vendor, major, minor; -} __attribute__ ((packed)) hermes_identity_t; - /* "ID" structure - used for ESSID and station nickname */ typedef struct hermes_id { uint16_t len; uint16_t val[16]; } __attribute__ ((packed)) hermes_id_t; -typedef struct hermes_commsqual { - uint16_t qual, signal, noise; -} __attribute__ ((packed)) hermes_commsqual_t; - typedef struct hermes_multicast { uint8_t addr[HERMES_MAX_MULTICAST][ETH_ALEN]; } __attribute__ ((packed)) hermes_multicast_t; @@ -349,37 +342,6 @@ { uint16_t rec = cpu_to_le16(word); return HERMES_WRITE_RECORD(hw, bap, rid, &rec); -} - -static inline int hermes_read_staidentity(hermes_t *hw, int bap, hermes_identity_t *buf) -{ - int err; - - err = HERMES_READ_RECORD(hw, bap, HERMES_RID_STAIDENTITY, buf); - if (err) - return err; - - le16_to_cpus(&buf->id); - le16_to_cpus(&buf->vendor); - le16_to_cpus(&buf->major); - le16_to_cpus(&buf->minor); - - return 0; -} - -static inline int hermes_read_commsqual(hermes_t *hw, int bap, hermes_commsqual_t *buf) -{ - int err; - - err = HERMES_READ_RECORD(hw, bap, HERMES_RID_COMMSQUALITY, buf); - if (err) - return err; - - le16_to_cpus(&buf->qual); - le16_to_cpus(&buf->signal); - le16_to_cpus(&buf->noise); - - return 0; } #else /* ! __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/drivers/net/wireless/orinoco.c linux/drivers/net/wireless/orinoco.c --- v2.4.9/linux/drivers/net/wireless/orinoco.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wireless/orinoco.c Mon Sep 17 22:52:35 2001 @@ -1,4 +1,4 @@ -/* orinoco.c 0.06f - (formerly known as dldwd_cs.c and orinoco_cs.c) +/* orinoco.c 0.07 - (formerly known as dldwd_cs.c and orinoco_cs.c) * * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ @@ -184,6 +184,13 @@ * 00:00:00. We really need a better way of handling this, but the module flag * is better than nothing for now. * + * v0.06f -> v0.07 - 20/8/2001 - David Gibson + * o Removed BAP error retries from hermes_bap_seek(). For Tx we now + * let the upper layers handle the retry, we retry explicitly in the + * Rx path, but don't make as much noise about it. + * o Firmware detection cleanups. + * + * * TODO - Jean II * o inline functions (lot's of candidate, need to reorder code) * o Test PrismII/Symbol cards & firmware versions @@ -195,7 +202,7 @@ #include #include #include -#include +#include #include #include #include @@ -220,9 +227,10 @@ #include "hermes.h" #include "orinoco.h" -static const char version[] __initdata = "orinoco.c 0.06f (David Gibson and others)"; +static char version[] __initdata = "orinoco.c 0.07 (David Gibson and others)"; MODULE_AUTHOR("David Gibson "); MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards"); +MODULE_LICENSE("Dual MPL/GPL"); /* Level of debugging. Used in the macros in orinoco.h */ #ifdef ORINOCO_DEBUG @@ -276,20 +284,22 @@ #define DLDWD_FTYPE_CTL 0x0004 #define DLDWD_FTYPE_DATA 0x0008 +#define __PACKED__ __attribute__ ((packed)) + struct p8022_hdr { - uint8_t dsap; - uint8_t ssap; - uint8_t ctrl; - uint8_t oui[3]; -} __attribute__ ((packed)); + uint8_t dsap __PACKED__; + uint8_t ssap __PACKED__; + uint8_t ctrl __PACKED__; + uint8_t oui[3] __PACKED__; +}; struct dldwd_frame_hdr { - hermes_frame_desc_t desc; - struct p80211_hdr p80211; - struct ethhdr p8023; - struct p8022_hdr p8022; - uint16_t ethertype; -} __attribute__ ((packed)); + hermes_frame_desc_t desc __PACKED__; + struct p80211_hdr p80211 __PACKED__; + struct ethhdr p8023 __PACKED__; + struct p8022_hdr p8022 __PACKED__; + uint16_t ethertype __PACKED__; +}; #define P8023_OFFSET (sizeof(hermes_frame_desc_t) + \ sizeof(struct p80211_hdr)) @@ -303,6 +313,14 @@ 0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00} }; +/* How many times to retry if we get an EIO reading the BAP in the Rx path */ +#define RX_EIO_RETRY 10 + +typedef struct dldwd_commsqual { + uint16_t qual, signal, noise; +} __PACKED__ dldwd_commsqual_t; + + /* * Function prototypes */ @@ -419,11 +437,6 @@ priv->port_type = 3; priv->allow_ibss = 0; } else { - /* Symbol is different here */ - if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) - priv->port_type = 4; - else - priv->port_type = 1; priv->port_type = priv->ibss_port; priv->allow_ibss = 1; } @@ -673,7 +686,7 @@ return err; break; - case FIRMWARE_TYPE_PRISM2: /* Prism II style WEP */ + case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */ case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ master_wep_flag = 0; /* Off */ if (priv->wep_on) { @@ -703,7 +716,7 @@ if (err) return err; - /* Authentication is where Prism2 and Symbol + /* Authentication is where Intersil and Symbol * firmware differ... */ if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) { /* Symbol cards : set the authentication : @@ -877,7 +890,7 @@ return 0; } -#ifndef PCMCIA_DEBUG +#ifndef ORINOCO_DEBUG static inline void show_rx_frame(struct dldwd_frame_hdr *frame) {} #else static void show_rx_frame(struct dldwd_frame_hdr *frame) @@ -1052,6 +1065,7 @@ struct net_device_stats *stats = &priv->stats; struct iw_statistics *wstats = &priv->wstats; struct sk_buff *skb = NULL; + int l = RX_EIO_RETRY; uint16_t rxfid, status; int length, data_len, data_off; char *p; @@ -1066,13 +1080,20 @@ necessary, since we ignore most of it, but it's conceptually simpler. We can tune this later if necessary. */ - err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, 0); + do { + err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), + rxfid, 0); + } while ( (err == -EIO) && (--l) ); if (err) { - printk(KERN_ERR "%s: error %d reading frame header. " - "Frame dropped.\n", dev->name, err); + if (err == -EIO) + DEBUG(1, "%s: EIO reading frame header.\n", dev->name); + else + printk(KERN_ERR "%s: error %d reading frame header. " + "Frame dropped.\n", dev->name, err); stats->rx_errors++; goto drop; } + DEBUG(2, "%s: BAP read suceeded: l=%d\n", dev->name, l); status = le16_to_cpu(hdr.desc.status); @@ -1138,8 +1159,7 @@ (!memcmp(&hdr.p8022, &encaps_hdr, 3))) { /* These indicate a SNAP within 802.2 LLC within 802.11 frame which we'll need to de-encapsulate to - the original EthernetII frame. - IEEE and ISO OSI have a lot to answer for. */ + the original EthernetII frame. */ /* Remove SNAP header, reconstruct EthernetII frame */ data_len = length - ENCAPS_OVERHEAD; @@ -1161,13 +1181,20 @@ } p = skb_put(skb, data_len); - if (hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len), - rxfid, data_off) != 0) { - printk(KERN_WARNING "%s: Error reading packet data\n", - dev->name); + do { + err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len), + rxfid, data_off); + } while ( (err == -EIO) && (--l) ); + if (err) { + if (err == -EIO) + DEBUG(1, "%s: EIO reading frame header.\n", dev->name); + else + printk(KERN_ERR "%s: error %d reading frame header. " + "Frame dropped.\n", dev->name, err); stats->rx_errors++; goto drop; } + DEBUG(2, "%s: BAP read suceeded: l=%d\n", dev->name, l); dev->last_rx = jiffies; skb->dev = dev; @@ -1231,28 +1258,38 @@ dldwd_priv_t *priv = dev->priv; hermes_t *hw = &priv->hw; int err; + struct sta_id { + uint16_t id, vendor, major, minor; + } __PACKED__ sta_id; uint32_t firmver; - char *vendor_str; /* Get the firmware version */ - err = hermes_read_staidentity(hw, USER_BAP, &priv->firmware_info); + err = HERMES_READ_RECORD(hw, USER_BAP, + HERMES_RID_STAIDENTITY, &sta_id); if (err) { printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n", dev->name, err); - memset(&priv->firmware_info, 0, sizeof(priv->firmware_info)); + memset(&sta_id, 0, sizeof(sta_id)); } - - firmver = ((uint32_t)priv->firmware_info.major << 16) | priv->firmware_info.minor; - DEBUG(2, "%s: firmver = 0x%X\n", dev->name, firmver); + le16_to_cpus(&sta_id.id); + le16_to_cpus(&sta_id.vendor); + le16_to_cpus(&sta_id.major); + le16_to_cpus(&sta_id.minor); + + firmver = ((uint32_t)sta_id.major << 16) | sta_id.minor; + + printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n", + dev->name, sta_id.id, sta_id.vendor, + sta_id.major, sta_id.minor); /* Determine capabilities from the firmware version */ - switch (priv->firmware_info.vendor) { - case 0x1: + if (sta_id.vendor == 1) { /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout, - * ELSA, Melco, HP, IBM, Dell 1150 cards */ - vendor_str = "Lucent"; - /* Lucent MAC : 00:60:1D:* & 00:02:2D:* */ + ELSE, Meloc, HP, IBM, Dell 1150 */ + printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware " + "version %d.%02d\n", dev->name, + sta_id.major, sta_id.minor); priv->firmware_type = FIRMWARE_TYPE_LUCENT; priv->tx_rate_ctrl = 0x3; /* 11 Mb/s auto */ @@ -1268,118 +1305,62 @@ priv->has_mwo = (firmver >= 0x60000); priv->has_pm = (firmver >= 0x40020); priv->has_preamble = 0; + priv->ibss_port = 1; /* Tested with Lucent firmware : * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II * Tested CableTron firmware : 4.32 => Anton */ - break; - case 0x2: - vendor_str = "Generic Prism II"; - /* Some D-Link cards report vendor 0x02... */ - - priv->firmware_type = FIRMWARE_TYPE_PRISM2; + } else if ((sta_id.vendor == 2) && + ((firmver == 0x10001) || (firmver == 0x20001))) { + /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */ + /* Intel MAC : 00:02:B3:* */ + /* 3Com MAC : 00:50:DA:* */ + printk(KERN_DEBUG "%s: Looks like a Symbol firmware " + "(unknown version)\n", dev->name); + + /* FIXME : we need to get Symbol firmware revision. + * I tried to use SYMBOL_***ARY_VER, but it didn't + * returned anything proper... */ + priv->firmware_type = FIRMWARE_TYPE_SYMBOL; priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ - priv->need_card_reset = 0; + priv->need_card_reset = 1; priv->broken_reset = 0; - priv->broken_allocate = 0; + priv->broken_allocate = 1; priv->has_port3 = 1; - priv->has_ibss = (firmver >= 0x00007); /* FIXME */ - priv->has_wep = (firmver >= 0x00007); /* FIXME */ - priv->has_big_wep = 0; + priv->has_ibss = 1; /* FIXME */ + priv->has_wep = 1; /* FIXME */ + priv->has_big_wep = 1; /* RID_SYMBOL_KEY_LENGTH */ priv->has_mwo = 0; - priv->has_pm = (firmver >= 0x00007); /* FIXME */ - priv->has_preamble = 0; - - /* Tim Hurley -> D-Link card, vendor 02, firmware 0.08 */ - - /* Special case for Symbol cards */ - if(firmver == 0x10001) { - /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */ - vendor_str = "Symbol"; - /* Intel MAC : 00:02:B3:* */ - /* 3Com MAC : 00:50:DA:* */ - - /* FIXME : we need to get Symbol firmware revision. - * I tried to use SYMBOL_***ARY_VER, but it didn't - * returned anything proper... */ - priv->firmware_type = FIRMWARE_TYPE_SYMBOL; - priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ - priv->need_card_reset = 1; - priv->broken_reset = 0; - priv->broken_allocate = 1; - priv->has_port3 = 1; - priv->has_ibss = 1; /* FIXME */ - priv->has_wep = 1; /* FIXME */ - priv->has_big_wep = 1; /* RID_SYMBOL_KEY_LENGTH */ - priv->has_mwo = 0; - priv->has_pm = 1; /* FIXME */ - priv->has_preamble = 0; /* FIXME */ - /* Tested with Intel firmware : v15 => Jean II */ - } - break; - case 0x3: - vendor_str = "Samsung"; - /* To check - Should cover Samsung & Compaq */ - - priv->firmware_type = FIRMWARE_TYPE_PRISM2; - priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ - priv->need_card_reset = 0; - priv->broken_reset = 0; - priv->broken_allocate = 0; - priv->has_port3 = 1; - priv->has_ibss = 0; /* FIXME: available in later firmwares */ - priv->has_wep = (firmver >= 0x20000); /* FIXME */ - priv->has_big_wep = 0; /* FIXME */ - priv->has_mwo = 0; - priv->has_pm = (firmver >= 0x20000); /* FIXME */ - priv->has_preamble = 0; - break; - case 0x6: - /* D-Link DWL 650, ... */ - vendor_str = "LinkSys/D-Link"; - /* D-Link MAC : 00:40:05:* */ + priv->has_pm = 1; /* FIXME */ + priv->has_preamble = 0; /* FIXME */ + priv->ibss_port = 4; + /* Tested with Intel firmware : v15 => Jean II */ + } else { + printk(KERN_DEBUG "%s: Looks like an Intersil firmware " + "version %d.%02d\n", dev->name, + sta_id.major, sta_id.minor); - priv->firmware_type = FIRMWARE_TYPE_PRISM2; + priv->firmware_type = FIRMWARE_TYPE_INTERSIL; priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ priv->need_card_reset = 0; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 1; priv->has_ibss = (firmver >= 0x00007); /* FIXME */ - priv->has_wep = (firmver >= 0x00007); /* FIXME */ + priv->has_wep = (firmver >= 0x00008); priv->has_big_wep = 0; priv->has_mwo = 0; - priv->has_pm = (firmver >= 0x00007); /* FIXME */ + priv->has_pm = (firmver >= 0x00007); priv->has_preamble = 0; - /* Tested with D-Link firmware 0.07 => Jean II */ - /* Note : with 0.07, IBSS to a Lucent card seem flaky */ - break; - default: - vendor_str = "UNKNOWN"; - priv->firmware_type = 0; - priv->tx_rate_ctrl = 0x3; /* Hum... */ - priv->need_card_reset = 0; - priv->broken_reset = 0; - priv->broken_allocate = 0; - priv->has_port3 = 0; - priv->has_ibss = 0; - priv->has_wep = 0; - priv->has_big_wep = 0; - priv->has_mwo = 0; - priv->has_pm = 0; - priv->has_preamble = 0; + if (firmver >= 0x00008) + priv->ibss_port = 0; + else { + printk(KERN_NOTICE "%s: Intersil firmware earlier " + "than v0.08 - several features not supported.", + dev->name); + priv->ibss_port = 1; + } } - - if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) - priv->ibss_port = 4; - else if ( (priv->firmware_type == FIRMWARE_TYPE_PRISM2) && (firmver >= 0x00008) ) - priv->ibss_port = 0; - else - priv->ibss_port = 1; - - printk(KERN_DEBUG "%s: Firmware ID %02X vendor 0x%x (%s) version %d.%02d\n", - dev->name, priv->firmware_info.id, priv->firmware_info.vendor, - vendor_str, priv->firmware_info.major, priv->firmware_info.minor); } /* @@ -1551,7 +1532,6 @@ hermes_t *hw = &priv->hw; struct iw_statistics *wstats = &priv->wstats; int err = 0; - hermes_commsqual_t cq; if (!priv->hw_ready) return NULL; @@ -1571,7 +1551,14 @@ } #endif /* WIRELESS_SPY */ } else { - err = hermes_read_commsqual(hw, USER_BAP, &cq); + dldwd_commsqual_t cq; + + err = HERMES_READ_RECORD(hw, USER_BAP, + HERMES_RID_COMMSQUALITY, &cq); + + le16_to_cpus(&cq.qual); + le16_to_cpus(&cq.signal); + le16_to_cpus(&cq.noise); DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name, cq.qual, cq.signal, cq.noise); @@ -1597,7 +1584,7 @@ #ifdef WIRELESS_SPY static inline void dldwd_spy_gather(struct net_device *dev, u_char *mac, - hermes_commsqual_t *cq) + dldwd_commsqual_t *cq) { dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv; int i; @@ -1620,7 +1607,7 @@ struct dldwd_frame_hdr *hdr) { dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv; - hermes_commsqual_t cq; + dldwd_commsqual_t cq; /* Using spy support with lots of Rx packets, like in an * infrastructure (AP), will really slow down everything, because @@ -1722,9 +1709,15 @@ err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), txfid, 0); if (err) { - printk(KERN_ERR - "%s: Error %d writing packet header to BAP\n", - dev->name, err); + if (err == -EIO) + /* We get these errors reported by the + firmware every so often apparently at + random. Let the upper layers + handle the retry */ + DEBUG(1, "%s: DEBUG: EIO writing packet header to BAP\n", dev->name); + else + printk(KERN_ERR "%s: Error %d writing packet header to BAP\n", + dev->name, err); stats->tx_errors++; goto fail; } @@ -1749,12 +1742,14 @@ /* Round up for odd length packets */ err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off); if (err) { - printk(KERN_ERR "%s: Error %d writing packet data to BAP\n", - dev->name, err); + if (err == -EIO) + DEBUG(1, "%s: DEBUG: EIO writing packet header to BAP\n", dev->name); + else + printk(KERN_ERR "%s: Error %d writing packet header to BAP", + dev->name, err); stats->tx_errors++; goto fail; } - /* Finally, we actually initiate the send */ err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, &resp); @@ -1941,7 +1936,9 @@ if (erq->pointer) { /* We actually have a key to set */ - + if(erq->length > MAX_KEY_SIZE) + return -EINVAL; + if (copy_from_user(keybuf, erq->pointer, erq->length)) return -EFAULT; } @@ -2344,7 +2341,7 @@ else priv->tx_rate_ctrl = rate_ctrl; break; - case FIRMWARE_TYPE_PRISM2: /* Prism II style rate */ + case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */ case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */ switch(brate) { case 0: @@ -2418,7 +2415,7 @@ } else rrq->fixed = 1; break; - case FIRMWARE_TYPE_PRISM2: /* Prism II style rate */ + case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */ case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */ /* Check if auto or fixed (crude approximation) */ if((val & 0x1) && (val > 1)) { @@ -3649,32 +3646,32 @@ int dldwd_setup(dldwd_priv_t* priv) { - struct net_device *ndev = &priv->ndev;; + struct net_device *dev = &priv->ndev;; spin_lock_init(&priv->lock); /* Set up the net_device */ - ether_setup(ndev); - ndev->priv = priv; + ether_setup(dev); + dev->priv = priv; /* Setup up default routines */ priv->card_reset_handler = NULL; /* Caller may override */ - ndev->init = dldwd_init; - ndev->open = NULL; /* Caller *must* override */ - ndev->stop = NULL; - ndev->hard_start_xmit = dldwd_xmit; - ndev->tx_timeout = dldwd_tx_timeout; - ndev->watchdog_timeo = 4*HZ; /* 4 second timeout */ - - ndev->get_stats = dldwd_get_stats; - ndev->get_wireless_stats = dldwd_get_wireless_stats; + dev->init = dldwd_init; + dev->open = NULL; /* Caller *must* override */ + dev->stop = NULL; + dev->hard_start_xmit = dldwd_xmit; + dev->tx_timeout = dldwd_tx_timeout; + dev->watchdog_timeo = HZ; /* 4 second timeout */ - ndev->do_ioctl = dldwd_ioctl; + dev->get_stats = dldwd_get_stats; + dev->get_wireless_stats = dldwd_get_wireless_stats; - ndev->change_mtu = dldwd_change_mtu; - ndev->set_multicast_list = dldwd_set_multicast_list; + dev->do_ioctl = dldwd_ioctl; - netif_stop_queue(ndev); + dev->change_mtu = dldwd_change_mtu; + dev->set_multicast_list = dldwd_set_multicast_list; + + netif_stop_queue(dev); return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/net/wireless/orinoco.h linux/drivers/net/wireless/orinoco.h --- v2.4.9/linux/drivers/net/wireless/orinoco.h Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wireless/orinoco.h Mon Sep 17 22:52:35 2001 @@ -64,10 +64,9 @@ uint16_t txfid; /* Capabilities of the hardware/firmware */ - hermes_identity_t firmware_info; int firmware_type; #define FIRMWARE_TYPE_LUCENT 1 -#define FIRMWARE_TYPE_PRISM2 2 +#define FIRMWARE_TYPE_INTERSIL 2 #define FIRMWARE_TYPE_SYMBOL 3 int has_ibss, has_port3, prefer_port3, has_ibss_any, ibss_port; int has_wep, has_big_wep; @@ -142,6 +141,5 @@ extern int dldwd_proc_dev_init(dldwd_priv_t *dev); extern void dldwd_proc_dev_cleanup(dldwd_priv_t *priv); extern void dldwd_interrupt(int irq, void * dev_id, struct pt_regs *regs); - #endif diff -u --recursive --new-file v2.4.9/linux/drivers/net/wireless/orinoco_cs.c linux/drivers/net/wireless/orinoco_cs.c --- v2.4.9/linux/drivers/net/wireless/orinoco_cs.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wireless/orinoco_cs.c Mon Sep 17 22:52:35 2001 @@ -1,4 +1,4 @@ -/* orinoco_cs.c 0.06f - (formerly known as dldwd_cs.c) +/* orinoco_cs.c 0.07 - (formerly known as dldwd_cs.c) * * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,10 +42,11 @@ /*====================================================================*/ -static const char version[] __initdata = "orinoco_cs.c 0.06f (David Gibson and others)"; +static char version[] __initdata = "orinoco_cs.c 0.07 (David Gibson and others)"; MODULE_AUTHOR("David Gibson "); MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards"); +MODULE_LICENSE("Dual MPL/GPL"); /* Parameters that can be set with 'insmod' */ @@ -181,7 +182,7 @@ dldwd_card_t* card = (dldwd_card_t *)priv->card; dev_link_t *link = &card->link; conf_reg_t reg; - u_long default_cor; + u_int default_cor; TRACE_ENTER(priv->ndev.name); @@ -713,6 +714,9 @@ switch (event) { case CS_EVENT_CARD_REMOVAL: + /* FIXME: Erg.. this whole hw_ready thing looks racy + to me. this may not be fixable without changin the + PCMCIA subsystem, though */ priv->hw_ready = 0; dldwd_shutdown(priv); link->state &= ~DEV_PRESENT; @@ -780,8 +784,7 @@ TRACE_ENTER("dldwd"); - printk(KERN_DEBUG "dldwd: David's Less Dodgy WaveLAN/IEEE Driver\n" - KERN_DEBUG "%s\n", version); + printk(KERN_DEBUG "%s\n", version); CardServices(GetCardServicesInfo, &serv); if (serv.Revision != CS_RELEASE_CODE) { 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/Config.in linux/drivers/parport/Config.in --- v2.4.9/linux/drivers/parport/Config.in Wed Jul 25 17:10:22 2001 +++ linux/drivers/parport/Config.in Thu Sep 13 16:04:43 2001 @@ -25,12 +25,8 @@ bool ' SuperIO chipset support (EXPERIMENTAL)' CONFIG_PARPORT_PC_SUPERIO fi fi - if [ "$CONFIG_PARPORT_PC" = "y" ]; then - # Don't bother with this if parport_pc is a module; it only affects - # the presence or not of some __init's, which are no-ops for modules. - if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then - bool ' Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA - fi + if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then + dep_tristate ' Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA $CONFIG_PCMCIA fi if [ "$CONFIG_ARM" = "y" ]; then dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT diff -u --recursive --new-file v2.4.9/linux/drivers/parport/Makefile linux/drivers/parport/Makefile --- v2.4.9/linux/drivers/parport/Makefile Wed Jul 25 17:10:22 2001 +++ linux/drivers/parport/Makefile Thu Sep 13 16:04:43 2001 @@ -23,6 +23,7 @@ obj-$(CONFIG_PARPORT) += parport.o obj-$(CONFIG_PARPORT_PC) += parport_pc.o obj-$(CONFIG_PARPORT_SERIAL) += parport_serial.o +obj-$(CONFIG_PARPORT_PC_PCMCIA)+= parport_cs.o obj-$(CONFIG_PARPORT_AMIGA) += parport_amiga.o obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o diff -u --recursive --new-file v2.4.9/linux/drivers/parport/parport_cs.c linux/drivers/parport/parport_cs.c --- v2.4.9/linux/drivers/parport/parport_cs.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/parport/parport_cs.c Thu Sep 13 16:04:43 2001 @@ -0,0 +1,482 @@ +/*====================================================================== + + A driver for PCMCIA parallel port adapters + + (specifically, for the Quatech SPP-100 EPP card: other cards will + probably require driver tweaks) + + parport_cs.c 1.20 2000/11/02 23:15:05 + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU General Public License version 2 (the "GPL"), in + which case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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) +static char *version = +"parport_cs.c 1.20 2000/11/02 23:15:05 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +#ifndef VERSION +#define VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xdeb8; +static int irq_list[4] = { -1 }; +static int epp_mode = 1; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); +MODULE_PARM(epp_mode, "i"); + +/*====================================================================*/ + +#define FORCE_EPP_MODE 0x08 + +typedef struct parport_info_t { + dev_link_t link; + int ndev; + dev_node_t node; + struct parport *port; +} parport_info_t; + +static dev_link_t *parport_attach(void); +static void parport_detach(dev_link_t *); +static void parport_config(dev_link_t *link); +static void parport_cs_release(u_long arg); +static int parport_event(event_t event, int priority, + event_callback_args_t *args); + +static dev_info_t dev_info = "parport_cs"; +static dev_link_t *dev_list = NULL; + +extern struct parport_operations parport_pc_ops; +static struct parport_operations parport_cs_ops; + +/*====================================================================*/ + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + parport_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + +======================================================================*/ + +static dev_link_t *parport_attach(void) +{ + parport_info_t *info; + dev_link_t *link; + client_reg_t client_reg; + int i, ret; + + DEBUG(0, "parport_attach()\n"); + + /* Create new parport device */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) return NULL; + memset(info, 0, sizeof(*info)); + link = &info->link; link->priv = info; + + link->release.function = &parport_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->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* 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 = &parport_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); + parport_detach(link); + return NULL; + } + + return link; +} /* parport_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void parport_detach(dev_link_t *link) +{ + dev_link_t **linkp; + int ret; + + DEBUG(0, "parport_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + del_timer(&link->release); + if (link->state & DEV_CONFIG) + parport_cs_release((u_long)link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink, free device structure */ + *linkp = link->next; + kfree(link->priv); + +} /* parport_detach */ + +/*====================================================================== + + parport_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + parport device available to the system. + +======================================================================*/ + +#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 struct { u_int flag; char *name; } mode[] = { + { PARPORT_MODE_TRISTATE, "PS2" }, + { PARPORT_MODE_EPP, "EPP" }, + { PARPORT_MODE_ECP, "ECP" }, +}; + +void parport_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + parport_info_t *info = link->priv; + 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 }; + struct parport *p; + int i, last_ret, last_fn; + + DEBUG(0, "parport_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]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* Not sure if this is right... look up the current Vcc */ + 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; + if (epp_mode) + link->conf.ConfigIndex |= FORCE_EPP_MODE; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + 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(RequestIRQ, handle, &link->irq); + CS_CHECK(RequestConfiguration, handle, &link->conf); + + p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, + link->irq.AssignedIRQ, PARPORT_DMA_NONE, + NULL); + if (p == NULL) { + printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at " + "0x%3x, irq %u failed\n", link->io.BasePort1, + link->irq.AssignedIRQ); + goto failed; + } + +#if (LINUX_VERSION_CODE < VERSION(2,3,6)) +#if (LINUX_VERSION_CODE >= VERSION(2,2,8)) + p->private_data = kmalloc(sizeof(struct parport_pc_private), + GFP_KERNEL); + ((struct parport_pc_private *)(p->private_data))->ctr = 0x0c; +#endif + parport_proc_register(p); + p->flags |= PARPORT_FLAG_COMA; + parport_pc_write_econtrol(p, 0x00); + parport_pc_write_control(p, 0x0c); + parport_pc_write_data(p, 0x00); +#endif + + p->modes |= PARPORT_MODE_PCSPP; + if (epp_mode) + p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP; + info->ndev = 1; + info->node.major = LP_MAJOR; + info->node.minor = p->number; + info->port = p; + strcpy(info->node.dev_name, p->name); + link->dev = &info->node; + printk(KERN_INFO "%s: PC-style PCMCIA at %#x", p->name, + link->io.BasePort1); + if (link->io.NumPorts2) + printk(" & %#x", link->io.BasePort2); + printk(", irq %u [SPP", link->irq.AssignedIRQ); + for (i = 0; i < 5; i++) + if (p->modes & mode[i].flag) printk(",%s", mode[i].name); + printk("]\n"); + + link->state &= ~DEV_CONFIG_PENDING; + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); +failed: + parport_cs_release((u_long)link); + +} /* parport_config */ + +/*====================================================================== + + After a card is removed, parport_cs_release() will unregister the + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +void parport_cs_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + parport_info_t *info = link->priv; + + DEBUG(0, "parport_release(0x%p)\n", link); + + if (info->ndev) { + struct parport *p = info->port; +#if (LINUX_VERSION_CODE < VERSION(2,3,6)) + if (!(p->flags & PARPORT_FLAG_COMA)) + parport_quiesce(p); +#endif + parport_proc_unregister(p); +#if (LINUX_VERSION_CODE >= VERSION(2,2,8)) + kfree(p->private_data); +#endif + parport_unregister_port(p); + } + info->ndev = 0; + link->dev = NULL; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; + +} /* parport_cs_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. + +======================================================================*/ + +int parport_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + + DEBUG(1, "parport_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) + mod_timer(&link->release, jiffies + HZ/20); + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + parport_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; +} /* parport_event */ + +/*====================================================================*/ + +#if (LINUX_VERSION_CODE < VERSION(2,3,6)) + +static void inc_use_count(void) +{ + MOD_INC_USE_COUNT; + parport_pc_ops.inc_use_count(); +} + +static void dec_use_count(void) +{ + MOD_DEC_USE_COUNT; + parport_pc_ops.dec_use_count(); +} + +#endif + +/*====================================================================*/ + +static int __init init_parport_cs(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "parport_cs: Card Services release " + "does not match!\n"); + return -1; + } + +#if (LINUX_VERSION_CODE < VERSION(2,3,6)) + /* This is to protect against unloading modules out of order */ + parport_cs_ops = parport_pc_ops; + parport_cs_ops.inc_use_count = &inc_use_count; + parport_cs_ops.dec_use_count = &dec_use_count; +#endif + + register_pccard_driver(&dev_info, &parport_attach, &parport_detach); + return 0; +} + +static void __exit exit_parport_cs(void) +{ + DEBUG(0, "parport_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + parport_detach(dev_list); +} + +module_init(init_parport_cs); +module_exit(exit_parport_cs); 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/Makefile linux/drivers/pci/Makefile --- v2.4.9/linux/drivers/pci/Makefile Tue Jul 3 17:08:20 2001 +++ linux/drivers/pci/Makefile Sun Sep 9 10:50:48 2001 @@ -25,8 +25,11 @@ # obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o +obj-$(CONFIG_PARISC) += setup-bus.o obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o obj-$(CONFIG_ALL_PPC) += setup-bus.o +obj-$(CONFIG_DDB5476) += setup-bus.o +obj-$(CONFIG_SGI_IP27) += setup-irq.o ifndef CONFIG_X86 obj-y += syscall.o 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 Mon Sep 17 22:52:35 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 @@ -396,8 +396,9 @@ /** * pci_enable_wake - enable device to generate PME# when suspended - * @dev - PCI device to operate on - * @enable - Flag to enable or disable generation + * @dev: - PCI device to operate on + * @state: - Current state of device. + * @enable: - Flag to enable or disable generation * * Set the bits in the device's PM Capabilities to generate PME# when * the system is suspended. @@ -489,6 +490,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/pci/quirks.c linux/drivers/pci/quirks.c --- v2.4.9/linux/drivers/pci/quirks.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/pci/quirks.c Tue Sep 18 14:23:15 2001 @@ -158,6 +158,15 @@ pci_pci_problems|=PCIPCI_VIAETBF; } } +static void __init quirk_vsfx(struct pci_dev *dev) +{ + if((pci_pci_problems&PCIPCI_VSFX)==0) + { + printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); + pci_pci_problems|=PCIPCI_VSFX; + } +} + /* * Natoma has some interesting boundary conditions with Zoran stuff @@ -434,6 +443,7 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, 0x3112 /* Not out yet ? */, quirk_vialatency }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi }, diff -u --recursive --new-file v2.4.9/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c --- v2.4.9/linux/drivers/pcmcia/i82365.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/pcmcia/i82365.c Tue Sep 18 14:10:43 2001 @@ -934,7 +934,7 @@ "we have a card coming in" electronics have seen it. */ if (events & SS_DETECT) - mdelay(2); + mdelay(4); if (socket[i].handler) socket[i].handler(socket[i].info, events); } 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 Mon Sep 10 12:42: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); @@ -2195,11 +2175,13 @@ case BLKGETSIZE:{ /* Return device size */ long blocks = major_info->gendisk.sizes [MINOR (inp->i_rdev)] << 1; - rc = - copy_to_user ((long *) data, &blocks, - sizeof (long)); - if (rc) - rc = -EFAULT; + rc = put_user(blocks, (long *)arg); + break; + } + case BLKGETSIZE64:{ + u64 blocks = major_info->gendisk.sizes + [MINOR (inp->i_rdev)]; + rc = put_user(blocks << 10, (u64 *)arg); break; } case BLKRRPART:{ @@ -2517,7 +2499,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 Sep 10 12:42:32 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); @@ -648,14 +647,14 @@ case BLKGETSIZE: /* 0x1260 */ /* Return the device size, expressed in sectors */ - if (!arg) return -EINVAL; /* NULL pointer: not valid */ - err= 0; /* verify_area_20(VERIFY_WRITE, (long *) arg, sizeof(long)); - * if (err) return err; - */ - put_user ( 1024* xpram_sizes[MINOR(inode->i_rdev)] + return put_user( 1024* xpram_sizes[MINOR(inode->i_rdev)] / XPRAM_SOFTSECT, (long *) arg); - return 0; + + case BLKGETSIZE64: + return put_user( (u64)(1024* xpram_sizes[MINOR(inode->i_rdev)] + / XPRAM_SOFTSECT) << 9, + (u64 *) arg); case BLKFLSBUF: /* flush, 0x1261 */ fsync_dev(inode->i_rdev); 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/s390/net/iucv.c linux/drivers/s390/net/iucv.c --- v2.4.9/linux/drivers/s390/net/iucv.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/s390/net/iucv.c Mon Sep 10 09:04:53 2001 @@ -1309,7 +1309,7 @@ if (residual_buffer) *residual_buffer = parm.ipbfadr1; } else { - moved = min(unsigned int, buflen, 8); + moved = min_t(unsigned int, buflen, 8); memcpy ((char *) buffer, (char *) &parm.ipbfadr1, moved); @@ -1402,7 +1402,7 @@ while ((moved < 8) && (moved < buflen)) { dyn_len = - min(unsigned int, + min_t(unsigned int, (buffer + i)->length, need_to_move); memcpy ((char *)((ulong)((buffer + i)->address)), diff -u --recursive --new-file v2.4.9/linux/drivers/s390/net/netiucv.c linux/drivers/s390/net/netiucv.c --- v2.4.9/linux/drivers/s390/net/netiucv.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/s390/net/netiucv.c Mon Sep 10 09:04:53 2001 @@ -828,7 +828,7 @@ memset (iucv_userid[devnumber], ' ', 8); memcpy (iucv_userid[devnumber], userid, - min(unsigned int, strlen(userid), 8)); + min_t(unsigned int, strlen(userid), 8)); dev = &iucv_netdev[devnumber]; sprintf (dev->name, "iucv%i", devnumber); diff -u --recursive --new-file v2.4.9/linux/drivers/sbus/char/jsflash.c linux/drivers/sbus/char/jsflash.c --- v2.4.9/linux/drivers/sbus/char/jsflash.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/sbus/char/jsflash.c Mon Sep 10 12:42:32 2001 @@ -454,6 +454,8 @@ switch (cmd) { case BLKGETSIZE: return put_user(jsfd_bytesizes[dev] >> 9, (long *) arg); + case BLKGETSIZE64: + return put_user(jsfd_bytesizes[dev], (u64 *) arg); #if 0 case BLKROSET: 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/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c --- v2.4.9/linux/drivers/sbus/char/sunkbd.c Wed Jul 25 17:10:22 2001 +++ linux/drivers/sbus/char/sunkbd.c Sun Sep 16 21:22:50 2001 @@ -514,7 +514,7 @@ } do_poke_blanked_console = 1; - tasklet_schedule(&console_tasklet); + schedule_console_callback(); add_keyboard_randomness(keycode); tty = ttytab? ttytab[fg_console]: NULL; 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/53c700-mem.c linux/drivers/scsi/53c700-mem.c --- v2.4.9/linux/drivers/scsi/53c700-mem.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/53c700-mem.c Sun Sep 9 11:18:52 2001 @@ -0,0 +1,1842 @@ +/* WARNING: GENERATED FILE (from 53c700.c), DO NOT MODIFY */ +#define MEM_MAPPED +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* NCR (or Symbios) 53c700 and 53c700-66 Driver + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.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. +** +**----------------------------------------------------------------------------- + */ + +/* Notes: + * + * This driver is designed exclusively for these chips (virtually the + * earliest of the scripts engine chips). They need their own drivers + * because they are missing so many of the scripts and snazzy register + * features of their elder brothers (the 710, 720 and 770). + * + * The 700 is the lowliest of the line, it can only do async SCSI. + * The 700-66 can at least do synchronous SCSI up to 10MHz. + * + * The 700 chip has no host bus interface logic of its own. However, + * it is usually mapped to a location with well defined register + * offsets. Therefore, if you can determine the base address and the + * irq your board incorporating this chip uses, you can probably use + * this driver to run it (although you'll probably have to write a + * minimal wrapper for the purpose---see the NCR_D700 driver for + * details about how to do this). + * + * + * TODO List: + * + * 1. Better statistics in the proc fs + * + * 2. Implement message queue (queues SCSI messages like commands) and make + * the abort and device reset functions use them. + * */ + +/* CHANGELOG + * + * Version 2.3 + * + * More endianness/cache coherency changes. + * + * Better bad device handling (handles devices lying about tag + * queueing support and devices which fail to provide sense data on + * contingent allegiance conditions) + * + * Many thanks to Richard Hirst for patiently + * debugging this driver on the parisc architecture and suggesting + * many improvements and bug fixes. + * + * Thanks also go to Linuxcare Inc. for providing several PARISC + * machines for me to debug the driver on. + * + * Version 2.2 + * + * Made the driver mem or io mapped; added endian invariance; added + * dma cache flushing operations for architectures which need it; + * added support for more varied clocking speeds. + * + * Version 2.1 + * + * Initial modularisation from the D700. See NCR_D700.c for the rest of + * the changelog. + * */ +#define NCR_700_VERSION "2.3" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "constants.h" + +#include "53c700.h" + +#ifdef NCR_700_DEBUG +#define STATIC +#else +#define STATIC static +#endif + +MODULE_AUTHOR("James Bottomley"); +MODULE_DESCRIPTION("53c700 and 53c700-66 Driver"); +MODULE_LICENSE("GPL"); + +/* This is the script */ +#include "53c700_d.h" + + +STATIC int NCR_700_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +STATIC int NCR_700_abort(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_bus_reset(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_dev_reset(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_host_reset(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_proc_directory_info(char *, char **, off_t, int, int, int); +STATIC void NCR_700_chip_setup(struct Scsi_Host *host); +STATIC void NCR_700_chip_reset(struct Scsi_Host *host); + +static char *NCR_700_phase[] = { + "", + "after selection", + "before command phase", + "after command phase", + "after status phase", + "after data in phase", + "after data out phase", + "during data phase", +}; + +static char *NCR_700_condition[] = { + "", + "NOT MSG_OUT", + "UNEXPECTED PHASE", + "NOT MSG_IN", + "UNEXPECTED MSG", + "MSG_IN", + "SDTR_MSG RECEIVED", + "REJECT_MSG RECEIVED", + "DISCONNECT_MSG RECEIVED", + "MSG_OUT", + "DATA_IN", + +}; + +static char *NCR_700_fatal_messages[] = { + "unexpected message after reselection", + "still MSG_OUT after message injection", + "not MSG_IN after selection", + "Illegal message length received", +}; + +static char *NCR_700_SBCL_bits[] = { + "IO ", + "CD ", + "MSG ", + "ATN ", + "SEL ", + "BSY ", + "ACK ", + "REQ ", +}; + +static char *NCR_700_SBCL_to_phase[] = { + "DATA_OUT", + "DATA_IN", + "CMD_OUT", + "STATE", + "ILLEGAL PHASE", + "ILLEGAL PHASE", + "MSG OUT", + "MSG IN", +}; + +static __u8 NCR_700_SDTR_msg[] = { + 0x01, /* Extended message */ + 0x03, /* Extended message Length */ + 0x01, /* SDTR Extended message */ + NCR_700_MIN_PERIOD, + NCR_700_MAX_OFFSET +}; + +struct Scsi_Host * __init +NCR_700_detect(Scsi_Host_Template *tpnt, + struct NCR_700_Host_Parameters *hostdata) +{ + __u32 *script = kmalloc(sizeof(SCRIPT), GFP_KERNEL); + __u32 pScript; + struct Scsi_Host *host; + static int banner = 0; + int j; + + /* Fill in the missing routines from the host template */ + tpnt->queuecommand = NCR_700_queuecommand; + tpnt->eh_abort_handler = NCR_700_abort; + tpnt->eh_device_reset_handler = NCR_700_dev_reset; + tpnt->eh_bus_reset_handler = NCR_700_bus_reset; + tpnt->eh_host_reset_handler = NCR_700_host_reset; + tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST; + tpnt->sg_tablesize = NCR_700_SG_SEGMENTS; + tpnt->cmd_per_lun = NCR_700_MAX_TAGS; + tpnt->use_clustering = DISABLE_CLUSTERING; + tpnt->use_new_eh_code = 1; + tpnt->proc_info = NCR_700_proc_directory_info; + + if(tpnt->name == NULL) + tpnt->name = "53c700"; + if(tpnt->proc_name == NULL) + tpnt->proc_name = "53c700"; + + + if((host = scsi_register(tpnt, 4)) == NULL) + return NULL; + if(script == NULL) { + printk(KERN_ERR "53c700: Failed to allocate script, detatching\n"); + scsi_unregister(host); + return NULL; + } + + hostdata->slots = kmalloc(sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST, GFP_KERNEL); + if(hostdata->slots == NULL) { + printk(KERN_ERR "53c700: Failed to allocate command slots, detatching\n"); + scsi_unregister(host); + return NULL; + } + memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST); + for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { + if(j == 0) + hostdata->free_list = &hostdata->slots[j]; + else + hostdata->slots[j-1].ITL_forw = &hostdata->slots[j]; + hostdata->slots[j].state = NCR_700_SLOT_FREE; + } + host->hostdata[0] = (__u32)hostdata; + for(j = 0; j < sizeof(SCRIPT)/sizeof(SCRIPT[0]); j++) { + script[j] = bS_to_host(SCRIPT[j]); + } + /* bus physical address of script */ + pScript = virt_to_bus(script); + /* adjust all labels to be bus physical */ + for(j = 0; j < PATCHES; j++) { + script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]); + } + /* now patch up fixed addresses */ + script_patch_32(script, MessageLocation, + virt_to_bus(&hostdata->msgout[0])); + script_patch_32(script, StatusAddress, + virt_to_bus(&hostdata->status)); + script_patch_32(script, ReceiveMsgAddress, + virt_to_bus(&hostdata->msgin[0])); + + hostdata->script = script; + hostdata->pScript = pScript; + hostdata->state = NCR_700_HOST_FREE; + spin_lock_init(&hostdata->lock); + hostdata->cmd = NULL; + host->max_id = 7; + host->max_lun = NCR_700_MAX_LUNS; + host->unique_id = hostdata->base; + host->base = hostdata->base; + host->hostdata[0] = (unsigned long)hostdata; + /* kick the chip */ + NCR_700_writeb(0xff, host, CTEST9_REG); + hostdata->rev = (NCR_700_readb(host, CTEST7_REG)<<4) & 0x0f; + hostdata->fast = (NCR_700_readb(host, CTEST9_REG) == 0); + if(banner == 0) { + printk(KERN_NOTICE "53c700: Version " NCR_700_VERSION " By James.Bottomley@HansenPartnership.com\n"); + banner = 1; + } + printk(KERN_NOTICE "scsi%d: %s rev %d %s\n", host->host_no, + hostdata->fast ? "53c700-66" : "53c700", + hostdata->rev, hostdata->differential ? + "(Differential)" : ""); + /* reset the chip */ + NCR_700_chip_reset(host); + NCR_700_writeb(ASYNC_OPERATION , host, SXFER_REG); + + return host; +} + +int +NCR_700_release(struct Scsi_Host *host) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + kfree(hostdata->script); + return 1; +} + +static inline __u8 +NCR_700_identify(int can_disconnect, __u8 lun) +{ + return IDENTIFY_BASE | + ((can_disconnect) ? 0x40 : 0) | + (lun & NCR_700_LUN_MASK); +} + +/* + * Function : static int datapath_residual (Scsi_Host *host) + * + * Purpose : return residual data count of what's in the chip. If you + * really want to know what this function is doing, it's almost a + * direct transcription of the algorithm described in the 53c710 + * guide, except that the DBC and DFIFO registers are only 6 bits + * wide. + * + * Inputs : host - SCSI host */ +static inline int +NCR_700_data_residual (struct Scsi_Host *host) { + int count, synchronous; + unsigned int ddir; + + count = ((NCR_700_readb(host, DFIFO_REG) & 0x3f) - + (NCR_700_readl(host, DBC_REG) & 0x3f)) & 0x3f; + + synchronous = NCR_700_readb(host, SXFER_REG) & 0x0f; + + /* get the data direction */ + ddir = NCR_700_readb(host, CTEST0_REG) & 0x01; + + if (ddir) { + /* Receive */ + if (synchronous) + count += (NCR_700_readb(host, SSTAT2_REG) & 0xf0) >> 4; + else + if (NCR_700_readb(host, SSTAT1_REG) & SIDL_REG_FULL) + ++count; + } else { + /* Send */ + __u8 sstat = NCR_700_readb(host, SSTAT1_REG); + if (sstat & SODL_REG_FULL) + ++count; + if (synchronous && (sstat & SODR_REG_FULL)) + ++count; + } + return count; +} + +/* print out the SCSI wires and corresponding phase from the SBCL register + * in the chip */ +static inline char * +sbcl_to_string(__u8 sbcl) +{ + int i; + static char ret[256]; + + ret[0]='\0'; + for(i=0; i<8; i++) { + if((1<free_list; + + if(slot == NULL) { + /* sanity check */ + if(hostdata->command_slot_count != NCR_700_COMMAND_SLOTS_PER_HOST) + printk(KERN_ERR "SLOTS FULL, but count is %d, should be %d\n", hostdata->command_slot_count, NCR_700_COMMAND_SLOTS_PER_HOST); + return NULL; + } + + if(slot->state != NCR_700_SLOT_FREE) + /* should panic! */ + printk(KERN_ERR "BUSY SLOT ON FREE LIST!!!\n"); + + + hostdata->free_list = slot->ITL_forw; + slot->ITL_forw = NULL; + + + /* NOTE: set the state to busy here, not queued, since this + * indicates the slot is in use and cannot be run by the IRQ + * finish routine. If we cannot queue the command when it + * is properly build, we then change to NCR_700_SLOT_QUEUED */ + slot->state = NCR_700_SLOT_BUSY; + hostdata->command_slot_count++; + + return slot; +} + +STATIC void +free_slot(struct NCR_700_command_slot *slot, + struct NCR_700_Host_Parameters *hostdata) +{ + int hash; + struct NCR_700_command_slot **forw, **back; + + + if((slot->state & NCR_700_SLOT_MASK) != NCR_700_SLOT_MAGIC) { + printk(KERN_ERR "53c700: SLOT %p is not MAGIC!!!\n", slot); + } + if(slot->state == NCR_700_SLOT_FREE) { + printk(KERN_ERR "53c700: SLOT %p is FREE!!!\n", slot); + } + /* remove from queues */ + if(slot->tag != NCR_700_NO_TAG) { + hash = hash_ITLQ(slot->cmnd->target, slot->cmnd->lun, + slot->tag); + if(slot->ITLQ_forw == NULL) + back = &hostdata->ITLQ_Hash_back[hash]; + else + back = &slot->ITLQ_forw->ITLQ_back; + + if(slot->ITLQ_back == NULL) + forw = &hostdata->ITLQ_Hash_forw[hash]; + else + forw = &slot->ITLQ_back->ITLQ_forw; + + *forw = slot->ITLQ_forw; + *back = slot->ITLQ_back; + } + hash = hash_ITL(slot->cmnd->target, slot->cmnd->lun); + if(slot->ITL_forw == NULL) + back = &hostdata->ITL_Hash_back[hash]; + else + back = &slot->ITL_forw->ITL_back; + + if(slot->ITL_back == NULL) + forw = &hostdata->ITL_Hash_forw[hash]; + else + forw = &slot->ITL_back->ITL_forw; + + *forw = slot->ITL_forw; + *back = slot->ITL_back; + + slot->resume_offset = 0; + slot->cmnd = NULL; + slot->state = NCR_700_SLOT_FREE; + slot->ITL_forw = hostdata->free_list; + hostdata->free_list = slot; + hostdata->command_slot_count--; +} + + +/* This routine really does very little. The command is indexed on + the ITL and (if tagged) the ITLQ lists in _queuecommand */ +STATIC void +save_for_reselection(struct NCR_700_Host_Parameters *hostdata, + Scsi_Cmnd *SCp, __u32 dsp) +{ + /* Its just possible that this gets executed twice */ + if(SCp != NULL) { + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + + slot->resume_offset = dsp; + } + hostdata->state = NCR_700_HOST_FREE; + hostdata->cmd = NULL; +} + +/* Most likely nexus is the oldest in each case */ +STATIC inline struct NCR_700_command_slot * +find_ITL_Nexus(struct NCR_700_Host_Parameters *hostdata, __u8 pun, __u8 lun) +{ + int hash = hash_ITL(pun, lun); + struct NCR_700_command_slot *slot = hostdata->ITL_Hash_back[hash]; + while(slot != NULL && !(slot->cmnd->target == pun && + slot->cmnd->lun == lun)) + slot = slot->ITL_back; + return slot; +} + +STATIC inline struct NCR_700_command_slot * +find_ITLQ_Nexus(struct NCR_700_Host_Parameters *hostdata, __u8 pun, + __u8 lun, __u8 tag) +{ + int hash = hash_ITLQ(pun, lun, tag); + struct NCR_700_command_slot *slot = hostdata->ITLQ_Hash_back[hash]; + + while(slot != NULL && !(slot->cmnd->target == pun + && slot->cmnd->lun == lun && slot->tag == tag)) + slot = slot->ITLQ_back; + +#ifdef NCR_700_TAG_DEBUG + if(slot != NULL) { + struct NCR_700_command_slot *n = slot->ITLQ_back; + while(n != NULL && n->cmnd->target != pun + && n->cmnd->lun != lun && n->tag != tag) + n = n->ITLQ_back; + + if(n != NULL && n->cmnd->target == pun && n->cmnd->lun == lun + && n->tag == tag) { + printk(KERN_WARNING "53c700: WARNING: DUPLICATE tag %d\n", + tag); + } + } +#endif + return slot; +} + + + +/* This translates the SDTR message offset and period to a value + * which can be loaded into the SXFER_REG. + * + * NOTE: According to SCSI-2, the true transfer period (in ns) is + * actually four times this period value */ +STATIC inline __u8 +NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata, + __u8 offset, __u8 period) +{ + int XFERP; + + if(period*4 < NCR_700_MIN_PERIOD) { + printk(KERN_WARNING "53c700: Period %dns is less than SCSI-2 minimum, setting to %d\n", period*4, NCR_700_MIN_PERIOD); + period = NCR_700_MIN_PERIOD/4; + } + XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; + if(offset > NCR_700_MAX_OFFSET) { + printk(KERN_WARNING "53c700: Offset %d exceeds maximum, setting to %d\n", + offset, NCR_700_MAX_OFFSET); + offset = NCR_700_MAX_OFFSET; + } + if(XFERP < NCR_700_MIN_XFERP) { + printk(KERN_WARNING "53c700: XFERP %d is less than minium, setting to %d\n", + XFERP, NCR_700_MIN_XFERP); + XFERP = NCR_700_MIN_XFERP; + } + return (offset & 0x0f) | (XFERP & 0x07)<<4; +} + + +STATIC inline void +NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, + Scsi_Cmnd *SCp, int result) +{ + hostdata->state = NCR_700_HOST_FREE; + hostdata->cmd = NULL; + + if(SCp != NULL) { + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + + if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) { +#ifdef NCR_700_DEBUG + printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is", + SCp, SCp->cmnd[7], result); + print_sense("53c700", SCp); +#endif + if(result == 0) + result = SCp->cmnd[7]; + } + + free_slot(slot, hostdata); + + SCp->host_scribble = NULL; + SCp->result = result; + SCp->scsi_done(SCp); + if(NCR_700_get_depth(SCp->device) == 0 || + NCR_700_get_depth(SCp->device) > NCR_700_MAX_TAGS) + printk(KERN_ERR "Invalid depth in NCR_700_scsi_done(): %d\n", + NCR_700_get_depth(SCp->device)); + NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) - 1); + } else { + printk(KERN_ERR "53c700: SCSI DONE HAS NULL SCp\n"); + } +} + + +STATIC void +NCR_700_internal_bus_reset(struct Scsi_Host *host) +{ + /* Bus reset */ + NCR_700_writeb(ASSERT_RST, host, SCNTL1_REG); + udelay(50); + NCR_700_writeb(0, host, SCNTL1_REG); + +} + +STATIC void +NCR_700_chip_setup(struct Scsi_Host *host) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + NCR_700_writeb(1 << host->this_id, host, SCID_REG); + NCR_700_writeb(0, host, SBCL_REG); + NCR_700_writeb(0, host, SXFER_REG); + + NCR_700_writeb(PHASE_MM_INT | SEL_TIMEOUT_INT | GROSS_ERR_INT | UX_DISC_INT + | RST_INT | PAR_ERR_INT | SELECT_INT, host, SIEN_REG); + + NCR_700_writeb(ABORT_INT | INT_INST_INT | ILGL_INST_INT, host, DIEN_REG); + NCR_700_writeb(BURST_LENGTH_8, host, DMODE_REG); + NCR_700_writeb(FULL_ARBITRATION | PARITY | AUTO_ATN, host, SCNTL0_REG); + NCR_700_writeb(LAST_DIS_ENBL | ENABLE_ACTIVE_NEGATION|GENERATE_RECEIVE_PARITY, + host, CTEST8_REG); + NCR_700_writeb(ENABLE_SELECT, host, SCNTL1_REG); + if(hostdata->clock > 75) { + printk(KERN_ERR "53c700: Clock speed %dMHz is too high: 75Mhz is the maximum this chip can be driven at\n", hostdata->clock); + /* do the best we can, but the async clock will be out + * of spec: sync divider 2, async divider 3 */ + DEBUG(("53c700: sync 2 async 3\n")); + NCR_700_writeb(SYNC_DIV_2_0, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_3_0, host, DCNTL_REG); + hostdata->sync_clock = hostdata->clock/2; + } else if(hostdata->clock > 50 && hostdata->clock <= 75) { + /* sync divider 1.5, async divider 3 */ + DEBUG(("53c700: sync 1.5 async 3\n")); + NCR_700_writeb(SYNC_DIV_1_5, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_3_0, host, DCNTL_REG); + hostdata->sync_clock = hostdata->clock*2; + hostdata->sync_clock /= 3; + + } else if(hostdata->clock > 37 && hostdata->clock <= 50) { + /* sync divider 1, async divider 2 */ + DEBUG(("53c700: sync 1 async 2\n")); + NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_2_0, host, DCNTL_REG); + hostdata->sync_clock = hostdata->clock; + } else if(hostdata->clock > 25 && hostdata->clock <=37) { + /* sync divider 1, async divider 1.5 */ + DEBUG(("53c700: sync 1 async 1.5\n")); + NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_1_5, host, DCNTL_REG); + hostdata->sync_clock = hostdata->clock; + } else { + DEBUG(("53c700: sync 1 async 1\n")); + NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_1_0, host, DCNTL_REG); + /* sync divider 1, async divider 1 */ + } +} + +STATIC void +NCR_700_chip_reset(struct Scsi_Host *host) +{ + /* Chip reset */ + NCR_700_writeb(SOFTWARE_RESET, host, DCNTL_REG); + udelay(100); + + NCR_700_writeb(0, host, DCNTL_REG); + + mdelay(1000); + + NCR_700_chip_setup(host); +} + +/* The heart of the message processing engine is that the instruction + * immediately after the INT is the normal case (and so must be CLEAR + * ACK). If we want to do something else, we call that routine in + * scripts and set temp to be the normal case + 8 (skipping the CLEAR + * ACK) so that the routine returns correctly to resume its activity + * */ +STATIC __u32 +process_extended_message(struct Scsi_Host *host, + struct NCR_700_Host_Parameters *hostdata, + Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps) +{ + __u32 resume_offset = dsp, temp = dsp + 8; + __u8 pun = 0xff, lun = 0xff; + + if(SCp != NULL) { + pun = SCp->target; + lun = SCp->lun; + } + + switch(hostdata->msgin[2]) { + case A_SDTR_MSG: + if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { + __u8 period = hostdata->msgin[3]; + __u8 offset = hostdata->msgin[4]; + __u8 sxfer; + + if(offset != 0 && period != 0) + sxfer = NCR_700_offset_period_to_sxfer(hostdata, offset, period); + else + sxfer = 0; + + if(sxfer != NCR_700_get_SXFER(SCp->device)) { + printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n", + host->host_no, pun, lun, + offset, period*4); + + NCR_700_set_SXFER(SCp->device, sxfer); + } + + + NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + + NCR_700_writeb(NCR_700_get_SXFER(SCp->device), + host, SXFER_REG); + + } else { + /* SDTR message out of the blue, reject it */ + printk(KERN_WARNING "scsi%d Unexpected SDTR msg\n", + host->host_no); + hostdata->msgout[0] = A_REJECT_MSG; + dma_cache_wback((unsigned long)hostdata->msgout, sizeof(hostdata->msgout)); + script_patch_16(hostdata->script, MessageCount, 1); + /* SendMsgOut returns, so set up the return + * address */ + resume_offset = hostdata->pScript + Ent_SendMessageWithATN; + } + break; + + case A_WDTR_MSG: + printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n", + host->host_no, pun, lun); + hostdata->msgout[0] = A_REJECT_MSG; + dma_cache_wback((unsigned long)hostdata->msgout, sizeof(hostdata->msgout)); + script_patch_16(hostdata->script, MessageCount, 1); + resume_offset = hostdata->pScript + Ent_SendMessageWithATN; + + break; + + default: + printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ", + host->host_no, pun, lun, + NCR_700_phase[(dsps & 0xf00) >> 8]); + print_msg(hostdata->msgin); + printk("\n"); + /* just reject it */ + hostdata->msgout[0] = A_REJECT_MSG; + dma_cache_wback((unsigned long)hostdata->msgout, sizeof(hostdata->msgout)); + script_patch_16(hostdata->script, MessageCount, 1); + /* SendMsgOut returns, so set up the return + * address */ + resume_offset = hostdata->pScript + Ent_SendMessageWithATN; + } + NCR_700_writel(temp, host, TEMP_REG); + return resume_offset; +} + +STATIC __u32 +process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata, + Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps) +{ + /* work out where to return to */ + __u32 temp = dsp + 8, resume_offset = dsp; + __u8 pun = 0xff, lun = 0xff; + + dma_cache_inv((unsigned long)hostdata->msgin, sizeof(hostdata->msgin)); + + if(SCp != NULL) { + pun = SCp->target; + lun = SCp->lun; + } + +#ifdef NCR_700_DEBUG + printk("scsi%d (%d:%d): message %s: ", host->host_no, pun, lun, + NCR_700_phase[(dsps & 0xf00) >> 8]); + print_msg(hostdata->msgin); + printk("\n"); +#endif + + switch(hostdata->msgin[0]) { + + case A_EXTENDED_MSG: + return process_extended_message(host, hostdata, SCp, + dsp, dsps); + + case A_REJECT_MSG: + if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { + /* Rejected our sync negotiation attempt */ + NCR_700_set_SXFER(SCp->device, 0); + NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + } else if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { + /* rejected our first simple tag message */ + printk(KERN_WARNING "scsi%d (%d:%d) Rejected first tag queue attempt, turning off tag queueing\n", host->host_no, pun, lun); + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + hostdata->tag_negotiated &= ~(1<target); + } else { + printk(KERN_WARNING "scsi%d (%d:%d) Unexpected REJECT Message %s\n", + host->host_no, pun, lun, + NCR_700_phase[(dsps & 0xf00) >> 8]); + /* however, just ignore it */ + } + break; + + case A_PARITY_ERROR_MSG: + printk(KERN_ERR "scsi%d (%d:%d) Parity Error!\n", host->host_no, + pun, lun); + NCR_700_internal_bus_reset(host); + break; + case A_SIMPLE_TAG_MSG: + printk(KERN_INFO "scsi%d (%d:%d) SIMPLE TAG %d %s\n", host->host_no, + pun, lun, hostdata->msgin[1], + NCR_700_phase[(dsps & 0xf00) >> 8]); + /* just ignore it */ + break; + default: + printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ", + host->host_no, pun, lun, + NCR_700_phase[(dsps & 0xf00) >> 8]); + + print_msg(hostdata->msgin); + printk("\n"); + /* just reject it */ + hostdata->msgout[0] = A_REJECT_MSG; + dma_cache_wback((unsigned long)hostdata->msgout, sizeof(hostdata->msgout)); + script_patch_16(hostdata->script, MessageCount, 1); + /* SendMsgOut returns, so set up the return + * address */ + resume_offset = hostdata->pScript + Ent_SendMessageWithATN; + + break; + } + NCR_700_writel(temp, host, TEMP_REG); + return resume_offset; +} + +STATIC __u32 +process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, + struct Scsi_Host *host, + struct NCR_700_Host_Parameters *hostdata) +{ + __u32 resume_offset = 0; + __u8 pun = 0xff, lun=0xff; + + if(SCp != NULL) { + pun = SCp->target; + lun = SCp->lun; + } + + if(dsps == A_GOOD_STATUS_AFTER_STATUS) { + dma_cache_inv((unsigned long)hostdata->status, sizeof(hostdata->status)); + DEBUG((" COMMAND COMPLETE, status=%02x\n", + hostdata->status)); + /* OK, if TCQ still on, we know it works */ + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + /* check for contingent allegiance contitions */ + if(status_byte(hostdata->status) == CHECK_CONDITION || + status_byte(hostdata->status) == COMMAND_TERMINATED) { + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + if(SCp->cmnd[0] == REQUEST_SENSE) { + /* OOPS: bad device, returning another + * contingent allegiance condition */ + printk(KERN_ERR "scsi%d (%d:%d) broken device is looping in contingent allegiance: ignoring\n", host->host_no, pun, lun); + NCR_700_scsi_done(hostdata, SCp, hostdata->status); + } else { + + DEBUG((" cmd %p has status %d, requesting sense\n", + SCp, hostdata->status)); + /* we can destroy the command here because the + * contingent allegiance condition will cause a + * retry which will re-copy the command from the + * saved data_cmnd */ + SCp->cmnd[0] = REQUEST_SENSE; + SCp->cmnd[1] = (SCp->lun & 0x7) << 5; + SCp->cmnd[2] = 0; + SCp->cmnd[3] = 0; + SCp->cmnd[4] = sizeof(SCp->sense_buffer); + SCp->cmnd[5] = 0; + SCp->cmd_len = 6; + /* Here's a quiet hack: the REQUEST_SENSE command is + * six bytes, so store a flag indicating that this + * was an internal sense request and the original + * status at the end of the command */ + SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; + SCp->cmnd[7] = hostdata->status; + slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); + slot->SG[0].pAddr = bS_to_host(virt_to_bus(SCp->sense_buffer)); + slot->SG[1].ins = bS_to_host(SCRIPT_RETURN); + slot->SG[1].pAddr = 0; + slot->resume_offset = hostdata->pScript; + dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG[0])*2); + dma_cache_inv((unsigned long)SCp->sense_buffer, sizeof(SCp->sense_buffer)); + + /* queue the command for reissue */ + slot->state = NCR_700_SLOT_QUEUED; + hostdata->state = NCR_700_HOST_FREE; + hostdata->cmd = NULL; + } + } else { + if(status_byte(hostdata->status) == GOOD && + SCp->cmnd[0] == INQUIRY && SCp->use_sg == 0) { + /* Piggy back the tag queueing support + * on this command */ + if(((char *)SCp->request_buffer)[7] & 0x02) { + printk(KERN_INFO "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", host->host_no, pun, lun); + hostdata->tag_negotiated |= (1<target); + NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + } else { + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + hostdata->tag_negotiated &= ~(1<target); + } + } + NCR_700_scsi_done(hostdata, SCp, hostdata->status); + } + } else if((dsps & 0xfffff0f0) == A_UNEXPECTED_PHASE) { + __u8 i = (dsps & 0xf00) >> 8; + + printk(KERN_ERR "scsi%d: (%d:%d), UNEXPECTED PHASE %s (%s)\n", + host->host_no, pun, lun, + NCR_700_phase[i], + sbcl_to_string(NCR_700_readb(host, SBCL_REG))); + printk(KERN_ERR " len = %d, cmd =", SCp->cmd_len); + print_command(SCp->cmnd); + + NCR_700_internal_bus_reset(host); + } else if((dsps & 0xfffff000) == A_FATAL) { + int i = (dsps & 0xfff); + + printk(KERN_ERR "scsi%d: (%d:%d) FATAL ERROR: %s\n", + host->host_no, pun, lun, NCR_700_fatal_messages[i]); + if(dsps == A_FATAL_ILLEGAL_MSG_LENGTH) { + printk(KERN_ERR " msg begins %02x %02x\n", + hostdata->msgin[0], hostdata->msgin[1]); + } + NCR_700_internal_bus_reset(host); + } else if((dsps & 0xfffff0f0) == A_DISCONNECT) { +#ifdef NCR_700_DEBUG + __u8 i = (dsps & 0xf00) >> 8; + + printk("scsi%d: (%d:%d), DISCONNECTED (%d) %s\n", + host->host_no, pun, lun, + i, NCR_700_phase[i]); +#endif + save_for_reselection(hostdata, SCp, dsp); + + } else if(dsps == A_RESELECTION_IDENTIFIED) { + __u8 lun; + struct NCR_700_command_slot *slot; + __u8 reselection_id = hostdata->reselection_id; + + dma_cache_inv((unsigned long)hostdata->msgin, sizeof(hostdata->msgin)); + + lun = hostdata->msgin[0] & 0x1f; + + hostdata->reselection_id = 0xff; + DEBUG(("scsi%d: (%d:%d) RESELECTED!\n", + host->host_no, reselection_id, lun)); + /* clear the reselection indicator */ + if(hostdata->msgin[1] == A_SIMPLE_TAG_MSG) { + slot = find_ITLQ_Nexus(hostdata, reselection_id, + lun, hostdata->msgin[2]); + } else { + slot = find_ITL_Nexus(hostdata, reselection_id, lun); + } + retry: + if(slot == NULL) { + struct NCR_700_command_slot *s = find_ITL_Nexus(hostdata, reselection_id, lun); + printk(KERN_ERR "scsi%d: (%d:%d) RESELECTED but no saved command (MSG = %02x %02x %02x)!!\n", + host->host_no, reselection_id, lun, + hostdata->msgin[0], hostdata->msgin[1], + hostdata->msgin[2]); + printk(KERN_ERR " OUTSTANDING TAGS:"); + while(s != NULL) { + if(s->cmnd->target == reselection_id && + s->cmnd->lun == lun) { + printk("%d ", s->tag); + if(s->tag == hostdata->msgin[2]) { + printk(" ***FOUND*** \n"); + slot = s; + goto retry; + } + + } + s = s->ITL_back; + } + printk("\n"); + } else { + if(hostdata->state != NCR_700_HOST_BUSY) + printk(KERN_ERR "scsi%d: FATAL, host not busy during valid reselection!\n", + host->host_no); + resume_offset = slot->resume_offset; + hostdata->cmd = slot->cmnd; + + /* re-patch for this command */ + script_patch_32_abs(hostdata->script, CommandAddress, + virt_to_bus(slot->cmnd->cmnd)); + script_patch_16(hostdata->script, + CommandCount, slot->cmnd->cmd_len); + script_patch_32_abs(hostdata->script, SGScriptStartAddress, + virt_to_bus(&slot->SG[0].ins)); + + /* Note: setting SXFER only works if we're + * still in the MESSAGE phase, so it is vital + * that ACK is still asserted when we process + * the reselection message. The resume offset + * should therefore always clear ACK */ + NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device), + host, SXFER_REG); + + } + } else if(dsps == A_RESELECTED_DURING_SELECTION) { + + /* This section is full of debugging code because I've + * never managed to reach it. I think what happens is + * that, because the 700 runs with selection + * interrupts enabled the whole time that we take a + * selection interrupt before we manage to get to the + * reselected script interrupt */ + + __u8 reselection_id = NCR_700_readb(host, SFBR_REG); + struct NCR_700_command_slot *slot; + + /* Take out our own ID */ + reselection_id &= ~(1<this_id); + + printk(KERN_INFO "scsi%d: (%d:%d) RESELECTION DURING SELECTION, dsp=%p[%04x] state=%d, count=%d\n", + host->host_no, reselection_id, lun, (void *)dsp, dsp - hostdata->pScript, hostdata->state, hostdata->command_slot_count); + + { + /* FIXME: DEBUGGING CODE */ + __u32 SG = (__u32)bus_to_virt(hostdata->script[A_SGScriptStartAddress_used[0]]); + int i; + + for(i=0; i< NCR_700_COMMAND_SLOTS_PER_HOST; i++) { + if(SG >= (__u32)(&hostdata->slots[i].SG[0]) + && SG <= (__u32)(&hostdata->slots[i].SG[NCR_700_SG_SEGMENTS])) + break; + } + printk(KERN_INFO "IDENTIFIED SG segment as being %p in slot %p, cmd %p, slot->resume_offset=%p\n", (void *)SG, &hostdata->slots[i], hostdata->slots[i].cmnd, (void *)hostdata->slots[i].resume_offset); + SCp = hostdata->slots[i].cmnd; + } + + if(SCp != NULL) { + slot = (struct NCR_700_command_slot *)SCp->host_scribble; + /* change slot from busy to queued to redo command */ + slot->state = NCR_700_SLOT_QUEUED; + } + hostdata->cmd = NULL; + + if(reselection_id == 0) { + if(hostdata->reselection_id == 0xff) { + printk(KERN_ERR "scsi%d: Invalid reselection during selection!!\n", host->host_no); + return 0; + } else { + printk(KERN_ERR "scsi%d: script reselected and we took a selection interrupt\n", + host->host_no); + reselection_id = hostdata->reselection_id; + } + } else { + + /* convert to real ID */ + reselection_id = bitmap_to_number(reselection_id); + } + hostdata->reselection_id = reselection_id; + hostdata->msgin[1] = 0; + dma_cache_wback((unsigned long)hostdata->msgin, sizeof(hostdata->msgin)); + if(hostdata->tag_negotiated & (1<pScript + Ent_GetReselectionWithTag; + } else { + resume_offset = hostdata->pScript + Ent_GetReselectionData; + } + } else if(dsps == A_COMPLETED_SELECTION_AS_TARGET) { + /* we've just disconnected from the bus, do nothing since + * a return here will re-run the queued command slot + * that may have been interrupted by the initial selection */ + DEBUG((" SELECTION COMPLETED\n")); + } else if((dsps & 0xfffff0f0) == A_MSG_IN) { + resume_offset = process_message(host, hostdata, SCp, + dsp, dsps); + } else if((dsps & 0xfffff000) == 0) { + __u8 i = (dsps & 0xf0) >> 4, j = (dsps & 0xf00) >> 8; + printk(KERN_ERR "scsi%d: (%d:%d), unhandled script condition %s %s at %04x\n", + host->host_no, pun, lun, NCR_700_condition[i], + NCR_700_phase[j], dsp - hostdata->pScript); + if(SCp != NULL) { + print_command(SCp->cmnd); + + if(SCp->use_sg) { + for(i = 0; i < SCp->use_sg + 1; i++) { + printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); + } + } + } + NCR_700_internal_bus_reset(host); + } else if((dsps & 0xfffff000) == A_DEBUG_INTERRUPT) { + printk(KERN_NOTICE "scsi%d (%d:%d) DEBUG INTERRUPT %d AT %p[%04x], continuing\n", + host->host_no, pun, lun, dsps & 0xfff, (void *)dsp, dsp - hostdata->pScript); + resume_offset = dsp; + } else { + printk(KERN_ERR "scsi%d: (%d:%d), unidentified script interrupt 0x%x at %04x\n", + host->host_no, pun, lun, dsps, dsp - hostdata->pScript); + NCR_700_internal_bus_reset(host); + } + return resume_offset; +} + +/* We run the 53c700 with selection interrupts always enabled. This + * means that the chip may be selected as soon as the bus frees. On a + * busy bus, this can be before the scripts engine finishes its + * processing. Therefore, part of the selection processing has to be + * to find out what the scripts engine is doing and complete the + * function if necessary (i.e. process the pending disconnect or save + * the interrupted initial selection */ +STATIC inline __u32 +process_selection(struct Scsi_Host *host, __u32 dsp) +{ + __u8 id = 0; /* Squash compiler warning */ + int count = 0; + __u32 resume_offset = 0; + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + Scsi_Cmnd *SCp = hostdata->cmd; + __u8 sbcl; + + for(count = 0; count < 5; count++) { + id = NCR_700_readb(host, SFBR_REG); + + /* Take out our own ID */ + id &= ~(1<this_id); + if(id != 0) + break; + udelay(5); + } + sbcl = NCR_700_readb(host, SBCL_REG); + if((sbcl & SBCL_IO) == 0) { + /* mark as having been selected rather than reselected */ + id = 0xff; + } else { + /* convert to real ID */ + hostdata->reselection_id = id = bitmap_to_number(id); + DEBUG(("scsi%d: Reselected by %d\n", + host->host_no, id)); + } + if(hostdata->state == NCR_700_HOST_BUSY && SCp != NULL) { + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + DEBUG((" ID %d WARNING: RESELECTION OF BUSY HOST, saving cmd %p, slot %p, addr %x [%04x], resume %x!\n", id, hostdata->cmd, slot, dsp, dsp - hostdata->pScript, resume_offset)); + + switch(dsp - hostdata->pScript) { + case Ent_Disconnect1: + case Ent_Disconnect2: + save_for_reselection(hostdata, SCp, Ent_Disconnect2 + hostdata->pScript); + break; + case Ent_Disconnect3: + case Ent_Disconnect4: + save_for_reselection(hostdata, SCp, Ent_Disconnect4 + hostdata->pScript); + break; + case Ent_Disconnect5: + case Ent_Disconnect6: + save_for_reselection(hostdata, SCp, Ent_Disconnect6 + hostdata->pScript); + break; + case Ent_Disconnect7: + case Ent_Disconnect8: + save_for_reselection(hostdata, SCp, Ent_Disconnect8 + hostdata->pScript); + break; + case Ent_Finish1: + case Ent_Finish2: + process_script_interrupt(A_GOOD_STATUS_AFTER_STATUS, dsp, SCp, host, hostdata); + break; + + default: + slot->state = NCR_700_SLOT_QUEUED; + break; + } + } + hostdata->state = NCR_700_HOST_BUSY; + hostdata->cmd = NULL; + hostdata->msgin[1] = 0; + dma_cache_wback((unsigned long)hostdata->msgin, sizeof(hostdata->msgin)); + + if(id == 0xff) { + /* Selected as target, Ignore */ + resume_offset = hostdata->pScript + Ent_SelectedAsTarget; + } else if(hostdata->tag_negotiated & (1<pScript + Ent_GetReselectionWithTag; + } else { + resume_offset = hostdata->pScript + Ent_GetReselectionData; + } + return resume_offset; +} + + +STATIC int +NCR_700_start_command(Scsi_Cmnd *SCp) +{ + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SCp->host->hostdata[0]; + unsigned long flags; + __u16 count = 1; /* for IDENTIFY message */ + + save_flags(flags); + cli(); + if(hostdata->state != NCR_700_HOST_FREE) { + /* keep this inside the lock to close the race window where + * the running command finishes on another CPU while we don't + * change the state to queued on this one */ + slot->state = NCR_700_SLOT_QUEUED; + restore_flags(flags); + + DEBUG(("scsi%d: host busy, queueing command %p, slot %p\n", + SCp->host->host_no, slot->cmnd, slot)); + return 0; + } + hostdata->state = NCR_700_HOST_BUSY; + hostdata->cmd = SCp; + slot->state = NCR_700_SLOT_BUSY; + /* keep interrupts disabled until we have the command correctly + * set up so we cannot take a selection interrupt */ + + hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE, + SCp->lun); + /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure + * if the negotiated transfer parameters still hold, so + * always renegotiate them */ + if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE) { + NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); + } + + /* REQUEST_SENSE is asking for contingent I_T_L status. If a + * contingent allegiance condition exists, the device will + * refuse all tags, so send the request sense as untagged */ + if((hostdata->tag_negotiated & (1<target)) + && (slot->tag != NCR_700_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) { + hostdata->msgout[count++] = A_SIMPLE_TAG_MSG; + hostdata->msgout[count++] = slot->tag; + } + + if(hostdata->fast && + NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { + memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, + sizeof(NCR_700_SDTR_msg)); + count += sizeof(NCR_700_SDTR_msg); + NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + } + + dma_cache_wback((unsigned long)hostdata->msgout, count); + + script_patch_16(hostdata->script, MessageCount, count); + + + script_patch_ID(hostdata->script, + Device_ID, 1<target); + + script_patch_32_abs(hostdata->script, CommandAddress, + virt_to_bus(SCp->cmnd)); + script_patch_16(hostdata->script, CommandCount, SCp->cmd_len); + /* finally plumb the beginning of the SG list into the script + * */ + script_patch_32_abs(hostdata->script, SGScriptStartAddress, + virt_to_bus(&slot->SG[0].ins)); + NCR_700_writeb(CLR_FIFO, SCp->host, DFIFO_REG); + + /* set the synchronous period/offset */ + if(slot->resume_offset == 0) + slot->resume_offset = hostdata->pScript; + NCR_700_writeb(NCR_700_get_SXFER(SCp->device), + SCp->host, SXFER_REG); + /* allow interrupts here so that if we're selected we can take + * a selection interrupt. The script start may not be + * effective in this case, but the selection interrupt will + * save our command in that case */ + NCR_700_writel(slot->temp, SCp->host, TEMP_REG); + NCR_700_writel(slot->resume_offset, SCp->host, DSP_REG); + restore_flags(flags); + + return 1; +} + +void +NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct Scsi_Host *host = (struct Scsi_Host *)dev_id; + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + __u8 istat; + __u32 resume_offset = 0; + __u8 pun = 0xff, lun = 0xff; + unsigned long flags; + + /* Unfortunately, we have to take the io_request_lock here + * rather than the host lock hostdata->lock because we're + * looking to exclude queuecommand from messing with the + * registers while we're processing the interrupt. Since + * queuecommand is called holding io_request_lock, and we have + * to take io_request_lock before we call the command + * scsi_done, we would get a deadlock if we took + * hostdata->lock here and in queuecommand (because the order + * of locking in queuecommand: 1) io_request_lock then 2) + * hostdata->lock would be the reverse of taking it in this + * routine */ + spin_lock_irqsave(&io_request_lock, flags); + if((istat = NCR_700_readb(host, ISTAT_REG)) + & (SCSI_INT_PENDING | DMA_INT_PENDING)) { + __u32 dsps; + __u8 sstat0 = 0, dstat = 0; + __u32 dsp; + Scsi_Cmnd *SCp = hostdata->cmd; + enum NCR_700_Host_State state; + + state = hostdata->state; + SCp = hostdata->cmd; + + if(istat & SCSI_INT_PENDING) { + udelay(10); + + sstat0 = NCR_700_readb(host, SSTAT0_REG); + } + + if(istat & DMA_INT_PENDING) { + udelay(10); + + dstat = NCR_700_readb(host, DSTAT_REG); + } + + dsps = NCR_700_readl(host, DSPS_REG); + dsp = NCR_700_readl(host, DSP_REG); + + DEBUG(("scsi%d: istat %02x sstat0 %02x dstat %02x dsp %04x[%08x] dsps 0x%x\n", + host->host_no, istat, sstat0, dstat, + (dsp - (__u32)virt_to_bus(hostdata->script))/4, + dsp, dsps)); + + if(SCp != NULL) { + pun = SCp->target; + lun = SCp->lun; + } + + if(sstat0 & SCSI_RESET_DETECTED) { + Scsi_Device *SDp; + int i; + + hostdata->state = NCR_700_HOST_BUSY; + + printk(KERN_ERR "scsi%d: Bus Reset detected, executing command %p, slot %p, dsp %p[%04x]\n", + host->host_no, SCp, SCp == NULL ? NULL : SCp->host_scribble, (void *)dsp, dsp - hostdata->pScript); + + /* clear all the negotiated parameters */ + for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) + SDp->hostdata = 0; + + /* clear all the slots and their pending commands */ + for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { + Scsi_Cmnd *SCp; + struct NCR_700_command_slot *slot = + &hostdata->slots[i]; + + if(slot->state == NCR_700_SLOT_FREE) + continue; + + SCp = slot->cmnd; + printk(KERN_ERR " failing command because of reset, slot %p, cmnd %p\n", + slot, SCp); + free_slot(slot, hostdata); + SCp->host_scribble = NULL; + NCR_700_set_depth(SCp->device, 0); + /* NOTE: deadlock potential here: we + * rely on mid-layer guarantees that + * scsi_done won't try to issue the + * command again otherwise we'll + * deadlock on the + * hostdata->state_lock */ + SCp->result = DID_RESET << 16; + SCp->scsi_done(SCp); + } + mdelay(25); + NCR_700_chip_setup(host); + + hostdata->state = NCR_700_HOST_FREE; + hostdata->cmd = NULL; + goto out_unlock; + } else if(sstat0 & SELECTION_TIMEOUT) { + DEBUG(("scsi%d: (%d:%d) selection timeout\n", + host->host_no, pun, lun)); + NCR_700_scsi_done(hostdata, SCp, DID_NO_CONNECT<<16); + } else if(sstat0 & PHASE_MISMATCH) { + struct NCR_700_command_slot *slot = (SCp == NULL) ? NULL : + (struct NCR_700_command_slot *)SCp->host_scribble; + + if(dsp == Ent_SendMessage + 8 + hostdata->pScript) { + /* It wants to reply to some part of + * our message */ +#ifdef NCR_700_DEBUG + __u32 temp = NCR_700_readl(host, TEMP_REG); + int count = (hostdata->script[Ent_SendMessage/4] & 0xffffff) - ((NCR_700_readl(host, DBC_REG) & 0xffffff) + NCR_700_data_residual(host)); + printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG))); +#endif + resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch; + } else if(dsp >= virt_to_bus(&slot->SG[0].ins) && + dsp <= virt_to_bus(&slot->SG[NCR_700_SG_SEGMENTS].ins)) { + int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff; + int SGcount = (dsp - virt_to_bus(&slot->SG[0].ins))/sizeof(struct NCR_700_SG_List); + int residual = NCR_700_data_residual(host); + int i; +#ifdef NCR_700_DEBUG + printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x\n", + host->host_no, pun, lun, + SGcount, data_transfer); + print_command(SCp->cmnd); + if(residual) { + printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x, residual %d\n", + host->host_no, pun, lun, + SGcount, data_transfer, residual); + } +#endif + data_transfer += residual; + + if(data_transfer != 0) { + int count; + __u32 pAddr; + + SGcount--; + + count = (bS_to_cpu(slot->SG[SGcount].ins) & 0x00ffffff); + DEBUG(("DATA TRANSFER MISMATCH, count = %d, transferred %d\n", count, count-data_transfer)); + slot->SG[SGcount].ins &= bS_to_host(0xff000000); + slot->SG[SGcount].ins |= bS_to_host(data_transfer); + pAddr = bS_to_cpu(slot->SG[SGcount].pAddr); + pAddr += (count - data_transfer); + slot->SG[SGcount].pAddr = bS_to_host(pAddr); + } + /* set the executed moves to nops */ + for(i=0; iSG[i].ins = bS_to_host(SCRIPT_NOP); + slot->SG[i].pAddr = 0; + } + dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG)); + /* and pretend we disconnected after + * the command phase */ + resume_offset = hostdata->pScript + Ent_MsgInDuringData; + } else { + __u8 sbcl = NCR_700_readb(host, SBCL_REG); + printk(KERN_ERR "scsi%d: (%d:%d) phase mismatch at %04x, phase %s\n", + host->host_no, pun, lun, dsp - hostdata->pScript, sbcl_to_string(sbcl)); + NCR_700_internal_bus_reset(host); + } + + } else if(sstat0 & SCSI_GROSS_ERROR) { + printk(KERN_ERR "scsi%d: (%d:%d) GROSS ERROR\n", + host->host_no, pun, lun); + NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16); + } else if(dstat & SCRIPT_INT_RECEIVED) { + DEBUG(("scsi%d: (%d:%d) ====>SCRIPT INTERRUPT<====\n", + host->host_no, pun, lun)); + resume_offset = process_script_interrupt(dsps, dsp, SCp, host, hostdata); + } else if(dstat & (ILGL_INST_DETECTED)) { + printk(KERN_ERR "scsi%d: (%d:%d) Illegal Instruction detected at 0x%p[0x%x]!!!\n" + " Please email James.Bottomley@HansenPartnership.com with the details\n", + host->host_no, pun, lun, + (void *)dsp, dsp - hostdata->pScript); + NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16); + } else if(dstat & (WATCH_DOG_INTERRUPT|ABORTED)) { + printk(KERN_ERR "scsi%d: (%d:%d) serious DMA problem, dstat=%02x\n", + host->host_no, pun, lun, dstat); + NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16); + } + + + /* NOTE: selection interrupt processing MUST occur + * after script interrupt processing to correctly cope + * with the case where we process a disconnect and + * then get reselected before we process the + * disconnection */ + if(sstat0 & SELECTED) { + /* FIXME: It currently takes at least FOUR + * interrupts to complete a command that + * disconnects: one for the disconnect, one + * for the reselection, one to get the + * reselection data and one to complete the + * command. If we guess the reselected + * command here and prepare it, we only need + * to get a reselection data interrupt if we + * guessed wrongly. Since the interrupt + * overhead is much greater than the command + * setup, this would be an efficient + * optimisation particularly as we probably + * only have one outstanding command on a + * target most of the time */ + + resume_offset = process_selection(host, dsp); + + } + + } + + if(resume_offset) { + if(hostdata->state != NCR_700_HOST_BUSY) { + printk(KERN_ERR "scsi%d: Driver error: resume at %p [%04x] with non busy host!\n", + host->host_no, (void *)resume_offset, resume_offset - hostdata->pScript); + hostdata->state = NCR_700_HOST_BUSY; + } + + DEBUG(("Attempting to resume at %x\n", resume_offset)); + NCR_700_writeb(CLR_FIFO, host, DFIFO_REG); + NCR_700_writel(resume_offset, host, DSP_REG); + } + /* There is probably a technical no-no about this: If we're a + * shared interrupt and we got this interrupt because the + * other device needs servicing not us, we're still going to + * check our queued commands here---of course, there shouldn't + * be any outstanding.... */ + if(hostdata->state == NCR_700_HOST_FREE) { + int i; + + for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { + /* fairness: always run the queue from the last + * position we left off */ + int j = (i + hostdata->saved_slot_position) + % NCR_700_COMMAND_SLOTS_PER_HOST; + + if(hostdata->slots[j].state != NCR_700_SLOT_QUEUED) + continue; + if(NCR_700_start_command(hostdata->slots[j].cmnd)) { + DEBUG(("scsi%d: Issuing saved command slot %p, cmd %p\t\n", + host->host_no, &hostdata->slots[j], + hostdata->slots[j].cmnd)); + hostdata->saved_slot_position = j + 1; + } + + break; + } + } + out_unlock: + spin_unlock_irqrestore(&io_request_lock, flags); +} + +/* FIXME: Need to put some proc information in and plumb it + * into the scsi proc system */ +STATIC int +NCR_700_proc_directory_info(char *proc_buf, char **startp, + off_t offset, int bytes_available, + int host_no, int write) +{ + static char buf[4096]; /* 1 page should be sufficient */ + int len = 0; + struct Scsi_Host *host = scsi_hostlist; + struct NCR_700_Host_Parameters *hostdata; + Scsi_Device *SDp; + + while(host != NULL && host->host_no != host_no) + host = host->next; + + if(host == NULL) + return 0; + + if(write) { + /* FIXME: Clear internal statistics here */ + return 0; + } + hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + len += sprintf(&buf[len], "Total commands outstanding: %d\n", hostdata->command_slot_count); + len += sprintf(&buf[len],"\ +Target Depth Active Next Tag\n\ +====== ===== ====== ========\n"); + for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) { + len += sprintf(&buf[len]," %2d:%2d %4d %4d %4d\n", SDp->id, SDp->lun, SDp->queue_depth, NCR_700_get_depth(SDp), SDp->current_tag); + } + if((len -= offset) <= 0) + return 0; + if(len > bytes_available) + len = bytes_available; + memcpy(proc_buf, buf + offset, len); + return len; +} + +STATIC int +NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SCp->host->hostdata[0]; + __u32 move_ins; + struct NCR_700_command_slot *slot; + int hash; + + if(hostdata->command_slot_count >= NCR_700_COMMAND_SLOTS_PER_HOST) { + /* We're over our allocation, this should never happen + * since we report the max allocation to the mid layer */ + printk(KERN_WARNING "scsi%d: Command depth has gone over queue depth\n", SCp->host->host_no); + return 1; + } + if(NCR_700_get_depth(SCp->device) != 0 && !(hostdata->tag_negotiated & (1<target))) { + DEBUG((KERN_ERR "scsi%d (%d:%d) has non zero depth %d\n", + SCp->host->host_no, SCp->target, SCp->lun, + NCR_700_get_depth(SCp->device))); + return 1; + } + if(NCR_700_get_depth(SCp->device) >= NCR_700_MAX_TAGS) { + DEBUG((KERN_ERR "scsi%d (%d:%d) has max tag depth %d\n", + SCp->host->host_no, SCp->target, SCp->lun, + NCR_700_get_depth(SCp->device))); + return 1; + } + NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1); + + /* begin the command here */ + /* no need to check for NULL, test for command_slot_cound above + * ensures a slot is free */ + slot = find_empty_slot(hostdata); + + slot->cmnd = SCp; + + SCp->scsi_done = done; + SCp->host_scribble = (unsigned char *)slot; + SCp->SCp.ptr = NULL; + SCp->SCp.buffer = NULL; + +#ifdef NCR_700_DEBUG + printk("53c700: scsi%d, command ", SCp->host->host_no); + print_command(SCp->cmnd); +#endif + + if(hostdata->tag_negotiated &(1<target)) { + + struct NCR_700_command_slot *old = + find_ITL_Nexus(hostdata, SCp->target, SCp->lun); +#ifdef NCR_700_TAG_DEBUG + struct NCR_700_command_slot *found; +#endif + + if(old != NULL && old->tag == SCp->device->current_tag) { + printk(KERN_WARNING "scsi%d (%d:%d) Tag clock back to current, queueing\n", SCp->host->host_no, SCp->target, SCp->lun); + return 1; + } + slot->tag = SCp->device->current_tag++; +#ifdef NCR_700_TAG_DEBUG + while((found = find_ITLQ_Nexus(hostdata, SCp->target, SCp->lun, slot->tag)) != NULL) { + printk("\n\n**ERROR** already using tag %d, but oldest is %d\n", slot->tag, (old == NULL) ? -1 : old->tag); + printk(" FOUND = %p, tag = %d, pun = %d, lun = %d\n", + found, found->tag, found->cmnd->target, found->cmnd->lun); + slot->tag = SCp->device->current_tag++; + printk(" Tag list is: "); + while(old != NULL) { + if(old->cmnd->target == SCp->target && + old->cmnd->lun == SCp->lun) + printk("%d ", old->tag); + old = old->ITL_back; + } + printk("\n\n"); + } +#endif + hash = hash_ITLQ(SCp->target, SCp->lun, slot->tag); + /* link into the ITLQ hash queues */ + slot->ITLQ_forw = hostdata->ITLQ_Hash_forw[hash]; + hostdata->ITLQ_Hash_forw[hash] = slot; +#ifdef NCR_700_TAG_DEBUG + if(slot->ITLQ_forw != NULL && slot->ITLQ_forw->ITLQ_back != NULL) { + printk(KERN_ERR "scsi%d (%d:%d) ITLQ_back is not NULL!!!!\n", SCp->host->host_no, SCp->target, SCp->lun); + } +#endif + if(slot->ITLQ_forw != NULL) + slot->ITLQ_forw->ITLQ_back = slot; + else + hostdata->ITLQ_Hash_back[hash] = slot; + slot->ITLQ_back = NULL; + } else { + slot->tag = NCR_700_NO_TAG; + } + /* link into the ITL hash queues */ + hash = hash_ITL(SCp->target, SCp->lun); + slot->ITL_forw = hostdata->ITL_Hash_forw[hash]; + hostdata->ITL_Hash_forw[hash] = slot; +#ifdef NCR_700_TAG_DEBUG + if(slot->ITL_forw != NULL && slot->ITL_forw->ITL_back != NULL) { + printk(KERN_ERR "scsi%d (%d:%d) ITL_back is not NULL!!!!\n", + SCp->host->host_no, SCp->target, SCp->lun); + } +#endif + if(slot->ITL_forw != NULL) + slot->ITL_forw->ITL_back = slot; + else + hostdata->ITL_Hash_back[hash] = slot; + slot->ITL_back = NULL; + + + /* This is f****g ridiculous; every low level HBA driver has + * to determine the direction of the commands, why isn't this + * done inside the scsi_lib !!??? */ + switch (SCp->cmnd[0]) { + case REQUEST_SENSE: + /* clear the internal sense magic */ + SCp->cmnd[6] = 0; + /* fall through */ + case INQUIRY: + case MODE_SENSE: + case READ_6: + case READ_10: + case READ_12: + case READ_CAPACITY: + case READ_BLOCK_LIMITS: + case READ_TOC: + move_ins = SCRIPT_MOVE_DATA_IN; + break; + case MODE_SELECT: + case WRITE_6: + case WRITE_10: + case WRITE_12: + move_ins = SCRIPT_MOVE_DATA_OUT; + break; + case TEST_UNIT_READY: + case ALLOW_MEDIUM_REMOVAL: + case START_STOP: + move_ins = 0; + break; + default: + /* OK, get it from the command */ + switch(SCp->sc_data_direction) { + case SCSI_DATA_UNKNOWN: + default: + printk(KERN_ERR "53c700: Unknown command for data direction "); + print_command(SCp->cmnd); + + move_ins = 0; + break; + case SCSI_DATA_NONE: + move_ins = 0; + break; + case SCSI_DATA_READ: + move_ins = SCRIPT_MOVE_DATA_IN; + break; + case SCSI_DATA_WRITE: + move_ins = SCRIPT_MOVE_DATA_OUT; + break; + } + } + + /* now build the scatter gather list */ + if(move_ins != 0) { + int i; + + for(i = 0; i < (SCp->use_sg ? SCp->use_sg : 1); i++) { + void *vPtr; + __u32 count; + + if(SCp->use_sg) { + vPtr = (((struct scatterlist *)SCp->buffer)[i].address); + count = ((struct scatterlist *)SCp->buffer)[i].length; + } else { + vPtr = SCp->request_buffer; + count = SCp->request_bufflen; + } + slot->SG[i].ins = bS_to_host(move_ins | count); + DEBUG((" scatter block %d: move %d[%08x] from 0x%lx\n", + i, count, slot->SG[i].ins, + virt_to_bus(vPtr))); + dma_cache_wback_inv((unsigned long)vPtr, count); + slot->SG[i].pAddr = bS_to_host(virt_to_bus(vPtr)); + } + slot->SG[i].ins = bS_to_host(SCRIPT_RETURN); + slot->SG[i].pAddr = 0; + dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG)); + DEBUG((" SETTING %08lx to %x\n", + virt_to_bus(&slot->SG[i].ins), + slot->SG[i].ins)); + } + slot->resume_offset = 0; + NCR_700_start_command(SCp); + return 0; +} + +STATIC int +NCR_700_abort(Scsi_Cmnd * SCp) +{ + struct NCR_700_command_slot *slot; + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SCp->host->hostdata[0]; + + printk(KERN_INFO "scsi%d (%d:%d) New error handler wants to abort command\n\t", + SCp->host->host_no, SCp->target, SCp->lun); + print_command(SCp->cmnd); + + slot = find_ITL_Nexus(hostdata, SCp->target, SCp->lun); + while(slot != NULL && slot->cmnd != SCp) + slot = slot->ITL_back; + + if(slot == NULL) + /* no outstanding command to abort */ + return SUCCESS; + if(SCp->cmnd[0] == TEST_UNIT_READY) { + /* FIXME: This is because of a problem in the new + * error handler. When it is in error recovery, it + * will send a TUR to a device it thinks may still be + * showing a problem. If the TUR isn't responded to, + * it will abort it and mark the device off line. + * Unfortunately, it does no other error recovery, so + * this would leave us with an outstanding command + * occupying a slot. Rather than allow this to + * happen, we issue a bus reset to force all + * outstanding commands to terminate here. */ + NCR_700_internal_bus_reset(SCp->host); + /* still drop through and return failed */ + } + return FAILED; + +} + +STATIC int +NCR_700_bus_reset(Scsi_Cmnd * SCp) +{ + printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t", + SCp->host->host_no, SCp->target, SCp->lun, SCp); + print_command(SCp->cmnd); + NCR_700_internal_bus_reset(SCp->host); + return SUCCESS; +} + +STATIC int +NCR_700_dev_reset(Scsi_Cmnd * SCp) +{ + printk(KERN_INFO "scsi%d (%d:%d) New error handler wants device reset\n\t", + SCp->host->host_no, SCp->target, SCp->lun); + print_command(SCp->cmnd); + + return FAILED; +} + +STATIC int +NCR_700_host_reset(Scsi_Cmnd * SCp) +{ + printk(KERN_INFO "scsi%d (%d:%d) New error handler wants HOST reset\n\t", + SCp->host->host_no, SCp->target, SCp->lun); + print_command(SCp->cmnd); + + NCR_700_internal_bus_reset(SCp->host); + NCR_700_chip_reset(SCp->host); + return SUCCESS; +} + +EXPORT_SYMBOL(NCR_700_detect); +EXPORT_SYMBOL(NCR_700_release); +EXPORT_SYMBOL(NCR_700_intr); diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/53c700.c linux/drivers/scsi/53c700.c --- v2.4.9/linux/drivers/scsi/53c700.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/53c700.c Sun Sep 9 10:50:48 2001 @@ -0,0 +1,1840 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* NCR (or Symbios) 53c700 and 53c700-66 Driver + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.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. +** +**----------------------------------------------------------------------------- + */ + +/* Notes: + * + * This driver is designed exclusively for these chips (virtually the + * earliest of the scripts engine chips). They need their own drivers + * because they are missing so many of the scripts and snazzy register + * features of their elder brothers (the 710, 720 and 770). + * + * The 700 is the lowliest of the line, it can only do async SCSI. + * The 700-66 can at least do synchronous SCSI up to 10MHz. + * + * The 700 chip has no host bus interface logic of its own. However, + * it is usually mapped to a location with well defined register + * offsets. Therefore, if you can determine the base address and the + * irq your board incorporating this chip uses, you can probably use + * this driver to run it (although you'll probably have to write a + * minimal wrapper for the purpose---see the NCR_D700 driver for + * details about how to do this). + * + * + * TODO List: + * + * 1. Better statistics in the proc fs + * + * 2. Implement message queue (queues SCSI messages like commands) and make + * the abort and device reset functions use them. + * */ + +/* CHANGELOG + * + * Version 2.3 + * + * More endianness/cache coherency changes. + * + * Better bad device handling (handles devices lying about tag + * queueing support and devices which fail to provide sense data on + * contingent allegiance conditions) + * + * Many thanks to Richard Hirst for patiently + * debugging this driver on the parisc architecture and suggesting + * many improvements and bug fixes. + * + * Thanks also go to Linuxcare Inc. for providing several PARISC + * machines for me to debug the driver on. + * + * Version 2.2 + * + * Made the driver mem or io mapped; added endian invariance; added + * dma cache flushing operations for architectures which need it; + * added support for more varied clocking speeds. + * + * Version 2.1 + * + * Initial modularisation from the D700. See NCR_D700.c for the rest of + * the changelog. + * */ +#define NCR_700_VERSION "2.3" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "constants.h" + +#include "53c700.h" + +#ifdef NCR_700_DEBUG +#define STATIC +#else +#define STATIC static +#endif + +MODULE_AUTHOR("James Bottomley"); +MODULE_DESCRIPTION("53c700 and 53c700-66 Driver"); +MODULE_LICENSE("GPL"); + +/* This is the script */ +#include "53c700_d.h" + + +STATIC int NCR_700_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +STATIC int NCR_700_abort(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_bus_reset(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_dev_reset(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_host_reset(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_proc_directory_info(char *, char **, off_t, int, int, int); +STATIC void NCR_700_chip_setup(struct Scsi_Host *host); +STATIC void NCR_700_chip_reset(struct Scsi_Host *host); + +static char *NCR_700_phase[] = { + "", + "after selection", + "before command phase", + "after command phase", + "after status phase", + "after data in phase", + "after data out phase", + "during data phase", +}; + +static char *NCR_700_condition[] = { + "", + "NOT MSG_OUT", + "UNEXPECTED PHASE", + "NOT MSG_IN", + "UNEXPECTED MSG", + "MSG_IN", + "SDTR_MSG RECEIVED", + "REJECT_MSG RECEIVED", + "DISCONNECT_MSG RECEIVED", + "MSG_OUT", + "DATA_IN", + +}; + +static char *NCR_700_fatal_messages[] = { + "unexpected message after reselection", + "still MSG_OUT after message injection", + "not MSG_IN after selection", + "Illegal message length received", +}; + +static char *NCR_700_SBCL_bits[] = { + "IO ", + "CD ", + "MSG ", + "ATN ", + "SEL ", + "BSY ", + "ACK ", + "REQ ", +}; + +static char *NCR_700_SBCL_to_phase[] = { + "DATA_OUT", + "DATA_IN", + "CMD_OUT", + "STATE", + "ILLEGAL PHASE", + "ILLEGAL PHASE", + "MSG OUT", + "MSG IN", +}; + +static __u8 NCR_700_SDTR_msg[] = { + 0x01, /* Extended message */ + 0x03, /* Extended message Length */ + 0x01, /* SDTR Extended message */ + NCR_700_MIN_PERIOD, + NCR_700_MAX_OFFSET +}; + +struct Scsi_Host * __init +NCR_700_detect(Scsi_Host_Template *tpnt, + struct NCR_700_Host_Parameters *hostdata) +{ + __u32 *script = kmalloc(sizeof(SCRIPT), GFP_KERNEL); + __u32 pScript; + struct Scsi_Host *host; + static int banner = 0; + int j; + + /* Fill in the missing routines from the host template */ + tpnt->queuecommand = NCR_700_queuecommand; + tpnt->eh_abort_handler = NCR_700_abort; + tpnt->eh_device_reset_handler = NCR_700_dev_reset; + tpnt->eh_bus_reset_handler = NCR_700_bus_reset; + tpnt->eh_host_reset_handler = NCR_700_host_reset; + tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST; + tpnt->sg_tablesize = NCR_700_SG_SEGMENTS; + tpnt->cmd_per_lun = NCR_700_MAX_TAGS; + tpnt->use_clustering = DISABLE_CLUSTERING; + tpnt->use_new_eh_code = 1; + tpnt->proc_info = NCR_700_proc_directory_info; + + if(tpnt->name == NULL) + tpnt->name = "53c700"; + if(tpnt->proc_name == NULL) + tpnt->proc_name = "53c700"; + + + if((host = scsi_register(tpnt, 4)) == NULL) + return NULL; + if(script == NULL) { + printk(KERN_ERR "53c700: Failed to allocate script, detatching\n"); + scsi_unregister(host); + return NULL; + } + + hostdata->slots = kmalloc(sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST, GFP_KERNEL); + if(hostdata->slots == NULL) { + printk(KERN_ERR "53c700: Failed to allocate command slots, detatching\n"); + scsi_unregister(host); + return NULL; + } + memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST); + for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { + if(j == 0) + hostdata->free_list = &hostdata->slots[j]; + else + hostdata->slots[j-1].ITL_forw = &hostdata->slots[j]; + hostdata->slots[j].state = NCR_700_SLOT_FREE; + } + host->hostdata[0] = (__u32)hostdata; + for(j = 0; j < sizeof(SCRIPT)/sizeof(SCRIPT[0]); j++) { + script[j] = bS_to_host(SCRIPT[j]); + } + /* bus physical address of script */ + pScript = virt_to_bus(script); + /* adjust all labels to be bus physical */ + for(j = 0; j < PATCHES; j++) { + script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]); + } + /* now patch up fixed addresses */ + script_patch_32(script, MessageLocation, + virt_to_bus(&hostdata->msgout[0])); + script_patch_32(script, StatusAddress, + virt_to_bus(&hostdata->status)); + script_patch_32(script, ReceiveMsgAddress, + virt_to_bus(&hostdata->msgin[0])); + + hostdata->script = script; + hostdata->pScript = pScript; + hostdata->state = NCR_700_HOST_FREE; + spin_lock_init(&hostdata->lock); + hostdata->cmd = NULL; + host->max_id = 7; + host->max_lun = NCR_700_MAX_LUNS; + host->unique_id = hostdata->base; + host->base = hostdata->base; + host->hostdata[0] = (unsigned long)hostdata; + /* kick the chip */ + NCR_700_writeb(0xff, host, CTEST9_REG); + hostdata->rev = (NCR_700_readb(host, CTEST7_REG)<<4) & 0x0f; + hostdata->fast = (NCR_700_readb(host, CTEST9_REG) == 0); + if(banner == 0) { + printk(KERN_NOTICE "53c700: Version " NCR_700_VERSION " By James.Bottomley@HansenPartnership.com\n"); + banner = 1; + } + printk(KERN_NOTICE "scsi%d: %s rev %d %s\n", host->host_no, + hostdata->fast ? "53c700-66" : "53c700", + hostdata->rev, hostdata->differential ? + "(Differential)" : ""); + /* reset the chip */ + NCR_700_chip_reset(host); + NCR_700_writeb(ASYNC_OPERATION , host, SXFER_REG); + + return host; +} + +int +NCR_700_release(struct Scsi_Host *host) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + kfree(hostdata->script); + return 1; +} + +static inline __u8 +NCR_700_identify(int can_disconnect, __u8 lun) +{ + return IDENTIFY_BASE | + ((can_disconnect) ? 0x40 : 0) | + (lun & NCR_700_LUN_MASK); +} + +/* + * Function : static int datapath_residual (Scsi_Host *host) + * + * Purpose : return residual data count of what's in the chip. If you + * really want to know what this function is doing, it's almost a + * direct transcription of the algorithm described in the 53c710 + * guide, except that the DBC and DFIFO registers are only 6 bits + * wide. + * + * Inputs : host - SCSI host */ +static inline int +NCR_700_data_residual (struct Scsi_Host *host) { + int count, synchronous; + unsigned int ddir; + + count = ((NCR_700_readb(host, DFIFO_REG) & 0x3f) - + (NCR_700_readl(host, DBC_REG) & 0x3f)) & 0x3f; + + synchronous = NCR_700_readb(host, SXFER_REG) & 0x0f; + + /* get the data direction */ + ddir = NCR_700_readb(host, CTEST0_REG) & 0x01; + + if (ddir) { + /* Receive */ + if (synchronous) + count += (NCR_700_readb(host, SSTAT2_REG) & 0xf0) >> 4; + else + if (NCR_700_readb(host, SSTAT1_REG) & SIDL_REG_FULL) + ++count; + } else { + /* Send */ + __u8 sstat = NCR_700_readb(host, SSTAT1_REG); + if (sstat & SODL_REG_FULL) + ++count; + if (synchronous && (sstat & SODR_REG_FULL)) + ++count; + } + return count; +} + +/* print out the SCSI wires and corresponding phase from the SBCL register + * in the chip */ +static inline char * +sbcl_to_string(__u8 sbcl) +{ + int i; + static char ret[256]; + + ret[0]='\0'; + for(i=0; i<8; i++) { + if((1<free_list; + + if(slot == NULL) { + /* sanity check */ + if(hostdata->command_slot_count != NCR_700_COMMAND_SLOTS_PER_HOST) + printk(KERN_ERR "SLOTS FULL, but count is %d, should be %d\n", hostdata->command_slot_count, NCR_700_COMMAND_SLOTS_PER_HOST); + return NULL; + } + + if(slot->state != NCR_700_SLOT_FREE) + /* should panic! */ + printk(KERN_ERR "BUSY SLOT ON FREE LIST!!!\n"); + + + hostdata->free_list = slot->ITL_forw; + slot->ITL_forw = NULL; + + + /* NOTE: set the state to busy here, not queued, since this + * indicates the slot is in use and cannot be run by the IRQ + * finish routine. If we cannot queue the command when it + * is properly build, we then change to NCR_700_SLOT_QUEUED */ + slot->state = NCR_700_SLOT_BUSY; + hostdata->command_slot_count++; + + return slot; +} + +STATIC void +free_slot(struct NCR_700_command_slot *slot, + struct NCR_700_Host_Parameters *hostdata) +{ + int hash; + struct NCR_700_command_slot **forw, **back; + + + if((slot->state & NCR_700_SLOT_MASK) != NCR_700_SLOT_MAGIC) { + printk(KERN_ERR "53c700: SLOT %p is not MAGIC!!!\n", slot); + } + if(slot->state == NCR_700_SLOT_FREE) { + printk(KERN_ERR "53c700: SLOT %p is FREE!!!\n", slot); + } + /* remove from queues */ + if(slot->tag != NCR_700_NO_TAG) { + hash = hash_ITLQ(slot->cmnd->target, slot->cmnd->lun, + slot->tag); + if(slot->ITLQ_forw == NULL) + back = &hostdata->ITLQ_Hash_back[hash]; + else + back = &slot->ITLQ_forw->ITLQ_back; + + if(slot->ITLQ_back == NULL) + forw = &hostdata->ITLQ_Hash_forw[hash]; + else + forw = &slot->ITLQ_back->ITLQ_forw; + + *forw = slot->ITLQ_forw; + *back = slot->ITLQ_back; + } + hash = hash_ITL(slot->cmnd->target, slot->cmnd->lun); + if(slot->ITL_forw == NULL) + back = &hostdata->ITL_Hash_back[hash]; + else + back = &slot->ITL_forw->ITL_back; + + if(slot->ITL_back == NULL) + forw = &hostdata->ITL_Hash_forw[hash]; + else + forw = &slot->ITL_back->ITL_forw; + + *forw = slot->ITL_forw; + *back = slot->ITL_back; + + slot->resume_offset = 0; + slot->cmnd = NULL; + slot->state = NCR_700_SLOT_FREE; + slot->ITL_forw = hostdata->free_list; + hostdata->free_list = slot; + hostdata->command_slot_count--; +} + + +/* This routine really does very little. The command is indexed on + the ITL and (if tagged) the ITLQ lists in _queuecommand */ +STATIC void +save_for_reselection(struct NCR_700_Host_Parameters *hostdata, + Scsi_Cmnd *SCp, __u32 dsp) +{ + /* Its just possible that this gets executed twice */ + if(SCp != NULL) { + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + + slot->resume_offset = dsp; + } + hostdata->state = NCR_700_HOST_FREE; + hostdata->cmd = NULL; +} + +/* Most likely nexus is the oldest in each case */ +STATIC inline struct NCR_700_command_slot * +find_ITL_Nexus(struct NCR_700_Host_Parameters *hostdata, __u8 pun, __u8 lun) +{ + int hash = hash_ITL(pun, lun); + struct NCR_700_command_slot *slot = hostdata->ITL_Hash_back[hash]; + while(slot != NULL && !(slot->cmnd->target == pun && + slot->cmnd->lun == lun)) + slot = slot->ITL_back; + return slot; +} + +STATIC inline struct NCR_700_command_slot * +find_ITLQ_Nexus(struct NCR_700_Host_Parameters *hostdata, __u8 pun, + __u8 lun, __u8 tag) +{ + int hash = hash_ITLQ(pun, lun, tag); + struct NCR_700_command_slot *slot = hostdata->ITLQ_Hash_back[hash]; + + while(slot != NULL && !(slot->cmnd->target == pun + && slot->cmnd->lun == lun && slot->tag == tag)) + slot = slot->ITLQ_back; + +#ifdef NCR_700_TAG_DEBUG + if(slot != NULL) { + struct NCR_700_command_slot *n = slot->ITLQ_back; + while(n != NULL && n->cmnd->target != pun + && n->cmnd->lun != lun && n->tag != tag) + n = n->ITLQ_back; + + if(n != NULL && n->cmnd->target == pun && n->cmnd->lun == lun + && n->tag == tag) { + printk(KERN_WARNING "53c700: WARNING: DUPLICATE tag %d\n", + tag); + } + } +#endif + return slot; +} + + + +/* This translates the SDTR message offset and period to a value + * which can be loaded into the SXFER_REG. + * + * NOTE: According to SCSI-2, the true transfer period (in ns) is + * actually four times this period value */ +STATIC inline __u8 +NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata, + __u8 offset, __u8 period) +{ + int XFERP; + + if(period*4 < NCR_700_MIN_PERIOD) { + printk(KERN_WARNING "53c700: Period %dns is less than SCSI-2 minimum, setting to %d\n", period*4, NCR_700_MIN_PERIOD); + period = NCR_700_MIN_PERIOD/4; + } + XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; + if(offset > NCR_700_MAX_OFFSET) { + printk(KERN_WARNING "53c700: Offset %d exceeds maximum, setting to %d\n", + offset, NCR_700_MAX_OFFSET); + offset = NCR_700_MAX_OFFSET; + } + if(XFERP < NCR_700_MIN_XFERP) { + printk(KERN_WARNING "53c700: XFERP %d is less than minium, setting to %d\n", + XFERP, NCR_700_MIN_XFERP); + XFERP = NCR_700_MIN_XFERP; + } + return (offset & 0x0f) | (XFERP & 0x07)<<4; +} + + +STATIC inline void +NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, + Scsi_Cmnd *SCp, int result) +{ + hostdata->state = NCR_700_HOST_FREE; + hostdata->cmd = NULL; + + if(SCp != NULL) { + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + + if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) { +#ifdef NCR_700_DEBUG + printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is", + SCp, SCp->cmnd[7], result); + print_sense("53c700", SCp); +#endif + if(result == 0) + result = SCp->cmnd[7]; + } + + free_slot(slot, hostdata); + + SCp->host_scribble = NULL; + SCp->result = result; + SCp->scsi_done(SCp); + if(NCR_700_get_depth(SCp->device) == 0 || + NCR_700_get_depth(SCp->device) > NCR_700_MAX_TAGS) + printk(KERN_ERR "Invalid depth in NCR_700_scsi_done(): %d\n", + NCR_700_get_depth(SCp->device)); + NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) - 1); + } else { + printk(KERN_ERR "53c700: SCSI DONE HAS NULL SCp\n"); + } +} + + +STATIC void +NCR_700_internal_bus_reset(struct Scsi_Host *host) +{ + /* Bus reset */ + NCR_700_writeb(ASSERT_RST, host, SCNTL1_REG); + udelay(50); + NCR_700_writeb(0, host, SCNTL1_REG); + +} + +STATIC void +NCR_700_chip_setup(struct Scsi_Host *host) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + NCR_700_writeb(1 << host->this_id, host, SCID_REG); + NCR_700_writeb(0, host, SBCL_REG); + NCR_700_writeb(0, host, SXFER_REG); + + NCR_700_writeb(PHASE_MM_INT | SEL_TIMEOUT_INT | GROSS_ERR_INT | UX_DISC_INT + | RST_INT | PAR_ERR_INT | SELECT_INT, host, SIEN_REG); + + NCR_700_writeb(ABORT_INT | INT_INST_INT | ILGL_INST_INT, host, DIEN_REG); + NCR_700_writeb(BURST_LENGTH_8, host, DMODE_REG); + NCR_700_writeb(FULL_ARBITRATION | PARITY | AUTO_ATN, host, SCNTL0_REG); + NCR_700_writeb(LAST_DIS_ENBL | ENABLE_ACTIVE_NEGATION|GENERATE_RECEIVE_PARITY, + host, CTEST8_REG); + NCR_700_writeb(ENABLE_SELECT, host, SCNTL1_REG); + if(hostdata->clock > 75) { + printk(KERN_ERR "53c700: Clock speed %dMHz is too high: 75Mhz is the maximum this chip can be driven at\n", hostdata->clock); + /* do the best we can, but the async clock will be out + * of spec: sync divider 2, async divider 3 */ + DEBUG(("53c700: sync 2 async 3\n")); + NCR_700_writeb(SYNC_DIV_2_0, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_3_0, host, DCNTL_REG); + hostdata->sync_clock = hostdata->clock/2; + } else if(hostdata->clock > 50 && hostdata->clock <= 75) { + /* sync divider 1.5, async divider 3 */ + DEBUG(("53c700: sync 1.5 async 3\n")); + NCR_700_writeb(SYNC_DIV_1_5, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_3_0, host, DCNTL_REG); + hostdata->sync_clock = hostdata->clock*2; + hostdata->sync_clock /= 3; + + } else if(hostdata->clock > 37 && hostdata->clock <= 50) { + /* sync divider 1, async divider 2 */ + DEBUG(("53c700: sync 1 async 2\n")); + NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_2_0, host, DCNTL_REG); + hostdata->sync_clock = hostdata->clock; + } else if(hostdata->clock > 25 && hostdata->clock <=37) { + /* sync divider 1, async divider 1.5 */ + DEBUG(("53c700: sync 1 async 1.5\n")); + NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_1_5, host, DCNTL_REG); + hostdata->sync_clock = hostdata->clock; + } else { + DEBUG(("53c700: sync 1 async 1\n")); + NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG); + NCR_700_writeb(ASYNC_DIV_1_0, host, DCNTL_REG); + /* sync divider 1, async divider 1 */ + } +} + +STATIC void +NCR_700_chip_reset(struct Scsi_Host *host) +{ + /* Chip reset */ + NCR_700_writeb(SOFTWARE_RESET, host, DCNTL_REG); + udelay(100); + + NCR_700_writeb(0, host, DCNTL_REG); + + mdelay(1000); + + NCR_700_chip_setup(host); +} + +/* The heart of the message processing engine is that the instruction + * immediately after the INT is the normal case (and so must be CLEAR + * ACK). If we want to do something else, we call that routine in + * scripts and set temp to be the normal case + 8 (skipping the CLEAR + * ACK) so that the routine returns correctly to resume its activity + * */ +STATIC __u32 +process_extended_message(struct Scsi_Host *host, + struct NCR_700_Host_Parameters *hostdata, + Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps) +{ + __u32 resume_offset = dsp, temp = dsp + 8; + __u8 pun = 0xff, lun = 0xff; + + if(SCp != NULL) { + pun = SCp->target; + lun = SCp->lun; + } + + switch(hostdata->msgin[2]) { + case A_SDTR_MSG: + if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { + __u8 period = hostdata->msgin[3]; + __u8 offset = hostdata->msgin[4]; + __u8 sxfer; + + if(offset != 0 && period != 0) + sxfer = NCR_700_offset_period_to_sxfer(hostdata, offset, period); + else + sxfer = 0; + + if(sxfer != NCR_700_get_SXFER(SCp->device)) { + printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n", + host->host_no, pun, lun, + offset, period*4); + + NCR_700_set_SXFER(SCp->device, sxfer); + } + + + NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + + NCR_700_writeb(NCR_700_get_SXFER(SCp->device), + host, SXFER_REG); + + } else { + /* SDTR message out of the blue, reject it */ + printk(KERN_WARNING "scsi%d Unexpected SDTR msg\n", + host->host_no); + hostdata->msgout[0] = A_REJECT_MSG; + dma_cache_wback((unsigned long)hostdata->msgout, sizeof(hostdata->msgout)); + script_patch_16(hostdata->script, MessageCount, 1); + /* SendMsgOut returns, so set up the return + * address */ + resume_offset = hostdata->pScript + Ent_SendMessageWithATN; + } + break; + + case A_WDTR_MSG: + printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n", + host->host_no, pun, lun); + hostdata->msgout[0] = A_REJECT_MSG; + dma_cache_wback((unsigned long)hostdata->msgout, sizeof(hostdata->msgout)); + script_patch_16(hostdata->script, MessageCount, 1); + resume_offset = hostdata->pScript + Ent_SendMessageWithATN; + + break; + + default: + printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ", + host->host_no, pun, lun, + NCR_700_phase[(dsps & 0xf00) >> 8]); + print_msg(hostdata->msgin); + printk("\n"); + /* just reject it */ + hostdata->msgout[0] = A_REJECT_MSG; + dma_cache_wback((unsigned long)hostdata->msgout, sizeof(hostdata->msgout)); + script_patch_16(hostdata->script, MessageCount, 1); + /* SendMsgOut returns, so set up the return + * address */ + resume_offset = hostdata->pScript + Ent_SendMessageWithATN; + } + NCR_700_writel(temp, host, TEMP_REG); + return resume_offset; +} + +STATIC __u32 +process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata, + Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps) +{ + /* work out where to return to */ + __u32 temp = dsp + 8, resume_offset = dsp; + __u8 pun = 0xff, lun = 0xff; + + dma_cache_inv((unsigned long)hostdata->msgin, sizeof(hostdata->msgin)); + + if(SCp != NULL) { + pun = SCp->target; + lun = SCp->lun; + } + +#ifdef NCR_700_DEBUG + printk("scsi%d (%d:%d): message %s: ", host->host_no, pun, lun, + NCR_700_phase[(dsps & 0xf00) >> 8]); + print_msg(hostdata->msgin); + printk("\n"); +#endif + + switch(hostdata->msgin[0]) { + + case A_EXTENDED_MSG: + return process_extended_message(host, hostdata, SCp, + dsp, dsps); + + case A_REJECT_MSG: + if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { + /* Rejected our sync negotiation attempt */ + NCR_700_set_SXFER(SCp->device, 0); + NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + } else if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { + /* rejected our first simple tag message */ + printk(KERN_WARNING "scsi%d (%d:%d) Rejected first tag queue attempt, turning off tag queueing\n", host->host_no, pun, lun); + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + hostdata->tag_negotiated &= ~(1<target); + } else { + printk(KERN_WARNING "scsi%d (%d:%d) Unexpected REJECT Message %s\n", + host->host_no, pun, lun, + NCR_700_phase[(dsps & 0xf00) >> 8]); + /* however, just ignore it */ + } + break; + + case A_PARITY_ERROR_MSG: + printk(KERN_ERR "scsi%d (%d:%d) Parity Error!\n", host->host_no, + pun, lun); + NCR_700_internal_bus_reset(host); + break; + case A_SIMPLE_TAG_MSG: + printk(KERN_INFO "scsi%d (%d:%d) SIMPLE TAG %d %s\n", host->host_no, + pun, lun, hostdata->msgin[1], + NCR_700_phase[(dsps & 0xf00) >> 8]); + /* just ignore it */ + break; + default: + printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ", + host->host_no, pun, lun, + NCR_700_phase[(dsps & 0xf00) >> 8]); + + print_msg(hostdata->msgin); + printk("\n"); + /* just reject it */ + hostdata->msgout[0] = A_REJECT_MSG; + dma_cache_wback((unsigned long)hostdata->msgout, sizeof(hostdata->msgout)); + script_patch_16(hostdata->script, MessageCount, 1); + /* SendMsgOut returns, so set up the return + * address */ + resume_offset = hostdata->pScript + Ent_SendMessageWithATN; + + break; + } + NCR_700_writel(temp, host, TEMP_REG); + return resume_offset; +} + +STATIC __u32 +process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, + struct Scsi_Host *host, + struct NCR_700_Host_Parameters *hostdata) +{ + __u32 resume_offset = 0; + __u8 pun = 0xff, lun=0xff; + + if(SCp != NULL) { + pun = SCp->target; + lun = SCp->lun; + } + + if(dsps == A_GOOD_STATUS_AFTER_STATUS) { + dma_cache_inv((unsigned long)hostdata->status, sizeof(hostdata->status)); + DEBUG((" COMMAND COMPLETE, status=%02x\n", + hostdata->status)); + /* OK, if TCQ still on, we know it works */ + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + /* check for contingent allegiance contitions */ + if(status_byte(hostdata->status) == CHECK_CONDITION || + status_byte(hostdata->status) == COMMAND_TERMINATED) { + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + if(SCp->cmnd[0] == REQUEST_SENSE) { + /* OOPS: bad device, returning another + * contingent allegiance condition */ + printk(KERN_ERR "scsi%d (%d:%d) broken device is looping in contingent allegiance: ignoring\n", host->host_no, pun, lun); + NCR_700_scsi_done(hostdata, SCp, hostdata->status); + } else { + + DEBUG((" cmd %p has status %d, requesting sense\n", + SCp, hostdata->status)); + /* we can destroy the command here because the + * contingent allegiance condition will cause a + * retry which will re-copy the command from the + * saved data_cmnd */ + SCp->cmnd[0] = REQUEST_SENSE; + SCp->cmnd[1] = (SCp->lun & 0x7) << 5; + SCp->cmnd[2] = 0; + SCp->cmnd[3] = 0; + SCp->cmnd[4] = sizeof(SCp->sense_buffer); + SCp->cmnd[5] = 0; + SCp->cmd_len = 6; + /* Here's a quiet hack: the REQUEST_SENSE command is + * six bytes, so store a flag indicating that this + * was an internal sense request and the original + * status at the end of the command */ + SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; + SCp->cmnd[7] = hostdata->status; + slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); + slot->SG[0].pAddr = bS_to_host(virt_to_bus(SCp->sense_buffer)); + slot->SG[1].ins = bS_to_host(SCRIPT_RETURN); + slot->SG[1].pAddr = 0; + slot->resume_offset = hostdata->pScript; + dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG[0])*2); + dma_cache_inv((unsigned long)SCp->sense_buffer, sizeof(SCp->sense_buffer)); + + /* queue the command for reissue */ + slot->state = NCR_700_SLOT_QUEUED; + hostdata->state = NCR_700_HOST_FREE; + hostdata->cmd = NULL; + } + } else { + if(status_byte(hostdata->status) == GOOD && + SCp->cmnd[0] == INQUIRY && SCp->use_sg == 0) { + /* Piggy back the tag queueing support + * on this command */ + if(((char *)SCp->request_buffer)[7] & 0x02) { + printk(KERN_INFO "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", host->host_no, pun, lun); + hostdata->tag_negotiated |= (1<target); + NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + } else { + NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + hostdata->tag_negotiated &= ~(1<target); + } + } + NCR_700_scsi_done(hostdata, SCp, hostdata->status); + } + } else if((dsps & 0xfffff0f0) == A_UNEXPECTED_PHASE) { + __u8 i = (dsps & 0xf00) >> 8; + + printk(KERN_ERR "scsi%d: (%d:%d), UNEXPECTED PHASE %s (%s)\n", + host->host_no, pun, lun, + NCR_700_phase[i], + sbcl_to_string(NCR_700_readb(host, SBCL_REG))); + printk(KERN_ERR " len = %d, cmd =", SCp->cmd_len); + print_command(SCp->cmnd); + + NCR_700_internal_bus_reset(host); + } else if((dsps & 0xfffff000) == A_FATAL) { + int i = (dsps & 0xfff); + + printk(KERN_ERR "scsi%d: (%d:%d) FATAL ERROR: %s\n", + host->host_no, pun, lun, NCR_700_fatal_messages[i]); + if(dsps == A_FATAL_ILLEGAL_MSG_LENGTH) { + printk(KERN_ERR " msg begins %02x %02x\n", + hostdata->msgin[0], hostdata->msgin[1]); + } + NCR_700_internal_bus_reset(host); + } else if((dsps & 0xfffff0f0) == A_DISCONNECT) { +#ifdef NCR_700_DEBUG + __u8 i = (dsps & 0xf00) >> 8; + + printk("scsi%d: (%d:%d), DISCONNECTED (%d) %s\n", + host->host_no, pun, lun, + i, NCR_700_phase[i]); +#endif + save_for_reselection(hostdata, SCp, dsp); + + } else if(dsps == A_RESELECTION_IDENTIFIED) { + __u8 lun; + struct NCR_700_command_slot *slot; + __u8 reselection_id = hostdata->reselection_id; + + dma_cache_inv((unsigned long)hostdata->msgin, sizeof(hostdata->msgin)); + + lun = hostdata->msgin[0] & 0x1f; + + hostdata->reselection_id = 0xff; + DEBUG(("scsi%d: (%d:%d) RESELECTED!\n", + host->host_no, reselection_id, lun)); + /* clear the reselection indicator */ + if(hostdata->msgin[1] == A_SIMPLE_TAG_MSG) { + slot = find_ITLQ_Nexus(hostdata, reselection_id, + lun, hostdata->msgin[2]); + } else { + slot = find_ITL_Nexus(hostdata, reselection_id, lun); + } + retry: + if(slot == NULL) { + struct NCR_700_command_slot *s = find_ITL_Nexus(hostdata, reselection_id, lun); + printk(KERN_ERR "scsi%d: (%d:%d) RESELECTED but no saved command (MSG = %02x %02x %02x)!!\n", + host->host_no, reselection_id, lun, + hostdata->msgin[0], hostdata->msgin[1], + hostdata->msgin[2]); + printk(KERN_ERR " OUTSTANDING TAGS:"); + while(s != NULL) { + if(s->cmnd->target == reselection_id && + s->cmnd->lun == lun) { + printk("%d ", s->tag); + if(s->tag == hostdata->msgin[2]) { + printk(" ***FOUND*** \n"); + slot = s; + goto retry; + } + + } + s = s->ITL_back; + } + printk("\n"); + } else { + if(hostdata->state != NCR_700_HOST_BUSY) + printk(KERN_ERR "scsi%d: FATAL, host not busy during valid reselection!\n", + host->host_no); + resume_offset = slot->resume_offset; + hostdata->cmd = slot->cmnd; + + /* re-patch for this command */ + script_patch_32_abs(hostdata->script, CommandAddress, + virt_to_bus(slot->cmnd->cmnd)); + script_patch_16(hostdata->script, + CommandCount, slot->cmnd->cmd_len); + script_patch_32_abs(hostdata->script, SGScriptStartAddress, + virt_to_bus(&slot->SG[0].ins)); + + /* Note: setting SXFER only works if we're + * still in the MESSAGE phase, so it is vital + * that ACK is still asserted when we process + * the reselection message. The resume offset + * should therefore always clear ACK */ + NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device), + host, SXFER_REG); + + } + } else if(dsps == A_RESELECTED_DURING_SELECTION) { + + /* This section is full of debugging code because I've + * never managed to reach it. I think what happens is + * that, because the 700 runs with selection + * interrupts enabled the whole time that we take a + * selection interrupt before we manage to get to the + * reselected script interrupt */ + + __u8 reselection_id = NCR_700_readb(host, SFBR_REG); + struct NCR_700_command_slot *slot; + + /* Take out our own ID */ + reselection_id &= ~(1<this_id); + + printk(KERN_INFO "scsi%d: (%d:%d) RESELECTION DURING SELECTION, dsp=%p[%04x] state=%d, count=%d\n", + host->host_no, reselection_id, lun, (void *)dsp, dsp - hostdata->pScript, hostdata->state, hostdata->command_slot_count); + + { + /* FIXME: DEBUGGING CODE */ + __u32 SG = (__u32)bus_to_virt(hostdata->script[A_SGScriptStartAddress_used[0]]); + int i; + + for(i=0; i< NCR_700_COMMAND_SLOTS_PER_HOST; i++) { + if(SG >= (__u32)(&hostdata->slots[i].SG[0]) + && SG <= (__u32)(&hostdata->slots[i].SG[NCR_700_SG_SEGMENTS])) + break; + } + printk(KERN_INFO "IDENTIFIED SG segment as being %p in slot %p, cmd %p, slot->resume_offset=%p\n", (void *)SG, &hostdata->slots[i], hostdata->slots[i].cmnd, (void *)hostdata->slots[i].resume_offset); + SCp = hostdata->slots[i].cmnd; + } + + if(SCp != NULL) { + slot = (struct NCR_700_command_slot *)SCp->host_scribble; + /* change slot from busy to queued to redo command */ + slot->state = NCR_700_SLOT_QUEUED; + } + hostdata->cmd = NULL; + + if(reselection_id == 0) { + if(hostdata->reselection_id == 0xff) { + printk(KERN_ERR "scsi%d: Invalid reselection during selection!!\n", host->host_no); + return 0; + } else { + printk(KERN_ERR "scsi%d: script reselected and we took a selection interrupt\n", + host->host_no); + reselection_id = hostdata->reselection_id; + } + } else { + + /* convert to real ID */ + reselection_id = bitmap_to_number(reselection_id); + } + hostdata->reselection_id = reselection_id; + hostdata->msgin[1] = 0; + dma_cache_wback((unsigned long)hostdata->msgin, sizeof(hostdata->msgin)); + if(hostdata->tag_negotiated & (1<pScript + Ent_GetReselectionWithTag; + } else { + resume_offset = hostdata->pScript + Ent_GetReselectionData; + } + } else if(dsps == A_COMPLETED_SELECTION_AS_TARGET) { + /* we've just disconnected from the bus, do nothing since + * a return here will re-run the queued command slot + * that may have been interrupted by the initial selection */ + DEBUG((" SELECTION COMPLETED\n")); + } else if((dsps & 0xfffff0f0) == A_MSG_IN) { + resume_offset = process_message(host, hostdata, SCp, + dsp, dsps); + } else if((dsps & 0xfffff000) == 0) { + __u8 i = (dsps & 0xf0) >> 4, j = (dsps & 0xf00) >> 8; + printk(KERN_ERR "scsi%d: (%d:%d), unhandled script condition %s %s at %04x\n", + host->host_no, pun, lun, NCR_700_condition[i], + NCR_700_phase[j], dsp - hostdata->pScript); + if(SCp != NULL) { + print_command(SCp->cmnd); + + if(SCp->use_sg) { + for(i = 0; i < SCp->use_sg + 1; i++) { + printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); + } + } + } + NCR_700_internal_bus_reset(host); + } else if((dsps & 0xfffff000) == A_DEBUG_INTERRUPT) { + printk(KERN_NOTICE "scsi%d (%d:%d) DEBUG INTERRUPT %d AT %p[%04x], continuing\n", + host->host_no, pun, lun, dsps & 0xfff, (void *)dsp, dsp - hostdata->pScript); + resume_offset = dsp; + } else { + printk(KERN_ERR "scsi%d: (%d:%d), unidentified script interrupt 0x%x at %04x\n", + host->host_no, pun, lun, dsps, dsp - hostdata->pScript); + NCR_700_internal_bus_reset(host); + } + return resume_offset; +} + +/* We run the 53c700 with selection interrupts always enabled. This + * means that the chip may be selected as soon as the bus frees. On a + * busy bus, this can be before the scripts engine finishes its + * processing. Therefore, part of the selection processing has to be + * to find out what the scripts engine is doing and complete the + * function if necessary (i.e. process the pending disconnect or save + * the interrupted initial selection */ +STATIC inline __u32 +process_selection(struct Scsi_Host *host, __u32 dsp) +{ + __u8 id = 0; /* Squash compiler warning */ + int count = 0; + __u32 resume_offset = 0; + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + Scsi_Cmnd *SCp = hostdata->cmd; + __u8 sbcl; + + for(count = 0; count < 5; count++) { + id = NCR_700_readb(host, SFBR_REG); + + /* Take out our own ID */ + id &= ~(1<this_id); + if(id != 0) + break; + udelay(5); + } + sbcl = NCR_700_readb(host, SBCL_REG); + if((sbcl & SBCL_IO) == 0) { + /* mark as having been selected rather than reselected */ + id = 0xff; + } else { + /* convert to real ID */ + hostdata->reselection_id = id = bitmap_to_number(id); + DEBUG(("scsi%d: Reselected by %d\n", + host->host_no, id)); + } + if(hostdata->state == NCR_700_HOST_BUSY && SCp != NULL) { + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + DEBUG((" ID %d WARNING: RESELECTION OF BUSY HOST, saving cmd %p, slot %p, addr %x [%04x], resume %x!\n", id, hostdata->cmd, slot, dsp, dsp - hostdata->pScript, resume_offset)); + + switch(dsp - hostdata->pScript) { + case Ent_Disconnect1: + case Ent_Disconnect2: + save_for_reselection(hostdata, SCp, Ent_Disconnect2 + hostdata->pScript); + break; + case Ent_Disconnect3: + case Ent_Disconnect4: + save_for_reselection(hostdata, SCp, Ent_Disconnect4 + hostdata->pScript); + break; + case Ent_Disconnect5: + case Ent_Disconnect6: + save_for_reselection(hostdata, SCp, Ent_Disconnect6 + hostdata->pScript); + break; + case Ent_Disconnect7: + case Ent_Disconnect8: + save_for_reselection(hostdata, SCp, Ent_Disconnect8 + hostdata->pScript); + break; + case Ent_Finish1: + case Ent_Finish2: + process_script_interrupt(A_GOOD_STATUS_AFTER_STATUS, dsp, SCp, host, hostdata); + break; + + default: + slot->state = NCR_700_SLOT_QUEUED; + break; + } + } + hostdata->state = NCR_700_HOST_BUSY; + hostdata->cmd = NULL; + hostdata->msgin[1] = 0; + dma_cache_wback((unsigned long)hostdata->msgin, sizeof(hostdata->msgin)); + + if(id == 0xff) { + /* Selected as target, Ignore */ + resume_offset = hostdata->pScript + Ent_SelectedAsTarget; + } else if(hostdata->tag_negotiated & (1<pScript + Ent_GetReselectionWithTag; + } else { + resume_offset = hostdata->pScript + Ent_GetReselectionData; + } + return resume_offset; +} + + +STATIC int +NCR_700_start_command(Scsi_Cmnd *SCp) +{ + struct NCR_700_command_slot *slot = + (struct NCR_700_command_slot *)SCp->host_scribble; + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SCp->host->hostdata[0]; + unsigned long flags; + __u16 count = 1; /* for IDENTIFY message */ + + save_flags(flags); + cli(); + if(hostdata->state != NCR_700_HOST_FREE) { + /* keep this inside the lock to close the race window where + * the running command finishes on another CPU while we don't + * change the state to queued on this one */ + slot->state = NCR_700_SLOT_QUEUED; + restore_flags(flags); + + DEBUG(("scsi%d: host busy, queueing command %p, slot %p\n", + SCp->host->host_no, slot->cmnd, slot)); + return 0; + } + hostdata->state = NCR_700_HOST_BUSY; + hostdata->cmd = SCp; + slot->state = NCR_700_SLOT_BUSY; + /* keep interrupts disabled until we have the command correctly + * set up so we cannot take a selection interrupt */ + + hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE, + SCp->lun); + /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure + * if the negotiated transfer parameters still hold, so + * always renegotiate them */ + if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE) { + NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); + } + + /* REQUEST_SENSE is asking for contingent I_T_L status. If a + * contingent allegiance condition exists, the device will + * refuse all tags, so send the request sense as untagged */ + if((hostdata->tag_negotiated & (1<target)) + && (slot->tag != NCR_700_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) { + hostdata->msgout[count++] = A_SIMPLE_TAG_MSG; + hostdata->msgout[count++] = slot->tag; + } + + if(hostdata->fast && + NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { + memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, + sizeof(NCR_700_SDTR_msg)); + count += sizeof(NCR_700_SDTR_msg); + NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + } + + dma_cache_wback((unsigned long)hostdata->msgout, count); + + script_patch_16(hostdata->script, MessageCount, count); + + + script_patch_ID(hostdata->script, + Device_ID, 1<target); + + script_patch_32_abs(hostdata->script, CommandAddress, + virt_to_bus(SCp->cmnd)); + script_patch_16(hostdata->script, CommandCount, SCp->cmd_len); + /* finally plumb the beginning of the SG list into the script + * */ + script_patch_32_abs(hostdata->script, SGScriptStartAddress, + virt_to_bus(&slot->SG[0].ins)); + NCR_700_writeb(CLR_FIFO, SCp->host, DFIFO_REG); + + /* set the synchronous period/offset */ + if(slot->resume_offset == 0) + slot->resume_offset = hostdata->pScript; + NCR_700_writeb(NCR_700_get_SXFER(SCp->device), + SCp->host, SXFER_REG); + /* allow interrupts here so that if we're selected we can take + * a selection interrupt. The script start may not be + * effective in this case, but the selection interrupt will + * save our command in that case */ + NCR_700_writel(slot->temp, SCp->host, TEMP_REG); + NCR_700_writel(slot->resume_offset, SCp->host, DSP_REG); + restore_flags(flags); + + return 1; +} + +void +NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct Scsi_Host *host = (struct Scsi_Host *)dev_id; + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + __u8 istat; + __u32 resume_offset = 0; + __u8 pun = 0xff, lun = 0xff; + unsigned long flags; + + /* Unfortunately, we have to take the io_request_lock here + * rather than the host lock hostdata->lock because we're + * looking to exclude queuecommand from messing with the + * registers while we're processing the interrupt. Since + * queuecommand is called holding io_request_lock, and we have + * to take io_request_lock before we call the command + * scsi_done, we would get a deadlock if we took + * hostdata->lock here and in queuecommand (because the order + * of locking in queuecommand: 1) io_request_lock then 2) + * hostdata->lock would be the reverse of taking it in this + * routine */ + spin_lock_irqsave(&io_request_lock, flags); + if((istat = NCR_700_readb(host, ISTAT_REG)) + & (SCSI_INT_PENDING | DMA_INT_PENDING)) { + __u32 dsps; + __u8 sstat0 = 0, dstat = 0; + __u32 dsp; + Scsi_Cmnd *SCp = hostdata->cmd; + enum NCR_700_Host_State state; + + state = hostdata->state; + SCp = hostdata->cmd; + + if(istat & SCSI_INT_PENDING) { + udelay(10); + + sstat0 = NCR_700_readb(host, SSTAT0_REG); + } + + if(istat & DMA_INT_PENDING) { + udelay(10); + + dstat = NCR_700_readb(host, DSTAT_REG); + } + + dsps = NCR_700_readl(host, DSPS_REG); + dsp = NCR_700_readl(host, DSP_REG); + + DEBUG(("scsi%d: istat %02x sstat0 %02x dstat %02x dsp %04x[%08x] dsps 0x%x\n", + host->host_no, istat, sstat0, dstat, + (dsp - (__u32)virt_to_bus(hostdata->script))/4, + dsp, dsps)); + + if(SCp != NULL) { + pun = SCp->target; + lun = SCp->lun; + } + + if(sstat0 & SCSI_RESET_DETECTED) { + Scsi_Device *SDp; + int i; + + hostdata->state = NCR_700_HOST_BUSY; + + printk(KERN_ERR "scsi%d: Bus Reset detected, executing command %p, slot %p, dsp %p[%04x]\n", + host->host_no, SCp, SCp == NULL ? NULL : SCp->host_scribble, (void *)dsp, dsp - hostdata->pScript); + + /* clear all the negotiated parameters */ + for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) + SDp->hostdata = 0; + + /* clear all the slots and their pending commands */ + for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { + Scsi_Cmnd *SCp; + struct NCR_700_command_slot *slot = + &hostdata->slots[i]; + + if(slot->state == NCR_700_SLOT_FREE) + continue; + + SCp = slot->cmnd; + printk(KERN_ERR " failing command because of reset, slot %p, cmnd %p\n", + slot, SCp); + free_slot(slot, hostdata); + SCp->host_scribble = NULL; + NCR_700_set_depth(SCp->device, 0); + /* NOTE: deadlock potential here: we + * rely on mid-layer guarantees that + * scsi_done won't try to issue the + * command again otherwise we'll + * deadlock on the + * hostdata->state_lock */ + SCp->result = DID_RESET << 16; + SCp->scsi_done(SCp); + } + mdelay(25); + NCR_700_chip_setup(host); + + hostdata->state = NCR_700_HOST_FREE; + hostdata->cmd = NULL; + goto out_unlock; + } else if(sstat0 & SELECTION_TIMEOUT) { + DEBUG(("scsi%d: (%d:%d) selection timeout\n", + host->host_no, pun, lun)); + NCR_700_scsi_done(hostdata, SCp, DID_NO_CONNECT<<16); + } else if(sstat0 & PHASE_MISMATCH) { + struct NCR_700_command_slot *slot = (SCp == NULL) ? NULL : + (struct NCR_700_command_slot *)SCp->host_scribble; + + if(dsp == Ent_SendMessage + 8 + hostdata->pScript) { + /* It wants to reply to some part of + * our message */ +#ifdef NCR_700_DEBUG + __u32 temp = NCR_700_readl(host, TEMP_REG); + int count = (hostdata->script[Ent_SendMessage/4] & 0xffffff) - ((NCR_700_readl(host, DBC_REG) & 0xffffff) + NCR_700_data_residual(host)); + printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG))); +#endif + resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch; + } else if(dsp >= virt_to_bus(&slot->SG[0].ins) && + dsp <= virt_to_bus(&slot->SG[NCR_700_SG_SEGMENTS].ins)) { + int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff; + int SGcount = (dsp - virt_to_bus(&slot->SG[0].ins))/sizeof(struct NCR_700_SG_List); + int residual = NCR_700_data_residual(host); + int i; +#ifdef NCR_700_DEBUG + printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x\n", + host->host_no, pun, lun, + SGcount, data_transfer); + print_command(SCp->cmnd); + if(residual) { + printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x, residual %d\n", + host->host_no, pun, lun, + SGcount, data_transfer, residual); + } +#endif + data_transfer += residual; + + if(data_transfer != 0) { + int count; + __u32 pAddr; + + SGcount--; + + count = (bS_to_cpu(slot->SG[SGcount].ins) & 0x00ffffff); + DEBUG(("DATA TRANSFER MISMATCH, count = %d, transferred %d\n", count, count-data_transfer)); + slot->SG[SGcount].ins &= bS_to_host(0xff000000); + slot->SG[SGcount].ins |= bS_to_host(data_transfer); + pAddr = bS_to_cpu(slot->SG[SGcount].pAddr); + pAddr += (count - data_transfer); + slot->SG[SGcount].pAddr = bS_to_host(pAddr); + } + /* set the executed moves to nops */ + for(i=0; iSG[i].ins = bS_to_host(SCRIPT_NOP); + slot->SG[i].pAddr = 0; + } + dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG)); + /* and pretend we disconnected after + * the command phase */ + resume_offset = hostdata->pScript + Ent_MsgInDuringData; + } else { + __u8 sbcl = NCR_700_readb(host, SBCL_REG); + printk(KERN_ERR "scsi%d: (%d:%d) phase mismatch at %04x, phase %s\n", + host->host_no, pun, lun, dsp - hostdata->pScript, sbcl_to_string(sbcl)); + NCR_700_internal_bus_reset(host); + } + + } else if(sstat0 & SCSI_GROSS_ERROR) { + printk(KERN_ERR "scsi%d: (%d:%d) GROSS ERROR\n", + host->host_no, pun, lun); + NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16); + } else if(dstat & SCRIPT_INT_RECEIVED) { + DEBUG(("scsi%d: (%d:%d) ====>SCRIPT INTERRUPT<====\n", + host->host_no, pun, lun)); + resume_offset = process_script_interrupt(dsps, dsp, SCp, host, hostdata); + } else if(dstat & (ILGL_INST_DETECTED)) { + printk(KERN_ERR "scsi%d: (%d:%d) Illegal Instruction detected at 0x%p[0x%x]!!!\n" + " Please email James.Bottomley@HansenPartnership.com with the details\n", + host->host_no, pun, lun, + (void *)dsp, dsp - hostdata->pScript); + NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16); + } else if(dstat & (WATCH_DOG_INTERRUPT|ABORTED)) { + printk(KERN_ERR "scsi%d: (%d:%d) serious DMA problem, dstat=%02x\n", + host->host_no, pun, lun, dstat); + NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16); + } + + + /* NOTE: selection interrupt processing MUST occur + * after script interrupt processing to correctly cope + * with the case where we process a disconnect and + * then get reselected before we process the + * disconnection */ + if(sstat0 & SELECTED) { + /* FIXME: It currently takes at least FOUR + * interrupts to complete a command that + * disconnects: one for the disconnect, one + * for the reselection, one to get the + * reselection data and one to complete the + * command. If we guess the reselected + * command here and prepare it, we only need + * to get a reselection data interrupt if we + * guessed wrongly. Since the interrupt + * overhead is much greater than the command + * setup, this would be an efficient + * optimisation particularly as we probably + * only have one outstanding command on a + * target most of the time */ + + resume_offset = process_selection(host, dsp); + + } + + } + + if(resume_offset) { + if(hostdata->state != NCR_700_HOST_BUSY) { + printk(KERN_ERR "scsi%d: Driver error: resume at %p [%04x] with non busy host!\n", + host->host_no, (void *)resume_offset, resume_offset - hostdata->pScript); + hostdata->state = NCR_700_HOST_BUSY; + } + + DEBUG(("Attempting to resume at %x\n", resume_offset)); + NCR_700_writeb(CLR_FIFO, host, DFIFO_REG); + NCR_700_writel(resume_offset, host, DSP_REG); + } + /* There is probably a technical no-no about this: If we're a + * shared interrupt and we got this interrupt because the + * other device needs servicing not us, we're still going to + * check our queued commands here---of course, there shouldn't + * be any outstanding.... */ + if(hostdata->state == NCR_700_HOST_FREE) { + int i; + + for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { + /* fairness: always run the queue from the last + * position we left off */ + int j = (i + hostdata->saved_slot_position) + % NCR_700_COMMAND_SLOTS_PER_HOST; + + if(hostdata->slots[j].state != NCR_700_SLOT_QUEUED) + continue; + if(NCR_700_start_command(hostdata->slots[j].cmnd)) { + DEBUG(("scsi%d: Issuing saved command slot %p, cmd %p\t\n", + host->host_no, &hostdata->slots[j], + hostdata->slots[j].cmnd)); + hostdata->saved_slot_position = j + 1; + } + + break; + } + } + out_unlock: + spin_unlock_irqrestore(&io_request_lock, flags); +} + +/* FIXME: Need to put some proc information in and plumb it + * into the scsi proc system */ +STATIC int +NCR_700_proc_directory_info(char *proc_buf, char **startp, + off_t offset, int bytes_available, + int host_no, int write) +{ + static char buf[4096]; /* 1 page should be sufficient */ + int len = 0; + struct Scsi_Host *host = scsi_hostlist; + struct NCR_700_Host_Parameters *hostdata; + Scsi_Device *SDp; + + while(host != NULL && host->host_no != host_no) + host = host->next; + + if(host == NULL) + return 0; + + if(write) { + /* FIXME: Clear internal statistics here */ + return 0; + } + hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + len += sprintf(&buf[len], "Total commands outstanding: %d\n", hostdata->command_slot_count); + len += sprintf(&buf[len],"\ +Target Depth Active Next Tag\n\ +====== ===== ====== ========\n"); + for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) { + len += sprintf(&buf[len]," %2d:%2d %4d %4d %4d\n", SDp->id, SDp->lun, SDp->queue_depth, NCR_700_get_depth(SDp), SDp->current_tag); + } + if((len -= offset) <= 0) + return 0; + if(len > bytes_available) + len = bytes_available; + memcpy(proc_buf, buf + offset, len); + return len; +} + +STATIC int +NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SCp->host->hostdata[0]; + __u32 move_ins; + struct NCR_700_command_slot *slot; + int hash; + + if(hostdata->command_slot_count >= NCR_700_COMMAND_SLOTS_PER_HOST) { + /* We're over our allocation, this should never happen + * since we report the max allocation to the mid layer */ + printk(KERN_WARNING "scsi%d: Command depth has gone over queue depth\n", SCp->host->host_no); + return 1; + } + if(NCR_700_get_depth(SCp->device) != 0 && !(hostdata->tag_negotiated & (1<target))) { + DEBUG((KERN_ERR "scsi%d (%d:%d) has non zero depth %d\n", + SCp->host->host_no, SCp->target, SCp->lun, + NCR_700_get_depth(SCp->device))); + return 1; + } + if(NCR_700_get_depth(SCp->device) >= NCR_700_MAX_TAGS) { + DEBUG((KERN_ERR "scsi%d (%d:%d) has max tag depth %d\n", + SCp->host->host_no, SCp->target, SCp->lun, + NCR_700_get_depth(SCp->device))); + return 1; + } + NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1); + + /* begin the command here */ + /* no need to check for NULL, test for command_slot_cound above + * ensures a slot is free */ + slot = find_empty_slot(hostdata); + + slot->cmnd = SCp; + + SCp->scsi_done = done; + SCp->host_scribble = (unsigned char *)slot; + SCp->SCp.ptr = NULL; + SCp->SCp.buffer = NULL; + +#ifdef NCR_700_DEBUG + printk("53c700: scsi%d, command ", SCp->host->host_no); + print_command(SCp->cmnd); +#endif + + if(hostdata->tag_negotiated &(1<target)) { + + struct NCR_700_command_slot *old = + find_ITL_Nexus(hostdata, SCp->target, SCp->lun); +#ifdef NCR_700_TAG_DEBUG + struct NCR_700_command_slot *found; +#endif + + if(old != NULL && old->tag == SCp->device->current_tag) { + printk(KERN_WARNING "scsi%d (%d:%d) Tag clock back to current, queueing\n", SCp->host->host_no, SCp->target, SCp->lun); + return 1; + } + slot->tag = SCp->device->current_tag++; +#ifdef NCR_700_TAG_DEBUG + while((found = find_ITLQ_Nexus(hostdata, SCp->target, SCp->lun, slot->tag)) != NULL) { + printk("\n\n**ERROR** already using tag %d, but oldest is %d\n", slot->tag, (old == NULL) ? -1 : old->tag); + printk(" FOUND = %p, tag = %d, pun = %d, lun = %d\n", + found, found->tag, found->cmnd->target, found->cmnd->lun); + slot->tag = SCp->device->current_tag++; + printk(" Tag list is: "); + while(old != NULL) { + if(old->cmnd->target == SCp->target && + old->cmnd->lun == SCp->lun) + printk("%d ", old->tag); + old = old->ITL_back; + } + printk("\n\n"); + } +#endif + hash = hash_ITLQ(SCp->target, SCp->lun, slot->tag); + /* link into the ITLQ hash queues */ + slot->ITLQ_forw = hostdata->ITLQ_Hash_forw[hash]; + hostdata->ITLQ_Hash_forw[hash] = slot; +#ifdef NCR_700_TAG_DEBUG + if(slot->ITLQ_forw != NULL && slot->ITLQ_forw->ITLQ_back != NULL) { + printk(KERN_ERR "scsi%d (%d:%d) ITLQ_back is not NULL!!!!\n", SCp->host->host_no, SCp->target, SCp->lun); + } +#endif + if(slot->ITLQ_forw != NULL) + slot->ITLQ_forw->ITLQ_back = slot; + else + hostdata->ITLQ_Hash_back[hash] = slot; + slot->ITLQ_back = NULL; + } else { + slot->tag = NCR_700_NO_TAG; + } + /* link into the ITL hash queues */ + hash = hash_ITL(SCp->target, SCp->lun); + slot->ITL_forw = hostdata->ITL_Hash_forw[hash]; + hostdata->ITL_Hash_forw[hash] = slot; +#ifdef NCR_700_TAG_DEBUG + if(slot->ITL_forw != NULL && slot->ITL_forw->ITL_back != NULL) { + printk(KERN_ERR "scsi%d (%d:%d) ITL_back is not NULL!!!!\n", + SCp->host->host_no, SCp->target, SCp->lun); + } +#endif + if(slot->ITL_forw != NULL) + slot->ITL_forw->ITL_back = slot; + else + hostdata->ITL_Hash_back[hash] = slot; + slot->ITL_back = NULL; + + + /* This is f****g ridiculous; every low level HBA driver has + * to determine the direction of the commands, why isn't this + * done inside the scsi_lib !!??? */ + switch (SCp->cmnd[0]) { + case REQUEST_SENSE: + /* clear the internal sense magic */ + SCp->cmnd[6] = 0; + /* fall through */ + case INQUIRY: + case MODE_SENSE: + case READ_6: + case READ_10: + case READ_12: + case READ_CAPACITY: + case READ_BLOCK_LIMITS: + case READ_TOC: + move_ins = SCRIPT_MOVE_DATA_IN; + break; + case MODE_SELECT: + case WRITE_6: + case WRITE_10: + case WRITE_12: + move_ins = SCRIPT_MOVE_DATA_OUT; + break; + case TEST_UNIT_READY: + case ALLOW_MEDIUM_REMOVAL: + case START_STOP: + move_ins = 0; + break; + default: + /* OK, get it from the command */ + switch(SCp->sc_data_direction) { + case SCSI_DATA_UNKNOWN: + default: + printk(KERN_ERR "53c700: Unknown command for data direction "); + print_command(SCp->cmnd); + + move_ins = 0; + break; + case SCSI_DATA_NONE: + move_ins = 0; + break; + case SCSI_DATA_READ: + move_ins = SCRIPT_MOVE_DATA_IN; + break; + case SCSI_DATA_WRITE: + move_ins = SCRIPT_MOVE_DATA_OUT; + break; + } + } + + /* now build the scatter gather list */ + if(move_ins != 0) { + int i; + + for(i = 0; i < (SCp->use_sg ? SCp->use_sg : 1); i++) { + void *vPtr; + __u32 count; + + if(SCp->use_sg) { + vPtr = (((struct scatterlist *)SCp->buffer)[i].address); + count = ((struct scatterlist *)SCp->buffer)[i].length; + } else { + vPtr = SCp->request_buffer; + count = SCp->request_bufflen; + } + slot->SG[i].ins = bS_to_host(move_ins | count); + DEBUG((" scatter block %d: move %d[%08x] from 0x%lx\n", + i, count, slot->SG[i].ins, + virt_to_bus(vPtr))); + dma_cache_wback_inv((unsigned long)vPtr, count); + slot->SG[i].pAddr = bS_to_host(virt_to_bus(vPtr)); + } + slot->SG[i].ins = bS_to_host(SCRIPT_RETURN); + slot->SG[i].pAddr = 0; + dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG)); + DEBUG((" SETTING %08lx to %x\n", + virt_to_bus(&slot->SG[i].ins), + slot->SG[i].ins)); + } + slot->resume_offset = 0; + NCR_700_start_command(SCp); + return 0; +} + +STATIC int +NCR_700_abort(Scsi_Cmnd * SCp) +{ + struct NCR_700_command_slot *slot; + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SCp->host->hostdata[0]; + + printk(KERN_INFO "scsi%d (%d:%d) New error handler wants to abort command\n\t", + SCp->host->host_no, SCp->target, SCp->lun); + print_command(SCp->cmnd); + + slot = find_ITL_Nexus(hostdata, SCp->target, SCp->lun); + while(slot != NULL && slot->cmnd != SCp) + slot = slot->ITL_back; + + if(slot == NULL) + /* no outstanding command to abort */ + return SUCCESS; + if(SCp->cmnd[0] == TEST_UNIT_READY) { + /* FIXME: This is because of a problem in the new + * error handler. When it is in error recovery, it + * will send a TUR to a device it thinks may still be + * showing a problem. If the TUR isn't responded to, + * it will abort it and mark the device off line. + * Unfortunately, it does no other error recovery, so + * this would leave us with an outstanding command + * occupying a slot. Rather than allow this to + * happen, we issue a bus reset to force all + * outstanding commands to terminate here. */ + NCR_700_internal_bus_reset(SCp->host); + /* still drop through and return failed */ + } + return FAILED; + +} + +STATIC int +NCR_700_bus_reset(Scsi_Cmnd * SCp) +{ + printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t", + SCp->host->host_no, SCp->target, SCp->lun, SCp); + print_command(SCp->cmnd); + NCR_700_internal_bus_reset(SCp->host); + return SUCCESS; +} + +STATIC int +NCR_700_dev_reset(Scsi_Cmnd * SCp) +{ + printk(KERN_INFO "scsi%d (%d:%d) New error handler wants device reset\n\t", + SCp->host->host_no, SCp->target, SCp->lun); + print_command(SCp->cmnd); + + return FAILED; +} + +STATIC int +NCR_700_host_reset(Scsi_Cmnd * SCp) +{ + printk(KERN_INFO "scsi%d (%d:%d) New error handler wants HOST reset\n\t", + SCp->host->host_no, SCp->target, SCp->lun); + print_command(SCp->cmnd); + + NCR_700_internal_bus_reset(SCp->host); + NCR_700_chip_reset(SCp->host); + return SUCCESS; +} + +EXPORT_SYMBOL(NCR_700_detect); +EXPORT_SYMBOL(NCR_700_release); +EXPORT_SYMBOL(NCR_700_intr); diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/53c700.h linux/drivers/scsi/53c700.h --- v2.4.9/linux/drivers/scsi/53c700.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/53c700.h Sun Sep 9 10:50:48 2001 @@ -0,0 +1,534 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* Driver for 53c700 and 53c700-66 chips from NCR and Symbios + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com + */ + +#ifndef _53C700_H +#define _53C700_H + +/* Turn on for general debugging---too verbose for normal use */ +#undef NCR_700_DEBUG +/* Debug the tag queues, checking hash queue allocation and deallocation + * and search for duplicate tags */ +#undef NCR_700_TAG_DEBUG + +#ifdef NCR_700_DEBUG +#define DEBUG(x) printk x +#else +#define DEBUG(x) +#endif + +/* The number of available command slots */ +#define NCR_700_COMMAND_SLOTS_PER_HOST 64 +/* The maximum number of Scatter Gathers we allow */ +#define NCR_700_SG_SEGMENTS 32 +/* The maximum number of luns (make this of the form 2^n) */ +#define NCR_700_MAX_LUNS 32 +#define NCR_700_LUN_MASK (NCR_700_MAX_LUNS - 1) +/* Alter this with care: too many tags won't give the elevator a chance to + * work; too few will cause the device to operate less efficiently */ +#define NCR_700_MAX_TAGS 16 +/* magic byte identifying an internally generated REQUEST_SENSE command */ +#define NCR_700_INTERNAL_SENSE_MAGIC 0x42 + +/* WARNING: Leave this in for now: the dependency preprocessor doesn't + * pick up file specific flags, so must define here if they are not + * set */ +#if !defined(IO_MAPPED) && !defined(MEM_MAPPED) +#define IO_MAPPED +#endif + + +struct NCR_700_Host_Parameters; + +/* These are the externally used routines */ +struct Scsi_Host *NCR_700_detect(Scsi_Host_Template *, struct NCR_700_Host_Parameters *); +int NCR_700_release(struct Scsi_Host *host); +void NCR_700_intr(int, void *, struct pt_regs *); + + +enum NCR_700_Host_State { + NCR_700_HOST_BUSY, + NCR_700_HOST_FREE, +}; + +struct NCR_700_SG_List { + /* The following is a script fragment to move the buffer onto the + * bus and then link the next fragment or return */ + #define SCRIPT_MOVE_DATA_IN 0x09000000 + #define SCRIPT_MOVE_DATA_OUT 0x08000000 + __u32 ins; + __u32 pAddr; + #define SCRIPT_NOP 0x80000000 + #define SCRIPT_RETURN 0x90080000 +}; + +/* We use device->hostdata to store negotiated parameters. This is + * supposed to be a pointer to a device private area, but we cannot + * really use it as such since it will never be freed, so just use the + * 32 bits to cram the information. The SYNC negotiation sequence looks + * like: + * + * If DEV_NEGOTIATED_SYNC not set, tack and SDTR message on to the + * initial identify for the device and set DEV_BEGIN_SYNC_NEGOTATION + * If we get an SDTR reply, work out the SXFER parameters, squirrel + * them away here, clear DEV_BEGIN_SYNC_NEGOTIATION and set + * DEV_NEGOTIATED_SYNC. If we get a REJECT msg, squirrel + * + * + * 0:7 SXFER_REG negotiated value for this device + * 8:15 Current queue depth + * 16 negotiated SYNC flag + * 17 begin SYNC negotiation flag + * 18 device supports tag queueing */ +#define NCR_700_DEV_NEGOTIATED_SYNC (1<<16) +#define NCR_700_DEV_BEGIN_SYNC_NEGOTIATION (1<<17) +#define NCR_700_DEV_BEGIN_TAG_QUEUEING (1<<18) + +static inline void +NCR_700_set_SXFER(Scsi_Device *SDp, __u8 sxfer) +{ + ((__u32)SDp->hostdata) &= 0xffffff00; + ((__u32)SDp->hostdata) |= sxfer & 0xff; +} +static inline __u8 NCR_700_get_SXFER(Scsi_Device *SDp) +{ + return (((__u32)SDp->hostdata) & 0xff); +} +static inline void +NCR_700_set_depth(Scsi_Device *SDp, __u8 depth) +{ + ((__u32)SDp->hostdata) &= 0xffff00ff; + ((__u32)SDp->hostdata) |= (0xff00 & (depth << 8)); +} +static inline __u8 +NCR_700_get_depth(Scsi_Device *SDp) +{ + return ((((__u32)SDp->hostdata) & 0xff00)>>8); +} +static inline int +NCR_700_is_flag_set(Scsi_Device *SDp, __u32 flag) +{ + return (((__u32)SDp->hostdata) & flag) == flag; +} +static inline int +NCR_700_is_flag_clear(Scsi_Device *SDp, __u32 flag) +{ + return (((__u32)SDp->hostdata) & flag) == 0; +} +static inline void +NCR_700_set_flag(Scsi_Device *SDp, __u32 flag) +{ + ((__u32)SDp->hostdata) |= (flag & 0xffff0000); +} +static inline void +NCR_700_clear_flag(Scsi_Device *SDp, __u32 flag) +{ + ((__u32)SDp->hostdata) &= ~(flag & 0xffff0000); +} + +/* These represent the Nexus hashing functions. A Nexus in SCSI terms + * just means the identification of an outstanding command, by ITL + * (Initiator Target Lun) or ITLQ (Initiator Target Lun Tag). I'm not + * very keen on XOR based hashes, so these are based on number theory + * instead. All you need to do is to fix your hash bucket size and + * then choose reasonable strides which are coprime with the chosen + * bucket size + * + * Note: this mathematical hash can be made very efficient, if the + * compiler is good at optimising: Choose the number of buckets to be + * 2^n and the modulo becomes a logical and with (2^n-1). + * Additionally, if you chose the coprimes of the form 2^n-2^n the + * multiplication can be done by a shift and an addition. */ +#define MAX_ITL_HASH_BUCKETS 16 +#define ITL_HASH_PRIME 7 + +#define MAX_ITLQ_HASH_BUCKETS 64 +#define ITLQ_PUN_PRIME 7 +#define ITLQ_LUN_PRIME 3 + +static inline int +hash_ITL(__u8 pun, __u8 lun) +{ + return (pun*ITL_HASH_PRIME + lun) % MAX_ITL_HASH_BUCKETS; +} + +static inline int +hash_ITLQ(__u8 pun, __u8 lun, __u8 tag) +{ + return (pun*ITLQ_PUN_PRIME + lun*ITLQ_LUN_PRIME + tag) % MAX_ITLQ_HASH_BUCKETS; +} + +struct NCR_700_command_slot { + #define NCR_700_SLOT_MASK 0xFC + #define NCR_700_SLOT_MAGIC 0xb8 + #define NCR_700_SLOT_FREE (0|NCR_700_SLOT_MAGIC) /* slot may be used */ + #define NCR_700_SLOT_BUSY (1|NCR_700_SLOT_MAGIC) /* slot has command active on HA */ + #define NCR_700_SLOT_QUEUED (2|NCR_700_SLOT_MAGIC) /* slot has command to be made active on HA */ + __u8 state; + #define NCR_700_NO_TAG 0xdead + __u16 tag; + struct NCR_700_SG_List SG[NCR_700_SG_SEGMENTS+1]; + __u32 resume_offset; + Scsi_Cmnd *cmnd; + __u32 temp; + /* Doubly linked ITL/ITLQ list kept in strict time order + * (latest at the back) */ + struct NCR_700_command_slot *ITL_forw; + struct NCR_700_command_slot *ITL_back; + struct NCR_700_command_slot *ITLQ_forw; + struct NCR_700_command_slot *ITLQ_back; +}; + +struct NCR_700_Host_Parameters { + /* These must be filled in by the calling driver */ + int clock; /* board clock speed in MHz */ + __u32 base; /* the base for the port (copied to host) */ + __u8 differential:1; /* if we are differential */ +#ifdef __hppa__ + /* This option is for HP only. Set it if your chip is wired for + * little endian on this platform (which is big endian) */ + __u8 force_le_on_be:1; +#endif + + /* NOTHING BELOW HERE NEEDS ALTERING */ + __u8 fast:1; /* if we can alter the SCSI bus clock + speed (so can negiotiate sync) */ + + int sync_clock; /* The speed of the SYNC core */ + + __u32 *script; /* pointer to script location */ + __u32 pScript; /* physical mem addr of script */ + + /* This will be the host lock. Unfortunately, we can't use it + * at the moment because of the necessity of holding the + * io_request_lock */ + spinlock_t lock; + enum NCR_700_Host_State state; /* protected by state lock */ + Scsi_Cmnd *cmd; + + __u8 msgout[8]; + __u8 tag_negotiated; + __u8 status; + __u8 msgin[8]; + struct NCR_700_command_slot *slots; + int saved_slot_position; + int command_slot_count; /* protected by state lock */ + __u8 rev; + __u8 reselection_id; + /* flags for the host */ + + /* ITL list. ALL outstanding commands are hashed here in strict + * order, latest at the back */ + struct NCR_700_command_slot *ITL_Hash_forw[MAX_ITL_HASH_BUCKETS]; + struct NCR_700_command_slot *ITL_Hash_back[MAX_ITL_HASH_BUCKETS]; + + /* Only tagged outstanding commands are hashed here (also latest + * at the back) */ + struct NCR_700_command_slot *ITLQ_Hash_forw[MAX_ITLQ_HASH_BUCKETS]; + struct NCR_700_command_slot *ITLQ_Hash_back[MAX_ITLQ_HASH_BUCKETS]; + + /* Free list, singly linked by ITL_forw elements */ + struct NCR_700_command_slot *free_list; +}; + +/* + * 53C700 Register Interface - the offset from the Selected base + * I/O address */ +#ifdef __hppa__ +#define bE (hostdata->force_le_on_be ? 0 : 3) +#define bSWAP (hostdata->force_le_on_be) +#elif defined(__BIG_ENDIAN) +#define bE 3 +#define bSWAP 0 +#elif defined(__LITTLE_ENDIAN) +#define bE 0 +#define bSWAP 0 +#else +#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined, did you include byteorder.h?" +#endif +#define bS_to_cpu(x) (bSWAP ? le32_to_cpu(x) : (x)) +#define bS_to_host(x) (bSWAP ? cpu_to_le32(x) : (x)) + +/* NOTE: These registers are in the LE register space only, the required byte + * swapping is done by the NCR_700_{read|write}[b] functions */ +#define SCNTL0_REG 0x00 +#define FULL_ARBITRATION 0xc0 +#define PARITY 0x08 +#define ENABLE_PARITY 0x04 +#define AUTO_ATN 0x02 +#define SCNTL1_REG 0x01 +#define SLOW_BUS 0x80 +#define ENABLE_SELECT 0x20 +#define ASSERT_RST 0x08 +#define ASSERT_EVEN_PARITY 0x04 +#define SDID_REG 0x02 +#define SIEN_REG 0x03 +#define PHASE_MM_INT 0x80 +#define FUNC_COMP_INT 0x40 +#define SEL_TIMEOUT_INT 0x20 +#define SELECT_INT 0x10 +#define GROSS_ERR_INT 0x08 +#define UX_DISC_INT 0x04 +#define RST_INT 0x02 +#define PAR_ERR_INT 0x01 +#define SCID_REG 0x04 +#define SXFER_REG 0x05 +#define ASYNC_OPERATION 0x00 +#define SODL_REG 0x06 +#define SOCL_REG 0x07 +#define SFBR_REG 0x08 +#define SIDL_REG 0x09 +#define SBDL_REG 0x0A +#define SBCL_REG 0x0B +/* read bits */ +#define SBCL_IO 0x01 +/*write bits */ +#define SYNC_DIV_AS_ASYNC 0x00 +#define SYNC_DIV_1_0 0x01 +#define SYNC_DIV_1_5 0x02 +#define SYNC_DIV_2_0 0x03 +#define DSTAT_REG 0x0C +#define ILGL_INST_DETECTED 0x01 +#define WATCH_DOG_INTERRUPT 0x02 +#define SCRIPT_INT_RECEIVED 0x04 +#define ABORTED 0x10 +#define SSTAT0_REG 0x0D +#define PARITY_ERROR 0x01 +#define SCSI_RESET_DETECTED 0x02 +#define UNEXPECTED_DISCONNECT 0x04 +#define SCSI_GROSS_ERROR 0x08 +#define SELECTED 0x10 +#define SELECTION_TIMEOUT 0x20 +#define FUNCTION_COMPLETE 0x40 +#define PHASE_MISMATCH 0x80 +#define SSTAT1_REG 0x0E +#define SIDL_REG_FULL 0x80 +#define SODR_REG_FULL 0x40 +#define SODL_REG_FULL 0x20 +#define SSTAT2_REG 0x0F +#define CTEST0_REG 0x14 +#define CTEST1_REG 0x15 +#define CTEST2_REG 0x16 +#define CTEST3_REG 0x17 +#define CTEST4_REG 0x18 +#define DISABLE_FIFO 0x00 +#define SLBE 0x10 +#define SFWR 0x08 +#define BYTE_LANE0 0x04 +#define BYTE_LANE1 0x05 +#define BYTE_LANE2 0x06 +#define BYTE_LANE3 0x07 +#define SCSI_ZMODE 0x20 +#define ZMODE 0x40 +#define CTEST5_REG 0x19 +#define MASTER_CONTROL 0x10 +#define DMA_DIRECTION 0x08 +#define CTEST7_REG 0x1B +#define DFP 0x08 +#define EVP 0x04 +#define DIFF 0x01 +#define CTEST6_REG 0x1A +#define TEMP_REG 0x1C +#define DFIFO_REG 0x20 +#define FLUSH_DMA_FIFO 0x80 +#define CLR_FIFO 0x40 +#define ISTAT_REG 0x21 +#define ABORT_OPERATION 0x80 +#define DMA_INT_PENDING 0x01 +#define SCSI_INT_PENDING 0x02 +#define CONNECTED 0x08 +#define CTEST8_REG 0x22 +#define LAST_DIS_ENBL 0x01 +#define SHORTEN_FILTERING 0x04 +#define ENABLE_ACTIVE_NEGATION 0x10 +#define GENERATE_RECEIVE_PARITY 0x20 +#define CTEST9_REG 0x23 +#define DBC_REG 0x24 +#define DCMD_REG 0x27 +#define DNAD_REG 0x28 +#define DIEN_REG 0x39 +#define ABORT_INT 0x10 +#define INT_INST_INT 0x04 +#define WD_INT 0x02 +#define ILGL_INST_INT 0x01 +#define DCNTL_REG 0x3B +#define SOFTWARE_RESET 0x01 +#define SCRPTS_16BITS 0x20 +#define ASYNC_DIV_2_0 0x00 +#define ASYNC_DIV_1_5 0x01 +#define ASYNC_DIV_1_0 0x02 +#define ASYNC_DIV_3_0 0x03 +#define DMODE_REG 0x34 +#define BURST_LENGTH_1 0x00 +#define BURST_LENGTH_2 0x40 +#define BURST_LENGTH_4 0x80 +#define BURST_LENGTH_8 0xC0 +#define BW16 32 +#define MODE_286 16 +#define IO_XFER 8 +#define FIXED_ADDR 4 + +#define DSP_REG 0x2C +#define DSPS_REG 0x30 + +/* Parameters to begin SDTR negotiations. Empirically, I find that + * the 53c700-66 cannot handle an offset >8, so don't change this */ +#define NCR_700_MAX_OFFSET 8 +#define NCR_700_MIN_XFERP 1 +#define NCR_700_MIN_PERIOD 25 /* for SDTR message, 100ns */ + +#define script_patch_32(script, symbol, value) \ +{ \ + int i; \ + for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ + __u32 val = bS_to_cpu((script)[A_##symbol##_used[i]]) + value; \ + (script)[A_##symbol##_used[i]] = bS_to_host(val); \ + dma_cache_wback((unsigned long)&(script)[A_##symbol##_used[i]], 4); \ + DEBUG((" script, patching %s at %d to 0x%lx\n", \ + #symbol, A_##symbol##_used[i], (value))); \ + } \ +} + +#define script_patch_32_abs(script, symbol, value) \ +{ \ + int i; \ + for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ + (script)[A_##symbol##_used[i]] = bS_to_host(value); \ + dma_cache_wback((unsigned long)&(script)[A_##symbol##_used[i]], 4); \ + DEBUG((" script, patching %s at %d to 0x%lx\n", \ + #symbol, A_##symbol##_used[i], (value))); \ + } \ +} + +/* Used for patching the SCSI ID in the SELECT instruction */ +#define script_patch_ID(script, symbol, value) \ +{ \ + int i; \ + for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ + __u32 val = bS_to_cpu((script)[A_##symbol##_used[i]]); \ + val &= 0xff00ffff; \ + val |= ((value) & 0xff) << 16; \ + (script)[A_##symbol##_used[i]] = bS_to_host(val); \ + dma_cache_wback((unsigned long)&(script)[A_##symbol##_used[i]], 4); \ + DEBUG((" script, patching ID field %s at %d to 0x%x\n", \ + #symbol, A_##symbol##_used[i], val)); \ + } \ +} + +#define script_patch_16(script, symbol, value) \ +{ \ + int i; \ + for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ + __u32 val = bS_to_cpu((script)[A_##symbol##_used[i]]); \ + val &= 0xffff0000; \ + val |= ((value) & 0xffff); \ + (script)[A_##symbol##_used[i]] = bS_to_host(val); \ + dma_cache_wback((unsigned long)&(script)[A_##symbol##_used[i]], 4); \ + DEBUG((" script, patching ID field %s at %d to 0x%x\n", \ + #symbol, A_##symbol##_used[i], val)); \ + } \ +} + +#endif + +#ifdef MEM_MAPPED +static inline __u8 +NCR_700_readb(struct Scsi_Host *host, __u32 reg) +{ + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + return readb(host->base + (reg^bE)); +} + +static inline __u32 +NCR_700_readl(struct Scsi_Host *host, __u32 reg) +{ + __u32 value = readl(host->base + reg); + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; +#if 1 + /* sanity check the register */ + if((reg & 0x3) != 0) + BUG(); +#endif + + return bS_to_cpu(value); +} + +static inline void +NCR_700_writeb(__u8 value, struct Scsi_Host *host, __u32 reg) +{ + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + writeb(value, host->base + (reg^bE)); +} + +static inline void +NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg) +{ + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + +#if 1 + /* sanity check the register */ + if((reg & 0x3) != 0) + BUG(); +#endif + + writel(bS_to_host(value), host->base + reg); +} +#elif defined(IO_MAPPED) +static inline __u8 +NCR_700_readb(struct Scsi_Host *host, __u32 reg) +{ + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + return inb(host->base + (reg^bE)); +} + +static inline __u32 +NCR_700_readl(struct Scsi_Host *host, __u32 reg) +{ + __u32 value = inl(host->base + reg); + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + +#if 1 + /* sanity check the register */ + if((reg & 0x3) != 0) + BUG(); +#endif + + return bS_to_cpu(value); +} + +static inline void +NCR_700_writeb(__u8 value, struct Scsi_Host *host, __u32 reg) +{ + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + outb(value, host->base + (reg^bE)); +} + +static inline void +NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg) +{ + const struct NCR_700_Host_Parameters *hostdata __attribute__((unused)) + = (struct NCR_700_Host_Parameters *)host->hostdata[0]; + +#if 1 + /* sanity check the register */ + if((reg & 0x3) != 0) + BUG(); +#endif + + outl(bS_to_host(value), host->base + reg); +} +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/53c700.scr linux/drivers/scsi/53c700.scr --- v2.4.9/linux/drivers/scsi/53c700.scr Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/53c700.scr Sun Sep 9 10:50:48 2001 @@ -0,0 +1,404 @@ +; Script for the NCR (or symbios) 53c700 and 53c700-66 chip +; +; Copyright (C) 2001 James.Bottomley@HansenPartnership.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 script is designed to be modified for the particular command in +; operation. The particular variables pertaining to the commands are: +; +ABSOLUTE Device_ID = 0 ; ID of target for command +ABSOLUTE MessageCount = 0 ; Number of bytes in message +ABSOLUTE MessageLocation = 0 ; Addr of message +ABSOLUTE CommandCount = 0 ; Number of bytes in command +ABSOLUTE CommandAddress = 0 ; Addr of Command +ABSOLUTE StatusAddress = 0 ; Addr to receive status return +ABSOLUTE ReceiveMsgAddress = 0 ; Addr to receive msg +; +; This is the magic component for handling scatter-gather. Each of the +; SG components is preceeded by a script fragment which moves the +; necessary amount of data and jumps to the next SG segment. The final +; SG segment jumps back to . However, this address is the first SG script +; segment. +; +ABSOLUTE SGScriptStartAddress = 0 + +; The following represent status interrupts we use 3 hex digits for +; this: 0xPRS where + +; P: +ABSOLUTE AFTER_SELECTION = 0x100 +ABSOLUTE BEFORE_CMD = 0x200 +ABSOLUTE AFTER_CMD = 0x300 +ABSOLUTE AFTER_STATUS = 0x400 +ABSOLUTE AFTER_DATA_IN = 0x500 +ABSOLUTE AFTER_DATA_OUT = 0x600 +ABSOLUTE DURING_DATA_IN = 0x700 + +; R: +ABSOLUTE NOT_MSG_OUT = 0x10 +ABSOLUTE UNEXPECTED_PHASE = 0x20 +ABSOLUTE NOT_MSG_IN = 0x30 +ABSOLUTE UNEXPECTED_MSG = 0x40 +ABSOLUTE MSG_IN = 0x50 +ABSOLUTE SDTR_MSG_R = 0x60 +ABSOLUTE REJECT_MSG_R = 0x70 +ABSOLUTE DISCONNECT = 0x80 +ABSOLUTE MSG_OUT = 0x90 +ABSOLUTE WDTR_MSG_R = 0xA0 + +; S: +ABSOLUTE GOOD_STATUS = 0x1 + +; Combinations, since the script assembler can't process | +ABSOLUTE NOT_MSG_OUT_AFTER_SELECTION = 0x110 +ABSOLUTE UNEXPECTED_PHASE_BEFORE_CMD = 0x220 +ABSOLUTE UNEXPECTED_PHASE_AFTER_CMD = 0x320 +ABSOLUTE NOT_MSG_IN_AFTER_STATUS = 0x430 +ABSOLUTE GOOD_STATUS_AFTER_STATUS = 0x401 +ABSOLUTE UNEXPECTED_PHASE_AFTER_DATA_IN = 0x520 +ABSOLUTE UNEXPECTED_PHASE_AFTER_DATA_OUT = 0x620 +ABSOLUTE UNEXPECTED_MSG_BEFORE_CMD = 0x240 +ABSOLUTE MSG_IN_BEFORE_CMD = 0x250 +ABSOLUTE MSG_IN_AFTER_CMD = 0x350 +ABSOLUTE SDTR_MSG_BEFORE_CMD = 0x260 +ABSOLUTE REJECT_MSG_BEFORE_CMD = 0x270 +ABSOLUTE DISCONNECT_AFTER_CMD = 0x380 +ABSOLUTE SDTR_MSG_AFTER_CMD = 0x360 +ABSOLUTE WDTR_MSG_AFTER_CMD = 0x3A0 +ABSOLUTE DISCONNECT_AFTER_DATA = 0x580 +ABSOLUTE MSG_IN_AFTER_DATA_IN = 0x550 +ABSOLUTE MSG_IN_AFTER_DATA_OUT = 0x650 +ABSOLUTE MSG_OUT_AFTER_DATA_IN = 0x590 +ABSOLUTE DATA_IN_AFTER_DATA_IN = 0x5a0 +ABSOLUTE MSG_IN_DURING_DATA_IN = 0x750 +ABSOLUTE DISCONNECT_DURING_DATA = 0x780 + +; +; Other interrupt conditions +; +ABSOLUTE RESELECTED_DURING_SELECTION = 0x1000 +ABSOLUTE COMPLETED_SELECTION_AS_TARGET = 0x1001 +ABSOLUTE RESELECTION_IDENTIFIED = 0x1003 +; +; Fatal interrupt conditions. If you add to this, also add to the +; array of corresponding messages +; +ABSOLUTE FATAL = 0x2000 +ABSOLUTE FATAL_UNEXPECTED_RESELECTION_MSG = 0x2000 +ABSOLUTE FATAL_SEND_MSG = 0x2001 +ABSOLUTE FATAL_NOT_MSG_IN_AFTER_SELECTION = 0x2002 +ABSOLUTE FATAL_ILLEGAL_MSG_LENGTH = 0x2003 + +ABSOLUTE DEBUG_INTERRUPT = 0x3000 +ABSOLUTE DEBUG_INTERRUPT1 = 0x3001 +ABSOLUTE DEBUG_INTERRUPT2 = 0x3002 +ABSOLUTE DEBUG_INTERRUPT3 = 0x3003 +ABSOLUTE DEBUG_INTERRUPT4 = 0x3004 +ABSOLUTE DEBUG_INTERRUPT5 = 0x3005 +ABSOLUTE DEBUG_INTERRUPT6 = 0x3006 + + +; +; SCSI Messages we interpret in the script +; +ABSOLUTE EXTENDED_MSG = 0x01 +ABSOLUTE SDTR_MSG = 0x01 +ABSOLUTE SAVE_DATA_PTRS_MSG = 0x02 +ABSOLUTE RESTORE_DATA_PTRS_MSG = 0x03 +ABSOLUTE WDTR_MSG = 0x03 +ABSOLUTE DISCONNECT_MSG = 0x04 +ABSOLUTE REJECT_MSG = 0x07 +ABSOLUTE PARITY_ERROR_MSG = 0x09 +ABSOLUTE SIMPLE_TAG_MSG = 0x20 +ABSOLUTE IDENTIFY_MSG = 0x80 +ABSOLUTE IDENTIFY_MSG_MASK = 0x7F +ABSOLUTE TWO_BYTE_MSG = 0x20 +ABSOLUTE TWO_BYTE_MSG_MASK = 0x0F + +; This is where the script begins + +ENTRY StartUp + +StartUp: + SELECT ATN Device_ID, Reselect + JUMP Finish, WHEN STATUS + JUMP SendIdentifyMsg, IF MSG_OUT + INT NOT_MSG_OUT_AFTER_SELECTION + +Reselect: + WAIT RESELECT SelectedAsTarget + INT RESELECTED_DURING_SELECTION, WHEN MSG_IN + INT FATAL_NOT_MSG_IN_AFTER_SELECTION + + ENTRY GetReselectionData +GetReselectionData: + MOVE 1, ReceiveMsgAddress, WHEN MSG_IN + INT RESELECTION_IDENTIFIED + + ENTRY GetReselectionWithTag +GetReselectionWithTag: + MOVE 3, ReceiveMsgAddress, WHEN MSG_IN + INT RESELECTION_IDENTIFIED + + ENTRY SelectedAsTarget +SelectedAsTarget: +; Basically tell the selecting device that there's nothing here + SET TARGET + DISCONNECT + CLEAR TARGET + INT COMPLETED_SELECTION_AS_TARGET +; +; These are the messaging entries +; +; Send a message. Message count should be correctly patched + ENTRY SendMessage +SendMessage: + MOVE MessageCount, MessageLocation, WHEN MSG_OUT +ResumeSendMessage: + RETURN, WHEN NOT MSG_OUT + INT FATAL_SEND_MSG + + ENTRY SendMessagePhaseMismatch +SendMessagePhaseMismatch: + CLEAR ACK + JUMP ResumeSendMessage +; +; Receive a message. Need to identify the message to +; receive it correctly + ENTRY ReceiveMessage +ReceiveMessage: + MOVE 1, ReceiveMsgAddress, WHEN MSG_IN +; +; Use this entry if we've just tried to look at the first byte +; of the message and want to process it further +ProcessReceiveMessage: + JUMP ReceiveExtendedMessage, IF EXTENDED_MSG + RETURN, IF NOT TWO_BYTE_MSG, AND MASK TWO_BYTE_MSG_MASK + CLEAR ACK + MOVE 1, ReceiveMsgAddress + 1, WHEN MSG_IN + RETURN +ReceiveExtendedMessage: + CLEAR ACK + MOVE 1, ReceiveMsgAddress + 1, WHEN MSG_IN + JUMP Receive1Byte, IF 0x01 + JUMP Receive2Byte, IF 0x02 + JUMP Receive3Byte, IF 0x03 + JUMP Receive4Byte, IF 0x04 + JUMP Receive5Byte, IF 0x05 + INT FATAL_ILLEGAL_MSG_LENGTH +Receive1Byte: + CLEAR ACK + MOVE 1, ReceiveMsgAddress + 2, WHEN MSG_IN + RETURN +Receive2Byte: + CLEAR ACK + MOVE 2, ReceiveMsgAddress + 2, WHEN MSG_IN + RETURN +Receive3Byte: + CLEAR ACK + MOVE 3, ReceiveMsgAddress + 2, WHEN MSG_IN + RETURN +Receive4Byte: + CLEAR ACK + MOVE 4, ReceiveMsgAddress + 2, WHEN MSG_IN + RETURN +Receive5Byte: + CLEAR ACK + MOVE 5, ReceiveMsgAddress + 2, WHEN MSG_IN + RETURN +; +; Come here from the message processor to ignore the message +; + ENTRY IgnoreMessage +IgnoreMessage: + CLEAR ACK + RETURN +; +; Come here to send a reply to a message +; + ENTRY SendMessageWithATN +SendMessageWithATN: + SET ATN + CLEAR ACK + JUMP SendMessage + +SendIdentifyMsg: + CALL SendMessage + JUMP SendCommand + +IgnoreMsgBeforeCommand: + CLEAR ACK + ENTRY SendCommand +SendCommand: + JUMP Finish, WHEN STATUS + JUMP MsgInBeforeCommand, IF MSG_IN + INT UNEXPECTED_PHASE_BEFORE_CMD, IF NOT CMD + MOVE CommandCount, CommandAddress, WHEN CMD +ResumeSendCommand: + JUMP Finish, WHEN STATUS + JUMP MsgInAfterCmd, IF MSG_IN + JUMP DataIn, IF DATA_IN + JUMP DataOut, IF DATA_OUT + INT UNEXPECTED_PHASE_AFTER_CMD + +IgnoreMsgDuringData: + CLEAR ACK + ; fall through to MsgInDuringData + +Entry MsgInDuringData +MsgInDuringData: +; +; Could be we have nothing more to transfer +; + JUMP Finish, WHEN STATUS + MOVE 1, ReceiveMsgAddress, WHEN MSG_IN + JUMP DisconnectDuringDataIn, IF DISCONNECT_MSG + JUMP IgnoreMsgDuringData, IF SAVE_DATA_PTRS_MSG + JUMP IgnoreMsgDuringData, IF RESTORE_DATA_PTRS_MSG + INT MSG_IN_DURING_DATA_IN + +MsgInAfterCmd: + MOVE 1, ReceiveMsgAddress, WHEN MSG_IN + JUMP DisconnectAfterCmd, IF DISCONNECT_MSG + JUMP IgnoreMsgInAfterCmd, IF SAVE_DATA_PTRS_MSG + JUMP IgnoreMsgInAfterCmd, IF RESTORE_DATA_PTRS_MSG + CALL ProcessReceiveMessage + INT MSG_IN_AFTER_CMD + CLEAR ACK + JUMP ResumeSendCommand + +IgnoreMsgInAfterCmd: + CLEAR ACK + JUMP ResumeSendCommand + +DisconnectAfterCmd: + CLEAR ACK + WAIT DISCONNECT + ENTRY Disconnect1 +Disconnect1: + INT DISCONNECT_AFTER_CMD + ENTRY Disconnect2 +Disconnect2: +; We return here after a reselection + CLEAR ACK + JUMP ResumeSendCommand + +MsgInBeforeCommand: + MOVE 1, ReceiveMsgAddress, WHEN MSG_IN + JUMP IgnoreMsgBeforeCommand, IF SAVE_DATA_PTRS_MSG + JUMP IgnoreMsgBeforeCommand, IF RESTORE_DATA_PTRS_MSG + CALL ProcessReceiveMessage + INT MSG_IN_BEFORE_CMD + CLEAR ACK + JUMP SendCommand + +DataIn: + CALL SGScriptStartAddress +ResumeDataIn: + JUMP Finish, WHEN STATUS + JUMP MsgInAfterDataIn, IF MSG_IN + JUMP DataInAfterDataIn, if DATA_IN + INT MSG_OUT_AFTER_DATA_IN, if MSG_OUT + INT UNEXPECTED_PHASE_AFTER_DATA_IN + +DataInAfterDataIn: + INT DATA_IN_AFTER_DATA_IN + JUMP ResumeDataIn + +DataOut: + CALL SGScriptStartAddress +ResumeDataOut: + JUMP Finish, WHEN STATUS + JUMP MsgInAfterDataOut, IF MSG_IN + INT UNEXPECTED_PHASE_AFTER_DATA_OUT + +MsgInAfterDataIn: + MOVE 1, ReceiveMsgAddress, WHEN MSG_IN + JUMP DisconnectAfterDataIn, IF DISCONNECT_MSG + JUMP IgnoreMsgAfterData, IF SAVE_DATA_PTRS_MSG + JUMP IgnoreMsgAfterData, IF RESTORE_DATA_PTRS_MSG + CALL ProcessReceiveMessage + INT MSG_IN_AFTER_DATA_IN + CLEAR ACK + JUMP ResumeDataIn + +DisconnectDuringDataIn: + CLEAR ACK + WAIT DISCONNECT + ENTRY Disconnect3 +Disconnect3: + INT DISCONNECT_DURING_DATA + ENTRY Disconnect4 +Disconnect4: +; we return here after a reselection + CLEAR ACK + JUMP ResumeSendCommand + + +DisconnectAfterDataIn: + CLEAR ACK + WAIT DISCONNECT + ENTRY Disconnect5 +Disconnect5: + INT DISCONNECT_AFTER_DATA + ENTRY Disconnect6 +Disconnect6: +; we return here after a reselection + CLEAR ACK + JUMP ResumeDataIn + +MsgInAfterDataOut: + MOVE 1, ReceiveMsgAddress, WHEN MSG_IN + JUMP DisconnectAfterDataOut, if DISCONNECT_MSG + JUMP IgnoreMsgAfterData, IF SAVE_DATA_PTRS_MSG + JUMP IgnoreMsgAfterData, IF RESTORE_DATA_PTRS_MSG + CALL ProcessReceiveMessage + INT MSG_IN_AFTER_DATA_OUT + CLEAR ACK + JUMP ResumeDataOut + +IgnoreMsgAfterData: + CLEAR ACK +; Data in and out do the same thing on resume, so pick one + JUMP ResumeDataIn + +DisconnectAfterDataOut: + CLEAR ACK + WAIT DISCONNECT + ENTRY Disconnect7 +Disconnect7: + INT DISCONNECT_AFTER_DATA + ENTRY Disconnect8 +Disconnect8: +; we return here after a reselection + CLEAR ACK + JUMP ResumeDataOut + +Finish: + MOVE 1, StatusAddress, WHEN STATUS + INT NOT_MSG_IN_AFTER_STATUS, WHEN NOT MSG_IN + CALL ReceiveMessage + CLEAR ACK + WAIT DISCONNECT + ENTRY Finish1 +Finish1: + INT GOOD_STATUS_AFTER_STATUS + ENTRY Finish2 +Finish2: + diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.4.9/linux/drivers/scsi/Config.in Wed Jul 25 17:10:22 2001 +++ linux/drivers/scsi/Config.in Sun Sep 9 10:52:35 2001 @@ -33,7 +33,7 @@ comment 'SCSI low-level drivers' if [ "$CONFIG_SGI_IP22" = "y" ]; then - dep_tristate 'SGI WD93C93 SCSI Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI + dep_tristate 'SGI WD93C93 SCSI Driver' CONFIG_SGIWD93_SCSI $CONFIG_SCSI fi if [ "$CONFIG_DECSTATION" = "y" ]; then if [ "$CONFIG_TC" = "y" ]; then @@ -59,6 +59,7 @@ bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_OLD_PROC_STATS fi fi +dep_tristate 'Adaptec I2O RAID support ' CONFIG_SCSI_DPT_I2O $CONFIG_SCSI dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI $CONFIG_PCI @@ -85,7 +86,7 @@ if [ "$CONFIG_MCA" = "y" ]; then dep_tristate 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS $CONFIG_SCSI fi -dep_tristate 'GDT SCSI Disk Array Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI +dep_tristate 'Intel/ICP (former GDT SCSI Disk Array) RAID Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then bool ' Enable NCR53c400 extensions' CONFIG_SCSI_GENERIC_NCR53C400 @@ -114,6 +115,10 @@ fi fi dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI +dep_tristate 'NCR Dual 700 MCA SCSI support' CONFIG_SCSI_NCR_D700 $CONFIG_SCSI $CONFIG_MCA +if [ "$CONFIG_PARISC" = "y" ]; then + dep_tristate 'HP LASI SCSI support for 53c700' CONFIG_SCSI_LASI70 $CONFIG_SCSI +fi dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI $CONFIG_PCI if [ "$CONFIG_SCSI_NCR53C7xx" != "n" ]; then bool ' always negotiate synchronous transfers' CONFIG_SCSI_NCR53C7xx_sync @@ -151,6 +156,9 @@ if [ "$CONFIG_PCI" = "y" ]; then dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI + if [ "$CONFIG_SCSI_QLOGIC_FC" != "n" ]; then + bool ' Include loadable firmware in driver' CONFIG_SCSI_QLOGIC_FC_FIRMWARE + fi dep_tristate 'Qlogic QLA 1280 SCSI support' CONFIG_SCSI_QLOGIC_1280 $CONFIG_SCSI fi if [ "$CONFIG_X86" = "y" ]; then diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.4.9/linux/drivers/scsi/Makefile Fri May 4 15:16:28 2001 +++ linux/drivers/scsi/Makefile Wed Sep 12 15:35:39 2001 @@ -31,7 +31,7 @@ endif endif -export-objs := scsi_syms.o +export-objs := scsi_syms.o 53c700.o 53c700-mem.o CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS @@ -47,6 +47,7 @@ obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o +obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o @@ -65,6 +66,7 @@ obj-$(CONFIG_SCSI_PCI2220I) += pci2220i.o obj-$(CONFIG_SCSI_PSI240I) += psi240i.o obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o +obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o obj-$(CONFIG_SCSI_ULTRASTOR) += ultrastor.o obj-$(CONFIG_SCSI_AHA152X) += aha152x.o @@ -80,6 +82,7 @@ obj-$(CONFIG_SCSI_IN2000) += in2000.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o +obj-$(CONFIG_SCSI_NCR_D700) += NCR_D700.o 53c700.o obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas.o obj-$(CONFIG_SCSI_QLOGIC_ISP) += qlogicisp.o @@ -121,6 +124,8 @@ obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o obj-$(CONFIG_SCSI_FCAL) += fcal.o +obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o +obj-$(CONFIG_SCSI_LASI700) += lasi700.o 53c700-mem.o ifeq ($(CONFIG_ARCH_ACORN),y) mod-subdirs += ../acorn/scsi @@ -134,7 +139,7 @@ obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o obj-$(CONFIG_CHR_DEV_SG) += sg.o -list-multi := scsi_mod.o sd_mod.o sr_mod.o initio.o a100u2w.o +list-multi := scsi_mod.o sd_mod.o sr_mod.o initio.o a100u2w.o cpqfc.o scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_proc.o scsi_error.o \ scsi_obsolete.o scsi_queue.o scsi_lib.o \ @@ -144,6 +149,7 @@ sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o initio-objs := ini9100u.o i91uscsi.o a100u2w-objs := inia100.o i60uscsi.o +cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o cpqfcTSworker.o cpqfcTStrigger.o include $(TOPDIR)/Rules.make @@ -163,6 +169,9 @@ a100u2w.o: $(a100u2w-objs) $(LD) -r -o $@ $(a100u2w-objs) +cpqfc.o: $(cpqfc-objs) + $(LD) -r -o $@ $(cpqfc-objs) + 53c8xx_d.h: 53c7,8xx.scr script_asm.pl ln -sf 53c7,8xx.scr fake8.c $(CPP) $(CPPFLAGS) -traditional -DCHIP=810 fake8.c | grep -v '^#' | $(PERL) script_asm.pl @@ -193,3 +202,17 @@ sim710_u.h: sim710_d.h sim710.o : sim710_d.h + +53c700_d.h: 53c700.scr script_asm.pl + $(PERL) -s script_asm.pl -ncr7x0_family < 53c700.scr + rm -f scriptu.h + mv script.h 53c700_d.h + +53c700.o: 53c700_d.h + +53c700-mem.o: 53c700_d.h + +53c700-mem.c: 53c700.c + echo "/* WARNING: GENERATED FILE (from $<), DO NOT MODIFY */" > $@ + echo "#define MEM_MAPPED" >> $@ + cat $< >> $@ diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/NCR53C9x.h linux/drivers/scsi/NCR53C9x.h --- v2.4.9/linux/drivers/scsi/NCR53C9x.h Sun Jul 9 22:22:57 2000 +++ linux/drivers/scsi/NCR53C9x.h Fri Sep 14 14:40:00 2001 @@ -140,7 +140,7 @@ * Yet, they all live within the same IO space. */ -#ifndef __i386__ +#if !defined(__i386__) && !defined(__x86_64__) #ifndef MULTIPLE_PAD_SIZES @@ -232,7 +232,7 @@ #endif -#else /* !defined __i386__ */ +#else /* !defined(__i386__) && !defined(__x86_64__) */ #define esp_write(__reg, __val) outb((__val), (__reg)) #define esp_read(__reg) inb((__reg)) @@ -267,7 +267,7 @@ #define esp_fgrnd io_addr + 15 /* rw Data base for fifo 0x3c */ }; -#endif /* !defined(__i386__) */ +#endif /* !defined(__i386__) && !defined(__x86_64__) */ /* Various revisions of the ESP board. */ enum esp_rev { diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/NCR_D700.c linux/drivers/scsi/NCR_D700.c --- v2.4.9/linux/drivers/scsi/NCR_D700.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/NCR_D700.c Sun Sep 9 11:58:36 2001 @@ -0,0 +1,326 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* NCR Dual 700 MCA SCSI Driver + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.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. +** +**----------------------------------------------------------------------------- + */ + +/* Notes: + * + * Most of the work is done in the chip specific module, 53c700.o + * + * TODO List: + * + * 1. Extract the SCSI ID from the voyager CMOS table (necessary to + * support multi-host environments. + * + * */ + + +/* CHANGELOG + * + * Version 2.1 + * + * Modularise the driver into a Board piece (this file) and a chip + * piece 53c700.[ch] and 53c700.scr, added module options. You can + * now specify the scsi id by the parameters + * + * NCR_D700=slot: [siop:] id: .... + * + * They need to be comma separated if compiled into the kernel + * + * Version 2.0 + * + * Initial implementation of TCQ (Tag Command Queueing). TCQ is full + * featured and uses the clock algorithm to keep track of outstanding + * tags and guard against individual tag starvation. Also fixed a bug + * in all of the 1.x versions where the D700_data_residue() function + * was returning results off by 32 bytes (and thus causing the same 32 + * bytes to be written twice corrupting the data block). It turns out + * the 53c700 only has a 6 bit DBC and DFIFO registers not 7 bit ones + * like the 53c710 (The 710 is the only data manual still available, + * which I'd been using to program the 700). + * + * Version 1.2 + * + * Much improved message handling engine + * + * Version 1.1 + * + * Add code to handle selection reasonably correctly. By the time we + * get the selection interrupt, we've already responded, but drop off the + * bus and hope the selector will go away. + * + * Version 1.0: + * + * Initial release. Fully functional except for procfs and tag + * command queueing. Has only been tested on cards with 53c700-66 + * chips and only single ended. Features are + * + * 1. Synchronous data transfers to offset 8 (limit of 700-66) and + * 100ns (10MHz) limit of SCSI-2 + * + * 2. Disconnection and reselection + * + * Testing: + * + * I've only really tested this with the 700-66 chip, but have done + * soak tests in multi-device environments to verify that + * disconnections and reselections are being processed correctly. + * */ + +#define NCR_D700_VERSION "2.1" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "scsi.h" +#include "hosts.h" +#include "constants.h" + +#include "53c700.h" +#include "NCR_D700.h" + +#ifndef CONFIG_MCA +#error "NCR_D700 driver only compiles for MCA" +#endif + +#ifdef NCR_D700_DEBUG +#define STATIC +#else +#define STATIC static +#endif + +char *NCR_D700; /* command line from insmod */ + +MODULE_AUTHOR("James Bottomley"); +MODULE_DESCRIPTION("NCR Dual700 SCSI Driver"); +MODULE_LICENSE("GPL"); +MODULE_PARM(NCR_D700, "s"); + +static __u8 __initdata id_array[2*(MCA_MAX_SLOT_NR + 1)] = + { [0 ... 2*(MCA_MAX_SLOT_NR + 1)-1] = 7 }; + +#ifdef MODULE +#define ARG_SEP ' ' +#else +#define ARG_SEP ',' +#endif + +static int __init +param_setup(char *string) +{ + char *pos = string, *next; + int slot = -1, siop = -1; + + while(pos != NULL && (next = strchr(pos, ':')) != NULL) { + int val = (int)simple_strtoul(++next, NULL, 0); + + if(!strncmp(pos, "slot:", 5)) + slot = val; + else if(!strncmp(pos, "siop:", 5)) + siop = val; + else if(!strncmp(pos, "id:", 3)) { + if(slot == -1) { + printk(KERN_WARNING "NCR D700: Must specify slot for id parameter\n"); + } else if(slot > MCA_MAX_SLOT_NR) { + printk(KERN_WARNING "NCR D700: Illegal slot %d for id %d\n", slot, val); + } else { + if(siop != 0 && siop != 1) { + id_array[slot*2] = val; + id_array[slot*2 + 1] =val; + } else { + id_array[slot*2 + siop] = val; + } + } + } + if((pos = strchr(pos, ARG_SEP)) != NULL) + pos++; + } + return 1; +} + +#ifndef MODULE +__setup("NCR_D700=", param_setup); +#endif + +/* Detect a D700 card. Note, because of the set up---the chips are + * essentially connectecd to the MCA bus independently, it is easier + * to set them up as two separate host adapters, rather than one + * adapter with two channels */ +STATIC int __init +D700_detect(Scsi_Host_Template *tpnt) +{ + int slot = 0; + int found = 0; + int differential; + int banner = 1; + + if(!MCA_bus) + return 0; + +#ifdef MODULE + if(NCR_D700) + param_setup(NCR_D700); +#endif + + for(slot = 0; (slot = mca_find_adapter(NCR_D700_MCA_ID, slot)) != MCA_NOTFOUND; slot++) { + int irq, i; + int pos3j, pos3k, pos3a, pos3b, pos4; + __u32 base_addr, offset_addr; + struct Scsi_Host *host = NULL; + + /* enable board interrupt */ + pos4 = mca_read_pos(slot, 4); + pos4 |= 0x4; + mca_write_pos(slot, 4, pos4); + + mca_write_pos(slot, 6, 9); + pos3j = mca_read_pos(slot, 3); + mca_write_pos(slot, 6, 10); + pos3k = mca_read_pos(slot, 3); + mca_write_pos(slot, 6, 0); + pos3a = mca_read_pos(slot, 3); + mca_write_pos(slot, 6, 1); + pos3b = mca_read_pos(slot, 3); + + base_addr = ((pos3j << 8) | pos3k) & 0xfffffff0; + offset_addr = ((pos3a << 8) | pos3b) & 0xffffff70; + + irq = (pos4 & 0x3) + 11; + if(irq >= 13) + irq++; + if(banner) { + printk(KERN_NOTICE "NCR D700: Driver Version " NCR_D700_VERSION "\n" + "NCR D700: Copyright (c) 2001 by James.Bottomley@HansenPartnership.com\n" + "NCR D700:\n"); + banner = 0; + } + printk(KERN_NOTICE "NCR D700: found in slot %d irq = %d I/O base = 0x%x\n", slot, irq, offset_addr); + + tpnt->proc_name = "NCR_D700"; + + /*outb(BOARD_RESET, base_addr);*/ + + /* clear any pending interrupts */ + (void)inb(base_addr + 0x08); + /* get modctl, used later for setting diff bits */ + switch(differential = (inb(base_addr + 0x08) >> 6)) { + case 0x00: + /* only SIOP1 differential */ + differential = 0x02; + break; + case 0x01: + /* Both SIOPs differential */ + differential = 0x03; + break; + case 0x03: + /* No SIOPs differential */ + differential = 0x00; + break; + default: + printk(KERN_ERR "D700: UNEXPECTED DIFFERENTIAL RESULT 0x%02x\n", + differential); + differential = 0x00; + break; + } + + /* plumb in both 700 chips */ + for(i=0; i<2; i++) { + __u32 region = offset_addr | (0x80 * i); + struct NCR_700_Host_Parameters *hostdata = + kmalloc(sizeof(struct NCR_700_Host_Parameters), + GFP_KERNEL); + if(hostdata == NULL) { + printk(KERN_ERR "NCR D700: Failed to allocate host data for channel %d, detatching\n", i); + continue; + } + memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); + if(request_region(region, 64, "NCR_D700") == NULL) { + printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n", region); + kfree(hostdata); + continue; + } + + /* Fill in the three required pieces of hostdata */ + hostdata->base = region; + hostdata->differential = (((1<clock = NCR_D700_CLOCK_MHZ; + /* and register the chip */ + if((host = NCR_700_detect(tpnt, hostdata)) == NULL) { + kfree(hostdata); + release_region(host->base, 64); + continue; + } + host->irq = irq; + /* FIXME: Read this from SUS */ + host->this_id = id_array[slot * 2 + i]; + printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n", + i, host->this_id); + if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) { + printk(KERN_ERR "NCR D700, channel %d: irq problem, detatching\n", i); + scsi_unregister(host); + NCR_700_release(host); + continue; + } + found++; + } + } + + return found; +} + + +STATIC int +D700_release(struct Scsi_Host *host) +{ + struct D700_Host_Parameters *hostdata = + (struct D700_Host_Parameters *)host->hostdata[0]; + + NCR_700_release(host); + kfree(hostdata); + free_irq(host->irq, host); + release_region(host->base, 64); + return 1; +} + + +static Scsi_Host_Template driver_template = NCR_D700_SCSI; + +#include "scsi_module.c" + diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/NCR_D700.h linux/drivers/scsi/NCR_D700.h --- v2.4.9/linux/drivers/scsi/NCR_D700.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/NCR_D700.h Sun Sep 9 11:58:36 2001 @@ -0,0 +1,45 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* NCR Dual 700 MCA SCSI Driver + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com + */ + +#ifndef _NCR_D700_H +#define _NCR_D700_H + +/* Don't turn on debugging messages */ +#undef NCR_D700_DEBUG + +/* The MCA identifier */ +#define NCR_D700_MCA_ID 0x0092 + +static int D700_detect(Scsi_Host_Template *); +static int D700_release(struct Scsi_Host *host); + + +/* Host template. Note the name and proc_name are optional, all the + * remaining parameters shown below must be filled in. The 53c700 + * routine NCR_700_detect will fill in all of the missing routines */ +#define NCR_D700_SCSI { \ + name: "NCR Dual 700 MCA", \ + proc_name: "NCR_D700", \ + detect: D700_detect, \ + release: D700_release, \ + this_id: 7, \ +} + + +/* Defines for the Board registers */ +#define BOARD_RESET 0x80 /* board level reset */ +#define ADD_PARENB 0x04 /* Address Parity Enabled */ +#define DAT_PARENB 0x01 /* Data Parity Enabled */ +#define SFBK_ENB 0x10 /* SFDBK Interrupt Enabled */ +#define LED0GREEN 0x20 /* Led 0 (red 0; green 1) */ +#define LED1GREEN 0x40 /* Led 1 (red 0; green 1) */ +#define LED0RED 0xDF /* Led 0 (red 0; green 1) */ +#define LED1RED 0xBF /* Led 1 (red 0; green 1) */ + +#define NCR_D700_CLOCK_MHZ 50 + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/README.53c700 linux/drivers/scsi/README.53c700 --- v2.4.9/linux/drivers/scsi/README.53c700 Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/README.53c700 Sun Sep 9 11:58:36 2001 @@ -0,0 +1,17 @@ +This driver supports the 53c700 and 53c700-66 chips only. It is full +featured and does sync (-66 only), disconnects and tag command +queueing. + +Since the 53c700 must be interfaced to a bus, you need to wrapper the +card detector around this driver. For an example, see the +NCR_D700.[ch] files. + +The comments in the 53c700.[ch] files tell you which parts you need to +fill in to get the driver working. + +The driver is currently I/O mapped only, but it should be easy enough +to memory map (just make the port reads #defines with MEM_MAPPED for +memory mapping or nothing for I/O mapping, specify an extra rule for +53c700-mem.o with the -DMEM_MAPPED flag and make your driver use it, +that way the make rules will generate the correct version). + diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/README.dpti linux/drivers/scsi/README.dpti --- v2.4.9/linux/drivers/scsi/README.dpti Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/README.dpti Sun Sep 9 10:52:35 2001 @@ -0,0 +1,83 @@ + /* TERMS AND CONDITIONS OF USE + * + * 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 Adaptec 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 Adaptec 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. + * + **************************************************************** + * This driver supports the Adaptec I2O RAID and DPT SmartRAID V I2O boards. + * + * CREDITS: + * The original linux driver was ported to Linux by Karen White while at + * Dell Computer. It was ported from Bob Pasteur's (of DPT) original + * non-Linux driver. Mark Salyzyn and Bob Pasteur consulted on the original + * driver. + * + * 2.0 version of the driver by Deanna Bonds and Mark Salyzyn. + * + * HISTORY: + * The driver was originally ported to linux version 2.0.34 + * + * V2.0 Rewrite of driver. Re-architectured based on i2o subsystem. + * This was the first full GPL version since the last version used + * i2osig headers which were not GPL. Developer Testing version. + * V2.1 Internal testing + * V2.2 First released version + * + * V2.3 + * Changes: + * Added Raptor Support + * Fixed bug causing system to hang under extreme load with + * management utilities running (removed GFP_DMA from kmalloc flags) + * + * + * V2.4 First version ready to be submitted to be embedded in the kernel + * Changes: + * Implemented suggestions from Alan Cox + * Added calculation of resid for sg layer + * Better error handling + * Added checking underflow condtions + * Added DATAPROTECT checking + * Changed error return codes + * Fixed pointer bug in bus reset routine + * Enabled hba reset from ioctls (allows a FW flash to reboot and use the new + * FW without having to reboot) + * Changed proc output + * + * TODO: + * Add 64 bit Scatter Gather when compiled on 64 bit architectures + * Add sparse lun scanning + * Add code that checks if a device that had been taken offline is + * now online (at the FW level) when test unit ready or inquiry + * command from scsi-core + * Add proc read interface + * busrescan command + * rescan command + * Add code to rescan routine that notifies scsi-core about new devices + * Add support for C-PCI (hotplug stuff) + * Add ioctl passthru error recovery + * + * NOTES: + * The DPT card optimizes the order of processing commands. Consequently, + * a command may take up to 6 minutes to complete after it has been sent + * to the board. + * + * The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the + * interface files for Adaptecs managment routines. These define the structures used + * in the ioctls. They are written to be portable. They are hard to read, but I need + * to use them 'as is' or I can miss changes in the interface. + * + */ + 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/aic7xxx/aic7xxx_osm.h linux/drivers/scsi/aic7xxx/aic7xxx_osm.h --- v2.4.9/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h Mon Aug 27 12:41:44 2001 +++ linux/drivers/scsi/aic7xxx/aic7xxx_osm.h Fri Sep 14 14:40:00 2001 @@ -580,7 +580,7 @@ /***************************** Low Level I/O **********************************/ -#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) +#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) || defined(__x86_64__) #define MMAPIO #endif diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/aic7xxx_old/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_old/aic7xxx_proc.c --- v2.4.9/linux/drivers/scsi/aic7xxx_old/aic7xxx_proc.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/scsi/aic7xxx_old/aic7xxx_proc.c Tue Sep 18 14:10:43 2001 @@ -162,7 +162,7 @@ size += sprintf(BLS, "%s", AIC7XXX_H_VERSION); size += sprintf(BLS, "\n"); size += sprintf(BLS, "Compile Options:\n"); -#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT +#ifdef CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT size += sprintf(BLS, " TCQ Enabled By Default : Enabled\n"); #else size += sprintf(BLS, " TCQ Enabled By Default : Disabled\n"); diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/aic7xxx_old.c linux/drivers/scsi/aic7xxx_old.c --- v2.4.9/linux/drivers/scsi/aic7xxx_old.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/scsi/aic7xxx_old.c Tue Sep 18 14:10:44 2001 @@ -283,7 +283,7 @@ # define FALSE 0 #endif -#if defined(__powerpc__) || defined(__i386__) +#if defined(__powerpc__) || defined(__i386__) || defined(__x86_64__) # define MMAPIO #endif @@ -311,10 +311,10 @@ * You can try raising me if tagged queueing is enabled, or lowering * me if you only have 4 SCBs. */ -#ifdef CONFIG_AIC7XXX_CMDS_PER_DEVICE -#define AIC7XXX_CMDS_PER_DEVICE CONFIG_AIC7XXX_CMDS_PER_DEVICE +#ifdef CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE +#define AIC7XXX_CMDS_PER_DEVICE CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE #else -#define AIC7XXX_CMDS_PER_DEVICE 8 +#define AIC7XXX_CMDS_PER_DEVICE 32 #endif /* @@ -323,7 +323,7 @@ * NOTE: Do NOT enable this when running on kernels version 1.2.x and below. * NOTE: This does affect performance since it has to maintain statistics. */ -#ifdef CONFIG_AIC7XXX_PROC_STATS +#ifdef CONFIG_AIC7XXX_OLD_PROC_STATS #define AIC7XXX_PROC_STATS #endif @@ -347,7 +347,7 @@ * Make a define that will tell the driver not to use tagged queueing * by default. */ -#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT +#ifdef CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT #define DEFAULT_TAG_COMMANDS {0, 0, 0, 0, 0, 0, 0, 0,\ 0, 0, 0, 0, 0, 0, 0, 0} #else @@ -8865,6 +8865,7 @@ memset(p, 0, sizeof(struct aic7xxx_host)); *p = *temp; p->host = host; + host->max_sectors = 512; p->scb_data = kmalloc(sizeof(scb_data_type), GFP_ATOMIC); if (p->scb_data != NULL) diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/dec_esp.c linux/drivers/scsi/dec_esp.c --- v2.4.9/linux/drivers/scsi/dec_esp.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/scsi/dec_esp.c Sun Sep 9 10:52:35 2001 @@ -9,6 +9,14 @@ * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de) * * jazz_esp is based on David S. Miller's ESP driver and cyber_esp + * + * 20000819 - Small PMAZ-AA fixes by Florian Lohoff + * Be warned the PMAZ-AA works currently as a single card. + * Dont try to put multiple cards in one machine - They are + * both detected but it may crash under high load garbling your + * data. + * 20001005 - Initialization fixes for 2.4.0-test9 + * Florian Lohoff */ #include @@ -45,8 +53,6 @@ * starting point. #define this an be prepared for tons * of warnings and errors :) */ -#undef PMAZ_A - static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); static void dma_drain(struct NCR_ESP *esp); static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp); @@ -62,7 +68,6 @@ static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); static void dma_advance_sg(Scsi_Cmnd * sp); -#ifdef PMAZ_A static void pmaz_dma_drain(struct NCR_ESP *esp); static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); @@ -70,10 +75,6 @@ static void pmaz_dma_ints_on(struct NCR_ESP *esp); static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp); -static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); - -volatile int *scsi_pmaz_dma_ptr_tc; -#endif #define TC_ESP_RAM_SIZE 0x20000 #define ESP_TGT_DMA_SIZE ((TC_ESP_RAM_SIZE/7) & ~(sizeof(int)-1)) @@ -83,9 +84,6 @@ #define TC_ESP_DMAR_WRITE 0x80000000 #define TC_ESP_DMA_ADDR(x) ((unsigned)(x) & TC_ESP_DMAR_MASK) -volatile unsigned char *scsi_pmaz_dma_ptrs_tc[ESP_NCMD]; -unsigned char scsi_pmaz_dma_buff_used[ESP_NCMD]; -unsigned char scsi_cur_buff = 1; /* Leave space for command buffer */ __u32 esp_virt_buffer; int scsi_current_length; @@ -105,20 +103,21 @@ static void scsi_dma_int(int, void *, struct pt_regs *); +static Scsi_Host_Template driver_template = SCSI_DEC_ESP; + +#include "scsi_module.c" + /***************************************************************** Detection */ int dec_esp_detect(Scsi_Host_Template * tpnt) { struct NCR_ESP *esp; struct ConfigDev *esp_dev; -#ifdef PMAZ_A - int slot, i; + int slot; unsigned long mem_start; - volatile unsigned char *buffer; -#endif if (IOASIC) { - esp_dev = 0; - esp = esp_allocate(tpnt, (void *) esp_dev); + esp_dev = 0; + esp = esp_allocate(tpnt, (void *) esp_dev); scsi_dma_ptr = (unsigned long *) (system_base + IOCTL + SCSI_DMA_P); scsi_next_ptr = (unsigned long *) (system_base + IOCTL + SCSI_DMA_BP); @@ -127,86 +126,89 @@ scsi_sdr0 = (unsigned long *) (system_base + IOCTL + SCSI_SDR0); scsi_sdr1 = (unsigned long *) (system_base + IOCTL + SCSI_SDR1); - /* Do command transfer with programmed I/O */ - esp->do_pio_cmds = 1; + /* Do command transfer with programmed I/O */ + esp->do_pio_cmds = 1; - /* Required functions */ - esp->dma_bytes_sent = &dma_bytes_sent; - esp->dma_can_transfer = &dma_can_transfer; - esp->dma_dump_state = &dma_dump_state; - esp->dma_init_read = &dma_init_read; - esp->dma_init_write = &dma_init_write; - esp->dma_ints_off = &dma_ints_off; - esp->dma_ints_on = &dma_ints_on; - esp->dma_irq_p = &dma_irq_p; - esp->dma_ports_p = &dma_ports_p; - esp->dma_setup = &dma_setup; + /* Required functions */ + esp->dma_bytes_sent = &dma_bytes_sent; + esp->dma_can_transfer = &dma_can_transfer; + esp->dma_dump_state = &dma_dump_state; + esp->dma_init_read = &dma_init_read; + esp->dma_init_write = &dma_init_write; + esp->dma_ints_off = &dma_ints_off; + esp->dma_ints_on = &dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &dma_setup; - /* Optional functions */ - esp->dma_barrier = 0; + /* Optional functions */ + esp->dma_barrier = 0; esp->dma_drain = &dma_drain; - esp->dma_invalidate = 0; - esp->dma_irq_entry = 0; - esp->dma_irq_exit = 0; - esp->dma_poll = 0; - esp->dma_reset = 0; - esp->dma_led_off = 0; - esp->dma_led_on = 0; - - /* virtual DMA functions */ - esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one; - esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_poll = 0; + esp->dma_reset = 0; + esp->dma_led_off = 0; + esp->dma_led_on = 0; + + /* virtual DMA functions */ + esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one; + esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl; esp->dma_mmu_release_scsi_one = 0; esp->dma_mmu_release_scsi_sgl = 0; - esp->dma_advance_sg = &dma_advance_sg; + esp->dma_advance_sg = &dma_advance_sg; - /* SCSI chip speed */ + /* SCSI chip speed */ esp->cfreq = 25000000; - /* - * we don't give the address of DMA channel, but the number - * of DMA channel, so we can use the jazz DMA functions - * - */ - esp->dregs = JAZZ_SCSI_DMA; + /* + * we don't give the address of DMA channel, but the number + * of DMA channel, so we can use the jazz DMA functions + * + */ + esp->dregs = JAZZ_SCSI_DMA; - /* ESP register base */ + /* ESP register base */ esp->eregs = (struct ESP_regs *) (system_base + SCSI); - /* Set the command buffer */ + /* Set the command buffer */ esp->esp_command = (volatile unsigned char *) cmd_buffer; - /* get virtual dma address for command buffer */ + /* get virtual dma address for command buffer */ esp->esp_command_dvma = (__u32) KSEG1ADDR((volatile unsigned char *) cmd_buffer); esp->irq = SCSI_INT; + + esp->scsi_id = 7; + + /* Check for differential SCSI-bus */ + esp->diff = 0; + + esp_initialize(esp); + if (request_irq(esp->irq, esp_intr, SA_INTERRUPT, "NCR 53C94 SCSI", NULL)) goto err_dealloc; if (request_irq(SCSI_DMA_INT, scsi_dma_int, SA_INTERRUPT, "JUNKIO SCSI DMA", NULL)) goto err_free_irq; - - - esp->scsi_id = 7; - - /* Check for differential SCSI-bus */ - esp->diff = 0; - - esp_initialize(esp); - + } -#ifdef PMAZ_A if (TURBOCHANNEL) { - while ((slot = search_tc_card("PMAZ_AA")) >= 0) { + while ((slot = search_tc_card("PMAZ-AA")) >= 0) { claim_tc_card(slot); - mem_start = get_tc_base_addr(slot); esp_dev = 0; esp = esp_allocate(tpnt, (void *) esp_dev); + mem_start = get_tc_base_addr(slot); + + /* Store base addr into esp struct */ + esp->slot = mem_start; + esp->dregs = 0; esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG); esp->do_pio_cmds = 1; @@ -217,16 +219,6 @@ /* get virtual dma address for command buffer */ esp->esp_command_dvma = (__u32) KSEG0ADDR((volatile unsigned char *) pmaz_cmd_buffer); - buffer = (volatile unsigned char *) (mem_start + DEC_SCSI_SRAM); - - scsi_pmaz_dma_ptr_tc = (volatile int *) (mem_start + DEC_SCSI_DMAREG); - - for (i = 0; i < ESP_NCMD; i++) { - scsi_pmaz_dma_ptrs_tc[i] = (volatile unsigned char *) (buffer + ESP_TGT_DMA_SIZE * i); - } - - scsi_pmaz_dma_buff_used[0] = 1; - esp->cfreq = get_tc_speed(); esp->irq = get_tc_irq_nr(slot); @@ -260,18 +252,17 @@ esp->dma_mmu_release_scsi_sgl = 0; esp->dma_advance_sg = 0; - if (request_irq(esp->irq, esp_intr, SA_INTERRUPT, - "PMAZ_AA", NULL)) { - esp_deallocate(esp); - release_tc_card(slot); - continue; - } + if (request_irq(esp->irq, esp_intr, SA_INTERRUPT, + "PMAZ_AA", NULL)) { + esp_deallocate(esp); + release_tc_card(slot); + continue; + } esp->scsi_id = 7; esp->diff = 0; esp_initialize(esp); } } -#endif if(nesps) { printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use); @@ -476,30 +467,35 @@ sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address); } -#ifdef PMAZ_A - static void pmaz_dma_drain(struct NCR_ESP *esp) { memcpy((void *) (KSEG0ADDR(esp_virt_buffer)), - (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length); + (void *) ( esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE), + scsi_current_length); } static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) { + volatile int *dmareg = (volatile int *) (esp->slot + DEC_SCSI_DMAREG); if (length > ESP_TGT_DMA_SIZE) length = ESP_TGT_DMA_SIZE; - *scsi_pmaz_dma_ptr_tc = TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]); + *dmareg = TC_ESP_DMA_ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE); + esp_virt_buffer = vaddress; scsi_current_length = length; } static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length) { - memcpy((void *)scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length); + volatile int *dmareg = (volatile int *) ( esp->slot + DEC_SCSI_DMAREG ); + + memcpy((void *) (esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE), + KSEG0ADDR((void *) vaddress), length); - *scsi_pmaz_dma_ptr_tc = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]); + *dmareg = TC_ESP_DMAR_WRITE | + TC_ESP_DMA_ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE); } @@ -524,18 +520,9 @@ } } -static void pmaz_dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) -{ - int x; - for (x = 1; x < 6; x++) - if (sp->SCp.have_data_in == PHYSADDR(scsi_pmaz_dma_ptrs_tc[x])) - scsi_pmaz_dma_buff_used[x] = 0; -} - static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) { sp->SCp.have_data_in = (int) sp->SCp.ptr = (char *) KSEG0ADDR((sp->request_buffer)); } -#endif 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 Sun Sep 9 10:52:35 2001 @@ -0,0 +1,3326 @@ +/*************************************************************************** + 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(chan < 0 || chan >= MAX_CHANNEL) + return NULL; + + 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/eata_pio.c linux/drivers/scsi/eata_pio.c --- v2.4.9/linux/drivers/scsi/eata_pio.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/scsi/eata_pio.c Mon Sep 10 08:06:32 2001 @@ -161,7 +161,7 @@ IncStat(&cmd->SCp,1); odd=FALSE; } - x=min(unsigned int,z,cmd->SCp.this_residual/2); + x=min_t(unsigned int,z,cmd->SCp.this_residual/2); insw(base+HA_RDATA,cmd->SCp.ptr,x); z-=x; IncStat(&cmd->SCp,2*x); @@ -191,7 +191,7 @@ z--; odd=FALSE; } - x=min(unsigned int,z,cmd->SCp.this_residual/2); + x=min_t(unsigned int,z,cmd->SCp.this_residual/2); outsw(base+HA_RDATA,cmd->SCp.ptr,x); z-=x; IncStat(&cmd->SCp,2*x); 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/lasi700.c linux/drivers/scsi/lasi700.c --- v2.4.9/linux/drivers/scsi/lasi700.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/lasi700.c Sun Sep 9 11:58:36 2001 @@ -0,0 +1,188 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* PARISC LASI driver for the 53c700 chip + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.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. +** +**----------------------------------------------------------------------------- + */ + +/* + * Many thanks to Richard Hirst for patiently + * debugging this driver on the parisc architecture and suggesting + * many improvements and bug fixes. + * + * Thanks also go to Linuxcare Inc. for providing several PARISC + * machines for me to debug the driver on. + */ + +#ifndef __hppa__ +#error "lasi700 only compiles on hppa architecture" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "scsi.h" +#include "hosts.h" +#include "constants.h" + +#include "lasi700.h" +#include "53c700.h" + +#ifdef MODULE + +char *lasi700; /* command line from insmod */ + +MODULE_AUTHOR("James Bottomley"); +MODULE_DESCRIPTION("lasi700 SCSI Driver"); +MODULE_LICENSE("GPL"); +MODULE_PARM(lasi700, "s"); + +#endif + +#ifdef MODULE +#define ARG_SEP ' ' +#else +#define ARG_SEP ',' +#endif + +static unsigned long __initdata opt_base; +static int __initdata opt_irq; + +static int __init +param_setup(char *string) +{ + char *pos = string, *next; + + while(pos != NULL && (next = strchr(pos, ':')) != NULL) { + int val = (int)simple_strtoul(++next, NULL, 0); + + if(!strncmp(pos, "addr:", 5)) + opt_base = val; + else if(!strncmp(pos, "irq:", 4)) + opt_irq = val; + + if((pos = strchr(pos, ARG_SEP)) != NULL) + pos++; + } + return 1; +} + +#ifndef MODULE +__setup("lasi700=", param_setup); +#endif + +static Scsi_Host_Template __initdata *host_tpnt = NULL; +static int __initdata host_count = 0; +static struct parisc_device_id lasi700_scsi_tbl[] = { + LASI700_ID_TABLE, + { 0 } +}; + +MODULE_DEVICE_TABLE(parisc, lasi700_scsi_tbl); + +static struct parisc_driver lasi700_driver = LASI700_DRIVER; + +static int __init +lasi700_detect(Scsi_Host_Template *tpnt) +{ + host_tpnt = tpnt; + +#ifdef MODULE + if(lasi700) + param_setup(lasi700); +#endif + + register_parisc_driver(&lasi700_driver); + + return (host_count != 0); +} + +static int __init +lasi700_driver_callback(struct parisc_device *dev) +{ + unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET; + int irq = busdevice_alloc_irq(dev); + struct Scsi_Host *host; + struct NCR_700_Host_Parameters *hostdata = + kmalloc(sizeof(struct NCR_700_Host_Parameters), + GFP_KERNEL); + if(hostdata == NULL) { + printk(KERN_ERR "lasi700: Failed to allocate host data\n"); + return 1; + } + memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); + if(request_mem_region(base, 64, "lasi700") == NULL) { + printk(KERN_ERR "lasi700: Failed to claim memory region\n"); + kfree(hostdata); + return 1; + } + hostdata->base = base; + hostdata->differential = 0; + hostdata->clock = LASI700_CLOCK; + hostdata->force_le_on_be = 1; + if((host = NCR_700_detect(host_tpnt, hostdata)) == NULL) { + kfree(hostdata); + release_mem_region(host->base, 64); + return 1; + } + host->irq = irq; + if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "lasi700", host)) { + printk(KERN_ERR "lasi700: irq problem, detatching\n"); + scsi_unregister(host); + NCR_700_release(host); + return 1; + } + host_count++; + return 0; +} + +static int +lasi700_release(struct Scsi_Host *host) +{ + struct D700_Host_Parameters *hostdata = + (struct D700_Host_Parameters *)host->hostdata[0]; + + NCR_700_release(host); + kfree(hostdata); + free_irq(host->irq, host); + release_mem_region(host->base, 64); + return 1; +} + +static Scsi_Host_Template driver_template = LASI700_SCSI; + +#include "scsi_module.c" diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/lasi700.h linux/drivers/scsi/lasi700.h --- v2.4.9/linux/drivers/scsi/lasi700.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/lasi700.h Sun Sep 9 11:58:36 2001 @@ -0,0 +1,57 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* PARISC LASI driver for the 53c700 chip + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.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. +** +**----------------------------------------------------------------------------- + */ + +#ifndef _LASI700_H +#define _LASI700_H + +static int lasi700_detect(Scsi_Host_Template *); +static int lasi700_driver_callback(struct parisc_device *dev); +static int lasi700_release(struct Scsi_Host *host); + + +#define LASI700_SCSI { \ + name: "LASI SCSI 53c700", \ + proc_name: "lasi700", \ + detect: lasi700_detect, \ + release: lasi700_release, \ + this_id: 7, \ +} + +#define LASI700_ID_TABLE { \ + hw_type: HPHW_FIO, \ + sversion: 0x071, \ + hversion: HVERSION_ANY_ID, \ + hversion_rev: HVERSION_REV_ANY_ID, \ +} + +#define LASI700_DRIVER { \ + name: "Lasi SCSI", \ + id_table: lasi700_scsi_tbl, \ + probe: lasi700_driver_callback,\ +} + +#define LASI700_CLOCK 25 +#define LASI_SCSI_CORE_OFFSET 0x100 + +#endif diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c --- v2.4.9/linux/drivers/scsi/megaraid.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/scsi/megaraid.c Mon Sep 17 13:16:30 2001 @@ -2857,6 +2857,7 @@ if (!host) goto err_unmap; +#if 0 /* * Comment the following initialization if you know 'max_sectors' is * not defined for this kernel. @@ -2864,6 +2865,7 @@ * greatly increases the IO performance - AM */ host->max_sectors = 1024; +#endif scsi_set_pci_device(host, pdev); megaCfg = (mega_host_config *) host->hostdata; @@ -3138,16 +3140,18 @@ * First argument (major) to register_chrdev implies a dynamic major * number allocation. */ - major = register_chrdev (0, "megadev", &megadev_fops); + if (count) { + major = register_chrdev (0, "megadev", &megadev_fops); - /* - * Register the Shutdown Notification hook in kernel - */ - if (register_reboot_notifier (&mega_notifier)) { - printk ("MegaRAID Shutdown routine not registered!!\n"); - } + /* + * Register the Shutdown Notification hook in kernel + */ + if (register_reboot_notifier (&mega_notifier)) { + printk ("MegaRAID Shutdown routine not registered!!\n"); + } - init_MUTEX (&mimd_entry_mtx); + init_MUTEX (&mimd_entry_mtx); + } return count; } diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c --- v2.4.9/linux/drivers/scsi/mesh.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/scsi/mesh.c Tue Sep 18 14:23:14 2001 @@ -29,6 +29,10 @@ #include #include #include +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#endif #include "scsi.h" #include "hosts.h" @@ -151,6 +155,7 @@ struct mesh_target tgts[8]; void *dma_cmd_space; struct device_node *ofnode; + u8* mio_base; #ifndef MESH_NEW_STYLE_EH Scsi_Cmnd *completed_q; Scsi_Cmnd *completed_qtail; @@ -210,6 +215,15 @@ static void halt_dma(struct mesh_state *); static int data_goes_out(Scsi_Cmnd *); static void do_abort(struct mesh_state *ms); +static void set_mesh_power(struct mesh_state *ms, int state); + +#ifdef CONFIG_PMAC_PBOOK +static int mesh_notify_sleep(struct pmu_sleep_notifier *self, int when); +static struct pmu_sleep_notifier mesh_sleep_notifier = { + mesh_notify_sleep, + SLEEP_LEVEL_BLOCK, +}; +#endif static struct notifier_block mesh_notifier = { mesh_notify_reboot, @@ -244,6 +258,8 @@ if (mesh == 0) mesh = find_compatible_devices("scsi", "chrp,mesh0"); for (; mesh != 0; mesh = mesh->next) { + struct device_node *mio; + if (mesh->n_addrs != 2 || mesh->n_intrs != 2) { printk(KERN_ERR "mesh: expected 2 addrs and 2 intrs" " (got %d,%d)", mesh->n_addrs, mesh->n_intrs); @@ -309,8 +325,13 @@ if (mesh_sync_period < minper) mesh_sync_period = minper; - feature_set(mesh, FEATURE_MESH_enable); - mdelay(200); + ms->mio_base = 0; + for (mio = ms->ofnode->parent; mio; mio = mio->parent) + if (strcmp(mio->name, "mac-io") == 0 && mio->n_addrs > 0) + break; + if (mio) + ms->mio_base = (u8 *) ioremap(mio->addrs[0].address, 0x40); + set_mesh_power(ms, 1); mesh_init(ms); @@ -321,8 +342,12 @@ ++nmeshes; } - if ((_machine == _MACH_Pmac) && (nmeshes > 0)) + if ((_machine == _MACH_Pmac) && (nmeshes > 0)) { +#ifdef CONFIG_PMAC_PBOOK + pmu_register_sleep_notifier(&mesh_sleep_notifier); +#endif /* CONFIG_PMAC_PBOOK */ register_reboot_notifier(&mesh_notifier); + } return nmeshes; } @@ -338,11 +363,69 @@ iounmap((void *) ms->mesh); if (ms->dma) iounmap((void *) ms->dma); + if (ms->mio_base) + iounmap((void *) ms->mio_base); kfree(ms->dma_cmd_space); free_irq(ms->meshintr, ms); feature_clear(ms->ofnode, FEATURE_MESH_enable); return 0; } + +static void +set_mesh_power(struct mesh_state *ms, int state) +{ + if (_machine != _MACH_Pmac) + return; + if (state) { + feature_set(ms->ofnode, FEATURE_MESH_enable); + /* This seems to enable the termination power. strangely + this doesn't fully agree with OF, but with MacOS */ + if (ms->mio_base) + out_8(ms->mio_base + 0x36, 0x70); + mdelay(200); + } else { + feature_clear(ms->ofnode, FEATURE_MESH_enable); + if (ms->mio_base) + out_8(ms->mio_base + 0x36, 0x34); + mdelay(10); + } +} + +#ifdef CONFIG_PMAC_PBOOK +/* + * notify clients before sleep and reset bus afterwards + */ +int +mesh_notify_sleep(struct pmu_sleep_notifier *self, int when) +{ + struct mesh_state *ms; + + switch (when) { + case PBOOK_SLEEP_REQUEST: + /* XXX We should wait for current transactions and queue + * new ones that would be posted beyond this point + */ + break; + case PBOOK_SLEEP_REJECT: + break; + + case PBOOK_SLEEP_NOW: + for (ms = all_meshes; ms != 0; ms = ms->next) { + disable_irq(ms->meshintr); + set_mesh_power(ms, 0); + } + break; + case PBOOK_WAKE: + for (ms = all_meshes; ms != 0; ms = ms->next) { + set_mesh_power(ms, 1); + mesh_init(ms); + enable_irq(ms->meshintr); + } + break; + } + return PBOOK_SLEEP_OK; +} +#endif /* CONFIG_PMAC_PBOOK */ int mesh_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) 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/qla1280.h linux/drivers/scsi/qla1280.h --- v2.4.9/linux/drivers/scsi/qla1280.h Mon Dec 11 13:19:24 2000 +++ linux/drivers/scsi/qla1280.h Mon Sep 17 13:16:31 2001 @@ -371,8 +371,6 @@ #define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ -typedef struct timer_list timer_t; /* timer */ - /* * SCSI Request Block structure */ 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/scsi_error.c linux/drivers/scsi/scsi_error.c --- v2.4.9/linux/drivers/scsi/scsi_error.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/scsi/scsi_error.c Sun Sep 9 10:52:35 2001 @@ -421,6 +421,7 @@ static unsigned char generic_sense[6] = {REQUEST_SENSE, 0, 0, 0, 255, 0}; unsigned char scsi_result0[256], *scsi_result = NULL; + int saved_result; ASSERT_LOCK(&io_request_lock, 0); @@ -446,6 +447,7 @@ memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); memset((void *) scsi_result, 0, 256); + saved_result = SCpnt->result; SCpnt->request_buffer = scsi_result; SCpnt->request_bufflen = 256; SCpnt->use_sg = 0; @@ -470,6 +472,7 @@ */ memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd, sizeof(SCpnt->data_cmnd)); + SCpnt->result = saved_result; SCpnt->request_buffer = SCpnt->buffer; SCpnt->request_bufflen = SCpnt->bufflen; SCpnt->use_sg = SCpnt->old_use_sg; 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 Mon Sep 10 12:42:32 2001 @@ -90,6 +90,7 @@ static int *sd_sizes; static int *sd_blocksizes; static int *sd_hardsizes; /* Hardware sector size */ +static int *sd_max_sectors; static int check_scsidisk_media_change(kdev_t); static int fop_revalidate_scsidisk(kdev_t); @@ -227,9 +228,9 @@ return 0; } case BLKGETSIZE: /* Return device size */ - if (!arg) - return -EINVAL; return put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects, (long *) arg); + case BLKGETSIZE64: + return put_user((u64)sd[SD_PARTITION(inode->i_rdev)].nr_sects << 9, (u64 *)arg); case BLKROSET: case BLKROGET: @@ -238,8 +239,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 */ @@ -561,22 +564,16 @@ static struct gendisk sd_gendisk = { - SCSI_DISK0_MAJOR, /* Major number */ - "sd", /* Major name */ - 4, /* Bits to shift to get real from partition */ - 1 << 4, /* Number of partitions per real */ - NULL, /* hd struct */ - NULL, /* block sizes */ - 0, /* number */ - NULL, /* internal */ - NULL, /* next */ - &sd_fops, /* file operations */ + major: SCSI_DISK0_MAJOR, + major_name: "sd", + minor_shift: 4, + max_p: 1 << 4, + fops: &sd_fops, }; 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 +1017,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; /* Ask for 255 bytes, even tho we want just the first 8 */ SRpnt->sr_cmd_len = 0; SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[2] = 0; @@ -1104,15 +1101,30 @@ if (!sd_hardsizes) goto cleanup_blocksizes; + sd_max_sectors = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); + if (!sd_max_sectors) + goto cleanup_max_sectors; + for (i = 0; i < sd_template.dev_max << 4; i++) { sd_blocksizes[i] = 1024; sd_hardsizes[i] = 512; + /* + * Allow lowlevel device drivers to generate 512k large scsi + * commands if they know what they're doing and they ask for it + * explicitly via the SHpnt->max_sectors API. + */ + sd_max_sectors[i] = MAX_SEGMENTS*8; } for (i = 0; i < N_USED_SD_MAJORS; i++) { blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4); hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4); + max_sectors[SD_MAJOR(i)] = sd_max_sectors + i * (SCSI_DISKS_PER_MAJOR << 4); } + /* + * FIXME: should unregister blksize_size, hardsect_size and max_sectors when + * the module is unloaded. + */ sd = kmalloc((sd_template.dev_max << 4) * sizeof(struct hd_struct), GFP_ATOMIC); @@ -1145,12 +1157,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: @@ -1164,6 +1174,8 @@ cleanup_sd_gendisks: kfree(sd); cleanup_sd: + kfree(sd_max_sectors); +cleanup_max_sectors: kfree(sd_hardsizes); cleanup_blocksizes: kfree(sd_blocksizes); @@ -1182,19 +1194,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 +1381,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 +1395,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 14 14:40:00 2001 @@ -123,12 +123,16 @@ #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 #endif +#ifndef __i386__ +#undef SEAGATE_USE_ASM +#endif + /* Thanks to Brian Antoine for the example code in his Messy-Loss ST-01 driver, and Mitsugu Suzuki for information on the ST-01 @@ -152,11 +156,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 +185,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 +197,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 +220,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 +264,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 +304,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 +383,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 +425,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 +461,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 +626,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 +687,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 +905,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 +923,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 +952,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 +990,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 +1099,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 +1121,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 +1268,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 +1277,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 +1451,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 +1652,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 +1665,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 +1685,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 +1723,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 +1777,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 Sun Sep 16 11:09:45 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); } @@ -640,6 +645,7 @@ Scsi_Request * SRpnt; Sg_device * sdp = sfp->parentdp; sg_io_hdr_t * hp = &srp->header; + request_queue_t * q; srp->data.cmd_opcode = cmnd[0]; /* hold opcode of command */ hp->status = 0; @@ -675,6 +681,7 @@ } srp->my_cmdp = SRpnt; + q = &SRpnt->sr_device->request_queue; SRpnt->sr_request.rq_dev = sdp->i_rdev; SRpnt->sr_request.rq_status = RQ_ACTIVE; SRpnt->sr_sense_buffer[0] = 0; @@ -710,7 +717,7 @@ (void *)SRpnt->sr_buffer, hp->dxfer_len, sg_cmd_done_bh, timeout, SG_DEFAULT_RETRIES); /* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */ - generic_unplug_device(&SRpnt->sr_device->request_queue); + generic_unplug_device(q); return 0; } @@ -874,6 +881,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 +1126,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 +1252,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 +1284,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 +1334,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 +2231,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 +2775,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/sgiwd93.c linux/drivers/scsi/sgiwd93.c --- v2.4.9/linux/drivers/scsi/sgiwd93.c Sat Nov 11 19:01:11 2000 +++ linux/drivers/scsi/sgiwd93.c Sun Sep 9 10:52:35 2001 @@ -281,18 +281,30 @@ sgiwd93_host->irq = SGI_WD93_0_IRQ; buf = (uchar *) get_free_page(GFP_KERNEL); + if (!buf) { + printk(KERN_WARNING "sgiwd93: Could not allocate memory for host0 buffer.\n"); + scsi_unregister(sgiwd93_host); + return 0; + } init_hpc_chain(buf); dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); /* HPC_SCSI_REG0 | 0x03 | KSEG1 */ - wd33c93_init(sgiwd93_host, (wd33c93_regs *) 0xbfbc0003, + wd33c93_init(sgiwd93_host, (wd33c93_regs *) KSEG1ADDR (0x1fbc0003), dma_setup, dma_stop, WD33C93_FS_16_20); hdata = (struct WD33C93_hostdata *)sgiwd93_host->hostdata; hdata->no_sync = 0; hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); - dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); - request_irq(SGI_WD93_0_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host); + if (request_irq(SGI_WD93_0_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host)) { + printk(KERN_WARNING "sgiwd93: Could not register IRQ %d (for host 0).\n", SGI_WD93_0_IRQ); +#ifdef MODULE + wd33c93_release(); +#endif + free_page((unsigned long)buf); + scsi_unregister(sgiwd93_host); + return 0; + } /* set up second controller on the Indigo2 */ if(!sgi_guiness) { sgiwd93_host1 = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata)); @@ -302,10 +314,16 @@ sgiwd93_host1->irq = SGI_WD93_1_IRQ; buf = (uchar *) get_free_page(GFP_KERNEL); + if (!buf) { + printk(KERN_WARNING "sgiwd93: Could not allocate memory for host1 buffer.\n"); + scsi_unregister(sgiwd93_host1); + called = 1; + return 1; /* We registered host0 so return success*/ + } init_hpc_chain(buf); dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); /* HPC_SCSI_REG1 | 0x03 | KSEG1 */ - wd33c93_init(sgiwd93_host1, (wd33c93_regs *) 0xbfbc8003, + wd33c93_init(sgiwd93_host1, (wd33c93_regs *) KSEG1ADDR (0x1fbc8003), dma_setup, dma_stop, WD33C93_FS_16_20); hdata1 = (struct WD33C93_hostdata *)sgiwd93_host1->hostdata; @@ -313,7 +331,15 @@ hdata1->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); - request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1); + if (request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1)) { + printk(KERN_WARNING "sgiwd93: Could not allocate irq %d (for host1).\n", SGI_WD93_1_IRQ); +#ifdef MODULE + wd33c93_release(); +#endif + free_page((unsigned long)buf); + scsi_unregister(sgiwd93_host1); + /* Fall through since host0 registered OK */ + } } } 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/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- v2.4.9/linux/drivers/scsi/sr_ioctl.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/scsi/sr_ioctl.c Mon Sep 10 12:42:32 2001 @@ -546,6 +546,8 @@ switch (cmd) { case BLKGETSIZE: return put_user(scsi_CDs[target].capacity, (long *) arg); + case BLKGETSIZE64: + return put_user((u64)scsi_CDs[target].capacity << 9, (u64 *)arg); case BLKROSET: case BLKROGET: case BLKRASET: diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/sym53c8xx.h linux/drivers/scsi/sym53c8xx.h --- v2.4.9/linux/drivers/scsi/sym53c8xx.h Tue Aug 7 12:52:12 2001 +++ linux/drivers/scsi/sym53c8xx.h Tue Sep 18 17:10:10 2001 @@ -96,6 +96,7 @@ this_id: 7, \ sg_tablesize: SCSI_NCR_SG_TABLESIZE, \ cmd_per_lun: SCSI_NCR_CMD_PER_LUN, \ + max_sectors: MAX_SEGMENTS*8, \ use_clustering: DISABLE_CLUSTERING} #else diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/sym53c8xx_defs.h linux/drivers/scsi/sym53c8xx_defs.h --- v2.4.9/linux/drivers/scsi/sym53c8xx_defs.h Tue Aug 7 12:51:53 2001 +++ linux/drivers/scsi/sym53c8xx_defs.h Tue Sep 18 17:09:57 2001 @@ -455,7 +455,7 @@ * We want to be paranoid for ppc and ia64. :) */ -#if defined __i386__ +#if defined(__i386__) || defined(__x86_64__) #define MEMORY_BARRIER() do { ; } while(0) #elif defined __powerpc__ #define MEMORY_BARRIER() __asm__ volatile("eieio; sync" : : : "memory") 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 14 14:04:07 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 @@ -198,3 +201,13 @@ fi dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C + +# A cross directory dependence. The sound modules will need gameport.o compiled in, +# but it resides in the drivers/char/joystick directory. This define_tristate takes +# care of that. --Vojtech + +if [ "$CONFIG_INPUT_GAMEPORT" != "n" ]; then + if [ "$CONFIG_SOUND_ESSSOLO1" = "y" -o "$CONFIG_SOUND_ES1370" = "y" -o "$CONFIG_SOUND_ES1371" = "y" -o "$CONFIG_SOUND_SONICVIBES" = "y" ]; then + define_tristate CONFIG_INPUT_GAMEPORT y + fi +fi diff -u --recursive --new-file v2.4.9/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v2.4.9/linux/drivers/sound/Makefile Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/Makefile Fri Sep 14 14:04:07 2001 @@ -63,15 +63,17 @@ obj-$(CONFIG_SOUND_CMPCI) += cmpci.o obj-$(CONFIG_SOUND_ES1370) += es1370.o obj-$(CONFIG_SOUND_ES1371) += es1371.o ac97_codec.o +obj-$(CONFIG_SOUND_VRC5477) += nec_vrc5477.o ac97_codec.o obj-$(CONFIG_SOUND_ESSSOLO1) += esssolo1.o obj-$(CONFIG_SOUND_FUSION) += cs46xx.o ac97_codec.o obj-$(CONFIG_SOUND_MAESTRO) += maestro.o obj-$(CONFIG_SOUND_MAESTRO3) += maestro3.o ac97_codec.o obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o -obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o +obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o +obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o obj-$(CONFIG_SOUND_BT878) += btaudio.o - obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o + ifeq ($(CONFIG_MIDI_EMU10K1),y) obj-$(CONFIG_SOUND_EMU10K1) += sound.o endif 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/btaudio.c linux/drivers/sound/btaudio.c --- v2.4.9/linux/drivers/sound/btaudio.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/btaudio.c Tue Sep 18 14:28:47 2001 @@ -1,7 +1,7 @@ /* btaudio - bt878 audio dma driver for linux 2.4.x - (c) 2000 Gerd Knorr + (c) 2000 Gerd Knorr 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 @@ -32,9 +32,7 @@ #include #include #include -#include #include -#include /* mmio access */ @@ -91,7 +89,6 @@ #define RISC_SYNC_VRO 0x0c #define HWBASE_AD (448000) -#define HWBASE_DA 31928 /* 48000 */ /* -------------------------------------------------------------- */ @@ -100,7 +97,8 @@ struct btaudio *next; /* device info */ - int dsp_dev; + int dsp_digital; + int dsp_analog; int mixer_dev; struct pci_dev *pci; unsigned int irq; @@ -142,14 +140,18 @@ int mixcount; int sampleshift; int channels; + int analog; }; static struct btaudio *btaudios = NULL; -static unsigned int dsp = -1; +static unsigned int dsp1 = -1; +static unsigned int dsp2 = -1; static unsigned int mixer = -1; static unsigned int debug = 0; static unsigned int irq_debug = 0; -static int analog = 0; +static int digital = 1; +static int analog = 1; +static int rate = 32000; /* -------------------------------------------------------------- */ @@ -210,7 +212,8 @@ if (bta->line_count > 255) return -EINVAL; if (debug) - printk("btaudio: bufsize=%d - bs=%d bc=%d - ls=%d, lc=%d\n", + printk(KERN_DEBUG + "btaudio: bufsize=%d - bs=%d bc=%d - ls=%d, lc=%d\n", bta->buf_size,bta->block_bytes,bta->block_count, bta->line_bytes,bta->line_count); rp = 0; bp = 0; @@ -250,7 +253,7 @@ btwrite((bta->line_count << 16) | bta->line_bytes, REG_PACKET_LEN); btwrite(IRQ_BTAUDIO, REG_INT_MASK); - if (analog) { + if (bta->analog) { btwrite(DMA_CTL_ACAP_EN | DMA_CTL_RISC_EN | DMA_CTL_FIFO_EN | @@ -278,7 +281,7 @@ bta->read_count = 0; bta->recording = 1; if (debug) - printk("btaudio: recording started\n"); + printk(KERN_DEBUG "btaudio: recording started\n"); return 0; } @@ -287,15 +290,9 @@ btand(~15, REG_GPIO_DMA_CTL); bta->recording = 0; if (debug) - printk("btaudio: recording stopped\n"); + printk(KERN_DEBUG "btaudio: recording stopped\n"); } -/* -------------------------------------------------------------- */ - -static loff_t btaudio_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} /* -------------------------------------------------------------- */ @@ -310,6 +307,8 @@ if (NULL == bta) return -ENODEV; + if (debug) + printk("btaudio: open mixer [%d]\n",minor); file->private_data = bta; return 0; } @@ -327,8 +326,9 @@ if (cmd == SOUND_MIXER_INFO) { mixer_info info; - strncpy(info.id, "bt878", sizeof(info.id)); - strncpy(info.name, "Brooktree Bt878 audio", sizeof(info.name)); + memset(&info,0,sizeof(info)); + strncpy(info.id,"bt878",sizeof(info.id)-1); + strncpy(info.name,"Brooktree Bt878 audio",sizeof(info.name)-1); info.modify_counter = bta->mixcount; if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; @@ -336,8 +336,9 @@ } if (cmd == SOUND_OLD_MIXER_INFO) { _old_mixer_info info; - strncpy(info.id, "bt878", sizeof(info.id)); - strncpy(info.name, "Brooktree Bt878 audio", sizeof(info.name)); + memset(&info,0,sizeof(info)); + strncpy(info.id,"bt878",sizeof(info.id)-1); + strncpy(info.name,"Brooktree Bt878 audio",sizeof(info.name)-1); if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; return 0; @@ -423,7 +424,7 @@ static struct file_operations btaudio_mixer_fops = { owner: THIS_MODULE, - llseek: btaudio_llseek, + llseek: no_llseek, open: btaudio_mixer_open, release: btaudio_mixer_release, ioctl: btaudio_mixer_ioctl, @@ -431,23 +432,16 @@ /* -------------------------------------------------------------- */ -static int btaudio_dsp_open(struct inode *inode, struct file *file) +static int btaudio_dsp_open(struct inode *inode, struct file *file, + struct btaudio *bta, int analog) { - int minor = MINOR(inode->i_rdev); - struct btaudio *bta; - - for (bta = btaudios; bta != NULL; bta = bta->next) - if (bta->dsp_dev == minor) - break; - if (NULL == bta) - return -ENODEV; - down(&bta->lock); if (bta->users) goto busy; bta->users++; file->private_data = bta; + bta->analog = analog; bta->dma_block = 0; bta->read_offset = 0; bta->read_count = 0; @@ -461,6 +455,38 @@ return -EBUSY; } +static int btaudio_dsp_open_digital(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct btaudio *bta; + + for (bta = btaudios; bta != NULL; bta = bta->next) + if (bta->dsp_digital == minor) + break; + if (NULL == bta) + return -ENODEV; + + if (debug) + printk("btaudio: open digital dsp [%d]\n",minor); + return btaudio_dsp_open(inode,file,bta,0); +} + +static int btaudio_dsp_open_analog(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct btaudio *bta; + + for (bta = btaudios; bta != NULL; bta = bta->next) + if (bta->dsp_analog == minor) + break; + if (NULL == bta) + return -ENODEV; + + if (debug) + printk("btaudio: open analog dsp [%d]\n",minor); + return btaudio_dsp_open(inode,file,bta,1); +} + static int btaudio_dsp_release(struct inode *inode, struct file *file) { struct btaudio *bta = file->private_data; @@ -511,9 +537,9 @@ if (nsrc > bta->buf_size - bta->read_offset) nsrc = bta->buf_size - bta->read_offset; ndst = nsrc >> bta->sampleshift; - - if ((analog && 0 == bta->sampleshift) || - (!analog && 2 == bta->channels)) { + + if ((bta->analog && 0 == bta->sampleshift) || + (!bta->analog && 2 == bta->channels)) { /* just copy */ if (copy_to_user(buffer + ret, bta->buf_cpu + bta->read_offset, nsrc)) { if (0 == ret) @@ -521,11 +547,11 @@ break; } - } else if (!analog) { + } else if (!bta->analog) { /* stereo => mono (digital audio) */ - __u16 *src = (__u16*)(bta->buf_cpu + bta->read_offset); - __u16 *dst = (__u16*)(buffer + ret); - __u16 avg; + __s16 *src = (__s16*)(bta->buf_cpu + bta->read_offset); + __s16 *dst = (__s16*)(buffer + ret); + __s16 avg; int n = ndst>>1; if (0 != verify_area(VERIFY_WRITE,dst,ndst)) { if (0 == ret) @@ -533,9 +559,9 @@ break; } for (; n; n--, dst++) { - avg = *(src++) >> 1; - avg += *(src++) >> 1; - __put_user(avg,(__u16*)(dst)); + avg = (__s16)le16_to_cpu(*src) / 2; src++; + avg += (__s16)le16_to_cpu(*src) / 2; src++; + __put_user(cpu_to_le16(avg),(__u16*)(dst)); } } else if (8 == bta->bits) { @@ -600,7 +626,7 @@ case SNDCTL_DSP_SPEED: if (get_user(val, (int*)arg)) return -EFAULT; - if (analog) { + if (bta->analog) { for (s = 0; s < 16; s++) if (val << s >= HWBASE_AD*4/15) break; @@ -610,7 +636,8 @@ bta->sampleshift = s; bta->decimation = i; if (debug) - printk("btaudio: rate: req=%d dec=%d shift=%d hwrate=%d swrate=%d\n", + printk(KERN_DEBUG "btaudio: rate: req=%d " + "dec=%d shift=%d hwrate=%d swrate=%d\n", val,i,s,(HWBASE_AD*4/i),(HWBASE_AD*4/i)>>s); } else { bta->sampleshift = (bta->channels == 2) ? 0 : 1; @@ -624,26 +651,30 @@ } /* fall through */ case SOUND_PCM_READ_RATE: - if (analog) { + if (bta->analog) { return put_user(HWBASE_AD*4/bta->decimation>>bta->sampleshift, (int*)arg); } else { - return put_user(HWBASE_DA, (int*)arg); + return put_user(rate, (int*)arg); } case SNDCTL_DSP_STEREO: - if (!analog) { + if (!bta->analog) { if (get_user(val, (int*)arg)) return -EFAULT; bta->channels = (val > 0) ? 2 : 1; bta->sampleshift = (bta->channels == 2) ? 0 : 1; - printk("btaudio: stereo=%d channels=%d\n", - val,bta->channels); + if (debug) + printk(KERN_INFO + "btaudio: stereo=%d channels=%d\n", + val,bta->channels); } else { if (val == 1) return -EFAULT; else { bta->channels = 1; - printk("btaudio: stereo=0 channels=1\n"); + if (debug) + printk(KERN_INFO + "btaudio: stereo=0 channels=1\n"); } } return put_user((bta->channels)-1, (int *)arg); @@ -654,8 +685,10 @@ return -EFAULT; bta->channels = (val > 1) ? 2 : 1; bta->sampleshift = (bta->channels == 2) ? 0 : 1; - printk("btaudio: val=%d channels=%d\n", - val,bta->channels); + if (debug) + printk(KERN_DEBUG + "btaudio: val=%d channels=%d\n", + val,bta->channels); } /* fall through */ case SOUND_PCM_READ_CHANNELS: @@ -683,7 +716,7 @@ } } if (debug) - printk("btaudio: fmt: bits=%d\n",bta->bits); + printk(KERN_DEBUG "btaudio: fmt: bits=%d\n",bta->bits); return put_user((bta->bits==16) ? AFMT_S16_LE : AFMT_S8, (int*)arg); break; @@ -736,10 +769,21 @@ return mask; } -static struct file_operations btaudio_dsp_fops = { +static struct file_operations btaudio_digital_dsp_fops = { owner: THIS_MODULE, - llseek: btaudio_llseek, - open: btaudio_dsp_open, + llseek: no_llseek, + open: btaudio_dsp_open_digital, + release: btaudio_dsp_release, + read: btaudio_dsp_read, + write: btaudio_dsp_write, + ioctl: btaudio_dsp_ioctl, + poll: btaudio_dsp_poll, +}; + +static struct file_operations btaudio_analog_dsp_fops = { + owner: THIS_MODULE, + llseek: no_llseek, + open: btaudio_dsp_open_analog, release: btaudio_dsp_release, read: btaudio_dsp_read, write: btaudio_dsp_write, @@ -769,7 +813,7 @@ if (irq_debug) { int i; - printk("btaudio: irq loop=%d risc=%x, bits:", + printk(KERN_DEBUG "btaudio: irq loop=%d risc=%x, bits:", count, stat>>28); for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) { if (stat & (1 << i)) @@ -787,7 +831,7 @@ bta->dma_block = stat >> 28; if (bta->read_count + 2*bta->block_bytes > bta->buf_size) { stop_recording(bta); - printk("btaudio: buffer overrun\n"); + printk(KERN_INFO "btaudio: buffer overrun\n"); } if (blocks > 0) { bta->read_count += blocks * bta->block_bytes; @@ -795,7 +839,8 @@ } } if (count > 10) { - printk("btaudio: Oops - irq mask cleared\n"); + printk(KERN_WARNING + "btaudio: Oops - irq mask cleared\n"); btwrite(0, REG_INT_MASK); } } @@ -831,7 +876,7 @@ bta->source = 1; bta->bits = 8; bta->channels = 1; - if (analog) { + if (bta->analog) { bta->decimation = 15; } else { bta->decimation = 0; @@ -843,7 +888,7 @@ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &latency); - printk("btaudio: Bt%x (rev %d) at %02x:%02x.%x, ", + printk(KERN_INFO "btaudio: Bt%x (rev %d) at %02x:%02x.%x, ", pci_dev->device,revision,pci_dev->bus->number, PCI_SLOT(pci_dev->devfn),PCI_FUNC(pci_dev->devfn)); printk("irq: %d, latency: %d, memory: 0x%lx\n", @@ -852,31 +897,44 @@ /* init hw */ btwrite(0, REG_GPIO_DMA_CTL); btwrite(0, REG_INT_MASK); - btwrite(~(u32)0x0, REG_INT_STAT); + btwrite(~0x0UL, REG_INT_STAT); pci_set_master(pci_dev); if ((rc = request_irq(bta->irq, btaudio_irq, SA_SHIRQ|SA_INTERRUPT, "btaudio",(void *)bta)) < 0) { - printk("btaudio: can't request irq (rc=%d)\n",rc); + printk(KERN_WARNING + "btaudio: can't request irq (rc=%d)\n",rc); goto fail1; } /* register devices */ - rc = bta->dsp_dev = register_sound_dsp(&btaudio_dsp_fops,dsp); - if (rc < 0) { - printk("btaudio: can't register dsp (rc=%d)\n",rc); - goto fail2; + if (digital) { + rc = bta->dsp_digital = + register_sound_dsp(&btaudio_digital_dsp_fops,dsp1); + if (rc < 0) { + printk(KERN_WARNING + "btaudio: can't register digital dsp (rc=%d)\n",rc); + goto fail2; + } } if (analog) { - rc = bta->mixer_dev = register_sound_mixer(&btaudio_mixer_fops,mixer); + rc = bta->dsp_analog = + register_sound_dsp(&btaudio_analog_dsp_fops,dsp2); if (rc < 0) { - printk("btaudio: can't register mixer (rc=%d)\n",rc); + printk(KERN_WARNING + "btaudio: can't register analog dsp (rc=%d)\n",rc); goto fail3; } + rc = bta->mixer_dev = register_sound_mixer(&btaudio_mixer_fops,mixer); + if (rc < 0) { + printk(KERN_WARNING + "btaudio: can't register mixer (rc=%d)\n",rc); + goto fail4; + } } if (debug) - printk("btaudio: dsp: minor=%d, mixer: minor=%d\n", - bta->dsp_dev,bta->mixer_dev); + printk(KERN_DEBUG "btaudio: minors: digital=%d, analog=%d, mixer=%d\n", + bta->dsp_digital, bta->dsp_analog, bta->mixer_dev); /* hook into linked list */ bta->next = btaudios; @@ -885,8 +943,11 @@ pci_set_drvdata(pci_dev,bta); return 0; + fail4: + unregister_sound_dsp(bta->dsp_analog); fail3: - unregister_sound_dsp(bta->dsp_dev); + if (digital) + unregister_sound_dsp(bta->dsp_digital); fail2: free_irq(bta->irq,bta); fail1: @@ -904,12 +965,16 @@ /* turn off all DMA / IRQs */ btand(~15, REG_GPIO_DMA_CTL); btwrite(0, REG_INT_MASK); - btwrite(~(u32)0x0, REG_INT_STAT); + btwrite(~0x0UL, REG_INT_STAT); /* unregister devices */ - unregister_sound_dsp(bta->dsp_dev); - if (analog) + if (digital) { + unregister_sound_dsp(bta->dsp_digital); + } + if (analog) { + unregister_sound_dsp(bta->dsp_analog); unregister_sound_mixer(bta->mixer_dev); + } /* free resources */ free_buffer(bta); @@ -950,8 +1015,10 @@ int btaudio_init_module(void) { - printk("btaudio: driver version 0.5 loaded [%s mode]\n", - analog ? "audio A/D" : "digital audio"); + printk(KERN_INFO "btaudio: driver version 0.6 loaded [%s%s%s]\n", + analog ? "analog" : "", + analog && digital ? "+" : "", + digital ? "digital" : ""); return pci_module_init(&btaudio_pci_driver); } @@ -964,15 +1031,19 @@ module_init(btaudio_init_module); module_exit(btaudio_cleanup_module); -MODULE_PARM(dsp,"i"); +MODULE_PARM(dsp1,"i"); +MODULE_PARM(dsp2,"i"); MODULE_PARM(mixer,"i"); MODULE_PARM(debug,"i"); MODULE_PARM(irq_debug,"i"); +MODULE_PARM(digital,"i"); MODULE_PARM(analog,"i"); +MODULE_PARM(rate,"i"); MODULE_DEVICE_TABLE(pci, btaudio_pci_tbl); -MODULE_DESCRIPTION("btaudio - bt878 audio dma driver"); +MODULE_DESCRIPTION("bt878 audio dma driver"); MODULE_AUTHOR("Gerd Knorr"); +MODULE_LICENSE("GPL"); /* * Local variables: 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/dmasound/dmasound_atari.c linux/drivers/sound/dmasound/dmasound_atari.c --- v2.4.9/linux/drivers/sound/dmasound/dmasound_atari.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/dmasound/dmasound_atari.c Mon Sep 10 09:09:49 2001 @@ -154,7 +154,7 @@ ssize_t count, used; u_char *p = &frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft); + count = min_t(unsigned long, userCount, frameLeft); if (dmasound.soft.stereo) count &= ~1; used = count; @@ -177,7 +177,7 @@ ssize_t count, used; void *p = &frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft); + count = min_t(unsigned long, userCount, frameLeft); if (dmasound.soft.stereo) count &= ~1; used = count; @@ -196,7 +196,7 @@ if (!dmasound.soft.stereo) { u_char *p = &frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft); + count = min_t(unsigned long, userCount, frameLeft); used = count; while (count > 0) { u_char data; @@ -207,7 +207,7 @@ } } else { u_short *p = (u_short *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft)>>1; + count = min_t(unsigned long, userCount, frameLeft)>>1; used = count*2; while (count > 0) { u_short data; @@ -230,7 +230,7 @@ if (!dmasound.soft.stereo) { u_short *p = (u_short *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft)>>1; + count = min_t(unsigned long, userCount, frameLeft)>>1; used = count*2; while (count > 0) { u_short data; @@ -243,7 +243,7 @@ *frameUsed += used*2; } else { void *p = (u_short *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft) & ~3; + count = min_t(unsigned long, userCount, frameLeft) & ~3; used = count; if (copy_from_user(p, userPtr, count)) return -EFAULT; @@ -261,7 +261,7 @@ if (!dmasound.soft.stereo) { u_short *p = (u_short *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft)>>1; + count = min_t(unsigned long, userCount, frameLeft)>>1; used = count*2; while (count > 0) { u_short data; @@ -275,7 +275,7 @@ *frameUsed += used*2; } else { u_long *p = (u_long *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft)>>2; + count = min_t(unsigned long, userCount, frameLeft)>>2; used = count*4; while (count > 0) { u_long data; @@ -299,7 +299,7 @@ count = frameLeft; if (!dmasound.soft.stereo) { u_short *p = (u_short *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft)>>1; + count = min_t(unsigned long, userCount, frameLeft)>>1; used = count*2; while (count > 0) { u_short data; @@ -313,7 +313,7 @@ *frameUsed += used*2; } else { u_long *p = (u_long *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft)>>2; + count = min_t(unsigned long, userCount, frameLeft)>>2; used = count*4; while (count > 0) { u_long data; @@ -338,7 +338,7 @@ count = frameLeft; if (!dmasound.soft.stereo) { u_short *p = (u_short *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft)>>1; + count = min_t(unsigned long, userCount, frameLeft)>>1; used = count*2; while (count > 0) { u_short data; @@ -351,7 +351,7 @@ *frameUsed += used*2; } else { u_long *p = (u_long *)&frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft)>>2; + count = min_t(unsigned long, userCount, frameLeft)>>2; used = count; while (count > 0) { u_long data; diff -u --recursive --new-file v2.4.9/linux/drivers/sound/dmasound/dmasound_awacs.c linux/drivers/sound/dmasound/dmasound_awacs.c --- v2.4.9/linux/drivers/sound/dmasound/dmasound_awacs.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/dmasound/dmasound_awacs.c Mon Sep 10 09:09:49 2001 @@ -267,7 +267,7 @@ frameLeft >>= 2; if (stereo) userCount >>= 1; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); while (count > 0) { u_char data; if (get_user(data, userPtr++)) @@ -298,7 +298,7 @@ frameLeft >>= 2; if (stereo) userCount >>= 1; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); while (count > 0) { u_char data; if (get_user(data, userPtr++)) @@ -329,7 +329,7 @@ frameLeft >>= 2; if (stereo) userCount >>= 1; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); while (count > 0) { u_char data; if (get_user(data, userPtr++)) @@ -359,7 +359,7 @@ frameLeft >>= 2; userCount >>= (stereo? 2: 1); - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); if (!stereo) { short *up = (short *) userPtr; while (count > 0) { @@ -390,7 +390,7 @@ frameLeft >>= 2; userCount >>= (stereo? 2: 1); - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); while (count > 0) { int data; if (get_user(data, up++)) @@ -648,7 +648,7 @@ frameLeft >>= 2; if (stereo) userCount >>= 1; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); while (count > 0) { u_char data; @@ -681,7 +681,7 @@ frameLeft >>= 2; if (stereo) userCount >>= 1; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); while (count > 0) { u_char data; @@ -713,7 +713,7 @@ frameLeft >>= 2; userCount >>= (stereo? 2: 1); - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); if (!stereo) { short *up = (short *) userPtr; while (count > 0) { @@ -744,7 +744,7 @@ frameLeft >>= 2; userCount >>= (stereo? 2: 1); - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(unsigned long, userCount, frameLeft); while (count > 0) { int data; diff -u --recursive --new-file v2.4.9/linux/drivers/sound/dmasound/dmasound_paula.c linux/drivers/sound/dmasound/dmasound_paula.c --- v2.4.9/linux/drivers/sound/dmasound/dmasound_paula.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/dmasound/dmasound_paula.c Mon Sep 10 09:09:49 2001 @@ -155,14 +155,14 @@ if (!dmasound.soft.stereo) { void *p = &frame[*frameUsed]; - count = min(unsigned long, userCount, frameLeft) & ~1; + count = min_t(unsigned long, userCount, frameLeft) & ~1; used = count; if (copy_from_user(p, userPtr, count)) return -EFAULT; } else { u_char *left = &frame[*frameUsed>>1]; u_char *right = left+write_sq_block_size_half; - count = min(unsigned long, userCount, frameLeft)>>1 & ~1; + count = min_t(unsigned long, userCount, frameLeft)>>1 & ~1; used = count*2; while (count > 0) { if (get_user(*left++, userPtr++) @@ -189,7 +189,7 @@ \ if (!dmasound.soft.stereo) { \ u_char *p = &frame[*frameUsed]; \ - count = min(unsigned long, userCount, frameLeft) & ~1; \ + count = min_t(size_t, userCount, frameLeft) & ~1; \ used = count; \ while (count > 0) { \ u_char data; \ @@ -201,7 +201,7 @@ } else { \ u_char *left = &frame[*frameUsed>>1]; \ u_char *right = left+write_sq_block_size_half; \ - count = min(unsigned long, userCount, frameLeft)>>1 & ~1;\ + count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \ used = count*2; \ while (count > 0) { \ u_char data; \ @@ -242,7 +242,7 @@ if (!dmasound.soft.stereo) { \ u_char *high = &frame[*frameUsed>>1]; \ u_char *low = high+write_sq_block_size_half; \ - count = min(unsigned long, userCount, frameLeft)>>1 & ~1;\ + count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \ used = count*2; \ while (count > 0) { \ if (get_user(data, ((u_short *)userPtr)++)) \ @@ -257,7 +257,7 @@ u_char *leftl = lefth+write_sq_block_size_quarter; \ u_char *righth = lefth+write_sq_block_size_half; \ u_char *rightl = righth+write_sq_block_size_quarter; \ - count = min(unsigned long, userCount, frameLeft)>>2 & ~1;\ + count = min_t(size_t, userCount, frameLeft)>>2 & ~1; \ used = count*4; \ while (count > 0) { \ if (get_user(data, ((u_short *)userPtr)++)) \ diff -u --recursive --new-file v2.4.9/linux/drivers/sound/dmasound/dmasound_q40.c linux/drivers/sound/dmasound/dmasound_q40.c --- v2.4.9/linux/drivers/sound/dmasound/dmasound_q40.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/dmasound/dmasound_q40.c Mon Sep 10 09:09:49 2001 @@ -58,7 +58,7 @@ ssize_t count, used; u_char *p = (u_char *) &frame[*frameUsed]; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(size_t, userCount, frameLeft); if (copy_from_user(p,userPtr,count)) return -EFAULT; while (count > 0) { @@ -84,7 +84,7 @@ frameLeft >>= 1; if (stereo) userCount >>= 1; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(size_t, userCount, frameLeft); while (count > 0) { u_char data; if (get_user(data, userPtr++)) @@ -112,7 +112,7 @@ ssize_t count, used; u_char *p = (u_char *) &frame[*frameUsed]; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(size_t, userCount, frameLeft); if (copy_from_user(p,userPtr,count)) return -EFAULT; while (count > 0) { @@ -136,7 +136,7 @@ frameLeft >>= 1; if (stereo) userCount >>= 1; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(size_t, userCount, frameLeft); while (count > 0) { u_char data; if (get_user(data, userPtr++)) @@ -164,7 +164,7 @@ ssize_t count, used; u_char *p = (u_char *) &frame[*frameUsed]; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(size_t, userCount, frameLeft); if (copy_from_user(p,userPtr,count)) return -EFAULT; *frameUsed += used; @@ -184,7 +184,7 @@ frameLeft >>= 1; if (stereo) userCount >>= 1; - used = count = min(unsigned long, userCount, frameLeft); + used = count = min_t(size_t, userCount, frameLeft); while (count > 0) { u_char data; if (get_user(data, userPtr++)) diff -u --recursive --new-file v2.4.9/linux/drivers/sound/emu10k1/audio.c linux/drivers/sound/emu10k1/audio.c --- v2.4.9/linux/drivers/sound/emu10k1/audio.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/emu10k1/audio.c Mon Sep 10 09:06:10 2001 @@ -115,7 +115,7 @@ if ((bytestocopy >= wiinst->buffer.fragment_size) || (bytestocopy >= count)) { - bytestocopy = min(u32, bytestocopy, count); + bytestocopy = min_t(u32, bytestocopy, count); emu10k1_wavein_xferdata(wiinst, (u8 *) buffer, &bytestocopy); @@ -215,7 +215,7 @@ if ((bytestocopy >= woinst->buffer.fragment_size) || (bytestocopy >= count)) { - bytestocopy = min(u32, bytestocopy, count); + bytestocopy = min_t(u32, bytestocopy, count); emu10k1_waveout_xferdata(woinst, (u8 *) buffer, &bytestocopy); diff -u --recursive --new-file v2.4.9/linux/drivers/sound/emu10k1/cardwi.c linux/drivers/sound/emu10k1/cardwi.c --- v2.4.9/linux/drivers/sound/emu10k1/cardwi.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/emu10k1/cardwi.c Mon Sep 10 09:06:10 2001 @@ -325,7 +325,7 @@ u32 sizetocopy, sizetocopy_now, start; unsigned long flags; - sizetocopy = min(u32, buffer->size, *size); + sizetocopy = min_t(u32, buffer->size, *size); *size = sizetocopy; if (!sizetocopy) diff -u --recursive --new-file v2.4.9/linux/drivers/sound/emu10k1/cardwo.c linux/drivers/sound/emu10k1/cardwo.c --- v2.4.9/linux/drivers/sound/emu10k1/cardwo.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/emu10k1/cardwo.c Mon Sep 10 09:06:10 2001 @@ -581,7 +581,7 @@ u32 sizetocopy, sizetocopy_now, start; unsigned long flags; - sizetocopy = min(u32, buffer->size, *size); + sizetocopy = min_t(u32, buffer->size, *size); *size = sizetocopy; if (!sizetocopy) diff -u --recursive --new-file v2.4.9/linux/drivers/sound/emu10k1/passthrough.c linux/drivers/sound/emu10k1/passthrough.c --- v2.4.9/linux/drivers/sound/emu10k1/passthrough.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/sound/emu10k1/passthrough.c Fri Sep 14 14:04:07 2001 @@ -32,7 +32,7 @@ #define __NO_VERSION__ #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.4.9/linux/drivers/sound/es1370.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/es1370.c Fri Sep 14 14:04:07 2001 @@ -163,23 +163,7 @@ #include #include #include - -#if defined(CONFIG_INPUT_ANALOG) || defined(CONFIG_INPUT_ANALOG_MODULE) #include -#else -struct gameport { - int io; - int size; -}; - -extern inline void gameport_register_port(struct gameport *gameport) -{ -} - -extern inline void gameport_unregister_port(struct gameport *gameport) -{ -} -#endif /* --------------------------------------------------------------------- */ @@ -1240,7 +1224,7 @@ { struct es1370_state *s = (struct es1370_state *)file->private_data; DECLARE_WAITQUEUE(wait, current); - ssize_t ret; + ssize_t ret = 0; unsigned long flags; unsigned swptr; int cnt; diff -u --recursive --new-file v2.4.9/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c --- v2.4.9/linux/drivers/sound/es1371.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/es1371.c Fri Sep 14 14:04:07 2001 @@ -136,23 +136,7 @@ #include #include #include - -#if defined(CONFIG_INPUT_ANALOG) || defined(CONFIG_INPUT_ANALOG_MODULE) #include -#else -struct gameport { - int io; - int size; -}; - -extern inline void gameport_register_port(struct gameport *gameport) -{ -} - -extern inline void gameport_unregister_port(struct gameport *gameport) -{ -} -#endif /* --------------------------------------------------------------------- */ 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/gus_wave.c linux/drivers/sound/gus_wave.c --- v2.4.9/linux/drivers/sound/gus_wave.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/sound/gus_wave.c Fri Sep 14 14:40:00 2001 @@ -1952,7 +1952,7 @@ int voice, cmd; unsigned short p1, p2; unsigned int plong; - unsigned flags; + unsigned long flags; cmd = event_rec[2]; voice = event_rec[3]; 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 Sun Sep 9 10:52:35 2001 @@ -106,6 +106,7 @@ static int ftsodell=0; static int strict_clocking=0; static unsigned int clocking=48000; +static int spdif_locked=0; //#define DEBUG //#define DEBUG2 @@ -118,6 +119,11 @@ #define I810_FMT_STEREO 2 #define I810_FMT_MASK 3 +#define SPDIF_ON 0x0004 +#define SURR_ON 0x0010 +#define CENTER_LFE_ON 0x0020 +#define VOL_MUTED 0x8000 + /* the 810's array of pointers to data buffers */ struct sg_item { @@ -191,7 +197,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" */ @@ -325,6 +331,8 @@ struct i810_state *states[NR_HW_CH]; u16 ac97_features; + u16 ac97_status; + u16 channels; /* hardware resources */ unsigned long iobase; @@ -401,11 +409,164 @@ card->channel[channel].used=0; } +static int i810_valid_spdif_rate ( struct ac97_codec *codec, int rate ) +{ + unsigned long id = 0L; + + id = (i810_ac97_get(codec, AC97_VENDOR_ID1) << 16); + id |= i810_ac97_get(codec, AC97_VENDOR_ID2) & 0xffff; +#ifdef DEBUG + printk ( "i810_audio: codec = %s, codec_id = 0x%08lx\n", codec->name, id); +#endif + switch ( id ) { + case 0x41445361: /* AD1886 */ + if (rate == 48000) { + return 1; + } + break; + default: /* all other codecs, until we know otherwiae */ + if (rate == 48000 || rate == 44100 || rate == 32000) { + return 1; + } + break; + } + return (0); +} + +/* i810_set_spdif_output + * + * Configure the S/PDIF output transmitter. When we turn on + * S/PDIF, we turn off the analog output. This may not be + * the right thing to do. + * + * Assumptions: + * The DSP sample rate must already be set to a supported + * S/PDIF rate (32kHz, 44.1kHz, or 48kHz) or we abort. + */ +static void i810_set_spdif_output(struct i810_state *state, int slots, int rate) +{ + int vol; + int aud_reg; + struct ac97_codec *codec = state->card->ac97_codec[0]; + + if(!(state->card->ac97_features & 4)) { +#ifdef DEBUG + printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n"); +#endif + state->card->ac97_status &= ~SPDIF_ON; + } else { + if ( slots == -1 ) { /* Turn off S/PDIF */ + aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS); + i810_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF)); + + /* If the volume wasn't muted before we turned on S/PDIF, unmute it */ + if ( !(state->card->ac97_status & VOL_MUTED) ) { + aud_reg = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO); + i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (aud_reg & ~VOL_MUTED)); + } + state->card->ac97_status &= ~(VOL_MUTED | SPDIF_ON); + return; + } + + vol = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO); + state->card->ac97_status = vol & VOL_MUTED; + + /* Set S/PDIF transmitter sample rate */ + aud_reg = i810_ac97_get(codec, AC97_SPDIF_CONTROL); + switch ( rate ) { + case 32000: + aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_32K; + break; + case 44100: + aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_44K; + break; + case 48000: + aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_48K; + break; + default: +#ifdef DEBUG + printk(KERN_WARNING "i810_audio: %d sample rate not supported by S/PDIF.\n", rate); +#endif + /* turn off S/PDIF */ + aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS); + i810_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF)); + state->card->ac97_status &= ~SPDIF_ON; + return; + } + + i810_ac97_set(codec, AC97_SPDIF_CONTROL, aud_reg); + + aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS); + aud_reg = (aud_reg & AC97_EA_SLOT_MASK) | slots | AC97_EA_VRA | AC97_EA_SPDIF; + i810_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg); + state->card->ac97_status |= SPDIF_ON; + + /* Check to make sure the configuration is valid */ + aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS); + if ( ! (aud_reg & 0x0400) ) { +#ifdef DEBUG + printk(KERN_WARNING "i810_audio: S/PDIF transmitter configuration not valid (0x%04x).\n", aud_reg); +#endif + + /* turn off S/PDIF */ + i810_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF)); + state->card->ac97_status &= ~SPDIF_ON; + return; + } + /* Mute the analog output */ + /* Should this only mute the PCM volume??? */ + i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (vol | VOL_MUTED)); + } +} + +/* i810_set_dac_channels + * + * Configure the codec's multi-channel DACs + * + * The logic is backwards. Setting the bit to 1 turns off the DAC. + * + * What about the ICH? We currently configure it using the + * SNDCTL_DSP_CHANNELS ioctl. If we're turnning on the DAC, + * does that imply that we want the ICH set to support + * these channels? + * + * TODO: + * vailidate that the codec really supports these DACs + * before turning them on. + */ +static void i810_set_dac_channels(struct i810_state *state, int channel) +{ + int aud_reg; + struct ac97_codec *codec = state->card->ac97_codec[0]; + + aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS); + aud_reg |= AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK; + state->card->ac97_status &= ~(SURR_ON | CENTER_LFE_ON); + + switch ( channel ) { + case 2: /* always enabled */ + break; + case 4: + aud_reg &= ~AC97_EA_PRJ; + state->card->ac97_status |= SURR_ON; + break; + case 6: + aud_reg &= ~(AC97_EA_PRJ | AC97_EA_PRI | AC97_EA_PRK); + state->card->ac97_status |= SURR_ON | CENTER_LFE_ON; + break; + default: + break; + } + i810_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg); + +} + + /* set playback sample rate */ static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int rate) { struct dmabuf *dmabuf = &state->dmabuf; - u32 dacp, new_rate; + u32 new_rate; struct ac97_codec *codec=state->card->ac97_codec[0]; if(!(state->card->ac97_features&0x0001)) @@ -429,20 +590,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); @@ -454,7 +606,7 @@ static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int rate) { struct dmabuf *dmabuf = &state->dmabuf; - u32 dacp, new_rate; + u32 new_rate; struct ac97_codec *codec=state->card->ac97_codec[0]; if(!(state->card->ac97_features&0x0001)) @@ -478,21 +630,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 +1128,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; @@ -1375,7 +1520,9 @@ unsigned long flags; audio_buf_info abinfo; count_info cinfo; - int val, mapped, ret; + unsigned int i_glob_cnt; + int val = 0, mapped, ret; + struct ac97_codec *codec = state->card->ac97_codec[0]; mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) || ((file->f_mode & FMODE_READ) && dmabuf->mapped); @@ -1428,11 +1575,31 @@ return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_WRITE) { - stop_dac(state); - dmabuf->ready = 0; - spin_lock_irqsave(&state->card->lock, flags); - i810_set_dac_rate(state, val); - spin_unlock_irqrestore(&state->card->lock, flags); + if ( (state->card->ac97_status & SPDIF_ON) ) { /* S/PDIF Enabled */ + /* AD1886 only supports 48000, need to check that */ + if ( i810_valid_spdif_rate ( codec, val ) ) { + /* Set DAC rate */ + i810_set_spdif_output ( state, -1, 0 ); + stop_dac(state); + dmabuf->ready = 0; + spin_lock_irqsave(&state->card->lock, flags); + i810_set_dac_rate(state, val); + spin_unlock_irqrestore(&state->card->lock, flags); + /* Set S/PDIF transmitter rate. */ + i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, val ); + if ( ! (state->card->ac97_status & SPDIF_ON) ) { + val = dmabuf->rate; + } + } else { /* Not a valid rate for S/PDIF, ignore it */ + val = dmabuf->rate; + } + } else { + stop_dac(state); + dmabuf->ready = 0; + spin_lock_irqsave(&state->card->lock, flags); + i810_set_dac_rate(state, val); + spin_unlock_irqrestore(&state->card->lock, flags); + } } if (file->f_mode & FMODE_READ) { stop_adc(state); @@ -1450,18 +1617,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) { @@ -1487,13 +1650,82 @@ #ifdef DEBUG printk("SNDCTL_DSP_SETFMT\n"); #endif - return put_user(AFMT_S16_LE, (int *)arg); + if (get_user(val, (int *)arg)) + return -EFAULT; + + switch ( val ) { + case AFMT_S16_LE: + break; + case AFMT_QUERY: + default: + val = AFMT_S16_LE; + break; + } + return put_user(val, (int *)arg); case SNDCTL_DSP_CHANNELS: #ifdef DEBUG printk("SNDCTL_DSP_CHANNELS\n"); #endif - return put_user(2, (int *)arg); + 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); + } + } else { + return put_user(state->card->channels, (int *)arg); + } + + /* ICH and ICH0 only support 2 channels */ + if ( state->card->pci_id == 0x2415 || state->card->pci_id == 0x2425 ) + return put_user(2, (int *)arg); + + /* Multi-channel support was added with ICH2. Bits in */ + /* Global Status and Global Control register are now */ + /* used to indicate this. */ + + i_glob_cnt = inl(state->card->iobase + GLOB_CNT); + + /* Current # of channels enabled */ + if ( i_glob_cnt & 0x0100000 ) + ret = 4; + else if ( i_glob_cnt & 0x0200000 ) + ret = 6; + else + ret = 2; + + switch ( val ) { + case 2: /* 2 channels is always supported */ + outl(state->card->iobase + GLOB_CNT, (i_glob_cnt & 0xcfffff)); + /* Do we need to change mixer settings???? */ + break; + case 4: /* Supported on some chipsets, better check first */ + if ( state->card->channels >= 4 ) { + outl(state->card->iobase + GLOB_CNT, ((i_glob_cnt & 0xcfffff) | 0x0100000)); + /* Do we need to change mixer settings??? */ + } else { + val = ret; + } + break; + case 6: /* Supported on some chipsets, better check first */ + if ( state->card->channels >= 6 ) { + outl(state->card->iobase + GLOB_CNT, ((i_glob_cnt & 0xcfffff) | 0x0200000)); + /* Do we need to change mixer settings??? */ + } else { + val = ret; + } + break; + default: /* nothing else is ever supported by the chipset */ + val = ret; + break; + } + + return put_user(val, (int *)arg); case SNDCTL_DSP_POST: /* the user has sent all data and is notifying us */ /* we update the swptr to the end of the last sg segment then return */ @@ -1740,6 +1972,148 @@ #endif return put_user(AFMT_S16_LE, (int *)arg); + case SNDCTL_DSP_SETSPDIF: /* Set S/PDIF Control register */ +#ifdef DEBUG + printk("SNDCTL_DSP_SETSPDIF\n"); +#endif + if (get_user(val, (int *)arg)) + return -EFAULT; + + /* Check to make sure the codec supports S/PDIF transmitter */ + + if((state->card->ac97_features & 4)) { + /* mask out the transmitter speed bits so the user can't set them */ + val &= ~0x3000; + + /* Add the current transmitter speed bits to the passed value */ + ret = i810_ac97_get(codec, AC97_SPDIF_CONTROL); + val |= (ret & 0x3000); + + i810_ac97_set(codec, AC97_SPDIF_CONTROL, val); + if(i810_ac97_get(codec, AC97_SPDIF_CONTROL) != val ) { + printk(KERN_ERR "i810_audio: Unable to set S/PDIF configuration to 0x%04x.\n", val); + return -EFAULT; + } + } +#ifdef DEBUG + else + printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n"); +#endif + return put_user(val, (int *)arg); + + case SNDCTL_DSP_GETSPDIF: /* Get S/PDIF Control register */ +#ifdef DEBUG + printk("SNDCTL_DSP_GETSPDIF\n"); +#endif + if (get_user(val, (int *)arg)) + return -EFAULT; + + /* Check to make sure the codec supports S/PDIF transmitter */ + + if(!(state->card->ac97_features & 4)) { +#ifdef DEBUG + printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n"); +#endif + val = 0; + } else { + val = i810_ac97_get(codec, AC97_SPDIF_CONTROL); + } + //return put_user((val & 0xcfff), (int *)arg); + return put_user(val, (int *)arg); + + case SNDCTL_DSP_GETCHANNELMASK: +#ifdef DEBUG + printk("SNDCTL_DSP_GETCHANNELMASK\n"); +#endif + if (get_user(val, (int *)arg)) + return -EFAULT; + + /* Based on AC'97 DAC support, not ICH hardware */ + val = DSP_BIND_FRONT; + if ( state->card->ac97_features & 0x0004 ) + val |= DSP_BIND_SPDIF; + + if ( state->card->ac97_features & 0x0080 ) + val |= DSP_BIND_SURR; + if ( state->card->ac97_features & 0x0140 ) + val |= DSP_BIND_CENTER_LFE; + + return put_user(val, (int *)arg); + + case SNDCTL_DSP_BIND_CHANNEL: +#ifdef DEBUG + printk("SNDCTL_DSP_BIND_CHANNEL\n"); +#endif + if (get_user(val, (int *)arg)) + return -EFAULT; + if ( val == DSP_BIND_QUERY ) { + val = DSP_BIND_FRONT; /* Always report this as being enabled */ + if ( state->card->ac97_status & SPDIF_ON ) + val |= DSP_BIND_SPDIF; + else { + if ( state->card->ac97_status & SURR_ON ) + val |= DSP_BIND_SURR; + if ( state->card->ac97_status & CENTER_LFE_ON ) + val |= DSP_BIND_CENTER_LFE; + } + } else { /* Not a query, set it */ + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + if ( dmabuf->enable == DAC_RUNNING ) { + stop_dac(state); + } + if ( val & DSP_BIND_SPDIF ) { /* Turn on SPDIF */ + /* Ok, this should probably define what slots + * to use. For now, we'll only set it to the + * defaults: + * + * non multichannel codec maps to slots 3&4 + * 2 channel codec maps to slots 7&8 + * 4 channel codec maps to slots 6&9 + * 6 channel codec maps to slots 10&11 + * + * there should be some way for the app to + * select the slot assignment. + */ + + i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, dmabuf->rate ); + if ( !(state->card->ac97_status & SPDIF_ON) ) + val &= ~DSP_BIND_SPDIF; + } else { + int mask; + int channels; + + /* Turn off S/PDIF if it was on */ + if ( state->card->ac97_status & SPDIF_ON ) + i810_set_spdif_output ( state, -1, 0 ); + + mask = val & (DSP_BIND_FRONT | DSP_BIND_SURR | DSP_BIND_CENTER_LFE); + switch (mask) { + case DSP_BIND_FRONT: + channels = 2; + break; + case DSP_BIND_FRONT|DSP_BIND_SURR: + channels = 4; + break; + case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE: + channels = 6; + break; + default: + val = DSP_BIND_FRONT; + channels = 2; + break; + } + i810_set_dac_channels ( state, channels ); + + /* check that they really got turned on */ + if ( !state->card->ac97_status & SURR_ON ) + val &= ~DSP_BIND_SURR; + if ( !state->card->ac97_status & CENTER_LFE_ON ) + val &= ~DSP_BIND_CENTER_LFE; + } + } + return put_user(val, (int *)arg); + case SNDCTL_DSP_MAPINBUF: case SNDCTL_DSP_MAPOUTBUF: case SNDCTL_DSP_SETSYNCRO: @@ -1805,7 +2179,15 @@ card->states[i] = NULL;; return -EBUSY; } - i810_set_dac_rate(state, 8000); + /* Initialize to 8kHz? What if we don't support 8kHz? */ + /* Let's change this to check for S/PDIF stuff */ + + if ( spdif_locked ) { + i810_set_dac_rate(state, spdif_locked); + i810_set_spdif_output(state, AC97_EA_SPSA_3_4, spdif_locked); + } else { + i810_set_dac_rate(state, 8000); + } dmabuf->trigger |= PCM_ENABLE_OUTPUT; } @@ -1875,20 +2257,23 @@ { struct i810_card *card = dev->private_data; int count = 100; + u8 reg_set = ((dev->id)?((reg&0x7f)|0x80):(reg&0x7f)); while(count-- && (inb(card->iobase + CAS) & 1)) udelay(1); - return inw(card->ac97base + (reg&0x7f)); + + return inw(card->ac97base + reg_set); } static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data) { struct i810_card *card = dev->private_data; int count = 100; + u8 reg_set = ((dev->id)?((reg&0x7f)|0x80):(reg&0x7f)); while(count-- && (inb(card->iobase + CAS) & 1)) udelay(1); - outw(data, card->ac97base + (reg&0x7f)); + outw(data, card->ac97base + reg_set); } @@ -1929,7 +2314,7 @@ static int __init i810_ac97_init(struct i810_card *card) { int num_ac97 = 0; - int ready_2nd = 0; + int total_channels = 0; struct ac97_codec *codec; u16 eid; int i=0; @@ -1961,10 +2346,38 @@ current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ/5); + + /* Number of channels supported */ + /* What about the codec? Just because the ICH supports */ + /* multiple channels doesn't mean the codec does. */ + /* we'll have to modify this in the codec section below */ + /* to reflect what the codec has. */ + /* ICH and ICH0 only support 2 channels so don't bother */ + /* to check.... */ + + card->channels = 2; + reg = inl(card->iobase + GLOB_STA); + if ( reg & 0x0200000 ) + card->channels = 6; + else if ( reg & 0x0100000 ) + card->channels = 4; + printk("i810_audio: Audio Controller supports %d channels.\n", card->channels); inw(card->ac97base); for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { + + /* The ICH programmer's reference says you should */ + /* check the ready status before probing. So we chk */ + /* What do we do if it's not ready? Wait and try */ + /* again, or abort? */ + reg = inl(card->iobase + GLOB_STA); + if (!(reg & (0x100 << num_ac97))) { + if(num_ac97 == 0) + printk(KERN_ERR "i810_audio: Primary codec not ready.\n"); + break; /* I think this works, if not ready stop */ + } + if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL) return -ENOMEM; memset(codec, 0, sizeof(struct ac97_codec)); @@ -1992,6 +2405,9 @@ schedule_timeout(HZ/20); } + /* Store state information about S/PDIF transmitter */ + card->ac97_status = 0; + /* Don't attempt to get eid until powerup is complete */ eid = i810_ac97_get(codec, AC97_EXTENDED_ID); @@ -2023,6 +2439,63 @@ } } + /* Determine how many channels the codec(s) support */ + /* - The primary codec always supports 2 */ + /* - If the codec supports AMAP, surround DACs will */ + /* automaticlly get assigned to slots. */ + /* * Check for surround DACs and increment if */ + /* found. */ + /* - Else check if the codec is revision 2.2 */ + /* * If surround DACs exist, assign them to slots */ + /* and increment channel count. */ + + /* All of this only applies to ICH2 and above. ICH */ + /* and ICH0 only support 2 channels. ICH2 will only */ + /* support multiple codecs in a "split audio" config. */ + /* as described above. */ + + /* TODO: Remove all the debugging messages! */ + + if((eid & 0xc000) == 0) /* primary codec */ + total_channels += 2; + + if(eid & 0x200) { /* GOOD, AMAP support */ + if (eid & 0x0080) /* L/R Surround channels */ + total_channels += 2; + if (eid & 0x0140) /* LFE and Center channels */ + total_channels += 2; + printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", num_ac97, total_channels); + } else if (eid & 0x0400) { /* this only works on 2.2 compliant codecs */ + eid &= 0xffcf; + if((eid & 0xc000) != 0) { + switch ( total_channels ) { + case 2: + /* Set dsa1, dsa0 to 01 */ + eid |= 0x0010; + break; + case 4: + /* Set dsa1, dsa0 to 10 */ + eid |= 0x0020; + break; + case 6: + /* Set dsa1, dsa0 to 11 */ + eid |= 0x0030; + break; + } + total_channels += 2; + } + i810_ac97_set(codec, AC97_EXTENDED_ID, eid); + eid = i810_ac97_get(codec, AC97_EXTENDED_ID); + printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", num_ac97, eid); + if (eid & 0x0080) /* L/R Surround channels */ + total_channels += 2; + if (eid & 0x0140) /* LFE and Center channels */ + total_channels += 2; + printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", num_ac97, total_channels); + } else { + printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", num_ac97, total_channels); + } + if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) { printk(KERN_ERR "i810_audio: couldn't register mixer!\n"); kfree(codec); @@ -2030,14 +2503,83 @@ } card->ac97_codec[num_ac97] = codec; - - /* if there is no secondary codec at all, don't probe any more */ - if (!ready_2nd) - return num_ac97+1; } + + /* pick the minimum of channels supported by ICHx or codec(s) */ + card->channels = (card->channels > total_channels)?total_channels:card->channels; + 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 +2644,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 +2689,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]); } @@ -2151,6 +2703,7 @@ MODULE_PARM(ftsodell, "i"); MODULE_PARM(clocking, "i"); MODULE_PARM(strict_clocking, "i"); +MODULE_PARM(spdif_locked, "i"); #define I810_MODULE_NAME "intel810_audio" @@ -2161,74 +2714,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) { @@ -2248,6 +2733,15 @@ if(clocking == 48000) { i810_configure_clocking(); } + if(spdif_locked > 0 ) { + if(spdif_locked == 32000 || spdif_locked == 44100 || spdif_locked == 48000) { + printk("i810_audio: Enabling S/PDIF at sample rate %dHz.\n", spdif_locked); + } else { + printk("i810_audio: S/PDIF can only be locked to 32000, 441000, or 48000Hz.\n"); + spdif_locked = 0; + } + } + return 0; } 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/opl3sa2.c linux/drivers/sound/opl3sa2.c --- v2.4.9/linux/drivers/sound/opl3sa2.c Fri Mar 2 18:38:39 2001 +++ linux/drivers/sound/opl3sa2.c Sun Sep 9 10:52:35 2001 @@ -810,7 +810,7 @@ struct isapnp_device_id isapnp_opl3sa2_list[] __initdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), - NULL }, + 0 }, {0} }; diff -u --recursive --new-file v2.4.9/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- v2.4.9/linux/drivers/sound/sb_card.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/sound/sb_card.c Tue Sep 18 14:10:43 2001 @@ -304,6 +304,11 @@ 0,0,0,0, 0,1,1,-1}, {"Sound Blaster 16", + ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), + 0,0,0,0, + 0,1,1,-1}, + {"Sound Blaster 16", ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0,0,0,0, @@ -313,6 +318,11 @@ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0,0,0,0, 0,1,1,-1}, + {"Sound Blaster 16", + ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), + 0,0,0,0, + 0,1,1,-1}, {"Sound Blaster Vibra16S", ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), @@ -364,6 +374,11 @@ 0,0,0,0, 0,1,1,-1}, {"Sound Blaster AWE 32", + ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), + 0,0,0,0, + 0,1,1,-1}, + {"Sound Blaster AWE 32", ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0,0,0,0, @@ -537,7 +552,13 @@ { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 }, + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002c), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 }, + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 }, + + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 }, { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0086), 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 14 14:04:07 2001 @@ -118,25 +118,10 @@ #include #include #include - -#include "dm.h" - -#if defined(CONFIG_INPUT_ANALOG) || defined(CONFIG_INPUT_ANALOG_MODULE) #include -#else -struct gameport { - int io; - int size; -}; -extern inline void gameport_register_port(struct gameport *gameport) -{ -} +#include "dm.h" -extern inline void gameport_unregister_port(struct gameport *gameport) -{ -} -#endif /* --------------------------------------------------------------------- */ @@ -2496,7 +2481,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/sound_core.c linux/drivers/sound/sound_core.c --- v2.4.9/linux/drivers/sound/sound_core.c Fri Apr 6 10:51:19 2001 +++ linux/drivers/sound/sound_core.c Sun Sep 9 10:52:35 2001 @@ -145,7 +145,7 @@ * This lock guards the sound loader list. */ -spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED; /* * Allocate the controlling structure and add it to the sound driver 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 Sun Sep 9 10:52:35 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 @@ -862,6 +858,7 @@ /** * via_chan_clear - Stop DMA channel operation, and reset pointers + * @card: the chip to accessed * @chan: Channel to be cleared * * Call via_chan_stop to halt DMA operations, and then resets diff -u --recursive --new-file v2.4.9/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c --- v2.4.9/linux/drivers/sound/wavfront.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/wavfront.c Thu Sep 13 12:49:44 2001 @@ -86,22 +86,6 @@ #include -/* - * This sucks, hopefully it'll get standardised - */ - -#if defined(__alpha__) -#ifdef CONFIG_SMP -#define LOOPS_PER_TICK cpu_data[smp_processor_id()].loops_per_jiffy -#else -#define LOOPS_PER_TICK loops_per_jiffy -#endif -#endif - -#if defined(__i386__) -#define LOOPS_PER_TICK current_cpu_data.loops_per_jiffy -#endif - #define _MIDI_SYNTH_C_ #define MIDI_SYNTH_NAME "WaveFront MIDI" #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT @@ -191,21 +175,17 @@ version of the WaveFront OS */ -int wait_usecs = 150; /* This magic number seems to give pretty optimal - throughput based on my limited experimentation. - If you want to play around with it and find a better - value, be my guest. Remember, the idea is to - get a number that causes us to just busy wait - for as many WaveFront commands as possible, without - coming up with a number so large that we hog the - whole CPU. - - Specifically, with this number, out of about 134,000 - status waits, only about 250 result in a sleep. - */ +int wait_polls = 2000; /* This is a number of tries we poll the status register + before resorting to sleeping. WaveFront being an ISA + card each poll takes about 1.2us. So before going to + sleep we wait up to 2.4ms in a loop. + */ + +int sleep_length = HZ/100; /* This says how long we're going to sleep between polls. + 10ms sounds reasonable for fast response. + */ -int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */ -int sleep_tries = 50; /* number of times we'll try to sleep */ +int sleep_tries = 50; /* Wait for status 0.5 seconds total. */ int reset_time = 2; /* hundreths of a second we wait after a HW reset for the expected interrupt. @@ -222,8 +202,8 @@ MODULE_PARM(wf_raw,"i"); MODULE_PARM(fx_raw,"i"); MODULE_PARM(debug_default,"i"); -MODULE_PARM(wait_usecs,"i"); -MODULE_PARM(sleep_interval,"i"); +MODULE_PARM(wait_polls,"i"); +MODULE_PARM(sleep_length,"i"); MODULE_PARM(sleep_tries,"i"); MODULE_PARM(ospath,"s"); MODULE_PARM(reset_time,"i"); @@ -437,54 +417,30 @@ } static int -wavefront_sleep (int limit) - -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(limit); - - return signal_pending(current); -} - -static int wavefront_wait (int mask) { - int i; - static int short_loop_cnt = 0; - - /* Compute the loop count that lets us sleep for about the - right amount of time, cache issues, bus speeds and all - other issues being unequal but largely irrelevant. - */ - - if (short_loop_cnt == 0) { - short_loop_cnt = wait_usecs * - (LOOPS_PER_TICK / (1000000 / HZ)); - } - - /* Spin for a short period of time, because >99% of all - requests to the WaveFront can be serviced inline like this. - */ + int i; - for (i = 0; i < short_loop_cnt; i++) { - if (wavefront_status() & mask) { + for (i = 0; i < wait_polls; i++) + if (wavefront_status() & mask) return 1; - } - } for (i = 0; i < sleep_tries; i++) { if (wavefront_status() & mask) { + set_current_state(TASK_RUNNING); return 1; } - if (wavefront_sleep (HZ/sleep_interval)) { - return (0); - } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(sleep_length); + if (signal_pending(current)) + break; } - return (0); + set_current_state(TASK_RUNNING); + return 0; } static int diff -u --recursive --new-file v2.4.9/linux/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c --- v2.4.9/linux/drivers/sound/ymfpci.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sound/ymfpci.c Mon Sep 17 23:26:09 2001 @@ -457,11 +457,12 @@ } #endif + set_current_state(TASK_UNINTERRUPTIBLE); while (ypcm->running) { spin_unlock_irqrestore(&unit->reg_lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); schedule(); spin_lock_irqsave(&unit->reg_lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); } spin_unlock_irqrestore(&unit->reg_lock, flags); @@ -1198,12 +1199,13 @@ ret = 0; add_wait_queue(&dmabuf->wait, &waita); + set_current_state(TASK_INTERRUPTIBLE); while (count > 0) { spin_lock_irqsave(&unit->reg_lock, flags); if (unit->suspended) { spin_unlock_irqrestore(&unit->reg_lock, flags); - set_current_state(TASK_INTERRUPTIBLE); schedule(); + set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { if (!ret) ret = -EAGAIN; break; @@ -1241,9 +1243,9 @@ is TOO LATE for the process to be scheduled to run (scheduler latency) which results in a (potential) buffer overrun. And worse, there is NOTHING we can do to prevent it. */ - set_current_state(TASK_INTERRUPTIBLE); tmo = schedule_timeout(tmo); spin_lock_irqsave(&state->unit->reg_lock, flags); + set_current_state(TASK_INTERRUPTIBLE); if (tmo == 0 && dmabuf->count == 0) { printk(KERN_ERR "ymfpci%d: recording schedule timeout, " "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", @@ -1326,12 +1328,13 @@ redzone *= 3; /* 2 redzone + 1 possible uncertainty reserve. */ add_wait_queue(&dmabuf->wait, &waita); + set_current_state(TASK_INTERRUPTIBLE); while (count > 0) { spin_lock_irqsave(&unit->reg_lock, flags); if (unit->suspended) { spin_unlock_irqrestore(&unit->reg_lock, flags); - set_current_state(TASK_INTERRUPTIBLE); schedule(); + set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { if (!ret) ret = -EAGAIN; break; @@ -1389,8 +1392,8 @@ if (!ret) ret = -EAGAIN; break; } - set_current_state(TASK_INTERRUPTIBLE); schedule(); + set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { if (!ret) ret = -ERESTARTSYS; break; 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 Sun Sep 9 10:52:35 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->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->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); - - ixj_write_cid_byte(j, 0x80); - checksum = 0x80; - ixj_write_cid_byte(j, mdmflen); - checksum = checksum + mdmflen; + while(1){ + ixj_write_cid_seize(j); - 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, 0x80); + checksum = 0x80; + ixj_write_cid_byte(j, mdmflen); + checksum = checksum + mdmflen; - 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, 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, 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, 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; - checksum %= 256; - checksum ^= 0xFF; - checksum += 1; + 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; - ixj_write_cid_byte(j, (char) checksum); + checksum %= 256; + checksum ^= 0xFF; + checksum += 1; - pad = j->fskdcnt % 240; - if (pad) { - pad = 240 - pad; + ixj_write_cid_byte(j, (char) checksum); + + 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) @@ -3341,18 +4718,22 @@ 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.low, j->XILINXbase + 0x02); // Load Mixer Data + outb_p(bytes.high & 0x1F, j->XILINXbase + 0x03); /* Load Mixer Address */ + + 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) { - j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + 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 */ 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,12 +6683,20 @@ 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]; + if(arg<0||arg>3) + retval = -EINVAL; + else + retval = j->filter_hist[arg]; break; case IXJCTL_INIT_TONE: copy_from_user(&ti, (char *) arg, sizeof(ti)); @@ -5102,117 +6708,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 +6834,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 +6854,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 +6894,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 +6957,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 +6974,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 +6983,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 +6991,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 +7003,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 +7040,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 +7129,7 @@ } else { ixj_set_port(j, PORT_POTS); SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); +/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ } } } @@ -5490,31 +7138,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 +7186,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 +7270,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 +7297,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 +7306,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 +7329,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 +7374,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 +7396,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 +7447,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 +7484,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 +7493,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 +7504,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 +7529,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 +7541,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 +7641,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 +7658,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 +7676,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 +7709,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 +7729,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 +7752,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 +7779,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 +7791,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 +7804,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 +7872,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 +7886,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 +8026,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 +8035,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 +8096,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 +8111,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 +8120,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 +8129,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 +8138,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 +8157,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 +8166,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 +8175,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 +8185,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 +8194,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 +8208,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 +8217,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 +8276,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 +8291,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 +8300,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 +8309,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 +8318,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 +8337,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 +8346,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 +8355,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 +8365,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 +8374,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 +8388,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 +8397,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 +8456,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 +8471,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 +8480,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 +8489,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 +8498,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 +8517,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 +8526,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 +8535,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 +8545,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 +8554,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 +8568,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 +8577,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 +8636,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 +8651,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 +8660,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 +8669,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 +8678,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 +8697,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 +8706,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 +8715,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 +8725,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 +8734,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 +8748,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 +8757,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 +8816,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 +8831,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 +8840,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 +8849,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 +8858,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 +8877,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 +8886,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 +8895,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 +8905,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 +8914,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 +8928,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 +8937,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 +8992,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 +10558,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 +10605,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 +10671,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 +10682,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/CDCEther.c linux/drivers/usb/CDCEther.c --- v2.4.9/linux/drivers/usb/CDCEther.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/CDCEther.c Mon Sep 17 22:52:35 2001 @@ -1271,6 +1271,7 @@ MODULE_AUTHOR("Brad Hards and another"); MODULE_DESCRIPTION("USB CDC Ethernet driver"); +MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE (usb, CDCEther_ids); 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 Wed Sep 12 15:34:06 2001 @@ -14,8 +14,9 @@ # Multipart objects. -list-multi := usbcore.o +list-multi := usbcore.o hid.o usbcore-objs := usb.o usb-debug.o hub.o +hid-objs := hid-core.o hid-input.o ifneq ($(CONFIG_USB_PWC),n) export-objs += pwc-uncompress.o @@ -31,6 +32,10 @@ usbcore-objs += devio.o inode.o drivers.o devices.o endif +ifeq ($(CONFIG_USB_HIDDEV),y) + hid-objs += hiddev.o +endif + # Object file lists. obj-y := @@ -60,16 +65,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 @@ -91,6 +96,8 @@ usbcore.o: $(usbcore-objs) $(LD) -r -o $@ $(usbcore-objs) -pwc.o: $(pwc-objs) - $(LD) -r -o $@ $(pwc-objs) +hid.o: $(hid-objs) + $(LD) -r -o $@ $(hid-objs) +pwc.o: $(pwc-objs) + $(LD) -r -o $@ $(pwc-objs) diff -u --recursive --new-file v2.4.9/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.4.9/linux/drivers/usb/acm.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/usb/acm.c Fri Sep 14 14:04:07 2001 @@ -732,4 +732,5 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); 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 Fri Sep 14 14:04:07 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 (count, bluetooth->bulk_out_buffer_size); memcpy (urb->transfer_buffer, current_position, buffer_size); /* build up our urb */ @@ -1346,4 +1345,5 @@ /* Module information */ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/catc.c linux/drivers/usb/catc.c --- v2.4.9/linux/drivers/usb/catc.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/catc.c Fri Sep 14 14:04:07 2001 @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -54,6 +54,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); /* * Some defines. diff -u --recursive --new-file v2.4.9/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c --- v2.4.9/linux/drivers/usb/dabusb.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/dabusb.c Fri Sep 14 14:04:07 2001 @@ -848,6 +848,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM (buffers, "i"); MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); 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 Fri Sep 14 14:04:07 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: @@ -465,6 +481,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. */ @@ -513,4 +531,5 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); 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 Mon Sep 10 08:06:32 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; @@ -1082,7 +1082,7 @@ if (retval == 0) /* ifno might usefully be passed ... */ retval = ifp->driver->ioctl (ps->dev, ctrl.ioctl_code, buf); - /* size = min(int, size, retval)? */ + /* size = min_t(int, size, retval)? */ } /* cleanup and return */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/hid-core.c linux/drivers/usb/hid-core.c --- v2.4.9/linux/drivers/usb/hid-core.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/hid-core.c Sun Sep 16 11:07:43 2001 @@ -0,0 +1,1307 @@ +/* + * $Id: hid-core.c,v 1.8 2001/05/23 12:02:18 vojtech Exp $ + * + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2001 Vojtech Pavlik + * + * USB HID support for Linux + * + * Sponsored by SuSE + */ + +/* + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG +#undef DEBUG_DATA + +#include + +#include "hid.h" +#ifdef CONFIG_USB_HIDDEV +#include +#endif + +/* + * Version Information + */ + +#define DRIVER_VERSION "v1.8" +#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik " +#define DRIVER_DESC "USB HID support drivers" + +static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", + "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; + +/* + * Register a new report for a device. + */ + +static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) +{ + struct hid_report_enum *report_enum = device->report_enum + type; + struct hid_report *report; + + if (report_enum->report_id_hash[id]) + return report_enum->report_id_hash[id]; + + if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL))) + return NULL; + memset(report, 0, sizeof(struct hid_report)); + + if (id != 0) report_enum->numbered = 1; + + report->id = id; + report->type = type; + report->size = 0; + report->device = device; + report_enum->report_id_hash[id] = report; + + list_add_tail(&report->list, &report_enum->report_list); + + return report; +} + +/* + * Register a new field for this report. + */ + +static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) +{ + struct hid_field *field; + + if (report->maxfield == HID_MAX_FIELDS) { + dbg("too many fields in report"); + return NULL; + } + + if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + + values * sizeof(unsigned), GFP_KERNEL))) return NULL; + + memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + + values * sizeof(unsigned)); + + report->field[report->maxfield++] = field; + field->usage = (struct hid_usage *)(field + 1); + field->value = (unsigned *)(field->usage + usages); + field->report = report; + + return field; +} + +/* + * Open a collection. The type/usage is pushed on the stack. + */ + +static int open_collection(struct hid_parser *parser, unsigned type) +{ + struct hid_collection *collection; + unsigned usage; + + usage = parser->local.usage[0]; + + if (type == HID_COLLECTION_APPLICATION + && parser->device->maxapplication < HID_MAX_APPLICATIONS) + parser->device->application[parser->device->maxapplication++] = usage; + + if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { + dbg("collection stack overflow"); + return -1; + } + + collection = parser->collection_stack + parser->collection_stack_ptr++; + collection->type = type; + collection->usage = usage; + + return 0; +} + +/* + * Close a collection. + */ + +static int close_collection(struct hid_parser *parser) +{ + if (!parser->collection_stack_ptr) { + dbg("collection stack underflow"); + return -1; + } + parser->collection_stack_ptr--; + return 0; +} + +/* + * Climb up the stack, search for the specified collection type + * and return the usage. + */ + +static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) +{ + int n; + for (n = parser->collection_stack_ptr - 1; n >= 0; n--) + if (parser->collection_stack[n].type == type) + return parser->collection_stack[n].usage; + return 0; /* we know nothing about this usage type */ +} + +/* + * Add a usage to the temporary parser table. + */ + +static int hid_add_usage(struct hid_parser *parser, unsigned usage) +{ + if (parser->local.usage_index >= HID_MAX_USAGES) { + dbg("usage index exceeded"); + return -1; + } + parser->local.usage[parser->local.usage_index++] = usage; + return 0; +} + +/* + * Register a new field for this report. + */ + +static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags) +{ + struct hid_report *report; + struct hid_field *field; + int usages; + unsigned offset; + int i; + + if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) { + dbg("hid_register_report failed"); + return -1; + } + + if (HID_MAIN_ITEM_VARIABLE & ~flags) { /* ARRAY */ + if (parser->global.logical_maximum <= parser->global.logical_minimum) { + dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); + return -1; + } + usages = parser->local.usage_index; + /* Hint: we can assume usages < MAX_USAGE here */ + } else { /* VARIABLE */ + usages = parser->global.report_count; + } + + offset = report->size; + report->size += parser->global.report_size * parser->global.report_count; + + if (usages == 0) + return 0; /* ignore padding fields */ + + if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL) + return 0; + + field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); + field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); + field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); + + for (i = 0; i < usages; i++) + field->usage[i].hid = parser->local.usage[i]; + + field->maxusage = usages; + field->flags = flags; + field->report_offset = offset; + field->report_type = report_type; + field->report_size = parser->global.report_size; + field->report_count = parser->global.report_count; + field->logical_minimum = parser->global.logical_minimum; + field->logical_maximum = parser->global.logical_maximum; + field->physical_minimum = parser->global.physical_minimum; + field->physical_maximum = parser->global.physical_maximum; + field->unit_exponent = parser->global.unit_exponent; + field->unit = parser->global.unit; + + return 0; +} + +/* + * Read data value from item. + */ + +static __inline__ __u32 item_udata(struct hid_item *item) +{ + switch (item->size) { + case 1: return item->data.u8; + case 2: return item->data.u16; + case 4: return item->data.u32; + } + return 0; +} + +static __inline__ __s32 item_sdata(struct hid_item *item) +{ + switch (item->size) { + case 1: return item->data.s8; + case 2: return item->data.s16; + case 4: return item->data.s32; + } + return 0; +} + +/* + * Process a global item. + */ + +static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) +{ + switch (item->tag) { + + case HID_GLOBAL_ITEM_TAG_PUSH: + + if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { + dbg("global enviroment stack overflow"); + return -1; + } + + memcpy(parser->global_stack + parser->global_stack_ptr++, + &parser->global, sizeof(struct hid_global)); + return 0; + + case HID_GLOBAL_ITEM_TAG_POP: + + if (!parser->global_stack_ptr) { + dbg("global enviroment stack underflow"); + return -1; + } + + memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr, + sizeof(struct hid_global)); + return 0; + + case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: + parser->global.usage_page = item_udata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: + parser->global.logical_minimum = item_sdata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: + parser->global.logical_maximum = item_sdata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: + parser->global.physical_minimum = item_sdata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: + parser->global.physical_maximum = item_sdata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: + parser->global.unit_exponent = item_udata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_UNIT: + parser->global.unit = item_udata(item); + return 0; + + case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: + if ((parser->global.report_size = item_udata(item)) > 32) { + dbg("invalid report_size %d", parser->global.report_size); + return -1; + } + return 0; + + case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: + if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) { + dbg("invalid report_count %d", parser->global.report_count); + return -1; + } + return 0; + + case HID_GLOBAL_ITEM_TAG_REPORT_ID: + if ((parser->global.report_id = item_udata(item)) == 0) { + dbg("report_id 0 is invalid"); + return -1; + } + return 0; + + default: + dbg("unknown global tag 0x%x", item->tag); + return -1; + } +} + +/* + * Process a local item. + */ + +static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) +{ + __u32 data; + unsigned n; + + if (item->size == 0) { + dbg("item data expected for local item"); + return -1; + } + + data = item_udata(item); + + switch (item->tag) { + + case HID_LOCAL_ITEM_TAG_DELIMITER: + + if (data) { + /* + * We treat items before the first delimiter + * as global to all usage sets (branch 0). + * In the moment we process only these global + * items and the first delimiter set. + */ + if (parser->local.delimiter_depth != 0) { + dbg("nested delimiters"); + return -1; + } + parser->local.delimiter_depth++; + parser->local.delimiter_branch++; + } else { + if (parser->local.delimiter_depth < 1) { + dbg("bogus close delimiter"); + return -1; + } + parser->local.delimiter_depth--; + } + return 1; + + case HID_LOCAL_ITEM_TAG_USAGE: + + if (parser->local.delimiter_branch > 1) { + dbg("alternative usage ignored"); + return 0; + } + + if (item->size <= 2) + data = (parser->global.usage_page << 16) + data; + + return hid_add_usage(parser, data); + + case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: + + if (parser->local.delimiter_branch > 1) { + dbg("alternative usage ignored"); + return 0; + } + + if (item->size <= 2) + data = (parser->global.usage_page << 16) + data; + + parser->local.usage_minimum = data; + return 0; + + case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: + + if (parser->local.delimiter_branch > 1) { + dbg("alternative usage ignored"); + return 0; + } + + if (item->size <= 2) + data = (parser->global.usage_page << 16) + data; + + for (n = parser->local.usage_minimum; n <= data; n++) + if (hid_add_usage(parser, n)) { + dbg("hid_add_usage failed\n"); + return -1; + } + return 0; + + default: + + dbg("unknown local item tag 0x%x", item->tag); + return 0; + } + return 0; +} + +/* + * Process a main item. + */ + +static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) +{ + __u32 data; + int ret; + + data = item_udata(item); + + switch (item->tag) { + case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: + ret = open_collection(parser, data & 3); + break; + case HID_MAIN_ITEM_TAG_END_COLLECTION: + ret = close_collection(parser); + break; + case HID_MAIN_ITEM_TAG_INPUT: + ret = hid_add_field(parser, HID_INPUT_REPORT, data); + break; + case HID_MAIN_ITEM_TAG_OUTPUT: + ret = hid_add_field(parser, HID_OUTPUT_REPORT, data); + break; + case HID_MAIN_ITEM_TAG_FEATURE: + ret = hid_add_field(parser, HID_FEATURE_REPORT, data); + break; + default: + dbg("unknown main item tag 0x%x", item->tag); + ret = 0; + } + + memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */ + + return ret; +} + +/* + * Process a reserved item. + */ + +static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item) +{ + dbg("reserved item type, tag 0x%x", item->tag); + return 0; +} + +/* + * Free a report and all registered fields. The field->usage and + * field->value table's are allocated behind the field, so we need + * only to free(field) itself. + */ + +static void hid_free_report(struct hid_report *report) +{ + unsigned n; + + for (n = 0; n < report->maxfield; n++) + kfree(report->field[n]); + if (report->data) + kfree(report->data); + kfree(report); +} + +/* + * Free a device structure, all reports, and all fields. + */ + +static void hid_free_device(struct hid_device *device) +{ + unsigned i,j; + + for (i = 0; i < HID_REPORT_TYPES; i++) { + struct hid_report_enum *report_enum = device->report_enum + i; + + for (j = 0; j < 256; j++) { + struct hid_report *report = report_enum->report_id_hash[j]; + if (report) hid_free_report(report); + } + } + + if (device->rdesc) kfree(device->rdesc); +} + +/* + * Fetch a report description item from the data stream. We support long + * items, though they are not used yet. + */ + +static __u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) +{ + if ((end - start) > 0) { + + __u8 b = *start++; + item->type = (b >> 2) & 3; + item->tag = (b >> 4) & 15; + + if (item->tag == HID_ITEM_TAG_LONG) { + + item->format = HID_ITEM_FORMAT_LONG; + + if ((end - start) >= 2) { + + item->size = *start++; + item->tag = *start++; + + if ((end - start) >= item->size) { + item->data.longdata = start; + start += item->size; + return start; + } + } + } else { + + item->format = HID_ITEM_FORMAT_SHORT; + item->size = b & 3; + switch (item->size) { + + case 0: + return start; + + case 1: + if ((end - start) >= 1) { + item->data.u8 = *start++; + return start; + } + break; + + case 2: + if ((end - start) >= 2) { + item->data.u16 = le16_to_cpu( get_unaligned(((__u16*)start)++)); + return start; + } + + case 3: + item->size++; + if ((end - start) >= 4) { + item->data.u32 = le32_to_cpu( get_unaligned(((__u32*)start)++)); + return start; + } + } + } + } + return NULL; +} + +/* + * Parse a report description into a hid_device structure. Reports are + * enumerated, fields are attached to these reports. + */ + +static struct hid_device *hid_parse_report(__u8 *start, unsigned size) +{ + struct hid_device *device; + struct hid_parser *parser; + struct hid_item item; + __u8 *end; + unsigned i; + static int (*dispatch_type[])(struct hid_parser *parser, + struct hid_item *item) = { + hid_parser_main, + hid_parser_global, + hid_parser_local, + hid_parser_reserved + }; + + if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL))) + return NULL; + memset(device, 0, sizeof(struct hid_device)); + + for (i = 0; i < HID_REPORT_TYPES; i++) + INIT_LIST_HEAD(&device->report_enum[i].report_list); + + if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) { + kfree(device); + return NULL; + } + memcpy(device->rdesc, start, size); + + if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) { + kfree(device->rdesc); + kfree(device); + return NULL; + } + memset(parser, 0, sizeof(struct hid_parser)); + parser->device = device; + + end = start + size; + while ((start = fetch_item(start, end, &item)) != 0) { + if (item.format != HID_ITEM_FORMAT_SHORT) { + dbg("unexpected long global item"); + hid_free_device(device); + kfree(parser); + return NULL; + } + if (dispatch_type[item.type](parser, &item)) { + dbg("item %u %u %u %u parsing failed\n", + item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); + hid_free_device(device); + kfree(parser); + return NULL; + } + + if (start == end) { + if (parser->collection_stack_ptr) { + dbg("unbalanced collection at end of report description"); + hid_free_device(device); + kfree(parser); + return NULL; + } + if (parser->local.delimiter_depth) { + dbg("unbalanced delimiter at end of report description"); + hid_free_device(device); + kfree(parser); + return NULL; + } + kfree(parser); + return device; + } + } + + dbg("item fetching failed at offset %d\n", (int)(end - start)); + hid_free_device(device); + kfree(parser); + return NULL; +} + +/* + * Convert a signed n-bit integer to signed 32-bit integer. Common + * cases are done through the compiler, the screwed things has to be + * done by hand. + */ + +static __inline__ __s32 snto32(__u32 value, unsigned n) +{ + switch (n) { + case 8: return ((__s8)value); + case 16: return ((__s16)value); + case 32: return ((__s32)value); + } + return value & (1 << (n - 1)) ? value | (-1 << n) : value; +} + +/* + * Convert a signed 32-bit integer to a signed n-bit integer. + */ + +static __inline__ __u32 s32ton(__s32 value, unsigned n) +{ + __s32 a = value >> (n - 1); + if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; + return value & ((1 << n) - 1); +} + +/* + * Extract/implement a data field from/to a report. + */ + +static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) +{ + report += (offset >> 5) << 2; offset &= 31; + return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1); +} + +static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) +{ + report += (offset >> 5) << 2; offset &= 31; + put_unaligned((get_unaligned((__u64*)report) + & cpu_to_le64(~((((__u64) 1 << n) - 1) << offset))) + | cpu_to_le64((__u64)value << offset), (__u64*)report); +} + +/* + * Search an array for a value. + */ + +static __inline__ int search(__s32 *array, __s32 value, unsigned n) +{ + while (n--) if (*array++ == value) return 0; + return -1; +} + +static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) +{ + hid_dump_input(usage, value); + if (hid->claimed & HID_CLAIMED_INPUT) + hidinput_hid_event(hid, field, usage, value); +#ifdef CONFIG_USB_HIDDEV + if (hid->claimed & HID_CLAIMED_HIDDEV) + hiddev_hid_event(hid, usage->hid, value); +#endif +} + + +/* + * Analyse a received field, and fetch the data from it. The field + * content is stored for next report processing (we do differential + * reporting to the layer). + */ + +static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data) +{ + unsigned n; + unsigned count = field->report_count; + unsigned offset = field->report_offset; + unsigned size = field->report_size; + __s32 min = field->logical_minimum; + __s32 max = field->logical_maximum; + __s32 value[count]; /* WARNING: gcc specific */ + + for (n = 0; n < count; n++) { + + value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) : + extract(data, offset + n * size, size); + + if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */ + && value[n] >= min && value[n] <= max + && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) + return; + } + + for (n = 0; n < count; n++) { + + if (HID_MAIN_ITEM_VARIABLE & field->flags) { + + if (field->flags & HID_MAIN_ITEM_RELATIVE) { + if (!value[n]) continue; + } else { + if (value[n] == field->value[n]) continue; + } + hid_process_event(hid, field, &field->usage[n], value[n]); + continue; + } + + if (field->value[n] >= min && field->value[n] <= max + && field->usage[field->value[n] - min].hid + && search(value, field->value[n], count)) + hid_process_event(hid, field, &field->usage[field->value[n] - min], 0); + + if (value[n] >= min && value[n] <= max + && field->usage[value[n] - min].hid + && search(field->value, value[n], count)) + hid_process_event(hid, field, &field->usage[value[n] - min], 1); + } + + memcpy(field->value, value, count * sizeof(__s32)); +} + +static int hid_input_report(int type, u8 *data, int len, struct hid_device *hid) +{ + struct hid_report_enum *report_enum = hid->report_enum + type; + struct hid_report *report; + int n, size; + + if (!len) { + dbg("empty report"); + return -1; + } + +#ifdef DEBUG_DATA + printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un"); +#endif + + n = 0; /* Normally report number is 0 */ + if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ + n = *data++; + len--; + } + + if (!(report = report_enum->report_id_hash[n])) { + dbg("undefined report_id %d received", n); +#ifdef DEBUG + printk(KERN_DEBUG __FILE__ ": report (size %u) = ", len); + for (n = 0; n < len; n++) + printk(" %02x", data[n]); + printk("\n"); +#endif + + return -1; + } + + size = ((report->size - 1) >> 3) + 1; + + if (len < size) { + + if (size <= 8) { + dbg("report %d is too short, (%d < %d)", report->id, len, size); + return -1; + } + + /* + * Some low-speed devices have large reports and maxpacketsize 8. + * We buffer the data in that case and parse it when we got it all. + * Works only for unnumbered reports. Doesn't make sense for numbered + * reports anyway - then they don't need to be large. + */ + + if (!report->data) + if (!(report->data = kmalloc(size, GFP_ATOMIC))) { + dbg("couldn't allocate report buffer"); + return -1; + } + + if (report->idx + len > size) { + dbg("report data buffer overflow"); + report->idx = 0; + return -1; + } + + memcpy(report->data + report->idx, data, len); + report->idx += len; + + if (report->idx < size) + return 0; + + data = report->data; + } + + for (n = 0; n < report->maxfield; n++) + hid_input_field(hid, report->field[n], data); + + report->idx = 0; + return 0; +} + +/* + * Interrupt input handler. + */ + +static void hid_irq(struct urb *urb) +{ + if (urb->status) { + dbg("nonzero status in irq %d", urb->status); + return; + } + + hid_input_report(HID_INPUT_REPORT, urb->transfer_buffer, urb->actual_length, urb->context); +} + +/* + * hid_read_report() reads in report values without waiting for an irq urb. + */ + +void hid_read_report(struct hid_device *hid, struct hid_report *report) +{ + int len = ((report->size - 1) >> 3) + 1 + hid->report_enum[report->type].numbered; + u8 data[len]; + int read; + + if ((read = usb_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, data, len)) != len) { + dbg("reading report type %d id %d failed len %d read %d", report->type + 1, report->id, len, read); + return; + } + + hid_input_report(report->type, data, len, hid); +} + +/* + * Output the field into the report. + */ + +static void hid_output_field(struct hid_field *field, __u8 *data) +{ + unsigned count = field->report_count; + unsigned offset = field->report_offset; + unsigned size = field->report_size; + unsigned n; + + for (n = 0; n < count; n++) { + if (field->logical_minimum < 0) /* signed values */ + implement(data, offset + n * size, size, s32ton(field->value[n], size)); + else /* unsigned values */ + implement(data, offset + n * size, size, field->value[n]); + } +} + +/* + * Create a report. + */ + +void hid_output_report(struct hid_report *report, __u8 *data) +{ + unsigned n; + for (n = 0; n < report->maxfield; n++) + hid_output_field(report->field[n], data); +} + +/* + * Set a field value. The report this field belongs to has to be + * created and transfered to the device, to set this value in the + * device. + */ + +int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) +{ + unsigned size = field->report_size; + + hid_dump_input(field->usage + offset, value); + + if (offset >= field->report_count) { + dbg("offset exceeds report_count"); + return -1; + } + if (field->logical_minimum < 0) { + if (value != snto32(s32ton(value, size), size)) { + dbg("value %d is out of range", value); + return -1; + } + } + if ( (value > field->logical_maximum) + || (value < field->logical_minimum)) { + dbg("value %d is invalid", value); + return -1; + } + field->value[offset] = value; + return 0; +} + +int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) +{ + struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT; + struct list_head *list = report_enum->report_list.next; + int i, j; + + while (list != &report_enum->report_list) { + struct hid_report *report = (struct hid_report *) list; + list = list->next; + for (i = 0; i < report->maxfield; i++) { + *field = report->field[i]; + for (j = 0; j < (*field)->maxusage; j++) + if ((*field)->usage[j].type == type && (*field)->usage[j].code == code) + return j; + } + } + return -1; +} + +static int hid_submit_out(struct hid_device *hid) +{ + hid->urbout.transfer_buffer_length = le16_to_cpup(&hid->out[hid->outtail].dr.length); + hid->urbout.transfer_buffer = hid->out[hid->outtail].buffer; + hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr); + hid->urbout.dev = hid->dev; + + if (usb_submit_urb(&hid->urbout)) { + err("usb_submit_urb(out) failed"); + return -1; + } + + return 0; +} + +static void hid_ctrl(struct urb *urb) +{ + struct hid_device *hid = urb->context; + + if (urb->status) + warn("ctrl urb status %d received", urb->status); + + hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1); + + if (hid->outhead != hid->outtail) + hid_submit_out(hid); +} + +void hid_write_report(struct hid_device *hid, struct hid_report *report) +{ + hid_output_report(report, hid->out[hid->outhead].buffer); + + hid->out[hid->outhead].dr.value = cpu_to_le16(0x200 | report->id); + hid->out[hid->outhead].dr.length = cpu_to_le16((report->size + 7) >> 3); + + hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1); + + if (hid->outhead == hid->outtail) + hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1); + + if (hid->urbout.status != -EINPROGRESS) + hid_submit_out(hid); +} + +int hid_open(struct hid_device *hid) +{ + if (hid->open++) + return 0; + + hid->urb.dev = hid->dev; + + if (usb_submit_urb(&hid->urb)) + return -EIO; + + return 0; +} + +void hid_close(struct hid_device *hid) +{ + if (!--hid->open) + usb_unlink_urb(&hid->urb); +} + +/* + * Initialize all readable reports + */ +void hid_init_reports(struct hid_device *hid) +{ + int i; + struct hid_report *report; + struct hid_report_enum *report_enum; + struct list_head *list; + + for (i = 0; i < HID_REPORT_TYPES; i++) { + if (i == HID_FEATURE_REPORT || i == HID_INPUT_REPORT) { + report_enum = hid->report_enum + i; + list = report_enum->report_list.next; + while (list != &report_enum->report_list) { + report = (struct hid_report *) list; + usb_set_idle(hid->dev, hid->ifnum, 0, report->id); + hid_read_report(hid, report); + list = list->next; + } + } + } +} + +#define USB_VENDOR_ID_WACOM 0x056a +#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010 +#define USB_DEVICE_ID_WACOM_INTUOS 0x0020 + +struct hid_blacklist { + __u16 idVendor; + __u16 idProduct; +} hid_blacklist[] = { + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1}, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2}, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3}, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4}, + { 0, 0 } +}; + +static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum) +{ + struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0; + struct hid_descriptor *hdesc; + struct hid_device *hid; + unsigned rsize = 0; + char *buf; + int n; + + for (n = 0; hid_blacklist[n].idVendor; n++) + if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) && + (hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL; + + if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc) && ((!interface->bNumEndpoints) || + usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc))) { + dbg("class descriptor not present\n"); + return NULL; + } + + for (n = 0; n < hdesc->bNumDescriptors; n++) + if (hdesc->desc[n].bDescriptorType == USB_DT_REPORT) + rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); + + if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { + dbg("weird size of report descriptor (%u)", rsize); + return NULL; + } + + { + __u8 rdesc[rsize]; + + if ((n = usb_get_class_descriptor(dev, interface->bInterfaceNumber, USB_DT_REPORT, 0, rdesc, rsize)) < 0) { + dbg("reading report descriptor failed"); + return NULL; + } + +#ifdef DEBUG_DATA + printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); + for (n = 0; n < rsize; n++) + printk(" %02x", (unsigned) rdesc[n]); + printk("\n"); +#endif + + if (!(hid = hid_parse_report(rdesc, rsize))) { + dbg("parsing report descriptor failed"); + return NULL; + } + } + + for (n = 0; n < interface->bNumEndpoints; n++) { + + struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n]; + int pipe, maxp; + + if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ + continue; + + if (!(endpoint->bEndpointAddress & 0x80)) /* Not an input endpoint */ + continue; + + pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + FILL_INT_URB(&hid->urb, dev, pipe, hid->buffer, maxp > 32 ? 32 : maxp, hid_irq, hid, endpoint->bInterval); + + break; + } + + if (n == interface->bNumEndpoints) { + dbg("couldn't find an input interrupt endpoint"); + hid_free_device(hid); + return NULL; + } + + hid->version = hdesc->bcdHID; + hid->country = hdesc->bCountryCode; + hid->dev = dev; + hid->ifnum = interface->bInterfaceNumber; + + for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) { + hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE; + hid->out[n].dr.request = USB_REQ_SET_REPORT; + hid->out[n].dr.index = cpu_to_le16(hid->ifnum); + } + + hid->name[0] = 0; + + if (!(buf = kmalloc(63, GFP_KERNEL))) + return NULL; + + if (usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) { + strcat(hid->name, buf); + if (usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) + sprintf(hid->name, "%s %s", hid->name, buf); + } else + sprintf(hid->name, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct); + + kfree(buf); + + FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0), + (void*) &hid->out[0].dr, hid->out[0].buffer, 1, hid_ctrl, hid); + +/* + * Some devices don't like this and crash. I don't know of any devices + * needing this, so it is disabled for now. + */ + +#if 0 + if (interface->bInterfaceSubClass == 1) + usb_set_protocol(dev, hid->ifnum, 1); +#endif + + return hid; +} + +static void* hid_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct hid_device *hid; + int i; + char *c; + + dbg("HID probe called for ifnum %d", ifnum); + + if (!(hid = usb_hid_configure(dev, ifnum))) + return NULL; + + hid_init_reports(hid); + hid_dump_device(hid); + + if (!hidinput_connect(hid)) + hid->claimed |= HID_CLAIMED_INPUT; +#ifdef CONFIG_USB_HIDDEV + if (!hiddev_connect(hid)) + hid->claimed |= HID_CLAIMED_HIDDEV; +#endif + printk(KERN_INFO); + + if (hid->claimed & HID_CLAIMED_INPUT) + printk("input%d", hid->input.number); + if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) + printk(","); + if (hid->claimed & HID_CLAIMED_HIDDEV) + printk("hiddev%d", hid->minor); + + c = "Device"; + for (i = 0; i < hid->maxapplication; i++) + if (IS_INPUT_APPLICATION(hid->application[i])) { + c = hid_types[hid->application[i] & 0xffff]; + break; + } + + printk(": USB HID v%x.%02x %s [%s] on usb%d:%d.%d\n", + hid->version >> 8, hid->version & 0xff, c, hid->name, + dev->bus->busnum, dev->devnum, ifnum); + + return hid; +} + +static void hid_disconnect(struct usb_device *dev, void *ptr) +{ + struct hid_device *hid = ptr; + + dbg("cleanup called"); + usb_unlink_urb(&hid->urb); + + if (hid->claimed & HID_CLAIMED_INPUT) + hidinput_disconnect(hid); +#ifdef CONFIG_USB_HIDDEV + if (hid->claimed & HID_CLAIMED_HIDDEV) + hiddev_disconnect(hid); +#endif + hid_free_device(hid); +} + +static struct usb_device_id hid_usb_ids [] = { + { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS, + bInterfaceClass: USB_INTERFACE_CLASS_HID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, hid_usb_ids); + +static struct usb_driver hid_driver = { + name: "hid", + probe: hid_probe, + disconnect: hid_disconnect, + id_table: hid_usb_ids, +}; + +static int __init hid_init(void) +{ +#ifdef CONFIG_USB_HIDDEV + hiddev_init(); +#endif + usb_register(&hid_driver); + info(DRIVER_VERSION " " DRIVER_AUTHOR); + info(DRIVER_DESC); + + return 0; +} + +static void __exit hid_exit(void) +{ +#ifdef CONFIG_USB_HIDDEV + hiddev_exit(); +#endif + usb_deregister(&hid_driver); +} + +module_init(hid_init); +module_exit(hid_exit); + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/hid-debug.h linux/drivers/usb/hid-debug.h --- v2.4.9/linux/drivers/usb/hid-debug.h Mon Jun 19 13:42:41 2000 +++ linux/drivers/usb/hid-debug.h Wed Sep 12 15:34:06 2001 @@ -1,8 +1,8 @@ /* - * $Id: hid-debug.h,v 1.2 2000/05/29 10:54:53 vojtech Exp $ + * $Id: hid-debug.h,v 1.3 2001/05/10 15:56:07 vojtech Exp $ * - * (c) 1999 Andreas Gal - * (c) 2000 Vojtech Pavlik + * (c) 1999 Andreas Gal + * (c) 2000-2001 Vojtech Pavlik * * Some debug stuff for the HID parser. * @@ -196,16 +196,18 @@ printk(")\n"); } -void hid_dump_device(struct hid_device *device) { +static void hid_dump_device(struct hid_device *device) { struct hid_report_enum *report_enum; struct hid_report *report; struct list_head *list; unsigned i,k; static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; - printk("Application("); - resolv_usage(device->application); - printk(")\n"); + for (i = 0; i < device->maxapplication; i++) { + printk("Application("); + resolv_usage(device->application[i]); + printk(")\n"); + } for (i = 0; i < HID_REPORT_TYPES; i++) { report_enum = device->report_enum + i; @@ -228,8 +230,8 @@ } } -void hid_dump_input(struct hid_usage *usage, __s32 value) { - printk("hidd: input "); +static void hid_dump_input(struct hid_usage *usage, __s32 value) { + printk("hid-debug: input "); resolv_usage(usage->hid); printk(" = %d\n", value); } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/hid-input.c linux/drivers/usb/hid-input.c --- v2.4.9/linux/drivers/usb/hid-input.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/hid-input.c Wed Sep 12 15:34:06 2001 @@ -0,0 +1,424 @@ +/* + * $Id: hid-input.c,v 1.5 2001/05/23 09:25:02 vojtech Exp $ + * + * Copyright (c) 2000-2001 Vojtech Pavlik + * + * USB HID to Linux Input mapping module + * + * Sponsored by SuSE + */ + +/* + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + */ + +#include +#include +#include +#include +#include +#include + +#include "hid.h" + +#define unk KEY_UNKNOWN + +static unsigned char hid_keyboard[256] = { + 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, + 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, + 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, + 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, + 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95, + 120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113, + 115,114,unk,unk,unk,124,unk,181,182,183,184,185,186,187,188,189, + 190,191,192,193,194,195,196,197,198,unk,unk,unk,unk,unk,unk,unk, + unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, + unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, + unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, + unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, + 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, + 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk +}; + +static struct { + __s32 x; + __s32 y; +} hid_hat_to_axis[] = {{0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; + +static void hidinput_configure_usage(struct hid_device *device, struct hid_field *field, struct hid_usage *usage) +{ + struct input_dev *input = &device->input; + int max; + unsigned long *bit; + + switch (usage->hid & HID_USAGE_PAGE) { + + case HID_UP_KEYBOARD: + + set_bit(EV_REP, input->evbit); + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + + if ((usage->hid & HID_USAGE) < 256) { + if (!(usage->code = hid_keyboard[usage->hid & HID_USAGE])) + return; + clear_bit(usage->code, bit); + } else + usage->code = KEY_UNKNOWN; + + break; + + case HID_UP_BUTTON: + + usage->code = ((usage->hid - 1) & 0xf) + 0x100; + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + + switch (field->application) { + case HID_GD_GAMEPAD: usage->code += 0x10; + case HID_GD_JOYSTICK: usage->code += 0x10; + case HID_GD_MOUSE: usage->code += 0x10; break; + default: + if (field->physical == HID_GD_POINTER) + usage->code += 0x10; + break; + } + break; + + case HID_UP_GENDESK: + + if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */ + switch (usage->hid & 0xf) { + case 0x1: usage->code = KEY_POWER; break; + case 0x2: usage->code = KEY_SLEEP; break; + case 0x3: usage->code = KEY_WAKEUP; break; + default: usage->code = KEY_UNKNOWN; break; + } + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + break; + } + + usage->code = usage->hid & 0xf; + + if (field->report_size == 1) { + usage->code = BTN_MISC; + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + break; + } + + if (field->flags & HID_MAIN_ITEM_RELATIVE) { + usage->type = EV_REL; bit = input->relbit; max = REL_MAX; + break; + } + + usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; + + if (usage->hid == HID_GD_HATSWITCH) { + usage->code = ABS_HAT0X; + usage->hat = 1 + (field->logical_maximum == 4); + } + break; + + case HID_UP_LED: + + usage->code = (usage->hid - 1) & 0xf; + usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; + break; + + case HID_UP_DIGITIZER: + + switch (usage->hid & 0xff) { + + case 0x30: /* TipPressure */ + + if (!test_bit(BTN_TOUCH, input->keybit)) { + device->quirks |= HID_QUIRK_NOTOUCH; + set_bit(EV_KEY, input->evbit); + set_bit(BTN_TOUCH, input->keybit); + } + usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; + usage->code = ABS_PRESSURE; + clear_bit(usage->code, bit); + break; + + case 0x32: /* InRange */ + + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + switch (field->physical & 0xff) { + case 0x21: usage->code = BTN_TOOL_MOUSE; break; + case 0x22: usage->code = BTN_TOOL_FINGER; break; + default: usage->code = BTN_TOOL_PEN; break; + } + break; + + case 0x3c: /* Invert */ + + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + usage->code = BTN_TOOL_RUBBER; + clear_bit(usage->code, bit); + break; + + case 0x33: /* Touch */ + case 0x42: /* TipSwitch */ + case 0x43: /* TipSwitch2 */ + + device->quirks &= ~HID_QUIRK_NOTOUCH; + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + usage->code = BTN_TOUCH; + clear_bit(usage->code, bit); + break; + + case 0x44: /* BarrelSwitch */ + + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + usage->code = BTN_STYLUS; + clear_bit(usage->code, bit); + break; + + default: goto unknown; + } + break; + + case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ + + switch (usage->hid & HID_USAGE) { + case 0x000: usage->code = 0; break; + case 0x034: usage->code = KEY_SLEEP; break; + case 0x036: usage->code = BTN_MISC; break; + case 0x08a: usage->code = KEY_WWW; break; + case 0x095: usage->code = KEY_HELP; break; + + case 0x0b4: usage->code = KEY_REWIND; break; + case 0x0b5: usage->code = KEY_NEXTSONG; break; + case 0x0b6: usage->code = KEY_PREVIOUSSONG; break; + case 0x0b7: usage->code = KEY_STOPCD; break; + case 0x0b8: usage->code = KEY_EJECTCD; break; + case 0x0cd: usage->code = KEY_PLAYPAUSE; break; + + case 0x0e2: usage->code = KEY_MUTE; break; + case 0x0e9: usage->code = KEY_VOLUMEUP; break; + case 0x0ea: usage->code = KEY_VOLUMEDOWN; break; + + case 0x183: usage->code = KEY_CONFIG; break; + case 0x18a: usage->code = KEY_MAIL; break; + case 0x192: usage->code = KEY_CALC; break; + case 0x194: usage->code = KEY_FILE; break; + + case 0x21a: usage->code = KEY_UNDO; break; + case 0x21b: usage->code = KEY_COPY; break; + case 0x21c: usage->code = KEY_CUT; break; + case 0x21d: usage->code = KEY_PASTE; break; + + case 0x221: usage->code = KEY_FIND; break; + case 0x223: usage->code = KEY_HOMEPAGE; break; + case 0x224: usage->code = KEY_BACK; break; + case 0x225: usage->code = KEY_FORWARD; break; + case 0x226: usage->code = KEY_STOP; break; + case 0x227: usage->code = KEY_REFRESH; break; + case 0x22a: usage->code = KEY_BOOKMARKS; break; + + default: usage->code = KEY_UNKNOWN; break; + + } + + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + break; + + default: + unknown: + + if (field->report_size == 1) { + + if (field->report->type == HID_OUTPUT_REPORT) { + usage->code = LED_MISC; + usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; + break; + } + + usage->code = BTN_MISC; + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + break; + } + + if (field->flags & HID_MAIN_ITEM_RELATIVE) { + usage->code = REL_MISC; + usage->type = EV_REL; bit = input->relbit; max = REL_MAX; + break; + } + + usage->code = ABS_MISC; + usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; + break; + } + + set_bit(usage->type, input->evbit); + + while (usage->code <= max && test_and_set_bit(usage->code, bit)) { + usage->code = find_next_zero_bit(bit, max + 1, usage->code); + } + + if (usage->code > max) return; + + if (usage->type == EV_ABS) { + int a = field->logical_minimum; + int b = field->logical_maximum; + + input->absmin[usage->code] = a; + input->absmax[usage->code] = b; + input->absfuzz[usage->code] = (b - a) >> 8; + input->absflat[usage->code] = (b - a) >> 4; + } + + if (usage->hat) { + int i; + for (i = usage->code; i < usage->code + 2 && i <= max; i++) { + input->absmax[i] = 1; + input->absmin[i] = -1; + input->absfuzz[i] = 0; + input->absflat[i] = 0; + } + set_bit(usage->code + 1, input->absbit); + } +} + +void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) +{ + struct input_dev *input = &hid->input; + int *quirks = &hid->quirks; + + if (usage->hat) { + if (usage->hat == 2) value = value * 2; + if (value > 8) value = 8; + input_event(input, usage->type, usage->code , hid_hat_to_axis[value].x); + input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y); + return; + } + + if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ + *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); + return; + } + + if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */ + if (value) { + input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1); + return; + } + input_event(input, usage->type, usage->code, 0); + input_event(input, usage->type, BTN_TOOL_RUBBER, 0); + return; + } + + if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */ + int a = field->logical_minimum; + int b = field->logical_maximum; + input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3)); + } + + if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */ + return; + + input_event(input, usage->type, usage->code, value); + + if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) + input_event(input, usage->type, usage->code, 0); +} + +static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + struct hid_device *hid = dev->private; + struct hid_field *field = NULL; + int offset; + + if ((offset = hid_find_field(hid, type, code, &field)) == -1) { + warn("event field not found"); + return -1; + } + + hid_set_field(field, offset, value); + hid_write_report(hid, field->report); + + return 0; +} + +static int hidinput_open(struct input_dev *dev) +{ + struct hid_device *hid = dev->private; + return hid_open(hid); +} + +static void hidinput_close(struct input_dev *dev) +{ + struct hid_device *hid = dev->private; + hid_close(hid); +} + +/* + * Register the input device; print a message. + * Configure the input layer interface + * Read all reports and initalize the absoulte field values. + */ + +int hidinput_connect(struct hid_device *hid) +{ + struct usb_device *dev = hid->dev; + struct hid_report_enum *report_enum; + struct hid_report *report; + struct list_head *list; + int i, j, k; + + for (i = 0; i < hid->maxapplication; i++) + if (IS_INPUT_APPLICATION(hid->application[i])) + break; + + if (i == hid->maxapplication) + return -1; + + hid->input.private = hid; + hid->input.event = hidinput_input_event; + hid->input.open = hidinput_open; + hid->input.close = hidinput_close; + + hid->input.name = hid->name; + hid->input.idbus = BUS_USB; + hid->input.idvendor = dev->descriptor.idVendor; + hid->input.idproduct = dev->descriptor.idProduct; + hid->input.idversion = dev->descriptor.bcdDevice; + + for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { + report_enum = hid->report_enum + k; + list = report_enum->report_list.next; + while (list != &report_enum->report_list) { + report = (struct hid_report *) list; + for (i = 0; i < report->maxfield; i++) + for (j = 0; j < report->field[i]->maxusage; j++) + hidinput_configure_usage(hid, report->field[i], report->field[i]->usage + j); + list = list->next; + } + } + + input_register_device(&hid->input); + + return 0; +} + +void hidinput_disconnect(struct hid_device *hid) +{ + input_unregister_device(&hid->input); +} diff -u --recursive --new-file v2.4.9/linux/drivers/usb/hid.c linux/drivers/usb/hid.c --- v2.4.9/linux/drivers/usb/hid.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/hid.c Wed Dec 31 16:00:00 1969 @@ -1,1576 +0,0 @@ -/* - * $Id: hid.c,v 1.16 2000/09/18 21:38:55 vojtech Exp $ - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000 Vojtech Pavlik - * - * USB HID support for the Linux input drivers - * - * Sponsored by SuSE - */ - -/* - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#undef DEBUG -#undef DEBUG_DATA -#include - -#include - -#include "hid.h" - -#ifdef DEBUG -#include "hid-debug.h" -#else -#define hid_dump_input(a,b) do { } while (0) -#define hid_dump_device(c) do { } while (0) -#endif - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.16" -#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik " -#define DRIVER_DESC "USB HID support drivers" - -#define unk KEY_UNKNOWN - -static unsigned char hid_keyboard[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95, - 120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114,unk,unk,unk,124,unk,181,182,183,184,185,186,187,188,189, - 190,191,192,193,194,195,196,197,198,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk -}; - -static struct { - __s32 x; - __s32 y; -} hid_hat_to_axis[] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}, { 0, 0}}; - -static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", - "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; - -/* - * Register a new report for a device. - */ - -static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) -{ - struct hid_report_enum *report_enum = device->report_enum + type; - struct hid_report *report; - - if (report_enum->report_id_hash[id]) - return report_enum->report_id_hash[id]; - - if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL))) - return NULL; - memset(report, 0, sizeof(struct hid_report)); - - if (id != 0) report_enum->numbered = 1; - - report->id = id; - report->type = type; - report->size = 0; - report->device = device; - report_enum->report_id_hash[id] = report; - - list_add_tail(&report->list, &report_enum->report_list); - - return report; -} - -/* - * Register a new field for this report. - */ - -static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) -{ - if (report->maxfield < HID_MAX_FIELDS) { - struct hid_field *field; - - if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) - + values * sizeof(unsigned), GFP_KERNEL))) - return NULL; - memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage) - + values * sizeof(unsigned)); - - report->field[report->maxfield++] = field; - field->usage = (struct hid_usage *)(field + 1); - field->value = (unsigned *)(field->usage + usages); - field->report = report; - - return field; - } - - dbg("too many fields in report"); - return NULL; -} - -/* - * Open a collection. The type/usage is pushed on the stack. - */ - -static int open_collection(struct hid_parser *parser, unsigned type) -{ - unsigned usage; - - usage = parser->local.usage[0]; - - if (type == HID_COLLECTION_APPLICATION && !parser->device->application) - parser->device->application = usage; - - if (parser->collection_stack_ptr < HID_COLLECTION_STACK_SIZE) { /* PUSH on stack */ - struct hid_collection *collection = parser->collection_stack + parser->collection_stack_ptr++; - collection->type = type; - collection->usage = usage; - return 0; - } - - dbg("collection stack overflow"); - return -1; -} - -/* - * Close a collection. - */ - -static int close_collection(struct hid_parser *parser) -{ - if (parser->collection_stack_ptr > 0) { /* POP from stack */ - parser->collection_stack_ptr--; - return 0; - } - dbg("collection stack underflow"); - return -1; -} - -/* - * Climb up the stack, search for the specified collection type - * and return the usage. - */ - -static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) -{ - int n; - for (n = parser->collection_stack_ptr - 1; n >= 0; n--) - if (parser->collection_stack[n].type == type) - return parser->collection_stack[n].usage; - return 0; /* we know nothing about this usage type */ -} - -/* - * Add a usage to the temporary parser table. - */ - -static int hid_add_usage(struct hid_parser *parser, unsigned usage) -{ - if (parser->local.usage_index >= HID_MAX_USAGES) { - dbg("usage index exceeded"); - return -1; - } - parser->local.usage[parser->local.usage_index++] = usage; - return 0; -} - -/* - * Register a new field for this report. - */ - -static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags) -{ - struct hid_report *report; - struct hid_field *field; - int usages; - unsigned offset; - int i; - - if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) { - dbg("hid_register_report failed"); - return -1; - } - - if (HID_MAIN_ITEM_VARIABLE & ~flags) { /* ARRAY */ - if (parser->global.logical_maximum <= parser->global.logical_minimum) { - dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); - return -1; - } - usages = parser->local.usage_index; - /* Hint: we can assume usages < MAX_USAGE here */ - } else { /* VARIABLE */ - usages = parser->global.report_count; - } - offset = report->size; - report->size += parser->global.report_size * - parser->global.report_count; - if (usages == 0) - return 0; /* ignore padding fields */ - if ((field = hid_register_field(report, usages, - parser->global.report_count)) == NULL) - return 0; - field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); - field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); - for (i = 0; i < usages; i++) field->usage[i].hid = parser->local.usage[i]; - field->maxusage = usages; - field->flags = flags; - field->report_offset = offset; - field->report_type = report_type; - field->report_size = parser->global.report_size; - field->report_count = parser->global.report_count; - field->logical_minimum = parser->global.logical_minimum; - field->logical_maximum = parser->global.logical_maximum; - field->physical_minimum = parser->global.physical_minimum; - field->physical_maximum = parser->global.physical_maximum; - field->unit_exponent = parser->global.unit_exponent; - field->unit = parser->global.unit; - return 0; -} - -/* - * Read data value from item. - */ - -static __inline__ __u32 item_udata(struct hid_item *item) -{ - switch (item->size) { - case 1: return item->data.u8; - case 2: return item->data.u16; - case 4: return item->data.u32; - } - return 0; -} - -static __inline__ __s32 item_sdata(struct hid_item *item) -{ - switch (item->size) { - case 1: return item->data.s8; - case 2: return item->data.s16; - case 4: return item->data.s32; - } - return 0; -} - -/* - * Process a global item. - */ - -static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) -{ - switch (item->tag) { - - case HID_GLOBAL_ITEM_TAG_PUSH: - - if (parser->global_stack_ptr < HID_GLOBAL_STACK_SIZE) { - memcpy(parser->global_stack + parser->global_stack_ptr++, - &parser->global, sizeof(struct hid_global)); - return 0; - } - dbg("global enviroment stack overflow"); - return -1; - - case HID_GLOBAL_ITEM_TAG_POP: - - if (parser->global_stack_ptr > 0) { - memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr, - sizeof(struct hid_global)); - return 0; - } - dbg("global enviroment stack underflow"); - return -1; - - case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: - parser->global.usage_page = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: - parser->global.logical_minimum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: - parser->global.logical_maximum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: - parser->global.physical_minimum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: - parser->global.physical_maximum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: - parser->global.unit_exponent = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_UNIT: - parser->global.unit = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: - if ((parser->global.report_size = item_udata(item)) > 32) { - dbg("invalid report_size %d", parser->global.report_size); - return -1; - } - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: - if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) { - dbg("invalid report_count %d", parser->global.report_count); - return -1; - } - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_ID: - if ((parser->global.report_id = item_udata(item)) == 0) { - dbg("report_id 0 is invalid"); - return -1; - } - return 0; - - default: - dbg("unknown global tag 0x%x", item->tag); - return -1; - } -} - -/* - * Process a local item. - */ - -static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) -{ - __u32 data; - - if (item->size == 0) { - dbg("item data expected for local item"); - return -1; - } - - data = item_udata(item); - - switch (item->tag) { - - case HID_LOCAL_ITEM_TAG_DELIMITER: - - if (data) { - /* - * We treat items before the first delimiter - * as global to all usage sets (branch 0). - * In the moment we process only these global - * items and the first delimiter set. - */ - if (parser->local.delimiter_depth != 0) { - dbg("nested delimiters"); - return -1; - } - parser->local.delimiter_depth++; - parser->local.delimiter_branch++; - } else { - if (parser->local.delimiter_depth < 1) { - dbg("bogus close delimiter"); - return -1; - } - parser->local.delimiter_depth--; - } - return 1; - - case HID_LOCAL_ITEM_TAG_USAGE: - - if (parser->local.delimiter_branch < 2) { - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - return hid_add_usage(parser, data); - } - dbg("alternative usage ignored"); - return 0; - - case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: - - if (parser->local.delimiter_branch < 2) { - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - parser->local.usage_minimum = data; - return 0; - } - dbg("alternative usage ignored"); - return 0; - - case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: - - if (parser->local.delimiter_branch < 2) { - unsigned n; - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - for (n = parser->local.usage_minimum; n <= data; n++) - if (hid_add_usage(parser, n)) { - dbg("hid_add_usage failed\n"); - return -1; - } - return 0; - } - dbg("alternative usage ignored"); - return 0; - - default: - - dbg("unknown local item tag 0x%x", item->tag); - return 0; - } -} - -/* - * Process a main item. - */ - -static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) -{ - __u32 data; - int ret; - - data = item_udata(item); - - switch (item->tag) { - case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: - ret = open_collection(parser, data & 3); - break; - case HID_MAIN_ITEM_TAG_END_COLLECTION: - ret = close_collection(parser); - break; - case HID_MAIN_ITEM_TAG_INPUT: - ret = hid_add_field(parser, HID_INPUT_REPORT, data); - break; - case HID_MAIN_ITEM_TAG_OUTPUT: - ret = hid_add_field(parser, HID_OUTPUT_REPORT, data); - break; - case HID_MAIN_ITEM_TAG_FEATURE: - ret = hid_add_field(parser, HID_FEATURE_REPORT, data); - break; - default: - dbg("unknown main item tag 0x%x", item->tag); - ret = 0; - } - - memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */ - - return ret; -} - -/* - * Process a reserved item. - */ - -static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item) -{ - dbg("reserved item type, tag 0x%x", item->tag); - return 0; -} - -/* - * Free a report and all registered fields. The field->usage and - * field->value table's are allocated behind the field, so we need - * only to free(field) itself. - */ - -static void hid_free_report(struct hid_report *report) -{ - unsigned n; - - for (n = 0; n < report->maxfield; n++) - kfree(report->field[n]); - kfree(report); -} - -/* - * Free a device structure, all reports, and all fields. - */ - -static void hid_free_device(struct hid_device *device) -{ - unsigned i,j; - - for (i = 0; i < HID_REPORT_TYPES; i++) { - struct hid_report_enum *report_enum = device->report_enum + i; - - for (j = 0; j < 256; j++) { - struct hid_report *report = report_enum->report_id_hash[j]; - if (report) hid_free_report(report); - } - } - - if (device->rdesc) kfree(device->rdesc); -} - -/* - * Fetch a report description item from the data stream. We support long - * items, though they are not used yet. - */ - -static __u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) -{ - if ((end - start) > 0) { - - __u8 b = *start++; - item->type = (b >> 2) & 3; - item->tag = (b >> 4) & 15; - - if (item->tag == HID_ITEM_TAG_LONG) { - - item->format = HID_ITEM_FORMAT_LONG; - - if ((end - start) >= 2) { - - item->size = *start++; - item->tag = *start++; - - if ((end - start) >= item->size) { - item->data.longdata = start; - start += item->size; - return start; - } - } - } else { - - item->format = HID_ITEM_FORMAT_SHORT; - item->size = b & 3; - switch (item->size) { - - case 0: - return start; - - case 1: - if ((end - start) >= 1) { - item->data.u8 = *start++; - return start; - } - break; - - case 2: - if ((end - start) >= 2) { - item->data.u16 = le16_to_cpu( get_unaligned(((__u16*)start)++)); - return start; - } - - case 3: - item->size++; - if ((end - start) >= 4) { - item->data.u32 = le32_to_cpu( get_unaligned(((__u32*)start)++)); - return start; - } - } - } - } - return NULL; -} - -/* - * Parse a report description into a hid_device structure. Reports are - * enumerated, fields are attached to these reports. - */ - -static struct hid_device *hid_parse_report(__u8 *start, unsigned size) -{ - struct hid_device *device; - struct hid_parser *parser; - struct hid_item item; - __u8 *end; - unsigned i; - static int (*dispatch_type[])(struct hid_parser *parser, - struct hid_item *item) = { - hid_parser_main, - hid_parser_global, - hid_parser_local, - hid_parser_reserved - }; - - if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL))) - return NULL; - memset(device, 0, sizeof(struct hid_device)); - - for (i = 0; i < HID_REPORT_TYPES; i++) - INIT_LIST_HEAD(&device->report_enum[i].report_list); - - if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) { - kfree(device); - return NULL; - } - memcpy(device->rdesc, start, size); - - if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) { - kfree(device->rdesc); - kfree(device); - return NULL; - } - memset(parser, 0, sizeof(struct hid_parser)); - parser->device = device; - - end = start + size; - while ((start = fetch_item(start, end, &item)) != 0) { - if (item.format != HID_ITEM_FORMAT_SHORT) { - dbg("unexpected long global item"); - hid_free_device(device); - kfree(parser); - return NULL; - } - if (dispatch_type[item.type](parser, &item)) { - dbg("item %u %u %u %u parsing failed\n", - item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); - hid_free_device(device); - kfree(parser); - return NULL; - } - - if (start == end) { - if (parser->collection_stack_ptr) { - dbg("unbalanced collection at end of report description"); - hid_free_device(device); - kfree(parser); - return NULL; - } - if (parser->local.delimiter_depth) { - dbg("unbalanced delimiter at end of report description"); - hid_free_device(device); - kfree(parser); - return NULL; - } - kfree(parser); - return device; - } - } - - dbg("item fetching failed at offset %d\n", (int)(end - start)); - hid_free_device(device); - kfree(parser); - return NULL; -} - -/* - * Convert a signed n-bit integer to signed 32-bit integer. Common - * cases are done through the compiler, the screwed things has to be - * done by hand. - */ - -static __inline__ __s32 snto32(__u32 value, unsigned n) -{ - switch (n) { - case 8: return ((__s8)value); - case 16: return ((__s16)value); - case 32: return ((__s32)value); - } - return value & (1 << (n - 1)) ? value | (-1 << n) : value; -} - -/* - * Convert a signed 32-bit integer to a signed n-bit integer. - */ - -static __inline__ __u32 s32ton(__s32 value, unsigned n) -{ - __s32 a = value >> (n - 1); - if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; - return value & ((1 << n) - 1); -} - -/* - * Extract/implement a data field from/to a report. We use 64-bit unsigned, - * 32-bit aligned, so that we can possibly have alignment problems on some - * odd architectures. - */ - -static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) -{ - report += (offset >> 5) << 2; offset &= 31; - return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1); -} - -static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) -{ - report += (offset >> 5) << 2; offset &= 31; - *(__u64*)report &= cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)); - *(__u64*)report |= cpu_to_le64((__u64)value << offset); -} - -static void hid_configure_usage(struct hid_device *device, struct hid_field *field, struct hid_usage *usage) -{ - struct input_dev *input = &device->input; - int max; - unsigned long *bit; - - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_KEYBOARD: - - set_bit(EV_REP, input->evbit); - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - - if ((usage->hid & HID_USAGE) < 256) { - if (!(usage->code = hid_keyboard[usage->hid & HID_USAGE])) - return; - clear_bit(usage->code, bit); - } else - usage->code = KEY_UNKNOWN; - - break; - - case HID_UP_BUTTON: - - usage->code = ((usage->hid - 1) & 0xf) + 0x100; - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - - switch (device->application) { - case HID_GD_GAMEPAD: usage->code += 0x10; - case HID_GD_JOYSTICK: usage->code += 0x10; - case HID_GD_MOUSE: usage->code += 0x10; break; - default: - if (field->physical == HID_GD_POINTER) - usage->code += 0x10; - break; - } - break; - - case HID_UP_GENDESK: - - if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */ - switch (usage->hid & 0xf) { - case 0x1: usage->code = KEY_POWER; break; - case 0x2: usage->code = KEY_SLEEP; break; - case 0x3: usage->code = KEY_WAKEUP; break; - default: usage->code = KEY_UNKNOWN; break; - } - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - break; - } - - usage->code = usage->hid & 0xf; - - if (field->report_size == 1) { - usage->code = BTN_MISC; - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - break; - } - - if (field->flags & HID_MAIN_ITEM_RELATIVE) { - usage->type = EV_REL; bit = input->relbit; max = REL_MAX; - break; - } - - usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; - - if (usage->hid == HID_GD_HATSWITCH) { - usage->code = ABS_HAT0X; - usage->hat = 1 + (field->logical_maximum == 4); - } - break; - - case HID_UP_LED: - - usage->code = (usage->hid - 1) & 0xf; - usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; - break; - - case HID_UP_DIGITIZER: - - switch (usage->hid & 0xff) { - - case 0x30: /* TipPressure */ - - if (!test_bit(BTN_TOUCH, input->keybit)) { - device->quirks |= HID_QUIRK_NOTOUCH; - set_bit(EV_KEY, input->evbit); - set_bit(BTN_TOUCH, input->keybit); - } - usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; - usage->code = ABS_PRESSURE; - clear_bit(usage->code, bit); - break; - - case 0x32: /* InRange */ - - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - switch (field->physical & 0xff) { - case 0x21: usage->code = BTN_TOOL_MOUSE; break; - case 0x22: usage->code = BTN_TOOL_FINGER; break; - default: usage->code = BTN_TOOL_PEN; break; - } - break; - - case 0x3c: /* Invert */ - - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - usage->code = BTN_TOOL_RUBBER; - clear_bit(usage->code, bit); - break; - - case 0x33: /* Touch */ - case 0x42: /* TipSwitch */ - case 0x43: /* TipSwitch2 */ - - device->quirks &= ~HID_QUIRK_NOTOUCH; - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - usage->code = BTN_TOUCH; - clear_bit(usage->code, bit); - break; - - case 0x44: /* BarrelSwitch */ - - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - usage->code = BTN_STYLUS; - clear_bit(usage->code, bit); - break; - - default: goto unknown; - } - break; - - case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ - - switch (usage->hid & HID_USAGE) { - case 0x000: usage->code = 0; break; - case 0x034: usage->code = KEY_SLEEP; break; - case 0x036: usage->code = BTN_MISC; break; - case 0x08a: usage->code = KEY_WWW; break; - case 0x095: usage->code = KEY_HELP; break; - - case 0x0b4: usage->code = KEY_REWIND; break; - case 0x0b5: usage->code = KEY_NEXTSONG; break; - case 0x0b6: usage->code = KEY_PREVIOUSSONG; break; - case 0x0b7: usage->code = KEY_STOPCD; break; - case 0x0b8: usage->code = KEY_EJECTCD; break; - case 0x0cd: usage->code = KEY_PLAYPAUSE; break; - - case 0x0e2: usage->code = KEY_MUTE; break; - case 0x0e9: usage->code = KEY_VOLUMEUP; break; - case 0x0ea: usage->code = KEY_VOLUMEDOWN; break; - - case 0x183: usage->code = KEY_CONFIG; break; - case 0x18a: usage->code = KEY_MAIL; break; - case 0x192: usage->code = KEY_CALC; break; - case 0x194: usage->code = KEY_FILE; break; - - case 0x21a: usage->code = KEY_UNDO; break; - case 0x21b: usage->code = KEY_COPY; break; - case 0x21c: usage->code = KEY_CUT; break; - case 0x21d: usage->code = KEY_PASTE; break; - - case 0x221: usage->code = KEY_FIND; break; - case 0x223: usage->code = KEY_HOMEPAGE; break; - case 0x224: usage->code = KEY_BACK; break; - case 0x225: usage->code = KEY_FORWARD; break; - case 0x226: usage->code = KEY_STOP; break; - case 0x227: usage->code = KEY_REFRESH; break; - case 0x22a: usage->code = KEY_BOOKMARKS; break; - - default: usage->code = KEY_UNKNOWN; break; - - } - - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - break; - - default: - unknown: - - if (field->report_size == 1) { - usage->code = BTN_MISC; - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - break; - } - - if (field->flags & HID_MAIN_ITEM_RELATIVE) { - usage->code = REL_MISC; - usage->type = EV_REL; bit = input->relbit; max = REL_MAX; - break; - } - - usage->code = ABS_MISC; - usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; - break; - } - - set_bit(usage->type, input->evbit); - - while (usage->code <= max && test_and_set_bit(usage->code, bit)) { - usage->code = find_next_zero_bit(bit, max + 1, usage->code); - } - - if (usage->code > max) return; - - if (usage->type == EV_ABS) { - int a = field->logical_minimum; - int b = field->logical_maximum; - - input->absmin[usage->code] = a; - input->absmax[usage->code] = b; - input->absfuzz[usage->code] = (b - a) >> 8; - input->absflat[usage->code] = (b - a) >> 4; - } - - if (usage->hat) { - int i; - for (i = usage->code; i < usage->code + 2 && i <= max; i++) { - input->absmax[i] = 1; - input->absmin[i] = -1; - input->absfuzz[i] = 0; - input->absflat[i] = 0; - } - set_bit(usage->code + 1, input->absbit); - } -} - -static void hid_process_event(struct input_dev *input, int *quirks, struct hid_field *field, struct hid_usage *usage, __s32 value) -{ - hid_dump_input(usage, value); - - if (usage->hat) { - if (usage->hat == 2) value = value * 2; - if (value > 8) value = 8; - input_event(input, usage->type, usage->code , hid_hat_to_axis[value].x); - input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ - *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */ - if (value) { - input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1); - return; - } - input_event(input, usage->type, usage->code, 0); - input_event(input, usage->type, BTN_TOOL_RUBBER, 0); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */ - int a = field->logical_minimum; - int b = field->logical_maximum; - input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3)); - } - - if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */ - return; - - input_event(input, usage->type, usage->code, value); - - if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) - input_event(input, usage->type, usage->code, 0); -} - -/* - * Search an array for a value. - */ - -static __inline__ int search(__s32 *array, __s32 value, unsigned n) -{ - while (n--) if (*array++ == value) return 0; - return -1; -} - -/* - * Analyse a received field, and fetch the data from it. The field - * content is stored for next report processing (we do differential - * reporting to the layer). - */ - -static void hid_input_field(struct hid_device *dev, struct hid_field *field, __u8 *data) -{ - unsigned n; - unsigned count = field->report_count; - unsigned offset = field->report_offset; - unsigned size = field->report_size; - __s32 min = field->logical_minimum; - __s32 max = field->logical_maximum; - __s32 value[count]; /* WARNING: gcc specific */ - - for (n = 0; n < count; n++) { - value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) : - extract(data, offset + n * size, size); - /* Handle the ErrorRollOver code (1) by simply ignoring this report */ - if (!(field->flags & HID_MAIN_ITEM_VARIABLE) - && value[n] >= min && value[n] <= max - && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) - return; - } - - for (n = 0; n < count; n++) { - - if (HID_MAIN_ITEM_VARIABLE & field->flags) { - - if (field->flags & HID_MAIN_ITEM_RELATIVE) { - if (!value[n]) continue; - } else { - if (value[n] == field->value[n]) continue; - } - hid_process_event(&dev->input, &dev->quirks, field, &field->usage[n], value[n]); - - } else { - - if (field->value[n] >= min && field->value[n] <= max /* non-NULL value */ - && field->usage[field->value[n] - min].hid /* nonzero usage */ - && search(value, field->value[n], count)) - hid_process_event(&dev->input, &dev->quirks, field, - &field->usage[field->value[n] - min], 0); - - if (value[n] >= min && value[n] <= max /* non-NULL value */ - && field->usage[value[n] - min].hid /* nonzero usage */ - && search(field->value, value[n], count)) - hid_process_event(&dev->input, &dev->quirks, - field, &field->usage[value[n] - min], 1); - } - } - - memcpy(field->value, value, count * sizeof(__s32)); -} - -/* - * Interrupt input handler - analyse a received report. - */ - -static void hid_irq(struct urb *urb) -{ - struct hid_device *device = urb->context; - struct hid_report_enum *report_enum = device->report_enum + HID_INPUT_REPORT; - struct hid_report *report; - __u8 *data = urb->transfer_buffer; - int len = urb->actual_length; - int n; - - if (urb->status) { - dbg("nonzero status in irq %d", urb->status); - return; - } - - if (!len) { - dbg("empty report"); - return; - } - -#ifdef DEBUG_DATA - printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered) = ", len, report_enum->numbered ? "" : "un"); - for (n = 0; n < len; n++) - printk(" %02x", data[n]); - printk("\n"); -#endif - - n = 0; /* Normally report number is 0 */ - - if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ - n = *data++; - len--; - } - - if (!(report = report_enum->report_id_hash[n])) { - dbg("undefined report_id %d received", n); -#ifdef DEBUG - printk(KERN_DEBUG __FILE__ ": report (size %u) = ", len); - for (n = 0; n < len; n++) - printk(" %02x", data[n]); - printk("\n"); -#endif - - return; - } - - if (len < ((report->size - 1) >> 3) + 1) { - dbg("report %d is too short, (%d < %d)", report->id, len, ((report->size - 1) >> 3) + 1); - return; - } - - for (n = 0; n < report->maxfield; n++) - hid_input_field(device, report->field[n], data); - - return; -} - -/* - * hid_read_report() s intended to read the hid devices values even - * before the input device is registered, so that the userland interface - * modules start with real values. This is especially important for joydev.c - * automagic calibration. Doesn't work yet, though. Don't know why, the control - * request just times out on most devices I have and returns nonsense on others. - */ - -static void hid_read_report(struct hid_device *hid, struct hid_report *report) -{ -#if 0 - int rlen = ((report->size - 1) >> 3) + 1; - char rdata[rlen]; - struct urb urb; - int read, j; - - memset(&urb, 0, sizeof(struct urb)); - memset(rdata, 0, rlen); - - urb.transfer_buffer = rdata; - urb.actual_length = rlen; - urb.context = hid; - - dbg("getting report type %d id %d len %d", report->type + 1, report->id, rlen); - - if ((read = usb_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, rdata, rlen)) != rlen) { - dbg("reading report failed rlen %d read %d", rlen, read); -#ifdef DEBUG - printk(KERN_DEBUG __FILE__ ": report = "); - for (j = 0; j < rlen; j++) printk(" %02x", rdata[j]); - printk("\n"); -#endif - return; - } - - hid_irq(&urb); -#endif -} - -/* - * Output the field into the report. - */ - -static void hid_output_field(struct hid_field *field, __u8 *data) -{ - unsigned count = field->report_count; - unsigned offset = field->report_offset; - unsigned size = field->report_size; - unsigned n; - - for (n = 0; n < count; n++) { - if (field->logical_minimum < 0) /* signed values */ - implement(data, offset + n * size, size, s32ton(field->value[n], size)); - else /* unsigned values */ - implement(data, offset + n * size, size, field->value[n]); - } -} - -/* - * Create a report. - */ - -void hid_output_report(struct hid_report *report, __u8 *data) -{ - unsigned n; - for (n = 0; n < report->maxfield; n++) - hid_output_field(report->field[n], data); -}; - -/* - * Set a field value. The report this field belongs to has to be - * created and transfered to the device, to set this value in the - * device. - */ - -int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) -{ - unsigned size = field->report_size; - - hid_dump_input(field->usage + offset, value); - - if (offset >= field->report_count) { - dbg("offset exceeds report_count"); - return -1; - } - if (field->logical_minimum < 0) { - if (value != snto32(s32ton(value, size), size)) { - dbg("value %d is out of range", value); - return -1; - } - } - if ( (value > field->logical_maximum) - || (value < field->logical_minimum)) { - dbg("value %d is invalid", value); - return -1; - } - field->value[offset] = value; - return 0; -} - -static int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) -{ - struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT; - struct list_head *list = report_enum->report_list.next; - int i, j; - - while (list != &report_enum->report_list) { - struct hid_report *report = (struct hid_report *) list; - list = list->next; - for (i = 0; i < report->maxfield; i++) { - *field = report->field[i]; - for (j = 0; j < (*field)->maxusage; j++) - if ((*field)->usage[j].type == type && (*field)->usage[j].code == code) - return j; - } - } - return -1; -} - -static int hid_submit_out(struct hid_device *hid) -{ - hid->urbout.transfer_buffer_length = le16_to_cpup(&hid->out[hid->outtail].dr.length); - hid->urbout.transfer_buffer = hid->out[hid->outtail].buffer; - hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr); - hid->urbout.dev = hid->dev; - - if (usb_submit_urb(&hid->urbout)) { - err("usb_submit_urb(out) failed"); - return -1; - } - - return 0; -} - -static void hid_ctrl(struct urb *urb) -{ - struct hid_device *hid = urb->context; - - if (urb->status) - warn("ctrl urb status %d received", urb->status); - - hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1); - - if (hid->outhead != hid->outtail) - hid_submit_out(hid); -} - -static int hid_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) -{ - struct hid_device *hid = dev->private; - struct hid_field *field = NULL; - int offset; - - if ((offset = hid_find_field(hid, type, code, &field)) == -1) { - warn("event field not found"); - return -1; - } - - hid_set_field(field, offset, value); - hid_output_report(field->report, hid->out[hid->outhead].buffer); - - hid->out[hid->outhead].dr.value = cpu_to_le16(0x200 | field->report->id); - hid->out[hid->outhead].dr.length = cpu_to_le16((field->report->size + 7) >> 3); - - hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1); - - if (hid->outhead == hid->outtail) - hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1); - - if (hid->urbout.status != -EINPROGRESS) - hid_submit_out(hid); - - return 0; -} - -static int hid_open(struct input_dev *dev) -{ - struct hid_device *hid = dev->private; - - if (hid->open++) - return 0; - - hid->urb.dev = hid->dev; - - if (usb_submit_urb(&hid->urb)) - return -EIO; - - return 0; -} - -static void hid_close(struct input_dev *dev) -{ - struct hid_device *hid = dev->private; - - if (!--hid->open) - usb_unlink_urb(&hid->urb); -} - -/* - * Configure the input layer interface - * Read all reports and initalize the absoulte field values. - */ - -static void hid_init_input(struct hid_device *hid) -{ - struct hid_report_enum *report_enum; - struct list_head *list; - int i, j, k; - - hid->input.private = hid; - hid->input.event = hid_event; - hid->input.open = hid_open; - hid->input.close = hid_close; - - for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { - - report_enum = hid->report_enum + k; - list = report_enum->report_list.next; - - while (list != &report_enum->report_list) { - - struct hid_report *report = (struct hid_report *) list; - - list = list->next; - - for (i = 0; i < report->maxfield; i++) - for (j = 0; j < report->field[i]->maxusage; j++) - hid_configure_usage(hid, report->field[i], report->field[i]->usage + j); - - if (k == HID_INPUT_REPORT) { - usb_set_idle(hid->dev, hid->ifnum, 0, report->id); - hid_read_report(hid, report); - } - } - } -} - -#define USB_VENDOR_ID_WACOM 0x056a -#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010 -#define USB_DEVICE_ID_WACOM_INTUOS 0x0020 - -struct hid_blacklist { - __u16 idVendor; - __u16 idProduct; -} hid_blacklist[] = { - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1}, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2}, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3}, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4}, - { 0, 0 } -}; - -static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum, char *name) -{ - struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0; - struct hid_descriptor *hdesc; - struct hid_device *hid; - unsigned rsize = 0; - int n; - - for (n = 0; hid_blacklist[n].idVendor; n++) - if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) && - (hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL; - - if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc) - && usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc)) { - dbg("class descriptor not present\n"); - return NULL; - } - - for (n = 0; n < hdesc->bNumDescriptors; n++) - if (hdesc->desc[n].bDescriptorType == USB_DT_REPORT) - rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); - - if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { - dbg("weird size of report descriptor (%u)", rsize); - return NULL; - } - - { - __u8 rdesc[rsize]; - - if ((n = usb_get_class_descriptor(dev, interface->bInterfaceNumber, USB_DT_REPORT, 0, rdesc, rsize)) < 0) { - dbg("reading report descriptor failed"); - return NULL; - } - -#ifdef DEBUG_DATA - printk(KERN_DEBUG __FILE__ ": report (size %u, read %d) = ", rsize, n); - for (n = 0; n < rsize; n++) - printk(" %02x", (unsigned) rdesc[n]); - printk("\n"); -#endif - - if (!(hid = hid_parse_report(rdesc, rsize))) { - dbg("parsing report descriptor failed"); - return NULL; - } - } - - for (n = 0; n < interface->bNumEndpoints; n++) { - - struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n]; - int pipe, maxp; - - if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ - continue; - - if (!(endpoint->bEndpointAddress & 0x80)) /* Not an input endpoint */ - continue; - - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - FILL_INT_URB(&hid->urb, dev, pipe, hid->buffer, maxp > 32 ? 32 : maxp, hid_irq, hid, endpoint->bInterval); - - break; - } - - if (n == interface->bNumEndpoints) { - dbg("couldn't find an input interrupt endpoint"); - hid_free_device(hid); - return NULL; - } - - hid->version = hdesc->bcdHID; - hid->country = hdesc->bCountryCode; - hid->dev = dev; - hid->ifnum = interface->bInterfaceNumber; - - for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) { - hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE; - hid->out[n].dr.request = USB_REQ_SET_REPORT; - hid->out[n].dr.index = cpu_to_le16(hid->ifnum); - } - - hid->input.name = hid->name; - hid->input.idbus = BUS_USB; - hid->input.idvendor = dev->descriptor.idVendor; - hid->input.idproduct = dev->descriptor.idProduct; - hid->input.idversion = dev->descriptor.bcdDevice; - - if (strlen(name)) - strcpy(hid->name, name); - else - sprintf(hid->name, "USB HID %s %04x:%04x", - ((hid->application >= 0x00010000) && (hid->application <= 0x00010008)) ? - hid_types[hid->application & 0xffff] : "Device", - hid->input.idvendor, hid->input.idproduct); - - FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0), - (void*) &hid->out[0].dr, hid->out[0].buffer, 1, hid_ctrl, hid); - - if (interface->bInterfaceSubClass == 1) - usb_set_protocol(dev, hid->ifnum, 1); - - return hid; -} - -static void* hid_probe(struct usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id) -{ - struct hid_device *hid; - char name[128]; - char *buf; - - dbg("HID probe called for ifnum %d", ifnum); - - name[0] = 0; - - if (!(buf = kmalloc(63, GFP_KERNEL))) - return NULL; - - if (dev->descriptor.iManufacturer && - usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) - strcat(name, buf); - if (dev->descriptor.iProduct && - usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) - sprintf(name, "%s %s", name, buf); - - kfree(buf); - - if (!(hid = usb_hid_configure(dev, ifnum, name))) - return NULL; - - hid_dump_device(hid); - - hid_init_input(hid); - input_register_device(&hid->input); - - printk(KERN_INFO "input%d: USB HID v%x.%02x %s", - hid->input.number, - hid->version >> 8, hid->version & 0xff, - ((hid->application >= 0x00010000) && (hid->application <= 0x00010008)) ? - hid_types[hid->application & 0xffff] : "Device"); - - if (strlen(name)) - printk(" [%s]", name); - else - printk(" [%04x:%04x]", hid->input.idvendor, hid->input.idproduct); - - printk(" on usb%d:%d.%d\n", dev->bus->busnum, dev->devnum, ifnum); - - return hid; -} - -static void hid_disconnect(struct usb_device *dev, void *ptr) -{ - struct hid_device *hid = ptr; - - dbg("cleanup called"); - usb_unlink_urb(&hid->urb); - input_unregister_device(&hid->input); - hid_free_device(hid); -} - -static struct usb_device_id hid_usb_ids [] = { - { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS, - bInterfaceClass: USB_INTERFACE_CLASS_HID}, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, hid_usb_ids); - -static struct usb_driver hid_driver = { - name: "hid", - probe: hid_probe, - disconnect: hid_disconnect, - id_table: hid_usb_ids, -}; - -static int __init hid_init(void) -{ - usb_register(&hid_driver); - info(DRIVER_VERSION ":" DRIVER_DESC); - return 0; -} - -static void __exit hid_exit(void) -{ - usb_deregister(&hid_driver); -} - -module_init(hid_init); -module_exit(hid_exit); - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); - diff -u --recursive --new-file v2.4.9/linux/drivers/usb/hid.h linux/drivers/usb/hid.h --- v2.4.9/linux/drivers/usb/hid.h Wed Apr 18 11:49:12 2001 +++ linux/drivers/usb/hid.h Wed Sep 12 15:34:06 2001 @@ -2,10 +2,10 @@ #define __HID_H /* - * $Id: hid.h,v 1.7 2000/05/31 22:57:48 vojtech Exp $ + * $Id: hid.h,v 1.10 2001/05/10 15:56:07 vojtech Exp $ * * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000 Vojtech Pavlik + * Copyright (c) 2000-2001 Vojtech Pavlik * * Sponsored by SuSE */ @@ -210,6 +210,7 @@ #define HID_MAX_DESCRIPTOR_SIZE 4096 #define HID_MAX_USAGES 1024 +#define HID_MAX_APPLICATIONS 16 struct hid_local { unsigned usage[HID_MAX_USAGES]; /* usage array */ @@ -239,6 +240,7 @@ struct hid_field { unsigned physical; /* physical usage for this field */ unsigned logical; /* logical usage for this field */ + unsigned application; /* application usage for this field */ struct hid_usage *usage; /* usage table for this function */ unsigned maxusage; /* maximum usage index */ unsigned flags; /* main-item flags (i.e. volatile,array,constant) */ @@ -265,6 +267,8 @@ struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ unsigned maxfield; /* maximum valid field index */ unsigned size; /* size of the report (bits) */ + unsigned idx; /* where we're in data */ + unsigned char *data; /* data for multi-packet reports */ struct hid_device *device; /* associated device */ }; @@ -284,10 +288,14 @@ char buffer[HID_BUFFER_SIZE]; }; +#define HID_CLAIMED_INPUT 1 +#define HID_CLAIMED_HIDDEV 2 + struct hid_device { /* device report descriptor */ __u8 *rdesc; unsigned rsize; - unsigned application; /* HID application, i.e. Digitizer */ + unsigned application[HID_MAX_APPLICATIONS]; /* List of HID applications */ + unsigned maxapplication; /* Number of applications */ unsigned version; /* HID version */ unsigned country; /* HID country */ struct hid_report_enum report_enum[HID_REPORT_TYPES]; @@ -302,9 +310,14 @@ struct hid_control_fifo out[HID_CONTROL_FIFO_SIZE]; /* Transmit buffer */ unsigned char outhead, outtail; /* Tx buffer head & tail */ - struct input_dev input; /* input device structure */ - int open; /* is the device open by input? */ - int quirks; /* Various nasty tricks the device can pull on us */ + unsigned claimed; /* Claimed by hidinput, hiddev? */ + unsigned quirks; /* Various quirks the device can pull on us */ + + struct input_dev input; /* The input structure */ + void *hiddev; /* The hiddev structure */ + int minor; /* Hiddev minor number */ + + int open; /* is the device open by anyone? */ char name[128]; /* Device name */ }; @@ -336,6 +349,25 @@ struct hid_class_descriptor desc[1]; } __attribute__ ((packed)); +void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); +int hidinput_connect(struct hid_device *); +void hidinput_disconnect(struct hid_device *); + +#ifdef DEBUG +#include "hid-debug.h" +#else +#define hid_dump_input(a,b) do { } while (0) +#define hid_dump_device(c) do { } while (0) +#endif #endif +#define IS_INPUT_APPLICATION(a) ((a >= 0x00010000) && (a <= 0x00010008)) + +int hid_open(struct hid_device *); +void hid_close(struct hid_device *); +int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field **); +int hid_set_field(struct hid_field *, unsigned, __s32); +void hid_write_report(struct hid_device *, struct hid_report *); +void hid_read_report(struct hid_device *, struct hid_report *); +void hid_init_reports(struct hid_device *hid); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/hiddev.c linux/drivers/usb/hiddev.c --- v2.4.9/linux/drivers/usb/hiddev.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/hiddev.c Wed Sep 12 15:34:06 2001 @@ -0,0 +1,677 @@ +/* + * Copyright (c) 2001 Paul Stewart + * Copyright (c) 2001 Vojtech Pavlik + * + * HID char devices, giving access to raw HID device events. + * + */ + +/* + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to Paul Stewart + */ + +#define HIDDEV_MINOR_BASE 96 +#define HIDDEV_MINORS 16 +#define HIDDEV_BUFFER_SIZE 64 + +#include +#include +#include +#include +#include +#include +#include +#include "hid.h" +#include + +struct hiddev { + int exist; + int open; + int minor; + wait_queue_head_t wait; + devfs_handle_t devfs; + struct hid_device *hid; + struct hiddev_list *list; +}; + +struct hiddev_list { + struct hiddev_event buffer[HIDDEV_BUFFER_SIZE]; + int head; + int tail; + struct fasync_struct *fasync; + struct hiddev *hiddev; + struct hiddev_list *next; +}; + +static struct hiddev *hiddev_table[HIDDEV_MINORS]; +static devfs_handle_t hiddev_devfs_handle; + +/* + * Find a report, given the report's type and ID. The ID can be specified + * indirectly by REPORT_ID_FIRST (which returns the first report of the given + * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the + * given type which follows old_id. + */ +static struct hid_report * +hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) +{ + struct hid_report_enum *report_enum; + struct list_head *list; + + if (rinfo->report_type < HID_REPORT_TYPE_MIN || + rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL; + + report_enum = hid->report_enum + + (rinfo->report_type - HID_REPORT_TYPE_MIN); + if ((rinfo->report_id & ~HID_REPORT_ID_MASK) != 0) { + switch (rinfo->report_id & ~HID_REPORT_ID_MASK) { + case HID_REPORT_ID_FIRST: + list = report_enum->report_list.next; + if (list == &report_enum->report_list) return NULL; + rinfo->report_id = ((struct hid_report *) list)->id; + break; + + case HID_REPORT_ID_NEXT: + list = (struct list_head *) + report_enum->report_id_hash[rinfo->report_id & + HID_REPORT_ID_MASK]; + if (list == NULL) return NULL; + list = list->next; + if (list == &report_enum->report_list) return NULL; + rinfo->report_id = ((struct hid_report *) list)->id; + break; + + default: + return NULL; + } + } + + return report_enum->report_id_hash[rinfo->report_id]; +} + +/* + * Perform an exhaustive search of the report table for a usage, given its + * type and usage id. + */ +static struct hid_field * +hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) +{ + int i, j; + struct hid_report *report; + struct hid_report_enum *report_enum; + struct list_head *list; + struct hid_field *field; + + if (uref->report_type < HID_REPORT_TYPE_MIN || + uref->report_type > HID_REPORT_TYPE_MAX) return NULL; + + report_enum = hid->report_enum + + (uref->report_type - HID_REPORT_TYPE_MIN); + list = report_enum->report_list.next; + while (list != &report_enum->report_list) { + report = (struct hid_report *) list; + for (i = 0; i < report->maxfield; i++) { + field = report->field[i]; + for (j = 0; j < field->maxusage; j++) { + if (field->usage[j].hid == uref->usage_code) { + uref->report_id = report->id; + uref->field_index = i; + uref->usage_index = j; + return field; + } + } + } + list = list->next; + } + + return NULL; +} + +/* + * This is where hid.c calls into hiddev to pass an event that occurred over + * the interrupt pipe + */ +void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value) +{ + struct hiddev *hiddev = hid->hiddev; + struct hiddev_list *list = hiddev->list; + + while (list) { + list->buffer[list->head].hid = usage; + list->buffer[list->head].value = value; + list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1); + + kill_fasync(&list->fasync, SIGIO, POLL_IN); + + list = list->next; + } + + wake_up_interruptible(&hiddev->wait); +} + +/* + * fasync file op + */ +static int hiddev_fasync(int fd, struct file *file, int on) +{ + int retval; + struct hiddev_list *list = file->private_data; + retval = fasync_helper(fd, file, on, &list->fasync); + return retval < 0 ? retval : 0; +} + +/* + * De-allocate a hiddev structure + */ +static void hiddev_cleanup(struct hiddev *hiddev) +{ + devfs_unregister(hiddev->devfs); + hiddev_table[hiddev->minor] = NULL; + kfree(hiddev); +} + +/* + * release file op + */ +static int hiddev_release(struct inode * inode, struct file * file) +{ + struct hiddev_list *list = file->private_data; + struct hiddev_list **listptr; + + lock_kernel(); + listptr = &list->hiddev->list; + hiddev_fasync(-1, file, 0); + + while (*listptr && (*listptr != list)) + listptr = &((*listptr)->next); + *listptr = (*listptr)->next; + + if (!--list->hiddev->open) { + if (list->hiddev->exist) + hid_close(list->hiddev->hid); + else + hiddev_cleanup(list->hiddev); + } + + kfree(list); + unlock_kernel(); + + return 0; +} + +/* + * open file op + */ +static int hiddev_open(struct inode * inode, struct file * file) { + struct hiddev_list *list; + + int i = MINOR(inode->i_rdev) - HIDDEV_MINOR_BASE; + + if (i >= HIDDEV_MINORS || !hiddev_table[i]) + return -ENODEV; + + if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL))) + return -ENOMEM; + memset(list, 0, sizeof(struct hiddev_list)); + + list->hiddev = hiddev_table[i]; + list->next = hiddev_table[i]->list; + hiddev_table[i]->list = list; + + file->private_data = list; + + if (!list->hiddev->open++) + if (list->hiddev->exist) + hid_open(hiddev_table[i]->hid); + + return 0; +} + +/* + * "write" file op + */ +static ssize_t hiddev_write(struct file * file, const char * buffer, + size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +/* + * "read" file op + */ +static ssize_t hiddev_read(struct file * file, char * buffer, size_t count, + loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + struct hiddev_list *list = file->private_data; + int retval = 0; + + if (list->head == list->tail) { + + add_wait_queue(&list->hiddev->wait, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (list->head == list->tail) { + + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + if (!list->hiddev->exist) { + retval = -EIO; + break; + } + + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue(&list->hiddev->wait, &wait); + } + + if (retval) + return retval; + + while (list->head != list->tail && retval + sizeof(struct hiddev_event) <= count) { + if (copy_to_user(buffer + retval, list->buffer + list->tail, + sizeof(struct hiddev_event))) return -EFAULT; + list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); + retval += sizeof(struct hiddev_event); + } + + return retval; +} + +/* + * "poll" file op + * No kernel lock - fine + */ +static unsigned int hiddev_poll(struct file *file, poll_table *wait) +{ + struct hiddev_list *list = file->private_data; + poll_wait(file, &list->hiddev->wait, wait); + if (list->head != list->tail) + return POLLIN | POLLRDNORM; + if (!list->hiddev->exist) + return POLLERR | POLLHUP; + return 0; +} + +#define GET_TIMEOUT 3 +#define SET_TIMEOUT 3 + +/* + * "ioctl" file op + */ +static int hiddev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct hiddev_list *list = file->private_data; + struct hiddev *hiddev = list->hiddev; + struct hid_device *hid = hiddev->hid; + struct usb_device *dev = hid->dev; + struct hiddev_report_info rinfo; + struct hiddev_usage_ref uref; + struct hid_report *report; + struct hid_field *field; + + if (!hiddev->exist) return -EIO; + + switch (cmd) { + + case HIDIOCGVERSION: + return put_user(HID_VERSION, (int *) arg); + + case HIDIOCAPPLICATION: + if (arg < 0 || arg >= hid->maxapplication) + return -EINVAL; + return hid->application[arg]; + + case HIDIOCGDEVINFO: + { + struct hiddev_devinfo dinfo; + dinfo.bustype = BUS_USB; + dinfo.busnum = dev->bus->busnum; + dinfo.devnum = dev->devnum; + dinfo.ifnum = hid->ifnum; + dinfo.vendor = dev->descriptor.idVendor; + dinfo.product = dev->descriptor.idProduct; + dinfo.version = dev->descriptor.bcdDevice; + dinfo.num_applications = hid->maxapplication; + return copy_to_user((void *) arg, &dinfo, sizeof(dinfo)); + } + + case HIDIOCGSTRING: + { + int idx, len; + char *buf; + + if (get_user(idx, (int *) arg)) + return -EFAULT; + + if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL) + return -ENOMEM; + + if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) { + kfree(buf); + return -EINVAL; + } + + if (copy_to_user((void *) (arg+sizeof(int)), buf, len+1)) { + kfree(buf); + return -EFAULT; + } + + kfree(buf); + + return len; + } + + case HIDIOCINITREPORT: + + hid_init_reports(hid); + + return 0; + + case HIDIOCGREPORT: + if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo))) + return -EFAULT; + + if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) + return -EINVAL; + + if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) + return -EINVAL; + + hid_read_report(hid, report); + + return 0; + + case HIDIOCSREPORT: + if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo))) + return -EFAULT; + + if (rinfo.report_type == HID_REPORT_TYPE_INPUT) + return -EINVAL; + + if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) + return -EINVAL; + + hid_write_report(hid, report); + + return 0; + + case HIDIOCGREPORTINFO: + if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo))) + return -EFAULT; + + if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) + return -EINVAL; + + rinfo.num_fields = report->maxfield; + + return copy_to_user((void *) arg, &rinfo, sizeof(rinfo)); + + case HIDIOCGFIELDINFO: + { + struct hiddev_field_info finfo; + if (copy_from_user(&finfo, (void *) arg, sizeof(finfo))) + return -EFAULT; + rinfo.report_type = finfo.report_type; + rinfo.report_id = finfo.report_id; + if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) + return -EINVAL; + + if (finfo.field_index >= report->maxfield) + return -EINVAL; + + field = report->field[finfo.field_index]; + memset(&finfo, 0, sizeof(finfo)); + finfo.report_type = rinfo.report_type; + finfo.report_id = rinfo.report_id; + finfo.field_index = field->report_count - 1; + finfo.maxusage = field->maxusage; + finfo.flags = field->flags; + finfo.physical = field->physical; + finfo.logical = field->logical; + finfo.application = field->application; + finfo.logical_minimum = field->logical_minimum; + finfo.logical_maximum = field->logical_maximum; + finfo.physical_minimum = field->physical_minimum; + finfo.physical_maximum = field->physical_maximum; + finfo.unit_exponent = field->unit_exponent; + finfo.unit = field->unit; + + return copy_to_user((void *) arg, &finfo, sizeof(finfo)); + } + + case HIDIOCGUCODE: + if (copy_from_user(&uref, (void *) arg, sizeof(uref))) + return -EFAULT; + + rinfo.report_type = uref.report_type; + rinfo.report_id = uref.report_id; + if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) + return -EINVAL; + + if (uref.field_index >= report->maxfield) + return -EINVAL; + + field = report->field[uref.field_index]; + if (uref.usage_index >= field->maxusage) + return -EINVAL; + + uref.usage_code = field->usage[uref.usage_index].hid; + + return copy_to_user((void *) arg, &uref, sizeof(uref)); + + case HIDIOCGUSAGE: + if (copy_from_user(&uref, (void *) arg, sizeof(uref))) + return -EFAULT; + + if (uref.report_id == HID_REPORT_ID_UNKNOWN) { + field = hiddev_lookup_usage(hid, &uref); + if (field == NULL) + return -EINVAL; + } else { + rinfo.report_type = uref.report_type; + rinfo.report_id = uref.report_id; + if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) + return -EINVAL; + + if (uref.field_index >= report->maxfield) + return -EINVAL; + + field = report->field[uref.field_index]; + if (uref.usage_index >= field->maxusage) + return -EINVAL; + } + + uref.value = field->value[uref.usage_index]; + + return copy_to_user((void *) arg, &uref, sizeof(uref)); + + case HIDIOCSUSAGE: + if (copy_from_user(&uref, (void *) arg, sizeof(uref))) + return -EFAULT; + + if (uref.report_type == HID_REPORT_TYPE_INPUT) + return -EINVAL; + + if (uref.report_id == HID_REPORT_ID_UNKNOWN) { + field = hiddev_lookup_usage(hid, &uref); + if (field == NULL) + return -EINVAL; + } else { + rinfo.report_type = uref.report_type; + rinfo.report_id = uref.report_id; + if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) + return -EINVAL; + + if (uref.field_index >= report->maxfield) + return -EINVAL; + + field = report->field[uref.field_index]; + if (uref.usage_index >= field->maxusage) + return -EINVAL; + } + + field->value[uref.usage_index] = uref.value; + + return 0; + + default: + + if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) + return -EINVAL; + + if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { + int len; + if (!hid->name) return 0; + len = strlen(hid->name) + 1; + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user((char *) arg, hid->name, len) ? + -EFAULT : len; + } + } + return -EINVAL; +} + +static struct file_operations hiddev_fops = { + owner: THIS_MODULE, + read: hiddev_read, + write: hiddev_write, + poll: hiddev_poll, + open: hiddev_open, + release: hiddev_release, + ioctl: hiddev_ioctl, + fasync: hiddev_fasync, +}; + +/* + * This is where hid.c calls us to connect a hid device to the hiddev driver + */ +int hiddev_connect(struct hid_device *hid) +{ + struct hiddev *hiddev; + int minor, i; + char devfs_name[16]; + + for (i = 0; i < hid->maxapplication; i++) + if (!IS_INPUT_APPLICATION(hid->application[i])) + break; + + if (i == hid->maxapplication) + return -1; + + for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++); + if (minor == HIDDEV_MINORS) { + printk(KERN_ERR "hiddev: no more free hiddev devices\n"); + return -1; + } + + if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) + return -1; + memset(hiddev, 0, sizeof(struct hiddev)); + + init_waitqueue_head(&hiddev->wait); + + hiddev->minor = minor; + hiddev_table[minor] = hiddev; + + hiddev->hid = hid; + hiddev->exist = 1; + + sprintf(devfs_name, "hiddev%d", minor); + hiddev->devfs = devfs_register(hiddev_devfs_handle, devfs_name, + DEVFS_FL_DEFAULT, USB_MAJOR, + minor + HIDDEV_MINOR_BASE, + S_IFCHR | S_IRUGO | S_IWUSR, + &hiddev_fops, NULL); + hid->minor = minor; + hid->hiddev = hiddev; + + return 0; +} + +/* + * This is where hid.c calls us to disconnect a hiddev device from the + * corresponding hid device (usually because the usb device has disconnected) + */ +void hiddev_disconnect(struct hid_device *hid) +{ + struct hiddev *hiddev = hid->hiddev; + + hiddev->exist = 0; + + if (hiddev->open) { + hid_close(hiddev->hid); + wake_up_interruptible(&hiddev->wait); + } else { + hiddev_cleanup(hiddev); + } +} + +/* Currently this driver is a USB driver. It's not a conventional one in + * the sense that it doesn't probe at the USB level. Instead it waits to + * be connected by HID through the hiddev_connect / hiddev_disconnect + * routines. The reason to register as a USB device is to gain part of the + * minor number space from the USB major. + * + * In theory, should the HID code be generalized to more than one physical + * medium (say, IEEE 1384), this driver will probably need to register its + * own major number, and in doing so, no longer need to register with USB. + * At that point the probe routine and hiddev_driver struct below will no + * longer be useful. + */ + + +/* We never attach in this manner, and rely on HID to connect us. This + * is why there is no disconnect routine defined in the usb_driver either. + */ +static void *hiddev_usbd_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *hiddev_info) +{ + return NULL; +} + + +static /* const */ struct usb_driver hiddev_driver = { + name: "hiddev", + probe: hiddev_usbd_probe, + fops: &hiddev_fops, + minor: HIDDEV_MINOR_BASE +}; + +int __init hiddev_init(void) +{ + hiddev_devfs_handle = + devfs_mk_dir(devfs_find_handle(NULL, "usb", 0, 0, 0, 0), "hid", NULL); + usb_register(&hiddev_driver); + return 0; +} + +void __exit hiddev_exit(void) +{ + devfs_unregister(hiddev_devfs_handle); + usb_deregister(&hiddev_driver); +} 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 Tue Sep 18 17:09:59 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 Fri Sep 14 14:04:07 2001 @@ -101,6 +101,7 @@ MODULE_AUTHOR("Michael Zappe , Stephane Alnet and Brad Hards "); MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver"); +MODULE_LICENSE("GPL"); static void *kaweth_probe( struct usb_device *dev, /* the device */ @@ -248,9 +249,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 +371,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 +480,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 +612,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 +723,6 @@ net->trans_start = jiffies; usb_unlink_urb(kaweth->tx_urb); - - netif_wake_queue(net); } /**************************************************************** @@ -836,7 +838,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 +881,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 +902,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 +1057,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/microtek.c linux/drivers/usb/microtek.c --- v2.4.9/linux/drivers/usb/microtek.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/microtek.c Sat Sep 15 22:21:43 2001 @@ -808,6 +808,7 @@ { "ScanMaker V6USL", mts_sup_unknown}, { "ScanMaker V6USL", mts_sup_unknown}, { "Scanmaker V6UL", mts_sup_unknown}, + { "Scanmaker V6UPL", mts_sup_alpha}, }; /* The entries of microtek_table must correspond, line-by-line to @@ -823,6 +824,7 @@ { USB_DEVICE(0x5da, 0x00a3) }, { USB_DEVICE(0x5da, 0x80a3) }, { USB_DEVICE(0x5da, 0x80ac) }, + { USB_DEVICE(0x5da, 0x00b6) }, { } /* Terminating entry */ }; @@ -1062,4 +1064,5 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); 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/ov511.c linux/drivers/usb/ov511.c --- v2.4.9/linux/drivers/usb/ov511.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/ov511.c Fri Sep 14 14:04:07 2001 @@ -156,6 +156,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); static struct usb_driver ov511_driver; 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 Fri Sep 14 14:04:07 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 @@ -83,6 +83,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(loopback, "i"); MODULE_PARM(mii_mode, "i"); MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)"); @@ -117,9 +118,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 +134,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 +155,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 +185,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 +205,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 +235,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 +255,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 +631,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 +643,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 +870,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-ctrl.c linux/drivers/usb/pwc-ctrl.c --- v2.4.9/linux/drivers/usb/pwc-ctrl.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/pwc-ctrl.c Sat Sep 15 22:21:43 2001 @@ -18,6 +18,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* + Changes + 2001/08/03 Alvarado Added methods for changing white balance and + red/green gains + */ + /* Control functions for the cam; brightness, contrast, video mode, etc. */ #ifdef __KERNEL__ @@ -603,12 +609,12 @@ char buf; int ret; - if (pdev->type < 730) + if (pdev->type < 675) return -1; ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), GET_CHROM_CTL, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - SATURATION_MODE_FORMATTER1, + pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, pdev->vcinterface, &buf, 1, HZ / 2); if (ret < 0) @@ -620,7 +626,7 @@ { char buf; - if (pdev->type < 730) + if (pdev->type < 675) return -EINVAL; if (value < 0) value = 0; @@ -631,7 +637,7 @@ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), SET_CHROM_CTL, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - SATURATION_MODE_FORMATTER1, + pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, pdev->vcinterface, &buf, 1, HZ / 2); } @@ -825,6 +831,218 @@ NULL, 0, HZ / 2); } + /* ************************************************* */ + /* Patch by Alvarado: (not in the original version */ + + /* + * the camera recognizes modes from 0 to 4: + * + * 00: indoor (incandescant lighting) + * 01: outdoor (sunlight) + * 02: fluorescent lighting + * 03: manual + * 04: auto + */ +static inline int pwc_set_awb(struct pwc_device *pdev, int mode) +{ + char buf; + int ret; + + if (mode < 0) + mode = 0; + + if (mode > 4) + mode = 4; + + buf = mode & 0x07; /* just the lowest three bits */ + + ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), + SET_CHROM_CTL, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + WB_MODE_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); + + if (ret < 0) + return ret; + return 0; +} + +static inline int pwc_get_awb(struct pwc_device *pdev) +{ + unsigned char buf; + int ret; + + ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), + GET_CHROM_CTL, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + WB_MODE_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); + + if (ret < 0) + return ret; + return buf; +} + +static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) +{ + unsigned char buf; + + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + + /* only the msb are considered */ + buf = value >> 8; + + return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), + SET_CHROM_CTL, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + PRESET_MANUAL_RED_GAIN_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); +} + +static inline int pwc_get_red_gain(struct pwc_device *pdev) +{ + unsigned char buf; + int ret; + + ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), + GET_STATUS_CTL, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + PRESET_MANUAL_RED_GAIN_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); + + if (ret < 0) + return ret; + + return (buf << 8); +} + + +static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value) +{ + unsigned char buf; + + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + + /* linear mapping of 0..0xffff to -0x80..0x7f */ + buf = (value >> 8); + + return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), + SET_CHROM_CTL, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + PRESET_MANUAL_BLUE_GAIN_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); +} + +static inline int pwc_get_blue_gain(struct pwc_device *pdev) +{ + unsigned char buf; + int ret; + + ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), + GET_STATUS_CTL, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + PRESET_MANUAL_BLUE_GAIN_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); + + if (ret < 0) + return ret; + + return (buf << 8); +} + +/* The following two functions are different, since they only read the + internal red/blue gains, which may be different from the manual + gains set or read above. + */ +static inline int pwc_read_red_gain(struct pwc_device *pdev) +{ + unsigned char buf; + int ret; + + ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), + GET_STATUS_CTL, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + READ_RED_GAIN_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); + + if (ret < 0) + return ret; + + return (buf << 8); +} +static inline int pwc_read_blue_gain(struct pwc_device *pdev) +{ + unsigned char buf; + int ret; + + ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), + GET_STATUS_CTL, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + READ_BLUE_GAIN_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); + + if (ret < 0) + return ret; + + return (buf << 8); +} + +/* still unused (it doesn't work yet...) */ +static inline int pwc_set_led(struct pwc_device *pdev, int value) +{ + unsigned char buf; + + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + + buf = (value >> 8); + + return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), + SET_STATUS_CTL, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + LED_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); +} + +/* still unused (it doesn't work yet...) */ +static inline int pwc_get_led(struct pwc_device *pdev) +{ + unsigned char buf; + int ret; + + ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), + GET_STATUS_CTL, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + LED_FORMATTER, + pdev->vcinterface, + &buf, 1, HZ / 2); + + if (ret < 0) + return ret; + + return (buf << 8); +} + + /* End of Add-Ons */ + /* ************************************************* */ + int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { switch(cmd) { @@ -910,6 +1128,74 @@ break; } + + /* ************************************************* */ + /* Begin of Add-Ons for color compensation */ + + case VIDIOCPWCSAWB: + { + struct pwc_whitebalance wb; + int ret; + + if (copy_from_user(&wb, arg, sizeof(wb))) + return -EFAULT; + + ret = pwc_set_awb(pdev, wb.mode); + if (ret >= 0 && wb.mode == PWC_WB_MANUAL) { + pwc_set_red_gain(pdev, wb.manual_red); + pwc_set_blue_gain(pdev, wb.manual_blue); + } + break; + } + + case VIDIOCPWCGAWB: + { + struct pwc_whitebalance wb; + + memset(&wb, 0, sizeof(wb)); + wb.mode = pwc_get_awb(pdev); + if (wb.mode < 0) + return -EINVAL; + wb.manual_red = pwc_get_red_gain(pdev); + wb.manual_blue = pwc_get_blue_gain(pdev); + if (wb.mode == PWC_WB_AUTO) { + wb.read_red = pwc_read_red_gain(pdev); + wb.read_blue = pwc_read_blue_gain(pdev); + } + break; + } + + case VIDIOCPWCSLED: + { + int led, ret; + if (copy_from_user(&led,arg,sizeof(led))) + return -EFAULT; + else { + /* ret = pwc_set_led(pdev, led); */ + ret = 0; + if (ret<0) + return ret; + } + break; + } + + + + case VIDIOCPWCGLED: + { + int led; + + led = pwc_get_led(pdev); + if (led < 0) + return -EINVAL; + if (copy_to_user(arg, &led, sizeof(led))) + return -EFAULT; + break; + } + + /* End of Add-Ons */ + /* ************************************************* */ + default: return -ENOIOCTLCMD; break; @@ -918,3 +1204,7 @@ } #endif + + + + 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 Sat Sep 15 22:21:43 2001 @@ -35,7 +35,12 @@ udev: struct usb_device * vdev: struct video_device * pdev: struct pwc_devive * -*/ +*/ + +/* Contributors: + - Alvarado: adding whitebalance code + - Alistar Moire: QuickCam 3000 Pro testing +*/ #include #include @@ -68,6 +73,7 @@ { USB_DEVICE(0x0471, 0x0311) }, { USB_DEVICE(0x0471, 0x0312) }, { USB_DEVICE(0x069A, 0x0001) }, + { USB_DEVICE(0x046D, 0x0b80) }, { } }; MODULE_DEVICE_TABLE(usb, pwc_device_table); @@ -85,10 +91,10 @@ static int default_size = PSZ_QCIF; static int default_fps = 10; -static int default_palette = VIDEO_PALETTE_YUV420P; /* This is normal for webcams */ +static int default_palette = VIDEO_PALETTE_YUV420P; /* This format is understood by most tools */ static int default_fbufs = 3; /* Default number of frame buffers */ static int default_mbufs = 2; /* Default number of mmap() buffers */ - int pwc_trace = TRACE_MODULE | TRACE_FLOW; + int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; static int power_save = 0; int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */ @@ -167,109 +173,90 @@ */ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) { - unsigned long ret = 0UL; + 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)); + 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)); + } - } - } - return ret; -} - -static inline unsigned long uvirt_to_bus(unsigned long adr) -{ - unsigned long kva, ret; - - kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); - ret = virt_to_bus((void *)kva); + } + } return ret; } -static inline unsigned long kvirt_to_bus(unsigned long adr) -{ - unsigned long va, kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = virt_to_bus((void *)kva); - 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. */ -static inline unsigned long kvirt_to_pa(unsigned long adr) +static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long va, kva, ret; + unsigned long va, kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); ret = __pa(kva); - return ret; + return ret; } -static void *rvmalloc(unsigned long size) +static void * rvmalloc(signed long size) { - void *mem; + void * mem; unsigned long adr, page; - /* Round it off to PAGE_SIZE */ - size += (PAGE_SIZE - 1); - size &= ~(PAGE_SIZE - 1); - - mem = vmalloc(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 = kvirt_to_pa(adr); - mem_map_reserve(MAP_NR(__va(page))); - adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + /* Round it off to PAGE_SIZE */ + size += (PAGE_SIZE - 1); + size &= ~(PAGE_SIZE - 1); + + mem=vmalloc_32(size); + if (mem) + { + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr=(unsigned long) mem; + while (size > 0) + { + page = kvirt_to_pa(adr); + mem_map_reserve(virt_to_page(__va(page))); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } } return mem; } -static void rvfree(void *mem, unsigned long size) +static void rvfree(void * mem, signed 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 = kvirt_to_pa(adr); - mem_map_unreserve(MAP_NR(__va(page))); - adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + unsigned long adr, page; + + /* Round it off to PAGE_SIZE */ + size += (PAGE_SIZE - 1); + size &= ~(PAGE_SIZE - 1); + if (mem) + { + adr=(unsigned long) mem; + while (size > 0) + { + page = kvirt_to_pa(adr); + mem_map_unreserve(virt_to_page(__va(page))); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + vfree(mem); } - vfree(mem); } + static int pwc_allocate_buffers(struct pwc_device *pdev) { int i; @@ -294,6 +281,7 @@ Err("Failed to allocate iso buffer %d.\n", i); return -ENOMEM; } + Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf); pdev->sbuf[i].data = kbuf; memset(kbuf, 0, ISO_BUFFER_SIZE); } @@ -306,19 +294,21 @@ Err("Failed to allocate frame buffer structure.\n"); return -ENOMEM; } + Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf); pdev->fbuf = kbuf; memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf)); } /* 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; } + Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf); pdev->fbuf[i].data = kbuf; - memset(kbuf, 0, FRAME_SIZE); + memset(kbuf, 128, PWC_FRAME_SIZE); } } @@ -330,23 +320,24 @@ Err("Failed to allocate decompress table.\n"); return -ENOMEM; } + Trace(TRACE_MEMORY, "Allocated decompress table %p.\n", kbuf); } pdev->decompress_data = kbuf; /* Allocate image buffer; double buffer for mmap() */ - kbuf = rvmalloc(default_mbufs * pdev->view_max.size * 4); + kbuf = rvmalloc(default_mbufs * pdev->len_per_image); if (kbuf == NULL) { Err("Failed to allocate image buffer(s).\n"); return -ENOMEM; } + Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf); pdev->image_data = kbuf; for (i = 0; i < default_mbufs; i++) - pdev->image_ptr[i] = kbuf + (i * pdev->view_max.size * 4); + pdev->image_ptr[i] = kbuf + i * pdev->len_per_image; for (; i < MAX_IMAGES; i++) pdev->image_ptr[i] = NULL; Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n"); - return 0; } @@ -366,18 +357,18 @@ #endif /* Release Iso-pipe buffers */ - Trace(TRACE_MEMORY, "Freeing ISO buffers.\n"); for (i = 0; i < MAX_ISO_BUFS; i++) if (pdev->sbuf[i].data != NULL) { + Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data); kfree(pdev->sbuf[i].data); pdev->sbuf[i].data = NULL; } /* The same for frame buffers */ - Trace(TRACE_MEMORY, "Freeing frame buffers.\n"); if (pdev->fbuf != NULL) { for (i = 0; i < default_fbufs; i++) { if (pdev->fbuf[i].data != NULL) { + Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data); vfree(pdev->fbuf[i].data); pdev->fbuf[i].data = NULL; } @@ -387,17 +378,18 @@ } /* Intermediate decompression buffer & tables */ - Trace(TRACE_MEMORY, "Freeing decompression buffer\n"); if (pdev->decompress_data != NULL) { + Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data); kfree(pdev->decompress_data); pdev->decompress_data = NULL; } pdev->decompressor = NULL; /* Release image buffers */ - Trace(TRACE_MEMORY, "Freeing image buffers\n"); - if (pdev->image_data != NULL) - rvfree(pdev->image_data, default_mbufs * pdev->view_max.size * 4); + if (pdev->image_data != NULL) { + Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data); + rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); + } pdev->image_data = NULL; Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); } @@ -461,7 +453,8 @@ */ static inline int pwc_next_fill_frame(struct pwc_device *pdev) { - int ret, flags; + int ret; + unsigned long flags; ret = 0; spin_lock_irqsave(&pdev->ptrlock, flags); @@ -512,7 +505,8 @@ */ static void pwc_reset_buffers(struct pwc_device *pdev) { - int i, flags; + int i; + unsigned long flags; spin_lock_irqsave(&pdev->ptrlock, flags); pdev->full_frames = NULL; @@ -541,7 +535,8 @@ */ static int pwc_handle_frame(struct pwc_device *pdev) { - int ret = 0, flags; + int ret = 0; + unsigned long flags; spin_lock_irqsave(&pdev->ptrlock, flags); /* First grab our read_frame; this is removed from all lists, so @@ -610,6 +605,7 @@ pwc_set_image_buffer_size(pdev); return 0; } + Trace(TRACE_READ, "Palette %d not supported.\n", pal); return -1; } @@ -642,7 +638,17 @@ return; } if (urb->status != -EINPROGRESS && urb->status != 0) { - Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d.\n", urb->status); + char *errmsg; + + errmsg = "Unknown"; + switch(urb->status) { + case -ENOSR: errmsg = "Buffer error (overrun)"; break; + case -EPIPE: errmsg = "Babble/stalled (bad cable?)"; break; + case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break; + case -EILSEQ: errmsg = "CRC/Timeout"; break; + case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; + } + Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); return; } @@ -739,9 +745,9 @@ pdev->vframes_dumped++; if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) { if (pdev->vframes_dumped < 20) - Info("Dumping frame %d.\n", pdev->vframe_count); + Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count); if (pdev->vframes_dumped == 20) - Info("Dumping frame %d (last message).\n", pdev->vframe_count); + Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count); } } fbuf = pdev->fill_frame; @@ -1104,7 +1110,7 @@ if (pdev == NULL) return -EFAULT; if (pdev->unplugged) { - Debug("pwc_video_read: Device got unplugged (1).\n"); + Info("pwc_video_read: Device got unplugged (1).\n"); return -EPIPE; /* unplugged device! */ } @@ -1166,7 +1172,7 @@ poll_wait(file, &pdev->frameq, wait); if (pdev->unplugged) { - Debug("pwc_video_poll: Device got unplugged.\n"); + Info("pwc_video_poll: Device got unplugged.\n"); return POLLERR; } if (pdev->full_frames != NULL) /* we have frames waiting */ @@ -1370,10 +1376,10 @@ int i; memset(&vm, 0, sizeof(vm)); - vm.size = default_mbufs * pdev->view_max.size * 4; - vm.frames = default_mbufs; /* double buffering should be enough */ + vm.size = default_mbufs * pdev->len_per_image; + vm.frames = default_mbufs; /* double buffering should be enough for most applications */ for (i = 0; i < default_mbufs; i++) - vm.offsets[i] = i * pdev->view_max.size * 4; + vm.offsets[i] = i * pdev->len_per_image; if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) return -EFAULT; @@ -1546,11 +1552,10 @@ unsigned long start = (unsigned long)adr; unsigned long page, pos; - Trace(TRACE_READ, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size); + Trace(TRACE_MEMORY, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size); pdev = vdev->priv; /* FIXME - audit mmap during a read */ - pos = (unsigned long)pdev->image_data; while (size > 0) { page = kvirt_to_pa(pos); @@ -1651,7 +1656,18 @@ break; } } - else return NULL; /* Not Philips or Askey, for sure. */ + else if (vendor_id == 0x046d) { + switch(product_id) { + case 0x08b0: + Info("Logitech QuickCam 3000 Pro detected.\n"); + type_id = 730; + break; + default: + return NULL; + break; + } + } + else return NULL; /* Not Philips or Askey, for sure. */ if (udev->descriptor.bNumConfigurations > 1) Info("Warning: more than 1 configuration available.\n"); @@ -1718,6 +1734,7 @@ { struct pwc_device *pdev; + lock_kernel(); free_mem_leak(); pdev = (struct pwc_device *)ptr; @@ -1770,6 +1787,7 @@ } } pdev->udev = NULL; + unlock_kernel(); kfree(pdev); } @@ -1807,6 +1825,7 @@ MODULE_DESCRIPTION("Philips USB webcam driver"); MODULE_AUTHOR("Nemosoft Unv. "); +MODULE_LICENSE("GPL"); static int __init usb_pwc_init(void) { @@ -1847,8 +1866,6 @@ default_palette = VIDEO_PALETTE_YUV420P; else { Err("Palette not recognized: try palette=yuv420 or yuv420p.\n"); - Info("Download the driver from http://www.smcc.demon.nl/webcam/ for in kernel\n"); - Info("format conversion support.\n"); return -EINVAL; } Info("Default palette set to %d.\n", default_palette); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/pwc-ioctl.h linux/drivers/usb/pwc-ioctl.h --- v2.4.9/linux/drivers/usb/pwc-ioctl.h Tue May 22 10:25:36 2001 +++ linux/drivers/usb/pwc-ioctl.h Sat Sep 15 22:21:43 2001 @@ -1,3 +1,6 @@ +#ifndef PWC_IOCTL_H +#define PWC_IOCTL_H + /* (C) 2001 Nemosoft Unv. webcam@smcc.demon.nl This program is free software; you can redistribute it and/or modify @@ -15,8 +18,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PWC_IOCTL_H -#define PWC_IOCTL_H +/* + Changes + 2001/08/03 Alvarado Added ioctl constants to access methods for + changing white balance and red/blue gains + */ /* These are private ioctl() commands, specific for the Philips webcams. They contain functions not found in other webcams, and settings not @@ -46,6 +52,30 @@ #define PWC_FPS_SNAPSHOT 0x00400000 +/* pwc_whitebalance.mode values */ +#define PWC_WB_INDOOR 0 +#define PWC_WB_OUTDOOR 1 +#define PWC_WB_FL 2 +#define PWC_WB_MANUAL 3 +#define PWC_WB_AUTO 4 + +/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). + Set mode to one of the PWC_WB_* values above. + *red and *blue are the respective gains of these colour components inside + the camera; range 0..65535 + When mode == PWC_WB_MANUAL, manual_red and manual_blue are set or read; + otherwise undefined. + read_red and read_blue are read-only. +*/ + +struct pwc_whitebalance +{ + int mode; + int manual_red, manual_blue; /* R/W */ + int read_red, read_blue; /* R/O */ +}; + + /* Restore user settings */ #define VIDIOCPWCRUSER _IO('v', 192) /* Save user settings */ @@ -71,5 +101,15 @@ #define VIDIOCPWCGAGC _IOR('v', 200, int) /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */ #define VIDIOCPWCSSHUTTER _IOW('v', 201, int) + + /* Color compensation (Auto White Balance) */ +#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance) +#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance) + + /* Turn LED on/off ; int range 0..65535 */ +#define VIDIOCPWCSLED _IOW('v', 205, int) + + /* Get state of LED; int range 0..65535 */ +#define VIDIOCPWCGLED _IOR('v', 205, int) #endif diff -u --recursive --new-file v2.4.9/linux/drivers/usb/pwc-misc.c linux/drivers/usb/pwc-misc.c --- v2.4.9/linux/drivers/usb/pwc-misc.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/pwc-misc.c Sat Sep 15 22:21:43 2001 @@ -97,6 +97,8 @@ } pdev->view_min.size = pdev->view_min.x * pdev->view_min.y; pdev->view_max.size = pdev->view_max.x * pdev->view_max.y; + /* length of image, in YUV format */ + pdev->len_per_image = (pdev->view_max.size * 3) / 2; } 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 Sat Sep 15 22:21:43 2001 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -33,9 +34,10 @@ #define PWC_MAGIC 0x89DC10ABUL #undef PWC_MAGIC -/* Debugging info on/off */ +/* Turn some debugging options on/off */ #define PWC_DEBUG 0 +/* Trace certain actions in the driver */ #define TRACE_MODULE 0x0001 #define TRACE_PROBE 0x0002 #define TRACE_OPEN 0x0004 @@ -58,8 +60,8 @@ /* Version block */ #define PWC_MAJOR 8 -#define PWC_MINOR 1 -#define PWC_VERSION "8.1" +#define PWC_MINOR 2 +#define PWC_VERSION "8.2" #define PWC_NAME "pwc" /* Turn certain features on/off */ @@ -77,7 +79,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 @@ -184,6 +186,7 @@ void *image_data; /* total buffer, which is subdivided into ... */ void *image_ptr[MAX_IMAGES]; /* ...several images... */ int fill_image; /* ...which are rotated. */ + int len_per_image; /* length per image */ int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */ int image_used[MAX_IMAGES]; /* For MCAPTURE and SYNC */ 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 Fri Sep 14 14:04:07 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 [] = { @@ -529,4 +546,5 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c --- v2.4.9/linux/drivers/usb/scanner.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/scanner.c Mon Sep 17 22:52:35 2001 @@ -228,6 +228,9 @@ * - Added Epson Perfection 1640SU and 1640SU Photo. Thanks to * Jean-Luc . * + * 0.4.6 08/16/2001 Yves Duret + * - added devfs support (from printer.c) + * * TODO * * - Performance @@ -579,6 +582,100 @@ return ret ? ret : bytes_read; } +#ifdef SCN_IOCTL +static int +ioctl_scanner(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_device *dev; + + int result; + + kdev_t scn_minor; + + scn_minor = USB_SCN_MINOR(inode); + + if (!p_scn_table[scn_minor]) { + err("ioctl_scanner(%d): invalid scn_minor", scn_minor); + return -ENODEV; + } + + dev = p_scn_table[scn_minor]->scn_dev; + + switch (cmd) + { + case IOCTL_SCANNER_VENDOR : + return (put_user(dev->descriptor.idVendor, (unsigned int *) arg)); + case IOCTL_SCANNER_PRODUCT : + return (put_user(dev->descriptor.idProduct, (unsigned int *) arg)); + case PV8630_IOCTL_INREQUEST : + { + struct { + __u8 data; + __u8 request; + __u16 value; + __u16 index; + } args; + + if (copy_from_user(&args, (void *)arg, sizeof(args))) + return -EFAULT; + + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + args.request, USB_TYPE_VENDOR| + USB_RECIP_DEVICE|USB_DIR_IN, + args.value, args.index, &args.data, + 1, HZ*5); + + dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index, args.request); + + if (copy_to_user((void *)arg, &args, sizeof(args))) + return -EFAULT; + + dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result); + + return result; + } + case PV8630_IOCTL_OUTREQUEST : + { + struct { + __u8 request; + __u16 value; + __u16 index; + } args; + + if (copy_from_user(&args, (void *)arg, sizeof(args))) + return -EFAULT; + + dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x args.request:%x\n", scn_minor, args.value, args.index, args.request); + + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + args.request, USB_TYPE_VENDOR| + USB_RECIP_DEVICE|USB_DIR_OUT, + args.value, args.index, NULL, + 0, HZ*5); + + dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result); + + return result; + } + default: + return -ENOTTY; + } + return 0; +} +#endif /* SCN_IOCTL */ + +static struct +file_operations usb_scanner_fops = { + read: read_scanner, + write: write_scanner, +#ifdef SCN_IOCTL + ioctl: ioctl_scanner, +#endif /* SCN_IOCTL */ + open: open_scanner, + release: close_scanner, +}; + static void * probe_scanner(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) @@ -813,6 +910,14 @@ init_MUTEX(&(scn->gen_lock)); + /* if we have devfs, create with perms=660 */ + scn->devfs = devfs_register(usb_devfs_handle, "scanner", + DEVFS_FL_DEFAULT, USB_MAJOR, + SCN_BASE_MNR + scn_minor, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | + S_IWGRP, &usb_scanner_fops, NULL); + + return p_scn_table[scn_minor] = scn; } @@ -828,6 +933,8 @@ usb_driver_release_interface(&scanner_driver, &scn->scn_dev->actconfig->interface[scn->ifnum]); + devfs_unregister (scn->devfs); + kfree(scn->ibuf); kfree(scn->obuf); @@ -836,99 +943,6 @@ kfree (scn); } -#ifdef SCN_IOCTL -static int -ioctl_scanner(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct usb_device *dev; - - int result; - - kdev_t scn_minor; - - scn_minor = USB_SCN_MINOR(inode); - - if (!p_scn_table[scn_minor]) { - err("ioctl_scanner(%d): invalid scn_minor", scn_minor); - return -ENODEV; - } - - dev = p_scn_table[scn_minor]->scn_dev; - - switch (cmd) - { - case IOCTL_SCANNER_VENDOR : - return (put_user(dev->descriptor.idVendor, (unsigned int *) arg)); - case IOCTL_SCANNER_PRODUCT : - return (put_user(dev->descriptor.idProduct, (unsigned int *) arg)); - case PV8630_IOCTL_INREQUEST : - { - struct { - __u8 data; - __u8 request; - __u16 value; - __u16 index; - } args; - - if (copy_from_user(&args, (void *)arg, sizeof(args))) - return -EFAULT; - - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - args.request, USB_TYPE_VENDOR| - USB_RECIP_DEVICE|USB_DIR_IN, - args.value, args.index, &args.data, - 1, HZ*5); - - dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index, args.request); - - if (copy_to_user((void *)arg, &args, sizeof(args))) - return -EFAULT; - - dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result); - - return result; - } - case PV8630_IOCTL_OUTREQUEST : - { - struct { - __u8 request; - __u16 value; - __u16 index; - } args; - - if (copy_from_user(&args, (void *)arg, sizeof(args))) - return -EFAULT; - - dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x args.request:%x\n", scn_minor, args.value, args.index, args.request); - - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - args.request, USB_TYPE_VENDOR| - USB_RECIP_DEVICE|USB_DIR_OUT, - args.value, args.index, NULL, - 0, HZ*5); - - dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result); - - return result; - } - default: - return -ENOTTY; - } - return 0; -} -#endif /* SCN_IOCTL */ - -static struct -file_operations usb_scanner_fops = { - read: read_scanner, - write: write_scanner, -#ifdef SCN_IOCTL - ioctl: ioctl_scanner, -#endif /* SCN_IOCTL */ - open: open_scanner, - release: close_scanner, -}; static struct usb_driver scanner_driver = { diff -u --recursive --new-file v2.4.9/linux/drivers/usb/scanner.h linux/drivers/usb/scanner.h --- v2.4.9/linux/drivers/usb/scanner.h Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/scanner.h Mon Sep 17 22:52:35 2001 @@ -5,6 +5,8 @@ * * David E. Nelson (dnelson@jump.net) * + * 08/16/2001 added devfs support Yves Duret + * * 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 @@ -31,6 +33,7 @@ #include #include #include +#include // #define DEBUG @@ -40,6 +43,7 @@ MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson"); MODULE_DESCRIPTION("USB Scanner Driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(vendor, "i"); MODULE_PARM_DESC(vendor, "User specified USB idVendor"); @@ -174,6 +178,7 @@ struct scn_usb_data { struct usb_device *scn_dev; + devfs_handle_t devfs; /* devfs device */ struct urb scn_irq; unsigned int ifnum; /* Interface number of the USB device */ kdev_t scn_minor; /* Scanner minor - used in disconnect() */ @@ -190,3 +195,5 @@ static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */}; static struct usb_driver scanner_driver; + +extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */ 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 14 14:27:10 2001 @@ -25,7 +25,7 @@ * - Jeroen Vreeken */ -static const char version[] = "0.22"; +static const char version[] = "0.23"; #include #include @@ -66,6 +66,7 @@ MODULE_AUTHOR("Jeroen Vreeken "); MODULE_DESCRIPTION("SE401 USB Camera Driver"); +MODULE_LICENSE("GPL"); MODULE_PARM(flickerless, "i"); MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); MODULE_PARM(video_nr, "i"); @@ -1034,8 +1035,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 +1055,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 +1083,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 +1200,7 @@ return -EINVAL; if (se401_set_size(se401, vw.width, vw.height)) return -EINVAL; - + return 0; } case VIDIOCGWIN: @@ -1280,7 +1275,7 @@ if(frame <0 || frame >= SE401_NUMFRAMES) return -EINVAL; - + ret=se401_newframe(se401, frame); se401->frame[frame].grabstate=FRAME_UNUSED; return ret; @@ -1350,12 +1345,11 @@ 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; } @@ -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 Fri Sep 14 14:41:56 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 @@ -30,6 +30,7 @@ dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL fi diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- v2.4.9/linux/drivers/usb/serial/Makefile Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/Makefile Fri Sep 14 14:41:56 2001 @@ -11,6 +11,7 @@ obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o +obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_KEYSPAN) += keyspan.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o 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 Fri Sep 14 14:04:07 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 */ @@ -625,6 +626,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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 Fri Sep 14 14:04:07 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); } @@ -514,6 +515,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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 Fri Sep 14 14:04:07 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(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(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(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,8 @@ 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( count, port->bulk_out_size-2 ); + count = min( 64, count); if( from_user && copy_from_user( user_buf, buf, count ) ) { return( -EFAULT ); } @@ -1308,7 +1304,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(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 +1930,7 @@ if( throttled ) { - len = MIN( len, + len = min( len, DIGI_IN_BUF_SIZE - priv->dp_in_buf_len ); if( len > 0 ) { @@ -1947,7 +1943,7 @@ } else { - len = MIN( len, TTY_FLIPBUF_SIZE - tty->flip.count ); + len = min( len, TTY_FLIPBUF_SIZE - tty->flip.count ); if( len > 0 ) { memcpy( tty->flip.char_buf_ptr, data, len ); @@ -2096,6 +2092,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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 Fri Sep 14 14:04:07 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 (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; @@ -661,6 +665,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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 Fri Sep 14 14:04:07 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, @@ -1002,6 +1003,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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 Fri Sep 14 14:04:07 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 ((unsigned 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 (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 (bytesleft, count); memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf); fifo->tail += firsthalf; fifo->count -= firsthalf; @@ -3101,6 +3103,7 @@ /* Module information */ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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/io_usbvend.h linux/drivers/usb/serial/io_usbvend.h --- v2.4.9/linux/drivers/usb/serial/io_usbvend.h Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/serial/io_usbvend.h Mon Sep 10 20:32:37 2001 @@ -115,7 +115,7 @@ // TxCredits value below which driver won't bother sending (to prevent too many small writes). // Send only if above 25% -#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit) (max(int, ((InitialCredit) / 4), EDGE_FW_BULK_MAX_PACKET_SIZE)) +#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit) (max(((InitialCredit) / 4), EDGE_FW_BULK_MAX_PACKET_SIZE)) #define EDGE_FW_BULK_MAX_PACKET_SIZE 64 // Max Packet Size for Bulk In Endpoint (EP1) #define EDGE_FW_BULK_READ_BUFFER_SIZE 1024 // Size to use for Bulk reads 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 Fri Sep 14 14:04:07 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); } @@ -1718,6 +1719,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c --- v2.4.9/linux/drivers/usb/serial/keyspan_pda.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/keyspan_pda.c Fri Sep 14 14:41:56 2001 @@ -1,5 +1,5 @@ /* - * USB Keyspan PDA Converter driver + * USB Keyspan PDA / Xircom / Entregra Converter driver * * Copyright (c) 1999 - 2001 Greg Kroah-Hartman * Copyright (c) 1999, 2000 Brian Warner @@ -12,6 +12,14 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (09/07/2001) gkh + * cleaned up the Xircom support. Added ids for Entregra device which is + * the same as the Xircom device. Enabled the code to be compiled for + * either Xircom or Keyspan devices. + * + * (08/11/2001) Cristian M. Craciunescu + * support for Xircom PGSDB9 + * * (05/31/2001) gkh * switched from using spinlock to a semaphore, which fixes lots of problems. * @@ -88,13 +96,32 @@ __u8 data[16]; }; +/* make a simple define to handle if we are compiling keyspan_pda or xircom support */ +#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE) + #define KEYSPAN +#else + #undef KEYSPAN +#endif +#if defined(CONFIG_USB_SERIAL_XIRCOM) || defined(CONFIG_USB_SERIAL_XIRCOM_MODULE) + #define XIRCOM +#else + #undef XIRCOM +#endif + +#ifdef KEYSPAN #include "keyspan_pda_fw.h" +#endif + +#ifdef XIRCOM +#include "xircom_pgs_fw.h" +#endif + #include "usb-serial.h" /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "Brian Warner " #define DRIVER_DESC "USB Keyspan PDA Converter driver" @@ -105,12 +132,25 @@ struct tq_struct unthrottle_task; }; + #define KEYSPAN_VENDOR_ID 0x06cd #define KEYSPAN_PDA_FAKE_ID 0x0103 #define KEYSPAN_PDA_ID 0x0104 /* no clue */ +/* For Xircom PGSDB9 and older Entregra version of the same device */ +#define XIRCOM_VENDOR_ID 0x085a +#define XIRCOM_FAKE_ID 0x8027 +#define ENTREGRA_VENDOR_ID 0x1645 +#define ENTREGRA_FAKE_ID 0x8093 + static __devinitdata struct usb_device_id id_table_combined [] = { +#ifdef KEYSPAN { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) }, +#endif +#ifdef XIRCOM + { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) }, + { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) }, +#endif { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_ID) }, { } /* Terminating entry */ }; @@ -122,10 +162,24 @@ { } /* Terminating entry */ }; +#ifdef KEYSPAN static __devinitdata struct usb_device_id id_table_fake [] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) }, { } /* Terminating entry */ }; +#endif + +#ifdef XIRCOM +static __devinitdata struct usb_device_id id_table_fake_xircom [] = { + { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) }, + { } +}; + +static __devinitdata struct usb_device_id id_table_fake_entregra [] = { + { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) }, + { } +}; +#endif static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) { @@ -709,12 +763,25 @@ static int keyspan_pda_fake_startup (struct usb_serial *serial) { int response; - const struct ezusb_hex_record *record; + const struct ezusb_hex_record *record = NULL; /* download the firmware here ... */ response = ezusb_set_reset(serial, 1); - record = &keyspan_pda_firmware[0]; +#ifdef KEYSPAN + if (serial->dev->descriptor.idVendor == KEYSPAN_VENDOR_ID) + record = &keyspan_pda_firmware[0]; +#endif +#ifdef XIRCOM + if ((serial->dev->descriptor.idVendor == XIRCOM_VENDOR_ID) || + (serial->dev->descriptor.idVendor == ENTREGRA_VENDOR_ID)) + record = &xircom_pgs_firmware[0]; +#endif + if (record == NULL) { + err(__FUNCTION__": unknown vendor, aborting."); + return -ENODEV; + } + while(record->address != 0xffff) { response = ezusb_writememory(serial, record->address, (unsigned char *)record->data, @@ -770,7 +837,8 @@ kfree(serial->port[0].private); } -struct usb_serial_device_type keyspan_pda_fake_device = { +#ifdef KEYSPAN +static struct usb_serial_device_type keyspan_pda_fake_device = { name: "Keyspan PDA - (prerenumeration)", id_table: id_table_fake, needs_interrupt_in: DONT_CARE, @@ -782,8 +850,37 @@ num_ports: 1, startup: keyspan_pda_fake_startup, }; +#endif + +#ifdef XIRCOM +static struct usb_serial_device_type xircom_pgs_fake_device = { + name: "Xircom PGS - (prerenumeration)", + id_table: id_table_fake_xircom, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + startup: keyspan_pda_fake_startup, +}; -struct usb_serial_device_type keyspan_pda_device = { +static struct usb_serial_device_type entregra_pgs_fake_device = { + name: "Entregra PGS - (prerenumeration)", + id_table: id_table_fake_entregra, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + startup: keyspan_pda_fake_startup, +}; +#endif + +static struct usb_serial_device_type keyspan_pda_device = { name: "Keyspan PDA", id_table: id_table_std, needs_interrupt_in: MUST_HAVE, @@ -812,17 +909,29 @@ static int __init keyspan_pda_init (void) { - usb_serial_register (&keyspan_pda_fake_device); usb_serial_register (&keyspan_pda_device); - info(DRIVER_VERSION ":" DRIVER_DESC); +#ifdef KEYSPAN + usb_serial_register (&keyspan_pda_fake_device); +#endif +#ifdef XIRCOM + usb_serial_register (&xircom_pgs_fake_device); + usb_serial_register (&entregra_pgs_fake_device); +#endif + info(DRIVER_DESC " " DRIVER_VERSION); return 0; } static void __exit keyspan_pda_exit (void) { - usb_serial_deregister (&keyspan_pda_fake_device); usb_serial_deregister (&keyspan_pda_device); +#ifdef KEYSPAN + usb_serial_deregister (&keyspan_pda_fake_device); +#endif +#ifdef XIRCOM + usb_serial_deregister (&entregra_pgs_fake_device); + usb_serial_deregister (&xircom_pgs_fake_device); +#endif } @@ -831,6 +940,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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 Fri Sep 14 14:04:07 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 */ @@ -892,6 +896,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); #ifdef FIX_WRITE_RETURN_CODE_PROBLEM MODULE_PARM(write_blocking, "i"); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c --- v2.4.9/linux/drivers/usb/serial/omninet.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/omninet.c Fri Sep 14 14:04:07 2001 @@ -420,6 +420,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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 14 14:04:07 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; } @@ -838,6 +567,7 @@ module_exit(pl2303_exit); MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h --- v2.4.9/linux/drivers/usb/serial/usb-serial.h Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/usb-serial.h Fri Sep 14 14:41:56 2001 @@ -153,12 +153,22 @@ extern void usb_serial_deregister(struct usb_serial_device_type *device); /* determine if we should include the EzUSB loader functions */ -#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_WHITEHEAT) || defined(CONFIG_USB_SERIAL_KEYSPAN) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE) || defined(CONFIG_USB_SERIAL_WHITEHEAT_MODULE) || defined(CONFIG_USB_SERIAL_KEYSPAN_MODULE) - #define USES_EZUSB_FUNCTIONS - extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest); - extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); -#else - #undef USES_EZUSB_FUNCTIONS +#undef USES_EZUSB_FUNCTIONS +#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE) + #define USES_EZUSB_FUNCTIONS +#endif +#if defined(CONFIG_USB_SERIAL_XIRCOM) || defined(CONFIG_USB_SERIAL_XIRCOM_MODULE) + #define USES_EZUSB_FUNCTIONS +#endif +#if defined(CONFIG_USB_SERIAL_KEYSPAN) || defined(CONFIG_USB_SERIAL_KEYSPAN_MODULE) + #define USES_EZUSB_FUNCTIONS +#endif +#if defined(CONFIG_USB_SERIAL_WHITEHEAT) || defined(CONFIG_USB_SERIAL_WHITEHEAT_MODULE) + #define USES_EZUSB_FUNCTIONS +#endif +#ifdef USES_EZUSB_FUNCTIONS +extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest); +extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); #endif 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 Fri Sep 14 14:16:08 2001 @@ -15,6 +15,10 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (09/13/2001) gkh + * Moved generic driver initialize after we have registered with the USB + * core. Thanks to Randy Dunlap for pointing this problem out. + * * (07/03/2001) gkh * Fixed module paramater size. Thanks to John Brockmeyer for the pointer. * Fixed vendor and product getting defined through the MODULE_PARM macro @@ -307,8 +311,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 +854,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 +1263,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(num_bulk_in, num_bulk_out); + max_endpoints = max(max_endpoints, num_interrupt_in); + max_endpoints = max(max_endpoints, (int)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]; @@ -1427,14 +1430,6 @@ return -1; } -#ifdef CONFIG_USB_SERIAL_GENERIC - generic_device_ids[0].idVendor = vendor; - generic_device_ids[0].idProduct = product; - generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; - /* register our generic driver with ourselves */ - usb_serial_register (&generic_device); -#endif - /* register the USB driver */ result = usb_register(&usb_serial_driver); if (result < 0) { @@ -1443,6 +1438,14 @@ return -1; } +#ifdef CONFIG_USB_SERIAL_GENERIC + generic_device_ids[0].idVendor = vendor; + generic_device_ids[0].idProduct = product; + generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; + /* register our generic driver with ourselves */ + usb_serial_register (&generic_device); +#endif + info(DRIVER_DESC " " DRIVER_VERSION); return 0; @@ -1513,6 +1516,7 @@ /* Module information */ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); @@ -1524,4 +1528,3 @@ MODULE_PARM(product, "h"); MODULE_PARM_DESC(product, "User specified USB idProduct"); #endif - 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 14 14:04:07 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 (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); @@ -801,6 +877,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); 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 Fri Sep 14 14:04:07 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; @@ -675,6 +677,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/xircom_pgs.S linux/drivers/usb/serial/xircom_pgs.S --- v2.4.9/linux/drivers/usb/serial/xircom_pgs.S Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/xircom_pgs.S Fri Sep 14 14:41:56 2001 @@ -0,0 +1,1192 @@ +/* $Id: loop.s,v 1.23 2000/03/20 09:49:06 warner Exp $ + * + * Firmware for the Keyspan PDA Serial Adapter, a USB serial port based on + * the EzUSB microcontroller. + * + * (C) Copyright 2000 Brian Warner + * + * 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. + * + * "Keyspan PDA Serial Adapter" is probably a copyright of Keyspan, the + * company. + * + * This serial adapter is basically an EzUSB chip and an RS-232 line driver + * in a little widget that has a DB-9 on one end and a USB plug on the other. + * It uses the EzUSB's internal UART0 (using the pins from Port C) and timer2 + * as a baud-rate generator. The wiring is: + * PC0/RxD0 <- rxd (DB9 pin 2) PC4 <- dsr pin 6 + * PC1/TxD0 -> txd pin 3 PC5 <- ri pin 9 + * PC2 -> rts pin 7 PC6 <- dcd pin 1 + * PC3 <- cts pin 8 PC7 -> dtr pin 4 + * PB1 -> line driver standby + * + * The EzUSB register constants below come from their excellent documentation + * and sample code (which used to be available at www.anchorchips.com, but + * that has now been absorbed into Cypress' site and the CD-ROM contents + * don't appear to be available online anymore). If we get multiple + * EzUSB-based drivers into the kernel, it might be useful to pull them out + * into a separate .h file. + * + * THEORY OF OPERATION: + * + * There are two 256-byte ring buffers, one for tx, one for rx. + * + * EP2out is pure tx data. When it appears, the data is copied into the tx + * ring and serial transmission is started if it wasn't already running. The + * "tx buffer empty" interrupt may kick off another character if the ring + * still has data. If the host is tx-blocked because the ring filled up, + * it will request a "tx unthrottle" interrupt. If sending a serial character + * empties the ring below the desired threshold, we set a bit that will send + * up the tx unthrottle message as soon as the rx buffer becomes free. + * + * EP2in (interrupt) is used to send both rx chars and rx status messages + * (only "tx unthrottle" at this time) back up to the host. The first byte + * of the rx message indicates data (0) or status msg (1). Status messages + * are sent before any data. + * + * Incoming serial characters are put into the rx ring by the serial + * interrupt, and the EP2in buffer sent if it wasn't already in transit. + * When the EP2in buffer returns, the interrupt prompts us to send more + * rx chars (or status messages) if they are pending. + * + * Device control happens through "vendor specific" control messages on EP0. + * All messages are destined for the "Interface" (with the index always 0, + * so that if their two-port device might someday use similar firmware, we + * can use index=1 to refer to the second port). The messages defined are: + * + * bRequest = 0 : set baud/bits/parity + * 1 : unused + * 2 : reserved for setting HW flow control (CTSRTS) + * 3 : get/set "modem info" (pin states: DTR, RTS, DCD, RI, etc) + * 4 : set break (on/off) + * 5 : reserved for requesting interrupts on pin state change + * 6 : query buffer room or chars in tx buffer + * 7 : request tx unthrottle interrupt + * + * The host-side driver is set to recognize the device ID values stashed in + * serial EEPROM (0x06cd, 0x0103), program this firmware into place, then + * start it running. This firmware will use EzUSB's "renumeration" trick by + * simulating a bus disconnect, then reconnect with a different device ID + * (encoded in the desc_device descriptor below). The host driver then + * recognizes the new device ID and glues it to the real serial driver code. + * + * USEFUL DOCS: + * EzUSB Technical Reference Manual: + * 8051 manuals: everywhere, but try www.dalsemi.com because the EzUSB is + * basically the Dallas enhanced 8051 code. Remember that the EzUSB IO ports + * use totally different registers! + * USB 1.1 spec: www.usb.org + * + * HOW TO BUILD: + * gcc -x assembler-with-cpp -P -E -o keyspan_pda.asm keyspan_pda.s + * as31 -l keyspan_pda.asm + * mv keyspan_pda.obj keyspan_pda.hex + * perl ezusb_convert.pl keyspan_pda < keyspan_pda.hex > keyspan_pda_fw.h + * Get as31 from , and hack on it + * a bit to make it build. + * + * THANKS: + * Greg Kroah-Hartman, for coordinating the whole usb-serial thing. + * AnchorChips, for making such an incredibly useful little microcontroller. + * KeySpan, for making a handy, cheap ($40) widget that was so easy to take + * apart and trace with an ohmmeter. + * + * TODO: + * lots. grep for TODO. Interrupt safety needs stress-testing. Better flow + * control. Interrupting host upon change in DCD, etc, counting transitions. + * Need to find a safe device id to use (the one used by the Keyspan firmware + * under Windows would be ideal.. can anyone figure out what it is?). Parity. + * More baud rates. Oh, and the string-descriptor-length silicon bug + * workaround should be implemented, but I'm lazy, and the consequence is + * that the device name strings that show up in your kernel log will have + * lots of trailing binary garbage in them (appears as ????). Device strings + * should be made more accurate. + * + * Questions, bugs, patches to Brian. + * + * -Brian Warner + * + */ + +#define HIGH(x) (((x) & 0xff00) / 256) +#define LOW(x) ((x) & 0xff) + +#define dpl1 0x84 +#define dph1 0x85 +#define dps 0x86 + +;;; our bit assignments +#define TX_RUNNING 0 +#define DO_TX_UNTHROTTLE 1 + + ;; stack from 0x60 to 0x7f: should really set SP to 0x60-1, not 0x60 +#define STACK #0x60-1 + +#define EXIF 0x91 +#define EIE 0xe8 + .flag EUSB, EIE.0 + .flag ES0, IE.4 + +#define EP0CS #0x7fb4 +#define EP0STALLbit #0x01 +#define IN0BUF #0x7f00 +#define IN0BC #0x7fb5 +#define OUT0BUF #0x7ec0 +#define OUT0BC #0x7fc5 +#define IN2BUF #0x7e00 +#define IN2BC #0x7fb9 +#define IN2CS #0x7fb8 +#define OUT2BC #0x7fc9 +#define OUT2CS #0x7fc8 +#define OUT2BUF #0x7dc0 +#define IN4BUF #0x7d00 +#define IN4BC #0x7fbd +#define IN4CS #0x7fbc +#define OEB #0x7f9d +#define OUTB #0x7f97 +#define OEC #0x7f9e +#define OUTC #0x7f98 +#define PINSC #0x7f9b +#define PORTBCFG #0x7f94 +#define PORTCCFG #0x7f95 +#define OEA #0x7f9c +#define IN07IRQ #0x7fa9 +#define OUT07IRQ #0x7faa +#define IN07IEN #0x7fac +#define OUT07IEN #0x7fad +#define USBIRQ #0x7fab +#define USBIEN #0x7fae +#define USBBAV #0x7faf +#define USBCS #0x7fd6 +#define SUDPTRH #0x7fd4 +#define SUDPTRL #0x7fd5 +#define SETUPDAT #0x7fe8 + + ;; usb interrupt : enable is EIE.0 (0xe8), flag is EXIF.4 (0x91) + + .org 0 + ljmp start + ;; interrupt vectors + .org 23H + ljmp serial_int + .byte 0 + + .org 43H + ljmp USB_Jump_Table + .byte 0 ; filled in by the USB core + +;;; local variables. These are not initialized properly: do it by hand. + .org 30H +rx_ring_in: .byte 0 +rx_ring_out: .byte 0 +tx_ring_in: .byte 0 +tx_ring_out: .byte 0 +tx_unthrottle_threshold: .byte 0 + + .org 0x100H ; wants to be on a page boundary +USB_Jump_Table: + ljmp ISR_Sudav ; Setup Data Available + .byte 0 + ljmp 0 ; Start of Frame + .byte 0 + ljmp 0 ; Setup Data Loading + .byte 0 + ljmp 0 ; Global Suspend + .byte 0 + ljmp 0 ; USB Reset + .byte 0 + ljmp 0 ; Reserved + .byte 0 + ljmp 0 ; End Point 0 In + .byte 0 + ljmp 0 ; End Point 0 Out + .byte 0 + ljmp 0 ; End Point 1 In + .byte 0 + ljmp 0 ; End Point 1 Out + .byte 0 + ljmp ISR_Ep2in + .byte 0 + ljmp ISR_Ep2out + .byte 0 + + + .org 0x200 + +start: mov SP,STACK-1 ; set stack + ;; clear local variables + clr a + mov tx_ring_in, a + mov tx_ring_out, a + mov rx_ring_in, a + mov rx_ring_out, a + mov tx_unthrottle_threshold, a + clr TX_RUNNING + clr DO_TX_UNTHROTTLE + + ;; clear fifo with "fe" + mov r1, 0 + mov a, #0xfe + mov dptr, #tx_ring +clear_tx_ring_loop: + movx @dptr, a + inc dptr + djnz r1, clear_tx_ring_loop + + mov a, #0xfd + mov dptr, #rx_ring +clear_rx_ring_loop: + movx @dptr, a + inc dptr + djnz r1, clear_rx_ring_loop + +;;; turn on the RS-232 driver chip (bring the STANDBY pin low) +;;; on Xircom the STANDBY is wired to PB6 and PC4 + mov dptr, PORTBCFG + mov a, #0xBf + movx @dptr, a + mov dptr, PORTCCFG + mov a, #0xef + movx @dptr, a + + ;; set OEC.4 + mov a, #0x10 + mov dptr,OEC + movx @dptr,a + + ;; clear PC4 + mov a, #0x00 + mov dptr,OUTC + movx @dptr,a + + ;; set OEB.6 + mov a, #0x40 + mov dptr,OEB + movx @dptr,a + + ;; clear PB6 + mov a, #0x00 + mov dptr,OUTB + movx @dptr,a + + ;; set OEC.[17] + mov a, #0x82 + mov dptr,OEC + movx @dptr,a + + + ;; set PORTCCFG.[01] to route TxD0,RxD0 to serial port + mov dptr, PORTCCFG + mov a, #0x03 + movx @dptr, a + + ;; set up interrupts, autovectoring + ;; set BKPT + mov dptr, USBBAV + movx a,@dptr + setb acc.0 ; AVEN bit to 0 + movx @dptr, a + + mov a,#0x01 ; enable SUDAV: setup data available (for ep0) + mov dptr, USBIRQ + movx @dptr, a ; clear SUDAVI + mov dptr, USBIEN + movx @dptr, a + + mov dptr, IN07IEN + mov a,#0x04 ; enable IN2 int + movx @dptr, a + + mov dptr, OUT07IEN + mov a,#0x04 ; enable OUT2 int + movx @dptr, a + mov dptr, OUT2BC + movx @dptr, a ; arm OUT2 + +;; mov a, #0x84 ; turn on RTS, DTR +;; mov dptr,OUTC +;; movx @dptr, a + + mov a, #0x7 ; turn on DTR + mov dptr,USBBAV + movx @dptr, a + + mov a, #0x20 ; turn on the RED led + mov dptr,OEA + movx @dptr, a + + mov a, #0x80 ; turn on RTS + mov dptr,OUTC + movx @dptr, a + + ;; setup the serial port. 9600 8N1. + mov a,#0x53 ; mode 1, enable rx, clear int + mov SCON, a + ;; using timer2, in 16-bit baud-rate-generator mode + ;; (xtal 12MHz, internal fosc 24MHz) + ;; RCAP2H,RCAP2L = 65536 - fosc/(32*baud) + ;; 57600: 0xFFF2.F, say 0xFFF3 + ;; 9600: 0xFFB1.E, say 0xFFB2 + ;; 300: 0xF63C +#define BAUD 9600 +#define BAUD_TIMEOUT(rate) (65536 - (24 * 1000 * 1000) / (32 * rate)) +#define BAUD_HIGH(rate) HIGH(BAUD_TIMEOUT(rate)) +#define BAUD_LOW(rate) LOW(BAUD_TIMEOUT(rate)) + + mov T2CON, #030h ; rclk=1,tclk=1,cp=0,tr2=0(enable later) + mov r3, #5 + acall set_baud + setb TR2 + mov SCON, #050h + +#if 0 + mov r1, #0x40 + mov a, #0x41 +send: + mov SBUF, a + inc a + anl a, #0x3F + orl a, #0x40 +; xrl a, #0x02 +wait1: + jnb TI, wait1 + clr TI + djnz r1, send +;done: sjmp done + +#endif + + setb EUSB + setb EA + setb ES0 + ;acall dump_stat + + ;; hey, what say we RENUMERATE! (TRM p.62) + mov a, #0 + mov dps, a + mov dptr, USBCS + mov a, #0x02 ; DISCON=0, DISCOE=0, RENUM=1 + movx @dptr, a + ;; now presence pin is floating, simulating disconnect. wait 0.5s + mov r1, #46 +renum_wait1: + mov r2, #0 +renum_wait2: + mov r3, #0 +renum_wait3: + djnz r3, renum_wait3 + djnz r2, renum_wait2 + djnz r1, renum_wait1 ; wait about n*(256^2) 6MHz clocks + mov a, #0x06 ; DISCON=0, DISCOE=1, RENUM=1 + movx @dptr, a + ;; we are back online. the host device will now re-query us + + +main: sjmp main + + + +ISR_Sudav: + push dps + push dpl + push dph + push dpl1 + push dph1 + push acc + mov a,EXIF + clr acc.4 + mov EXIF,a ; clear INT2 first + mov dptr, USBIRQ ; clear USB int + mov a,#01h + movx @dptr,a + + ;; get request type + mov dptr, SETUPDAT + movx a, @dptr + mov r1, a ; r1 = bmRequestType + inc dptr + movx a, @dptr + mov r2, a ; r2 = bRequest + inc dptr + movx a, @dptr + mov r3, a ; r3 = wValueL + inc dptr + movx a, @dptr + mov r4, a ; r4 = wValueH + + ;; main switch on bmRequest.type: standard or vendor + mov a, r1 + anl a, #0x60 + cjne a, #0x00, setup_bmreq_type_not_standard + ;; standard request: now main switch is on bRequest + ljmp setup_bmreq_is_standard + +setup_bmreq_type_not_standard: + ;; a still has bmreq&0x60 + cjne a, #0x40, setup_bmreq_type_not_vendor + ;; Anchor reserves bRequest 0xa0-0xaf, we use small ones + ;; switch on bRequest. bmRequest will always be 0x41 or 0xc1 + cjne r2, #0x00, setup_ctrl_not_00 + ;; 00 is set baud, wValue[0] has baud rate index + lcall set_baud ; index in r3, carry set if error + jc setup_bmreq_type_not_standard__do_stall + ljmp setup_done_ack +setup_bmreq_type_not_standard__do_stall: + ljmp setup_stall +setup_ctrl_not_00: + cjne r2, #0x01, setup_ctrl_not_01 + ;; 01 is reserved for set bits (parity). TODO + ljmp setup_stall +setup_ctrl_not_01: + cjne r2, #0x02, setup_ctrl_not_02 + ;; 02 is set HW flow control. TODO + ljmp setup_stall +setup_ctrl_not_02: + cjne r2, #0x03, setup_ctrl_not_03 + ;; 03 is control pins (RTS, DTR). + ljmp control_pins ; will jump to setup_done_ack, + ; or setup_return_one_byte +setup_ctrl_not_03: + cjne r2, #0x04, setup_ctrl_not_04 + ;; 04 is send break (really "turn break on/off"). TODO + cjne r3, #0x00, setup_ctrl_do_break_on + ;; do break off: restore PORTCCFG.1 to reconnect TxD0 to serial port + mov dptr, PORTCCFG + movx a, @dptr + orl a, #0x02 + movx @dptr, a + ljmp setup_done_ack +setup_ctrl_do_break_on: + ;; do break on: clear PORTCCFG.0, set TxD high(?) (b1 low) + mov dptr, OUTC + movx a, @dptr + anl a, #0xfd ; ~0x02 + movx @dptr, a + mov dptr, PORTCCFG + movx a, @dptr + anl a, #0xfd ; ~0x02 + movx @dptr, a + ljmp setup_done_ack +setup_ctrl_not_04: + cjne r2, #0x05, setup_ctrl_not_05 + ;; 05 is set desired interrupt bitmap. TODO + ljmp setup_stall +setup_ctrl_not_05: + cjne r2, #0x06, setup_ctrl_not_06 + ;; 06 is query room + cjne r3, #0x00, setup_ctrl_06_not_00 + ;; 06, wValue[0]=0 is query write_room + mov a, tx_ring_out + setb c + subb a, tx_ring_in ; out-1-in = 255 - (in-out) + ljmp setup_return_one_byte +setup_ctrl_06_not_00: + cjne r3, #0x01, setup_ctrl_06_not_01 + ;; 06, wValue[0]=1 is query chars_in_buffer + mov a, tx_ring_in + clr c + subb a, tx_ring_out ; in-out + ljmp setup_return_one_byte +setup_ctrl_06_not_01: + ljmp setup_stall +setup_ctrl_not_06: + cjne r2, #0x07, setup_ctrl_not_07 + ;; 07 is request tx unthrottle interrupt + mov tx_unthrottle_threshold, r3; wValue[0] is threshold value + ljmp setup_done_ack +setup_ctrl_not_07: + ljmp setup_stall + +setup_bmreq_type_not_vendor: + ljmp setup_stall + + +setup_bmreq_is_standard: + cjne r2, #0x00, setup_breq_not_00 + ;; 00: Get_Status (sub-switch on bmRequestType: device, ep, int) + cjne r1, #0x80, setup_Get_Status_not_device + ;; Get_Status(device) + ;; are we self-powered? no. can we do remote wakeup? no + ;; so return two zero bytes. This is reusable +setup_return_two_zero_bytes: + mov dptr, IN0BUF + clr a + movx @dptr, a + inc dptr + movx @dptr, a + mov dptr, IN0BC + mov a, #2 + movx @dptr, a + ljmp setup_done_ack +setup_Get_Status_not_device: + cjne r1, #0x82, setup_Get_Status_not_endpoint + ;; Get_Status(endpoint) + ;; must get stall bit for ep[wIndexL], return two bytes, bit in lsb 0 + ;; for now: cheat. TODO + sjmp setup_return_two_zero_bytes +setup_Get_Status_not_endpoint: + cjne r1, #0x81, setup_Get_Status_not_interface + ;; Get_Status(interface): return two zeros + sjmp setup_return_two_zero_bytes +setup_Get_Status_not_interface: + ljmp setup_stall + +setup_breq_not_00: + cjne r2, #0x01, setup_breq_not_01 + ;; 01: Clear_Feature (sub-switch on wValueL: stall, remote wakeup) + cjne r3, #0x00, setup_Clear_Feature_not_stall + ;; Clear_Feature(stall). should clear a stall bit. TODO + ljmp setup_stall +setup_Clear_Feature_not_stall: + cjne r3, #0x01, setup_Clear_Feature_not_rwake + ;; Clear_Feature(remote wakeup). ignored. + ljmp setup_done_ack +setup_Clear_Feature_not_rwake: + ljmp setup_stall + +setup_breq_not_01: + cjne r2, #0x03, setup_breq_not_03 + ;; 03: Set_Feature (sub-switch on wValueL: stall, remote wakeup) + cjne r3, #0x00, setup_Set_Feature_not_stall + ;; Set_Feature(stall). Should set a stall bit. TODO + ljmp setup_stall +setup_Set_Feature_not_stall: + cjne r3, #0x01, setup_Set_Feature_not_rwake + ;; Set_Feature(remote wakeup). ignored. + ljmp setup_done_ack +setup_Set_Feature_not_rwake: + ljmp setup_stall + +setup_breq_not_03: + cjne r2, #0x06, setup_breq_not_06 + ;; 06: Get_Descriptor (s-switch on wValueH: dev, config[n], string[n]) + cjne r4, #0x01, setup_Get_Descriptor_not_device + ;; Get_Descriptor(device) + mov dptr, SUDPTRH + mov a, #HIGH(desc_device) + movx @dptr, a + mov dptr, SUDPTRL + mov a, #LOW(desc_device) + movx @dptr, a + ljmp setup_done_ack +setup_Get_Descriptor_not_device: + cjne r4, #0x02, setup_Get_Descriptor_not_config + ;; Get_Descriptor(config[n]) + cjne r3, #0x00, setup_stall; only handle n==0 + ;; Get_Descriptor(config[0]) + mov dptr, SUDPTRH + mov a, #HIGH(desc_config1) + movx @dptr, a + mov dptr, SUDPTRL + mov a, #LOW(desc_config1) + movx @dptr, a + ljmp setup_done_ack +setup_Get_Descriptor_not_config: + cjne r4, #0x03, setup_Get_Descriptor_not_string + ;; Get_Descriptor(string[wValueL]) + ;; if (wValueL >= maxstrings) stall + mov a, #((desc_strings_end-desc_strings)/2) + clr c + subb a,r3 ; a=4, r3 = 0..3 . if a<=0 then stall + jc setup_stall + jz setup_stall + mov a, r3 + add a, r3 ; a = 2*wValueL + mov dptr, #desc_strings + add a, dpl + mov dpl, a + mov a, #0 + addc a, dph + mov dph, a ; dph = desc_strings[a]. big endian! (handy) + ;; it looks like my adapter uses a revision of the EZUSB that + ;; contains "rev D errata number 8", as hinted in the EzUSB example + ;; code. I cannot find an actual errata description on the Cypress + ;; web site, but from the example code it looks like this bug causes + ;; the length of string descriptors to be read incorrectly, possibly + ;; sending back more characters than the descriptor has. The workaround + ;; is to manually send out all of the data. The consequence of not + ;; using the workaround is that the strings gathered by the kernel + ;; driver are too long and are filled with trailing garbage (including + ;; leftover strings). Writing this out by hand is a nuisance, so for + ;; now I will just live with the bug. + movx a, @dptr + mov r1, a + inc dptr + movx a, @dptr + mov r2, a + mov dptr, SUDPTRH + mov a, r1 + movx @dptr, a + mov dptr, SUDPTRL + mov a, r2 + movx @dptr, a + ;; done + ljmp setup_done_ack + +setup_Get_Descriptor_not_string: + ljmp setup_stall + +setup_breq_not_06: + cjne r2, #0x08, setup_breq_not_08 + ;; Get_Configuration. always 1. return one byte. + ;; this is reusable + mov a, #1 +setup_return_one_byte: + mov dptr, IN0BUF + movx @dptr, a + mov a, #1 + mov dptr, IN0BC + movx @dptr, a + ljmp setup_done_ack +setup_breq_not_08: + cjne r2, #0x09, setup_breq_not_09 + ;; 09: Set_Configuration. ignored. + ljmp setup_done_ack +setup_breq_not_09: + cjne r2, #0x0a, setup_breq_not_0a + ;; 0a: Get_Interface. get the current altsetting for int[wIndexL] + ;; since we only have one interface, ignore wIndexL, return a 0 + mov a, #0 + ljmp setup_return_one_byte +setup_breq_not_0a: + cjne r2, #0x0b, setup_breq_not_0b + ;; 0b: Set_Interface. set altsetting for interface[wIndexL]. ignored + ljmp setup_done_ack +setup_breq_not_0b: + ljmp setup_stall + + +setup_done_ack: + ;; now clear HSNAK + mov dptr, EP0CS + mov a, #0x02 + movx @dptr, a + sjmp setup_done +setup_stall: + ;; unhandled. STALL + ;EP0CS |= bmEPSTALL + mov dptr, EP0CS + movx a, @dptr + orl a, EP0STALLbit + movx @dptr, a + sjmp setup_done + +setup_done: + pop acc + pop dph1 + pop dpl1 + pop dph + pop dpl + pop dps + reti + +;;; ============================================================== + +set_baud: ; baud index in r3 + ;; verify a < 10 + mov a, r3 + jb ACC.7, set_baud__badbaud + clr c + subb a, #10 + jnc set_baud__badbaud + mov a, r3 + rl a ; a = index*2 + add a, #LOW(baud_table) + mov dpl, a + mov a, #HIGH(baud_table) + addc a, #0 + mov dph, a + ;; TODO: shut down xmit/receive + ;; TODO: wait for current xmit char to leave + ;; TODO: shut down timer to avoid partial-char glitch + movx a,@dptr ; BAUD_HIGH + mov RCAP2H, a + mov TH2, a + inc dptr + movx a,@dptr ; BAUD_LOW + mov RCAP2L, a + mov TL2, a + ;; TODO: restart xmit/receive + ;; TODO: reenable interrupts, resume tx if pending + clr c ; c=0: success + ret +set_baud__badbaud: + setb c ; c=1: failure + ret + +;;; ================================================== +control_pins: + cjne r1, #0x41, control_pins_in +control_pins_out: + ;TODO BKPT is DTR + mov a, r3 ; wValue[0] holds new bits: b7 is new RTS + xrl a, #0xff ; 1 means active, 0V, +12V ? + anl a, #0x80 + mov r3, a + mov dptr, OUTC + movx a, @dptr ; only change bit 7 + anl a, #0x7F ; ~0x84 + orl a, r3 + movx @dptr, a ; other pins are inputs, bits ignored + ljmp setup_done_ack +control_pins_in: + mov dptr, PINSC + movx a, @dptr + xrl a, #0xff + ljmp setup_return_one_byte + +;;; ======================================== + +ISR_Ep2in: + push dps + push dpl + push dph + push dpl1 + push dph1 + push acc + mov a,EXIF + clr acc.4 + mov EXIF,a ; clear INT2 first + mov dptr, IN07IRQ ; clear USB int + mov a,#04h + movx @dptr,a + + mov a, #0x20 ; Turn off the green LED + mov dptr,OEA + movx @dptr, a + + + ;; do stuff + lcall start_in + + mov a, #0x20 ; Turn off the green LED + mov dptr,OEA + movx @dptr, a + + + + pop acc + pop dph1 + pop dpl1 + pop dph + pop dpl + pop dps + reti + +ISR_Ep2out: + push dps + push dpl + push dph + push dpl1 + push dph1 + push acc + + mov a, #0x10 ; Turn the green LED + mov dptr,OEA + movx @dptr, a + + + + mov a,EXIF + clr acc.4 + mov EXIF,a ; clear INT2 first + mov dptr, OUT07IRQ ; clear USB int + mov a,#04h + movx @dptr,a + + ;; do stuff + + ;; copy data into buffer. for now, assume we will have enough space + mov dptr, OUT2BC ; get byte count + movx a,@dptr + mov r1, a + clr a + mov dps, a + mov dptr, OUT2BUF ; load DPTR0 with source + mov dph1, #HIGH(tx_ring) ; load DPTR1 with target + mov dpl1, tx_ring_in +OUT_loop: + movx a,@dptr ; read + inc dps ; switch to DPTR1: target + inc dpl1 ; target = tx_ring_in+1 + movx @dptr,a ; store + mov a,dpl1 + cjne a, tx_ring_out, OUT_no_overflow + sjmp OUT_overflow +OUT_no_overflow: + inc tx_ring_in ; tx_ring_in++ + inc dps ; switch to DPTR0: source + inc dptr + djnz r1, OUT_loop + sjmp OUT_done +OUT_overflow: + ;; signal overflow + ;; fall through +OUT_done: + ;; ack + mov dptr,OUT2BC + movx @dptr,a + + ;; start tx + acall maybe_start_tx + ;acall dump_stat + + mov a, #0x20 ; Turn off the green LED + mov dptr,OEA + movx @dptr, a + + pop acc + pop dph1 + pop dpl1 + pop dph + pop dpl + pop dps + reti + +dump_stat: + ;; fill in EP4in with a debugging message: + ;; tx_ring_in, tx_ring_out, rx_ring_in, rx_ring_out + ;; tx_active + ;; tx_ring[0..15] + ;; 0xfc + ;; rx_ring[0..15] + clr a + mov dps, a + + mov dptr, IN4CS + movx a, @dptr + jb acc.1, dump_stat__done; busy: cannot dump, old one still pending + mov dptr, IN4BUF + + mov a, tx_ring_in + movx @dptr, a + inc dptr + mov a, tx_ring_out + movx @dptr, a + inc dptr + + mov a, rx_ring_in + movx @dptr, a + inc dptr + mov a, rx_ring_out + movx @dptr, a + inc dptr + + clr a + jnb TX_RUNNING, dump_stat__no_tx_running + inc a +dump_stat__no_tx_running: + movx @dptr, a + inc dptr + ;; tx_ring[0..15] + inc dps + mov dptr, #tx_ring ; DPTR1: source + mov r1, #16 +dump_stat__tx_ring_loop: + movx a, @dptr + inc dptr + inc dps + movx @dptr, a + inc dptr + inc dps + djnz r1, dump_stat__tx_ring_loop + inc dps + + mov a, #0xfc + movx @dptr, a + inc dptr + + ;; rx_ring[0..15] + inc dps + mov dptr, #rx_ring ; DPTR1: source + mov r1, #16 +dump_stat__rx_ring_loop: + movx a, @dptr + inc dptr + inc dps + movx @dptr, a + inc dptr + inc dps + djnz r1, dump_stat__rx_ring_loop + + ;; now send it + clr a + mov dps, a + mov dptr, IN4BC + mov a, #38 + movx @dptr, a +dump_stat__done: + ret + +;;; ============================================================ + +maybe_start_tx: + ;; make sure the tx process is running. + jb TX_RUNNING, start_tx_done +start_tx: + ;; is there work to be done? + mov a, tx_ring_in + cjne a,tx_ring_out, start_tx__work + ret ; no work +start_tx__work: + ;; tx was not running. send the first character, setup the TI int + inc tx_ring_out ; [++tx_ring_out] + mov dph, #HIGH(tx_ring) + mov dpl, tx_ring_out + movx a, @dptr + mov sbuf, a + setb TX_RUNNING +start_tx_done: + ;; can we unthrottle the host tx process? + ;; step 1: do we care? + mov a, #0 + cjne a, tx_unthrottle_threshold, start_tx__maybe_unthrottle_tx + ;; nope +start_tx_really_done: + ret +start_tx__maybe_unthrottle_tx: + ;; step 2: is there now room? + mov a, tx_ring_out + setb c + subb a, tx_ring_in + ;; a is now write_room. If thresh >= a, we can unthrottle + clr c + subb a, tx_unthrottle_threshold + jc start_tx_really_done ; nope + ;; yes, we can unthrottle. remove the threshold and mark a request + mov tx_unthrottle_threshold, #0 + setb DO_TX_UNTHROTTLE + ;; prod rx, which will actually send the message when in2 becomes free + ljmp start_in + + +serial_int: + push dps + push dpl + push dph + push dpl1 + push dph1 + push acc + jnb TI, serial_int__not_tx + ;; tx finished. send another character if we have one + clr TI ; clear int + clr TX_RUNNING + lcall start_tx +serial_int__not_tx: + jnb RI, serial_int__not_rx + lcall get_rx_char + clr RI ; clear int +serial_int__not_rx: + ;; return + pop acc + pop dph1 + pop dpl1 + pop dph + pop dpl + pop dps + reti + +get_rx_char: + mov dph, #HIGH(rx_ring) + mov dpl, rx_ring_in + inc dpl ; target = rx_ring_in+1 + mov a, sbuf + movx @dptr, a + ;; check for overflow before incrementing rx_ring_in + mov a, dpl + cjne a, rx_ring_out, get_rx_char__no_overflow + ;; signal overflow + ret +get_rx_char__no_overflow: + inc rx_ring_in + ;; kick off USB INpipe + acall start_in + ret + +start_in: + ;; check if the inpipe is already running. + mov a,#0x10 + mov dptr, OEA + movx @dptr,a + + mov dptr, IN2CS + movx a, @dptr + jb acc.1, start_in__done; int will handle it + jb DO_TX_UNTHROTTLE, start_in__do_tx_unthrottle + ;; see if there is any work to do. a serial interrupt might occur + ;; during this sequence? + mov a, rx_ring_in + cjne a, rx_ring_out, start_in__have_work + ret ; nope +start_in__have_work: + ;; now copy as much data as possible into the pipe. 63 bytes max. + clr a + mov dps, a + mov dph, #HIGH(rx_ring) ; load DPTR0 with source + inc dps + mov dptr, IN2BUF ; load DPTR1 with target + movx @dptr, a ; in[0] signals that rest of IN is rx data + inc dptr + inc dps + ;; loop until we run out of data, or we have copied 64 bytes + mov r1, #1 ; INbuf size counter +start_in__loop: + mov a, rx_ring_in + cjne a, rx_ring_out, start_in__still_copying + sjmp start_in__kick +start_in__still_copying: + inc rx_ring_out + mov dpl, rx_ring_out + movx a, @dptr + inc dps + movx @dptr, a ; write into IN buffer + inc dptr + inc dps + inc r1 + cjne r1, #64, start_in__loop; loop +start_in__kick: + ;; either we ran out of data, or we copied 64 bytes. r1 has byte count + ;; kick off IN + mov a, #0x10 ; Turn the green LED + mov dptr,OEA + movx @dptr, a + mov dptr, IN2BC + mov a, r1 + jz start_in__done + movx @dptr, a + ;; done +start_in__done: + ;acall dump_stat + ret +start_in__do_tx_unthrottle: + ;; special sequence: send a tx unthrottle message + clr DO_TX_UNTHROTTLE + clr a + mov dps, a + mov dptr, IN2BUF + mov a, #1 + movx @dptr, a + inc dptr + mov a, #2 + movx @dptr, a + mov dptr, IN2BC + movx @dptr, a + ret + +putchar: + clr TI + mov SBUF, a +putchar_wait: + jnb TI, putchar_wait + clr TI + ret + + +baud_table: ; baud_high, then baud_low + ;; baud[0]: 110 + .byte BAUD_HIGH(110) + .byte BAUD_LOW(110) + ;; baud[1]: 300 + .byte BAUD_HIGH(300) + .byte BAUD_LOW(300) + ;; baud[2]: 1200 + .byte BAUD_HIGH(1200) + .byte BAUD_LOW(1200) + ;; baud[3]: 2400 + .byte BAUD_HIGH(2400) + .byte BAUD_LOW(2400) + ;; baud[4]: 4800 + .byte BAUD_HIGH(4800) + .byte BAUD_LOW(4800) + ;; baud[5]: 9600 + .byte BAUD_HIGH(9600) + .byte BAUD_LOW(9600) + ;; baud[6]: 19200 + .byte BAUD_HIGH(19200) + .byte BAUD_LOW(19200) + ;; baud[7]: 38400 + .byte BAUD_HIGH(38400) + .byte BAUD_LOW(38400) + ;; baud[8]: 57600 + .byte BAUD_HIGH(57600) + .byte BAUD_LOW(57600) + ;; baud[9]: 115200 + .byte BAUD_HIGH(115200) + .byte BAUD_LOW(115200) + +desc_device: + .byte 0x12, 0x01, 0x00, 0x01, 0xff, 0xff, 0xff, 0x40 + .byte 0xcd, 0x06, 0x04, 0x01, 0x89, 0xab, 1, 2, 3, 0x01 +;;; The "real" device id, which must match the host driver, is that +;;; "0xcd 0x06 0x04 0x01" sequence, which is 0x06cd, 0x0104 + +desc_config1: + .byte 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32 + .byte 0x09, 0x04, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0x00 + .byte 0x07, 0x05, 0x82, 0x03, 0x40, 0x00, 0x01 + .byte 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00 + +desc_strings: + .word string_langids, string_mfg, string_product, string_serial +desc_strings_end: + +string_langids: .byte string_langids_end-string_langids + .byte 3 + .word 0 +string_langids_end: + + ;; sigh. These strings are Unicode, meaning UTF16? 2 bytes each. Now + ;; *that* is a pain in the ass to encode. And they are little-endian + ;; too. Use this perl snippet to get the bytecodes: + /* while (<>) { + @c = split(//); + foreach $c (@c) { + printf("0x%02x, 0x00, ", ord($c)); + } + } + */ + +string_mfg: .byte string_mfg_end-string_mfg + .byte 3 +; .byte "ACME usb widgets" + .byte 0x41, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x62, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x65, 0x00, 0x74, 0x00, 0x73, 0x00 +string_mfg_end: + +string_product: .byte string_product_end-string_product + .byte 3 +; .byte "ACME USB serial widget" + .byte 0x41, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x65, 0x00, 0x74, 0x00 +string_product_end: + +string_serial: .byte string_serial_end-string_serial + .byte 3 +; .byte "47" + .byte 0x34, 0x00, 0x37, 0x00 +string_serial_end: + +;;; ring buffer memory + ;; tx_ring_in+1 is where the next input byte will go + ;; [tx_ring_out] has been sent + ;; if tx_ring_in == tx_ring_out, theres no work to do + ;; there are (tx_ring_in - tx_ring_out) chars to be written + ;; dont let _in lap _out + ;; cannot inc if tx_ring_in+1 == tx_ring_out + ;; write [tx_ring_in+1] then tx_ring_in++ + ;; if (tx_ring_in+1 == tx_ring_out), overflow + ;; else tx_ring_in++ + ;; read/send [tx_ring_out+1], then tx_ring_out++ + + ;; rx_ring_in works the same way + + .org 0x1000 +tx_ring: + .skip 0x100 ; 256 bytes +rx_ring: + .skip 0x100 ; 256 bytes + + + .END + diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/xircom_pgs_fw.h linux/drivers/usb/serial/xircom_pgs_fw.h --- v2.4.9/linux/drivers/usb/serial/xircom_pgs_fw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/xircom_pgs_fw.h Fri Sep 14 14:41:56 2001 @@ -0,0 +1,103 @@ +/* + * USB Xircom PGS Firmware + * + * Copyright (c) 1999, 2000 Brian Warner + * Copyright (c) 2001 Cristian M. Craciunescu + * + * 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. + * + * Generated from xircom_pgs.S by ezusb_convert_x.pl + */ + +static const struct ezusb_hex_record xircom_pgs_firmware[] = { +{ 0x0000, 3, {0x02, 0x02, 0x00} }, +{ 0x0023, 4, {0x02, 0x05, 0x9b, 0x00} }, +{ 0x0030, 5, {0x00, 0x00, 0x00, 0x00, 0x00} }, +{ 0x0043, 4, {0x02, 0x01, 0x00, 0x00} }, +{ 0x0100, 16, {0x02, 0x02, 0xba, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00} }, +{ 0x0110, 16, {0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00} }, +{ 0x0120, 16, {0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x04, 0x85, 0x00, 0x02, 0x04, 0xb9, 0x00} }, +{ 0x0200, 16, {0x75, 0x81, 0x5e, 0xe4, 0xf5, 0x32, 0xf5, 0x33, 0xf5, 0x30, 0xf5, 0x31, 0xf5, 0x34, 0xc2, 0x00} }, +{ 0x0210, 16, {0xc2, 0x01, 0xa9, 0x00, 0x74, 0xfe, 0x90, 0x10, 0x00, 0xf0, 0xa3, 0xd9, 0xfc, 0x74, 0xfd, 0x90} }, +{ 0x0220, 16, {0x11, 0x00, 0xf0, 0xa3, 0xd9, 0xfc, 0x90, 0x7f, 0x94, 0x74, 0xbf, 0xf0, 0x90, 0x7f, 0x95, 0x74} }, +{ 0x0230, 16, {0xef, 0xf0, 0x74, 0x10, 0x90, 0x7f, 0x9e, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0x98, 0xf0, 0x74, 0x40} }, +{ 0x0240, 16, {0x90, 0x7f, 0x9d, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0x97, 0xf0, 0x74, 0x82, 0x90, 0x7f, 0x9e, 0xf0} }, +{ 0x0250, 16, {0x90, 0x7f, 0x95, 0x74, 0x03, 0xf0, 0x90, 0x7f, 0xaf, 0xe0, 0xd2, 0xe0, 0xf0, 0x74, 0x01, 0x90} }, +{ 0x0260, 16, {0x7f, 0xab, 0xf0, 0x90, 0x7f, 0xae, 0xf0, 0x90, 0x7f, 0xac, 0x74, 0x04, 0xf0, 0x90, 0x7f, 0xad} }, +{ 0x0270, 16, {0x74, 0x04, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x74, 0x07, 0x90, 0x7f, 0xaf, 0xf0, 0x74, 0x20, 0x90} }, +{ 0x0280, 16, {0x7f, 0x9c, 0xf0, 0x74, 0x80, 0x90, 0x7f, 0x98, 0xf0, 0x74, 0x53, 0xf5, 0x98, 0x75, 0xc8, 0x30} }, +{ 0x0290, 16, {0x7b, 0x05, 0x91, 0x44, 0xd2, 0xca, 0x75, 0x98, 0x50, 0xd2, 0xe8, 0xd2, 0xaf, 0xd2, 0xac, 0x74} }, +{ 0x02a0, 16, {0x00, 0xf5, 0x86, 0x90, 0x7f, 0xd6, 0x74, 0x02, 0xf0, 0x79, 0x2e, 0x7a, 0x00, 0x7b, 0x00, 0xdb} }, +{ 0x02b0, 16, {0xfe, 0xda, 0xfa, 0xd9, 0xf6, 0x74, 0x06, 0xf0, 0x80, 0xfe, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83} }, +{ 0x02c0, 16, {0xc0, 0x84, 0xc0, 0x85, 0xc0, 0xe0, 0xe5, 0x91, 0xc2, 0xe4, 0xf5, 0x91, 0x90, 0x7f, 0xab, 0x74} }, +{ 0x02d0, 16, {0x01, 0xf0, 0x90, 0x7f, 0xe8, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0xa3, 0xe0, 0xfc} }, +{ 0x02e0, 16, {0xe9, 0x54, 0x60, 0xb4, 0x00, 0x03, 0x02, 0x03, 0x5d, 0xb4, 0x40, 0x6e, 0xba, 0x00, 0x0b, 0x12} }, +{ 0x02f0, 16, {0x04, 0x44, 0x40, 0x03, 0x02, 0x04, 0x26, 0x02, 0x04, 0x2e, 0xba, 0x01, 0x03, 0x02, 0x04, 0x2e} }, +{ 0x0300, 16, {0xba, 0x02, 0x03, 0x02, 0x04, 0x2e, 0xba, 0x03, 0x03, 0x02, 0x04, 0x68, 0xba, 0x04, 0x1e, 0xbb} }, +{ 0x0310, 16, {0x00, 0x0a, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x04, 0x26, 0x90, 0x7f, 0x98, 0xe0} }, +{ 0x0320, 16, {0x54, 0xfd, 0xf0, 0x90, 0x7f, 0x95, 0xe0, 0x54, 0xfd, 0xf0, 0x02, 0x04, 0x26, 0xba, 0x05, 0x03} }, +{ 0x0330, 16, {0x02, 0x04, 0x2e, 0xba, 0x06, 0x19, 0xbb, 0x00, 0x08, 0xe5, 0x33, 0xd3, 0x95, 0x32, 0x02, 0x04} }, +{ 0x0340, 16, {0x02, 0xbb, 0x01, 0x08, 0xe5, 0x32, 0xc3, 0x95, 0x33, 0x02, 0x04, 0x02, 0x02, 0x04, 0x2e, 0xba} }, +{ 0x0350, 16, {0x07, 0x05, 0x8b, 0x34, 0x02, 0x04, 0x26, 0x02, 0x04, 0x2e, 0x02, 0x04, 0x2e, 0xba, 0x00, 0x20} }, +{ 0x0360, 16, {0xb9, 0x80, 0x10, 0x90, 0x7f, 0x00, 0xe4, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0} }, +{ 0x0370, 16, {0x02, 0x04, 0x26, 0xb9, 0x82, 0x02, 0x80, 0xeb, 0xb9, 0x81, 0x02, 0x80, 0xe6, 0x02, 0x04, 0x2e} }, +{ 0x0380, 16, {0xba, 0x01, 0x0f, 0xbb, 0x00, 0x03, 0x02, 0x04, 0x2e, 0xbb, 0x01, 0x03, 0x02, 0x04, 0x26, 0x02} }, +{ 0x0390, 16, {0x04, 0x2e, 0xba, 0x03, 0x0f, 0xbb, 0x00, 0x03, 0x02, 0x04, 0x2e, 0xbb, 0x01, 0x03, 0x02, 0x04} }, +{ 0x03a0, 16, {0x26, 0x02, 0x04, 0x2e, 0xba, 0x06, 0x56, 0xbc, 0x01, 0x0f, 0x90, 0x7f, 0xd4, 0x74, 0x06, 0xf0} }, +{ 0x03b0, 16, {0x90, 0x7f, 0xd5, 0x74, 0x5a, 0xf0, 0x02, 0x04, 0x26, 0xbc, 0x02, 0x12, 0xbb, 0x00, 0x6f, 0x90} }, +{ 0x03c0, 16, {0x7f, 0xd4, 0x74, 0x06, 0xf0, 0x90, 0x7f, 0xd5, 0x74, 0x6c, 0xf0, 0x02, 0x04, 0x26, 0xbc, 0x03} }, +{ 0x03d0, 16, {0x29, 0x74, 0x04, 0xc3, 0x9b, 0x40, 0x57, 0x60, 0x55, 0xeb, 0x2b, 0x90, 0x06, 0x8c, 0x25, 0x82} }, +{ 0x03e0, 16, {0xf5, 0x82, 0x74, 0x00, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0x90, 0x7f, 0xd4} }, +{ 0x03f0, 16, {0xe9, 0xf0, 0x90, 0x7f, 0xd5, 0xea, 0xf0, 0x02, 0x04, 0x26, 0x02, 0x04, 0x2e, 0xba, 0x08, 0x0f} }, +{ 0x0400, 16, {0x74, 0x01, 0x90, 0x7f, 0x00, 0xf0, 0x74, 0x01, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x04, 0x26, 0xba} }, +{ 0x0410, 16, {0x09, 0x03, 0x02, 0x04, 0x26, 0xba, 0x0a, 0x05, 0x74, 0x00, 0x02, 0x04, 0x02, 0xba, 0x0b, 0x03} }, +{ 0x0420, 16, {0x02, 0x04, 0x26, 0x02, 0x04, 0x2e, 0x90, 0x7f, 0xb4, 0x74, 0x02, 0xf0, 0x80, 0x09, 0x90, 0x7f} }, +{ 0x0430, 16, {0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x00, 0xd0, 0xe0, 0xd0, 0x85, 0xd0, 0x84, 0xd0, 0x83, 0xd0} }, +{ 0x0440, 16, {0x82, 0xd0, 0x86, 0x32, 0xeb, 0x20, 0xe7, 0x1e, 0xc3, 0x94, 0x0a, 0x50, 0x19, 0xeb, 0x23, 0x24} }, +{ 0x0450, 16, {0x46, 0xf5, 0x82, 0x74, 0x06, 0x34, 0x00, 0xf5, 0x83, 0xe0, 0xf5, 0xcb, 0xf5, 0xcd, 0xa3, 0xe0} }, +{ 0x0460, 16, {0xf5, 0xca, 0xf5, 0xcc, 0xc3, 0x22, 0xd3, 0x22, 0xb9, 0x41, 0x11, 0xeb, 0x64, 0xff, 0x54, 0x80} }, +{ 0x0470, 16, {0xfb, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0x7f, 0x4b, 0xf0, 0x02, 0x04, 0x26, 0x90, 0x7f, 0x9b, 0xe0} }, +{ 0x0480, 16, {0x64, 0xff, 0x02, 0x04, 0x02, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x84, 0xc0, 0x85, 0xc0} }, +{ 0x0490, 16, {0xe0, 0xe5, 0x91, 0xc2, 0xe4, 0xf5, 0x91, 0x90, 0x7f, 0xa9, 0x74, 0x04, 0xf0, 0x74, 0x20, 0x90} }, +{ 0x04a0, 16, {0x7f, 0x9c, 0xf0, 0x12, 0x05, 0xdc, 0x74, 0x20, 0x90, 0x7f, 0x9c, 0xf0, 0xd0, 0xe0, 0xd0, 0x85} }, +{ 0x04b0, 16, {0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0} }, +{ 0x04c0, 16, {0x84, 0xc0, 0x85, 0xc0, 0xe0, 0x74, 0x10, 0x90, 0x7f, 0x9c, 0xf0, 0xe5, 0x91, 0xc2, 0xe4, 0xf5} }, +{ 0x04d0, 16, {0x91, 0x90, 0x7f, 0xaa, 0x74, 0x04, 0xf0, 0x90, 0x7f, 0xc9, 0xe0, 0xf9, 0xe4, 0xf5, 0x86, 0x90} }, +{ 0x04e0, 16, {0x7d, 0xc0, 0x75, 0x85, 0x10, 0x85, 0x32, 0x84, 0xe0, 0x05, 0x86, 0x05, 0x84, 0xf0, 0xe5, 0x84} }, +{ 0x04f0, 16, {0xb5, 0x33, 0x02, 0x80, 0x09, 0x05, 0x32, 0x05, 0x86, 0xa3, 0xd9, 0xec, 0x80, 0x00, 0x90, 0x7f} }, +{ 0x0500, 16, {0xc9, 0xf0, 0xb1, 0x6d, 0x74, 0x20, 0x90, 0x7f, 0x9c, 0xf0, 0xd0, 0xe0, 0xd0, 0x85, 0xd0, 0x84} }, +{ 0x0510, 16, {0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0xe4, 0xf5, 0x86, 0x90, 0x7f, 0xbc, 0xe0, 0x20, 0xe1} }, +{ 0x0520, 16, {0x4b, 0x90, 0x7d, 0x00, 0xe5, 0x32, 0xf0, 0xa3, 0xe5, 0x33, 0xf0, 0xa3, 0xe5, 0x30, 0xf0, 0xa3} }, +{ 0x0530, 16, {0xe5, 0x31, 0xf0, 0xa3, 0xe4, 0x30, 0x00, 0x01, 0x04, 0xf0, 0xa3, 0x05, 0x86, 0x90, 0x10, 0x00} }, +{ 0x0540, 16, {0x79, 0x10, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xd9, 0xf6, 0x05, 0x86, 0x74, 0xfc} }, +{ 0x0550, 16, {0xf0, 0xa3, 0x05, 0x86, 0x90, 0x11, 0x00, 0x79, 0x10, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0xa3, 0x05} }, +{ 0x0560, 16, {0x86, 0xd9, 0xf6, 0xe4, 0xf5, 0x86, 0x90, 0x7f, 0xbd, 0x74, 0x26, 0xf0, 0x22, 0x20, 0x00, 0x13} }, +{ 0x0570, 16, {0xe5, 0x32, 0xb5, 0x33, 0x01, 0x22, 0x05, 0x33, 0x75, 0x83, 0x10, 0x85, 0x33, 0x82, 0xe0, 0xf5} }, +{ 0x0580, 16, {0x99, 0xd2, 0x00, 0x74, 0x00, 0xb5, 0x34, 0x01, 0x22, 0xe5, 0x33, 0xd3, 0x95, 0x32, 0xc3, 0x95} }, +{ 0x0590, 16, {0x34, 0x40, 0xf5, 0x75, 0x34, 0x00, 0xd2, 0x01, 0x02, 0x05, 0xdc, 0xc0, 0x86, 0xc0, 0x82, 0xc0} }, +{ 0x05a0, 16, {0x83, 0xc0, 0x84, 0xc0, 0x85, 0xc0, 0xe0, 0x30, 0x99, 0x07, 0xc2, 0x99, 0xc2, 0x00, 0x12, 0x05} }, +{ 0x05b0, 16, {0x70, 0x30, 0x98, 0x05, 0x12, 0x05, 0xc6, 0xc2, 0x98, 0xd0, 0xe0, 0xd0, 0x85, 0xd0, 0x84, 0xd0} }, +{ 0x05c0, 16, {0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0x75, 0x83, 0x11, 0x85, 0x30, 0x82, 0x05, 0x82, 0xe5, 0x99} }, +{ 0x05d0, 16, {0xf0, 0xe5, 0x82, 0xb5, 0x31, 0x01, 0x22, 0x05, 0x30, 0xb1, 0xdc, 0x22, 0x74, 0x10, 0x90, 0x7f} }, +{ 0x05e0, 16, {0x9c, 0xf0, 0x90, 0x7f, 0xb8, 0xe0, 0x20, 0xe1, 0x3e, 0x20, 0x01, 0x3c, 0xe5, 0x30, 0xb5, 0x31} }, +{ 0x05f0, 16, {0x01, 0x22, 0xe4, 0xf5, 0x86, 0x75, 0x83, 0x11, 0x05, 0x86, 0x90, 0x7e, 0x00, 0xf0, 0xa3, 0x05} }, +{ 0x0600, 16, {0x86, 0x79, 0x01, 0xe5, 0x30, 0xb5, 0x31, 0x02, 0x80, 0x10, 0x05, 0x31, 0x85, 0x31, 0x82, 0xe0} }, +{ 0x0610, 16, {0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0x09, 0xb9, 0x40, 0xe9, 0x74, 0x10, 0x90, 0x7f, 0x9c, 0xf0} }, +{ 0x0620, 16, {0x90, 0x7f, 0xb9, 0xe9, 0x60, 0x01, 0xf0, 0x22, 0xc2, 0x01, 0xe4, 0xf5, 0x86, 0x90, 0x7e, 0x00} }, +{ 0x0630, 16, {0x74, 0x01, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x90, 0x7f, 0xb9, 0xf0, 0x22, 0xc2, 0x99, 0xf5, 0x99} }, +{ 0x0640, 16, {0x30, 0x99, 0xfd, 0xc2, 0x99, 0x22, 0xe5, 0x5e, 0xf6, 0x3c, 0xfd, 0x8f, 0xfe, 0xc8, 0xff, 0x64} }, +{ 0x0650, 16, {0xff, 0xb2, 0xff, 0xd9, 0xff, 0xed, 0xff, 0xf3, 0xff, 0xfa, 0x12, 0x01, 0x00, 0x01, 0xff, 0xff} }, +{ 0x0660, 16, {0xff, 0x40, 0xcd, 0x06, 0x04, 0x01, 0x89, 0xab, 0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x20, 0x00} }, +{ 0x0670, 16, {0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05} }, +{ 0x0680, 16, {0x82, 0x03, 0x40, 0x00, 0x01, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x06, 0x94, 0x06, 0x98} }, +{ 0x0690, 16, {0x06, 0xba, 0x06, 0xe8, 0x04, 0x03, 0x00, 0x00, 0x22, 0x03, 0x41, 0x00, 0x43, 0x00, 0x4d, 0x00} }, +{ 0x06a0, 16, {0x45, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x62, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00} }, +{ 0x06b0, 16, {0x64, 0x00, 0x67, 0x00, 0x65, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2e, 0x03, 0x41, 0x00, 0x43, 0x00} }, +{ 0x06c0, 16, {0x4d, 0x00, 0x45, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x73, 0x00} }, +{ 0x06d0, 16, {0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00} }, +{ 0x06e0, 14, {0x64, 0x00, 0x67, 0x00, 0x65, 0x00, 0x74, 0x00, 0x06, 0x03, 0x34, 0x00, 0x37, 0x00} }, +{ 0xffff, 0, {0x00} } +}; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/storage/datafab.c linux/drivers/usb/storage/datafab.c --- v2.4.9/linux/drivers/usb/storage/datafab.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/storage/datafab.c Mon Sep 10 09:04:53 2001 @@ -204,7 +204,7 @@ do { // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit) - len = min(int, totallen, 65536); + len = min_t(int, totallen, 65536); if (use_sg) { sg = (struct scatterlist *) dest; @@ -329,7 +329,7 @@ do { // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit) - len = min(int, totallen, 65536); + len = min_t(int, totallen, 65536); if (use_sg) { sg = (struct scatterlist *) src; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/storage/isd200.c linux/drivers/usb/storage/isd200.c --- v2.4.9/linux/drivers/usb/storage/isd200.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/storage/isd200.c Fri Sep 14 14:04:07 2001 @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/usb/storage/jumpshot.c linux/drivers/usb/storage/jumpshot.c --- v2.4.9/linux/drivers/usb/storage/jumpshot.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/storage/jumpshot.c Fri Sep 14 14:04:07 2001 @@ -45,7 +45,7 @@ #include #include -#include +#include extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, u8 request, u8 requesttype, u16 value, @@ -280,7 +280,7 @@ do { // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit) - len = min(int, totallen, 65536); + len = min_t(int, totallen, 65536); if (use_sg) { sg = (struct scatterlist *) dest; @@ -395,7 +395,7 @@ do { // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit) - len = min(int, totallen, 65536); + len = min_t(int, totallen, 65536); if (use_sg) { sg = (struct scatterlist *) src; 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 Tue Sep 18 14:10:43 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) @@ -49,7 +49,7 @@ #include "debug.h" #include "transport.h" -#include +#include /* * kernel thread actions @@ -346,6 +346,7 @@ /* show the GUID of the device */ SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); + SPRINTF(" Attached: %d\n", us->pusb_dev != NULL); /* * Calculate start of next buffer, and return value. 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 Fri Sep 14 14:04:07 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 = " @@ -965,7 +965,7 @@ (info->pageshift + info->blockshift) ) ) { US_DEBUGP("Error: Requested LBA %04X exceeds maximum " - "block %04X\n", lba, + "block %04lX\n", lba, (info->capacity >> (info->pageshift + info->blockshift))-1); // FIXME: sense buffer? 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 Fri Sep 14 14:04:07 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) @@ -52,7 +52,7 @@ #include #include -#include +#include /*********************************************************************** * Helper routines @@ -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 Tue Sep 18 17:09:31 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/storage/usb.c linux/drivers/usb/storage/usb.c --- v2.4.9/linux/drivers/usb/storage/usb.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/storage/usb.c Fri Sep 14 14:04:07 2001 @@ -81,11 +81,12 @@ #include #include #include -#include +#include /* Some informational data */ MODULE_AUTHOR("Matthew Dharm "); MODULE_DESCRIPTION("USB Mass Storage driver for Linux"); +MODULE_LICENSE("GPL"); /* * Per device data diff -u --recursive --new-file v2.4.9/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.4.9/linux/drivers/usb/uhci.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/uhci.c Mon Sep 10 08:06:32 2001 @@ -2131,14 +2131,14 @@ case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { case 0x01: /* device descriptor */ - len = min(unsigned int, leni, - min(unsigned int, + len = min_t(unsigned int, leni, + min_t(unsigned int, sizeof(root_hub_dev_des), wLength)); memcpy(data, root_hub_dev_des, len); OK(len); case 0x02: /* configuration descriptor */ - len = min(unsigned int, leni, - min(unsigned int, + len = min_t(unsigned int, leni, + min_t(unsigned int, sizeof(root_hub_config_des), wLength)); memcpy (data, root_hub_config_des, len); OK(len); @@ -2147,15 +2147,15 @@ uhci->io_addr, "UHCI-alt", data, wLength); if (len > 0) { - OK(min(int, leni, len)); + OK(min_t(int, leni, len)); } else stat = -EPIPE; } break; case RH_GET_DESCRIPTOR | RH_CLASS: root_hub_hub_des[2] = uhci->rh.numports; - len = min(unsigned int, leni, - min(unsigned int, sizeof(root_hub_hub_des), wLength)); + len = min_t(unsigned int, leni, + min_t(unsigned int, sizeof(root_hub_hub_des), wLength)); memcpy(data, root_hub_hub_des, len); OK(len); case RH_GET_CONFIGURATION: diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c --- v2.4.9/linux/drivers/usb/usb-ohci.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/usb-ohci.c Fri Sep 14 14:04:07 2001 @@ -1806,8 +1806,8 @@ if (ret > 0) { memcpy(rh_data, data, - min(unsigned int, len, - min(unsigned int, rh_len, sizeof(data)))); + min_t(unsigned int, len, + min_t(unsigned int, rh_len, sizeof(data)))); return len; } return 0; @@ -1989,16 +1989,16 @@ case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { case (0x01): /* device descriptor */ - len = min(unsigned int, + len = min_t(unsigned int, leni, - min(unsigned int, + min_t(unsigned int, sizeof (root_hub_dev_des), wLength)); data_buf = root_hub_dev_des; OK(len); case (0x02): /* configuration descriptor */ - len = min(unsigned int, + len = min_t(unsigned int, leni, - min(unsigned int, + min_t(unsigned int, sizeof (root_hub_config_des), wLength)); data_buf = root_hub_config_des; OK(len); @@ -2008,7 +2008,7 @@ data, wLength); if (len > 0) { data_buf = data; - OK(min(int, leni, len)); + OK(min_t(int, leni, len)); } // else fallthrough default: @@ -2043,8 +2043,8 @@ data_buf [10] = data_buf [9] = 0xff; } - len = min(unsigned int, leni, - min(unsigned int, data_buf [0], wLength)); + len = min_t(unsigned int, leni, + min_t(unsigned int, data_buf [0], wLength)); OK (len); } @@ -2061,7 +2061,7 @@ // ohci_dump_roothub (ohci, 0); #endif - len = min(int, len, leni); + len = min_t(int, len, leni); if (data != data_buf) memcpy (data, data_buf, len); urb->actual_length = len; @@ -2864,3 +2864,4 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); 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 Fri Sep 14 14:04:07 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; } @@ -649,4 +650,5 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); 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 Tue Sep 18 14:10:43 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 - if (!in_interrupt()) - spin_unlock(&urb->lock); + // move descriptors out the the running chains, dequeue urb + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_DONT_STORE); - 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) { @@ -2159,14 +2111,14 @@ case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { case (0x01): /* device descriptor */ - len = min(unsigned int, leni, - min(unsigned int, + len = min_t(unsigned int, leni, + min_t(unsigned int, sizeof (root_hub_dev_des), wLength)); memcpy (data, root_hub_dev_des, len); OK (len); case (0x02): /* configuration descriptor */ - len = min(unsigned int, leni, - min(unsigned int, + len = min_t(unsigned int, leni, + min_t(unsigned int, sizeof (root_hub_config_des), wLength)); memcpy (data, root_hub_config_des, len); OK (len); @@ -2175,7 +2127,7 @@ uhci->io_addr, "UHCI", data, wLength); if (len > 0) { - OK(min(int, leni, len)); + OK(min_t(int, leni, len)); } else stat = -EPIPE; } @@ -2183,8 +2135,8 @@ case RH_GET_DESCRIPTOR | RH_CLASS: root_hub_hub_des[2] = uhci->rh.numports; - len = min(unsigned int, leni, - min(unsigned int, sizeof (root_hub_hub_des), wLength)); + len = min_t(unsigned int, leni, + min_t(unsigned int, sizeof (root_hub_hub_des), wLength)); memcpy (data, root_hub_hub_des, len); OK (len); @@ -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); @@ -3031,6 +3021,11 @@ if (pci_enable_device(dev) < 0) return -ENODEV; + + if (!dev->irq) { + err("found UHCI device with no IRQ assigned. check BIOS settings!"); + return -ENODEV; + } pci_set_master(dev); 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/usbkbd.c linux/drivers/usb/usbkbd.c --- v2.4.9/linux/drivers/usb/usbkbd.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/usbkbd.c Fri Sep 14 14:04:07 2001 @@ -44,6 +44,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); static unsigned char usb_kbd_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c --- v2.4.9/linux/drivers/usb/usbmouse.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/usbmouse.c Fri Sep 14 14:04:07 2001 @@ -44,6 +44,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); struct usb_mouse { signed char data[8]; 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 Fri Sep 14 14:04:07 2001 @@ -0,0 +1,1568 @@ +/* + * 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, ...)"); +MODULE_LICENSE("GPL"); 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/usb/wacom.c linux/drivers/usb/wacom.c --- v2.4.9/linux/drivers/usb/wacom.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/wacom.c Mon Sep 17 22:52:35 2001 @@ -1,12 +1,13 @@ /* - * $Id: wacom.c,v 1.14 2000/11/23 09:34:32 vojtech Exp $ + * $Id: wacom.c,v 1.22 2001/04/26 11:26:09 vojtech Exp $ * - * Copyright (c) 2000 Vojtech Pavlik + * Copyright (c) 2000-2001 Vojtech Pavlik * Copyright (c) 2000 Andreas Bach Aaen * Copyright (c) 2000 Clifford Wolf * Copyright (c) 2000 Sam Mosel * Copyright (c) 2000 James E. Blair * Copyright (c) 2000 Daniel Egger + * Copyright (c) 2001 Frederic Lepied * * USB Wacom Graphire and Wacom Intuos tablet support * @@ -28,6 +29,15 @@ * v1.12 (de) - Add support for two more inking pen IDs * v1.14 (vp) - Use new USB device id probing scheme. * Fix Wacom Graphire mouse wheel + * v1.18 (vp) - Fix mouse wheel direction + * Make mouse relative + * v1.20 (fl) - Report tool id for Intuos devices + * - Multi tools support + * - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...) + * - Add PL models support + * - Fix Wacom Graphire mouse wheel again + * v1.21 (vp) - Removed protocol descriptions + * - Added MISC_SERIAL for tool serial numbers * (gb) - Identify version on module load. */ @@ -61,81 +71,13 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.14" +#define DRIVER_VERSION "v1.21" #define DRIVER_AUTHOR "Vojtech Pavlik " #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); - -/* - * Wacom Graphire packet: - * - * byte 0: report ID (2) - * byte 1: bit7 pointer in range - * bit5-6 pointer type 0 - pen, 1 - rubber, 2 - mouse - * bit4 1 ? - * bit3 0 ? - * bit2 mouse middle button / pen button2 - * bit1 mouse right button / pen button1 - * bit0 mouse left button / touch - * byte 2: X low bits - * byte 3: X high bits - * byte 4: Y low bits - * byte 5: Y high bits - * byte 6: pen pressure low bits / mouse wheel - * byte 7: pen presure high bits / mouse distance - * - * There are also two single-byte feature reports (2 and 3). - * - * Wacom Intuos status packet: - * - * byte 0: report ID (2) - * byte 1: bit7 1 - sync bit - * bit6 pointer in range - * bit5 pointer type report - * bit4 0 ? - * bit3 mouse packet type - * bit2 pen button2 - * bit1 pen button1 - * bit0 0 ? - * byte 2: X high bits - * byte 3: X low bits - * byte 4: Y high bits - * byte 5: Y low bits - * - * Pen packet: - * - * byte 6: bits 0-7: pressure (bits 2-9) - * byte 7: bits 6-7: pressure (bits 0-1) - * byte 7: bits 0-5: X tilt (bits 1-6) - * byte 8: bit 7: X tilt (bit 0) - * byte 8: bits 0-6: Y tilt (bits 0-6) - * byte 9: bits 4-7: distance - * - * Mouse packet type 0: - * - * byte 6: bits 0-7: wheel (bits 2-9) - * byte 7: bits 6-7: wheel (bits 0-1) - * byte 7: bits 0-5: 0 - * byte 8: bits 6-7: 0 - * byte 8: bit 5: left extra button - * byte 8: bit 4: right extra button - * byte 8: bit 3: wheel (sign) - * byte 8: bit 2: right button - * byte 8: bit 1: middle button - * byte 8: bit 0: left button - * byte 9: bits 4-7: distance - * - * Mouse packet type 1: - * - * byte 6: bits 0-7: rotation (bits 2-9) - * byte 7: bits 6-7: rotation (bits 0-1) - * byte 7: bit 5: rotation (sign) - * byte 7: bits 0-4: 0 - * byte 8: bits 0-7: 0 - * byte 9: bits 4-7: distance - */ +MODULE_LICENSE("GPL"); #define USB_VENDOR_ID_WACOM 0x056a @@ -160,25 +102,56 @@ struct usb_device *usbdev; struct urb irq; struct wacom_features *features; - int tool; + int tool[2]; int open; + int x, y; + __u32 serial[2]; }; -static void wacom_graphire_irq(struct urb *urb) +static void wacom_pl_irq(struct urb *urb) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; struct input_dev *dev = &wacom->dev; + int prox; if (urb->status) return; if (data[0] != 2) dbg("received unknown report #%d", data[0]); - if ( data[1] & 0x80 ) { - input_report_abs(dev, ABS_X, data[2] | ((__u32)data[3] << 8)); - input_report_abs(dev, ABS_Y, data[4] | ((__u32)data[5] << 8)); + prox = data[1] & 0x20; + + input_report_key(dev, BTN_TOOL_PEN, prox); + + if (prox) { + int pressure = (data[4] & 0x04) >> 2 | ((__u32)(data[7] & 0x7f) << 1); + + input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 8) | ((__u32)(data[1] & 0x03) << 16)); + input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 8) | ((__u32)(data[4] & 0x03) << 8)); + input_report_abs(dev, ABS_PRESSURE, (data[7] & 0x80) ? (255 - pressure) : (pressure + 255)); + input_report_key(dev, BTN_TOUCH, data[4] & 0x08); + input_report_key(dev, BTN_STYLUS, data[4] & 0x10); + input_report_key(dev, BTN_STYLUS2, data[4] & 0x20); } + + input_event(dev, EV_MSC, MSC_SERIAL, 0); +} + +static void wacom_graphire_irq(struct urb *urb) +{ + struct wacom *wacom = urb->context; + unsigned char *data = wacom->data; + struct input_dev *dev = &wacom->dev; + int x, y; + + if (urb->status) return; + + if (data[0] != 2) + dbg("received unknown report #%d", data[0]); + + x = data[2] | ((__u32)data[3] << 8); + y = data[4] | ((__u32)data[5] << 8); switch ((data[1] >> 5) & 3) { @@ -197,14 +170,25 @@ input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); input_report_abs(dev, ABS_DISTANCE, data[7]); input_report_rel(dev, REL_WHEEL, (signed char) data[6]); + + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + + input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01); return; } - input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8)); + if (data[1] & 0x80) { + input_report_abs(dev, ABS_X, wacom->x = x); + input_report_abs(dev, ABS_Y, wacom->y = y); + } + input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8)); input_report_key(dev, BTN_TOUCH, data[1] & 0x01); input_report_key(dev, BTN_STYLUS, data[1] & 0x02); input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); + + input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01); } static void wacom_intuos_irq(struct urb *urb) @@ -213,35 +197,47 @@ unsigned char *data = wacom->data; struct input_dev *dev = &wacom->dev; unsigned int t; + int idx; if (urb->status) return; if (data[0] != 2) dbg("received unknown report #%d", data[0]); - if (((data[1] >> 5) & 0x3) == 0x2) { /* Enter report */ + /* tool number */ + idx = data[1] & 0x01; + + if ((data[1] & 0xfc) == 0xc0) { /* Enter report */ + + wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 4) + /* serial number of the tool */ + ((__u32)data[4] << 16) + ((__u32)data[5] << 12) + + ((__u32)data[6] << 4) + (data[7] >> 4); switch (((__u32)data[2] << 4) | (data[3] >> 4)) { case 0x832: - case 0x812: - case 0x012: wacom->tool = BTN_TOOL_PENCIL; break; /* Inking pen */ + case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL; break; /* Inking pen */ case 0x822: - case 0x022: wacom->tool = BTN_TOOL_PEN; break; /* Pen */ - case 0x032: wacom->tool = BTN_TOOL_BRUSH; break; /* Stroke pen */ - case 0x094: wacom->tool = BTN_TOOL_MOUSE; break; /* Mouse 4D */ - case 0x096: wacom->tool = BTN_TOOL_LENS; break; /* Lens cursor */ + case 0x022: wacom->tool[idx] = BTN_TOOL_PEN; break; /* Pen */ + case 0x812: + case 0x032: wacom->tool[idx] = BTN_TOOL_BRUSH; break; /* Stroke pen */ + case 0x09c: + case 0x094: wacom->tool[idx] = BTN_TOOL_MOUSE; break; /* Mouse 4D */ + case 0x096: wacom->tool[idx] = BTN_TOOL_LENS; break; /* Lens cursor */ case 0x82a: - case 0x0fa: wacom->tool = BTN_TOOL_RUBBER; break; /* Eraser */ - case 0x112: wacom->tool = BTN_TOOL_AIRBRUSH; break; /* Airbrush */ - default: wacom->tool = BTN_TOOL_PEN; break; /* Unknown tool */ + case 0x91a: + case 0x0fa: wacom->tool[idx] = BTN_TOOL_RUBBER; break; /* Eraser */ + case 0x112: wacom->tool[idx] = BTN_TOOL_AIRBRUSH; break; /* Airbrush */ + default: wacom->tool[idx] = BTN_TOOL_PEN; break; /* Unknown tool */ } - input_report_key(dev, wacom->tool, 1); + + input_report_key(dev, wacom->tool[idx], 1); + input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); return; } - if ((data[1] | data[2] | data[3] | data[4] | data[5] | - data[6] | data[7] | data[8] | data[9]) == 0x80) { /* Exit report */ - input_report_key(dev, wacom->tool, 0); + if ((data[1] & 0xfe) == 0x80) { /* Exit report */ + input_report_key(dev, wacom->tool[idx], 0); + input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); return; } @@ -249,42 +245,52 @@ input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]); input_report_abs(dev, ABS_DISTANCE, data[9] >> 4); - switch (wacom->tool) { + if ((data[1] & 0xb8) == 0xa0) { /* general pen packet */ + input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); + input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); + input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); + input_report_key(dev, BTN_STYLUS, data[1] & 2); + input_report_key(dev, BTN_STYLUS2, data[1] & 4); + input_report_key(dev, BTN_TOUCH, t > 10); + } - case BTN_TOOL_PENCIL: - case BTN_TOOL_PEN: - case BTN_TOOL_BRUSH: - case BTN_TOOL_RUBBER: - case BTN_TOOL_AIRBRUSH: - - input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); - input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); - input_report_key(dev, BTN_STYLUS, data[1] & 2); - input_report_key(dev, BTN_STYLUS2, data[1] & 4); - input_report_key(dev, BTN_TOUCH, t > 10); - break; + if ((data[1] & 0xbc) == 0xb4) { /* airbrush second packet */ + input_report_abs(dev, ABS_WHEEL, ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); + input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); + input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); + } + + if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ - case BTN_TOOL_MOUSE: - case BTN_TOOL_LENS: + if (data[1] & 0x02) { /* Rotation packet */ - if (data[1] & 0x02) { /* Rotation packet */ - input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? - ((__u32)data[6] << 2) | ((data[7] >> 6) & 3): - (-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1); - break; - } + input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? + ((__u32)data[6] << 2) | ((data[7] >> 6) & 3): + (-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1); + + } else { input_report_key(dev, BTN_LEFT, data[8] & 0x01); input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); input_report_key(dev, BTN_RIGHT, data[8] & 0x04); - input_report_key(dev, BTN_SIDE, data[8] & 0x20); - input_report_key(dev, BTN_EXTRA, data[8] & 0x10); - input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? - ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) : - -((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); - break; - } + + if ((data[1] & 0x10) == 0) { /* 4D mouse packets */ + + input_report_key(dev, BTN_SIDE, data[8] & 0x20); + input_report_key(dev, BTN_EXTRA, data[8] & 0x10); + input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? + ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) : + -((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); + + } else { /* Lens cursor packets */ + + input_report_key(dev, BTN_SIDE, data[8] & 0x10); + input_report_key(dev, BTN_EXTRA, data[8] & 0x08); + } + } + } + + input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); } #define WACOM_INTUOS_TOOLS (BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS)) @@ -304,6 +310,8 @@ 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, { "Wacom Intuos 12x18", 10, 47720, 30480, 1023, 15, wacom_intuos_irq, 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, + { "Wacom PL500", 8, 12328, 9256, 511, 32, wacom_pl_irq, + 0, 0, 0, 0 }, { NULL , 0 } }; @@ -314,6 +322,7 @@ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), driver_info: 3 }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), driver_info: 4 }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), driver_info: 5 }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), driver_info: 6 }, { } }; @@ -351,12 +360,13 @@ wacom->features = wacom_features + id->driver_info; - wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | wacom->features->evbit; - wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | wacom->features->absbit; + wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC) | wacom->features->evbit; + wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | wacom->features->absbit; wacom->dev.relbit[0] |= wacom->features->relbit; wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | wacom->features->btnbit; wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) | wacom->features->digibit; + wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); wacom->dev.absmax[ABS_X] = wacom->features->x_max; wacom->dev.absmax[ABS_Y] = wacom->features->y_max; @@ -364,6 +374,7 @@ wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max; wacom->dev.absmax[ABS_TILT_X] = 127; wacom->dev.absmax[ABS_TILT_Y] = 127; + wacom->dev.absmax[ABS_WHEEL] = 1023; wacom->dev.absmin[ABS_RZ] = -900; wacom->dev.absmax[ABS_RZ] = 899; diff -u --recursive --new-file v2.4.9/linux/drivers/video/Config.in linux/drivers/video/Config.in --- v2.4.9/linux/drivers/video/Config.in Sun Aug 12 13:28:00 2001 +++ linux/drivers/video/Config.in Fri Sep 14 14:04:07 2001 @@ -73,6 +73,9 @@ bool ' S3 Trio display support' CONFIG_FB_S3TRIO tristate ' VGA 16-color graphics console' CONFIG_FB_VGA16 fi + if [ "$CONFIG_PARISC" = "y" ]; then + bool ' Generic STI frame buffer device support' CONFIG_FB_STI + fi if [ "$CONFIG_MAC" = "y" ]; then define_bool CONFIG_FB_MAC y bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE @@ -101,12 +104,16 @@ bool ' CGsix (GX,TurboGX) support' CONFIG_FB_CGSIX fi fi - tristate ' NEC PowerVR 2 display support' CONFIG_FB_PVR2 - dep_bool ' Debug pvr2fb' CONFIG_FB_PVR2_DEBUG $CONFIG_FB_PVR2 - bool ' Epson 1355 framebuffer support' CONFIG_FB_E1355 - if [ "$CONFIG_FB_E1355" = "y" ]; then - hex ' Register Base Address' CONFIG_E1355_REG_BASE a8000000 - hex ' Framebuffer Base Address' CONFIG_E1355_FB_BASE a8200000 + if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then + tristate ' NEC PowerVR 2 display support' CONFIG_FB_PVR2 + dep_bool ' Debug pvr2fb' CONFIG_FB_PVR2_DEBUG $CONFIG_FB_PVR2 + fi + if [ "$CONFIG_SUPERH" = "y" ]; then + bool ' Epson 1355 framebuffer support' CONFIG_FB_E1355 + if [ "$CONFIG_FB_E1355" = "y" ]; then + hex ' Register Base Address' CONFIG_E1355_REG_BASE a8000000 + hex ' Framebuffer Base Address' CONFIG_E1355_FB_BASE a8200000 + fi fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_PCI" != "n" ]; then @@ -128,10 +135,19 @@ if [ "$CONFIG_FB_ATY" != "n" ]; then bool ' Mach64 GX support (EXPERIMENTAL)' CONFIG_FB_ATY_GX bool ' Mach64 CT/VT/GT/LT (incl. 3D RAGE) support' CONFIG_FB_ATY_CT + if [ "$CONFIG_FB_ATY_CT" = "y" ]; then + bool ' Sony Vaio C1VE 1024x480 LCD support' CONFIG_FB_ATY_CT_VAIO_LCD + fi + fi + tristate ' ATI Radeon display support (EXPERIMENTAL)' CONFIG_FB_RADEON + tristate ' ATI Rage128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128 + tristate ' SIS acceleration (EXPERIMENTAL)' CONFIG_FB_SIS + if [ "$CONFIG_FB_SIS" != "n" ]; then + bool ' SIS 630/540/730 support' CONFIG_FB_SIS_300 + bool ' SIS 315H/315 support' CONFIG_FB_SIS_315 fi - tristate ' ATI Rage 128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128 tristate ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX - tristate ' SIS 630/540 display support (EXPERIMENTAL)' CONFIG_FB_SIS + tristate ' 3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1 fi fi if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then @@ -173,6 +189,23 @@ if [ "$CONFIG_HD64461" = "y" ]; then tristate ' HD64461 Frame Buffer support' CONFIG_FB_HIT fi + if [ "$CONFIG_DECSTATION" = "y" ]; then + if [ "$CONFIG_TC" = "y" ]; then + bool ' PMAG-BA TURBOchannel framebuffer support' CONFIG_FB_PMAG_BA + bool ' PMAGB-B TURBOchannel framebuffer spport' CONFIG_FB_PMAGB_B + bool ' Maxine (Personal DECstation) onboard framebuffer spport' CONFIG_FB_MAXINE + fi + fi + if [ "$CONFIG_NINO" = "y" ]; then + bool ' TMPTX3912/PR31700 frame buffer support' CONFIG_FB_TX3912 + fi + if [ "$CONFIG_DECSTATION" = "y" ]; then + if [ "$CONFIG_TC" = "y" ]; then + bool ' PMAG-BA TURBOchannel framebuffer support' CONFIG_FB_PMAG_BA + bool ' PMAGB-B TURBOchannel framebuffer spport' CONFIG_FB_PMAGB_B + bool ' Maxine (Personal DECstation) onboard framebuffer spport' CONFIG_FB_MAXINE + fi + fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate ' Virtual Frame Buffer support (ONLY FOR TESTING!)' CONFIG_FB_VIRTUAL fi @@ -202,24 +235,28 @@ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ - "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then + "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ + "$CONFIG_FB_TX3912" = "y" ]; then define_tristate CONFIG_FBCON_MFB y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ - "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then + "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ + "$CONFIG_FB_TX3912" = "m" ]; then define_tristate CONFIG_FBCON_MFB m fi fi if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ - "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" ]; then + "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ + "$CONFIG_FB_TX3912" = "y" ]; then define_tristate CONFIG_FBCON_CFB2 y define_tristate CONFIG_FBCON_CFB4 y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ - "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then + "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ + "$CONFIG_FB_TX3912" = "m" ]; then define_tristate CONFIG_FBCON_CFB2 m define_tristate CONFIG_FBCON_CFB4 m fi @@ -236,9 +273,11 @@ "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ "$CONFIG_FB_P9100" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ - "$CONFIG_FB_RIVA" = "y" -o \ + "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \ + "$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \ + "$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \ "$CONFIG_FB_SIS" = "y" ]; then define_tristate CONFIG_FBCON_CFB8 y else @@ -256,14 +295,17 @@ "$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \ "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ - "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" ]; then + "$CONFIG_FB_PMAG_BA" = "m" -o "$CONFIG_FB_PMAGB_B" = "m" -o \ + "$CONFIG_FB_MAXINE" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ + "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ + "$CONFIG_FB_TX3912" = "m" ]; then define_tristate CONFIG_FBCON_CFB8 m fi fi if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \ - "$CONFIG_FB_Q40" = "y" -o \ + "$CONFIG_FB_Q40" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ @@ -272,7 +314,7 @@ "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \ - "$CONFIG_FB_PVR2" = "y" ]; then + "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" ]; then define_tristate CONFIG_FBCON_CFB16 y else if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ @@ -286,22 +328,25 @@ "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \ "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ - "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_PVR2" = "m" ]; then + "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ + "$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" ]; then define_tristate CONFIG_FBCON_CFB16 m fi fi if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" -o \ "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ - "$CONFIG_FB_ATY128" = "y" -o \ - "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PVR2" = "y" ]; then + "$CONFIG_FB_ATY128" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ + "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \ + "$CONFIG_FB_VOODOO1" = "y" ]; then define_tristate CONFIG_FBCON_CFB24 y else if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" -o \ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ - "$CONFIG_FB_ATY128" = "m" -o \ - "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_PVR2" = "m" ]; then + "$CONFIG_FB_ATY128" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ + "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \ + "$CONFIG_FB_VOODOO1" = "m" ]; then define_tristate CONFIG_FBCON_CFB24 m fi fi @@ -312,8 +357,9 @@ "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ "$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \ + "$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \ "$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_SIS" = "y" -o \ - "$CONFIG_FB_PVR2" = "y" ]; then + "$CONFIG_FB_VOODOO1" = "y" ]; then define_tristate CONFIG_FBCON_CFB32 y else if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ @@ -322,9 +368,9 @@ "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ - "$CONFIG_FB_3DFX" = "m" -o \ + "$CONFIG_FB_3DFX" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ - "$CONFIG_FB_PVR2" = "m" ]; then + "$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" ]; then define_tristate CONFIG_FBCON_CFB32 m fi fi @@ -370,6 +416,9 @@ if [ "$CONFIG_FB_HGA" = "m" ]; then define_tristate CONFIG_FBCON_HGA m fi + fi + if [ "$CONFIG_FB_STI" = "y" ]; then + define_tristate CONFIG_FBCON_STI y fi fi bool ' Support only 8 pixels wide fonts' CONFIG_FBCON_FONTWIDTH8_ONLY diff -u --recursive --new-file v2.4.9/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.4.9/linux/drivers/video/Makefile Sun Aug 12 13:28:00 2001 +++ linux/drivers/video/Makefile Fri Sep 14 14:04:07 2001 @@ -22,6 +22,7 @@ obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o +obj-$(CONFIG_STI_CONSOLE) += sticon.o sticon-bmode.o sticore.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o @@ -47,6 +48,7 @@ obj-$(CONFIG_FB_Q40) += q40fb.o obj-$(CONFIG_FB_ATARI) += atafb.o obj-$(CONFIG_FB_ATY128) += aty128fb.o +obj-$(CONFIG_FB_RADEON) += radeonfb.o obj-$(CONFIG_FB_IGA) += igafb.o obj-$(CONFIG_FB_CONTROL) += controlfb.o obj-$(CONFIG_FB_PLATINUM) += platinumfb.o @@ -77,6 +79,12 @@ obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o +obj-$(CONFIG_FB_STI) += stifb.o sticore.o fbgen.o +obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o +obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o +obj-$(CONFIG_FB_MAXINE) += maxinefb.o +obj-$(CONFIG_FB_TX3912) += tx3912fb.o + subdir-$(CONFIG_FB_MATROX) += matrox ifeq ($(CONFIG_FB_MATROX),y) @@ -106,6 +114,7 @@ obj-$(CONFIG_FB_HIT) += hitfb.o fbgen.o obj-$(CONFIG_FB_E1355) += epson1355fb.o fbgen.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o +obj-$(CONFIG_FB_VOODOO1) += sstfb.o # Generic Low Level Drivers @@ -125,6 +134,7 @@ obj-$(CONFIG_FBCON_MFB) += fbcon-mfb.o obj-$(CONFIG_FBCON_VGA) += fbcon-vga.o obj-$(CONFIG_FBCON_HGA) += fbcon-hga.o +obj-$(CONFIG_FBCON_STI) += fbcon-sti.o include $(TOPDIR)/Rules.make @@ -140,3 +150,4 @@ -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c promcon_tbl.o: promcon_tbl.c $(TOPDIR)/include/linux/types.h + diff -u --recursive --new-file v2.4.9/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c --- v2.4.9/linux/drivers/video/S3triofb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/S3triofb.c Thu Sep 13 16:04:43 2001 @@ -858,3 +858,5 @@ fontwidthmask: FONTWIDTH(8) }; #endif + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c --- v2.4.9/linux/drivers/video/acornfb.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/video/acornfb.c Thu Sep 13 16:04:43 2001 @@ -1771,3 +1771,5 @@ return -EINVAL; return 0; } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/amifb.c linux/drivers/video/amifb.c --- v2.4.9/linux/drivers/video/amifb.c Mon Aug 27 12:41:46 2001 +++ linux/drivers/video/amifb.c Thu Sep 13 16:04:43 2001 @@ -911,7 +911,7 @@ #define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb) -static const char *mode_option __initdata = NULL; +static char *mode_option __initdata = NULL; static int round_down_bpp = 1; /* for mode probing */ /* @@ -3334,6 +3334,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return amifb_init(); diff -u --recursive --new-file v2.4.9/linux/drivers/video/atafb.c linux/drivers/video/atafb.c --- v2.4.9/linux/drivers/video/atafb.c Wed Apr 18 11:49:12 2001 +++ linux/drivers/video/atafb.c Thu Sep 13 16:04:43 2001 @@ -3137,6 +3137,8 @@ } #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return atafb_init(); diff -u --recursive --new-file v2.4.9/linux/drivers/video/aty/atyfb_base.c linux/drivers/video/aty/atyfb_base.c --- v2.4.9/linux/drivers/video/aty/atyfb_base.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/video/aty/atyfb_base.c Thu Sep 13 16:04:43 2001 @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/drivers/video/bwtwofb.c linux/drivers/video/bwtwofb.c --- v2.4.9/linux/drivers/video/bwtwofb.c Sun Feb 18 19:49:55 2001 +++ linux/drivers/video/bwtwofb.c Thu Sep 13 16:04:43 2001 @@ -263,3 +263,5 @@ return idstring; } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/cgfourteenfb.c linux/drivers/video/cgfourteenfb.c --- v2.4.9/linux/drivers/video/cgfourteenfb.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/video/cgfourteenfb.c Thu Sep 13 16:04:43 2001 @@ -72,6 +72,8 @@ #define CG14_MCR_PIXMODE_16 2 #define CG14_MCR_PIXMODE_32 3 +MODULE_LICENSE("GPL"); + struct cg14_regs{ volatile u8 mcr; /* Master Control Reg */ volatile u8 ppr; /* Packed Pixel Reg */ diff -u --recursive --new-file v2.4.9/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c --- v2.4.9/linux/drivers/video/cgsixfb.c Sun Feb 18 19:49:55 2001 +++ linux/drivers/video/cgsixfb.c Thu Sep 13 16:04:43 2001 @@ -128,6 +128,8 @@ #define CG6_THC_MISC_INT (1 << 4) #define CG6_THC_MISC_INIT 0x9f +MODULE_LICENSE("GPL"); + /* The contents are unknown */ struct cg6_tec { volatile int tec_matrix; diff -u --recursive --new-file v2.4.9/linux/drivers/video/cgthreefb.c linux/drivers/video/cgthreefb.c --- v2.4.9/linux/drivers/video/cgthreefb.c Sun Feb 18 19:49:55 2001 +++ linux/drivers/video/cgthreefb.c Thu Sep 13 16:04:43 2001 @@ -44,6 +44,8 @@ #define CG3_SR_ID_MONO 0x02 #define CG3_SR_ID_MONO_ECL 0x03 +MODULE_LICENSE("GPL"); + enum cg3_type { CG3_AT_66HZ = 0, CG3_AT_76HZ, diff -u --recursive --new-file v2.4.9/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c --- v2.4.9/linux/drivers/video/chipsfb.c Sat May 19 18:14:38 2001 +++ linux/drivers/video/chipsfb.c Thu Sep 13 16:04:43 2001 @@ -739,3 +739,5 @@ return PBOOK_SLEEP_OK; } #endif /* CONFIG_PMAC_PBOOK */ + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c --- v2.4.9/linux/drivers/video/controlfb.c Mon Aug 27 12:41:46 2001 +++ linux/drivers/video/controlfb.c Thu Sep 13 16:04:43 2001 @@ -236,6 +236,8 @@ /******************** The functions for controlfb_ops ********************/ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { struct device_node *dp; diff -u --recursive --new-file v2.4.9/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c --- v2.4.9/linux/drivers/video/creatorfb.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/video/creatorfb.c Thu Sep 13 16:04:43 2001 @@ -920,3 +920,5 @@ return idstring; } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c --- v2.4.9/linux/drivers/video/cyber2000fb.c Mon Aug 27 12:41:46 2001 +++ linux/drivers/video/cyber2000fb.c Fri Sep 14 14:40:00 2001 @@ -1285,7 +1285,7 @@ cfb->mclk_div = cyber2000_grphr(MCLK_DIV); } #endif -#ifdef __i386__ +#if defined(__i386__) || defined(__x86_64__) /* * x86 is simple, we just do regular outb's instead of * cyber2000_outb. @@ -1673,6 +1673,7 @@ } #ifdef MODULE +MODULE_LICENSE("GPL"); module_init(cyber2000fb_init); #endif module_exit(cyberpro_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c --- v2.4.9/linux/drivers/video/cyberfb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/cyberfb.c Thu Sep 13 16:04:43 2001 @@ -1251,6 +1251,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return cyberfb_init(); diff -u --recursive --new-file v2.4.9/linux/drivers/video/dn_cfb4.c linux/drivers/video/dn_cfb4.c --- v2.4.9/linux/drivers/video/dn_cfb4.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/dn_cfb4.c Thu Sep 13 16:04:43 2001 @@ -505,3 +505,5 @@ revc: rev_char_apollofb, fontwidthmask: FONTWIDTH(8) }; + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/dn_cfb8.c linux/drivers/video/dn_cfb8.c --- v2.4.9/linux/drivers/video/dn_cfb8.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/dn_cfb8.c Thu Sep 13 16:04:43 2001 @@ -553,3 +553,5 @@ revc: rev_char_apollofb, fontwidthmask: FONTWIDTH(8) }; + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/dnfb.c linux/drivers/video/dnfb.c --- v2.4.9/linux/drivers/video/dnfb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/dnfb.c Thu Sep 13 16:04:43 2001 @@ -509,3 +509,5 @@ revc: rev_char_apollofb, fontwidthmask: FONTWIDTH(8) }; + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/epson1355fb.c linux/drivers/video/epson1355fb.c --- v2.4.9/linux/drivers/video/epson1355fb.c Sun May 20 12:11:39 2001 +++ linux/drivers/video/epson1355fb.c Thu Sep 13 16:04:43 2001 @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -538,3 +538,4 @@ /* ... */ } +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-afb.c linux/drivers/video/fbcon-afb.c --- v2.4.9/linux/drivers/video/fbcon-afb.c Mon Jul 24 18:24:25 2000 +++ linux/drivers/video/fbcon-afb.c Thu Sep 13 16:04:43 2001 @@ -422,6 +422,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-cfb16.c linux/drivers/video/fbcon-cfb16.c --- v2.4.9/linux/drivers/video/fbcon-cfb16.c Mon Jul 24 18:24:25 2000 +++ linux/drivers/video/fbcon-cfb16.c Thu Sep 13 16:04:43 2001 @@ -292,6 +292,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-cfb2.c linux/drivers/video/fbcon-cfb2.c --- v2.4.9/linux/drivers/video/fbcon-cfb2.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-cfb2.c Thu Sep 13 16:04:43 2001 @@ -201,6 +201,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-cfb24.c linux/drivers/video/fbcon-cfb24.c --- v2.4.9/linux/drivers/video/fbcon-cfb24.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-cfb24.c Thu Sep 13 16:04:43 2001 @@ -304,6 +304,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-cfb32.c linux/drivers/video/fbcon-cfb32.c --- v2.4.9/linux/drivers/video/fbcon-cfb32.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-cfb32.c Thu Sep 13 16:04:43 2001 @@ -278,6 +278,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-cfb4.c linux/drivers/video/fbcon-cfb4.c --- v2.4.9/linux/drivers/video/fbcon-cfb4.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-cfb4.c Thu Sep 13 16:04:43 2001 @@ -205,6 +205,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-cfb8.c linux/drivers/video/fbcon-cfb8.c --- v2.4.9/linux/drivers/video/fbcon-cfb8.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-cfb8.c Thu Sep 13 16:04:43 2001 @@ -268,6 +268,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-hga.c linux/drivers/video/fbcon-hga.c --- v2.4.9/linux/drivers/video/fbcon-hga.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-hga.c Thu Sep 13 16:04:43 2001 @@ -225,6 +225,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-ilbm.c linux/drivers/video/fbcon-ilbm.c --- v2.4.9/linux/drivers/video/fbcon-ilbm.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-ilbm.c Thu Sep 13 16:04:43 2001 @@ -270,6 +270,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-iplan2p2.c linux/drivers/video/fbcon-iplan2p2.c --- v2.4.9/linux/drivers/video/fbcon-iplan2p2.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-iplan2p2.c Thu Sep 13 16:04:43 2001 @@ -450,6 +450,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-iplan2p4.c linux/drivers/video/fbcon-iplan2p4.c --- v2.4.9/linux/drivers/video/fbcon-iplan2p4.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-iplan2p4.c Thu Sep 13 16:04:43 2001 @@ -470,6 +470,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-iplan2p8.c linux/drivers/video/fbcon-iplan2p8.c --- v2.4.9/linux/drivers/video/fbcon-iplan2p8.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-iplan2p8.c Thu Sep 13 16:04:43 2001 @@ -507,6 +507,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-mac.c linux/drivers/video/fbcon-mac.c --- v2.4.9/linux/drivers/video/fbcon-mac.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-mac.c Thu Sep 13 16:04:43 2001 @@ -458,6 +458,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-mfb.c linux/drivers/video/fbcon-mfb.c --- v2.4.9/linux/drivers/video/fbcon-mfb.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-mfb.c Thu Sep 13 16:04:43 2001 @@ -190,6 +190,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-sti.c linux/drivers/video/fbcon-sti.c --- v2.4.9/linux/drivers/video/fbcon-sti.c Mon Aug 27 12:41:46 2001 +++ linux/drivers/video/fbcon-sti.c Thu Sep 13 16:04:43 2001 @@ -332,3 +332,5 @@ clear_margins: fbcon_sti_clear_margins, fontwidthmask: FONTWIDTH(8) }; + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-vga-planes.c linux/drivers/video/fbcon-vga-planes.c --- v2.4.9/linux/drivers/video/fbcon-vga-planes.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-vga-planes.c Thu Sep 13 16:04:43 2001 @@ -347,6 +347,8 @@ }; #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; diff -u --recursive --new-file v2.4.9/linux/drivers/video/fbcon-vga.c linux/drivers/video/fbcon-vga.c --- v2.4.9/linux/drivers/video/fbcon-vga.c Mon Jul 24 18:24:26 2000 +++ linux/drivers/video/fbcon-vga.c Thu Sep 13 16:04:43 2001 @@ -188,6 +188,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { return 0; 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 Sun Sep 16 21:22:50 2001 @@ -1150,11 +1150,13 @@ } } scr_writew(c, d); + console_conditional_schedule(); s++; d++; } while (s < le); if (s > start) p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); + console_conditional_schedule(); if (offset > 0) line++; else { @@ -2206,6 +2208,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 +2286,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 +2503,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/fbmem.c linux/drivers/video/fbmem.c --- v2.4.9/linux/drivers/video/fbmem.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/video/fbmem.c Fri Sep 14 14:40:00 2001 @@ -593,7 +593,7 @@ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED; #elif defined(__alpha__) /* Caching is off in the I/O space quadrant by design. */ -#elif defined(__i386__) +#elif defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; #elif defined(__mips__) diff -u --recursive --new-file v2.4.9/linux/drivers/video/fm2fb.c linux/drivers/video/fm2fb.c --- v2.4.9/linux/drivers/video/fm2fb.c Tue Nov 7 10:59:43 2000 +++ linux/drivers/video/fm2fb.c Thu Sep 13 16:04:43 2001 @@ -528,3 +528,5 @@ else fb_set_cmap(fb_default_cmap(256), 1, fm2fb_setcolreg, info); } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/g364fb.c linux/drivers/video/g364fb.c --- v2.4.9/linux/drivers/video/g364fb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/g364fb.c Thu Sep 13 16:04:43 2001 @@ -487,3 +487,5 @@ fb_set_cmap(fb_default_cmap(1< #include #include -#include +#include #include #include #include @@ -382,6 +382,7 @@ } #ifdef MODULE +MODULE_LICENSE("GPL"); module_init(maxinefb_init); #endif module_exit(maxinefb_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c --- v2.4.9/linux/drivers/video/mdacon.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/video/mdacon.c Thu Sep 13 16:04:43 2001 @@ -615,6 +615,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + int init_module(void) { mda_console_init(); diff -u --recursive --new-file v2.4.9/linux/drivers/video/newport_con.c linux/drivers/video/newport_con.c --- v2.4.9/linux/drivers/video/newport_con.c Mon Oct 16 12:53:18 2000 +++ linux/drivers/video/newport_con.c Fri Sep 14 14:04:07 2001 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,14 @@ #define FONT_DATA ((unsigned char *)font_vga_8x16.data) +/* borrowed from fbcon.c */ +#define REFCOUNT(fd) (((int *)(fd))[-1]) +#define FNTSIZE(fd) (((int *)(fd))[-2]) +#define FNTCHARCNT(fd) (((int *)(fd))[-3]) +#define FONT_EXTRA_WORDS 3 + +static unsigned char *font_data[MAX_NR_CONSOLES]; + extern struct newport_regs *npregs; static int logo_active; @@ -65,114 +74,117 @@ static inline void newport_render_background(int xstart, int ystart, int xend, int yend, int ci) { - newport_wait(); - npregs->set.wrmask = 0xffffffff; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.colori = ci; - npregs->set.xystarti = (xstart << 16) | ((ystart + topscan) & 0x3ff); - npregs->go.xyendi = ((xend + 7) << 16) | ((yend + topscan + 15) & 0x3ff); + newport_wait(); + npregs->set.wrmask = 0xffffffff; + npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX + | NPORT_DMODE0_STOPY); + npregs->set.colori = ci; + npregs->set.xystarti = + (xstart << 16) | ((ystart + topscan) & 0x3ff); + npregs->go.xyendi = + ((xend + 7) << 16) | ((yend + topscan + 15) & 0x3ff); } static inline void newport_init_cmap(void) { - unsigned short i; - - for(i = 0; i < 16; i++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, color_table[i]); - newport_cmap_setrgb(npregs, - default_red[i], - default_grn[i], - default_blu[i]); - } + unsigned short i; + + for (i = 0; i < 16; i++) { + newport_bfwait(); + newport_cmap_setaddr(npregs, color_table[i]); + newport_cmap_setrgb(npregs, + default_red[i], + default_grn[i], default_blu[i]); + } } static inline void newport_show_logo(void) { - unsigned long i; + unsigned long i; - for(i = 0; i < LINUX_LOGO_COLORS; i++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, i + 0x20); - newport_cmap_setrgb(npregs, - linux_logo_red[i], - linux_logo_green[i], - linux_logo_blue[i]); - } - - newport_wait(); - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_CHOST); - - npregs->set.xystarti = ((newport_xsize - LOGO_W) << 16) | (0); - npregs->set.xyendi = ((newport_xsize - 1) << 16); - newport_wait(); + for (i = 0; i < LINUX_LOGO_COLORS; i++) { + newport_bfwait(); + newport_cmap_setaddr(npregs, i + 0x20); + newport_cmap_setrgb(npregs, + linux_logo_red[i], + linux_logo_green[i], + linux_logo_blue[i]); + } + + newport_wait(); + npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_CHOST); - for (i = 0; i < LOGO_W * LOGO_H; i++) - npregs->go.hostrw0 = linux_logo[i] << 24; + npregs->set.xystarti = ((newport_xsize - LOGO_W) << 16) | (0); + npregs->set.xyendi = ((newport_xsize - 1) << 16); + newport_wait(); + + for (i = 0; i < LOGO_W * LOGO_H; i++) + npregs->go.hostrw0 = linux_logo[i] << 24; } static inline void newport_clear_screen(int xstart, int ystart, int xend, - int yend, int ci) { - if (logo_active) - return; - - newport_wait(); - npregs->set.wrmask = 0xffffffff; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.colori = ci; - npregs->set.xystarti = (xstart << 16) | ystart; - npregs->go.xyendi = (xend << 16) | yend; + int yend, int ci) +{ + if (logo_active) + return; + + newport_wait(); + npregs->set.wrmask = 0xffffffff; + npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX + | NPORT_DMODE0_STOPY); + npregs->set.colori = ci; + npregs->set.xystarti = (xstart << 16) | ystart; + npregs->go.xyendi = (xend << 16) | yend; } static inline void newport_clear_lines(int ystart, int yend, int ci) { - ystart = ((ystart << 4) + topscan) & 0x3ff; - yend = ((yend << 4) + topscan + 15) & 0x3ff; - newport_clear_screen (0, ystart, 1280+63, yend, ci); -} - -void newport_reset (void) -{ - unsigned short treg; - int i; - - newport_wait(); - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EVIDEO)); - - treg = newport_vc2_get(npregs, VC2_IREG_CENTRY); - newport_vc2_set(npregs, VC2_IREG_RADDR, treg); - npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | - NPORT_DMODE_W2 | VC2_PROTOCOL); - for(i = 0; i < 128; i++) { - newport_bfwait(); - if (i == 92 || i == 94) - npregs->set.dcbdata0.byshort.s1 = 0xff00; - else - npregs->set.dcbdata0.byshort.s1 = 0x0000; - } + ystart = ((ystart << 4) + topscan) & 0x3ff; + yend = ((yend << 4) + topscan + 15) & 0x3ff; + newport_clear_screen(0, ystart, 1280 + 63, yend, ci); +} + +void newport_reset(void) +{ + unsigned short treg; + int i; + + newport_wait(); + treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); + newport_vc2_set(npregs, VC2_IREG_CONTROL, + (treg | VC2_CTRL_EVIDEO)); + + treg = newport_vc2_get(npregs, VC2_IREG_CENTRY); + newport_vc2_set(npregs, VC2_IREG_RADDR, treg); + npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | + NPORT_DMODE_W2 | VC2_PROTOCOL); + for (i = 0; i < 128; i++) { + newport_bfwait(); + if (i == 92 || i == 94) + npregs->set.dcbdata0.byshort.s1 = 0xff00; + else + npregs->set.dcbdata0.byshort.s1 = 0x0000; + } - newport_init_cmap(); + newport_init_cmap(); - /* turn off popup plane */ - npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL | - XM9_CRS_CONFIG | NPORT_DMODE_W1); - npregs->set.dcbdata0.bybytes.b3 &= ~XM9_PUPMODE; - npregs->set.dcbmode = (DCB_XMAP1 | R_DCB_XMAP9_PROTOCOL | - XM9_CRS_CONFIG | NPORT_DMODE_W1); - npregs->set.dcbdata0.bybytes.b3 &= ~XM9_PUPMODE; - - topscan = 0; - npregs->cset.topscan = 0x3ff; - npregs->cset.xywin = (4096 << 16) | 4096; + /* turn off popup plane */ + npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL | + XM9_CRS_CONFIG | NPORT_DMODE_W1); + npregs->set.dcbdata0.bybytes.b3 &= ~XM9_PUPMODE; + npregs->set.dcbmode = (DCB_XMAP1 | R_DCB_XMAP9_PROTOCOL | + XM9_CRS_CONFIG | NPORT_DMODE_W1); + npregs->set.dcbdata0.bybytes.b3 &= ~XM9_PUPMODE; + + topscan = 0; + npregs->cset.topscan = 0x3ff; + npregs->cset.xywin = (4096 << 16) | 4096; - /* Clear the screen. */ - newport_clear_screen(0,0,1280+63,1024,0); + /* Clear the screen. */ + newport_clear_screen(0, 0, 1280 + 63, 1024, 0); } /* @@ -181,395 +193,508 @@ */ void newport_get_screensize(void) { - int i,cols; - unsigned short ventry,treg; - unsigned short linetable[128]; /* should be enough */ - - ventry = newport_vc2_get (npregs, VC2_IREG_VENTRY); - newport_vc2_set(npregs, VC2_IREG_RADDR, ventry); - npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | - NPORT_DMODE_W2 | VC2_PROTOCOL); - for(i = 0; i < 128; i++) { - newport_bfwait(); - linetable[i] = npregs->set.dcbdata0.byshort.s1; - } - - newport_xsize = newport_ysize = 0; - for (i = 0; linetable[i+1] && (i < sizeof(linetable)); i+=2) { - cols = 0; - newport_vc2_set(npregs, VC2_IREG_RADDR, linetable[i]); - npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | + int i, cols; + unsigned short ventry, treg; + unsigned short linetable[128]; /* should be enough */ + + ventry = newport_vc2_get(npregs, VC2_IREG_VENTRY); + newport_vc2_set(npregs, VC2_IREG_RADDR, ventry); + npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | NPORT_DMODE_W2 | VC2_PROTOCOL); - do { - newport_bfwait(); - treg = npregs->set.dcbdata0.byshort.s1; - if ((treg & 1) == 0) - cols += (treg >> 7) & 0xfe; - if ((treg & 0x80) == 0) { + for (i = 0; i < 128; i++) { newport_bfwait(); - treg = npregs->set.dcbdata0.byshort.s1; - } - } while ((treg & 0x8000) == 0); - if (cols) { - if (cols > newport_xsize) - newport_xsize = cols; - newport_ysize += linetable[i+1]; + linetable[i] = npregs->set.dcbdata0.byshort.s1; } - } - printk ("NG1: Screensize %dx%d\n",newport_xsize,newport_ysize); + + newport_xsize = newport_ysize = 0; + for (i = 0; linetable[i + 1] && (i < sizeof(linetable)); i += 2) { + cols = 0; + newport_vc2_set(npregs, VC2_IREG_RADDR, linetable[i]); + npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | + NPORT_DMODE_W2 | VC2_PROTOCOL); + do { + newport_bfwait(); + treg = npregs->set.dcbdata0.byshort.s1; + if ((treg & 1) == 0) + cols += (treg >> 7) & 0xfe; + if ((treg & 0x80) == 0) { + newport_bfwait(); + treg = npregs->set.dcbdata0.byshort.s1; + } + } while ((treg & 0x8000) == 0); + if (cols) { + if (cols > newport_xsize) + newport_xsize = cols; + newport_ysize += linetable[i + 1]; + } + } + printk("NG1: Screensize %dx%d\n", newport_xsize, newport_ysize); } static void newport_get_revisions(void) { - unsigned int tmp; - unsigned int board_rev; - unsigned int rex3_rev; - unsigned int vc2_rev; - unsigned int cmap_rev; - unsigned int xmap9_rev; - unsigned int bt445_rev; - unsigned int bitplanes; - - rex3_rev = npregs->cset.status & NPORT_STAT_VERS; - - npregs->set.dcbmode = (DCB_CMAP0 | NCMAP_PROTOCOL | - NCMAP_REGADDR_RREG | NPORT_DMODE_W1); - tmp = npregs->set.dcbdata0.bybytes.b3; - cmap_rev = tmp & 7; - board_rev = (tmp >> 4) & 7; - bitplanes = ((board_rev > 1) && (tmp & 0x80)) ? 8 : 24; - - npregs->set.dcbmode = (DCB_CMAP1 | NCMAP_PROTOCOL | - NCMAP_REGADDR_RREG | NPORT_DMODE_W1); - tmp = npregs->set.dcbdata0.bybytes.b3; - if ((tmp & 7) < cmap_rev) - cmap_rev = (tmp & 7); - - vc2_rev = (newport_vc2_get(npregs, VC2_IREG_CONFIG) >> 5) & 7; - - npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL | - XM9_CRS_REVISION | NPORT_DMODE_W1); - xmap9_rev = npregs->set.dcbdata0.bybytes.b3 & 7; - - npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL | - BT445_CSR_ADDR_REG | NPORT_DMODE_W1); - npregs->set.dcbdata0.bybytes.b3 = BT445_REVISION_REG; - npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL | - BT445_CSR_REVISION | NPORT_DMODE_W1); - bt445_rev = (npregs->set.dcbdata0.bybytes.b3 >> 4) - 0x0a; + unsigned int tmp; + unsigned int board_rev; + unsigned int rex3_rev; + unsigned int vc2_rev; + unsigned int cmap_rev; + unsigned int xmap9_rev; + unsigned int bt445_rev; + unsigned int bitplanes; + + rex3_rev = npregs->cset.status & NPORT_STAT_VERS; + + npregs->set.dcbmode = (DCB_CMAP0 | NCMAP_PROTOCOL | + NCMAP_REGADDR_RREG | NPORT_DMODE_W1); + tmp = npregs->set.dcbdata0.bybytes.b3; + cmap_rev = tmp & 7; + board_rev = (tmp >> 4) & 7; + bitplanes = ((board_rev > 1) && (tmp & 0x80)) ? 8 : 24; + + npregs->set.dcbmode = (DCB_CMAP1 | NCMAP_PROTOCOL | + NCMAP_REGADDR_RREG | NPORT_DMODE_W1); + tmp = npregs->set.dcbdata0.bybytes.b3; + if ((tmp & 7) < cmap_rev) + cmap_rev = (tmp & 7); + + vc2_rev = (newport_vc2_get(npregs, VC2_IREG_CONFIG) >> 5) & 7; + + npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL | + XM9_CRS_REVISION | NPORT_DMODE_W1); + xmap9_rev = npregs->set.dcbdata0.bybytes.b3 & 7; + + npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL | + BT445_CSR_ADDR_REG | NPORT_DMODE_W1); + npregs->set.dcbdata0.bybytes.b3 = BT445_REVISION_REG; + npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL | + BT445_CSR_REVISION | NPORT_DMODE_W1); + bt445_rev = (npregs->set.dcbdata0.bybytes.b3 >> 4) - 0x0a; #define L(a) (char)('A'+(a)) - printk ("NG1: Revision %d, %d bitplanes, REX3 revision %c, VC2 revision %c, xmap9 revision %c, cmap revision %c, bt445 revision %c\n", - board_rev,bitplanes,L(rex3_rev),L(vc2_rev), L(xmap9_rev), - L(cmap_rev ? (cmap_rev+1):0),L(bt445_rev)); + printk + ("NG1: Revision %d, %d bitplanes, REX3 revision %c, VC2 revision %c, xmap9 revision %c, cmap revision %c, bt445 revision %c\n", + board_rev, bitplanes, L(rex3_rev), L(vc2_rev), L(xmap9_rev), + L(cmap_rev ? (cmap_rev + 1) : 0), L(bt445_rev)); #undef L - if (board_rev == 3) /* I don't know all affected revisions */ - xcurs_correction = 21; + if (board_rev == 3) /* I don't know all affected revisions */ + xcurs_correction = 21; } #ifdef MODULE static const char *newport_startup(void) #else -static const char * __init newport_startup(void) +static const char *__init newport_startup(void) #endif { - struct newport_regs *p; + int i; + struct newport_regs *p; + + npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000); + + p = npregs; + p->cset.config = NPORT_CFG_GD0; + + if (newport_wait()) { + return NULL; + } + + p->set.xstarti = TESTVAL; + if (p->set._xstart.word != XSTI_TO_FXSTART(TESTVAL)) + return NULL; - npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000); - - p = npregs; - p->cset.config = NPORT_CFG_GD0; - - if(newport_wait()) { - return NULL; - } - - p->set.xstarti = TESTVAL; if(p->set._xstart.word != XSTI_TO_FXSTART(TESTVAL)) { - return NULL; - } - - newport_reset (); - newport_get_revisions(); - newport_get_screensize(); - - // gfx_init (display_desc); - - return "SGI Newport"; + for (i = 0; i < MAX_NR_CONSOLES; i++) + font_data[i] = FONT_DATA; + + newport_reset(); + newport_get_revisions(); + newport_get_screensize(); + + /* gfx_init (display_desc); */ + + return "SGI Newport"; } static void newport_init(struct vc_data *vc, int init) { - vc->vc_cols = newport_xsize / 8; - vc->vc_rows = newport_ysize / 16; - vc->vc_can_do_color = 1; -} - -static void newport_clear(struct vc_data *vc, int sy, int sx, int height, int width) -{ - int xend = ((sx + width) << 3) - 1; - int ystart = ((sy << 4) + topscan) & 0x3ff; - int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff; - - if (logo_active) - return; - - if (ystart < yend) { - newport_clear_screen(sx << 3, ystart, xend, yend, - (vc->vc_color & 0xf0) >> 4); - } else { - newport_clear_screen(sx << 3, ystart, xend, 1023, - (vc->vc_color & 0xf0) >> 4); - newport_clear_screen(sx << 3, 0, xend, yend, - (vc->vc_color & 0xf0) >> 4); - } -} - -static void newport_putc(struct vc_data *vc, int charattr, int ypos, int xpos) -{ - unsigned char *p; - - p = &FONT_DATA[(charattr & 0xff) << 4]; - charattr = (charattr >> 8) & 0xff; - xpos <<= 3; - ypos <<= 4; - - newport_render_background(xpos, ypos, xpos, ypos, (charattr & 0xf0) >> 4); - - /* Set the color and drawing mode. */ - newport_wait(); - npregs->set.colori = charattr & 0xf; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - - /* Set coordinates for bitmap operation. */ - npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff); - npregs->set.xyendi = ((xpos + 7) << 16); - newport_wait(); - - /* Go, baby, go... */ - RENDER(npregs, p); + vc->vc_cols = newport_xsize / 8; + vc->vc_rows = newport_ysize / 16; + vc->vc_can_do_color = 1; } -static void newport_putcs(struct vc_data *vc, const unsigned short *s, - int count, int ypos, int xpos) +static void newport_clear(struct vc_data *vc, int sy, int sx, int height, + int width) { - int i; - int charattr; - unsigned char *p; - - charattr = (*s >> 8) & 0xff; - - xpos <<= 3; - ypos <<= 4; - - if (!logo_active) - /* Clear the area behing the string */ - newport_render_background(xpos, ypos, xpos + ((count-1) << 3), ypos, - (charattr & 0xf0) >> 4); + int xend = ((sx + width) << 3) - 1; + int ystart = ((sy << 4) + topscan) & 0x3ff; + int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff; - newport_wait(); + if (logo_active) + return; - /* Set the color and drawing mode. */ - npregs->set.colori = charattr & 0xf; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - - for (i = 0; i < count; i++, xpos += 8) { - p = &FONT_DATA[(s[i] & 0xff) << 4]; + if (ystart < yend) { + newport_clear_screen(sx << 3, ystart, xend, yend, + (vc->vc_color & 0xf0) >> 4); + } else { + newport_clear_screen(sx << 3, ystart, xend, 1023, + (vc->vc_color & 0xf0) >> 4); + newport_clear_screen(sx << 3, 0, xend, yend, + (vc->vc_color & 0xf0) >> 4); + } +} +static void newport_putc(struct vc_data *vc, int charattr, int ypos, + int xpos) +{ + unsigned char *p; + + p = &font_data[vc->vc_num][(charattr & 0xff) << 4]; + charattr = (charattr >> 8) & 0xff; + xpos <<= 3; + ypos <<= 4; + + newport_render_background(xpos, ypos, xpos, ypos, + (charattr & 0xf0) >> 4); + + /* Set the color and drawing mode. */ newport_wait(); + npregs->set.colori = charattr & 0xf; + npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | + NPORT_DMODE0_L32); /* Set coordinates for bitmap operation. */ npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff); npregs->set.xyendi = ((xpos + 7) << 16); + newport_wait(); /* Go, baby, go... */ RENDER(npregs, p); - } +} + +static void newport_putcs(struct vc_data *vc, const unsigned short *s, + int count, int ypos, int xpos) +{ + int i; + int charattr; + unsigned char *p; + + charattr = (*s >> 8) & 0xff; + + xpos <<= 3; + ypos <<= 4; + + if (!logo_active) + /* Clear the area behing the string */ + newport_render_background(xpos, ypos, + xpos + ((count - 1) << 3), ypos, + (charattr & 0xf0) >> 4); + + newport_wait(); + + /* Set the color and drawing mode. */ + npregs->set.colori = charattr & 0xf; + npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | + NPORT_DMODE0_L32); + + for (i = 0; i < count; i++, xpos += 8) { + p = &font_data[vc->vc_num][(s[i] & 0xff) << 4]; + + newport_wait(); + + /* Set coordinates for bitmap operation. */ + npregs->set.xystarti = + (xpos << 16) | ((ypos + topscan) & 0x3ff); + npregs->set.xyendi = ((xpos + 7) << 16); + + /* Go, baby, go... */ + RENDER(npregs, p); + } } static void newport_cursor(struct vc_data *vc, int mode) { - unsigned short treg; - int xcurs, ycurs; - - switch (mode) { - case CM_ERASE: - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP))); - break; + unsigned short treg; + int xcurs, ycurs; - case CM_MOVE: - case CM_DRAW: - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP)); - xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2; - ycurs = ((xcurs / vc->vc_cols) << 4) + 31; - xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction; - newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs); - newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs); - } + switch (mode) { + case CM_ERASE: + treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); + newport_vc2_set(npregs, VC2_IREG_CONTROL, + (treg & ~(VC2_CTRL_ECDISP))); + break; + + case CM_MOVE: + case CM_DRAW: + treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); + newport_vc2_set(npregs, VC2_IREG_CONTROL, + (treg | VC2_CTRL_ECDISP)); + xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2; + ycurs = ((xcurs / vc->vc_cols) << 4) + 31; + xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction; + newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs); + newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs); + } } static int newport_switch(struct vc_data *vc) { - static int logo_drawn = 0; + static int logo_drawn = 0; - topscan = 0; - npregs->cset.topscan = 0x3ff; + topscan = 0; + npregs->cset.topscan = 0x3ff; - if (!logo_drawn) { - newport_show_logo(); - logo_drawn = 1; - logo_active = 1; - } + if (!logo_drawn) { + newport_show_logo(); + logo_drawn = 1; + logo_active = 1; + } - return 1; + return 1; } static int newport_blank(struct vc_data *c, int blank) { - unsigned short treg; - - if (blank == 0) { - /* unblank console */ - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EDISP)); - } else { - /* blank console */ - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EDISP))); - } - return 1; + unsigned short treg; + + if (blank == 0) { + /* unblank console */ + treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); + newport_vc2_set(npregs, VC2_IREG_CONTROL, + (treg | VC2_CTRL_EDISP)); + } else { + /* blank console */ + treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); + newport_vc2_set(npregs, VC2_IREG_CONTROL, + (treg & ~(VC2_CTRL_EDISP))); + } + return 1; +} + +static int newport_set_font(int unit, struct console_font_op *op) +{ + int w = op->width; + int h = op->height; + int size = h * op->charcount; + int i; + unsigned char *new_data, *data = op->data, *p; + + /* ladis: when I grow up, there will be a day... and more sizes will + * be supported ;-) */ + if ((w != 8) || (h != 16) + || (op->charcount != 256 && op->charcount != 512)) + return -EINVAL; + + if (!(new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, + GFP_USER))) return -ENOMEM; + + new_data += FONT_EXTRA_WORDS * sizeof(int); + FNTSIZE(new_data) = size; + FNTCHARCNT(new_data) = op->charcount; + REFCOUNT(new_data) = 0; /* usage counter */ + + p = new_data; + for (i = 0; i < op->charcount; i++) { + memcpy(p, data, h); + data += 32; + p += h; + } + + /* check if font is already used by other console */ + for (i = 0; i < MAX_NR_CONSOLES; i++) { + if (font_data[i] != FONT_DATA + && FNTSIZE(font_data[i]) == size + && !memcmp(font_data[i], new_data, size)) { + kfree(new_data - FONT_EXTRA_WORDS * sizeof(int)); + /* current font is the same as the new one */ + if (i == unit) + return 0; + new_data = font_data[i]; + break; + } + } + /* old font is user font */ + if (font_data[unit] != FONT_DATA) { + if (--REFCOUNT(font_data[unit]) == 0) + kfree(font_data[unit] - + FONT_EXTRA_WORDS * sizeof(int)); + } + REFCOUNT(new_data)++; + font_data[unit] = new_data; + + return 0; +} + +static int newport_set_def_font(int unit, struct console_font_op *op) +{ + if (font_data[unit] != FONT_DATA) { + if (--REFCOUNT(font_data[unit]) == 0) + kfree(font_data[unit] - + FONT_EXTRA_WORDS * sizeof(int)); + font_data[unit] = FONT_DATA; + } + + return 0; } -static int newport_font_op(struct vc_data *vc, struct console_font_op *f) +static int newport_font_op(struct vc_data *vc, struct console_font_op *op) { - return -ENOSYS; + int unit = vc->vc_num; + + switch (op->op) { + case KD_FONT_OP_SET: + return newport_set_font(unit, op); + case KD_FONT_OP_SET_DEFAULT: + return newport_set_def_font(unit, op); + default: + return -ENOSYS; + } } static int newport_set_palette(struct vc_data *vc, unsigned char *table) { - return -EINVAL; + return -EINVAL; } static int newport_scrolldelta(struct vc_data *vc, int lines) { - /* there is (nearly) no off-screen memory, so we can't scroll back */ - return 0; + /* there is (nearly) no off-screen memory, so we can't scroll back */ + return 0; } -static int newport_scroll(struct vc_data *vc, int t, int b, int dir, int lines) +static int newport_scroll(struct vc_data *vc, int t, int b, int dir, + int lines) { - int count,x,y; - unsigned short *s, *d; - unsigned short chattr; - - logo_active = 0; /* it's time to disable the logo now.. */ + int count, x, y; + unsigned short *s, *d; + unsigned short chattr; + + logo_active = 0; /* it's time to disable the logo now.. */ + + if (t == 0 && b == vc->vc_rows) { + if (dir == SM_UP) { + topscan = (topscan + (lines << 4)) & 0x3ff; + newport_clear_lines(vc->vc_rows - lines, + vc->vc_rows - 1, + (vc->vc_color & 0xf0) >> 4); + } else { + topscan = (topscan + (-lines << 4)) & 0x3ff; + newport_clear_lines(0, lines - 1, + (vc->vc_color & 0xf0) >> 4); + } + npregs->cset.topscan = (topscan - 1) & 0x3ff; + return 0; + } - if (t == 0 && b == vc->vc_rows) { + count = (b - t - lines) * vc->vc_cols; if (dir == SM_UP) { - topscan = (topscan + (lines << 4)) & 0x3ff; - newport_clear_lines (vc->vc_rows-lines,vc->vc_rows-1, - (vc->vc_color & 0xf0) >> 4); + x = 0; + y = t; + s = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * (t + lines)); + d = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * t); + while (count--) { + chattr = scr_readw(s++); + if (chattr != scr_readw(d)) { + newport_putc(vc, chattr, y, x); + scr_writew(chattr, d); + } + d++; + if (++x == vc->vc_cols) { + x = 0; + y++; + } + } + d = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * (b - lines)); + x = 0; + y = b - lines; + for (count = 0; count < (lines * vc->vc_cols); count++) { + if (scr_readw(d) != vc->vc_video_erase_char) { + newport_putc(vc, vc->vc_video_erase_char, + y, x); + scr_writew(vc->vc_video_erase_char, d); + } + d++; + if (++x == vc->vc_cols) { + x = 0; + y++; + } + } } else { - topscan = (topscan + (-lines << 4)) & 0x3ff; - newport_clear_lines (0,lines-1, (vc->vc_color & 0xf0) >> 4); + x = vc->vc_cols - 1; + y = b - 1; + s = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * (b - lines) - 2); + d = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * b - 2); + while (count--) { + chattr = scr_readw(s--); + if (chattr != scr_readw(d)) { + newport_putc(vc, chattr, y, x); + scr_writew(chattr, d); + } + d--; + if (x-- == 0) { + x = vc->vc_cols - 1; + y--; + } + } + d = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * t); + x = 0; + y = t; + for (count = 0; count < (lines * vc->vc_cols); count++) { + if (scr_readw(d) != vc->vc_video_erase_char) { + newport_putc(vc, vc->vc_video_erase_char, + y, x); + scr_writew(vc->vc_video_erase_char, d); + } + d++; + if (++x == vc->vc_cols) { + x = 0; + y++; + } + } } - npregs->cset.topscan = (topscan - 1) & 0x3ff; - return 0; - } - - count = (b-t-lines) * vc->vc_cols; - if (dir == SM_UP) { - x = 0; y = t; - s = (unsigned short *)(vc->vc_origin + vc->vc_size_row*(t+lines)); - d = (unsigned short *)(vc->vc_origin + vc->vc_size_row*t); - while (count--) { - chattr = scr_readw (s++); - if (chattr != scr_readw(d)) { - newport_putc (vc, chattr, y, x); - scr_writew (chattr, d); - } - d++; - if (++x == vc->vc_cols) { - x = 0; y++; - } - } - d = (unsigned short *)(vc->vc_origin + vc->vc_size_row*(b-lines)); - x = 0; y = b-lines; - for (count = 0; count < (lines * vc->vc_cols); count++) { - if (scr_readw(d) != vc->vc_video_erase_char) { - newport_putc (vc, vc->vc_video_erase_char, y, x); - scr_writew (vc->vc_video_erase_char, d); - } - d++; - if (++x == vc->vc_cols) { - x = 0; y++; - } - } - } else { - x = vc->vc_cols-1; y = b-1; - s = (unsigned short *)(vc->vc_origin + vc->vc_size_row*(b-lines)-2); - d = (unsigned short *)(vc->vc_origin + vc->vc_size_row*b-2); - while (count--) { - chattr = scr_readw (s--); - if (chattr != scr_readw(d)) { - newport_putc (vc, chattr, y, x); - scr_writew (chattr, d); - } - d--; - if (x-- == 0) { - x = vc->vc_cols-1; y--; - } - } - d = (unsigned short *)(vc->vc_origin + vc->vc_size_row*t); - x = 0; y = t; - for (count = 0; count < (lines * vc->vc_cols); count++) { - if (scr_readw(d) != vc->vc_video_erase_char) { - newport_putc (vc, vc->vc_video_erase_char, y, x); - scr_writew (vc->vc_video_erase_char, d); - } - d++; - if (++x == vc->vc_cols) { - x = 0; y++; - } - } - } - return 1; -} - -static void newport_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, int h, int w) -{ - short xs, ys, xe, ye, xoffs, yoffs, tmp; - - xs = sx << 3; xe = ((sx+w) << 3)-1; - /* - * as bmove is only used to move stuff around in the same line - * (h == 1), we don't care about wrap arounds caused by topscan != 0 - */ - ys = ((sy << 4) + topscan) & 0x3ff; ye = (((sy+h) << 4)-1+topscan) & 0x3ff; - xoffs = (dx - sx) << 3; - yoffs = (dy - sy) << 4; - if (xoffs > 0) { - /* move to the right, exchange starting points */ - tmp = xe; xe = xs; xs = tmp; - } - newport_wait(); - npregs->set.drawmode0 = (NPORT_DMODE0_S2S | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.xystarti = (xs << 16) | ys; - npregs->set.xyendi = (xe << 16) | ye; - npregs->go.xymove = (xoffs << 16) | yoffs; + return 1; +} + +static void newport_bmove(struct vc_data *vc, int sy, int sx, int dy, + int dx, int h, int w) +{ + short xs, ys, xe, ye, xoffs, yoffs, tmp; + + xs = sx << 3; + xe = ((sx + w) << 3) - 1; + /* + * as bmove is only used to move stuff around in the same line + * (h == 1), we don't care about wrap arounds caused by topscan != 0 + */ + ys = ((sy << 4) + topscan) & 0x3ff; + ye = (((sy + h) << 4) - 1 + topscan) & 0x3ff; + xoffs = (dx - sx) << 3; + yoffs = (dy - sy) << 4; + if (xoffs > 0) { + /* move to the right, exchange starting points */ + tmp = xe; + xe = xs; + xs = tmp; + } + newport_wait(); + npregs->set.drawmode0 = (NPORT_DMODE0_S2S | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX + | NPORT_DMODE0_STOPY); + npregs->set.xystarti = (xs << 16) | ys; + npregs->set.xyendi = (xe << 16) | ye; + npregs->go.xymove = (xoffs << 16) | yoffs; } static int newport_dummy(struct vc_data *c) { - return 0; + return 0; } #define DUMMY (void *) newport_dummy @@ -590,25 +715,32 @@ con_set_palette: newport_set_palette, con_scrolldelta: newport_scrolldelta, con_set_origin: DUMMY, - con_save_screen: DUMMY, + con_save_screen: DUMMY }; #ifdef MODULE +MODULE_LICENSE("GPL"); -int init_module(void) { - if (!newport_startup()) - printk("Error loading SGI Newport Console driver\n"); - else - printk("Loading SGI Newport Console Driver\n"); - - take_over_console(&newport_con,0,MAX_NR_CONSOLES-1,1); +int init_module(void) +{ + if (!newport_startup()) + printk("Error loading SGI Newport Console driver\n"); + else + printk("Loading SGI Newport Console Driver\n"); + take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); - return 0; + return 0; } -int cleanup_module(void) { - printk("Unloading SGI Newport Console Driver\n"); - return 0; -} +int cleanup_module(void) +{ + int i; + printk("Unloading SGI Newport Console Driver\n"); + /* free memory used by user font */ + for (i = 0; i < MAX_NR_CONSOLES; i++) + newport_set_def_font(i, NULL); + + return 0; +} #endif diff -u --recursive --new-file v2.4.9/linux/drivers/video/offb.c linux/drivers/video/offb.c --- v2.4.9/linux/drivers/video/offb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/offb.c Fri Sep 14 14:04:07 2001 @@ -49,7 +49,8 @@ cmap_m64, /* ATI Mach64 */ cmap_r128, /* ATI Rage128 */ cmap_M3A, /* ATI Rage Mobility M3 Head A */ - cmap_M3B /* ATI Rage Mobility M3 Head B */ + cmap_M3B, /* ATI Rage Mobility M3 Head B */ + cmap_radeon /* ATI Radeon */ }; struct fb_info_offb { @@ -433,6 +434,10 @@ unsigned long regbase = dp->parent->addrs[2].address; info->cmap_adr = ioremap(regbase, 0x1FFF); info->cmap_type = cmap_M3B; + } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { + unsigned long regbase = dp->addrs[1].address; + info->cmap_adr = ioremap(regbase, 0x1FFF); + info->cmap_type = cmap_radeon; } else if (!strncmp(name, "ATY,", 4)) { unsigned long base = address & 0xff000000UL; info->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0; @@ -669,6 +674,10 @@ out_8(info2->cmap_adr + 0xb0, i); out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0); break; + case cmap_radeon: + out_8(info2->cmap_adr + 0xb0, i); + out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0); + break; } } else @@ -748,6 +757,12 @@ out_le32((unsigned *)(info2->cmap_adr + 0xb4), (red << 16 | green << 8 | blue)); break; + case cmap_radeon: + /* Set palette index & data (could be smarter) */ + out_8(info2->cmap_adr + 0xb0, regno); + out_le32((unsigned *)(info2->cmap_adr + 0xb4), + (red << 16 | green << 8 | blue)); + break; } if (regno < 16) @@ -783,3 +798,5 @@ fb_set_cmap(fb_default_cmap(size), 1, offb_setcolreg, info); } } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/platinumfb.c linux/drivers/video/platinumfb.c --- v2.4.9/linux/drivers/video/platinumfb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/platinumfb.c Thu Sep 13 16:04:43 2001 @@ -878,3 +878,5 @@ } return 0; } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/pm2fb.c linux/drivers/video/pm2fb.c --- v2.4.9/linux/drivers/video/pm2fb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/pm2fb.c Thu Sep 13 16:04:43 2001 @@ -2152,6 +2152,8 @@ #ifdef MODULE +MODULE_LICENSE("GPL"); + static char *mode = NULL; MODULE_PARM(mode, "s"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/pmag-ba-fb.c linux/drivers/video/pmag-ba-fb.c --- v2.4.9/linux/drivers/video/pmag-ba-fb.c Wed Apr 18 11:49:12 2001 +++ linux/drivers/video/pmag-ba-fb.c Fri Sep 14 14:04:07 2001 @@ -13,7 +13,7 @@ * DECstation related code Copyright (C) 1999, 2000, 2001 by * Michael Engel , * Karsten Merker and - * Harald Koerfgen . + * Harald Koerfgen. * 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. @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -429,3 +429,5 @@ { return 0; } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/pmagb-b-fb.c linux/drivers/video/pmagb-b-fb.c --- v2.4.9/linux/drivers/video/pmagb-b-fb.c Wed Apr 18 11:49:12 2001 +++ linux/drivers/video/pmagb-b-fb.c Fri Sep 14 14:04:07 2001 @@ -9,7 +9,7 @@ * DECstation related code Copyright (C) 1999, 2000, 2001 by * Michael Engel , * Karsten Merker and - * Harald Koerfgen . + * Harald Koerfgen. * 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. @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -432,3 +432,5 @@ { return 0; } + +MODULE_LICENSE("GPL"); diff -u --recursive --new-file v2.4.9/linux/drivers/video/pvr2fb.c linux/drivers/video/pvr2fb.c --- v2.4.9/linux/drivers/video/pvr2fb.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/video/pvr2fb.c Fri Sep 14 14:04:07 2001 @@ -51,7 +51,7 @@ #include #include #include -#include +#include #include #include #include @@ -299,7 +299,7 @@ #define DEFMODE_VGA 2 static int defmode = DEFMODE_NTSC; -static const char *mode_option __initdata = NULL; +static char *mode_option __initdata = NULL; /* Get the fixed part of the display */ @@ -1165,6 +1165,7 @@ #endif #ifdef MODULE +MODULE_LICENSE("GPL"); module_init(pvr2fb_init); #endif module_exit(pvr2fb_exit); diff -u --recursive --new-file v2.4.9/linux/drivers/video/q40fb.c linux/drivers/video/q40fb.c --- v2.4.9/linux/drivers/video/q40fb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/q40fb.c Thu Sep 13 16:04:43 2001 @@ -368,3 +368,5 @@ static void q40con_blank(int blank, struct fb_info *info) { } + +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 Sun Sep 9 10:52:35 2001 @@ -0,0 +1,666 @@ +#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 PCI_DEVICE_ID_RADEON_VE 0x5159 + +#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 Sun Sep 9 10:52:35 2001 @@ -0,0 +1,1913 @@ +/* + * 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 + * + * 2001-09-07 Radeon VE support + * + * Special thanks to ATI DevRel team for their hardware donations. + * + */ + + +#define RADEON_VERSION "0.0.10" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include